Update binary version parsing.
authorBrian Aker <brian@tangent.org>
Mon, 30 Jan 2012 07:32:18 +0000 (23:32 -0800)
committerBrian Aker <brian@tangent.org>
Mon, 30 Jan 2012 07:32:18 +0000 (23:32 -0800)
ChangeLog
clients/client_options.h
clients/memstat.cc
clients/utilities.cc
libmemcached/io.cc
libmemcached/response.cc
libmemcached/version.cc
tests/memstat.cc

index 304bbf919485a2a8a2044c98697a1c8e22062bdc..450519fd3c31de074b2ca068be7ea6514b1f2d8a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+1.0.5
+
+* Version is now parsed directly in the parser, which makes buffered
+operations now work with it..
+
+* memstat has been extended so that it can be used to find the version of the
+server.
+
+
 1.0.4 Thu Jan 26 22:33:54 PST 2012
 * Fix for memcached_dump().
 * Additional testing for memcached_stat_execute().
index c3420b493b78141b50f8496594f13f00140197b5..16ce4beda0c2bbb28f45e83c12001f0463fe8e9c 100644 (file)
@@ -39,6 +39,7 @@ enum memcached_options {
   OPT_USERNAME,
   OPT_PASSWD,
   OPT_STAT_ARGS,
+  OPT_SERVER_VERSION,
   OPT_QUIET,
   OPT_FILE= 'f'
 };
index 8036ea186ada1b38a46aeb725ead246740d1e4cd..88221cf38ede6f9ca09e80c1130dab923e22cf86 100644 (file)
@@ -39,9 +39,10 @@ static void run_analyzer(memcached_st *memc, memcached_stat_st *memc_stat);
 static void print_analysis_report(memcached_st *memc,
                                   memcached_analysis_st *report);
 
-static int opt_verbose= 0;
-static int opt_displayflag= 0;
-static int opt_analyze= 0;
+static bool opt_binary= false;
+static bool opt_verbose= false;
+static bool opt_server_version= false;
+static bool opt_analyze= false;
 static char *opt_servers= NULL;
 static char *stat_args= NULL;
 static char *analyze_mode= NULL;
@@ -52,10 +53,11 @@ static struct option long_options[]=
   {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
   {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
   {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
-  {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
-  {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
+  {(OPTIONSTRING)"verbose", no_argument, NULL, OPT_VERBOSE},
+  {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
+  {(OPTIONSTRING)"debug", no_argument, NULL, OPT_DEBUG},
+  {(OPTIONSTRING)"server-version", no_argument, NULL, OPT_SERVER_VERSION},
   {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
-  {(OPTIONSTRING)"flag", no_argument, &opt_displayflag, OPT_FLAG},
   {(OPTIONSTRING)"analyze", optional_argument, NULL, OPT_ANALYZE},
   {0, 0, 0, 0},
 };
@@ -81,6 +83,18 @@ static memcached_return_t stat_printer(memcached_server_instance_st instance,
   return MEMCACHED_SUCCESS;
 }
 
+static memcached_return_t server_print_callback(const memcached_st *,
+                                                const memcached_server_st *instance,
+                                                void *)
+{
+  std::cerr << memcached_server_name(instance) << ":" << memcached_server_port(instance) <<
+    " " << int(instance->major_version) << 
+    "." << int(instance->minor_version) << 
+    "." << int(instance->micro_version) << std::endl;
+
+  return MEMCACHED_SUCCESS;
+}
+
 int main(int argc, char *argv[])
 {
   options_parse(argc, argv);
@@ -101,6 +115,7 @@ int main(int argc, char *argv[])
   }
 
   memcached_st *memc= memcached_create(NULL);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, opt_binary);
 
   memcached_server_st *servers= memcached_servers_parse(opt_servers);
   free(opt_servers);
@@ -108,21 +123,33 @@ int main(int argc, char *argv[])
   memcached_return_t rc= memcached_server_push(memc, servers);
   memcached_server_list_free(servers);
 
-  if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_SOME_ERRORS)
+  if (rc != MEMCACHED_SUCCESS and rc != MEMCACHED_SOME_ERRORS)
   {
     printf("Failure to communicate with servers (%s)\n",
            memcached_strerror(memc, rc));
-    exit(1);
+    exit(EXIT_FAILURE);
   }
 
-  if (opt_analyze)
+  if (opt_server_version)
   {
-    memcached_stat_st *memc_stat;
+    if (memcached_failed(memcached_version(memc)))
+    {
+      std::cerr << "Unable to obtain server version";
+      exit(EXIT_FAILURE);
+    }
 
-    memc_stat= memcached_stat(memc, NULL, &rc);
+    memcached_server_fn callbacks[1];
+    callbacks[0]= server_print_callback;
+    memcached_server_cursor(memc, callbacks, NULL,  1);
+  }
+  else if (opt_analyze)
+  {
+    memcached_stat_st *memc_stat= memcached_stat(memc, NULL, &rc);
 
-    if (! memc_stat)
-      exit(-1);
+    if (memc_stat == NULL)
+    {
+      exit(EXIT_FAILURE);
+    }
 
     run_analyzer(memc, memc_stat);
 
@@ -326,11 +353,19 @@ static void options_parse(int argc, char *argv[])
       break;
 
     case OPT_VERBOSE: /* --verbose or -v */
-      opt_verbose = OPT_VERBOSE;
+      opt_verbose= true;
       break;
 
     case OPT_DEBUG: /* --debug or -d */
-      opt_verbose = OPT_DEBUG;
+      opt_verbose= true;
+      break;
+
+    case OPT_BINARY:
+      opt_binary= true;
+      break;
+
+    case OPT_SERVER_VERSION:
+      opt_server_version= true;
       break;
 
     case OPT_VERSION: /* --version or -V */
index d0b3dba8f5038227ed7db86244649d2515ef6f1b..bae9407642ee56e23508d1e427c4d5b3c7d2d8b9 100644 (file)
@@ -103,6 +103,7 @@ static const char *lookup_help(memcached_options option)
   case OPT_PASSWD: return "Password to use for SASL authentication";
   case OPT_FILE: return "Path to file in which to save result";
   case OPT_STAT_ARGS: return "Argument for statistics";
+  case OPT_SERVER_VERSION: return "Memcached daemon software version";
   default:
                       break;
   };
index fbfb8555e975cb6d164b3b6ba1f5ac4cc7ca6a79..50fa77ae404dd256d0e9e2daa2c76d4e1fad60d2 100644 (file)
@@ -677,7 +677,7 @@ memcached_server_write_instance_st memcached_io_get_readable_server(memcached_st
   struct pollfd fds[MAX_SERVERS_TO_POLL];
   unsigned int host_index= 0;
 
-  for (uint32_t x= 0; x < memcached_server_count(memc) && host_index < MAX_SERVERS_TO_POLL; ++x)
+  for (uint32_t x= 0; x < memcached_server_count(memc) and host_index < MAX_SERVERS_TO_POLL; ++x)
   {
     memcached_server_write_instance_st instance= memcached_server_instance_fetch(memc, x);
 
@@ -728,11 +728,12 @@ memcached_server_write_instance_st memcached_io_get_readable_server(memcached_st
       {
         for (uint32_t y= 0; y < memcached_server_count(memc); ++y)
         {
-          memcached_server_write_instance_st instance=
-            memcached_server_instance_fetch(memc, y);
+          memcached_server_write_instance_st instance= memcached_server_instance_fetch(memc, y);
 
           if (instance->fd == fds[x].fd)
+          {
             return instance;
+          }
         }
       }
     }
index b840e9d7037a1a8a5cfe0b81674242f0bbb6f7ea..69ac26a4ac54ae6fa1057a8910f7013f6e7c7363 100644 (file)
@@ -38,7 +38,7 @@
 #include <libmemcached/common.h>
 #include <libmemcached/string.hpp>
 
-static memcached_return_t textual_value_fetch(memcached_server_write_instance_st ptr,
+static memcached_return_t textual_value_fetch(memcached_server_write_instance_st instance,
                                               char *buffer,
                                               memcached_result_st *result)
 {
@@ -46,7 +46,7 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
   ssize_t read_length= 0;
   size_t value_length;
 
-  WATCHPOINT_ASSERT(ptr->root);
+  WATCHPOINT_ASSERT(instance->root);
   char *end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;
 
   memcached_result_reset(result);
@@ -57,13 +57,10 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
 
   /* We load the key */
   {
-    char *key;
-    size_t prefix_length;
-
-    key= result->item_key;
+    char *key= result->item_key;
     result->key_length= 0;
 
-    for (prefix_length= memcached_array_size(ptr->root->_namespace); !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++)
+    for (size_t prefix_length= memcached_array_size(instance->root->_namespace); !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++)
     {
       if (prefix_length == 0)
       {
@@ -133,7 +130,7 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
   /* We add two bytes so that we can walk the \r\n */
   if (memcached_failed(memcached_string_check(&result->value, value_length +2)))
   {
-    return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
   }
 
   {
@@ -146,11 +143,11 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
       some people lazy about using the return length.
     */
     size_t to_read= (value_length) + 2;
-    memcached_return_t rrc= memcached_io_read(ptr, value_ptr, to_read, read_length);
+    memcached_return_t rrc= memcached_io_read(instance, value_ptr, to_read, read_length);
     if (memcached_failed(rrc) and rrc == MEMCACHED_IN_PROGRESS)
     {
-      memcached_quit_server(ptr, true);
-      return memcached_set_error(*ptr, MEMCACHED_IN_PROGRESS, MEMCACHED_AT);
+      memcached_quit_server(instance, true);
+      return memcached_set_error(*instance, MEMCACHED_IN_PROGRESS, MEMCACHED_AT);
     }
     else if (memcached_failed(rrc))
     {
@@ -175,7 +172,7 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
   return MEMCACHED_SUCCESS;
 
 read_error:
-  memcached_io_reset(ptr);
+  memcached_io_reset(instance);
 
   return MEMCACHED_PARTIAL_READ;
 }
@@ -447,14 +444,14 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta
                              buffer, total_read);
 }
 
-static memcached_return_t binary_read_one_response(memcached_server_write_instance_st ptr,
+static memcached_return_t binary_read_one_response(memcached_server_write_instance_st instance,
                                                    char *buffer, const size_t buffer_length,
                                                    memcached_result_st *result)
 {
   memcached_return_t rc;
   protocol_binary_response_header header;
 
-  if ((rc= memcached_safe_read(ptr, &header.bytes, sizeof(header.bytes))) != MEMCACHED_SUCCESS)
+  if ((rc= memcached_safe_read(instance, &header.bytes, sizeof(header.bytes))) != MEMCACHED_SUCCESS)
   {
     WATCHPOINT_ERROR(rc);
     return rc;
@@ -462,7 +459,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
 
   if (header.response.magic != PROTOCOL_BINARY_RES)
   {
-    return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+    return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
   }
 
   /*
@@ -484,7 +481,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
        * We didn't increment the response counter for the GETKQ packet
        * (only the final NOOP), so we need to increment the counter again.
        */
-      memcached_server_response_increment(ptr);
+      memcached_server_response_increment(instance);
       /* FALLTHROUGH */
     case PROTOCOL_BINARY_CMD_GETK:
       {
@@ -492,7 +489,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
         memcached_result_reset(result);
         result->item_cas= header.response.cas;
 
-        if ((rc= memcached_safe_read(ptr, &result->item_flags, sizeof (result->item_flags))) != MEMCACHED_SUCCESS)
+        if ((rc= memcached_safe_read(instance, &result->item_flags, sizeof (result->item_flags))) != MEMCACHED_SUCCESS)
         {
           WATCHPOINT_ERROR(rc);
           return MEMCACHED_UNKNOWN_READ_FAILURE;
@@ -502,7 +499,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
         bodylen -= header.response.extlen;
 
         result->key_length= keylen;
-        if (memcached_failed(rc= memcached_safe_read(ptr, result->item_key, keylen)))
+        if (memcached_failed(rc= memcached_safe_read(instance, result->item_key, keylen)))
         {
           WATCHPOINT_ERROR(rc);
           return MEMCACHED_UNKNOWN_READ_FAILURE;
@@ -511,15 +508,15 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
         // Only bother with doing this if key_length > 0
         if (result->key_length)
         {
-          if (memcached_array_size(ptr->root->_namespace) and memcached_array_size(ptr->root->_namespace) >= result->key_length)
+          if (memcached_array_size(instance->root->_namespace) and memcached_array_size(instance->root->_namespace) >= result->key_length)
           {
-            return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+            return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
           }
 
-          if (memcached_array_size(ptr->root->_namespace))
+          if (memcached_array_size(instance->root->_namespace))
           {
-            result->key_length-= memcached_array_size(ptr->root->_namespace);
-            memmove(result->item_key, result->item_key +memcached_array_size(ptr->root->_namespace), result->key_length);
+            result->key_length-= memcached_array_size(instance->root->_namespace);
+            memmove(result->item_key, result->item_key +memcached_array_size(instance->root->_namespace), result->key_length);
           }
         }
 
@@ -530,7 +527,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
         }
 
         char *vptr= memcached_string_value_mutable(&result->value);
-        if (memcached_failed(rc= memcached_safe_read(ptr, vptr, bodylen)))
+        if (memcached_failed(rc= memcached_safe_read(instance, vptr, bodylen)))
         {
           WATCHPOINT_ERROR(rc);
           return MEMCACHED_UNKNOWN_READ_FAILURE;
@@ -546,11 +543,11 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
         if (bodylen != sizeof(uint64_t))
         {
           result->numeric_value= UINT64_MAX;
-          return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+          return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
         }
 
         uint64_t val;
-        if ((rc= memcached_safe_read(ptr, &val, sizeof(val))) != MEMCACHED_SUCCESS)
+        if ((rc= memcached_safe_read(instance, &val, sizeof(val))) != MEMCACHED_SUCCESS)
         {
           result->numeric_value= UINT64_MAX;
           return MEMCACHED_UNKNOWN_READ_FAILURE;
@@ -563,19 +560,41 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
     case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS:
     case PROTOCOL_BINARY_CMD_VERSION:
       {
-        memset(buffer, 0, buffer_length);
-        if (bodylen >= buffer_length)
+        char version_buffer[32]; // @todo document this number
+        memset(version_buffer, 0, sizeof(version_buffer));
+
+        if (memcached_safe_read(instance, version_buffer, bodylen) != MEMCACHED_SUCCESS)
         {
-          /* not enough space in buffer.. should not happen... */
           return MEMCACHED_UNKNOWN_READ_FAILURE;
         }
-        else if ((rc= memcached_safe_read(ptr, buffer, bodylen)) != MEMCACHED_SUCCESS)
+
+        char *p;
+        long int version= strtol(version_buffer, &p, 10);
+        if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX or version == 0)
         {
-          WATCHPOINT_ERROR(rc);
-          return MEMCACHED_UNKNOWN_READ_FAILURE;
+          instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
+          return memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse major version"));
+        }
+        instance->major_version= uint8_t(version);
+
+        version= strtol(p +1, &p, 10);
+        if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX)
+        {
+          instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
+          return memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
+        }
+        instance->minor_version= uint8_t(version);
+
+        version= strtol(p + 1, NULL, 10);
+        if (errno == ERANGE)
+        {
+          instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
+          return memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
         }
+        instance->micro_version= uint8_t(version);
       }
       break;
+
     case PROTOCOL_BINARY_CMD_FLUSH:
     case PROTOCOL_BINARY_CMD_QUIT:
     case PROTOCOL_BINARY_CMD_SET:
@@ -611,8 +630,8 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
         {
           size_t keylen= header.response.keylen;
           memset(buffer, 0, buffer_length);
-          if ((rc= memcached_safe_read(ptr, buffer, keylen)) != MEMCACHED_SUCCESS ||
-              (rc= memcached_safe_read(ptr, buffer + keylen + 1, bodylen - keylen)) != MEMCACHED_SUCCESS)
+          if ((rc= memcached_safe_read(instance, buffer, keylen)) != MEMCACHED_SUCCESS ||
+              (rc= memcached_safe_read(instance, buffer + keylen + 1, bodylen - keylen)) != MEMCACHED_SUCCESS)
           {
             WATCHPOINT_ERROR(rc);
             return MEMCACHED_UNKNOWN_READ_FAILURE;
@@ -632,7 +651,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
           return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
 
         char *vptr= memcached_string_value_mutable(&result->value);
-        if ((rc= memcached_safe_read(ptr, vptr, bodylen)) != MEMCACHED_SUCCESS)
+        if ((rc= memcached_safe_read(instance, vptr, bodylen)) != MEMCACHED_SUCCESS)
         {
           WATCHPOINT_ERROR(rc);
           return MEMCACHED_UNKNOWN_READ_FAILURE;
@@ -644,7 +663,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
     default:
       {
         /* Command not implemented yet! */
-        return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+        return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
       }
     }
   }
@@ -655,10 +674,10 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
     while (bodylen > 0)
     {
       size_t nr= (bodylen > SMALL_STRING_LEN) ? SMALL_STRING_LEN : bodylen;
-      if ((rc= memcached_safe_read(ptr, hole, nr)) != MEMCACHED_SUCCESS)
+      if ((rc= memcached_safe_read(instance, hole, nr)) != MEMCACHED_SUCCESS)
       {
         WATCHPOINT_ERROR(rc);
-        return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+        return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
       }
       bodylen-= (uint32_t) nr;
     }
@@ -674,7 +693,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
     case PROTOCOL_BINARY_CMD_REPLACEQ:
     case PROTOCOL_BINARY_CMD_APPENDQ:
     case PROTOCOL_BINARY_CMD_PREPENDQ:
-      return binary_read_one_response(ptr, buffer, buffer_length, result);
+      return binary_read_one_response(instance, buffer, buffer_length, result);
 
     default:
       break;
@@ -717,7 +736,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
     case PROTOCOL_BINARY_RESPONSE_EINVAL:
     case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND:
     default:
-      return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+      return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
       break;
     }
   }
@@ -725,72 +744,72 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
   return rc;
 }
 
-static memcached_return_t _read_one_response(memcached_server_write_instance_st ptr,
+static memcached_return_t _read_one_response(memcached_server_write_instance_st instance,
                                              char *buffer, const size_t buffer_length,
                                              memcached_result_st *result)
 {
-  memcached_server_response_decrement(ptr);
+  memcached_server_response_decrement(instance);
 
   if (result == NULL)
   {
-    memcached_st *root= (memcached_st *)ptr->root;
+    memcached_st *root= (memcached_st *)instance->root;
     result = &root->result;
   }
 
   memcached_return_t rc;
-  if (memcached_is_binary(ptr->root))
+  if (memcached_is_binary(instance->root))
   {
-    rc= binary_read_one_response(ptr, buffer, buffer_length, result);
+    rc= binary_read_one_response(instance, buffer, buffer_length, result);
   }
   else
   {
-    rc= textual_read_one_response(ptr, buffer, buffer_length, result);
+    rc= textual_read_one_response(instance, buffer, buffer_length, result);
     assert(rc != MEMCACHED_PROTOCOL_ERROR);
   }
 
   if (memcached_fatal(rc))
   {
-    memcached_io_reset(ptr);
+    memcached_io_reset(instance);
   }
 
   return rc;
 }
 
-memcached_return_t memcached_read_one_response(memcached_server_write_instance_st ptr,
+memcached_return_t memcached_read_one_response(memcached_server_write_instance_st instance,
                                                memcached_result_st *result)
 {
   char buffer[SMALL_STRING_LEN];
 
-  if (memcached_is_udp(ptr->root))
+  if (memcached_is_udp(instance->root))
   {
-    return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
+    return memcached_set_error(*instance, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
   }
 
 
-  return _read_one_response(ptr, buffer, sizeof(buffer), result);
+  return _read_one_response(instance, buffer, sizeof(buffer), result);
 }
 
-memcached_return_t memcached_response(memcached_server_write_instance_st ptr,
+memcached_return_t memcached_response(memcached_server_write_instance_st instance,
                                       memcached_result_st *result)
 {
   char buffer[1024];
 
-  return memcached_response(ptr, buffer, sizeof(buffer), result);
+  return memcached_response(instance, buffer, sizeof(buffer), result);
 }
 
-memcached_return_t memcached_response(memcached_server_write_instance_st ptr,
+memcached_return_t memcached_response(memcached_server_write_instance_st instance,
                                       char *buffer, size_t buffer_length,
                                       memcached_result_st *result)
 {
-  if (memcached_is_udp(ptr->root))
+  if (memcached_is_udp(instance->root))
   {
-    return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
+    return memcached_set_error(*instance, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
   }
 
   /* We may have old commands in the buffer not set, first purge */
-  if ((ptr->root->flags.no_block) and (memcached_is_processing_input(ptr->root) == false))
+  if ((instance->root->flags.no_block) and (memcached_is_processing_input(instance->root) == false))
   {
-    (void)memcached_io_write(ptr);
+    (void)memcached_io_write(instance);
   }
 
   /*
@@ -798,16 +817,16 @@ memcached_return_t memcached_response(memcached_server_write_instance_st ptr,
    * returned the last one. Purge all pending messages to ensure backwards
    * compatibility.
  */
-  if (memcached_is_binary(ptr->root) == false and memcached_server_response_count(ptr) > 1)
+  if (memcached_is_binary(instance->root) == false and memcached_server_response_count(instance) > 1)
   {
     memcached_result_st junked_result;
-    memcached_result_st *junked_result_ptr= memcached_result_create(ptr->root, &junked_result);
+    memcached_result_st *junked_result_ptr= memcached_result_create(instance->root, &junked_result);
 
     assert(junked_result_ptr);
 
-    while (memcached_server_response_count(ptr) > 1)
+    while (memcached_server_response_count(instance) > 1)
     {
-      memcached_return_t rc= _read_one_response(ptr, buffer, buffer_length, junked_result_ptr);
+      memcached_return_t rc= _read_one_response(instance, buffer, buffer_length, junked_result_ptr);
 
       // @TODO should we return an error on another but a bad read case?
       if (memcached_fatal(rc))
@@ -819,5 +838,5 @@ memcached_return_t memcached_response(memcached_server_write_instance_st ptr,
     memcached_result_free(junked_result_ptr);
   }
 
-  return _read_one_response(ptr, buffer, buffer_length, result);
+  return _read_one_response(instance, buffer, buffer_length, result);
 }
index 961f6916096bbf3aa64c8fa7211b3559a121b385..7fc85fd432fd7a6ebb636105f0b8f591d9131b3a 100644 (file)
@@ -89,6 +89,7 @@ static inline memcached_return_t memcached_version_binary(memcached_st *ptr)
     { request.bytes, sizeof(request.bytes) }
   };
 
+  uint32_t success= 0;
   bool errors_happened= false;
   for (uint32_t x= 0; x < memcached_server_count(ptr); x++) 
   {
@@ -106,59 +107,23 @@ static inline memcached_return_t memcached_version_binary(memcached_st *ptr)
       errors_happened= true;
       continue;
     }
+
+    success++;
   }
 
-  for (uint32_t x= 0; x < memcached_server_count(ptr); x++) 
+  if (success)
   {
-    memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
-
-    if (instance->major_version != UINT8_MAX)
-    {
-      continue;
-    }
-
-    if (memcached_server_response_count(instance) > 0) 
+    // Collect the returned items
+    memcached_server_write_instance_st instance;
+    while ((instance= memcached_io_get_readable_server(ptr)))
     {
       char buffer[32];
-      char *p;
-
       memcached_return_t rrc= memcached_response(instance, buffer, sizeof(buffer), NULL);
       if (memcached_failed(rrc))
       {
         memcached_io_reset(instance);
         errors_happened= true;
-        continue;
-      }
-
-      long int version= strtol(buffer, &p, 10);
-      if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX or version == 0)
-      {
-        memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse major version"));
-        instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
-        errors_happened= true;
-        continue;
-      }
-      instance->major_version= uint8_t(version);
-
-      version= strtol(p +1, &p, 10);
-      if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX)
-      {
-        memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
-        instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
-        errors_happened= true;
-        continue;
-      }
-      instance->minor_version= uint8_t(version);
-
-      version= strtol(p + 1, NULL, 10);
-      if (errno == ERANGE)
-      {
-        memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
-        instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
-        errors_happened= true;
-        continue;
       }
-      instance->micro_version= uint8_t(version);
     }
   }
 
index ec7dd4f88cd6d30de2d2040236367e7ab431a30b..33a14e334eeb45624c0ce8a2dd8270848e41dbee 100644 (file)
@@ -70,21 +70,31 @@ static test_return_t help_test(void *)
   return TEST_SUCCESS;
 }
 
-static test_return_t ascii_test(void *)
+static test_return_t binary_TEST(void *)
 {
   char buffer[1024];
-  snprintf(buffer, sizeof(buffer), "-%d", int(default_port()));
-  const char *args[]= { "--quiet", buffer, " -a ", 0 };
+  snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(default_port()));
+  const char *args[]= { "--quiet", buffer, " --binary ", 0 };
 
   test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
 }
 
-static test_return_t binary_test(void *)
+static test_return_t server_version_TEST(void *)
 {
   char buffer[1024];
-  snprintf(buffer, sizeof(buffer), "-p %d", int(default_port()));
-  const char *args[]= { "--quiet", buffer, " -b ", 0 };
+  snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(default_port()));
+  const char *args[]= { "--quiet", buffer, " --server-version", 0 };
+
+  test_true(exec_cmdline(executable, args));
+  return TEST_SUCCESS;
+}
+
+static test_return_t binary_server_version_TEST(void *)
+{
+  char buffer[1024];
+  snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(default_port()));
+  const char *args[]= { "--quiet", buffer, " --binary --server-version", 0 };
 
   test_true(exec_cmdline(executable, args));
   return TEST_SUCCESS;
@@ -93,8 +103,9 @@ static test_return_t binary_test(void *)
 test_st memstat_tests[] ={
   {"--quiet", 0, quiet_test},
   {"--help", 0, help_test},
-  {"-a, ascii", 0, ascii_test},
-  {"-b, binary", 0, binary_test},
+  {"--binary", 0, binary_TEST},
+  {"--server-version", 0, server_version_TEST},
+  {"--binary --server-version", 0, binary_server_version_TEST},
   {0, 0, 0}
 };