Implement the server failure rehash mechanism
authorYin Chen <subdragon@gmail.com>
Wed, 6 Aug 2008 10:35:27 +0000 (18:35 +0800)
committerYin Chen <subdragon@gmail.com>
Wed, 6 Aug 2008 10:35:27 +0000 (18:35 +0800)
configure.ac
docs/memcached_behavior.pod
libmemcached/common.h
libmemcached/memcached.h
libmemcached/memcached_behavior.c
libmemcached/memcached_connect.c
libmemcached/memcached_constants.h
libmemcached/memcached_hosts.c
libmemcached/memcached_server.h

index a99c994b10490218d367566b78bdaf6edf0d143a..73a2f4216cc0ae36b1a2572451efab88003dff45 100644 (file)
@@ -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
 
index 7807bc9f0496c86c854187511624eb31b50f1deb..68714fb4a956b17369eed0e2bc607d8bb332fdfa 100755 (executable)
@@ -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
index ea2c557498798ba724895df14452da89851daaf1..9b8a104098d30b06ca162f1a7555335932c38797 100644 (file)
@@ -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);
index 0cbb12f1cd0debfc28deb74c0265b4f5e0cea049..8ce333caebcc2deee87464e3660e2cb9f3f8ff53 100644 (file)
@@ -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;
 };
 
 
index f61fba52e6b6b5db168dac0a6f00231df890a67e..a4b77d66fb60022632244036003fc092b2f96de0 100644 (file)
@@ -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;
index 33a8a521924ca32faadf5cbcb00a9ea625ecbee6..f2549dc75157877fb23a8e79244a7e2b465298e4 100644 (file)
@@ -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() */
 }
 
index d7770a73280f2881038a9d33fa83542736174ce9..ca1640f003ea988052594c4d215b2eb57b41c7be 100644 (file)
@@ -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 {
index c52aa09621c51d549308385b5019c7ac8b0921fa..693750386f65c63b4767aebf0538b494707f99fc 100644 (file)
@@ -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)
index c566ddbee3f33f86c49b4f2965d49086331618d1..ad03898dc4fd23cbfa1ce4041aa744bd3cb7b4f4 100644 (file)
@@ -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