Added server_timeout_counter and behavior MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT.
authorNicolas Van Eenaeme <nicolas@poison.be>
Wed, 20 Nov 2013 15:37:48 +0000 (16:37 +0100)
committerBrian Aker <brian@tangent.org>
Wed, 20 Nov 2013 15:37:48 +0000 (16:37 +0100)
This feature works as follows:
When a timeout occurs, retry MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT times before
putting the server in MEMCACHED_SERVER_STATE_IN_TIMEOUT state.

It makes sense to not fail from the 1st time but retry on the next calls before marking
the server as timeout.

13 files changed:
libmemcached-1.0/defaults.h
libmemcached-1.0/struct/memcached.h
libmemcached-1.0/struct/server.h
libmemcached-1.0/types/behavior.h
libmemcached/behavior.cc
libmemcached/connect.cc
libmemcached/instance.cc
libmemcached/instance.hpp
libmemcached/memcached.cc
libmemcached/quit.cc
libmemcached/server.cc
libmemcached/server.hpp
tests/libmemcached-1.0/mem_functions.cc

index 177e18cf6b61ca91121e5ece1a2f5d37fe6ce97d..d440f8c8cc2c1d42680b662c980e9c7dcea8e567 100644 (file)
@@ -52,5 +52,5 @@
 #define MEMCACHED_SERVER_FAILURE_LIMIT 5
 #define MEMCACHED_SERVER_FAILURE_RETRY_TIMEOUT 2
 #define MEMCACHED_SERVER_FAILURE_DEAD_TIMEOUT 0
-
+#define MEMCACHED_SERVER_TIMEOUT_LIMIT 0
 
index 37df2751a536dcd56b45065e62ab35fdb282718a..a368bfe8a06e9fe56f7de27ac4ea378aca1b0f06 100644 (file)
@@ -79,6 +79,7 @@ struct memcached_st {
   int32_t snd_timeout;
   int32_t rcv_timeout;
   uint32_t server_failure_limit;
+  uint32_t server_timeout_limit;
   uint32_t io_msg_watermark;
   uint32_t io_bytes_watermark;
   uint32_t io_key_prefetch;
index 33bdc0491eb8dd42b4a343812a4821f8efcd259b..9337938dc234d8b55cd4a0785a57556dc7125fd1 100644 (file)
@@ -77,6 +77,8 @@ struct memcached_server_st {
   uint32_t request_id;
   uint32_t server_failure_counter;
   uint64_t server_failure_counter_query_id;
+  uint32_t server_timeout_counter;
+  uint64_t server_timeout_counter_query_id;
   uint32_t weight;
   uint32_t version;
   enum memcached_server_state_t state;
index d0af189ada06817b9fb8a6e9d880286ee2211adb..a1bbfd22c81856f7f44a12514cd1aa8311904a01 100644 (file)
@@ -76,6 +76,7 @@ enum memcached_behavior_t {
   MEMCACHED_BEHAVIOR_LOAD_FROM_FILE,
   MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS,
   MEMCACHED_BEHAVIOR_DEAD_TIMEOUT,
+  MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT,
   MEMCACHED_BEHAVIOR_MAX
 };
 
index 081f8082f1ad89b1ef45160fe7e02b5b249188b3..40fb5fb66259f3fb1dc8546c5e1606a3ff514993 100644 (file)
@@ -116,6 +116,10 @@ memcached_return_t memcached_behavior_set(memcached_st *shell,
     ptr->server_failure_limit= uint32_t(data);
     break;
 
+  case MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT:
+    ptr->server_timeout_limit= uint32_t(data);
+    break;
+
   case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL:
     send_quit(ptr); // We need t shutdown all of the connections to make sure we do the correct protocol
     if (data)
@@ -374,6 +378,9 @@ uint64_t memcached_behavior_get(memcached_st *shell,
   case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT:
     return ptr->server_failure_limit;
 
+  case MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT:
+    return ptr->server_timeout_limit;
+
   case MEMCACHED_BEHAVIOR_SORT_HOSTS:
     return ptr->flags.use_sort_hosts;
 
index 3c82f641cb0f1f75fb12f12dceeb09ed4140b356..52cd293a64c7b0827e79bc970c8dfb7e4d1fcdeb 100644 (file)
@@ -713,6 +713,7 @@ static memcached_return_t backoff_handling(memcached_instance_st* server, bool&
     if (_gettime_success and server->next_retry < curr_time.tv_sec)
     {
       server->state= MEMCACHED_SERVER_STATE_NEW;
+      server->server_timeout_counter= 0;
     }
     else
     {
index 82621f7a051e5aa35aaea601dc42d74555b09459..53f74f79365ee5d5a48e11a3f78e1497232db8e7 100644 (file)
@@ -54,6 +54,8 @@ static inline void _server_init(memcached_instance_st* self, Memcached *root,
   self->request_id= 0;
   self->server_failure_counter= 0;
   self->server_failure_counter_query_id= 0;
+  self->server_timeout_counter= 0;
+  self->server_timeout_counter_query_id= 0;
   self->weight= weight ? weight : 1; // 1 is the default weight value
   self->io_wait_count.read= 0;
   self->io_wait_count.write= 0;
index c76dc7ee1db708cca782a0db81b761de73f11133..73d74a66c43dfe7ca4dd87b048b74df94b8b10b9 100644 (file)
@@ -73,6 +73,7 @@ struct memcached_instance_st {
   void mark_server_as_clean()
   {
     server_failure_counter= 0;
+    server_timeout_counter= 0;
     next_retry= 0;
   }
 
@@ -147,6 +148,8 @@ struct memcached_instance_st {
   uint32_t request_id;
   uint32_t server_failure_counter;
   uint64_t server_failure_counter_query_id;
+  uint32_t server_timeout_counter;
+  uint32_t server_timeout_counter_query_id;
   uint32_t weight;
   uint32_t version;
   enum memcached_server_state_t state;
index a3c6a67939490536f56e7c441612886834da566b..337f918dbbe498a20acafe53b6604d1561c6665a 100644 (file)
@@ -87,6 +87,7 @@ static inline bool _memcached_init(Memcached *self)
   self->snd_timeout= 0;
   self->rcv_timeout= 0;
   self->server_failure_limit= MEMCACHED_SERVER_FAILURE_LIMIT;
+  self->server_timeout_limit= MEMCACHED_SERVER_TIMEOUT_LIMIT;
   self->query_id= 1; // 0 is considered invalid
 
   /* TODO, Document why we picked these defaults */
@@ -362,6 +363,7 @@ memcached_st *memcached_clone(memcached_st *clone, const memcached_st *source)
   new_clone->get_key_failure= source->get_key_failure;
   new_clone->delete_trigger= source->delete_trigger;
   new_clone->server_failure_limit= source->server_failure_limit;
+  new_clone->server_timeout_limit= source->server_timeout_limit;
   new_clone->io_msg_watermark= source->io_msg_watermark;
   new_clone->io_bytes_watermark= source->io_bytes_watermark;
   new_clone->io_key_prefetch= source->io_key_prefetch;
index 04b77ceac1d97b81c5e98b38a47a29dc553fa4d8..5d17b3133e76375e92d8f88498ee73d52784e967 100644 (file)
@@ -93,6 +93,7 @@ namespace {
      * sent to the server.
      */
     instance->server_failure_counter= 0;
+    instance->server_timeout_counter= 0;
   }
 }
 
index c4747ddc277a3b08c2c72eeb1315b180da2c51a7..e2837c7d03c84e2f43248db2bfa5892375564227 100644 (file)
@@ -54,6 +54,8 @@ static inline void _server_init(memcached_server_st *self, Memcached *root,
   self->request_id= 0;
   self->server_failure_counter= 0;
   self->server_failure_counter_query_id= 0;
+  self->server_timeout_counter= 0;
+  self->server_timeout_counter_query_id= 0;
   self->weight= weight ? weight : 1; // 1 is the default weight value
   self->io_wait_count.read= 0;
   self->io_wait_count.write= 0;
index 708e64606610f462a73903fad188d6e5c1944c99..6ea0b7f2007b5ced75da0f77d584a633ea6cae7e 100644 (file)
@@ -76,7 +76,13 @@ static inline void memcached_mark_server_for_timeout(memcached_instance_st* serv
 {
   if (server->state != MEMCACHED_SERVER_STATE_IN_TIMEOUT)
   {
-    if (server->root->retry_timeout != 0)
+    if (server->server_timeout_counter_query_id != server->root->query_id)
+    {
+      server->server_timeout_counter++;
+      server->server_timeout_counter_query_id= server->root->query_id;
+    }
+
+    if (server->server_timeout_counter >= server->root->server_timeout_limit)
     {
       struct timeval next_time;
       if (gettimeofday(&next_time, NULL) == 0)
@@ -89,12 +95,12 @@ static inline void memcached_mark_server_for_timeout(memcached_instance_st* serv
       }
 
       server->state= MEMCACHED_SERVER_STATE_IN_TIMEOUT;
+      if (server->server_failure_counter_query_id != server->root->query_id)
+      {
+        server->server_failure_counter++;
+        server->server_failure_counter_query_id= server->root->query_id;
+      }
+      set_last_disconnected_host(server);
     }
-    if (server->server_failure_counter_query_id != server->root->query_id)
-    {
-      server->server_failure_counter++;
-      server->server_failure_counter_query_id= server->root->query_id;
-    }
-    set_last_disconnected_host(server);
   }
 }
index 365839d5614ca8c61ef80f8bdad81bd2f165df9b..321a35dbac19e613ffa21813853ea15895f3efac 100644 (file)
@@ -412,6 +412,7 @@ test_return_t clone_test(memcached_st *memc)
     test_true(memc_clone->retry_timeout == memc->retry_timeout);
     test_true(memc_clone->send_size == memc->send_size);
     test_true(memc_clone->server_failure_limit == memc->server_failure_limit);
+    test_true(memc_clone->server_timeout_limit == memc->server_timeout_limit);
     test_true(memc_clone->snd_timeout == memc->snd_timeout);
     test_true(memc_clone->user_data == memc->user_data);