Bug #25487 deleting ndb_cluster_connection object takes long time

  
  aim is to:
  a) if set_connect_timeout called, timeout connect attempt (for retry on
  next call) after timeout period
  b) preserve existing blocking behaviour otherwise (for, e.g. mgmapi)
  
  Related to customer issue with long time deleting ndb_cluster_connection
  object. believe we're hanging on the connect(2) call until timeout (when
  we then realise we should exit the thread).
parent 12911bb5
...@@ -540,6 +540,16 @@ extern "C" { ...@@ -540,6 +540,16 @@ extern "C" {
*/ */
const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz); const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz);
/**
* Sets the number of seconds to wait for connect(2) during ndb_mgm_connect
* Default is no timeout
*
* @param handle NdbMgmHandle
* @param seconds number of seconds
* @return non-zero on success
*/
int ndb_mgm_set_connect_timeout(NdbMgmHandle handle, unsigned int seconds);
/** /**
* Connects to a management server. Connectstring is set by * Connects to a management server. Connectstring is set by
* ndb_mgm_set_connectstring(). * ndb_mgm_set_connectstring().
......
...@@ -23,6 +23,7 @@ class SocketClient ...@@ -23,6 +23,7 @@ class SocketClient
{ {
NDB_SOCKET_TYPE m_sockfd; NDB_SOCKET_TYPE m_sockfd;
struct sockaddr_in m_servaddr; struct sockaddr_in m_servaddr;
unsigned int m_connect_timeout_sec;
unsigned short m_port; unsigned short m_port;
char *m_server_name; char *m_server_name;
SocketAuthenticator *m_auth; SocketAuthenticator *m_auth;
...@@ -34,6 +35,9 @@ public: ...@@ -34,6 +35,9 @@ public:
m_port = port; m_port = port;
m_servaddr.sin_port = htons(m_port); m_servaddr.sin_port = htons(m_port);
}; };
void set_connect_timeout(unsigned int s) {
m_connect_timeout_sec= s;
}
unsigned short get_port() { return m_port; }; unsigned short get_port() { return m_port; };
char *get_server_name() { return m_server_name; }; char *get_server_name() { return m_server_name; };
int bind(const char* toaddress, unsigned short toport); int bind(const char* toaddress, unsigned short toport);
......
...@@ -79,9 +79,13 @@ Transporter::Transporter(TransporterRegistry &t_reg, ...@@ -79,9 +79,13 @@ Transporter::Transporter(TransporterRegistry &t_reg,
if (isServer) if (isServer)
m_socket_client= 0; m_socket_client= 0;
else else
{
m_socket_client= new SocketClient(remoteHostName, s_port, m_socket_client= new SocketClient(remoteHostName, s_port,
new SocketAuthSimple("ndbd", new SocketAuthSimple("ndbd",
"ndbd passwd")); "ndbd passwd"));
m_socket_client->set_connect_timeout(m_timeOutMillis/1000);
}
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -140,9 +144,9 @@ Transporter::connect_client() { ...@@ -140,9 +144,9 @@ Transporter::connect_client() {
} }
sockfd= m_socket_client->connect(); sockfd= m_socket_client->connect();
} }
return connect_client(sockfd); return connect_client(sockfd);
} }
bool bool
Transporter::connect_client(NDB_SOCKET_TYPE sockfd) { Transporter::connect_client(NDB_SOCKET_TYPE sockfd) {
......
...@@ -26,6 +26,7 @@ SocketClient::SocketClient(const char *server_name, unsigned short port, SocketA ...@@ -26,6 +26,7 @@ SocketClient::SocketClient(const char *server_name, unsigned short port, SocketA
m_port= port; m_port= port;
m_server_name= server_name ? strdup(server_name) : 0; m_server_name= server_name ? strdup(server_name) : 0;
m_sockfd= NDB_INVALID_SOCKET; m_sockfd= NDB_INVALID_SOCKET;
m_connect_timeout_sec= 0;
} }
SocketClient::~SocketClient() SocketClient::~SocketClient()
...@@ -58,7 +59,7 @@ SocketClient::init() ...@@ -58,7 +59,7 @@ SocketClient::init()
if (m_sockfd == NDB_INVALID_SOCKET) { if (m_sockfd == NDB_INVALID_SOCKET) {
return false; return false;
} }
DBUG_PRINT("info",("NDB_SOCKET: %d", m_sockfd)); DBUG_PRINT("info",("NDB_SOCKET: %d", m_sockfd));
return true; return true;
...@@ -104,6 +105,13 @@ SocketClient::bind(const char* bindaddress, unsigned short localport) ...@@ -104,6 +105,13 @@ SocketClient::bind(const char* bindaddress, unsigned short localport)
NDB_SOCKET_TYPE NDB_SOCKET_TYPE
SocketClient::connect(const char *toaddress, unsigned short toport) SocketClient::connect(const char *toaddress, unsigned short toport)
{ {
fd_set rset, wset;
struct timeval tval;
int r;
bool use_timeout;
socklen_t len;
int flags;
if (m_sockfd == NDB_INVALID_SOCKET) if (m_sockfd == NDB_INVALID_SOCKET)
{ {
if (!init()) { if (!init()) {
...@@ -127,14 +135,58 @@ SocketClient::connect(const char *toaddress, unsigned short toport) ...@@ -127,14 +135,58 @@ SocketClient::connect(const char *toaddress, unsigned short toport)
if (Ndb_getInAddr(&m_servaddr.sin_addr, m_server_name)) if (Ndb_getInAddr(&m_servaddr.sin_addr, m_server_name))
return NDB_INVALID_SOCKET; return NDB_INVALID_SOCKET;
} }
const int r = ::connect(m_sockfd, (struct sockaddr*) &m_servaddr, sizeof(m_servaddr)); flags= fcntl(m_sockfd, F_GETFL, 0);
if (r == -1) { fcntl(m_sockfd, F_SETFL, flags | O_NONBLOCK);
r= ::connect(m_sockfd, (struct sockaddr*) &m_servaddr, sizeof(m_servaddr));
if (r == 0)
goto done; // connected immediately.
if (r < 0 && (errno != EINPROGRESS)) {
NDB_CLOSE_SOCKET(m_sockfd);
m_sockfd= NDB_INVALID_SOCKET;
return NDB_INVALID_SOCKET;
}
FD_ZERO(&rset);
FD_SET(m_sockfd, &rset);
wset= rset;
tval.tv_sec= m_connect_timeout_sec;
tval.tv_usec= 0;
use_timeout= m_connect_timeout_sec;
if ((r= select(m_sockfd+1, &rset, &wset, NULL,
use_timeout? &tval : NULL)) == 0)
{
NDB_CLOSE_SOCKET(m_sockfd); NDB_CLOSE_SOCKET(m_sockfd);
m_sockfd= NDB_INVALID_SOCKET; m_sockfd= NDB_INVALID_SOCKET;
return NDB_INVALID_SOCKET; return NDB_INVALID_SOCKET;
} }
if (FD_ISSET(m_sockfd, &rset) || FD_ISSET(m_sockfd, &wset))
{
len= sizeof(r);
if (getsockopt(m_sockfd, SOL_SOCKET, SO_ERROR, &r, &len) < 0)
{
// Solaris got an error... different than others
NDB_CLOSE_SOCKET(m_sockfd);
m_sockfd= NDB_INVALID_SOCKET;
return NDB_INVALID_SOCKET;
}
}
else
{
// select error, probably m_sockfd not set.
NDB_CLOSE_SOCKET(m_sockfd);
m_sockfd= NDB_INVALID_SOCKET;
return NDB_INVALID_SOCKET;
}
done:
fcntl(m_sockfd, F_SETFL, flags);
if (m_auth) { if (m_auth) {
if (!m_auth->client_authenticate(m_sockfd)) if (!m_auth->client_authenticate(m_sockfd))
{ {
......
...@@ -93,6 +93,7 @@ struct ndb_mgm_handle { ...@@ -93,6 +93,7 @@ struct ndb_mgm_handle {
char last_error_desc[NDB_MGM_MAX_ERR_DESC_SIZE]; char last_error_desc[NDB_MGM_MAX_ERR_DESC_SIZE];
int read_timeout; int read_timeout;
int write_timeout; int write_timeout;
unsigned int connect_timeout;
NDB_SOCKET_TYPE socket; NDB_SOCKET_TYPE socket;
...@@ -159,6 +160,7 @@ ndb_mgm_create_handle() ...@@ -159,6 +160,7 @@ ndb_mgm_create_handle()
h->socket = NDB_INVALID_SOCKET; h->socket = NDB_INVALID_SOCKET;
h->read_timeout = 50000; h->read_timeout = 50000;
h->write_timeout = 100; h->write_timeout = 100;
h->connect_timeout = 0;
h->cfg_i = -1; h->cfg_i = -1;
h->errstream = stdout; h->errstream = stdout;
h->m_name = 0; h->m_name = 0;
...@@ -426,6 +428,16 @@ int ndb_mgm_is_connected(NdbMgmHandle handle) ...@@ -426,6 +428,16 @@ int ndb_mgm_is_connected(NdbMgmHandle handle)
return handle->connected; return handle->connected;
} }
extern "C"
int ndb_mgm_set_connect_timeout(NdbMgmHandle handle, unsigned int seconds)
{
if(!handle)
return -1;
handle->connect_timeout= seconds;
return 0;
}
/** /**
* Connect to a management server * Connect to a management server
*/ */
...@@ -456,6 +468,7 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries, ...@@ -456,6 +468,7 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
Uint32 i; Uint32 i;
int binderror = 0; int binderror = 0;
SocketClient s(0, 0); SocketClient s(0, 0);
s.set_connect_timeout(handle->connect_timeout);
if (!s.init()) if (!s.init())
{ {
fprintf(handle->errstream, fprintf(handle->errstream,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment