Merge for Dmitry
authorBrian Aker <brian@gaz>
Thu, 18 Feb 2010 22:53:58 +0000 (14:53 -0800)
committerBrian Aker <brian@gaz>
Thu, 18 Feb 2010 22:53:58 +0000 (14:53 -0800)
53 files changed:
ChangeLog
clients/memstat.c
docs/memcached_server_st.pod
docs/memcached_servers.pod
libmemcached/auto.c
libmemcached/behavior.c
libmemcached/behavior.h
libmemcached/common.h
libmemcached/connect.c
libmemcached/delete.c
libmemcached/do.c
libmemcached/do.h
libmemcached/dump.c
libmemcached/fetch.c
libmemcached/flush.c
libmemcached/flush_buffers.c
libmemcached/get.c
libmemcached/hash.c
libmemcached/hash.h
libmemcached/hosts.c
libmemcached/include.am
libmemcached/io.c
libmemcached/io.h
libmemcached/memcached.c
libmemcached/memcached.h
libmemcached/memcached.hpp
libmemcached/parse.c
libmemcached/parse.h
libmemcached/purge.c
libmemcached/quit.c
libmemcached/quit.h
libmemcached/response.c
libmemcached/response.h
libmemcached/result.c
libmemcached/result.h
libmemcached/server.c
libmemcached/server.h
libmemcached/server_list.c
libmemcached/server_list.h [new file with mode: 0644]
libmemcached/stats.c
libmemcached/stats.h
libmemcached/storage.c
libmemcached/string.c
libmemcached/string.h
libmemcached/types.h
libmemcached/verbosity.c
libmemcached/version.c
support/libmemcached.spec.in
tests/include.am
tests/libmemcached_world.h
tests/mem_functions.c
tests/mem_udp.c [new file with mode: 0644]
tests/server.c

index 1b946b4332ac3fd6036e517e497d6a1d7004080e..962299f4c841ea5d6e33df35caf06654b023a550 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+0.39
+
+* Remove the undocumented call memcached_server_remove().
+
+* The undocumented call memcached_server_by_key() now returns const.
+
+* memcached_server_error_reset() has been deprecated.
+
+* memcached_server_list() has been deprecated. Use memcached_server_cursor() to walk the servers found in a memcached_st() structure.
+
 0.38 Wed Feb 10 09:40:33 PST 2010
 * C++ interface for libhashkit.
 * Modified memcached_set_memory_allocators() so that it requires a context pointer.
index 42503d551ac8ce4242f98475b0d8e90d8f9bff8a..6b6c5bcf0ac1df9f37627de8ce44b73ca5d81e5f 100644 (file)
 
 /* Prototypes */
 static void options_parse(int argc, char *argv[]);
-static void run_analyzer(memcached_st *memc, memcached_stat_st *memc_stat,
-                         memcached_server_st *server_list);
-static void print_server_listing(memcached_st *memc, memcached_stat_st *memc_stat,
-                                 memcached_server_st *server_list);
+static void run_analyzer(memcached_st *memc, memcached_stat_st *memc_stat);
 static void print_analysis_report(memcached_st *memc,
-                                  memcached_analysis_st *report,
-                                  memcached_server_st *server_list);
+                                  memcached_analysis_st *report);
 
 static int opt_verbose= 0;
 static int opt_displayflag= 0;
@@ -59,17 +55,50 @@ static struct option long_options[]=
   {0, 0, 0, 0},
 };
 
+
+static memcached_return_t server_print_callback(const memcached_st *memc,
+                                                memcached_server_instance_st instance,
+                                                void *context)
+{
+  memcached_stat_st server_stat;
+  memcached_return_t rc;
+  char **list;
+  char **ptr;
+
+  (void)context;
+
+  rc= memcached_stat_servername(&server_stat, NULL,
+                                memcached_server_name(instance),
+                                memcached_server_port(instance));
+
+  list= memcached_stat_get_keys(memc, &server_stat, &rc);
+
+  printf("Server: %s (%u)\n", memcached_server_name(instance),
+         (uint32_t)memcached_server_port(instance));
+
+  for (ptr= list; *ptr; ptr++)
+  {
+    char *value= memcached_stat_get_value(memc, &server_stat, *ptr, &rc);
+
+    printf("\t %s: %s\n", *ptr, value);
+    free(value);
+  }
+
+  free(list);
+  printf("\n");
+
+  return MEMCACHED_SUCCESS;
+}
+
 int main(int argc, char *argv[])
 {
   memcached_return_t rc;
   memcached_st *memc;
-  memcached_stat_st *memc_stat;
   memcached_server_st *servers;
-  memcached_server_st *server_list;
 
   options_parse(argc, argv);
 
-  if (!opt_servers)
+  if (! opt_servers)
   {
     char *temp;
 
@@ -89,8 +118,6 @@ int main(int argc, char *argv[])
   memcached_server_push(memc, servers);
   memcached_server_list_free(servers);
 
-  memc_stat= memcached_stat(memc, NULL, &rc);
-
   if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_SOME_ERRORS)
   {
     printf("Failure to communicate with servers (%s)\n",
@@ -98,23 +125,37 @@ int main(int argc, char *argv[])
     exit(1);
   }
 
-  server_list= memcached_server_list(memc);
-
   if (opt_analyze)
-    run_analyzer(memc, memc_stat, server_list);
+  {
+    memcached_stat_st *memc_stat;
+
+    memc_stat= memcached_stat(memc, NULL, &rc);
+
+    if (! memc_stat)
+      exit(-1);
+
+    run_analyzer(memc, memc_stat);
+
+    memcached_stat_free(memc, memc_stat);
+  }
   else
-    print_server_listing(memc, memc_stat, server_list);
+  {
+    memcached_server_fn callbacks[1];
+
+    callbacks[0]= server_print_callback;
+    rc= memcached_server_cursor(memc, callbacks,
+                                NULL, 1);
+
+  }
 
-  free(memc_stat);
   free(opt_servers);
 
   memcached_free(memc);
 
-  return 0;
+  return rc == MEMCACHED_SUCCESS ? 0: -1;
 }
 
-static void run_analyzer(memcached_st *memc, memcached_stat_st *memc_stat,
-                         memcached_server_st *server_list)
+static void run_analyzer(memcached_st *memc, memcached_stat_st *memc_stat)
 {
   memcached_return_t rc;
 
@@ -128,13 +169,13 @@ static void run_analyzer(memcached_st *memc, memcached_stat_st *memc_stat,
              memcached_strerror(memc, rc));
       exit(1);
     }
-    print_analysis_report(memc, report, server_list);
+    print_analysis_report(memc, report);
     free(report);
   }
   else if (strcmp(analyze_mode, "latency") == 0)
   {
     memcached_st **servers;
-    uint32_t x, y, flags, server_count= memcached_server_count(memc);
+    uint32_t flags, server_count= memcached_server_count(memc);
     uint32_t num_of_tests= 32;
     const char *test_key= "libmemcached_test_key";
 
@@ -145,9 +186,12 @@ static void run_analyzer(memcached_st *memc, memcached_stat_st *memc_stat,
       return;
     }
 
-    for (x= 0; x < server_count; x++)
+    for (uint32_t x= 0; x < server_count; x++)
     {
-      if((servers[x]= memcached_create(NULL)) == NULL)
+      memcached_server_instance_st instance=
+        memcached_server_instance_by_position(memc, x);
+
+      if ((servers[x]= memcached_create(NULL)) == NULL)
       {
         fprintf(stderr, "Failed to memcached_create()\n");
         if (x > 0)
@@ -160,18 +204,22 @@ static void run_analyzer(memcached_st *memc, memcached_stat_st *memc_stat,
         return;
       }
       memcached_server_add(servers[x],
-                           memcached_server_name(memc, server_list[x]),
-                           memcached_server_port(memc, server_list[x]));
+                           memcached_server_name(instance),
+                           memcached_server_port(instance));
     }
 
     printf("Network Latency Test:\n\n");
     struct timeval start_time, end_time;
-    long elapsed_time, slowest_time= 0, slowest_server= 0;
+    uint32_t slowest_server= 0;
+    long elapsed_time, slowest_time= 0;
 
-    for (x= 0; x < server_count; x++)
+    for (uint32_t x= 0; x < server_count; x++)
     {
+      memcached_server_instance_st instance=
+        memcached_server_instance_by_position(memc, x);
       gettimeofday(&start_time, NULL);
-      for (y= 0; y < num_of_tests; y++)
+
+      for (uint32_t y= 0; y < num_of_tests; y++)
       {
         size_t vlen;
         char *val= memcached_get(servers[x], test_key, strlen(test_key),
@@ -187,36 +235,39 @@ static void run_analyzer(memcached_st *memc, memcached_stat_st *memc_stat,
 
       if (elapsed_time > slowest_time)
       {
-        slowest_server= (long)x;
+        slowest_server= x;
         slowest_time= elapsed_time;
       }
 
       if (rc != MEMCACHED_NOTFOUND && rc != MEMCACHED_SUCCESS)
       {
         printf("\t %s (%d)  =>  failed to reach the server\n",
-               memcached_server_name(memc, server_list[x]),
-               memcached_server_port(memc, server_list[x]));
+               memcached_server_name(instance),
+               memcached_server_port(instance));
       }
       else
       {
         printf("\t %s (%d)  =>  %ld.%ld seconds\n",
-               memcached_server_name(memc, server_list[x]),
-               memcached_server_port(memc, server_list[x]),
+               memcached_server_name(instance),
+               memcached_server_port(instance),
                elapsed_time / 1000, elapsed_time % 1000);
       }
     }
 
     if (server_count > 1 && slowest_time > 0)
     {
+      memcached_server_instance_st slowest=
+        memcached_server_instance_by_position(memc, slowest_server);
+
       printf("---\n");
       printf("Slowest Server: %s (%d) => %ld.%ld seconds\n",
-             memcached_server_name(memc, server_list[slowest_server]),
-             memcached_server_port(memc, server_list[slowest_server]),
+             memcached_server_name(slowest),
+             memcached_server_port(slowest),
              slowest_time / 1000, slowest_time % 1000);
     }
     printf("\n");
 
-    for (x= 0; x < server_count; x++)
+    for (uint32_t x= 0; x < server_count; x++)
       memcached_free(servers[x]);
 
     free(servers);
@@ -229,40 +280,14 @@ static void run_analyzer(memcached_st *memc, memcached_stat_st *memc_stat,
   }
 }
 
-static void print_server_listing(memcached_st *memc, memcached_stat_st *memc_stat,
-                                 memcached_server_st *server_list)
-{
-  unsigned int x;
-  memcached_return_t rc;
-
-  printf("Listing %u Server\n\n", memcached_server_count(memc));
-  for (x= 0; x < memcached_server_count(memc); x++)
-  {
-    char **list;
-    char **ptr;
-
-    list= memcached_stat_get_keys(memc, &memc_stat[x], &rc);
-
-    printf("Server: %s (%u)\n", memcached_server_name(memc, server_list[x]),
-           (uint32_t)memcached_server_port(memc, server_list[x]));
-    for (ptr= list; *ptr; ptr++)
-    {
-      char *value= memcached_stat_get_value(memc, &memc_stat[x], *ptr, &rc);
-
-      printf("\t %s: %s\n", *ptr, value);
-      free(value);
-    }
-
-    free(list);
-    printf("\n");
-  }
-}
-
 static void print_analysis_report(memcached_st *memc,
-                                  memcached_analysis_st *report,
-                                  memcached_server_st *server_list)
+                                  memcached_analysis_st *report)
+                                  
 {
   uint32_t server_count= memcached_server_count(memc);
+  memcached_server_instance_st most_consumed_server= memcached_server_instance_by_position(memc, report->most_consumed_server);
+  memcached_server_instance_st least_free_server= memcached_server_instance_by_position(memc, report->least_free_server);
+  memcached_server_instance_st oldest_server= memcached_server_instance_by_position(memc, report->oldest_server);
 
   printf("Memcached Cluster Analysis Report\n\n");
 
@@ -278,16 +303,16 @@ static void print_analysis_report(memcached_st *memc,
 
   printf("\n");
   printf("\tNode with most memory consumption  : %s:%u (%llu bytes)\n",
-         memcached_server_name(memc, server_list[report->most_consumed_server]),
-         (uint32_t)memcached_server_port(memc, server_list[report->most_consumed_server]),
+         memcached_server_name(most_consumed_server),
+         (uint32_t)memcached_server_port(most_consumed_server),
          (unsigned long long)report->most_used_bytes);
   printf("\tNode with least free space         : %s:%u (%llu bytes remaining)\n",
-         memcached_server_name(memc, server_list[report->least_free_server]),
-         (uint32_t)memcached_server_port(memc, server_list[report->least_free_server]),
+         memcached_server_name(least_free_server),
+         (uint32_t)memcached_server_port(least_free_server),
          (unsigned long long)report->least_remaining_bytes);
   printf("\tNode with longest uptime           : %s:%u (%us)\n",
-         memcached_server_name(memc, server_list[report->oldest_server]),
-         (uint32_t)memcached_server_port(memc, server_list[report->oldest_server]),
+         memcached_server_name(oldest_server),
+         (uint32_t)memcached_server_port(oldest_server),
          report->longest_uptime);
   printf("\tPool-wide Hit Ratio                : %1.f%%\n", report->pool_hit_ratio);
   printf("\n");
index 32d4e1e98344b014e88fae9564707b3f9dfd9c69..d50334ae26eb2103e80df6180ad8884fc277e245 100644 (file)
@@ -11,21 +11,25 @@ C Client Library for memcached (libmemcached, -lmemcached)
 
   #include <memcached.h>
 
-  void memcached_server_list_free (memcached_server_st *ptr);
+  const memcached_server_instance_st
+    memcached_server_list (memcached_st *ptr);
 
-  memcached_server_st *
-    memcached_server_list_append (memcached_server_st *ptr, 
+  void memcached_server_list_free (memcached_server_list_st list);
+
+  memcached_server_list_st
+    memcached_server_list_append (memcached_server_list_st list, 
                                   const char *hostname,
                                   unsigned int port, 
                                   memcached_return_t *error);
 
-  unsigned int memcached_server_list_count (memcached_server_st *ptr);
+  uint32_t memcached_server_list_count (memcached_server_list_st list);
 
-  memcached_server_st *memcached_servers_parse (const char *server_strings);
+  memcached_server_list_st memcached_servers_parse (const char *server_strings);
 
-  const char *memcached_server_error (memcached_server_st *ptr);
+  const char *memcached_server_error (memcached_server_instance_st instance);
 
-  void memcached_server_error_reset (memcached_server_st *ptr);
+  DEPRECATED
+  void memcached_server_error_reset (memcached_server_instance_st list);
 
 =head1 DESCRIPTION
 
@@ -34,6 +38,9 @@ memcached_server_st structures. You should not modify these structures
 directly. Functions are provided to modify these structures (and more can be
 added, just ask!).
 
+memcached_server_list() is used to provide an array of all defined hosts.
+This was incorrectly documented as "requiring free()" up till version 0.39.
+
 memcached_server_list_free() deallocates all memory associated with the array
 of memcached_server_st that you passed to it. 
 
@@ -49,9 +56,11 @@ The example is "localhost, foo:555, foo, bar". All hosts except foo:555 will
 be set to the default port, while that host will have a port of 555.
 
 memcached_server_error() can be used to look at the text of the last error 
-message sent by the server to to the client. Use memcached_server_error_reset() 
-to reset the message (this does not currently free up the memory associated
-with the message).
+message sent by the server to to the client.
+
+Before version 0.39 theses functions used a memcache_server_st *. In 0.39
+memcached_server_st * was aliased to memcached_server_list_st. This was
+done for a style reason/to help clean up some concepts in the code. 
 
 
 =head1 RETURN
index 6ffd8e225aa90aed1c32e8a01bd97d705ac2b2d0..f2d66c94f68335765a29c95f1124f72ce7a0e24c 100644 (file)
@@ -12,9 +12,6 @@ C Client Library for memcached (libmemcached, -lmemcached)
 
   uint32_t memcached_server_count (memcached_st *ptr);
 
-  memcached_server_st *
-    memcached_server_list (memcached_st *ptr);
-
   memcached_return_t
     memcached_server_add (memcached_st *ptr,
                           const char *hostname,
@@ -22,8 +19,8 @@ C Client Library for memcached (libmemcached, -lmemcached)
 
   memcached_return_t
     memcached_server_add_udp (memcached_st *ptr,
-                          const char *hostname,
-                          in_port_t port);
+                             const char *hostname,
+                             in_port_t port);
 
   memcached_return_t
     memcached_server_add_unix_socket (memcached_st *ptr,
@@ -31,21 +28,22 @@ C Client Library for memcached (libmemcached, -lmemcached)
 
   memcached_return_t
     memcached_server_push (memcached_st *ptr,
-                           memcached_server_st *list);
+                           const memcached_server_st *list);
 
-  memcached_server_st *
-    memcached_server_by_key (memcached_st *ptr,
-                             const char *key, size_t key_length,
+  memcached_server_instance_st
+    memcached_server_by_key (const memcached_st *ptr,
+                             const char *key,
+                            size_t key_length,
                              memcached_return_t *error);
 
-  memcached_server_st *
-    memcached_server_get_last_disconnect (memcached_st *ptr)
+  memcached_server_instance_st
+    memcached_server_get_last_disconnect (const memcached_st *ptr)
 
   memcached_return_t
-    memcached_server_cursor(memcached_st *ptr,
-                           memcached_server_fn *callback,
-                           void *context,
-                           uint32_t number_of_callbacks);
+    memcached_server_cursor(const memcached_st *ptr,
+                           const memcached_server_fn *callback,
+                           void *context,
+                           uint32_t number_of_callbacks);
 
 
 =head1 DESCRIPTION
@@ -58,10 +56,6 @@ memcached_server_st(3).
 memcached_server_count() provides you a count of the current number of
 servers being used by a C<memcached_st> structure.
 
-memcached_server_list() is used to provide an array of all defined hosts.
-You are responsible for freeing this list (aka it is not a pointer to the
-currently used structure).
-
 memcached_server_add() pushes a single TCP server into the C<memcached_st>
 structure. This server will be placed at the end. Duplicate servers are
 allowed, so duplication is not checked. Executing this function with the
index 608324df23ff8d99acde7960997ab74cd8c824a1..c36cd92f4c969ccf0508f89b19d09a75093a1596 100644 (file)
@@ -22,7 +22,7 @@ static memcached_return_t text_incr_decr(memcached_st *ptr,
   memcached_return_t rc;
   char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
   uint32_t server_key;
-  memcached_server_instance_st *instance;
+  memcached_server_write_instance_st instance;
   bool no_reply= ptr->flags.no_reply;
 
   unlikely (memcached_server_count(ptr) == 0)
@@ -31,7 +31,7 @@ static memcached_return_t text_incr_decr(memcached_st *ptr,
   if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
     return MEMCACHED_BAD_KEY_PROVIDED;
 
-  server_key= memcached_generate_hash(ptr, master_key, master_key_length);
+  server_key= memcached_generate_hash_with_redistribution(ptr, master_key, master_key_length);
   instance= memcached_server_instance_fetch(ptr, server_key);
 
   send_length= (size_t)snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
@@ -83,13 +83,13 @@ static memcached_return_t binary_incr_decr(memcached_st *ptr, uint8_t cmd,
                                            uint64_t *value)
 {
   uint32_t server_key;
-  memcached_server_instance_st *instance;
+  memcached_server_write_instance_st instance;
   bool no_reply= ptr->flags.no_reply;
 
   unlikely (memcached_server_count(ptr) == 0)
     return MEMCACHED_NO_SERVERS;
 
-  server_key= memcached_generate_hash(ptr, master_key, master_key_length);
+  server_key= memcached_generate_hash_with_redistribution(ptr, master_key, master_key_length);
   instance= memcached_server_instance_fetch(ptr, server_key);
 
   if (no_reply)
index ba4db7377d8899d87d053748ad71082969c43952..886457a59a7867fcf31e18825aa7d8a037f2a020 100644 (file)
@@ -170,7 +170,7 @@ memcached_return_t memcached_behavior_set(memcached_st *ptr,
       break;
   case MEMCACHED_BEHAVIOR_CORK:
       {
-        memcached_server_instance_st *instance;
+        memcached_server_write_instance_st instance;
         bool action= set_flag(data);
 
         if (action == false)
@@ -230,6 +230,11 @@ memcached_return_t memcached_behavior_set(memcached_st *ptr,
   return MEMCACHED_SUCCESS;
 }
 
+inline bool _is_auto_eject_host(const memcached_st *ptr)
+{
+  return ptr->flags.auto_eject_hosts;
+}
+
 uint64_t memcached_behavior_get(memcached_st *ptr,
                                 const memcached_behavior_t flag)
 {
@@ -287,7 +292,7 @@ uint64_t memcached_behavior_get(memcached_st *ptr,
     {
       int sock_size= 0;
       socklen_t sock_length= sizeof(int);
-      memcached_server_instance_st *instance;
+      memcached_server_write_instance_st instance;
 
       if (ptr->send_size != -1) // If value is -1 then we are using the default
         return (uint64_t) ptr->send_size;
@@ -312,7 +317,7 @@ uint64_t memcached_behavior_get(memcached_st *ptr,
     {
       int sock_size= 0;
       socklen_t sock_length= sizeof(int);
-      memcached_server_instance_st *instance;
+      memcached_server_write_instance_st instance;
 
       if (ptr->recv_size != -1) // If value is -1 then we are using the default
         return (uint64_t) ptr->recv_size;
index 1bc51b7d80465bbcdf957185ec24b06cb21cd11d..39a430d7fa526f470476c14c38386c3fc18bf8cc 100644 (file)
@@ -40,6 +40,9 @@ memcached_return_t memcached_behavior_set_distribution_hash(memcached_st *ptr, m
 LIBMEMCACHED_API
 memcached_hash_t memcached_behavior_get_distribution_hash(memcached_st *ptr);
 
+LIBMEMCACHED_LOCAL
+bool _is_auto_eject_host(const memcached_st *ptr);
+
 
 #ifdef __cplusplus
 }
index 3391c22957ed6113b49656296953de722c6fc1b6..a03cabbf7655b014055fafd71f6cf718471d46c2 100644 (file)
 #include "libmemcached/memcached.h"
 #include "libmemcached/watchpoint.h"
 
-typedef struct memcached_server_st memcached_server_instance_st;
+typedef struct memcached_server_st * memcached_server_write_instance_st;
+
+LIBMEMCACHED_LOCAL
+memcached_server_write_instance_st memcached_server_instance_fetch(memcached_st *ptr, uint32_t server_key);
 
 /* These are private not to be installed headers */
 #include "libmemcached/do.h"
@@ -101,10 +104,7 @@ extern "C" {
 #endif
 
 LIBMEMCACHED_LOCAL
-memcached_return_t memcached_connect(memcached_server_instance_st *ptr);
-
-LIBMEMCACHED_LOCAL
-void memcached_quit_server(memcached_server_instance_st *ptr, bool io_death);
+memcached_return_t memcached_connect(memcached_server_write_instance_st ptr);
 
 LIBMEMCACHED_LOCAL
 memcached_return_t run_distribution(memcached_st *ptr);
@@ -124,23 +124,22 @@ memcached_return_t run_distribution(memcached_st *ptr);
 #define memcached_set_allocated(__object, __value) ((__object)->options.is_allocated(= (__value))
 
 
-LIBMEMCACHED_LOCAL
-memcached_return_t value_fetch(memcached_server_instance_st *ptr,
-                               char *buffer,
-                               memcached_result_st *result);
-LIBMEMCACHED_LOCAL
-void server_list_free(memcached_st *ptr, memcached_server_instance_st *servers);
-
 LIBMEMCACHED_LOCAL
 memcached_return_t memcached_key_test(const char * const *keys,
                                       const size_t *key_length,
                                       size_t number_of_keys);
 
 LIBMEMCACHED_LOCAL
-uint32_t generate_hash(memcached_st *ptr, const char *key, size_t key_length);
+memcached_return_t memcached_purge(memcached_server_write_instance_st ptr);
 
 LIBMEMCACHED_LOCAL
-memcached_return_t memcached_purge(memcached_server_instance_st *ptr);
+memcached_server_st *memcached_server_create_with(const memcached_st *memc,
+                                                  memcached_server_write_instance_st host,
+                                                  const char *hostname,
+                                                  in_port_t port,
+                                                  uint32_t weight,
+                                                  memcached_connection_t type);
+
 
 static inline memcached_return_t memcached_validate_key_length(size_t key_length, bool binary)
 {
index b599977fab77ab4799297b1dcb5a9e1197c17f54..4b8939c11d4942802ea511134df2ad962acb3672 100644 (file)
@@ -313,7 +313,7 @@ static memcached_return_t network_connect(memcached_server_st *ptr)
 }
 
 
-memcached_return_t memcached_connect(memcached_server_st *ptr)
+memcached_return_t memcached_connect(memcached_server_write_instance_st ptr)
 {
   memcached_return_t rc= MEMCACHED_NO_SERVERS;
   LIBMEMCACHED_MEMCACHED_CONNECT_START();
index 75a44ed8383a38e605d341ef60e7d5c3caf1d07f..7fd1f2aa307c1837521fbb6b8fa41ad0b54fca42 100644 (file)
@@ -24,7 +24,7 @@ memcached_return_t memcached_delete_by_key(memcached_st *ptr,
   memcached_return_t rc;
   char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
   uint32_t server_key;
-  memcached_server_instance_st *instance;
+  memcached_server_write_instance_st instance;
 
   LIBMEMCACHED_MEMCACHED_DELETE_START();
 
@@ -36,7 +36,7 @@ memcached_return_t memcached_delete_by_key(memcached_st *ptr,
   unlikely (memcached_server_count(ptr) == 0)
     return MEMCACHED_NO_SERVERS;
 
-  server_key= memcached_generate_hash(ptr, master_key, master_key_length);
+  server_key= memcached_generate_hash_with_redistribution(ptr, master_key, master_key_length);
   instance= memcached_server_instance_fetch(ptr, server_key);
 
   to_write= (ptr->flags.buffer_requests) ? false : true;
@@ -148,7 +148,7 @@ static inline memcached_return_t binary_delete(memcached_st *ptr,
                                                size_t key_length,
                                                bool flush)
 {
-  memcached_server_instance_st *instance;
+  memcached_server_write_instance_st instance;
   protocol_binary_request_delete request= {.bytes= {0}};
 
   instance= memcached_server_instance_fetch(ptr, server_key);
@@ -188,7 +188,7 @@ static inline memcached_return_t binary_delete(memcached_st *ptr,
 
     for (uint32_t x= 0; x < ptr->number_of_replicas; ++x)
     {
-      memcached_server_instance_st *replica;
+      memcached_server_write_instance_st replica;
 
       ++server_key;
       if (server_key == memcached_server_count(ptr))
index d5a75484244137103804d8eaac80396b2b1a6607..2fd1f3273ee5f2439fb13808d66997e5e5ed266c 100644 (file)
@@ -11,7 +11,7 @@
 
 #include "common.h"
 
-memcached_return_t memcached_do(memcached_server_st *ptr, const void *command, 
+memcached_return_t memcached_do(memcached_server_write_instance_st ptr, const void *command, 
                                 size_t command_length, bool with_flush)
 {
   memcached_return_t rc;
index d62cd489371a73094e2b9ef0006f14c8c0fdb170..8f95c8b5f3dcec2025aa64393f2c6166f57c1740 100644 (file)
@@ -17,8 +17,10 @@ extern "C" {
 #endif
 
 LIBMEMCACHED_LOCAL
-memcached_return_t memcached_do(memcached_server_instance_st *ptr, const void *commmand,
-                                size_t command_length, bool with_flush);
+memcached_return_t memcached_do(memcached_server_write_instance_st ptr, 
+                                const void *commmand,
+                                size_t command_length,
+                                bool with_flush);
 
 #ifdef __cplusplus
 }
index 8d9c525fb70e5ccda651eeb9dcae93992dd97d7b..a0d62df0e806ffb237a8b84b8761c920eeaea7ca 100644 (file)
@@ -20,7 +20,7 @@ static memcached_return_t ascii_dump(memcached_st *ptr, memcached_dump_fn *callb
 
   for (server_key= 0; server_key < memcached_server_count(ptr); server_key++)
   {
-    memcached_server_instance_st *instance;
+    memcached_server_write_instance_st instance;
     instance= memcached_server_instance_fetch(ptr, server_key);
 
     /* 256 I BELIEVE is the upper limit of slabs */
index 321ff85e7d586f0b0ac473c886ec68cbfdcb3e5a..4359c9355bf006af53a5b1e3d999fa2d263d3483 100644 (file)
@@ -58,7 +58,7 @@ memcached_result_st *memcached_fetch_result(memcached_st *ptr,
     if ((result= memcached_result_create(ptr, NULL)) == NULL)
       return NULL;
 
-  while ((server = memcached_io_get_readable_server(ptr)) != NULL) 
+  while ((server= memcached_io_get_readable_server(ptr)) != NULL) 
   {
     char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
     *error= memcached_response(server, buffer, sizeof(buffer), result);
index 8e1361a886a92546d6fb6326ac7faed012a9ea26..c8428f7015f979deec1f3e2eca63d18143079fdd 100644 (file)
@@ -32,7 +32,7 @@ static memcached_return_t memcached_flush_textual(memcached_st *ptr,
   for (x= 0; x < memcached_server_count(ptr); x++)
   {
     bool no_reply= ptr->flags.no_reply;
-    memcached_server_instance_st *instance=
+    memcached_server_write_instance_st instance=
       memcached_server_instance_fetch(ptr, x);
 
     if (expiration)
@@ -70,7 +70,7 @@ static memcached_return_t memcached_flush_binary(memcached_st *ptr,
 
   for (x= 0; x < memcached_server_count(ptr); x++)
   {
-    memcached_server_instance_st *instance=
+    memcached_server_write_instance_st instance=
       memcached_server_instance_fetch(ptr, x);
 
     if (ptr->flags.no_reply)
@@ -92,7 +92,7 @@ static memcached_return_t memcached_flush_binary(memcached_st *ptr,
 
   for (x= 0; x < memcached_server_count(ptr); x++)
   {
-    memcached_server_instance_st *instance=
+    memcached_server_write_instance_st instance=
       memcached_server_instance_fetch(ptr, x);
 
     if (memcached_server_response_count(instance) > 0)
index cf391440688d5872589f9987d9867111b26ab1e6..0a90275792f7e0b6524cedad5caa367c33cb457d 100644 (file)
@@ -6,7 +6,7 @@ memcached_return_t memcached_flush_buffers(memcached_st *memc)
 
   for (uint32_t x= 0; x < memcached_server_count(memc); ++x)
   {
-    memcached_server_instance_st *instance=
+    memcached_server_write_instance_st instance=
       memcached_server_instance_fetch(memc, x);
 
     if (instance->write_buffer_offset != 0) 
index ba4d4bc3b479b83ec7a516ee085de8569e26f29f..1df6247cbbcf6b3f6d12af8e63de03aa5793e655 100644 (file)
@@ -169,7 +169,7 @@ static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr,
   {
     if (ptr->flags.verify_key && (memcached_key_test((const char * const *)&master_key, &master_key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
       return MEMCACHED_BAD_KEY_PROVIDED;
-    master_server_key= memcached_generate_hash(ptr, master_key, master_key_length);
+    master_server_key= memcached_generate_hash_with_redistribution(ptr, master_key, master_key_length);
     is_master_key_set= true;
   }
 
@@ -181,7 +181,7 @@ static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr,
   */
   for (x= 0; x < memcached_server_count(ptr); x++)
   {
-    memcached_server_instance_st *instance=
+    memcached_server_write_instance_st instance=
       memcached_server_instance_fetch(ptr, x);
 
     if (memcached_server_response_count(instance))
@@ -212,7 +212,7 @@ static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr,
   */
   for (x= 0; x < number_of_keys; x++)
   {
-    memcached_server_instance_st *instance;
+    memcached_server_write_instance_st instance;
     uint32_t server_key;
 
     if (is_master_key_set)
@@ -221,7 +221,7 @@ static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr,
     }
     else
     {
-      server_key= memcached_generate_hash(ptr, keys[x], key_length[x]);
+      server_key= memcached_generate_hash_with_redistribution(ptr, keys[x], key_length[x]);
     }
 
     instance= memcached_server_instance_fetch(ptr, server_key);
@@ -274,7 +274,7 @@ static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr,
   */
   for (x= 0; x < memcached_server_count(ptr); x++)
   {
-    memcached_server_instance_st *instance=
+    memcached_server_write_instance_st instance=
       memcached_server_instance_fetch(ptr, x);
 
     if (memcached_server_response_count(instance))
@@ -362,7 +362,7 @@ static memcached_return_t simple_binary_mget(memcached_st *ptr,
   for (x= 0; x < number_of_keys; x++)
   {
     uint32_t server_key;
-    memcached_server_instance_st *instance;
+    memcached_server_write_instance_st instance;
 
     if (is_master_key_set)
     {
@@ -370,7 +370,7 @@ static memcached_return_t simple_binary_mget(memcached_st *ptr,
     }
     else
     {
-      server_key= memcached_generate_hash(ptr, keys[x], key_length[x]);
+      server_key= memcached_generate_hash_with_redistribution(ptr, keys[x], key_length[x]);
     }
 
     instance= memcached_server_instance_fetch(ptr, server_key);
@@ -436,7 +436,7 @@ static memcached_return_t simple_binary_mget(memcached_st *ptr,
 
     for (x= 0; x < memcached_server_count(ptr); x++)
     {
-      memcached_server_instance_st *instance=
+      memcached_server_write_instance_st instance=
         memcached_server_instance_fetch(ptr, x);
 
       if (memcached_server_response_count(instance))
@@ -484,7 +484,7 @@ static memcached_return_t replication_binary_mget(memcached_st *ptr,
 
     for (x= 0; x < number_of_keys; ++x)
     {
-      memcached_server_instance_st *instance;
+      memcached_server_write_instance_st instance;
 
       if (hash[x] == memcached_server_count(ptr))
         continue; /* Already successfully sent */
@@ -598,7 +598,7 @@ static memcached_return_t binary_mget_by_key(memcached_st *ptr,
     {
       for (size_t x= 0; x < number_of_keys; x++)
       {
-        hash[x]= memcached_generate_hash(ptr, keys[x], key_length[x]);
+        hash[x]= memcached_generate_hash_with_redistribution(ptr, keys[x], key_length[x]);
       }
     }
 
index 1c11c50de2c043bd6df6301945a11f5a3977a2ce..b418d2e1188fe48c130b77e89b0c7d5f0150c457 100644 (file)
@@ -17,22 +17,12 @@ uint32_t memcached_generate_hash_value(const char *key, size_t key_length, memca
   return libhashkit_digest(key, key_length, (hashkit_hash_algorithm_t)hash_algorithm);
 }
 
-uint32_t generate_hash(memcached_st *ptr, const char *key, size_t key_length)
+static inline uint32_t generate_hash(const memcached_st *ptr, const char *key, size_t key_length)
 {
-  uint32_t hash= 1; /* Just here to remove compile warning */
-
-
-  WATCHPOINT_ASSERT(memcached_server_count(ptr));
-
-  if (memcached_server_count(ptr) == 1)
-    return 0;
-
-  hash= hashkit_digest(&ptr->hashkit, key, key_length);
-
-  return hash;
+  return hashkit_digest(&ptr->hashkit, key, key_length);
 }
 
-static uint32_t dispatch_host(memcached_st *ptr, uint32_t hash)
+static uint32_t dispatch_host(const memcached_st *ptr, uint32_t hash)
 {
   switch (ptr->distribution)
   {
@@ -73,13 +63,10 @@ static uint32_t dispatch_host(memcached_st *ptr, uint32_t hash)
 }
 
 /*
-  One day make this public, and have it return the actual memcached_server_st
-  to the calling application.
+  One version is public and will not modify the distribution hash, the other will.
 */
-uint32_t memcached_generate_hash(memcached_st *ptr, const char *key, size_t key_length)
+static inline uint32_t _generate_hash_wrapper(const memcached_st *ptr, const char *key, size_t key_length)
 {
-  uint32_t hash= 1; /* Just here to remove compile warning */
-
   WATCHPOINT_ASSERT(memcached_server_count(ptr));
 
   if (memcached_server_count(ptr) == 1)
@@ -95,14 +82,18 @@ uint32_t memcached_generate_hash(memcached_st *ptr, const char *key, size_t key_
 
     strncpy(temp, ptr->prefix_key, ptr->prefix_key_length);
     strncpy(temp + ptr->prefix_key_length, key, key_length);
-    hash= generate_hash(ptr, temp, temp_length);
+
+    return generate_hash(ptr, temp, temp_length);
   }
   else
   {
-    hash= generate_hash(ptr, key, key_length);
+    return generate_hash(ptr, key, key_length);
   }
+}
 
-  if (memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS) && ptr->next_distribution_rebuild)
+static inline void _regen_for_auto_eject(memcached_st *ptr)
+{
+  if (_is_auto_eject_host(ptr) && ptr->next_distribution_rebuild)
   {
     struct timeval now;
 
@@ -112,10 +103,27 @@ uint32_t memcached_generate_hash(memcached_st *ptr, const char *key, size_t key_
       run_distribution(ptr);
     }
   }
+}
+
+void memcached_autoeject(memcached_st *ptr)
+{
+  _regen_for_auto_eject(ptr);
+}
+
+uint32_t memcached_generate_hash_with_redistribution(memcached_st *ptr, const char *key, size_t key_length)
+{
+  uint32_t hash= _generate_hash_wrapper(ptr, key, key_length);
+
+  _regen_for_auto_eject(ptr);
 
   return dispatch_host(ptr, hash);
 }
 
+uint32_t memcached_generate_hash(const memcached_st *ptr, const char *key, size_t key_length)
+{
+  return dispatch_host(ptr, _generate_hash_wrapper(ptr, key, key_length));
+}
+
 hashkit_st *memcached_get_hashkit(memcached_st *ptr)
 {
   return &ptr->hashkit;
index 40f1f5652ee6839612369f6c44bdf4c79bd52183..5f6012295b1f5d074f0e83fca4929311a5d76728 100644 (file)
@@ -24,8 +24,13 @@ LIBMEMCACHED_API
 hashkit_st *memcached_get_hashkit(memcached_st *ptr);
 
 LIBMEMCACHED_API
-uint32_t memcached_generate_hash(memcached_st *ptr, const char *key, size_t key_length);
+uint32_t memcached_generate_hash(const memcached_st *ptr, const char *key, size_t key_length);
 
+LIBMEMCACHED_LOCAL
+uint32_t memcached_generate_hash_with_redistribution(memcached_st *ptr, const char *key, size_t key_length);
+
+LIBMEMCACHED_API
+void memcached_autoeject(memcached_st *ptr);
 
 #ifdef __cplusplus
 }
index b98a18e86398c1fc559d7abf587fb588c480bdab..0836c97e02128ddaf36c07287d66d051dc046fac 100644 (file)
@@ -22,8 +22,8 @@ static memcached_return_t update_continuum(memcached_st *ptr);
 static int compare_servers(const void *p1, const void *p2)
 {
   int return_value;
-  memcached_server_instance_st *a= (memcached_server_instance_st *)p1;
-  memcached_server_instance_st *b= (memcached_server_instance_st *)p2;
+  memcached_server_instance_st a= (memcached_server_instance_st)p1;
+  memcached_server_instance_st b= (memcached_server_instance_st)p2;
 
   return_value= strcmp(a->hostname, b->hostname);
 
@@ -39,9 +39,9 @@ static void sort_hosts(memcached_st *ptr)
 {
   if (memcached_server_count(ptr))
   {
-    memcached_server_instance_st *instance;
+    memcached_server_write_instance_st instance;
 
-    qsort(memcached_server_list(ptr), memcached_server_count(ptr), sizeof(memcached_server_instance_st), compare_servers);
+    qsort(memcached_server_list(ptr), memcached_server_count(ptr), sizeof(memcached_server_st), compare_servers);
     instance= memcached_server_instance_fetch(ptr, 0);
     instance->number_of_hosts= memcached_server_count(ptr);
   }
@@ -106,7 +106,7 @@ static memcached_return_t update_continuum(memcached_st *ptr)
   uint32_t host_index;
   uint32_t continuum_index= 0;
   uint32_t value;
-  memcached_server_instance_st *list;
+  memcached_server_st *list;
   uint32_t pointer_index;
   uint32_t pointer_counter= 0;
   uint32_t pointer_per_server= MEMCACHED_POINTS_PER_SERVER;
@@ -127,7 +127,7 @@ static memcached_return_t update_continuum(memcached_st *ptr)
   list = memcached_server_list(ptr);
 
   /* count live servers (those without a retry delay set) */
-  is_auto_ejecting= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS);
+  is_auto_ejecting= _is_auto_eject_host(ptr);
   if (is_auto_ejecting)
   {
     live_servers= 0;
@@ -176,12 +176,12 @@ static memcached_return_t update_continuum(memcached_st *ptr)
       {
         list[host_index].weight = 1;
       }
-      if (!is_auto_ejecting || list[host_index].next_retry <= now.tv_sec)
+      if (! is_auto_ejecting || list[host_index].next_retry <= now.tv_sec)
         total_weight += list[host_index].weight;
     }
   }
 
-  for (host_index = 0; host_index < memcached_server_count(ptr); ++host_index)
+  for (host_index= 0; host_index < memcached_server_count(ptr); ++host_index)
   {
     if (is_auto_ejecting && list[host_index].next_retry > now.tv_sec)
       continue;
@@ -305,7 +305,7 @@ static memcached_return_t update_continuum(memcached_st *ptr)
 }
 
 
-memcached_return_t memcached_server_push(memcached_st *ptr, memcached_server_st *list)
+memcached_return_t memcached_server_push(memcached_st *ptr, const memcached_server_list_st list)
 {
   uint32_t count;
   memcached_server_st *new_host_list;
@@ -313,9 +313,9 @@ memcached_return_t memcached_server_push(memcached_st *ptr, memcached_server_st
   if (! list)
     return MEMCACHED_SUCCESS;
 
-  count= memcached_servers_count(list);
+  count= memcached_server_list_count(list);
   new_host_list= libmemcached_realloc(ptr, memcached_server_list(ptr),
-                                      sizeof(memcached_server_instance_st) * (count + memcached_server_count(ptr)));
+                                      sizeof(memcached_server_st) * (count + memcached_server_count(ptr)));
 
   if (! new_host_list)
     return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
@@ -324,7 +324,7 @@ memcached_return_t memcached_server_push(memcached_st *ptr, memcached_server_st
 
   for (uint32_t x= 0; x < count; x++)
   {
-    memcached_server_instance_st *instance;
+    memcached_server_write_instance_st instance;
 
     if ((ptr->flags.use_udp && list[x].type != MEMCACHED_CONNECTION_UDP)
             || ((list[x].type == MEMCACHED_CONNECTION_UDP)
@@ -343,7 +343,7 @@ memcached_return_t memcached_server_push(memcached_st *ptr, memcached_server_st
 
   // Provides backwards compatibility with server list.
   {
-    memcached_server_instance_st *instance;
+    memcached_server_write_instance_st instance;
     instance= memcached_server_instance_fetch(ptr, 0);
     instance->number_of_hosts= memcached_server_count(ptr);
   }
@@ -414,15 +414,15 @@ static memcached_return_t server_add(memcached_st *ptr, const char *hostname,
                                      uint32_t weight,
                                      memcached_connection_t type)
 {
-  memcached_server_instance_st *new_host_list;
-  memcached_server_instance_st *instance;
+  memcached_server_st *new_host_list;
+  memcached_server_write_instance_st instance;
 
   if ( (ptr->flags.use_udp && type != MEMCACHED_CONNECTION_UDP)
       || ( (type == MEMCACHED_CONNECTION_UDP) && (! ptr->flags.use_udp) ) )
     return MEMCACHED_INVALID_HOST_PROTOCOL;
 
   new_host_list= libmemcached_realloc(ptr, memcached_server_list(ptr),
-                                      sizeof(memcached_server_instance_st) * (ptr->number_of_hosts + 1));
+                                      sizeof(memcached_server_st) * (ptr->number_of_hosts + 1));
 
   if (new_host_list == NULL)
     return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
index 6dc3d705c0e4c10705a6929b4f18b84cb81aad45..737c5e12e5c312d4c7b17c84e0fbf5dc96c09d84 100644 (file)
@@ -45,6 +45,7 @@ nobase_include_HEADERS+= \
                         libmemcached/quit.h \
                         libmemcached/result.h \
                         libmemcached/server.h \
+                        libmemcached/server_list.h \
                         libmemcached/stats.h \
                         libmemcached/storage.h \
                         libmemcached/strerror.h \
index ef46a0d9e460b93f819e8c70d368ce3c2c107b72..f1afc6695322fe961edc7a9dbd2c41a402def199 100644 (file)
@@ -19,10 +19,11 @@ typedef enum {
   MEM_WRITE
 } memc_read_or_write;
 
-static ssize_t io_flush(memcached_server_instance_st *ptr, memcached_return_t *error);
-static void increment_udp_message_id(memcached_server_instance_st *ptr);
+static ssize_t io_flush(memcached_server_write_instance_st ptr,
+                        memcached_return_t *error);
+static void increment_udp_message_id(memcached_server_write_instance_st ptr);
 
-static memcached_return_t io_wait(memcached_server_instance_st *ptr,
+static memcached_return_t io_wait(memcached_server_write_instance_st ptr,
                                   memc_read_or_write read_or_write)
 {
   struct pollfd fds= {
@@ -91,7 +92,7 @@ static memcached_return_t io_wait(memcached_server_instance_st *ptr,
  *
  * @param ptr the server to pack
  */
-static bool repack_input_buffer(memcached_server_instance_st *ptr)
+static bool repack_input_buffer(memcached_server_write_instance_st ptr)
 {
   if (ptr->read_ptr != ptr->read_buffer)
   {
@@ -131,7 +132,7 @@ static bool repack_input_buffer(memcached_server_instance_st *ptr)
  * @param ptr the server to star processing iput messages for
  * @return true if we processed anything, false otherwise
  */
-static bool process_input_buffer(memcached_server_instance_st *ptr)
+static bool process_input_buffer(memcached_server_write_instance_st ptr)
 {
   /*
    ** We might be able to process some of the response messages if we
@@ -234,7 +235,7 @@ void memcached_io_preread(memcached_st *ptr)
 }
 #endif
 
-memcached_return_t memcached_io_read(memcached_server_instance_st *ptr,
+memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr,
                                      void *buffer, size_t length, ssize_t *nread)
 {
   char *buffer_ptr;
@@ -325,7 +326,7 @@ memcached_return_t memcached_io_read(memcached_server_instance_st *ptr,
   return MEMCACHED_SUCCESS;
 }
 
-ssize_t memcached_io_write(memcached_server_instance_st *ptr,
+ssize_t memcached_io_write(memcached_server_write_instance_st ptr,
                            const void *buffer, size_t length, bool with_flush)
 {
   size_t original_length;
@@ -402,7 +403,7 @@ ssize_t memcached_io_write(memcached_server_instance_st *ptr,
   return (ssize_t) original_length;
 }
 
-memcached_return_t memcached_io_close(memcached_server_instance_st *ptr)
+memcached_return_t memcached_io_close(memcached_server_write_instance_st ptr)
 {
   if (ptr->fd == -1)
   {
@@ -425,7 +426,7 @@ memcached_return_t memcached_io_close(memcached_server_instance_st *ptr)
   return MEMCACHED_SUCCESS;
 }
 
-memcached_server_instance_st *memcached_io_get_readable_server(memcached_st *memc)
+memcached_server_write_instance_st memcached_io_get_readable_server(memcached_st *memc)
 {
 #define MAX_SERVERS_TO_POLL 100
   struct pollfd fds[MAX_SERVERS_TO_POLL];
@@ -435,7 +436,7 @@ memcached_server_instance_st *memcached_io_get_readable_server(memcached_st *mem
        x< memcached_server_count(memc) && host_index < MAX_SERVERS_TO_POLL;
        ++x)
   {
-    memcached_server_instance_st *instance=
+    memcached_server_write_instance_st instance=
       memcached_server_instance_fetch(memc, x);
 
     if (instance->read_buffer_length > 0) /* I have data in the buffer */
@@ -455,7 +456,7 @@ memcached_server_instance_st *memcached_io_get_readable_server(memcached_st *mem
     /* We have 0 or 1 server with pending events.. */
     for (uint32_t x= 0; x< memcached_server_count(memc); ++x)
     {
-      memcached_server_instance_st *instance=
+      memcached_server_write_instance_st instance=
         memcached_server_instance_fetch(memc, x);
 
       if (memcached_server_response_count(instance) > 0)
@@ -481,7 +482,7 @@ memcached_server_instance_st *memcached_io_get_readable_server(memcached_st *mem
       {
         for (uint32_t y= 0; y < memcached_server_count(memc); ++y)
         {
-          memcached_server_instance_st *instance=
+          memcached_server_write_instance_st instance=
             memcached_server_instance_fetch(memc, y);
 
           if (instance->fd == fds[x].fd)
@@ -494,7 +495,7 @@ memcached_server_instance_st *memcached_io_get_readable_server(memcached_st *mem
   return NULL;
 }
 
-static ssize_t io_flush(memcached_server_instance_st *ptr,
+static ssize_t io_flush(memcached_server_write_instance_st ptr,
                         memcached_return_t *error)
 {
   /*
@@ -610,7 +611,7 @@ static ssize_t io_flush(memcached_server_instance_st *ptr,
 /*
   Eventually we will just kill off the server with the problem.
 */
-void memcached_io_reset(memcached_server_instance_st *ptr)
+void memcached_io_reset(memcached_server_write_instance_st ptr)
 {
   memcached_quit_server(ptr, true);
 }
@@ -619,7 +620,7 @@ void memcached_io_reset(memcached_server_instance_st *ptr)
  * Read a given number of bytes from the server and place it into a specific
  * buffer. Reset the IO channel on this server if an error occurs.
  */
-memcached_return_t memcached_safe_read(memcached_server_instance_st *ptr,
+memcached_return_t memcached_safe_read(memcached_server_write_instance_st ptr,
                                        void *dta,
                                        size_t size)
 {
@@ -640,7 +641,7 @@ memcached_return_t memcached_safe_read(memcached_server_instance_st *ptr,
   return MEMCACHED_SUCCESS;
 }
 
-memcached_return_t memcached_io_readline(memcached_server_instance_st *ptr,
+memcached_return_t memcached_io_readline(memcached_server_write_instance_st ptr,
                                          char *buffer_ptr,
                                          size_t size)
 {
@@ -698,7 +699,7 @@ memcached_return_t memcached_io_readline(memcached_server_instance_st *ptr,
  * extracts the message number from message_id, increments it and then
  * writes the new value back into the header
  */
-static void increment_udp_message_id(memcached_server_instance_st *ptr)
+static void increment_udp_message_id(memcached_server_write_instance_st ptr)
 {
   struct udp_datagram_header_st *header= (struct udp_datagram_header_st *)ptr->write_buffer;
   uint16_t cur_req= get_udp_datagram_request_id(header);
@@ -711,7 +712,7 @@ static void increment_udp_message_id(memcached_server_instance_st *ptr)
   header->request_id= htons((uint16_t) (thread_id | msg_num));
 }
 
-memcached_return_t memcached_io_init_udp_header(memcached_server_instance_st *ptr, uint16_t thread_id)
+memcached_return_t memcached_io_init_udp_header(memcached_server_write_instance_st ptr, uint16_t thread_id)
 {
   if (thread_id > UDP_REQUEST_ID_MAX_THREAD_ID)
     return MEMCACHED_FAILURE;
index ca22c27d34c5018cce604e6d5e7c5235765a1d17..dc6a672f7a896b5c563088cdc2331930f808c9e4 100644 (file)
@@ -41,37 +41,37 @@ struct udp_datagram_header_st
 };
 
 LIBMEMCACHED_LOCAL
-ssize_t memcached_io_write(memcached_server_instance_st *ptr,
+ssize_t memcached_io_write(memcached_server_write_instance_st ptr,
                            const void *buffer, size_t length, bool with_flush);
 
 LIBMEMCACHED_LOCAL
-void memcached_io_reset(memcached_server_instance_st *ptr);
+void memcached_io_reset(memcached_server_write_instance_st ptr);
 
 LIBMEMCACHED_LOCAL
-memcached_return_t memcached_io_read(memcached_server_instance_st *ptr,
+memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr,
                                      void *buffer, size_t length, ssize_t *nread);
 
 /* Read a line (terminated by '\n') into the buffer */
 LIBMEMCACHED_LOCAL
-memcached_return_t memcached_io_readline(memcached_server_instance_st *ptr,
+memcached_return_t memcached_io_readline(memcached_server_write_instance_st ptr,
                                          char *buffer_ptr,
                                          size_t size);
 
 LIBMEMCACHED_LOCAL
-memcached_return_t memcached_io_close(memcached_server_instance_st *ptr);
+memcached_return_t memcached_io_close(memcached_server_write_instance_st ptr);
 
 /* Read n bytes of data from the server and store them in dta */
 LIBMEMCACHED_LOCAL
-memcached_return_t memcached_safe_read(memcached_server_instance_st *ptr,
+memcached_return_t memcached_safe_read(memcached_server_write_instance_st ptr,
                                        void *dta,
                                        size_t size);
 
 LIBMEMCACHED_LOCAL
-memcached_return_t memcached_io_init_udp_header(memcached_server_instance_st *ptr,
+memcached_return_t memcached_io_init_udp_header(memcached_server_write_instance_st ptr,
                                                 uint16_t thread_id);
 
 LIBMEMCACHED_LOCAL
-memcached_server_instance_st *memcached_io_get_readable_server(memcached_st *memc);
+memcached_server_write_instance_st memcached_io_get_readable_server(memcached_st *memc);
 
 #ifdef __cplusplus
 }
index c0fee34d0e6520405e678bdaa9b2e44114e383db..4e0308a043df72b29bdc43800a475d04942c73d7 100644 (file)
@@ -132,35 +132,9 @@ memcached_st *memcached_create(memcached_st *ptr)
   return ptr;
 }
 
-void server_list_free(memcached_st *ptr, memcached_server_st *servers)
-{
-  uint32_t x;
-
-  if (servers == NULL)
-    return;
-
-  for (x= 0; x < memcached_servers_count(servers); x++)
-  {
-    if (servers[x].address_info)
-    {
-      freeaddrinfo(servers[x].address_info);
-      servers[x].address_info= NULL;
-    }
-  }
-
-  if (ptr)
-  {
-    libmemcached_free(ptr, servers);
-  }
-  else
-  {
-    free(servers);
-  }
-}
-
 void memcached_servers_reset(memcached_st *ptr)
 {
-  server_list_free(ptr, memcached_server_list(ptr));
+  memcached_server_list_free(memcached_server_list(ptr));
 
   memcached_server_list_set(ptr, NULL);
   ptr->number_of_hosts= 0;
@@ -172,7 +146,7 @@ void memcached_free(memcached_st *ptr)
 {
   /* If we have anything open, lets close it now */
   memcached_quit(ptr);
-  server_list_free(ptr, memcached_server_list(ptr));
+  memcached_server_list_free(memcached_server_list(ptr));
   memcached_result_free(&ptr->result);
 
   if (ptr->on_cleanup)
@@ -252,8 +226,8 @@ memcached_st *memcached_clone(memcached_st *clone, const memcached_st *source)
   new_clone->io_key_prefetch= source->io_key_prefetch;
   new_clone->number_of_replicas= source->number_of_replicas;
 
-  if (memcached_server_list(source))
-    rc= memcached_server_push(new_clone, memcached_server_list(source));
+  if (memcached_server_count(source))
+    rc= memcached_push(new_clone, source);
 
   if (rc != MEMCACHED_SUCCESS)
   {
@@ -296,3 +270,18 @@ void *memcached_set_user_data(memcached_st *ptr, void *data)
 
   return ret;
 }
+
+memcached_return_t memcached_push(memcached_st *destination, const memcached_st *source)
+{
+  return memcached_server_push(destination, source->servers);
+}
+
+inline memcached_server_write_instance_st memcached_server_instance_fetch(memcached_st *ptr, uint32_t server_key)
+{
+  return &ptr->servers[server_key];
+}
+
+inline memcached_server_instance_st memcached_server_instance_by_position(const memcached_st *ptr, uint32_t server_key)
+{
+  return &ptr->servers[server_key];
+}
index 9415f4321eb84d946cc27bc108a2122fde93e56e..30823a8733d3d96cc12cfc666c74d2c61af14ef4 100644 (file)
@@ -48,6 +48,7 @@
 #include <libmemcached/quit.h>
 #include <libmemcached/result.h>
 #include <libmemcached/server.h>
+#include <libmemcached/server_list.h>
 #include <libmemcached/storage.h>
 #include <libmemcached/strerror.h>
 #include <libmemcached/verbosity.h>
@@ -149,17 +150,20 @@ void *memcached_get_user_data(const memcached_st *ptr);
 LIBMEMCACHED_API
 void *memcached_set_user_data(memcached_st *ptr, void *data);
 
+LIBMEMCACHED_API
+memcached_return_t memcached_push(memcached_st *destination, const memcached_st *source);
+
+LIBMEMCACHED_API
+memcached_server_instance_st memcached_server_instance_by_position(const memcached_st *ptr, uint32_t server_key);
+
+LIBMEMCACHED_API
+uint32_t memcached_server_count(const memcached_st *);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
 
 
-// Local Only Inline
-static inline memcached_server_st *memcached_server_instance_fetch(memcached_st *ptr, uint32_t server_key)
-{
-  return &ptr->servers[server_key];
-}
-
 #ifdef __cplusplus
 class Memcached : private memcached_st {
 public:
index 17c306e9a2a467ddecf6bca4140bb8839b97d6ad..a83902622495994ed6beab230309023cd9678a2f 100644 (file)
@@ -40,7 +40,6 @@ public:
     :
       servers_list(),
       memc(),
-      servers(NULL),
       result()
   {
     memcached_create(&memc);
@@ -50,12 +49,10 @@ public:
     :
       servers_list(in_servers_list),
       memc(),
-      servers(NULL),
       result()
   {
     memcached_create(&memc);
-    servers= memcached_servers_parse(servers_list.c_str());
-    memcached_server_push(&memc, servers);
+    init();
   }
 
   Memcache(const std::string &hostname,
@@ -63,24 +60,23 @@ public:
     :
       servers_list(),
       memc(),
-      servers(NULL),
       result()
   {
     memcached_create(&memc);
+
     servers_list.append(hostname);
     servers_list.append(":");
     std::ostringstream strsmt;
     strsmt << port;
     servers_list.append(strsmt.str());
-    servers= memcached_servers_parse(servers_list.c_str());
-    memcached_server_push(&memc, servers);
+
+    init();
   }
 
   Memcache(memcached_st *clone)
     :
       servers_list(),
       memc(),
-      servers(NULL),
       result()
   {
     memcached_clone(&memc, clone);
@@ -90,12 +86,10 @@ public:
     :
       servers_list(rhs.servers_list),
       memc(),
-      servers(NULL),
       result()
   {
     memcached_clone(&memc, const_cast<memcached_st *>(&rhs.getImpl()));
-    servers= memcached_servers_parse(servers_list.c_str());
-    memcached_server_push(&memc, servers);
+    init();
   }
 
   Memcache &operator=(const Memcache &rhs)
@@ -103,16 +97,23 @@ public:
     if (this != &rhs)
     {
       memcached_clone(&memc, const_cast<memcached_st *>(&rhs.getImpl()));
-      servers= memcached_servers_parse(servers_list.c_str());
-      memcached_server_push(&memc, servers);
+      init();
     }
+
     return *this;
   }
 
   ~Memcache()
   {
     memcached_free(&memc);
-    memcached_server_list_free(servers);
+  }
+
+  void init()
+  {
+    memcached_server_st *servers;
+    servers= memcached_servers_parse(servers_list.c_str());
+    memcached_server_push(&memc, servers);
+    memcached_server_free(servers);
   }
 
   /**
@@ -175,9 +176,9 @@ public:
   bool setServers(const std::string &in_servers_list)
   {
     servers_list.assign(in_servers_list);
-    servers= memcached_servers_parse(in_servers_list.c_str());
-    memcached_server_push(&memc, servers);
-    return (servers == NULL);
+    init();
+
+    return (memcached_server_count(&memc));
   }
 
   /**
@@ -190,17 +191,9 @@ public:
   bool addServer(const std::string &server_name, in_port_t port)
   {
     memcached_return_t rc;
-    std::ostringstream strstm;
-    servers_list.append(",");
-    servers_list.append(server_name);
-    servers_list.append(":");
-    strstm << port;
-    servers_list.append(strstm.str());
-    servers= memcached_server_list_append(servers,
-                                          server_name.c_str(),
-                                          port,
-                                          &rc);
-    memcached_server_push(&memc, servers);
+
+    rc= memcached_server_add(&memc, server_name.c_str(), port);
+
     return (rc == MEMCACHED_SUCCESS);
   }
 
@@ -220,11 +213,10 @@ public:
     tmp_str.append(":");
     strstm << port;
     tmp_str.append(strstm.str());
-    memcached_server_st *server= memcached_servers_parse(tmp_str.c_str());
 
-    memcached_return_t rc= memcached_server_remove(server);
-
-    return (rc == MEMCACHED_SUCCESS);
+    //memcached_return_t rc= memcached_server_remove(server);
+    
+    return false;
   }
 
   /**
@@ -967,10 +959,12 @@ public:
      */
     for (uint32_t x= 0; x < server_count; x++)
     {
+      memcached_server_instance_st instance=
+        memcached_server_instance_by_position(&memc, x);
       std::ostringstream strstm;
-      std::string server_name(memcached_server_name(&memc, servers[x]));
+      std::string server_name(memcached_server_name(instance));
       server_name.append(":");
-      strstm << memcached_server_port(&memc, servers[x]);
+      strstm << memcached_server_port(instance);
       server_name.append(strstm.str());
 
       std::map<std::string, std::string> server_stats;
@@ -997,7 +991,6 @@ private:
 
   std::string servers_list;
   memcached_st memc;
-  memcached_server_st *servers;
   memcached_result_st result;
 };
 
index 6675b1a3c2a54bfe44ec74d3769ddd0e40dce6c7..917c5e3097b9874bfc0658c7bd199a4ed3ed3444 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "common.h"
 
-memcached_server_st *memcached_servers_parse(const char *server_strings)
+memcached_server_list_st memcached_servers_parse(const char *server_strings)
 {
   char *string;
   in_port_t port;
index 9409d454ba1f7dc84bd350923709249c5030857d..45a5d746946eb95d9409893bb3eb2c7dff3b09f8 100644 (file)
@@ -17,7 +17,7 @@ extern "C" {
 #endif
 
 LIBMEMCACHED_API
-memcached_server_st *memcached_servers_parse(const char *server_strings);
+memcached_server_list_st memcached_servers_parse(const char *server_strings);
 
 #ifdef __cplusplus
 }
index bee5c921e0b7020930719a8ff6d107e699d143cb..07cd135f56c939281ae786bdd32372ea97e4b985 100644 (file)
@@ -1,6 +1,6 @@
 #include "common.h"
 
-memcached_return_t memcached_purge(memcached_server_instance_st *ptr)
+memcached_return_t memcached_purge(memcached_server_write_instance_st ptr)
 {
   uint32_t x;
   memcached_return_t ret= MEMCACHED_SUCCESS;
index 292bc6e43442f6158287b1e54c7a3a6fa38ae96d..35d434bc6b7886a4634edbec083f5872699278d7 100644 (file)
@@ -81,7 +81,7 @@ void memcached_quit(memcached_st *ptr)
   {
     for (x= 0; x < memcached_server_count(ptr); x++)
     {
-      memcached_server_instance_st *instance=
+      memcached_server_write_instance_st instance=
         memcached_server_instance_fetch(ptr, x);
 
       memcached_quit_server(instance, false);
index 453adeaa969126e67bedf045d29f499490122dff..e252a1ea10b24396090ad082fbfda3449db68c92 100644 (file)
@@ -19,6 +19,9 @@ extern "C" {
 LIBMEMCACHED_API
 void memcached_quit(memcached_st *ptr);
 
+LIBMEMCACHED_LOCAL
+void memcached_quit_server(memcached_server_st *ptr, bool io_death);
+
 #ifdef __cplusplus
 }
 #endif
index abd92e4e6a50edb27e83421727c11476b990022b..c14dd1ff6688c6678922c5d4356c77e02bbe6e17 100644 (file)
 
 #include "common.h"
 
-static memcached_return_t textual_read_one_response(memcached_server_instance_st *ptr,
+static memcached_return_t textual_read_one_response(memcached_server_write_instance_st ptr,
                                                     char *buffer, size_t buffer_length,
                                                     memcached_result_st *result);
-static memcached_return_t binary_read_one_response(memcached_server_instance_st *ptr,
+static memcached_return_t binary_read_one_response(memcached_server_write_instance_st ptr,
                                                    char *buffer, size_t buffer_length,
                                                    memcached_result_st *result);
 
-memcached_return_t memcached_read_one_response(memcached_server_instance_st *ptr,
+memcached_return_t memcached_read_one_response(memcached_server_write_instance_st ptr,
                                                char *buffer, size_t buffer_length,
                                                memcached_result_st *result)
 {
@@ -45,7 +45,7 @@ memcached_return_t memcached_read_one_response(memcached_server_instance_st *ptr
   return rc;
 }
 
-memcached_return_t memcached_response(memcached_server_instance_st *ptr, 
+memcached_return_t memcached_response(memcached_server_write_instance_st ptr, 
                                       char *buffer, size_t buffer_length,
                                       memcached_result_st *result)
 {
@@ -79,7 +79,7 @@ memcached_return_t memcached_response(memcached_server_instance_st *ptr,
   return memcached_read_one_response(ptr, buffer, buffer_length, result);
 }
 
-static memcached_return_t textual_value_fetch(memcached_server_instance_st *ptr,
+static memcached_return_t textual_value_fetch(memcached_server_write_instance_st ptr,
                                               char *buffer,
                                               memcached_result_st *result)
 {
@@ -210,7 +210,7 @@ read_error:
   return MEMCACHED_PARTIAL_READ;
 }
 
-static memcached_return_t textual_read_one_response(memcached_server_instance_st *ptr,
+static memcached_return_t textual_read_one_response(memcached_server_write_instance_st ptr,
                                                     char *buffer, size_t buffer_length,
                                                     memcached_result_st *result)
 {
@@ -327,7 +327,7 @@ static memcached_return_t textual_read_one_response(memcached_server_instance_st
   /* NOTREACHED */
 }
 
-static memcached_return_t binary_read_one_response(memcached_server_instance_st *ptr,
+static memcached_return_t binary_read_one_response(memcached_server_write_instance_st ptr,
                                                    char *buffer, size_t buffer_length,
                                                    memcached_result_st *result)
 {
index 6599b8a7e945c71b144dc9bd6c7b92acb6030377..da6f2b4274cc345757c132ea510ce0185dfe7879 100644 (file)
@@ -18,12 +18,12 @@ extern "C" {
 
 /* Read a single response from the server */
 LIBMEMCACHED_LOCAL
-memcached_return_t memcached_read_one_response(memcached_server_instance_st *ptr,
+memcached_return_t memcached_read_one_response(memcached_server_write_instance_st ptr,
                                                char *buffer, size_t buffer_length,
                                                memcached_result_st *result);
 
 LIBMEMCACHED_LOCAL
-memcached_return_t memcached_response(memcached_server_instance_st *ptr,
+memcached_return_t memcached_response(memcached_server_write_instance_st ptr,
                                       char *buffer, size_t buffer_length,
                                       memcached_result_st *result);
 
index 037293e7f79af0c4a7471dcc5aca110996fd4098..06e3ba9e75d472b526982f926515b953f13de69e 100644 (file)
@@ -94,3 +94,45 @@ memcached_return_t memcached_result_set_value(memcached_result_st *ptr,
 {
   return memcached_string_append(&ptr->value, value, length);
 }
+
+inline const char *memcached_result_key_value(const memcached_result_st *self)
+{
+  return self->key_length ? self->item_key : NULL;
+}
+
+inline size_t memcached_result_key_length(const memcached_result_st *self)
+{
+  return self->key_length;
+}
+
+inline const char *memcached_result_value(const memcached_result_st *self)
+{
+  const memcached_string_st *sptr= &self->value;
+  return memcached_string_value(sptr);
+}
+
+inline size_t memcached_result_length(const memcached_result_st *self)
+{
+  const memcached_string_st *sptr= &self->value;
+  return memcached_string_length(sptr);
+}
+
+inline uint32_t memcached_result_flags(const memcached_result_st *self)
+{
+  return self->item_flags;
+}
+
+inline uint64_t memcached_result_cas(const memcached_result_st *self)
+{
+  return self->item_cas;
+}
+
+inline void memcached_result_set_flags(memcached_result_st *self, uint32_t flags)
+{
+  self->item_flags= flags;
+}
+
+inline void memcached_result_set_expiration(memcached_result_st *self, time_t expiration)
+{
+  self->item_expiration= expiration;
+}
index a7fe00b48a5666272cce1e782a3fdab27c6dddf6..59ce9b91b1baba26a8cf096786781b0b945f3078 100644 (file)
@@ -42,50 +42,32 @@ LIBMEMCACHED_API
 memcached_result_st *memcached_result_create(const memcached_st *ptr,
                                              memcached_result_st *result);
 
-static inline const char *memcached_result_key_value(const memcached_result_st *self)
-{
-  return self->key_length ? self->item_key : NULL;
-}
-
-static inline size_t memcached_result_key_length(const memcached_result_st *self)
-{
-  return self->key_length;
-}
-
-static inline const char *memcached_result_value(const memcached_result_st *self)
-{
-  const memcached_string_st *sptr= &self->value;
-  return memcached_string_value(sptr);
-}
-
-static inline size_t memcached_result_length(const memcached_result_st *self)
-{
-  const memcached_string_st *sptr= &self->value;
-  return memcached_string_length(sptr);
-}
-
-static inline uint32_t memcached_result_flags(const memcached_result_st *self)
-{
-  return self->item_flags;
-}
-
-static inline uint64_t memcached_result_cas(const memcached_result_st *self)
-{
-  return self->item_cas;
-}
+LIBMEMCACHED_API
+const char *memcached_result_key_value(const memcached_result_st *self);
+
+LIBMEMCACHED_API
+size_t memcached_result_key_length(const memcached_result_st *self);
+
+LIBMEMCACHED_API
+const char *memcached_result_value(const memcached_result_st *self);
+
+LIBMEMCACHED_API
+size_t memcached_result_length(const memcached_result_st *self);
+
+LIBMEMCACHED_API
+uint32_t memcached_result_flags(const memcached_result_st *self);
+
+LIBMEMCACHED_API
+uint64_t memcached_result_cas(const memcached_result_st *self);
 
 LIBMEMCACHED_API
 memcached_return_t memcached_result_set_value(memcached_result_st *ptr, const char *value, size_t length);
 
-static inline void memcached_result_set_flags(memcached_result_st *self, uint32_t flags)
-{
-  self->item_flags= flags;
-}
+LIBMEMCACHED_API
+void memcached_result_set_flags(memcached_result_st *self, uint32_t flags);
 
-static inline void memcached_result_set_expiration(memcached_result_st *self, time_t expiration)
-{
-  self->item_expiration= expiration;
-}
+LIBMEMCACHED_API
+void memcached_result_set_expiration(memcached_result_st *self, time_t expiration);
 
 #ifdef __cplusplus
 } // extern "C"
index f480750d8679079c5003ce4448c834777da91c6d..f46c75bc785e3d0de7182d4957a04c9fb35ab574 100644 (file)
@@ -78,7 +78,8 @@ static memcached_server_st *_server_create(memcached_server_st *self, const memc
   return self;
 }
 
-memcached_server_st *memcached_server_create_with(const memcached_st *memc, memcached_server_st *self,
+memcached_server_st *memcached_server_create_with(const memcached_st *memc,
+                                                  memcached_server_write_instance_st self,
                                                   const char *hostname, in_port_t port,
                                                   uint32_t weight, memcached_connection_t type)
 {
@@ -144,24 +145,21 @@ memcached_server_st *memcached_server_clone(memcached_server_st *destination,
 
 }
 
-memcached_return_t memcached_server_cursor(memcached_st *ptr,
-                                           memcached_server_fn *callback,
+memcached_return_t memcached_server_cursor(const memcached_st *ptr,
+                                           const memcached_server_fn *callback,
                                            void *context,
                                            uint32_t number_of_callbacks)
 {
-  uint32_t y;
-
-  for (y= 0; y < memcached_server_count(ptr); y++)
+  for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
   {
-    uint32_t x;
-    memcached_server_instance_st *instance=
-      memcached_server_instance_fetch(ptr, y);
+    memcached_server_instance_st instance=
+      memcached_server_instance_by_position(ptr, x);
 
-    for (x= 0; x < number_of_callbacks; x++)
+    for (uint32_t y= 0; y < number_of_callbacks; y++)
     {
       unsigned int iferror;
 
-      iferror= (*callback[x])(ptr, instance, context);
+      iferror= (*callback[y])(ptr, instance, context);
 
       if (iferror)
         continue;
@@ -171,10 +169,13 @@ memcached_return_t memcached_server_cursor(memcached_st *ptr,
   return MEMCACHED_SUCCESS;
 }
 
-memcached_server_st *memcached_server_by_key(memcached_st *ptr,  const char *key, size_t key_length, memcached_return_t *error)
+memcached_server_instance_st memcached_server_by_key(const memcached_st *ptr,
+                                                     const char *key,
+                                                     size_t key_length,
+                                                     memcached_return_t *error)
 {
   uint32_t server_key;
-  memcached_server_instance_st *instance;
+  memcached_server_instance_st instance;
 
   *error= memcached_validate_key_length(key_length,
                                         ptr->flags.binary_protocol);
@@ -194,17 +195,10 @@ memcached_server_st *memcached_server_by_key(memcached_st *ptr,  const char *key
   }
 
   server_key= memcached_generate_hash(ptr, key, key_length);
-  instance= memcached_server_instance_fetch(ptr, server_key);
-
-  return memcached_server_clone(NULL, instance);
+  instance= memcached_server_instance_by_position(ptr, server_key);
 
-}
+  return instance;
 
-const char *memcached_server_error(memcached_server_st *ptr)
-{
-  return ptr 
-    ?  ptr->cached_server_error
-    : NULL;
 }
 
 void memcached_server_error_reset(memcached_server_st *ptr)
@@ -212,54 +206,66 @@ 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)
+memcached_server_instance_st memcached_server_get_last_disconnect(const memcached_st *ptr)
 {
   return ptr->last_disconnected_server;
 }
 
-uint32_t memcached_server_list_count(memcached_server_st *ptr)
-{
-  return (ptr == NULL)
-    ? 0
-    : memcached_servers_count(ptr);
-}
-
-void memcached_server_list_free(memcached_server_st *ptr)
-{
-  server_list_free(NULL, ptr);
-}
-
-/**
-  @todo allow lists to query themselves even if they lack a root
-*/
-memcached_return_t memcached_server_remove(memcached_server_st *st_ptr)
+void memcached_server_list_free(memcached_server_list_st self)
 {
-  uint32_t x, host_index;
-  memcached_st *root= (memcached_st *)st_ptr->root;
-  memcached_server_st *list;
-
-  if (root == NULL)
-    return MEMCACHED_FAILURE;
+  if (self == NULL)
+    return;
 
-  list= memcached_server_list(root);
+  const memcached_st *root= self->root;
 
-  for (x= 0, host_index= 0; x < memcached_server_count(root); x++)
+  for (uint32_t x= 0; x < memcached_server_list_count(self); x++)
   {
-    if (strncmp(list[x].hostname, st_ptr->hostname, NI_MAXHOST) != 0 || list[x].port != st_ptr->port)
+    if (self[x].address_info)
     {
-      if (host_index != x)
-        memcpy(list+host_index, list+x, sizeof(memcached_server_st));
-      host_index++;
+      freeaddrinfo(self[x].address_info);
+      self[x].address_info= NULL;
     }
   }
-  root->number_of_hosts= host_index;
 
-  if (st_ptr->address_info)
+  if (root)
   {
-    freeaddrinfo(st_ptr->address_info);
-    st_ptr->address_info= NULL;
+    libmemcached_free(root, self);
   }
-  run_distribution(root);
+  else
+  {
+    free(self);
+  }
+}
 
-  return MEMCACHED_SUCCESS;
+inline uint32_t memcached_servers_set_count(memcached_server_st *servers, uint32_t count)
+{
+  return servers->number_of_hosts= count;
+}
+
+inline uint32_t memcached_server_count(const memcached_st *self)
+{
+  return self->number_of_hosts;
+}
+
+inline const char *memcached_server_name(memcached_server_instance_st self)
+{
+  return self->hostname;
+}
+
+inline in_port_t memcached_server_port(memcached_server_instance_st self)
+{
+  return self->port;
+}
+
+inline uint32_t memcached_server_response_count(memcached_server_instance_st self)
+{
+  return self->cursor_active;
+}
+
+const char *memcached_server_error(memcached_server_instance_st ptr)
+{
+  return ptr
+    ?  ptr->cached_server_error
+    : NULL;
 }
+
index 5174752822c63ee8327eebbb2fbd461c69fd21da..44a32bba46c0627329994e17dbabad9fb08c414d 100644 (file)
@@ -55,35 +55,20 @@ extern "C" {
 #endif
 
 LIBMEMCACHED_API
-memcached_return_t memcached_server_cursor(memcached_st *ptr,
-                                           memcached_server_fn *callback,
+memcached_return_t memcached_server_cursor(const memcached_st *ptr,
+                                           const memcached_server_fn *callback,
                                            void *context,
                                            uint32_t number_of_callbacks);
 
 LIBMEMCACHED_API
-memcached_server_st *memcached_server_by_key(memcached_st *ptr,
-                                             const char *key,
-                                             size_t key_length,
-                                             memcached_return_t *error);
-
-LIBMEMCACHED_API
-const char *memcached_server_error(memcached_server_st *ptr);
+  memcached_server_instance_st memcached_server_by_key(const memcached_st *ptr,
+                                                        const char *key,
+                                                        size_t key_length,
+                                                        memcached_return_t *error);
 
 LIBMEMCACHED_API
 void memcached_server_error_reset(memcached_server_st *ptr);
 
-/* These should not currently be used by end users */
-/* TODO: Is the above comment valid? If so, how can we unit test these if they
- * aren't exported. If not, we should remove the comment */
-
-LIBMEMCACHED_LOCAL
-memcached_server_st *memcached_server_create_with(const memcached_st *memc,
-                                                  memcached_server_st *host,
-                                                  const char *hostname,
-                                                  in_port_t port,
-                                                  uint32_t weight,
-                                                  memcached_connection_t type);
-
 LIBMEMCACHED_API
 void memcached_server_free(memcached_server_st *ptr);
 
@@ -92,10 +77,7 @@ memcached_server_st *memcached_server_clone(memcached_server_st *destination,
                                             const memcached_server_st *source);
 
 LIBMEMCACHED_API
-memcached_return_t memcached_server_remove(memcached_server_st *st_ptr);
-
-LIBMEMCACHED_API
-memcached_server_st *memcached_server_get_last_disconnect(memcached_st *ptr);
+memcached_server_instance_st memcached_server_get_last_disconnect(const memcached_st *ptr);
 
 
 LIBMEMCACHED_API
@@ -122,48 +104,23 @@ LIBMEMCACHED_API
 memcached_return_t memcached_server_add_with_weight(memcached_st *ptr, const char *hostname,
                                                     in_port_t port,
                                                     uint32_t weight);
-/* Server List Public functions */
 
+/**
+  Operations on Single Servers.
+*/
 LIBMEMCACHED_API
-void memcached_server_list_free(memcached_server_st *ptr);
-
+uint32_t memcached_server_response_count(memcached_server_instance_st self);
 
 LIBMEMCACHED_API
-memcached_return_t memcached_server_push(memcached_st *ptr, memcached_server_st *list);
+const char *memcached_server_name(memcached_server_instance_st self);
 
 LIBMEMCACHED_API
-memcached_server_st *memcached_server_list_append(memcached_server_st *ptr,
-                                                  const char *hostname,
-                                                  in_port_t port,
-                                                  memcached_return_t *error);
-LIBMEMCACHED_API
-memcached_server_st *memcached_server_list_append_with_weight(memcached_server_st *ptr,
-                                                              const char *hostname,
-                                                              in_port_t port,
-                                                              uint32_t weight,
-                                                              memcached_return_t *error);
+in_port_t memcached_server_port(memcached_server_instance_st self);
+
 LIBMEMCACHED_API
-unsigned int memcached_server_list_count(memcached_server_st *ptr);
-
-// Local Only Inline
-static inline uint32_t memcached_servers_count(memcached_server_st *servers)
-{
-  return servers->number_of_hosts;
-}
-
-// Local Only Inline
-static inline uint32_t memcached_servers_set_count(memcached_server_st *servers, uint32_t count)
-{
-  return servers->number_of_hosts= count;
-}
-
-
-#define memcached_server_count(A) (A)->number_of_hosts
-#define memcached_server_name(A,B) (B).hostname
-#define memcached_server_port(A,B) (B).port
-#define memcached_server_list(A) (A)->servers
-#define memcached_server_list_set(A,B) (A)->servers=(B)
-#define memcached_server_response_count(A) (A)->cursor_active
+const char *memcached_server_error(memcached_server_instance_st ptr);
+
+
 
 #ifdef __cplusplus
 } // extern "C"
index f3750ea17bcb741ea150c3f76989c7e17d0a635e..10b6a6b37cc8e9517ecdb0a1464c2a70fa355cdc 100644 (file)
 
 #include "common.h"
 
-memcached_server_st *memcached_server_list_append_with_weight(memcached_server_st *ptr,
-                                                              const char *hostname, in_port_t port,
-                                                              uint32_t weight,
-                                                              memcached_return_t *error)
+memcached_server_list_st 
+memcached_server_list_append_with_weight(memcached_server_list_st ptr,
+                                         const char *hostname, in_port_t port,
+                                         uint32_t weight,
+                                         memcached_return_t *error)
 {
-  unsigned int count;
-  memcached_server_instance_st *new_host_list;
+  uint32_t count;
+  memcached_server_list_st new_host_list;
 
   if (hostname == NULL || error == NULL)
     return NULL;
@@ -30,10 +31,10 @@ memcached_server_st *memcached_server_list_append_with_weight(memcached_server_s
   count= 1;
   if (ptr != NULL)
   {
-    count+= memcached_servers_count(ptr);
+    count+= memcached_server_list_count(ptr);
   }
 
-  new_host_list= (memcached_server_instance_st *)realloc(ptr, sizeof(memcached_server_instance_st) * count);
+  new_host_list= (memcached_server_write_instance_st)realloc(ptr, sizeof(memcached_server_st) * count);
   if (!new_host_list)
   {
     *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
@@ -50,9 +51,27 @@ memcached_server_st *memcached_server_list_append_with_weight(memcached_server_s
   return new_host_list;
 }
 
-memcached_server_st *memcached_server_list_append(memcached_server_st *ptr,
-                                                  const char *hostname, in_port_t port,
-                                                  memcached_return_t *error)
+memcached_server_list_st
+memcached_server_list_append(memcached_server_list_st ptr,
+                             const char *hostname, in_port_t port,
+                             memcached_return_t *error)
 {
   return memcached_server_list_append_with_weight(ptr, hostname, port, 0, error);
 }
+
+inline uint32_t memcached_server_list_count(const memcached_server_list_st self)
+{
+  return (self == NULL)
+    ? 0
+    : self->number_of_hosts;
+}
+
+inline memcached_server_st *memcached_server_list(const memcached_st *self)
+{
+  return self->servers;
+}
+
+inline void memcached_server_list_set(memcached_st *self, memcached_server_st *list)
+{
+  self->servers= list;
+}
diff --git a/libmemcached/server_list.h b/libmemcached/server_list.h
new file mode 100644 (file)
index 0000000..299b491
--- /dev/null
@@ -0,0 +1,53 @@
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: Types for libmemcached
+ *
+ */
+
+#ifndef __LIBMEMCACHED_SERVER_LIST_H__
+#define __LIBMEMCACHED_SERVER_LIST_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Server List Public functions */
+LIBMEMCACHED_API
+  void memcached_server_list_free(memcached_server_list_st ptr);
+
+LIBMEMCACHED_API
+  memcached_return_t memcached_server_push(memcached_st *ptr, const memcached_server_list_st list);
+
+LIBMEMCACHED_API
+  memcached_server_list_st memcached_server_list_append(memcached_server_list_st ptr,
+                                                        const char *hostname,
+                                                        in_port_t port,
+                                                        memcached_return_t *error);
+LIBMEMCACHED_API
+  memcached_server_list_st memcached_server_list_append_with_weight(memcached_server_list_st ptr,
+                                                                    const char *hostname,
+                                                                    in_port_t port,
+                                                                    uint32_t weight,
+                                                                    memcached_return_t *error);
+LIBMEMCACHED_API
+  uint32_t memcached_server_list_count(const memcached_server_list_st ptr);
+
+LIBMEMCACHED_LOCAL
+  uint32_t memcached_servers_set_count(memcached_server_list_st servers, uint32_t count);
+
+LIBMEMCACHED_LOCAL
+  memcached_server_st *memcached_server_list(const memcached_st *);
+
+LIBMEMCACHED_LOCAL
+  void memcached_server_list_set(memcached_st *self, memcached_server_list_st list);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* __LIBMEMCACHED_SERVER_LIST_H__ */
index 1f3ca5bf8700db57a0de8a1111df784a28de8c8a..fcafe2154c910ca47f29c3e6b76f59fb133f1421 100644 (file)
@@ -161,7 +161,7 @@ static memcached_return_t set_data(memcached_stat_st *memc_stat, char *key, char
   return MEMCACHED_SUCCESS;
 }
 
-char *memcached_stat_get_value(memcached_st *ptr, memcached_stat_st *memc_stat,
+char *memcached_stat_get_value(const memcached_st *ptr, memcached_stat_st *memc_stat,
                                const char *key, memcached_return_t *error)
 {
   char buffer[SMALL_STRING_LEN];
@@ -229,7 +229,7 @@ char *memcached_stat_get_value(memcached_st *ptr, memcached_stat_st *memc_stat,
 
 static memcached_return_t binary_stats_fetch(memcached_stat_st *memc_stat,
                                              char *args,
-                                             memcached_server_instance_st *instance)
+                                             memcached_server_write_instance_st instance)
 {
   memcached_return_t rc;
 
@@ -299,7 +299,7 @@ static memcached_return_t binary_stats_fetch(memcached_stat_st *memc_stat,
 
 static memcached_return_t ascii_stats_fetch(memcached_stat_st *memc_stat,
                                             char *args,
-                                            memcached_server_instance_st *instance)
+                                            memcached_server_write_instance_st instance)
 {
   memcached_return_t rc;
   char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
@@ -379,7 +379,7 @@ memcached_stat_st *memcached_stat(memcached_st *ptr, char *args, memcached_retur
   for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
   {
     memcached_return_t temp_return;
-    memcached_server_instance_st *instance;
+    memcached_server_write_instance_st instance;
     memcached_stat_st *stat_instance;
 
     stat_instance= stats + x;
@@ -411,7 +411,9 @@ memcached_return_t memcached_stat_servername(memcached_stat_st *memc_stat, char
   memcached_return_t rc;
   memcached_st memc;
   memcached_st *memc_ptr;
-  memcached_server_instance_st *instance;
+  memcached_server_write_instance_st instance;
+
+  memset(memc_stat, 0, sizeof(memcached_stat_st));
 
   memc_ptr= memcached_create(&memc);
   WATCHPOINT_ASSERT(memc_ptr);
@@ -438,7 +440,7 @@ memcached_return_t memcached_stat_servername(memcached_stat_st *memc_stat, char
   We make a copy of the keys since at some point in the not so distant future
   we will add support for "found" keys.
 */
-char ** memcached_stat_get_keys(memcached_st *ptr,
+char ** memcached_stat_get_keys(const memcached_st *ptr,
                                 memcached_stat_st *memc_stat,
                                 memcached_return_t *error)
 {
@@ -462,7 +464,7 @@ char ** memcached_stat_get_keys(memcached_st *ptr,
   return list;
 }
 
-void memcached_stat_free(memcached_st *ptr, memcached_stat_st *memc_stat)
+void memcached_stat_free(const memcached_st *ptr, memcached_stat_st *memc_stat)
 {
   if (memc_stat == NULL)
   {
index 245f0711015f4f0f338927dddee2d6187745ebdb..105e89103e1c0606e454a758f47cdd6c7da8ec34 100644 (file)
@@ -45,7 +45,7 @@ extern "C" {
 #endif
 
 LIBMEMCACHED_API
-void memcached_stat_free(memcached_st *, memcached_stat_st *);
+void memcached_stat_free(const memcached_st *, memcached_stat_st *);
 
 LIBMEMCACHED_API
 memcached_stat_st *memcached_stat(memcached_st *ptr, char *args, memcached_return_t *error);
@@ -55,11 +55,11 @@ memcached_return_t memcached_stat_servername(memcached_stat_st *memc_stat, char
                                              const char *hostname, in_port_t port);
 
 LIBMEMCACHED_API
-char *memcached_stat_get_value(memcached_st *ptr, memcached_stat_st *memc_stat,
+char *memcached_stat_get_value(const memcached_st *ptr, memcached_stat_st *memc_stat,
                                const char *key, memcached_return_t *error);
 
 LIBMEMCACHED_API
-char ** memcached_stat_get_keys(memcached_st *ptr, memcached_stat_st *memc_stat,
+char ** memcached_stat_get_keys(const memcached_st *ptr, memcached_stat_st *memc_stat,
                                 memcached_return_t *error);
 
 #ifdef __cplusplus
index 7a96b778368c98e3398c102cce69c4571064094d..6225af3732b15934db4d94df5e8b02be3dd95f63 100644 (file)
@@ -70,7 +70,7 @@ static inline memcached_return_t memcached_send(memcached_st *ptr,
   memcached_return_t rc;
   char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
   uint32_t server_key;
-  memcached_server_instance_st *instance;
+  memcached_server_write_instance_st instance;
 
   WATCHPOINT_ASSERT(!(value == NULL && value_length > 0));
 
@@ -92,7 +92,7 @@ static inline memcached_return_t memcached_send(memcached_st *ptr,
                                  flags, cas, verb);
   }
 
-  server_key= memcached_generate_hash(ptr, master_key, master_key_length);
+  server_key= memcached_generate_hash_with_redistribution(ptr, master_key, master_key_length);
   instance= memcached_server_instance_fetch(ptr, server_key);
 
   if (cas)
@@ -444,10 +444,10 @@ static memcached_return_t memcached_send_binary(memcached_st *ptr,
   bool flush;
   protocol_binary_request_set request= {.bytes= {0}};
   size_t send_length= sizeof(request.bytes);
-  uint32_t server_key= memcached_generate_hash(ptr, master_key,
-                                               master_key_length);
+  uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, master_key,
+                                                                   master_key_length);
 
-  memcached_server_instance_st *server=
+  memcached_server_write_instance_st server=
     memcached_server_instance_fetch(ptr, server_key);
 
   bool noreply= server->root->flags.no_reply;
@@ -502,7 +502,7 @@ static memcached_return_t memcached_send_binary(memcached_st *ptr,
 
     for (uint32_t x= 0; x < ptr->number_of_replicas; x++)
     {
-      memcached_server_instance_st *instance;
+      memcached_server_write_instance_st instance;
 
       ++server_key;
       if (server_key == memcached_server_count(ptr))
index 464d55c0c9878bd2fea2eb5252a55f00ae2e9530..b69433900463ab59b5d32d1f1bdb7db92064f329 100644 (file)
@@ -177,3 +177,27 @@ memcached_return_t memcached_string_check(memcached_string_st *string, size_t ne
   return _string_check(string, need);
 }
 
+inline size_t memcached_string_length(const memcached_string_st *self)
+{
+  return (size_t)(self->end - self->string);
+}
+
+inline size_t memcached_string_size(const memcached_string_st *self)
+{
+  return self->current_size;
+}
+
+inline const char *memcached_string_value(const memcached_string_st *self)
+{
+  return self->string;
+}
+
+inline char *memcached_string_value_mutable(const memcached_string_st *self)
+{
+  return self->string;
+}
+
+inline void memcached_string_set_length(memcached_string_st *self, size_t length)
+{
+  self->end= self->string + length;
+}
index 605ac57ba4c7e664e215f5e2c81082f24f7a32f4..ef567874248a8b47c408648818f8f7398e99f888 100644 (file)
@@ -59,27 +59,20 @@ memcached_return_t memcached_string_reset(memcached_string_st *string);
 LIBMEMCACHED_LOCAL
 void memcached_string_free(memcached_string_st *string);
 
-static inline size_t memcached_string_length(const memcached_string_st *self)
-{
-  return (size_t)(self->end - self->string);
-}
+LIBMEMCACHED_LOCAL
+size_t memcached_string_length(const memcached_string_st *self);
 
-static inline size_t memcached_string_size(const memcached_string_st *self)
-{
-  return self->current_size;
-}
+LIBMEMCACHED_LOCAL
+size_t memcached_string_size(const memcached_string_st *self);
 
-static inline const char *memcached_string_value(const memcached_string_st *self)
-{
-  return self->string;
-}
+LIBMEMCACHED_LOCAL
+const char *memcached_string_value(const memcached_string_st *self);
 
-static inline char *memcached_string_value_mutable(const memcached_string_st *self)
-{
-  return self->string;
-}
+LIBMEMCACHED_LOCAL
+char *memcached_string_value_mutable(const memcached_string_st *self);
 
-#define memcached_string_set_length(A, B) (A)->end= (A)->string + B
+LIBMEMCACHED_LOCAL
+void memcached_string_set_length(memcached_string_st *self, size_t length);
 
 #ifdef __cplusplus
 }
index deaf2f49dc7f7a21a390f886843d33c86ec12525..897abaed89049fdf901fa83ca4754674ebb48483 100644 (file)
@@ -16,9 +16,15 @@ typedef struct memcached_st memcached_st;
 typedef struct memcached_stat_st memcached_stat_st;
 typedef struct memcached_analysis_st memcached_analysis_st;
 typedef struct memcached_result_st memcached_result_st;
+
+// All of the flavors of memcache_server_st
 typedef struct memcached_server_st memcached_server_st;
+typedef const struct memcached_server_st *memcached_server_instance_st;
+typedef struct memcached_server_st *memcached_server_list_st;
+
 typedef struct memcached_callback_st memcached_callback_st;
 
+// The following two structures are internal, and never exposed to users.
 typedef struct memcached_string_st memcached_string_st;
 typedef struct memcached_continuum_item_st memcached_continuum_item_st;
 
@@ -40,7 +46,7 @@ typedef void *(*memcached_calloc_fn)(const memcached_st *ptr, size_t nelem, cons
 
 
 typedef memcached_return_t (*memcached_execute_fn)(const memcached_st *ptr, memcached_result_st *result, void *context);
-typedef memcached_return_t (*memcached_server_fn)(const memcached_st *ptr, memcached_server_st *server, void *context);
+typedef memcached_return_t (*memcached_server_fn)(const memcached_st *ptr, memcached_server_instance_st server, void *context);
 
 /**
   Trigger functions.
index e9fa3ef40212b0b2d339ee5bff43c91bb581a798..00c89fbf8716b03e2b0d607bf24fb5b7950f44cc 100644 (file)
@@ -16,7 +16,7 @@ memcached_return_t memcached_verbosity(memcached_st *ptr, uint32_t verbosity)
   for (x= 0; x < memcached_server_count(ptr); x++)
   {
     memcached_return_t rrc;
-    memcached_server_instance_st *instance=
+    memcached_server_write_instance_st instance=
       memcached_server_instance_fetch(ptr, x);
 
     rrc= memcached_do(instance, buffer, send_length, true);
index e3541d06aca1e3533a8c96f8de4f3d7a52f92310..7ab488809b6b083504db0192b65e5c91973e4155 100644 (file)
@@ -33,7 +33,7 @@ static inline memcached_return_t memcached_version_textual(memcached_st *ptr)
   for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
   {
     memcached_return_t rrc;
-    memcached_server_instance_st *instance=
+    memcached_server_write_instance_st instance=
       memcached_server_instance_fetch(ptr, x);
 
     rrc= memcached_do(instance, command, send_length, true);
@@ -80,7 +80,7 @@ static inline memcached_return_t memcached_version_binary(memcached_st *ptr)
   {
     memcached_return_t rrc;
 
-    memcached_server_instance_st *instance=
+    memcached_server_write_instance_st instance=
       memcached_server_instance_fetch(ptr, x);
 
     rrc= memcached_do(instance, request.bytes, sizeof(request.bytes), true);
@@ -94,7 +94,7 @@ static inline memcached_return_t memcached_version_binary(memcached_st *ptr)
 
   for (x= 0; x < memcached_server_count(ptr); x++) 
   {
-    memcached_server_instance_st *instance=
+    memcached_server_write_instance_st instance=
       memcached_server_instance_fetch(ptr, x);
 
     if (memcached_server_response_count(instance) > 0) 
index 0f15cd218d424296d5f36925c8726d7bad2441b2..1bfc01ad58ec3290ddccedd52a862dd7c7c529ad 100644 (file)
@@ -137,6 +137,7 @@ you will need to install %{name}-devel.
 %{_includedir}/libmemcached/protocol_handler.h
 %{_includedir}/libmemcached/result.h
 %{_includedir}/libmemcached/server.h
+%{_includedir}/libmemcached/server_list.h
 %{_includedir}/libmemcached/stats.h
 %{_includedir}/libmemcached/storage.h
 %{_includedir}/libmemcached/string.h
index 6404153555c77b434ec21bf3b773b288d46c536a..b34f1f165ae8c9e9c65bc505716b9d6782162bad 100644 (file)
@@ -41,7 +41,8 @@ noinst_PROGRAMS+= \
                  tests/startservers \
                  tests/testapp \
                  tests/testhashkit \
-                 tests/testplus
+                 tests/testplus \
+                 tests/testudp
 
 noinst_LTLIBRARIES+= tests/libserver.la
 tests_libserver_la_SOURCES= tests/server.c
@@ -71,6 +72,15 @@ tests_atomsmasher_LDADD= \
        $(TESTS_LDADDS)
 tests_atomsmasher_DEPENDENCIES= $(tests_atomsmasher_LDADD)
 
+tests_testudp_CFLAGS= $(AM_CFLAGS) $(NO_CONVERSION) $(NO_STRICT_ALIASING)
+tests_testudp_SOURCES= tests/mem_udp.c
+tests_testudp_LDADD= \
+       clients/libgenexec.la \
+       tests/libserver.la \
+       tests/libtest.la \
+       $(TESTS_LDADDS)
+tests_testudp_DEPENDENCIES= $(tests_testudp_LDADD)
+
 tests_startservers_SOURCES= tests/start.c
 tests_startservers_LDADD= tests/libserver.la $(TESTS_LDADDS)
 tests_startservers_DEPENDENCIES= $(tests_startservers_LDADD)
@@ -217,11 +227,16 @@ HASHPLUS_COMMAND= tests/hashplus $(COLLECTION) $(SUITE)
 
 ATOM_COMMAND= tests/atomsmasher $(COLLECTION) $(SUITE)
 
+UDP_COMMAND= tests/testudp $(COLLECTION) $(SUITE)
+
 HASH_COMMAND= tests/testhashkit $(COLLECTION) $(SUITE)
 
 test-mem: tests/testapp
        $(MEM_COMMAND)
 
+test-udp: tests/testudp
+       $(UDP_COMMAND)
+
 test-atom: tests/atomsmasher
        $(ATOM_COMMAND)
 
@@ -244,6 +259,9 @@ gdb-mem: tests/testapp
        $(DEBUG_COMMAND)  $(MEM_COMMAND)
 
 gdb-atom: tests/atomsmasher
+       $(DEBUG_COMMAND)  $(UDP_COMMAND)
+
+gdb-udp: tests/testudp
        $(DEBUG_COMMAND)  $(ATOM_COMMAND)
 
 gdb-plus: tests/testplus
@@ -267,6 +285,9 @@ valgrind-mem: tests/testapp
 valgrind-atom: tests/atomsmasher
        $(VALGRIND_COMMAND)  $(ATOM_COMMAND)
 
+valgrind-udp: tests/testudp
+       $(VALGRIND_COMMAND)  $(UDP_COMMAND)
+
 valgrind-plus: tests/testplus
        $(VALGRIND_COMMAND)  $(TESTPLUS_COMMAND)
 
index 45927a23afac06d7afcf66e1c24d3a9f044d7aae..b608d9ae953294824ef558d06c13d48b5e15f3bc 100644 (file)
@@ -98,8 +98,8 @@ test_return_t world_pre_run(libmemcached_test_container_st *container)
 {
   for (uint32_t loop= 0; loop < memcached_server_list_count(container->construct.servers); loop++)
   {
-    memcached_server_st *instance=
-      memcached_server_instance_fetch(container->memc, loop);
+    memcached_server_instance_st instance=
+      memcached_server_instance_by_position(container->memc, loop);
 
     test_true(instance->fd == -1);
     test_true(instance->cursor_active == 0);
index cf48940bbeca39573c0d9428fe70bd1f7a6c980c..84ac0dc14abbd5677b22afde097b8871a13ce4d4 100644 (file)
@@ -83,12 +83,13 @@ static test_return_t server_list_null_test(memcached_st *ptr __attribute__((unus
 in_port_t test_ports[TEST_PORT_COUNT];
 
 static memcached_return_t  server_display_function(const memcached_st *ptr __attribute__((unused)),
-                                                   memcached_server_st *server, void *context)
+                                                   const memcached_server_st *server,
+                                                   void *context)
 {
   /* Do Nothing */
   size_t bigger= *((size_t *)(context));
-  assert(bigger <= server->port);
-  *((size_t *)(context))= server->port;
+  assert(bigger <= memcached_server_port(server));
+  *((size_t *)(context))= memcached_server_port(server);
 
   return MEMCACHED_SUCCESS;
 }
@@ -110,7 +111,9 @@ static test_return_t server_sort_test(memcached_st *ptr __attribute__((unused)))
     test_ports[x]= (in_port_t)random() % 64000;
     rc= memcached_server_add_with_weight(local_memc, "localhost", test_ports[x], 0);
     test_true(memcached_server_count(local_memc) == x + 1);
-    test_true(memcached_servers_count(memcached_server_list(local_memc)) == x+1);
+#if 0 // Rewrite
+    test_true(memcached_server_list_count(memcached_server_list(local_memc)) == x+1);
+#endif
     test_true(rc == MEMCACHED_SUCCESS);
   }
 
@@ -129,7 +132,7 @@ static test_return_t server_sort2_test(memcached_st *ptr __attribute__((unused))
   memcached_return_t rc;
   memcached_server_fn callbacks[1];
   memcached_st *local_memc;
-  memcached_server_instance_st *instance;
+  memcached_server_instance_st instance;
 
   local_memc= memcached_create(NULL);
   test_true(local_memc);
@@ -138,17 +141,17 @@ static test_return_t server_sort2_test(memcached_st *ptr __attribute__((unused))
 
   rc= memcached_server_add_with_weight(local_memc, "MEMCACHED_BEHAVIOR_SORT_HOSTS", 43043, 0);
   test_true(rc == MEMCACHED_SUCCESS);
-  instance= memcached_server_instance_fetch(local_memc, 0);
-  test_true(instance->port == 43043);
+  instance= memcached_server_instance_by_position(local_memc, 0);
+  test_true(memcached_server_port(instance) == 43043);
 
   rc= memcached_server_add_with_weight(local_memc, "MEMCACHED_BEHAVIOR_SORT_HOSTS", 43042, 0);
   test_true(rc == MEMCACHED_SUCCESS);
 
-  instance= memcached_server_instance_fetch(local_memc, 0);
-  test_true(instance->port == 43042);
+  instance= memcached_server_instance_by_position(local_memc, 0);
+  test_true(memcached_server_port(instance) == 43042);
 
-  instance= memcached_server_instance_fetch(local_memc, 1);
-  test_true(instance->port == 43043);
+  instance= memcached_server_instance_by_position(local_memc, 1);
+  test_true(memcached_server_port(instance) == 43043);
 
   callbacks[0]= server_display_function;
   memcached_server_cursor(local_memc, callbacks, (void *)&bigger,  1);
@@ -159,7 +162,46 @@ static test_return_t server_sort2_test(memcached_st *ptr __attribute__((unused))
   return TEST_SUCCESS;
 }
 
-static memcached_return_t server_display_unsort_function(const memcached_st *ptr __attribute__((unused)), memcached_server_st *server, void *context)
+static memcached_return_t server_print_callback(const memcached_st *ptr __attribute__((unused)),
+                                                const memcached_server_st *server,
+                                                void *context __attribute__((unused)))
+{
+  (void)server; // Just in case we aren't printing.
+
+#if 0
+  fprintf(stderr, "%s(%d)", memcached_server_name(server), memcached_server_port(server));
+#endif
+
+  return MEMCACHED_SUCCESS;
+}
+
+static test_return_t memcached_server_remove_test(memcached_st *ptr __attribute__((unused)))
+{
+  memcached_return_t rc;
+  memcached_st local_memc;
+  memcached_st *memc;
+  memcached_server_st *servers;
+  memcached_server_fn callbacks[1];
+
+  const char *server_string= "localhost:4444, localhost:4445, localhost:4446, localhost:4447, localhost, memcache1.memcache.bk.sapo.pt:11211, memcache1.memcache.bk.sapo.pt:11212, memcache1.memcache.bk.sapo.pt:11213, memcache1.memcache.bk.sapo.pt:11214, memcache2.memcache.bk.sapo.pt:11211, memcache2.memcache.bk.sapo.pt:11212, memcache2.memcache.bk.sapo.pt:11213, memcache2.memcache.bk.sapo.pt:11214";
+
+  memc= memcached_create(&local_memc);
+
+  servers= memcached_servers_parse(server_string);
+
+  rc= memcached_server_push(memc, servers);
+
+  callbacks[0]= server_print_callback;
+  memcached_server_cursor(memc, callbacks, NULL,  1);
+
+  memcached_free(memc);
+
+  return TEST_SUCCESS;
+}
+
+static memcached_return_t server_display_unsort_function(const memcached_st *ptr __attribute__((unused)),
+                                                         const memcached_server_st *server,
+                                                         void *context)
 {
   /* Do Nothing */
   uint32_t x= *((uint32_t *)(context));
@@ -186,7 +228,9 @@ static test_return_t server_unsort_test(memcached_st *ptr __attribute__((unused)
     test_ports[x]= (in_port_t)(random() % 64000);
     rc= memcached_server_add_with_weight(local_memc, "localhost", test_ports[x], 0);
     test_true(memcached_server_count(local_memc) == x+1);
-    test_true(memcached_servers_count(memcached_server_list(local_memc)) == x+1);
+#if 0 // Rewrite
+    test_true(memcached_server_list_count(memcached_server_list(local_memc)) == x+1);
+#endif
     test_true(rc == MEMCACHED_SUCCESS);
   }
 
@@ -530,7 +574,7 @@ static test_return_t cas_test(memcached_st *memc)
   test_true(rc == MEMCACHED_SUCCESS);
   uint64_t cas = memcached_result_cas(results);
 
-  #if 0
+#if 0
   results= memcached_fetch_result(memc, &results_obj, &rc);
   test_true(rc == MEMCACHED_END);
   test_true(results == NULL);
@@ -695,7 +739,7 @@ static test_return_t flush_test(memcached_st *memc)
 }
 
 static memcached_return_t  server_function(const memcached_st *ptr __attribute__((unused)),
-                                           memcached_server_st *server __attribute__((unused)),
+                                           const memcached_server_st *server __attribute__((unused)),
                                            void *context __attribute__((unused)))
 {
   /* Do Nothing */
@@ -1168,12 +1212,12 @@ static test_return_t stats_servername_test(memcached_st *memc)
 {
   memcached_return_t rc;
   memcached_stat_st memc_stat;
-  memcached_server_instance_st *instance=
-    memcached_server_instance_fetch(memc, 0);
+  memcached_server_instance_st instance=
+    memcached_server_instance_by_position(memc, 0);
 
   rc= memcached_stat_servername(&memc_stat, NULL,
-                                instance->hostname,
-                                instance->port);
+                                memcached_server_name(instance),
+                                memcached_server_port(instance));
 
   return TEST_SUCCESS;
 }
@@ -2666,22 +2710,19 @@ static test_return_t user_supplied_bug17(memcached_st *memc)
   From Andrei on IRC
 */
 
-static test_return_t user_supplied_bug19(memcached_st *memc)
+static test_return_t user_supplied_bug19(memcached_st *not_used)
 {
-  memcached_st *m;
-  memcached_server_st *s;
+  memcached_st *memc;
+  const memcached_server_st *server;
   memcached_return_t res;
 
-  (void)memc;
-
-  m= memcached_create(NULL);
-  memcached_server_add_with_weight(m, "localhost", 11311, 100);
-  memcached_server_add_with_weight(m, "localhost", 11312, 100);
+  (void)not_used;
 
-  s= memcached_server_by_key(m, "a", 1, &res);
-  memcached_server_free(s);
+  memc= memcached_create(NULL);
+  memcached_server_add_with_weight(memc, "localhost", 11311, 100);
+  memcached_server_add_with_weight(memc, "localhost", 11312, 100);
 
-  memcached_free(m);
+  server= memcached_server_by_key(memc, "a", 1, &res);
 
   return TEST_SUCCESS;
 }
@@ -2768,9 +2809,11 @@ static test_return_t user_supplied_bug18(memcached_st *trash)
   for (x= 0; x < 99; x++)
   {
     uint32_t server_idx = memcached_generate_hash(memc, ketama_test_cases[x].key, strlen(ketama_test_cases[x].key));
-    memcached_server_instance_st *instance=
-      memcached_server_instance_fetch(memc, server_idx);
-    char *hostname = instance->hostname;
+
+    memcached_server_instance_st instance=
+      memcached_server_instance_by_position(memc, server_idx);
+
+    const char *hostname = memcached_server_name(instance);
     test_strcmp(hostname, ketama_test_cases[x].server);
   }
 
@@ -2872,7 +2915,7 @@ static test_return_t user_supplied_bug21(memcached_st *memc)
 static test_return_t auto_eject_hosts(memcached_st *trash)
 {
   (void) trash;
-  memcached_server_instance_st *instance;
+  memcached_server_instance_st instance;
 
   memcached_return_t rc;
   memcached_st *memc= memcached_create(NULL);
@@ -2913,18 +2956,22 @@ static test_return_t auto_eject_hosts(memcached_st *trash)
   test_true(server_pool[7].port == 11211);
   test_true(server_pool[7].weight == 100);
 
-  instance= memcached_server_instance_fetch(memc, 2);
-  instance->next_retry = time(NULL) + 15;
+  instance= memcached_server_instance_by_position(memc, 2);
+  ((memcached_server_write_instance_st)instance)->next_retry = time(NULL) + 15;
   memc->next_distribution_rebuild= time(NULL) - 1;
 
+  /*
+    This would not work if there were only two hosts.
+  */
   for (size_t x= 0; x < 99; x++)
   {
+    memcached_autoeject(memc);
     uint32_t server_idx = memcached_generate_hash(memc, ketama_test_cases[x].key, strlen(ketama_test_cases[x].key));
     test_true(server_idx != 2);
   }
 
   /* and re-added when it's back. */
-  instance->next_retry = time(NULL) - 1;
+  ((memcached_server_write_instance_st)instance)->next_retry = time(NULL) - 1;
   memc->next_distribution_rebuild= time(NULL) - 1;
   memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_DISTRIBUTION,
                          memc->distribution);
@@ -2933,8 +2980,8 @@ static test_return_t auto_eject_hosts(memcached_st *trash)
     uint32_t server_idx = memcached_generate_hash(memc, ketama_test_cases[x].key, strlen(ketama_test_cases[x].key));
     // We re-use instance from above.
     instance=
-      memcached_server_instance_fetch(memc, server_idx);
-    char *hostname = instance->hostname;
+      memcached_server_instance_by_position(memc, server_idx);
+    const char *hostname = memcached_server_name(instance);
     test_true(strcmp(hostname, ketama_test_cases[x].server) == 0);
   }
 
@@ -3203,8 +3250,8 @@ static test_return_t generate_data_with_stats(memcached_st *memc)
   {
     /* This test was changes so that "make test" would work properlly */
 #ifdef DEBUG
-    memcached_server_instance_st *instance=
-      memcached_server_instance_fetch(memc, host_index);
+    memcached_server_instance_st instance=
+      memcached_server_instance_by_position(memc, host_index);
 
     printf("\nserver %u|%s|%u bytes: %llu\n", host_index, instance->hostname, instance->port, (unsigned long long)(stat_p + host_index)->bytes);
 #endif
@@ -3437,7 +3484,7 @@ static test_return_t pre_nonblock_binary(memcached_st *memc)
 {
   memcached_return_t rc= MEMCACHED_FAILURE;
   memcached_st *memc_clone;
-  memcached_server_instance_st *instance;
+  memcached_server_instance_st instance;
 
   memc_clone= memcached_clone(NULL, memc);
   test_true(memc_clone);
@@ -3445,7 +3492,7 @@ static test_return_t pre_nonblock_binary(memcached_st *memc)
   // will not toggle protocol on an connection.
   memcached_version(memc_clone);
 
-  instance= memcached_server_instance_fetch(memc_clone, 0);
+  instance= memcached_server_instance_by_position(memc_clone, 0);
 
   if (instance->major_version >= 1 && instance->minor_version > 2)
   {
@@ -3573,7 +3620,7 @@ static test_return_t pre_binary(memcached_st *memc)
 {
   memcached_return_t rc= MEMCACHED_FAILURE;
   memcached_st *memc_clone;
-  memcached_server_instance_st *instance;
+  memcached_server_instance_st instance;
 
   memc_clone= memcached_clone(NULL, memc);
   test_true(memc_clone);
@@ -3581,7 +3628,7 @@ static test_return_t pre_binary(memcached_st *memc)
   // will not toggle protocol on an connection.
   memcached_version(memc_clone);
 
-  instance= memcached_server_instance_fetch(memc_clone, 0);
+  instance= memcached_server_instance_by_position(memc_clone, 0);
 
   if (instance->major_version >= 1 && instance->minor_version > 2)
   {
@@ -3892,8 +3939,8 @@ static test_return_t enable_cas(memcached_st *memc)
 {
   unsigned int set= 1;
 
-  memcached_server_instance_st *instance=
-    memcached_server_instance_fetch(memc, 0);
+  memcached_server_instance_st instance=
+    memcached_server_instance_by_position(memc, 0);
 
   memcached_version(memc);
 
@@ -3911,8 +3958,9 @@ static test_return_t enable_cas(memcached_st *memc)
 static test_return_t check_for_1_2_3(memcached_st *memc)
 {
   memcached_version(memc);
-  memcached_server_instance_st *instance=
-    memcached_server_instance_fetch(memc, 0);
+
+  memcached_server_instance_st instance=
+    memcached_server_instance_by_position(memc, 0);
 
   if ((instance->major_version >= 1 && (instance->minor_version == 2 && instance->micro_version >= 4))
       || instance->minor_version > 2)
@@ -4018,8 +4066,8 @@ static test_return_t noreply_test(memcached_st *memc)
     int no_msg=0;
     for (uint32_t x= 0; x < memcached_server_count(memc); ++x)
     {
-      memcached_server_instance_st *instance=
-        memcached_server_instance_fetch(memc, x);
+      memcached_server_instance_st instance=
+        memcached_server_instance_by_position(memc, x);
       no_msg+=(int)(instance->cursor_active);
     }
 
@@ -4305,10 +4353,10 @@ static test_return_t replication_get_test(memcached_st *memc)
   for (uint32_t host= 0; host < memcached_server_count(memc); ++host)
   {
     memcached_st *memc_clone= memcached_clone(NULL, memc);
-    memcached_server_instance_st *instance=
-      memcached_server_instance_fetch(memc_clone, host);
+    memcached_server_instance_st instance=
+      memcached_server_instance_by_position(memc_clone, host);
 
-    instance->port= 0;
+    ((memcached_server_write_instance_st)instance)->port= 0;
 
     for (int x= 'a'; x <= 'z'; ++x)
     {
@@ -4367,9 +4415,9 @@ static test_return_t replication_mget_test(memcached_st *memc)
   for (uint32_t host= 0; host < memc_clone->number_of_hosts; host++)
   {
     memcached_st *new_clone= memcached_clone(NULL, memc);
-    memcached_server_instance_st *instance=
-      memcached_server_instance_fetch(new_clone, host);
-    instance->port= 0;
+    memcached_server_instance_st instance=
+      memcached_server_instance_by_position(new_clone, host);
+    ((memcached_server_write_instance_st)instance)->port= 0;
 
     for (int x= 'a'; x <= 'z'; ++x)
     {
@@ -4465,10 +4513,10 @@ static test_return_t replication_delete_test(memcached_st *memc)
   uint32_t hash= memcached_generate_hash(memc, keys[0], len[0]);
   for (uint32_t x= 0; x < (repl + 1); ++x)
   {
-    memcached_server_instance_st *instance=
-      memcached_server_instance_fetch(memc_clone, x);
+    memcached_server_instance_st instance=
+      memcached_server_instance_by_position(memc_clone, x);
 
-    instance->port= 0;
+    ((memcached_server_write_instance_st)instance)->port= 0;
     if (++hash == memc_clone->number_of_hosts)
       hash= 0;
   }
@@ -4500,390 +4548,6 @@ static test_return_t replication_delete_test(memcached_st *memc)
   return TEST_SUCCESS;
 }
 
-static void increment_request_id(uint16_t *id)
-{
-  (*id)++;
-  if ((*id & UDP_REQUEST_ID_THREAD_MASK) != 0)
-    *id= 0;
-}
-
-static uint16_t *get_udp_request_ids(memcached_st *memc)
-{
-  uint16_t *ids= malloc(sizeof(uint16_t) * memcached_server_count(memc));
-  assert(ids != NULL);
-
-  for (uint32_t x= 0; x < memcached_server_count(memc); x++)
-  {
-    memcached_server_instance_st *instance=
-      memcached_server_instance_fetch(memc, x);
-
-    ids[x]= get_udp_datagram_request_id((struct udp_datagram_header_st *) instance->write_buffer);
-  }
-
-  return ids;
-}
-
-static test_return_t post_udp_op_check(memcached_st *memc, uint16_t *expected_req_ids)
-{
-  memcached_server_st *cur_server = memcached_server_list(memc);
-  uint16_t *cur_req_ids = get_udp_request_ids(memc);
-
-  for (size_t x= 0; x < memcached_server_count(memc); x++)
-  {
-    test_true(cur_server[x].cursor_active == 0);
-    test_true(cur_req_ids[x] == expected_req_ids[x]);
-  }
-  free(expected_req_ids);
-  free(cur_req_ids);
-
-  return TEST_SUCCESS;
-}
-
-/*
-** There is a little bit of a hack here, instead of removing
-** the servers, I just set num host to 0 and them add then new udp servers
-**/
-static test_return_t init_udp(memcached_st *memc)
-{
-  memcached_version(memc);
-  memcached_server_instance_st *instance=
-    memcached_server_instance_fetch(memc, 0);
-
-  /* For the time being, only support udp test for >= 1.2.6 && < 1.3 */
-  if (instance->major_version != 1 || instance->minor_version != 2
-          || instance->micro_version < 6)
-    return TEST_SKIPPED;
-
-  uint32_t num_hosts= memcached_server_count(memc);
-  memcached_server_st servers[num_hosts];
-  memcpy(servers, memcached_server_list(memc), sizeof(memcached_server_st) * num_hosts);
-  for (uint32_t x= 0; x < num_hosts; x++)
-  {
-    memcached_server_instance_st *set_instance=
-      memcached_server_instance_fetch(memc, x);
-
-    memcached_server_free(set_instance);
-  }
-
-  memc->number_of_hosts= 0;
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, 1);
-  for (uint32_t x= 0; x < num_hosts; x++)
-  {
-    memcached_server_instance_st *set_instance=
-      memcached_server_instance_fetch(memc, x);
-
-    test_true(memcached_server_add_udp(memc, servers[x].hostname, servers[x].port) == MEMCACHED_SUCCESS);
-    test_true(set_instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH);
-  }
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t binary_init_udp(memcached_st *memc)
-{
-  test_return_t test_rc;
-  test_rc= pre_binary(memc);
-
-  if (test_rc != TEST_SUCCESS)
-    return test_rc;
-
-  return init_udp(memc);
-}
-
-/* Make sure that I cant add a tcp server to a udp client */
-static test_return_t add_tcp_server_udp_client_test(memcached_st *memc)
-{
-  (void)memc;
-#if 0
-  memcached_server_st server;
-  memcached_server_instance_st *instance=
-    memcached_server_instance_fetch(memc, 0);
-  memcached_server_clone(&server, &memc->hosts[0]);
-  test_true(memcached_server_remove(&(memc->hosts[0])) == MEMCACHED_SUCCESS);
-  test_true(memcached_server_add(memc, server.hostname, server.port) == MEMCACHED_INVALID_HOST_PROTOCOL);
-#endif
-  return TEST_SUCCESS;
-}
-
-/* Make sure that I cant add a udp server to a tcp client */
-static test_return_t add_udp_server_tcp_client_test(memcached_st *memc)
-{
-  (void)memc;
-#if 0
-  memcached_server_st server;
-  memcached_server_instance_st *instance=
-    memcached_server_instance_fetch(memc, 0);
-  memcached_server_clone(&server, &memc->hosts[0]);
-  test_true(memcached_server_remove(&(memc->hosts[0])) == MEMCACHED_SUCCESS);
-
-  memcached_st tcp_client;
-  memcached_create(&tcp_client);
-  test_true(memcached_server_add_udp(&tcp_client, server.hostname, server.port) == MEMCACHED_INVALID_HOST_PROTOCOL);
-#endif
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t set_udp_behavior_test(memcached_st *memc)
-{
-
-  memcached_quit(memc);
-  memc->number_of_hosts= 0;
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, memc->distribution);
-  test_true(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, 1) == MEMCACHED_SUCCESS);
-  test_true(memc->flags.use_udp);
-  test_true(memc->flags.no_reply);
-
-  test_true(memcached_server_count(memc) == 0);
-
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP,0);
-  test_true(! (memc->flags.use_udp));
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY,0);
-  test_true(! (memc->flags.no_reply));
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t udp_set_test(memcached_st *memc)
-{
-  unsigned int num_iters= 1025; //request id rolls over at 1024
-
-  for (size_t x= 0; x < num_iters;x++)
-  {
-    memcached_return_t rc;
-    const char *key= "foo";
-    const char *value= "when we sanitize";
-    uint16_t *expected_ids= get_udp_request_ids(memc);
-    unsigned int server_key= memcached_generate_hash(memc, key, strlen(key));
-    memcached_server_instance_st *instance=
-      memcached_server_instance_fetch(memc, server_key);
-    size_t init_offset= instance->write_buffer_offset;
-
-    rc= memcached_set(memc, key, strlen(key),
-                      value, strlen(value),
-                      (time_t)0, (uint32_t)0);
-    test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
-    /** NB, the check below assumes that if new write_ptr is less than
-     *  the original write_ptr that we have flushed. For large payloads, this
-     *  maybe an invalid assumption, but for the small payload we have it is OK
-     */
-    if (rc == MEMCACHED_SUCCESS ||
-            instance->write_buffer_offset < init_offset)
-      increment_request_id(&expected_ids[server_key]);
-
-    if (rc == MEMCACHED_SUCCESS)
-    {
-      test_true(instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH);
-    }
-    else
-    {
-      test_true(instance->write_buffer_offset != UDP_DATAGRAM_HEADER_LENGTH);
-      test_true(instance->write_buffer_offset <= MAX_UDP_DATAGRAM_LENGTH);
-    }
-    test_true(post_udp_op_check(memc, expected_ids) == TEST_SUCCESS);
-  }
-  return TEST_SUCCESS;
-}
-
-static test_return_t udp_buffered_set_test(memcached_st *memc)
-{
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1);
-  return udp_set_test(memc);
-}
-
-static test_return_t udp_set_too_big_test(memcached_st *memc)
-{
-  memcached_return_t rc;
-  const char *key= "bar";
-  char value[MAX_UDP_DATAGRAM_LENGTH];
-  uint16_t *expected_ids= get_udp_request_ids(memc);
-  rc= memcached_set(memc, key, strlen(key),
-                    value, MAX_UDP_DATAGRAM_LENGTH,
-                    (time_t)0, (uint32_t)0);
-  test_true(rc == MEMCACHED_WRITE_FAILURE);
-
-  return post_udp_op_check(memc,expected_ids);
-}
-
-static test_return_t udp_delete_test(memcached_st *memc)
-{
-  unsigned int num_iters= 1025; //request id rolls over at 1024
-
-  for (size_t x= 0; x < num_iters;x++)
-  {
-    memcached_return_t rc;
-    const char *key= "foo";
-    uint16_t *expected_ids=get_udp_request_ids(memc);
-    unsigned int server_key= memcached_generate_hash(memc, key, strlen(key));
-    memcached_server_instance_st *instance=
-      memcached_server_instance_fetch(memc, server_key);
-    size_t init_offset= instance->write_buffer_offset;
-
-    rc= memcached_delete(memc, key, strlen(key), 0);
-    test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
-
-    if (rc == MEMCACHED_SUCCESS || instance->write_buffer_offset < init_offset)
-      increment_request_id(&expected_ids[server_key]);
-    if (rc == MEMCACHED_SUCCESS)
-    {
-      test_true(instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH);
-    }
-    else
-    {
-      test_true(instance->write_buffer_offset != UDP_DATAGRAM_HEADER_LENGTH);
-      test_true(instance->write_buffer_offset <= MAX_UDP_DATAGRAM_LENGTH);
-    }
-    test_true(post_udp_op_check(memc,expected_ids) == TEST_SUCCESS);
-  }
-  return TEST_SUCCESS;
-}
-
-static test_return_t udp_buffered_delete_test(memcached_st *memc)
-{
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1);
-  return udp_delete_test(memc);
-}
-
-static test_return_t udp_verbosity_test(memcached_st *memc)
-{
-  memcached_return_t rc;
-  uint16_t *expected_ids= get_udp_request_ids(memc);
-
-  for (size_t x= 0; x < memcached_server_count(memc); x++)
-  {
-    increment_request_id(&expected_ids[x]);
-  }
-
-  rc= memcached_verbosity(memc,3);
-  test_true(rc == MEMCACHED_SUCCESS);
-  return post_udp_op_check(memc,expected_ids);
-}
-
-static test_return_t udp_quit_test(memcached_st *memc)
-{
-  uint16_t *expected_ids= get_udp_request_ids(memc);
-  memcached_quit(memc);
-  return post_udp_op_check(memc, expected_ids);
-}
-
-static test_return_t udp_flush_test(memcached_st *memc)
-{
-  memcached_return_t rc;
-  uint16_t *expected_ids= get_udp_request_ids(memc);
-
-  for (size_t x= 0; x < memcached_server_count(memc); x++)
-  {
-    increment_request_id(&expected_ids[x]);
-  }
-
-  rc= memcached_flush(memc,0);
-  test_true(rc == MEMCACHED_SUCCESS);
-  return post_udp_op_check(memc,expected_ids);
-}
-
-static test_return_t udp_incr_test(memcached_st *memc)
-{
-  memcached_return_t rc;
-  const char *key= "incr";
-  const char *value= "1";
-  rc= memcached_set(memc, key, strlen(key),
-                    value, strlen(value),
-                    (time_t)0, (uint32_t)0);
-
-  test_true(rc == MEMCACHED_SUCCESS);
-  uint16_t *expected_ids= get_udp_request_ids(memc);
-  unsigned int server_key= memcached_generate_hash(memc, key, strlen(key));
-  increment_request_id(&expected_ids[server_key]);
-  uint64_t newvalue;
-  rc= memcached_increment(memc, key, strlen(key), 1, &newvalue);
-  test_true(rc == MEMCACHED_SUCCESS);
-  return post_udp_op_check(memc, expected_ids);
-}
-
-static test_return_t udp_decr_test(memcached_st *memc)
-{
-  memcached_return_t rc;
-  const char *key= "decr";
-  const char *value= "1";
-  rc= memcached_set(memc, key, strlen(key),
-                    value, strlen(value),
-                    (time_t)0, (uint32_t)0);
-
-  test_true(rc == MEMCACHED_SUCCESS);
-  uint16_t *expected_ids= get_udp_request_ids(memc);
-  unsigned int server_key= memcached_generate_hash(memc, key, strlen(key));
-  increment_request_id(&expected_ids[server_key]);
-  uint64_t newvalue;
-  rc= memcached_decrement(memc, key, strlen(key), 1, &newvalue);
-  test_true(rc == MEMCACHED_SUCCESS);
-  return post_udp_op_check(memc, expected_ids);
-}
-
-
-static test_return_t udp_stat_test(memcached_st *memc)
-{
-  memcached_stat_st * rv= NULL;
-  memcached_return_t rc;
-  char args[]= "";
-  uint16_t *expected_ids = get_udp_request_ids(memc);
-  rv = memcached_stat(memc, args, &rc);
-  free(rv);
-  test_true(rc == MEMCACHED_NOT_SUPPORTED);
-  return post_udp_op_check(memc, expected_ids);
-}
-
-static test_return_t udp_version_test(memcached_st *memc)
-{
-  memcached_return_t rc;
-  uint16_t *expected_ids = get_udp_request_ids(memc);
-  rc = memcached_version(memc);
-  test_true(rc == MEMCACHED_NOT_SUPPORTED);
-  return post_udp_op_check(memc, expected_ids);
-}
-
-static test_return_t udp_get_test(memcached_st *memc)
-{
-  memcached_return_t rc;
-  const char *key= "foo";
-  size_t vlen;
-  uint16_t *expected_ids = get_udp_request_ids(memc);
-  char *val= memcached_get(memc, key, strlen(key), &vlen, (uint32_t)0, &rc);
-  test_true(rc == MEMCACHED_NOT_SUPPORTED);
-  test_true(val == NULL);
-  return post_udp_op_check(memc, expected_ids);
-}
-
-static test_return_t udp_mixed_io_test(memcached_st *memc)
-{
-  test_st current_op;
-  test_st mixed_io_ops [] ={
-    {"udp_set_test", 0,
-      (test_callback_fn)udp_set_test},
-    {"udp_set_too_big_test", 0,
-      (test_callback_fn)udp_set_too_big_test},
-    {"udp_delete_test", 0,
-      (test_callback_fn)udp_delete_test},
-    {"udp_verbosity_test", 0,
-      (test_callback_fn)udp_verbosity_test},
-    {"udp_quit_test", 0,
-      (test_callback_fn)udp_quit_test},
-    {"udp_flush_test", 0,
-      (test_callback_fn)udp_flush_test},
-    {"udp_incr_test", 0,
-      (test_callback_fn)udp_incr_test},
-    {"udp_decr_test", 0,
-      (test_callback_fn)udp_decr_test},
-    {"udp_version_test", 0,
-      (test_callback_fn)udp_version_test}
-  };
-  for (size_t x= 0; x < 500; x++)
-  {
-    current_op= mixed_io_ops[random() % 9];
-    test_true(current_op.test_fn(memc) == TEST_SUCCESS);
-  }
-  return TEST_SUCCESS;
-}
-
 #if 0
 static test_return_t hash_sanity_test (memcached_st *memc)
 {
@@ -5209,9 +4873,9 @@ static test_return_t ketama_compatibility_libmemcached(memcached_st *trash)
   for (x= 0; x < 99; x++)
   {
     uint32_t server_idx = memcached_generate_hash(memc, ketama_test_cases[x].key, strlen(ketama_test_cases[x].key));
-    memcached_server_instance_st *instance=
-      memcached_server_instance_fetch(memc, server_idx);
-    char *hostname = instance->hostname;
+    memcached_server_instance_st instance=
+      memcached_server_instance_by_position(memc, server_idx);
+    const char *hostname = memcached_server_name(instance);
 
     test_strcmp(hostname, ketama_test_cases[x].server);
   }
@@ -5267,10 +4931,13 @@ static test_return_t ketama_compatibility_spymemcached(memcached_st *trash)
   /* verify the standard ketama set. */
   for (x= 0; x < 99; x++)
   {
-    uint32_t server_idx = memcached_generate_hash(memc, ketama_test_cases_spy[x].key, strlen(ketama_test_cases_spy[x].key));
-    memcached_server_instance_st *instance=
-      memcached_server_instance_fetch(memc, server_idx);
-    char *hostname = instance->hostname;
+    uint32_t server_idx= memcached_generate_hash(memc, ketama_test_cases_spy[x].key, strlen(ketama_test_cases_spy[x].key));
+
+    memcached_server_instance_st instance=
+      memcached_server_instance_by_position(memc, server_idx);
+
+    const char *hostname= memcached_server_name(instance);
+
     test_strcmp(hostname, ketama_test_cases_spy[x].server);
   }
 
@@ -5471,8 +5138,8 @@ static test_return_t regression_bug_442914(memcached_st *memc)
 
 static test_return_t regression_bug_447342(memcached_st *memc)
 {
-  memcached_server_instance_st *instance_one;
-  memcached_server_instance_st *instance_two;
+  memcached_server_instance_st instance_one;
+  memcached_server_instance_st instance_two;
 
   if (memcached_server_count(memc) < 3 || pre_replication(memc) != MEMCACHED_SUCCESS)
     return TEST_SKIPPED;
@@ -5531,13 +5198,13 @@ static test_return_t regression_bug_447342(memcached_st *memc)
    * This is to verify correct behavior in the library. Fake that two servers
    * are dead..
    */
-  instance_one= memcached_server_instance_fetch(memc, 0);
-  instance_two= memcached_server_instance_fetch(memc, 2);
+  instance_one= memcached_server_instance_by_position(memc, 0);
+  instance_two= memcached_server_instance_by_position(memc, 2);
   in_port_t port0= instance_one->port;
   in_port_t port2= instance_two->port;
 
-  instance_one->port= 0;
-  instance_two->port= 0;
+  ((memcached_server_write_instance_st)instance_one)->port= 0;
+  ((memcached_server_write_instance_st)instance_two)->port= 0;
 
   rc= memcached_mget(memc, (const char* const *)keys, key_length, max_keys);
   test_true(rc == MEMCACHED_SUCCESS);
@@ -5547,8 +5214,8 @@ static test_return_t regression_bug_447342(memcached_st *memc)
   test_true(counter == (unsigned int)max_keys);
 
   /* restore the memc handle */
-  instance_one->port= port0;
-  instance_two->port= port2;
+  ((memcached_server_write_instance_st)instance_one)->port= port0;
+  ((memcached_server_write_instance_st)instance_two)->port= port2;
 
   memcached_quit(memc);
 
@@ -5563,8 +5230,8 @@ static test_return_t regression_bug_447342(memcached_st *memc)
   }
 
   memcached_quit(memc);
-  instance_one->port= 0;
-  instance_two->port= 0;
+  ((memcached_server_write_instance_st)instance_one)->port= 0;
+  ((memcached_server_write_instance_st)instance_two)->port= 0;
 
   /* now retry the command, this time we should have cache misses */
   rc= memcached_mget(memc, (const char* const *)keys, key_length, max_keys);
@@ -5583,8 +5250,8 @@ static test_return_t regression_bug_447342(memcached_st *memc)
   free(key_length);
 
   /* restore the memc handle */
-  instance_one->port= port0;
-  instance_two->port= port2;
+  ((memcached_server_write_instance_st)instance_one)->port= port0;
+  ((memcached_server_write_instance_st)instance_two)->port= port2;
 
   return TEST_SUCCESS;
 }
@@ -5595,8 +5262,8 @@ static test_return_t regression_bug_463297(memcached_st *memc)
   test_true(memc_clone != NULL);
   test_true(memcached_version(memc_clone) == MEMCACHED_SUCCESS);
 
-  memcached_server_instance_st *instance=
-    memcached_server_instance_fetch(memc_clone, 0);
+  memcached_server_instance_st instance=
+    memcached_server_instance_by_position(memc_clone, 0);
 
   if (instance->major_version > 1 ||
       (instance->major_version == 1 &&
@@ -5657,7 +5324,7 @@ static test_return_t regression_bug_463297(memcached_st *memc)
 static test_return_t test_get_last_disconnect(memcached_st *memc)
 {
   memcached_return_t rc;
-  memcached_server_st *disconnected_server;
+  memcached_server_instance_st disconnected_server;
 
   /* With the working set of server */
   const char *key= "marmotte";
@@ -5692,8 +5359,8 @@ static test_return_t test_get_last_disconnect(memcached_st *memc)
 
   disconnected_server = memcached_server_get_last_disconnect(mine);
   test_true(disconnected_server != NULL);
-  test_true(disconnected_server->port == 9);
-  test_true(strncmp(disconnected_server->hostname,"localhost",9) == 0);
+  test_true(memcached_server_port(disconnected_server)== 9);
+  test_true(strncmp(memcached_server_name(disconnected_server),"localhost",9) == 0);
 
   memcached_quit(mine);
   memcached_free(mine);
@@ -5708,7 +5375,7 @@ static test_return_t test_get_last_disconnect(memcached_st *memc)
 static test_return_t wrong_failure_counter_test(memcached_st *memc)
 {
   memcached_return_t rc;
-  memcached_server_instance_st *instance;
+  memcached_server_instance_st instance;
 
   /* Set value to force connection to the server */
   const char *key= "marmotte";
@@ -5729,12 +5396,12 @@ static test_return_t wrong_failure_counter_test(memcached_st *memc)
   test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
 
 
-  instance= memcached_server_instance_fetch(memc, 0);
+  instance= memcached_server_instance_by_position(memc, 0);
   /* The test is to see that the memcached_quit doesn't increase the
    * the server failure conter, so let's ensure that it is zero
    * before sending quit
    */
-  instance->server_failure_counter= 0;
+  ((memcached_server_write_instance_st)instance)->server_failure_counter= 0;
 
   memcached_quit(memc);
 
@@ -5835,31 +5502,6 @@ static test_return_t regression_bug_490486(memcached_st *memc)
 
 
 
-test_st udp_setup_server_tests[] ={
-  {"set_udp_behavior_test", 0, (test_callback_fn)set_udp_behavior_test},
-  {"add_tcp_server_udp_client_test", 0, (test_callback_fn)add_tcp_server_udp_client_test},
-  {"add_udp_server_tcp_client_test", 0, (test_callback_fn)add_udp_server_tcp_client_test},
-  {0, 0, 0}
-};
-
-test_st upd_io_tests[] ={
-  {"udp_set_test", 0, (test_callback_fn)udp_set_test},
-  {"udp_buffered_set_test", 0, (test_callback_fn)udp_buffered_set_test},
-  {"udp_set_too_big_test", 0, (test_callback_fn)udp_set_too_big_test},
-  {"udp_delete_test", 0, (test_callback_fn)udp_delete_test},
-  {"udp_buffered_delete_test", 0, (test_callback_fn)udp_buffered_delete_test},
-  {"udp_verbosity_test", 0, (test_callback_fn)udp_verbosity_test},
-  {"udp_quit_test", 0, (test_callback_fn)udp_quit_test},
-  {"udp_flush_test", 0, (test_callback_fn)udp_flush_test},
-  {"udp_incr_test", 0, (test_callback_fn)udp_incr_test},
-  {"udp_decr_test", 0, (test_callback_fn)udp_decr_test},
-  {"udp_stat_test", 0, (test_callback_fn)udp_stat_test},
-  {"udp_version_test", 0, (test_callback_fn)udp_version_test},
-  {"udp_get_test", 0, (test_callback_fn)udp_get_test},
-  {"udp_mixed_io_test", 0, (test_callback_fn)udp_mixed_io_test},
-  {0, 0, 0}
-};
-
 /* Clean the server before beginning testing */
 test_st tests[] ={
   {"flush", 0, (test_callback_fn)flush_test },
@@ -5869,6 +5511,7 @@ test_st tests[] ={
   {"server_unsort", 0, (test_callback_fn)server_unsort_test},
   {"server_sort", 0, (test_callback_fn)server_sort_test},
   {"server_sort2", 0, (test_callback_fn)server_sort2_test},
+  {"memcached_server_remove", 0, (test_callback_fn)memcached_server_remove_test},
   {"clone_test", 0, (test_callback_fn)clone_test },
   {"connection_test", 0, (test_callback_fn)connection_test},
   {"callback_test", 0, (test_callback_fn)callback_test},
@@ -6097,9 +5740,6 @@ collection_st collection[] ={
   {"hash_sanity", 0, 0, hash_sanity},
 #endif
   {"hsieh_availability", 0, 0, hsieh_availability},
-  {"udp_setup", (test_callback_fn)init_udp, 0, udp_setup_server_tests},
-  {"udp_io", (test_callback_fn)init_udp, 0, upd_io_tests},
-  {"udp_binary_io", (test_callback_fn)binary_init_udp, 0, upd_io_tests},
   {"block", 0, 0, tests},
   {"binary", (test_callback_fn)pre_binary, 0, tests},
   {"nonblock", (test_callback_fn)pre_nonblock, 0, tests},
diff --git a/tests/mem_udp.c b/tests/mem_udp.c
new file mode 100644 (file)
index 0000000..5a41c53
--- /dev/null
@@ -0,0 +1,514 @@
+/* libMemcached Functions Test
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ */
+
+/*
+  Sample test application.
+*/
+
+#include "libmemcached/common.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "server.h"
+
+#ifndef INT64_MAX
+#define INT64_MAX LONG_MAX
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX INT_MAX
+#endif
+
+
+#include "test.h"
+
+#define SERVERS_TO_CREATE 5
+
+
+/**
+  @note This should be testing to see if the server really supports the binary protocol.
+*/
+static test_return_t pre_binary(memcached_st *memc)
+{
+  memcached_return_t rc= MEMCACHED_FAILURE;
+  memcached_st *memc_clone;
+  memcached_server_instance_st instance;
+
+  memc_clone= memcached_clone(NULL, memc);
+  test_true(memc_clone);
+  // The memcached_version needs to be done on a clone, because the server
+  // will not toggle protocol on an connection.
+  memcached_version(memc_clone);
+
+  instance= memcached_server_instance_by_position(memc_clone, 0);
+
+  if (instance->major_version >= 1 && instance->minor_version > 2)
+  {
+    rc = memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1);
+    test_true(rc == MEMCACHED_SUCCESS);
+    test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) == 1);
+  }
+
+  memcached_free(memc_clone);
+
+  return rc == MEMCACHED_SUCCESS ? TEST_SUCCESS : TEST_SKIPPED;
+}
+
+static void increment_request_id(uint16_t *id)
+{
+  (*id)++;
+  if ((*id & UDP_REQUEST_ID_THREAD_MASK) != 0)
+    *id= 0;
+}
+
+static uint16_t *get_udp_request_ids(memcached_st *memc)
+{
+  uint16_t *ids= malloc(sizeof(uint16_t) * memcached_server_count(memc));
+  assert(ids != NULL);
+
+  for (uint32_t x= 0; x < memcached_server_count(memc); x++)
+  {
+    memcached_server_instance_st instance=
+      memcached_server_instance_by_position(memc, x);
+
+    ids[x]= get_udp_datagram_request_id((struct udp_datagram_header_st *) ((memcached_server_instance_st )instance)->write_buffer);
+  }
+
+  return ids;
+}
+
+static test_return_t post_udp_op_check(memcached_st *memc, uint16_t *expected_req_ids)
+{
+  (void)memc;
+  (void)expected_req_ids;
+#if 0
+  memcached_server_st *cur_server = memcached_server_list(memc);
+  uint16_t *cur_req_ids = get_udp_request_ids(memc);
+
+  for (size_t x= 0; x < memcached_server_count(memc); x++)
+  {
+    test_true(cur_server[x].cursor_active == 0);
+    test_true(cur_req_ids[x] == expected_req_ids[x]);
+  }
+  free(expected_req_ids);
+  free(cur_req_ids);
+
+#endif
+  return TEST_SUCCESS;
+}
+
+/*
+** There is a little bit of a hack here, instead of removing
+** the servers, I just set num host to 0 and them add then new udp servers
+**/
+static test_return_t init_udp(memcached_st *memc)
+{
+  memcached_version(memc);
+#if 0
+  memcached_server_instance_st instance=
+    memcached_server_instance_by_position(memc, 0);
+
+  /* For the time being, only support udp test for >= 1.2.6 && < 1.3 */
+  if (instance->major_version != 1 || instance->minor_version != 2
+          || instance->micro_version < 6)
+    return TEST_SKIPPED;
+
+  uint32_t num_hosts= memcached_server_count(memc);
+  memcached_server_st servers[num_hosts];
+  memcpy(servers, memcached_server_list(memc), sizeof(memcached_server_st) * num_hosts);
+  for (uint32_t x= 0; x < num_hosts; x++)
+  {
+   memcached_server_instance_st set_instance=
+     memcached_server_instance_by_position(memc, x);
+
+    memcached_server_free(((memcached_server_write_instance_st)set_instance));
+  }
+
+  memc->number_of_hosts= 0;
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, 1);
+  for (uint32_t x= 0; x < num_hosts; x++)
+  {
+    memcached_server_instance_st set_instance=
+      memcached_server_instance_by_position(memc, x);
+
+    test_true(memcached_server_add_udp(memc, servers[x].hostname, servers[x].port) == MEMCACHED_SUCCESS);
+    test_true(set_instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH);
+  }
+#endif
+
+  return TEST_SKIPPED;
+}
+
+static test_return_t binary_init_udp(memcached_st *memc)
+{
+  test_return_t test_rc;
+  test_rc= pre_binary(memc);
+
+  if (test_rc != TEST_SUCCESS)
+    return test_rc;
+
+  return init_udp(memc);
+}
+
+/* Make sure that I cant add a tcp server to a udp client */
+static test_return_t add_tcp_server_udp_client_test(memcached_st *memc)
+{
+  (void)memc;
+#if 0
+  memcached_server_st server;
+  memcached_server_instance_st instance=
+    memcached_server_instance_by_position(memc, 0);
+  memcached_server_clone(&server, &memc->hosts[0]);
+  test_true(memcached_server_remove(&(memc->hosts[0])) == MEMCACHED_SUCCESS);
+  test_true(memcached_server_add(memc, server.hostname, server.port) == MEMCACHED_INVALID_HOST_PROTOCOL);
+#endif
+  return TEST_SUCCESS;
+}
+
+/* Make sure that I cant add a udp server to a tcp client */
+static test_return_t add_udp_server_tcp_client_test(memcached_st *memc)
+{
+  (void)memc;
+#if 0
+  memcached_server_st server;
+  memcached_server_instance_st instance=
+    memcached_server_instance_by_position(memc, 0);
+  memcached_server_clone(&server, &memc->hosts[0]);
+  test_true(memcached_server_remove(&(memc->hosts[0])) == MEMCACHED_SUCCESS);
+
+  memcached_st tcp_client;
+  memcached_create(&tcp_client);
+  test_true(memcached_server_add_udp(&tcp_client, server.hostname, server.port) == MEMCACHED_INVALID_HOST_PROTOCOL);
+#endif
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t set_udp_behavior_test(memcached_st *memc)
+{
+
+  memcached_quit(memc);
+  memc->number_of_hosts= 0;
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, memc->distribution);
+  test_true(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, 1) == MEMCACHED_SUCCESS);
+  test_true(memc->flags.use_udp);
+  test_true(memc->flags.no_reply);
+
+  test_true(memcached_server_count(memc) == 0);
+
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP,0);
+  test_true(! (memc->flags.use_udp));
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY,0);
+  test_true(! (memc->flags.no_reply));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t udp_set_test(memcached_st *memc)
+{
+  unsigned int num_iters= 1025; //request id rolls over at 1024
+
+  for (size_t x= 0; x < num_iters;x++)
+  {
+    memcached_return_t rc;
+    const char *key= "foo";
+    const char *value= "when we sanitize";
+    uint16_t *expected_ids= get_udp_request_ids(memc);
+    unsigned int server_key= memcached_generate_hash(memc, key, strlen(key));
+    memcached_server_instance_st instance=
+      memcached_server_instance_by_position(memc, server_key);
+    size_t init_offset= instance->write_buffer_offset;
+
+    rc= memcached_set(memc, key, strlen(key),
+                      value, strlen(value),
+                      (time_t)0, (uint32_t)0);
+    test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+    /** NB, the check below assumes that if new write_ptr is less than
+     *  the original write_ptr that we have flushed. For large payloads, this
+     *  maybe an invalid assumption, but for the small payload we have it is OK
+     */
+    if (rc == MEMCACHED_SUCCESS ||
+            instance->write_buffer_offset < init_offset)
+      increment_request_id(&expected_ids[server_key]);
+
+    if (rc == MEMCACHED_SUCCESS)
+    {
+      test_true(instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH);
+    }
+    else
+    {
+      test_true(instance->write_buffer_offset != UDP_DATAGRAM_HEADER_LENGTH);
+      test_true(instance->write_buffer_offset <= MAX_UDP_DATAGRAM_LENGTH);
+    }
+    test_true(post_udp_op_check(memc, expected_ids) == TEST_SUCCESS);
+  }
+  return TEST_SUCCESS;
+}
+
+static test_return_t udp_buffered_set_test(memcached_st *memc)
+{
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1);
+  return udp_set_test(memc);
+}
+
+static test_return_t udp_set_too_big_test(memcached_st *memc)
+{
+  memcached_return_t rc;
+  const char *key= "bar";
+  char value[MAX_UDP_DATAGRAM_LENGTH];
+  uint16_t *expected_ids= get_udp_request_ids(memc);
+  rc= memcached_set(memc, key, strlen(key),
+                    value, MAX_UDP_DATAGRAM_LENGTH,
+                    (time_t)0, (uint32_t)0);
+  test_true(rc == MEMCACHED_WRITE_FAILURE);
+
+  return post_udp_op_check(memc,expected_ids);
+}
+
+static test_return_t udp_delete_test(memcached_st *memc)
+{
+  unsigned int num_iters= 1025; //request id rolls over at 1024
+
+  for (size_t x= 0; x < num_iters;x++)
+  {
+    memcached_return_t rc;
+    const char *key= "foo";
+    uint16_t *expected_ids=get_udp_request_ids(memc);
+    unsigned int server_key= memcached_generate_hash(memc, key, strlen(key));
+    memcached_server_instance_st instance=
+      memcached_server_instance_by_position(memc, server_key);
+    size_t init_offset= instance->write_buffer_offset;
+
+    rc= memcached_delete(memc, key, strlen(key), 0);
+    test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+
+    if (rc == MEMCACHED_SUCCESS || instance->write_buffer_offset < init_offset)
+      increment_request_id(&expected_ids[server_key]);
+    if (rc == MEMCACHED_SUCCESS)
+    {
+      test_true(instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH);
+    }
+    else
+    {
+      test_true(instance->write_buffer_offset != UDP_DATAGRAM_HEADER_LENGTH);
+      test_true(instance->write_buffer_offset <= MAX_UDP_DATAGRAM_LENGTH);
+    }
+    test_true(post_udp_op_check(memc,expected_ids) == TEST_SUCCESS);
+  }
+  return TEST_SUCCESS;
+}
+
+static test_return_t udp_buffered_delete_test(memcached_st *memc)
+{
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1);
+  return udp_delete_test(memc);
+}
+
+static test_return_t udp_verbosity_test(memcached_st *memc)
+{
+  memcached_return_t rc;
+  uint16_t *expected_ids= get_udp_request_ids(memc);
+
+  for (size_t x= 0; x < memcached_server_count(memc); x++)
+  {
+    increment_request_id(&expected_ids[x]);
+  }
+
+  rc= memcached_verbosity(memc,3);
+  test_true(rc == MEMCACHED_SUCCESS);
+  return post_udp_op_check(memc,expected_ids);
+}
+
+static test_return_t udp_quit_test(memcached_st *memc)
+{
+  uint16_t *expected_ids= get_udp_request_ids(memc);
+  memcached_quit(memc);
+  return post_udp_op_check(memc, expected_ids);
+}
+
+static test_return_t udp_flush_test(memcached_st *memc)
+{
+  memcached_return_t rc;
+  uint16_t *expected_ids= get_udp_request_ids(memc);
+
+  for (size_t x= 0; x < memcached_server_count(memc); x++)
+  {
+    increment_request_id(&expected_ids[x]);
+  }
+
+  rc= memcached_flush(memc,0);
+  test_true(rc == MEMCACHED_SUCCESS);
+  return post_udp_op_check(memc,expected_ids);
+}
+
+static test_return_t udp_incr_test(memcached_st *memc)
+{
+  memcached_return_t rc;
+  const char *key= "incr";
+  const char *value= "1";
+  rc= memcached_set(memc, key, strlen(key),
+                    value, strlen(value),
+                    (time_t)0, (uint32_t)0);
+
+  test_true(rc == MEMCACHED_SUCCESS);
+  uint16_t *expected_ids= get_udp_request_ids(memc);
+  unsigned int server_key= memcached_generate_hash(memc, key, strlen(key));
+  increment_request_id(&expected_ids[server_key]);
+  uint64_t newvalue;
+  rc= memcached_increment(memc, key, strlen(key), 1, &newvalue);
+  test_true(rc == MEMCACHED_SUCCESS);
+  return post_udp_op_check(memc, expected_ids);
+}
+
+static test_return_t udp_decr_test(memcached_st *memc)
+{
+  memcached_return_t rc;
+  const char *key= "decr";
+  const char *value= "1";
+  rc= memcached_set(memc, key, strlen(key),
+                    value, strlen(value),
+                    (time_t)0, (uint32_t)0);
+
+  test_true(rc == MEMCACHED_SUCCESS);
+  uint16_t *expected_ids= get_udp_request_ids(memc);
+  unsigned int server_key= memcached_generate_hash(memc, key, strlen(key));
+  increment_request_id(&expected_ids[server_key]);
+  uint64_t newvalue;
+  rc= memcached_decrement(memc, key, strlen(key), 1, &newvalue);
+  test_true(rc == MEMCACHED_SUCCESS);
+  return post_udp_op_check(memc, expected_ids);
+}
+
+
+static test_return_t udp_stat_test(memcached_st *memc)
+{
+  memcached_stat_st * rv= NULL;
+  memcached_return_t rc;
+  char args[]= "";
+  uint16_t *expected_ids = get_udp_request_ids(memc);
+  rv = memcached_stat(memc, args, &rc);
+  free(rv);
+  test_true(rc == MEMCACHED_NOT_SUPPORTED);
+  return post_udp_op_check(memc, expected_ids);
+}
+
+static test_return_t udp_version_test(memcached_st *memc)
+{
+  memcached_return_t rc;
+  uint16_t *expected_ids = get_udp_request_ids(memc);
+  rc = memcached_version(memc);
+  test_true(rc == MEMCACHED_NOT_SUPPORTED);
+  return post_udp_op_check(memc, expected_ids);
+}
+
+static test_return_t udp_get_test(memcached_st *memc)
+{
+  memcached_return_t rc;
+  const char *key= "foo";
+  size_t vlen;
+  uint16_t *expected_ids = get_udp_request_ids(memc);
+  char *val= memcached_get(memc, key, strlen(key), &vlen, (uint32_t)0, &rc);
+  test_true(rc == MEMCACHED_NOT_SUPPORTED);
+  test_true(val == NULL);
+  return post_udp_op_check(memc, expected_ids);
+}
+
+static test_return_t udp_mixed_io_test(memcached_st *memc)
+{
+  test_st current_op;
+  test_st mixed_io_ops [] ={
+    {"udp_set_test", 0,
+      (test_callback_fn)udp_set_test},
+    {"udp_set_too_big_test", 0,
+      (test_callback_fn)udp_set_too_big_test},
+    {"udp_delete_test", 0,
+      (test_callback_fn)udp_delete_test},
+    {"udp_verbosity_test", 0,
+      (test_callback_fn)udp_verbosity_test},
+    {"udp_quit_test", 0,
+      (test_callback_fn)udp_quit_test},
+    {"udp_flush_test", 0,
+      (test_callback_fn)udp_flush_test},
+    {"udp_incr_test", 0,
+      (test_callback_fn)udp_incr_test},
+    {"udp_decr_test", 0,
+      (test_callback_fn)udp_decr_test},
+    {"udp_version_test", 0,
+      (test_callback_fn)udp_version_test}
+  };
+
+  for (size_t x= 0; x < 500; x++)
+  {
+    current_op= mixed_io_ops[random() % 9];
+    test_true(current_op.test_fn(memc) == TEST_SUCCESS);
+  }
+  return TEST_SUCCESS;
+}
+
+test_st udp_setup_server_tests[] ={
+  {"set_udp_behavior_test", 0, (test_callback_fn)set_udp_behavior_test},
+  {"add_tcp_server_udp_client_test", 0, (test_callback_fn)add_tcp_server_udp_client_test},
+  {"add_udp_server_tcp_client_test", 0, (test_callback_fn)add_udp_server_tcp_client_test},
+  {0, 0, 0}
+};
+
+test_st upd_io_tests[] ={
+  {"udp_set_test", 0, (test_callback_fn)udp_set_test},
+  {"udp_buffered_set_test", 0, (test_callback_fn)udp_buffered_set_test},
+  {"udp_set_too_big_test", 0, (test_callback_fn)udp_set_too_big_test},
+  {"udp_delete_test", 0, (test_callback_fn)udp_delete_test},
+  {"udp_buffered_delete_test", 0, (test_callback_fn)udp_buffered_delete_test},
+  {"udp_verbosity_test", 0, (test_callback_fn)udp_verbosity_test},
+  {"udp_quit_test", 0, (test_callback_fn)udp_quit_test},
+  {"udp_flush_test", 0, (test_callback_fn)udp_flush_test},
+  {"udp_incr_test", 0, (test_callback_fn)udp_incr_test},
+  {"udp_decr_test", 0, (test_callback_fn)udp_decr_test},
+  {"udp_stat_test", 0, (test_callback_fn)udp_stat_test},
+  {"udp_version_test", 0, (test_callback_fn)udp_version_test},
+  {"udp_get_test", 0, (test_callback_fn)udp_get_test},
+  {"udp_mixed_io_test", 0, (test_callback_fn)udp_mixed_io_test},
+  {0, 0, 0}
+};
+
+collection_st collection[] ={
+  {"udp_setup", (test_callback_fn)init_udp, 0, udp_setup_server_tests},
+  {"udp_io", (test_callback_fn)init_udp, 0, upd_io_tests},
+  {"udp_binary_io", (test_callback_fn)binary_init_udp, 0, upd_io_tests},
+  {0, 0, 0, 0}
+};
+
+#define SERVERS_TO_CREATE 5
+
+#include "libmemcached_world.h"
+
+void get_world(world_st *world)
+{
+  world->collections= collection;
+
+  world->create= (test_callback_create_fn)world_create;
+  world->destroy= (test_callback_fn)world_destroy;
+
+  world->test.startup= (test_callback_fn)world_test_startup;
+  world->test.flush= (test_callback_fn)world_flush;
+  world->test.pre_run= (test_callback_fn)world_pre_run;
+  world->test.post_run= (test_callback_fn)world_post_run;
+  world->test.on_error= (test_callback_error_fn)world_on_error;
+
+  world->collection.startup= (test_callback_fn)world_container_startup;
+  world->collection.shutdown= (test_callback_fn)world_container_shutdown;
+
+  world->runner= &defualt_libmemcached_runner;
+}
index 68b3d80146416ede910f85a8c963369dc09d8d98..383469bd5b846307c8812396bfdb995a57331fcb 100644 (file)
@@ -99,7 +99,7 @@ void server_startup(server_startup_st *construct)
 
   for (x= 0; x < memcached_server_list_count(construct->servers); x++)
   {
-    printf("\t%s : %d\n", construct->servers[x].hostname, construct->servers[x].port);
+    printf("\t%s : %d\n", memcached_server_name(&construct->servers[x]), memcached_server_port(&construct->servers[x]));
     assert(construct->servers[x].fd == -1);
     assert(construct->servers[x].cursor_active == 0);
   }