From: Yin Chen Date: Wed, 6 Aug 2008 10:35:27 +0000 (+0800) Subject: Implement the server failure rehash mechanism X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=e14aa2d3a2cb1aa64f8028d572741f60ca2cb0a1;p=m6w6%2Flibmemcached Implement the server failure rehash mechanism --- diff --git a/configure.ac b/configure.ac index a99c994b..73a2f421 100644 --- a/configure.ac +++ b/configure.ac @@ -61,12 +61,14 @@ then if test "$ENABLE_DEBUG" = "yes" then CFLAGS="-Wall -ggdb -DMEMCACHED_INTERNAL -DHAVE_DEBUG $CFLAGS" + LDFLAGS="-lm" else CFLAGS="-Wall -O3 -DMEMCACHED_INTERNAL $CFLAGS" + LDFLAGS="-lm" fi else CFLAGS="-Xa -xstrconst -mt -D_FORTEC_ $CFLAGS" - LDFLAGS="-lsocket -lnsl $LDFLAGS" + LDFLAGS="-lm -lsocket -lnsl $LDFLAGS" DTRACEFLAGS="$DTRACEFLAGS" fi diff --git a/docs/memcached_behavior.pod b/docs/memcached_behavior.pod index 7807bc9f..68714fb4 100755 --- a/docs/memcached_behavior.pod +++ b/docs/memcached_behavior.pod @@ -138,6 +138,11 @@ connection. Enable the use of the binary protocol. Please note that you cannot toggle this flag on an open connection. +=item MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT + +Set this value to enable the server be removed after continuous MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT +times connection failure. + =back =head1 RETURN diff --git a/libmemcached/common.h b/libmemcached/common.h index ea2c5574..9b8a1040 100644 --- a/libmemcached/common.h +++ b/libmemcached/common.h @@ -118,6 +118,7 @@ memcached_return run_distribution(memcached_st *ptr); uint32_t generate_hash_value(const char *key, size_t key_length, memcached_hash hash_algorithm); uint32_t generate_hash(memcached_st *ptr, const char *key, size_t key_length); +memcached_return server_remove(memcached_server_st *st_ptr); extern uint64_t ntohll(uint64_t); extern uint64_t htonll(uint64_t); diff --git a/libmemcached/memcached.h b/libmemcached/memcached.h index 0cbb12f1..8ce333ca 100644 --- a/libmemcached/memcached.h +++ b/libmemcached/memcached.h @@ -97,6 +97,7 @@ struct memcached_st { uint32_t continuum_points_counter; int32_t snd_timeout; int32_t rcv_timeout; + int32_t server_failure_limit; }; diff --git a/libmemcached/memcached_behavior.c b/libmemcached/memcached_behavior.c index f61fba52..a4b77d66 100644 --- a/libmemcached/memcached_behavior.c +++ b/libmemcached/memcached_behavior.c @@ -29,6 +29,9 @@ memcached_return memcached_behavior_set(memcached_st *ptr, case MEMCACHED_BEHAVIOR_RCV_TIMEOUT: ptr->rcv_timeout= (int32_t)data; break; + case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT: + ptr->server_failure_limit= (int32_t)data; + break; case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL: set_behavior_flag(ptr, MEM_BINARY_PROTOCOL, data); break; @@ -159,6 +162,8 @@ uint64_t memcached_behavior_get(memcached_st *ptr, return ptr->hash; case MEMCACHED_BEHAVIOR_KETAMA_HASH: return ptr->hash_continuum; + case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT: + return ptr->server_failure_limit; case MEMCACHED_BEHAVIOR_SORT_HOSTS: temp_flag= MEM_USE_SORT_HOSTS; break; diff --git a/libmemcached/memcached_connect.c b/libmemcached/memcached_connect.c index 33a8a521..f2549dc7 100644 --- a/libmemcached/memcached_connect.c +++ b/libmemcached/memcached_connect.c @@ -172,6 +172,11 @@ static memcached_return network_connect(memcached_server_st *ptr) { struct addrinfo *use; + if(ptr->root->server_failure_limit != 0) { + if(ptr->server_failure_counter >= ptr->root->server_failure_limit) { + server_remove(ptr); + } + } /* Old connection junk still is in the structure */ WATCHPOINT_ASSERT(ptr->cursor_active == 0); @@ -224,7 +229,7 @@ test_connect: { goto handle_retry; } - else if (error != 1) + else if (error != 1 || fds[0].revents & POLLERR) { ptr->cached_errno= errno; WATCHPOINT_ERRNO(ptr->cached_errno); @@ -237,6 +242,14 @@ test_connect: ptr->address_info= NULL; } + if (ptr->root->retry_timeout) + { + struct timeval next_time; + + gettimeofday(&next_time, NULL); + ptr->next_retry= next_time.tv_sec + ptr->root->retry_timeout; + } + ptr->server_failure_counter+= 1; return MEMCACHED_ERRNO; } @@ -264,15 +277,19 @@ handle_retry: else { WATCHPOINT_ASSERT(ptr->cursor_active == 0); + ptr->server_failure_counter= 0; return MEMCACHED_SUCCESS; } use = use->ai_next; } } - if (ptr->fd == -1) + if (ptr->fd == -1) { + ptr->server_failure_counter+= 1; return MEMCACHED_ERRNO; /* The last error should be from connect() */ + } + ptr->server_failure_counter= 0; return MEMCACHED_SUCCESS; /* The last error should be from connect() */ } diff --git a/libmemcached/memcached_constants.h b/libmemcached/memcached_constants.h index d7770a73..ca1640f0 100644 --- a/libmemcached/memcached_constants.h +++ b/libmemcached/memcached_constants.h @@ -91,6 +91,7 @@ typedef enum { MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, MEMCACHED_BEHAVIOR_SND_TIMEOUT, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, + MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, } memcached_behavior; typedef enum { diff --git a/libmemcached/memcached_hosts.c b/libmemcached/memcached_hosts.c index c52aa096..69375038 100644 --- a/libmemcached/memcached_hosts.c +++ b/libmemcached/memcached_hosts.c @@ -282,6 +282,27 @@ static memcached_return server_add(memcached_st *ptr, char *hostname, return run_distribution(ptr); } +memcached_return server_remove(memcached_server_st *st_ptr) +{ + int i,index; + memcached_st *ptr= st_ptr->root; + memcached_server_st *list=ptr->hosts; + index= 0; + for(i= 0; i< ptr->number_of_hosts; ++i) { + if(strncmp(list[i].hostname, st_ptr->hostname, MEMCACHED_MAX_HOST_LENGTH)!=0 || list[i].port != st_ptr->port) { + memcpy(list+index, list+i, sizeof(memcached_server_st)); + index++; + } else { + ptr->number_of_hosts-=1; + } + } + if(st_ptr->address_info) { + freeaddrinfo(st_ptr->address_info); + } + run_distribution(ptr); + return MEMCACHED_SUCCESS; +} + memcached_server_st *memcached_server_list_append(memcached_server_st *ptr, char *hostname, unsigned int port, memcached_return *error) diff --git a/libmemcached/memcached_server.h b/libmemcached/memcached_server.h index c566ddbe..ad03898d 100644 --- a/libmemcached/memcached_server.h +++ b/libmemcached/memcached_server.h @@ -35,6 +35,7 @@ struct memcached_server_st { time_t next_retry; memcached_st *root; uint64_t limit_maxbytes; + uint32_t server_failure_counter; }; #define memcached_server_count(A) (A)->number_of_hosts