Added reviewed version of memcached_server_get_last_disconnect
authorJean-Charles Redoutey <jc@Jayce2009lnx>
Sat, 10 Oct 2009 11:57:03 +0000 (13:57 +0200)
committerJean-Charles Redoutey <jc@Jayce2009lnx>
Sat, 10 Oct 2009 11:57:03 +0000 (13:57 +0200)
docs/memcached_servers.pod
libmemcached/memcached.h
libmemcached/memcached_connect.c
libmemcached/memcached_hosts.c
libmemcached/memcached_server.c
libmemcached/memcached_server.h
tests/function.c

index 125e1f4b1ba169c33d6fa3c7df885fd3fe2305f9..a4495382683a7c32e89311e28e6fbe1f7746c320 100644 (file)
@@ -1,6 +1,6 @@
 =head1 NAME
 
-memcached_server_count, memcached_server_list, memcached_server_add, memcached_server_push - Manage server list
+memcached_server_count, memcached_server_list, memcached_server_add, memcached_server_push, memcached_server_get_last_disconnect - Manage server list
 
 =head1 LIBRARY
 
@@ -37,6 +37,9 @@ C Client Library for memcached (libmemcached, -lmemcached)
     memcached_server_by_key (memcached_st *ptr,  
                              const char *key, size_t key_length, 
                              memcached_return *error);
+  memcached_server_st *                          
+    memcached_server_get_last_disconnect (memcached_st *ptr)
+    
 
 =head1 DESCRIPTION
 
@@ -81,6 +84,11 @@ from its original structure and must be freed. If NULL is returned you
 should consult *error. The returning structure should be freed with
 memcached_server_free().
 
+memcached_server_get_last_disconnect() returns a pointer to the last server 
+for which there was a connection problem. It does not mean this particular 
+server is currently dead but if the library is reporting a server is, 
+the returned server is a very good candidate.
+
 =head1 RETURN
 
 Varies, see particular functions.
index 5068f98b6294ba0e5d802c8584900fe7adc8424f..08c66a2c2b7f8688d9beb43f2355fb48f3d682d2 100644 (file)
@@ -80,6 +80,7 @@ struct memcached_st {
   uint8_t hash;
   uint32_t continuum_points_counter;
   memcached_server_st *hosts;
+  memcached_server_st *last_disconnected_server;
   int32_t snd_timeout;
   int32_t rcv_timeout;
   uint32_t server_failure_limit;
@@ -133,12 +134,12 @@ LIBMEMCACHED_API
 memcached_return memcached_delete(memcached_st *ptr, const char *key, size_t key_length,
                                   time_t expiration);
 LIBMEMCACHED_API
-memcached_return memcached_increment(memcached_st *ptr, 
+memcached_return memcached_increment(memcached_st *ptr,
                                      const char *key, size_t key_length,
                                      uint32_t offset,
                                      uint64_t *value);
 LIBMEMCACHED_API
-memcached_return memcached_decrement(memcached_st *ptr, 
+memcached_return memcached_decrement(memcached_st *ptr,
                                      const char *key, size_t key_length,
                                      uint32_t offset,
                                      uint64_t *value);
@@ -163,7 +164,7 @@ void memcached_stat_free(memcached_st *, memcached_stat_st *);
 LIBMEMCACHED_API
 memcached_stat_st *memcached_stat(memcached_st *ptr, char *args, memcached_return *error);
 LIBMEMCACHED_API
-memcached_return memcached_stat_servername(memcached_stat_st *memc_stat, char *args, 
+memcached_return memcached_stat_servername(memcached_stat_st *memc_stat, char *args,
                                            char *hostname, unsigned int port);
 LIBMEMCACHED_API
 memcached_return memcached_flush(memcached_st *ptr, time_t expiration);
@@ -190,27 +191,27 @@ memcached_return memcached_flush_buffers(memcached_st *mem);
 /* Server Public functions */
 
 LIBMEMCACHED_API
-memcached_return memcached_server_add_udp(memcached_st *ptr, 
+memcached_return memcached_server_add_udp(memcached_st *ptr,
                                           const char *hostname,
                                           unsigned int port);
 LIBMEMCACHED_API
-memcached_return memcached_server_add_unix_socket(memcached_st *ptr, 
+memcached_return memcached_server_add_unix_socket(memcached_st *ptr,
                                                   const char *filename);
 LIBMEMCACHED_API
-memcached_return memcached_server_add(memcached_st *ptr, const char *hostname, 
+memcached_return memcached_server_add(memcached_st *ptr, const char *hostname,
                                       unsigned int port);
 
 LIBMEMCACHED_API
-memcached_return memcached_server_add_udp_with_weight(memcached_st *ptr, 
+memcached_return memcached_server_add_udp_with_weight(memcached_st *ptr,
                                                       const char *hostname,
                                                       unsigned int port,
                                                       uint32_t weight);
 LIBMEMCACHED_API
-memcached_return memcached_server_add_unix_socket_with_weight(memcached_st *ptr, 
+memcached_return memcached_server_add_unix_socket_with_weight(memcached_st *ptr,
                                                               const char *filename,
                                                               uint32_t weight);
 LIBMEMCACHED_API
-memcached_return memcached_server_add_with_weight(memcached_st *ptr, const char *hostname, 
+memcached_return memcached_server_add_with_weight(memcached_st *ptr, const char *hostname,
                                                   unsigned int port,
                                                   uint32_t weight);
 LIBMEMCACHED_API
@@ -219,14 +220,14 @@ LIBMEMCACHED_API
 memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *list);
 
 LIBMEMCACHED_API
-memcached_server_st *memcached_server_list_append(memcached_server_st *ptr, 
-                                                  const char *hostname, 
-                                                  unsigned int port, 
+memcached_server_st *memcached_server_list_append(memcached_server_st *ptr,
+                                                  const char *hostname,
+                                                  unsigned int port,
                                                   memcached_return *error);
 LIBMEMCACHED_API
-memcached_server_st *memcached_server_list_append_with_weight(memcached_server_st *ptr, 
-                                                              const char *hostname, 
-                                                              unsigned int port, 
+memcached_server_st *memcached_server_list_append_with_weight(memcached_server_st *ptr,
+                                                              const char *hostname,
+                                                              unsigned int port,
                                                               uint32_t weight,
                                                               memcached_return *error);
 LIBMEMCACHED_API
@@ -235,30 +236,30 @@ LIBMEMCACHED_API
 memcached_server_st *memcached_servers_parse(const char *server_strings);
 
 LIBMEMCACHED_API
-char *memcached_stat_get_value(memcached_st *ptr, memcached_stat_st *memc_stat, 
+char *memcached_stat_get_value(memcached_st *ptr, memcached_stat_st *memc_stat,
                                const char *key, memcached_return *error);
 LIBMEMCACHED_API
-char ** memcached_stat_get_keys(memcached_st *ptr, memcached_stat_st *memc_stat, 
+char ** memcached_stat_get_keys(memcached_st *ptr, memcached_stat_st *memc_stat,
                                 memcached_return *error);
 
 LIBMEMCACHED_API
-memcached_return memcached_delete_by_key(memcached_st *ptr, 
+memcached_return memcached_delete_by_key(memcached_st *ptr,
                                          const char *master_key, size_t master_key_length,
                                          const char *key, size_t key_length,
                                          time_t expiration);
 
 LIBMEMCACHED_API
-memcached_return memcached_fetch_execute(memcached_st *ptr, 
+memcached_return memcached_fetch_execute(memcached_st *ptr,
                                              memcached_execute_function *callback,
                                              void *context,
                                              unsigned int number_of_callbacks);
 
 LIBMEMCACHED_API
-memcached_return memcached_callback_set(memcached_st *ptr, 
-                                        memcached_callback flag, 
+memcached_return memcached_callback_set(memcached_st *ptr,
+                                        memcached_callback flag,
                                         void *data);
 LIBMEMCACHED_API
-void *memcached_callback_get(memcached_st *ptr, 
+void *memcached_callback_get(memcached_st *ptr,
                              memcached_callback flag,
                              memcached_return *error);
 
index 833ad0efba97f9b9eb126d7f177ab1bb4147aff9..1c4069cfc530771d9cd9b0f131924a23a4a704f7 100644 (file)
@@ -60,7 +60,7 @@ static memcached_return set_socket_options(memcached_server_st *ptr)
     waittime.tv_sec= 0;
     waittime.tv_usec= ptr->root->snd_timeout;
 
-    error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDTIMEO, 
+    error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDTIMEO,
                       &waittime, (socklen_t)sizeof(struct timeval));
     WATCHPOINT_ASSERT(error == 0);
   }
@@ -75,7 +75,7 @@ static memcached_return set_socket_options(memcached_server_st *ptr)
     waittime.tv_sec= 0;
     waittime.tv_usec= ptr->root->rcv_timeout;
 
-    error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVTIMEO, 
+    error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVTIMEO,
                       &waittime, (socklen_t)sizeof(struct timeval));
     WATCHPOINT_ASSERT(error == 0);
   }
@@ -86,9 +86,9 @@ static memcached_return set_socket_options(memcached_server_st *ptr)
     int error;
     struct linger linger;
 
-    linger.l_onoff= 1; 
-    linger.l_linger= 0; /* By default on close() just drop the socket */ 
-    error= setsockopt(ptr->fd, SOL_SOCKET, SO_LINGER, 
+    linger.l_onoff= 1;
+    linger.l_linger= 0; /* By default on close() just drop the socket */
+    error= setsockopt(ptr->fd, SOL_SOCKET, SO_LINGER,
                       &linger, (socklen_t)sizeof(struct linger));
     WATCHPOINT_ASSERT(error == 0);
   }
@@ -98,7 +98,7 @@ static memcached_return set_socket_options(memcached_server_st *ptr)
     int flag= 1;
     int error;
 
-    error= setsockopt(ptr->fd, IPPROTO_TCP, TCP_NODELAY, 
+    error= setsockopt(ptr->fd, IPPROTO_TCP, TCP_NODELAY,
                       &flag, (socklen_t)sizeof(int));
     WATCHPOINT_ASSERT(error == 0);
   }
@@ -107,7 +107,7 @@ static memcached_return set_socket_options(memcached_server_st *ptr)
   {
     int error;
 
-    error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDBUF, 
+    error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDBUF,
                       &ptr->root->send_size, (socklen_t)sizeof(int));
     WATCHPOINT_ASSERT(error == 0);
   }
@@ -116,7 +116,7 @@ static memcached_return set_socket_options(memcached_server_st *ptr)
   {
     int error;
 
-    error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVBUF, 
+    error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVBUF,
                       &ptr->root->recv_size, (socklen_t)sizeof(int));
     WATCHPOINT_ASSERT(error == 0);
   }
@@ -156,7 +156,7 @@ static memcached_return unix_socket_connect(memcached_server_st *ptr)
     addrlen= (socklen_t) (strlen(servAddr.sun_path) + sizeof(servAddr.sun_family));
 
 test_connect:
-    if (connect(ptr->fd, 
+    if (connect(ptr->fd,
                 (struct sockaddr *)&servAddr,
                 sizeof(servAddr)) < 0)
     {
@@ -208,8 +208,8 @@ static memcached_return network_connect(memcached_server_st *ptr)
         continue;
       }
 
-      if ((ptr->fd= socket(use->ai_family, 
-                           use->ai_socktype, 
+      if ((ptr->fd= socket(use->ai_family,
+                           use->ai_socktype,
                            use->ai_protocol)) < 0)
       {
         ptr->cached_errno= errno;
@@ -228,7 +228,7 @@ static memcached_return network_connect(memcached_server_st *ptr)
       }
 
       /* connect to server */
-      while (ptr->fd != -1 && 
+      while (ptr->fd != -1 &&
              connect(ptr->fd, use->ai_addr, use->ai_addrlen) < 0)
       {
         ptr->cached_errno= errno;
@@ -253,23 +253,23 @@ static memcached_return network_connect(memcached_server_st *ptr)
             (void)close(ptr->fd);
             ptr->fd= -1;
           }
-        } 
+        }
         else if (errno == EISCONN) /* we are connected :-) */
         {
           break;
-        } 
+        }
         else if (errno != EINTR)
         {
           (void)close(ptr->fd);
           ptr->fd= -1;
           break;
-        } 
+        }
       }
 
       if (ptr->fd != -1)
       {
-        /* restore flags */ 
-        if (ptr->root->connect_timeout && (ptr->root->flags & MEM_NO_BLOCK) == 0) 
+        /* restore flags */
+        if (ptr->root->connect_timeout && (ptr->root->flags & MEM_NO_BLOCK) == 0)
           (void)fcntl(ptr->fd, F_SETFL, flags & ~O_NONBLOCK);
 
         WATCHPOINT_ASSERT(ptr->cursor_active == 0);
@@ -348,6 +348,8 @@ memcached_return memcached_connect(memcached_server_st *ptr)
     WATCHPOINT_ASSERT(0);
   }
 
+  unlikely ( rc != MEMCACHED_SUCCESS) ptr->root->last_disconnected_server = ptr;
+
   LIBMEMCACHED_MEMCACHED_CONNECT_END();
 
   return rc;
index f56c89f17c5e2c1bc58b59f4732829e7da095421..d664ab2b5a7b0e7eefa89d88f2b5f28e1d9971be 100644 (file)
@@ -2,7 +2,7 @@
 #include <math.h>
 
 /* Protoypes (static) */
-static memcached_return server_add(memcached_st *ptr, const char *hostname, 
+static memcached_return server_add(memcached_st *ptr, const char *hostname,
                                    unsigned int port,
                                    uint32_t weight,
                                    memcached_connection type);
@@ -36,7 +36,7 @@ static void sort_hosts(memcached_st *ptr)
 
 memcached_return run_distribution(memcached_st *ptr)
 {
-  switch (ptr->distribution) 
+  switch (ptr->distribution)
   {
   case MEMCACHED_DISTRIBUTION_CONSISTENT:
   case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
@@ -51,6 +51,8 @@ memcached_return run_distribution(memcached_st *ptr)
     WATCHPOINT_ASSERT(0); /* We have added a distribution without extending the logic */
   }
 
+  ptr->last_disconnected_server = NULL;
+
   return MEMCACHED_SUCCESS;
 }
 
@@ -77,7 +79,7 @@ void server_list_free(memcached_st *ptr, memcached_server_st *servers)
 static uint32_t ketama_server_hash(const char *key, unsigned int key_length, int alignment)
 {
   unsigned char results[16];
-  
+
   md5_signature((unsigned char*)key, key_length, results);
   return ((uint32_t) (results[3 + alignment * 4] & 0xFF) << 24)
     | ((uint32_t) (results[2 + alignment * 4] & 0xFF) << 16)
@@ -155,7 +157,7 @@ memcached_return update_continuum(memcached_st *ptr)
   {
     memcached_continuum_item_st *new_ptr;
 
-    new_ptr= ptr->call_realloc(ptr, ptr->continuum, 
+    new_ptr= ptr->call_realloc(ptr, ptr->continuum,
                                sizeof(memcached_continuum_item_st) * (live_servers + MEMCACHED_CONTINUUM_ADDITION) * points_per_server);
 
     if (new_ptr == 0)
@@ -165,9 +167,9 @@ memcached_return update_continuum(memcached_st *ptr)
     ptr->continuum_count= live_servers + MEMCACHED_CONTINUUM_ADDITION;
   }
 
-  if (is_ketama_weighted) 
+  if (is_ketama_weighted)
   {
-    for (host_index = 0; host_index < ptr->number_of_hosts; ++host_index) 
+    for (host_index = 0; host_index < ptr->number_of_hosts; ++host_index)
     {
       if (list[host_index].weight == 0)
       {
@@ -178,27 +180,27 @@ memcached_return update_continuum(memcached_st *ptr)
     }
   }
 
-  for (host_index = 0; host_index < ptr->number_of_hosts; ++host_index) 
+  for (host_index = 0; host_index < ptr->number_of_hosts; ++host_index)
   {
     if (is_auto_ejecting && list[host_index].next_retry > now.tv_sec)
       continue;
 
-    if (is_ketama_weighted) 
+    if (is_ketama_weighted)
     {
         float pct = (float)list[host_index].weight / (float)total_weight;
         pointer_per_server= (uint32_t) ((floorf((float) (pct * MEMCACHED_POINTS_PER_SERVER_KETAMA / 4 * (float)live_servers + 0.0000000001))) * 4);
         pointer_per_hash= 4;
 #ifdef DEBUG
-        printf("ketama_weighted:%s|%d|%llu|%u\n", 
-               list[host_index].hostname, 
-               list[host_index].port,  
-               (unsigned long long)list[host_index].weight, 
+        printf("ketama_weighted:%s|%d|%llu|%u\n",
+               list[host_index].hostname,
+               list[host_index].port,
+               (unsigned long long)list[host_index].weight,
                pointer_per_server);
 #endif
     }
     for (pointer_index= 1;
          pointer_index <= pointer_per_server / pointer_per_hash;
-         ++pointer_index) 
+         ++pointer_index)
     {
       char sort_host[MEMCACHED_MAX_HOST_SORT_LENGTH]= "";
       size_t sort_host_length;
@@ -214,7 +216,7 @@ memcached_return update_continuum(memcached_st *ptr)
       else
       {
         sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH,
-                                            "%s:%d-%d", 
+                                            "%s:%d-%d",
                                             list[host_index].hostname,
                                             list[host_index].port, pointer_index - 1);
       }
@@ -247,7 +249,7 @@ memcached_return update_continuum(memcached_st *ptr)
   qsort(ptr->continuum, ptr->continuum_points_counter, sizeof(memcached_continuum_item_st), continuum_item_cmp);
 
 #ifdef DEBUG
-  for (pointer_index= 0; ptr->number_of_hosts && pointer_index < ((live_servers * MEMCACHED_POINTS_PER_SERVER) - 1); pointer_index++) 
+  for (pointer_index= 0; ptr->number_of_hosts && pointer_index < ((live_servers * MEMCACHED_POINTS_PER_SERVER) - 1); pointer_index++)
   {
     WATCHPOINT_ASSERT(ptr->continuum[pointer_index].value <= ptr->continuum[pointer_index + 1].value);
   }
@@ -267,7 +269,7 @@ memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *l
     return MEMCACHED_SUCCESS;
 
   count= list[0].count;
-  new_host_list= ptr->call_realloc(ptr, ptr->hosts, 
+  new_host_list= ptr->call_realloc(ptr, ptr->hosts,
                                    sizeof(memcached_server_st) * (count + ptr->number_of_hosts));
 
   if (!new_host_list)
@@ -285,7 +287,7 @@ memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *l
     WATCHPOINT_ASSERT(list[x].hostname[0] != 0);
     memcached_server_create(ptr, &ptr->hosts[ptr->number_of_hosts]);
     /* TODO check return type */
-    (void)memcached_server_create_with(ptr, &ptr->hosts[ptr->number_of_hosts], list[x].hostname, 
+    (void)memcached_server_create_with(ptr, &ptr->hosts[ptr->number_of_hosts], list[x].hostname,
                                        list[x].port, list[x].weight, list[x].type);
     ptr->number_of_hosts++;
   }
@@ -294,14 +296,14 @@ memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *l
   return run_distribution(ptr);
 }
 
-memcached_return memcached_server_add_unix_socket(memcached_st *ptr, 
+memcached_return memcached_server_add_unix_socket(memcached_st *ptr,
                                                   const char *filename)
 {
   return memcached_server_add_unix_socket_with_weight(ptr, filename, 0);
 }
 
-memcached_return memcached_server_add_unix_socket_with_weight(memcached_st *ptr, 
-                                                              const char *filename, 
+memcached_return memcached_server_add_unix_socket_with_weight(memcached_st *ptr,
+                                                              const char *filename,
                                                               uint32_t weight)
 {
   if (!filename)
@@ -310,41 +312,41 @@ memcached_return memcached_server_add_unix_socket_with_weight(memcached_st *ptr,
   return server_add(ptr, filename, 0, weight, MEMCACHED_CONNECTION_UNIX_SOCKET);
 }
 
-memcached_return memcached_server_add_udp(memcached_st *ptr, 
+memcached_return memcached_server_add_udp(memcached_st *ptr,
                                           const char *hostname,
                                           unsigned int port)
 {
   return memcached_server_add_udp_with_weight(ptr, hostname, port, 0);
 }
 
-memcached_return memcached_server_add_udp_with_weight(memcached_st *ptr, 
+memcached_return memcached_server_add_udp_with_weight(memcached_st *ptr,
                                                       const char *hostname,
                                                       unsigned int port,
                                                       uint32_t weight)
 {
   if (!port)
-    port= MEMCACHED_DEFAULT_PORT; 
+    port= MEMCACHED_DEFAULT_PORT;
 
   if (!hostname)
-    hostname= "localhost"; 
+    hostname= "localhost";
 
   return server_add(ptr, hostname, port, weight, MEMCACHED_CONNECTION_UDP);
 }
 
-memcached_return memcached_server_add(memcached_st *ptr, 
-                                      const char *hostname, 
+memcached_return memcached_server_add(memcached_st *ptr,
+                                      const char *hostname,
                                       unsigned int port)
 {
   return memcached_server_add_with_weight(ptr, hostname, port, 0);
 }
 
-memcached_return memcached_server_add_with_weight(memcached_st *ptr, 
-                                                  const char *hostname, 
+memcached_return memcached_server_add_with_weight(memcached_st *ptr,
+                                                  const char *hostname,
                                                   unsigned int port,
                                                   uint32_t weight)
 {
   if (!port)
-    port= MEMCACHED_DEFAULT_PORT; 
+    port= MEMCACHED_DEFAULT_PORT;
 
   if (!hostname)
     hostname= "localhost";
@@ -352,7 +354,7 @@ memcached_return memcached_server_add_with_weight(memcached_st *ptr,
   return server_add(ptr, hostname, port, weight, MEMCACHED_CONNECTION_TCP);
 }
 
-static memcached_return server_add(memcached_st *ptr, const char *hostname, 
+static memcached_return server_add(memcached_st *ptr, const char *hostname,
                                    unsigned int port,
                                    uint32_t weight,
                                    memcached_connection type)
@@ -362,8 +364,8 @@ static memcached_return server_add(memcached_st *ptr, const char *hostname,
   if ( (ptr->flags & MEM_USE_UDP && type != MEMCACHED_CONNECTION_UDP)
       || ( (type == MEMCACHED_CONNECTION_UDP) && !(ptr->flags & MEM_USE_UDP) ) )
     return MEMCACHED_INVALID_HOST_PROTOCOL;
-  
-  new_host_list= ptr->call_realloc(ptr, ptr->hosts, 
+
+  new_host_list= ptr->call_realloc(ptr, ptr->hosts,
                                    sizeof(memcached_server_st) * (ptr->number_of_hosts+1));
 
   if (new_host_list == NULL)
@@ -385,18 +387,18 @@ memcached_return memcached_server_remove(memcached_server_st *st_ptr)
   memcached_st *ptr= st_ptr->root;
   memcached_server_st *list= ptr->hosts;
 
-  for (x= 0, host_index= 0; x < ptr->number_of_hosts; x++) 
+  for (x= 0, host_index= 0; x < ptr->number_of_hosts; x++)
   {
-    if (strncmp(list[x].hostname, st_ptr->hostname, MEMCACHED_MAX_HOST_LENGTH) != 0 || list[x].port != st_ptr->port) 
+    if (strncmp(list[x].hostname, st_ptr->hostname, MEMCACHED_MAX_HOST_LENGTH) != 0 || list[x].port != st_ptr->port)
     {
       if (host_index != x)
         memcpy(list+host_index, list+x, sizeof(memcached_server_st));
       host_index++;
-    } 
+    }
   }
   ptr->number_of_hosts= host_index;
 
-  if (st_ptr->address_info) 
+  if (st_ptr->address_info)
   {
     freeaddrinfo(st_ptr->address_info);
     st_ptr->address_info= NULL;
@@ -406,16 +408,16 @@ memcached_return memcached_server_remove(memcached_server_st *st_ptr)
   return MEMCACHED_SUCCESS;
 }
 
-memcached_server_st *memcached_server_list_append(memcached_server_st *ptr, 
+memcached_server_st *memcached_server_list_append(memcached_server_st *ptr,
                                                   const char *hostname, unsigned int port,
                                                   memcached_return *error)
 {
   return memcached_server_list_append_with_weight(ptr, hostname, port, 0, error);
 }
 
-memcached_server_st *memcached_server_list_append_with_weight(memcached_server_st *ptr, 
+memcached_server_st *memcached_server_list_append_with_weight(memcached_server_st *ptr,
                                                               const char *hostname, unsigned int port,
-                                                              uint32_t weight, 
+                                                              uint32_t weight,
                                                               memcached_return *error)
 {
   unsigned int count;
@@ -425,14 +427,14 @@ memcached_server_st *memcached_server_list_append_with_weight(memcached_server_s
     return NULL;
 
   if (!port)
-    port= MEMCACHED_DEFAULT_PORT; 
+    port= MEMCACHED_DEFAULT_PORT;
 
   /* Increment count for hosts */
   count= 1;
   if (ptr != NULL)
   {
     count+= ptr[0].count;
-  } 
+  }
 
   new_host_list= (memcached_server_st *)realloc(ptr, sizeof(memcached_server_st) * count);
   if (!new_host_list)
index 7b9c2117bff972b893f17eca23e1d0ae05b4aaf9..2ecbe214d9fb416f60b9fca98290bb70ee37977f 100644 (file)
@@ -16,14 +16,14 @@ memcached_server_st *memcached_server_create(memcached_st *memc, memcached_serve
   }
   else
     memset(ptr, 0, sizeof(memcached_server_st));
-  
+
   ptr->root= memc;
 
   return ptr;
 }
 
-memcached_server_st *memcached_server_create_with(memcached_st *memc, memcached_server_st *host, 
-                                                  const char *hostname, unsigned int port, 
+memcached_server_st *memcached_server_create_with(memcached_st *memc, memcached_server_st *host,
+                                                  const char *hostname, unsigned int port,
                                                   uint32_t weight, memcached_connection type)
 {
   host= memcached_server_create(memc, host);
@@ -76,7 +76,7 @@ memcached_server_st *memcached_server_clone(memcached_server_st *clone, memcache
   if (ptr == NULL)
     return NULL;
 
-  rv = memcached_server_create_with(ptr->root, clone, 
+  rv = memcached_server_create_with(ptr->root, clone,
                                     ptr->hostname, ptr->port, ptr->weight,
                                     ptr->type);
   if (rv != NULL)
@@ -90,7 +90,7 @@ memcached_server_st *memcached_server_clone(memcached_server_st *clone, memcache
 
 }
 
-memcached_return memcached_server_cursor(memcached_st *ptr, 
+memcached_return memcached_server_cursor(memcached_st *ptr,
                                          memcached_server_function *callback,
                                          void *context,
                                          unsigned int number_of_callbacks)
@@ -119,7 +119,7 @@ memcached_server_st *memcached_server_by_key(memcached_st *ptr,  const char *key
 {
   uint32_t server_key;
 
-  *error= memcached_validate_key_length(key_length, 
+  *error= memcached_validate_key_length(key_length,
                                         ptr->flags & MEM_BINARY_PROTOCOL);
   unlikely (*error != MEMCACHED_SUCCESS)
     return NULL;
@@ -146,7 +146,7 @@ const char *memcached_server_error(memcached_server_st *ptr)
 {
   if (ptr)
     return ptr->cached_server_error;
-  else 
+  else
     return NULL;
 }
 
@@ -154,3 +154,8 @@ void memcached_server_error_reset(memcached_server_st *ptr)
 {
   ptr->cached_server_error[0]= 0;
 }
+
+memcached_server_st *memcached_server_get_last_disconnect(memcached_st *ptr)
+{
+  return ptr->last_disconnected_server;
+}
index ec1014a61b1aa85f955305e676dcca3c35acae88..de57eaec3534cf69cba4fd5cd91707cf666d4740 100644 (file)
@@ -49,13 +49,13 @@ struct memcached_server_st {
 #define memcached_server_response_count(A) (A)->cursor_active
 
 LIBMEMCACHED_API
-memcached_return memcached_server_cursor(memcached_st *ptr, 
+memcached_return memcached_server_cursor(memcached_st *ptr,
                                          memcached_server_function *callback,
                                          void *context,
                                          unsigned int number_of_callbacks);
 
 LIBMEMCACHED_API
-memcached_server_st *memcached_server_by_key(memcached_st *ptr,  const char *key, 
+memcached_server_st *memcached_server_by_key(memcached_st *ptr,  const char *key,
                                              size_t key_length, memcached_return *error);
 
 LIBMEMCACHED_API
@@ -71,8 +71,8 @@ LIBMEMCACHED_API
 memcached_server_st *memcached_server_create(memcached_st *memc, memcached_server_st *ptr);
 
 LIBMEMCACHED_API
-memcached_server_st *memcached_server_create_with(memcached_st *memc, memcached_server_st *host, 
-                                                  const char *hostname, unsigned int port, 
+memcached_server_st *memcached_server_create_with(memcached_st *memc, memcached_server_st *host,
+                                                  const char *hostname, unsigned int port,
                                                   uint32_t weight, memcached_connection type);
 
 LIBMEMCACHED_API
@@ -86,6 +86,9 @@ memcached_analysis_st *memcached_analyze(memcached_st *memc, memcached_stat_st *
 LIBMEMCACHED_API
 memcached_return memcached_server_remove(memcached_server_st *st_ptr);
 
+LIBMEMCACHED_API
+memcached_server_st *memcached_server_get_last_disconnect(memcached_st *ptr);
+
 #ifdef __cplusplus
 }
 #endif
index 914e17f2b6bb2da91544d99986703790e98528f9..9e048784228873fd8238666c1f001ab8c32fbe7f 100644 (file)
@@ -4732,6 +4732,60 @@ static test_return_t regression_bug_442914(memcached_st *memc)
   return TEST_SUCCESS;
 }
 
+
+
+/* Test memcached_server_get_last_disconnect
+ * For a working server set, shall be NULL
+ * For a set of non existing server, shall not be NULL
+ */
+static test_return_t  test_get_last_disconnect(memcached_st *memc)
+{
+  memcached_return rc;
+  memcached_server_st *disconnected_server;
+
+  /* With the working set of server */
+  const char *key= "marmotte";
+  const char *value= "milka";
+
+  rc= memcached_set(memc, key, strlen(key),
+                    value, strlen(value),
+                    (time_t)0, (uint32_t)0);
+  assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+
+  disconnected_server = memcached_server_get_last_disconnect(memc);
+  assert(disconnected_server == NULL);
+
+  /* With a non existing server */
+  memcached_st *mine;
+  memcached_server_st *servers;
+
+  const char *server_list= "localhost:9";
+
+  servers= memcached_servers_parse(server_list);
+  assert(servers);
+  mine= memcached_create(NULL);
+  rc= memcached_server_push(mine, servers);
+  assert(rc == MEMCACHED_SUCCESS);
+  memcached_server_list_free(servers);
+  assert(mine);
+
+  rc= memcached_set(mine, key, strlen(key),
+                    value, strlen(value),
+                    (time_t)0, (uint32_t)0);
+  assert(rc != MEMCACHED_SUCCESS);
+
+  disconnected_server = memcached_server_get_last_disconnect(mine);
+  assert(disconnected_server != NULL);
+  assert(disconnected_server->port == 9);
+  assert(strncmp(disconnected_server->hostname,"localhost",9) == 0);
+
+  memcached_quit(mine);
+  memcached_free(mine);
+
+  return TEST_SUCCESS;
+}
+
+
 test_st udp_setup_server_tests[] ={
   {"set_udp_behavior_test", 0, set_udp_behavior_test},
   {"add_tcp_server_udp_client_test", 0, add_tcp_server_udp_client_test},
@@ -4811,6 +4865,7 @@ test_st tests[] ={
 #ifdef HAVE_LIBMEMCACHEDUTIL
   {"connectionpool", 1, connection_pool_test },
 #endif
+  {"test_get_last_disconnect", 1, test_get_last_disconnect},
   {0, 0, 0}
 };