From 85a0b3bc944db78c070961cd3a48b8e34dcef8a4 Mon Sep 17 00:00:00 2001 From: Date: Tue, 19 Feb 2008 08:04:34 +0530 Subject: [PATCH] MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT added from Marcelo's patch to make sure that connnect() does not block/loop when using non-block mode. --- ChangeLog | 4 ++++ docs/memcached_behavior.pod | 5 +++++ include/memcached.h | 2 ++ lib/memcached_behavior.c | 11 ++++++++++ lib/memcached_connect.c | 42 ++++++++++++++++++++++++++++++++++++- 5 files changed, 63 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 4510c19b..0c835b88 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +0.17 + * MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT added for connect timeout in + non-block mode. + 0.16 * Work on the UDP protocol * Added get_by_key, set_by_key tests for C++ API diff --git a/docs/memcached_behavior.pod b/docs/memcached_behavior.pod index 50e215f8..74a3a732 100755 --- a/docs/memcached_behavior.pod +++ b/docs/memcached_behavior.pod @@ -98,6 +98,11 @@ are valid keys. Enabling this will cause hosts that are added to be placed in the host list in sorted order. This will defeat consisten hashing. +=item MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT + +In non-blocking mode this changes the value of the timeout during socket +connection. + =back =head1 RETURN diff --git a/include/memcached.h b/include/memcached.h index e0f829aa..54589741 100644 --- a/include/memcached.h +++ b/include/memcached.h @@ -102,6 +102,7 @@ typedef enum { MEMCACHED_BEHAVIOR_USER_DATA, MEMCACHED_BEHAVIOR_SORT_HOSTS, MEMCACHED_BEHAVIOR_VERIFY_KEY, + MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, } memcached_behavior; typedef enum { @@ -217,6 +218,7 @@ struct memcached_st { int send_size; int recv_size; int32_t poll_timeout; + int32_t connect_timeout; memcached_result_st result; memcached_hash hash; memcached_server_distribution distribution; diff --git a/lib/memcached_behavior.c b/lib/memcached_behavior.c index 8c02a383..15ee08c9 100644 --- a/lib/memcached_behavior.c +++ b/lib/memcached_behavior.c @@ -73,6 +73,13 @@ memcached_return memcached_behavior_set(memcached_st *ptr, ptr->poll_timeout= timeout; break; } + case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT: + { + int32_t timeout= (*((int32_t *)data)); + + ptr->connect_timeout= timeout; + break; + } case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE: { ptr->send_size= (*((int *)data)); @@ -133,6 +140,10 @@ unsigned long long memcached_behavior_get(memcached_st *ptr, { return (unsigned long long)ptr->poll_timeout; } + case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT: + { + return (unsigned long long)ptr->connect_timeout; + } case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE: { int sock_size; diff --git a/lib/memcached_connect.c b/lib/memcached_connect.c index b4642c76..50c6fa62 100644 --- a/lib/memcached_connect.c +++ b/lib/memcached_connect.c @@ -135,9 +135,49 @@ test_connect: sizeof(servAddr)) < 0) { switch (errno) { + case EINPROGRESS: + { + struct timeval tm = { ptr->root->connect_timeout, 0 }; + socklen_t len= sizeof(int); + fd_set wset; + int error=0, value; + + FD_ZERO(&wset); + FD_SET(ptr->fd, &wset); + + select(ptr->fd+1, NULL, &wset, NULL, &tm); + if (FD_ISSET(ptr->fd, &wset) != 0) + { + if (getsockopt(ptr->fd, SOL_SOCKET, SO_ERROR, &value, &len) == 0) + { + if (value) + { + error= 1; + } + } + else + { + error= 1; + } + } + else + { + error= 1; + } + + if (error) + { + ptr->cached_errno= errno; + WATCHPOINT_ERRNO(ptr->cached_errno); + close(ptr->fd); + ptr->fd= -1; + return MEMCACHED_ERRNO; + } + + break; + } /* We are spinning waiting on connect */ case EALREADY: - case EINPROGRESS: case EINTR: goto test_connect; case EISCONN: /* We were spinning waiting on connect */ -- 2.30.2