Merge from build trunk.
authorBrian Aker <brian@tangent.org>
Wed, 4 Jan 2012 05:59:51 +0000 (21:59 -0800)
committerBrian Aker <brian@tangent.org>
Wed, 4 Jan 2012 05:59:51 +0000 (21:59 -0800)
56 files changed:
clients/client_options.h
clients/execute.cc
clients/memcp.cc
clients/memslap.cc
clients/utilities.cc
configure.ac
libmemcached-1.0/struct/memcached.h
libmemcached/assert.hpp
libmemcached/auto.cc
libmemcached/backtrace.cc
libmemcached/backtrace.hpp
libmemcached/behavior.cc
libmemcached/common.h
libmemcached/connect.cc
libmemcached/delete.cc
libmemcached/do.cc
libmemcached/do.hpp
libmemcached/dump.cc
libmemcached/error.cc
libmemcached/exist.cc
libmemcached/fetch.cc
libmemcached/flush.cc
libmemcached/flush_buffers.cc
libmemcached/get.cc
libmemcached/include.am
libmemcached/initialize_query.cc
libmemcached/initialize_query.h
libmemcached/io.cc
libmemcached/io.h
libmemcached/io.hpp
libmemcached/is.h
libmemcached/key.cc
libmemcached/memcached.cc
libmemcached/purge.cc
libmemcached/quit.cc
libmemcached/response.cc
libmemcached/response.h
libmemcached/sasl.cc
libmemcached/server.cc
libmemcached/server_list.cc
libmemcached/stats.cc
libmemcached/storage.cc
libmemcached/touch.cc
libmemcached/udp.cc [new file with mode: 0644]
libmemcached/udp.hpp [new file with mode: 0644]
libmemcached/verbosity.cc
libmemcached/version.cc
libmemcachedutil/pid.cc
libtest/run.gdb
m4/ax_cxx_gcc_abi_demangle.m4 [new file with mode: 0644]
tests/include.am
tests/libmemcached-1.0/include.am
tests/libmemcached-1.0/mem_functions.cc
tests/libmemcached-1.0/parser.cc
tests/mem_udp.cc
util/instance.cc

index 57aefd2bb4d366c29054611f56230a2c74e93a5d..c3420b493b78141b50f8496594f13f00140197b5 100644 (file)
@@ -35,6 +35,7 @@ enum memcached_options {
   OPT_HASH,
   OPT_BINARY,
   OPT_UDP,
+  OPT_BUFFER,
   OPT_USERNAME,
   OPT_PASSWD,
   OPT_STAT_ARGS,
index 1ada836f0345c61e82df361d3549618a7750dc19..b276954533e1b119375cd3aba183886dfbf30d21 100644 (file)
@@ -15,7 +15,7 @@
 */
 
 #include <config.h>
-#include "execute.h"
+#include "clients/execute.h"
 
 unsigned int execute_set(memcached_st *memc, pairs_st *pairs, unsigned int number_of)
 {
@@ -27,10 +27,15 @@ unsigned int execute_set(memcached_st *memc, pairs_st *pairs, unsigned int numbe
     memcached_return_t rc= memcached_set(memc, pairs[x].key, pairs[x].key_length,
                                          pairs[x].value, pairs[x].value_length,
                                          0, 0);
-    if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED)
+    if (rc != MEMCACHED_SUCCESS and rc != MEMCACHED_BUFFERED)
     {
-      fprintf(stderr, "Failured on insert of %.*s\n",
+      fprintf(stderr, "%s:%d Failure on insert (%s) of %.*s\n",
+              __FILE__, __LINE__,
+              memcached_last_error_message(memc),
               (unsigned int)pairs[x].key_length, pairs[x].key);
+      
+      // We will try to reconnect and see if that fixes the issue
+      memcached_quit(memc);
     }
     else
     {
@@ -54,23 +59,27 @@ unsigned int execute_get(memcached_st *memc, pairs_st *pairs, unsigned int numbe
 
   for (retrieved= 0,x= 0; x < number_of; x++)
   {
-    char *value;
     size_t value_length;
     uint32_t flags;
-    unsigned int fetch_key;
 
-    fetch_key= (unsigned int)((unsigned int)random() % number_of);
+    unsigned int fetch_key= (unsigned int)((unsigned int)random() % number_of);
 
-    value= memcached_get(memc, pairs[fetch_key].key, pairs[fetch_key].key_length,
-                         &value_length, &flags, &rc);
+    char *value= memcached_get(memc, pairs[fetch_key].key, pairs[fetch_key].key_length,
+                               &value_length, &flags, &rc);
 
     if (rc != MEMCACHED_SUCCESS)
-      fprintf(stderr, "Failured on read of %.*s\n",
+    {
+      fprintf(stderr, "%s:%d Failure on read(%s) of %.*s\n",
+              __FILE__, __LINE__,
+              memcached_last_error_message(memc),
               (unsigned int)pairs[fetch_key].key_length, pairs[fetch_key].key);
+    }
     else
+    {
       retrieved++;
+    }
 
-    free(value);
+    ::free(value);
   }
 
   return retrieved;
@@ -116,7 +125,8 @@ unsigned int execute_mget(memcached_st *memc,
     rc= memcached_fetch_execute(memc, callbacks, (void *)&retrieved, 1);
     if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_NOTFOUND && rc != MEMCACHED_END)
     {
-      fprintf(stderr, "Failed to execute mget: %s\n",
+      fprintf(stderr, "%s:%d Failed to execute mget: %s\n",
+              __FILE__, __LINE__,
               memcached_strerror(memc, rc));
       memcached_quit(memc);
       return 0;
@@ -124,7 +134,8 @@ unsigned int execute_mget(memcached_st *memc,
   }
   else
   {
-    fprintf(stderr, "Failed to execute mget: %s\n",
+    fprintf(stderr, "%s:%d Failed to execute mget: %s\n",
+            __FILE__, __LINE__,
             memcached_strerror(memc, rc));
     memcached_quit(memc);
     return 0;
index 4f4f8e1097243ac10e4a754ae244a3ae54dca6f7..5422aa7386cbbe7a4b9f36a1bc31ba2a37647b5f 100644 (file)
@@ -42,6 +42,8 @@
 static void options_parse(int argc, char *argv[]);
 
 static bool opt_binary= false;
+static bool opt_udp= false;
+static bool opt_buffer= false;
 static int opt_verbose= 0;
 static char *opt_servers= NULL;
 static char *opt_hash= NULL;
@@ -61,8 +63,8 @@ static long strtol_wrapper(const char *nptr, int base, bool *error)
 
   /* Check for various possible errors */
 
-  if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
-      || (errno != 0 && val == 0))
+  if ((errno == ERANGE and (val == LONG_MAX or val == LONG_MIN))
+      or (errno != 0 && val == 0))
   {
     *error= true;
     return EXIT_SUCCESS;
@@ -85,6 +87,37 @@ int main(int argc, char *argv[])
   initialize_sockets();
 
   memcached_st *memc= memcached_create(NULL);
+
+  if (opt_udp)
+  {
+    if (opt_verbose)
+    {
+      std::cout << "Enabling UDP" << std::endl;
+    }
+
+    if (memcached_failed(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, opt_udp)))
+    {
+      memcached_free(memc);
+      std::cerr << "Could not enable UDP protocol." << std::endl;
+      return EXIT_FAILURE;
+    }
+  }
+
+  if (opt_buffer)
+  {
+    if (opt_verbose)
+    {
+      std::cout << "Enabling MEMCACHED_BEHAVIOR_BUFFER_REQUESTS" << std::endl;
+    }
+
+    if (memcached_failed(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, opt_buffer)))
+    {
+      memcached_free(memc);
+      std::cerr << "Could not enable MEMCACHED_BEHAVIOR_BUFFER_REQUESTS." << std::endl;
+      return EXIT_FAILURE;
+    }
+  }
+
   process_hash_option(memc, opt_hash);
 
   if (opt_servers == NULL)
@@ -114,9 +147,7 @@ int main(int argc, char *argv[])
 
   memcached_server_push(memc, servers);
   memcached_server_list_free(servers);
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
-                         (uint64_t)opt_binary);
-
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, opt_binary);
   if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
   {
     memcached_free(memc);
@@ -143,7 +174,7 @@ int main(int argc, char *argv[])
     {
       if (opt_verbose)
       {
-        fprintf(stderr, "memcp: %s: %s\n", argv[optind], strerror(errno));
+        std::cerr << "memcp " << argv[optind] << " " << strerror(errno) << std::endl;
         optind++;
       }
       exit_code= EXIT_FAILURE;
@@ -175,59 +206,65 @@ int main(int argc, char *argv[])
     char *file_buffer_ptr;
     if ((file_buffer_ptr= (char *)malloc(sizeof(char) * (size_t)sbuf.st_size)) == NULL)
     {
-      fprintf(stderr, "malloc: %s\n", strerror(errno));
+      std::cerr << "Error allocating file buffer(" << strerror(errno) << ")" << std::endl;
       exit(EXIT_FAILURE);
     }
 
     ssize_t read_length;
-    if ((read_length= read(fd, file_buffer_ptr, (size_t)sbuf.st_size)) == -1)
+    if ((read_length= ::read(fd, file_buffer_ptr, (size_t)sbuf.st_size)) == -1)
     {
-      fprintf(stderr, "read: %s\n", strerror(errno));
+      std::cerr << "Error while reading file " << file_buffer_ptr << " (" << strerror(errno) << ")" << std::endl;
       exit(EXIT_FAILURE);
     }
 
     if (read_length != sbuf.st_size)
     {
-      fprintf(stderr, "Failure reading from file\n");
-      exit(1);
+      std::cerr << "Failure while reading file. Read length was not equal to stat() length" << std::endl;
+      exit(EXIT_FAILURE);
     }
 
     memcached_return_t rc;
     if (opt_method == OPT_ADD)
+    {
       rc= memcached_add(memc, ptr, strlen(ptr),
                         file_buffer_ptr, (size_t)sbuf.st_size,
                        opt_expires, opt_flags);
+    }
     else if (opt_method == OPT_REPLACE)
+    {
       rc= memcached_replace(memc, ptr, strlen(ptr),
                            file_buffer_ptr, (size_t)sbuf.st_size,
                            opt_expires, opt_flags);
+    }
     else
+    {
       rc= memcached_set(memc, ptr, strlen(ptr),
                         file_buffer_ptr, (size_t)sbuf.st_size,
                         opt_expires, opt_flags);
+    }
 
-    if (rc != MEMCACHED_SUCCESS)
+    if (memcached_failed(rc))
     {
-      fprintf(stderr, "memcp: %s: memcache error %s",
-             ptr, memcached_strerror(memc, rc));
-      if (memcached_last_error_errno(memc))
-       fprintf(stderr, " system error %s", strerror(memcached_last_error_errno(memc)));
-      fprintf(stderr, "\n");
-
+      std::cerr << "Error occrrured during operation: " << memcached_last_error_message(memc) << std::endl;
       exit_code= EXIT_FAILURE;
     }
 
-    free(file_buffer_ptr);
-    close(fd);
+    ::free(file_buffer_ptr);
+    ::close(fd);
     optind++;
   }
 
   memcached_free(memc);
 
   if (opt_servers)
+  {
     free(opt_servers);
+  }
+
   if (opt_hash)
+  {
     free(opt_hash);
+  }
 
   return exit_code;
 }
@@ -244,6 +281,8 @@ static void options_parse(int argc, char *argv[])
       {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
       {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
       {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
+      {(OPTIONSTRING)"udp", no_argument, NULL, OPT_UDP},
+      {(OPTIONSTRING)"buffer", no_argument, NULL, OPT_BUFFER},
       {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
       {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
       {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
@@ -274,6 +313,7 @@ static void options_parse(int argc, char *argv[])
     {
     case 0:
       break;
+
     case OPT_BINARY:
       opt_binary= true;
       break;
@@ -350,6 +390,14 @@ static void options_parse(int argc, char *argv[])
       close_stdio();
       break;
 
+    case OPT_UDP:
+      opt_udp= true;
+      break;
+
+    case OPT_BUFFER:
+      opt_buffer= true;
+      break;
+
     case '?':
       /* getopt_long already printed an error message. */
       exit(1);
index f00ba45764ed24bf43b3e762dbe5dab0b9668dca..a8c0da1ed7b61a531dbbe66cbc86682eae2b22e6 100644 (file)
@@ -53,6 +53,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <iostream>
+
 #include <libmemcached/memcached.h>
 
 #include "client_options.h"
@@ -152,7 +154,7 @@ static unsigned int opt_createial_load= 0;
 static unsigned int opt_concurrency= 0;
 static int opt_displayflag= 0;
 static char *opt_servers= NULL;
-static int opt_udp_io= 0;
+static bool opt_udp_io= false;
 test_t opt_test= SET_TEST;
 
 extern "C" {
@@ -243,26 +245,31 @@ void scheduler(memcached_server_st *servers, conclusions_st *conclusion)
 
   memcached_st *memc= memcached_create(NULL);
 
+  memcached_server_push(memc, servers);
+
   /* We need to set udp behavior before adding servers to the client */
   if (opt_udp_io)
   {
-    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP,
-                           (uint64_t)opt_udp_io);
-    for (uint32_t x= 0; x < memcached_server_list_count(servers); x++ )
+    if (memcached_failed(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, opt_udp_io)))
     {
-      servers[x].type= MEMCACHED_CONNECTION_UDP;
+      std::cerr << "Failed to enable UDP." << std::endl;
+      memcached_free(memc);
+      exit(EXIT_FAILURE);
     }
   }
-  memcached_server_push(memc, servers);
 
   memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
                          (uint64_t)opt_binary);
 
   if (opt_flush)
+  {
     flush_all(memc);
+  }
 
   if (opt_createial_load)
+  {
     pairs= load_create_data(memc, opt_createial_load, &actual_loaded);
+  }
 
   char **keys= static_cast<char **>(calloc(actual_loaded, sizeof(char*)));
   size_t *key_lengths= static_cast<size_t *>(calloc(actual_loaded, sizeof(size_t)));
@@ -399,7 +406,7 @@ void options_parse(int argc, char *argv[])
                   "does not currently support get ops.\n");
         exit(1);
       }
-      opt_udp_io= 1;
+      opt_udp_io= true;
       break;
 
     case OPT_BINARY:
index 79f2f2aebcda1560a4750bc7f11175924fa1d0d3..d0b3dba8f5038227ed7db86244649d2515ef6f1b 100644 (file)
@@ -98,6 +98,7 @@ static const char *lookup_help(memcached_options option)
   case OPT_BINARY: return("Switch to binary protocol.");
   case OPT_ANALYZE: return("Analyze the provided servers.");
   case OPT_UDP: return("Use UDP protocol when communicating with server.");
+  case OPT_BUFFER: return("Enable request buffering.");
   case OPT_USERNAME: return "Username to use for SASL authentication";
   case OPT_PASSWD: return "Password to use for SASL authentication";
   case OPT_FILE: return "Path to file in which to save result";
index 883fa3c4c9d7e9ce7f40cc203f74b7f49debb215..602b4520bec8dc6bd55d44ea5f89808b9eb128ee 100644 (file)
@@ -127,6 +127,10 @@ AC_CHECK_HEADERS([netinet/in.h])
 AC_CHECK_HEADERS([stddef.h])
 AC_CHECK_HEADERS([sys/time.h])
 AC_CHECK_HEADERS([sasl/sasl.h])
+AC_CHECK_HEADERS([execinfo.h])
+AC_CHECK_HEADERS([cxxabi.h], 
+       AC_DEFINE([HAVE_CXXABI_H], [1], [Have cxxabi.h]),
+       AC_DEFINE([HAVE_CXXABI_H], [0], [Have cxxabi.h]))
 AC_CXX_HEADER_STDCXX_98
 
 AC_FUNC_ALLOCA
@@ -154,6 +158,8 @@ AC_C_INLINE
 AC_C_VOLATILE
 AC_C_RESTRICT
 
+AX_CXX_GCC_ABI_DEMANGLE
+
 dnl The sasl functions should only be visible if we build with sasl support
 AS_IF([test "x$ac_cv_sasl" = "xyes"],
       [
index 152f310330c8402428df3500a5a39731372c2269..564eb74e55b9c825252a2cf16dd6eed16c5db8cb 100644 (file)
@@ -54,7 +54,7 @@ struct memcached_st {
     bool buffer_requests:1;
     bool hash_with_namespace:1;
     bool no_block:1; // Don't block
-    bool no_reply:1;
+    bool reply:1;
     bool randomize_replica_read:1;
     bool support_cas:1;
     bool tcp_nodelay:1;
index 787d844adb414e51a165af7a0d382b85fe7a3b5e..6858879c180faeddc8f33608224c2e5135d21593 100644 (file)
@@ -49,7 +49,7 @@ do \
 { \
   if (not (__expr)) \
   { \
-    fprintf(stderr, "\nAssertion \"%s\" failed for function \"%s\" likely for %s, at %s:%d\n", #__expr, __func__, (#__mesg),  __FILE__, __LINE__);\
+    fprintf(stderr, "\n%s:%d Assertion \"%s\" failed for function \"%s\" likely for %s\n", __FILE__, __LINE__, #__expr, __func__, (#__mesg));\
     custom_backtrace(); \
     abort(); \
   } \
index b2e4f534def078ece54f55682561b3b0eb765eac..28550a18c1e73940a36523122fde7d416d002770 100644 (file)
 
 #include <libmemcached/common.h>
 
-static memcached_return_t text_incr_decr(memcached_st *ptr,
-                                         const char *verb,
-                                         const char *group_key, size_t group_key_length,
+static memcached_return_t text_incr_decr(memcached_server_write_instance_st instance,
+                                         const bool is_incr,
                                          const char *key, size_t key_length,
-                                         uint64_t offset,
-                                         uint64_t *value)
+                                         const uint64_t offset,
+                                         const bool reply,
+                                         uint64_t& numeric_value)
 {
   char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-  uint32_t server_key;
-  memcached_server_write_instance_st instance;
-  bool no_reply= ptr->flags.no_reply;
 
-  if (memcached_failed(memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
+  int send_length= snprintf(buffer, sizeof(buffer), " %" PRIu64, offset);
+  if (size_t(send_length) >= sizeof(buffer) or send_length < 0)
   {
-    return memcached_set_error(*ptr, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT);
+    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                               memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
   }
 
-  server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
-  instance= memcached_server_instance_fetch(ptr, server_key);
+  libmemcached_io_vector_st vector[]=
+  {
+    { NULL, 0 },
+    { memcached_literal_param("incr ") },
+    { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
+    { key, key_length },
+    { buffer, send_length },
+    { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
+    { memcached_literal_param("\r\n") }
+  };
 
-  int send_length;
-  send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
-                        "%s %.*s%.*s %" PRIu64 "%s\r\n", verb,
-                        memcached_print_array(ptr->_namespace),
-                        (int)key_length, key,
-                        offset, no_reply ? " noreply" : "");
-  if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0)
+  if (is_incr == false)
   {
-    return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
-                               memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
+    vector[1].buffer= "decr ";
   }
 
-  memcached_return_t rc= memcached_do(instance, buffer, (size_t)send_length, true);
-  if (no_reply or memcached_failed(rc))
-    return rc;
-
-  rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+  memcached_return_t rc= memcached_vdo(instance, vector, 7, true);
 
-  if (rc != MEMCACHED_SUCCESS)
+  if (reply == false)
   {
-    return memcached_set_error(*instance, rc, MEMCACHED_AT);
+    return MEMCACHED_SUCCESS;
   }
 
-  /*
-    So why recheck responce? Because the protocol is brain dead :)
-    The number returned might end up equaling one of the string
-    values. Less chance of a mistake with strncmp() so we will
-    use it. We still called memcached_response() though since it
-    worked its magic for non-blocking IO.
-  */
-  if (not strncmp(buffer, memcached_literal_param("ERROR\r\n")))
+  if (memcached_failed(rc))
   {
-    *value= 0;
-    rc= MEMCACHED_PROTOCOL_ERROR;
-  }
-  else if (not strncmp(buffer, memcached_literal_param("CLIENT_ERROR\r\n")))
-  {
-    *value= 0;
-    rc= MEMCACHED_PROTOCOL_ERROR;
-  }
-  else if (not strncmp(buffer, memcached_literal_param("NOT_FOUND\r\n")))
-  {
-    *value= 0;
-    rc= MEMCACHED_NOTFOUND;
-  }
-  else
-  {
-    *value= strtoull(buffer, (char **)NULL, 10);
-    rc= MEMCACHED_SUCCESS;
+    numeric_value= UINT64_MAX;
+    return rc;
   }
 
+  rc= memcached_response(instance, buffer, sizeof(buffer), NULL, numeric_value);
+
   return memcached_set_error(*instance, rc, MEMCACHED_AT);
 }
 
-static memcached_return_t binary_incr_decr(memcached_st *ptr, uint8_t cmd,
-                                           const char *group_key, size_t group_key_length,
-                                           const char *key, size_t key_length,
-                                           uint64_t offset, uint64_t initial,
-                                           uint32_t expiration,
+static memcached_return_t binary_incr_decr(memcached_server_write_instance_st instance,
+                                           protocol_binary_command cmd,
+                                           const char *key, const size_t key_length,
+                                           const uint64_t offset,
+                                           const uint64_t initial,
+                                           const uint32_t expiration,
+                                           const bool reply,
                                            uint64_t *value)
 {
-  bool no_reply= ptr->flags.no_reply;
-
-  uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
-  memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
-
-  if (no_reply)
+  if (reply == false)
   {
     if(cmd == PROTOCOL_BINARY_CMD_DECREMENT)
+    {
       cmd= PROTOCOL_BINARY_CMD_DECREMENTQ;
+    }
 
     if(cmd == PROTOCOL_BINARY_CMD_INCREMENT)
+    {
       cmd= PROTOCOL_BINARY_CMD_INCREMENTQ;
+    }
   }
   protocol_binary_request_incr request= {}; // = {.bytes= {0}};
 
   request.message.header.request.magic= PROTOCOL_BINARY_REQ;
   request.message.header.request.opcode= cmd;
-  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->_namespace)));
+  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(instance->root->_namespace)));
   request.message.header.request.extlen= 20;
   request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-  request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(ptr->_namespace) +request.message.header.request.extlen));
+  request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(instance->root->_namespace) +request.message.header.request.extlen));
   request.message.body.delta= memcached_htonll(offset);
   request.message.body.initial= memcached_htonll(initial);
   request.message.body.expiration= htonl((uint32_t) expiration);
 
-  struct libmemcached_io_vector_st vector[]=
+  libmemcached_io_vector_st vector[]=
   {
+    { NULL, 0 },
     { request.bytes, sizeof(request.bytes) },
-    { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
+    { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
     { key, key_length }
   };
 
   memcached_return_t rc;
-  if (memcached_failed(rc= memcached_vdo(instance, vector, 3, true)))
+  if (memcached_failed(rc= memcached_vdo(instance, vector, 4, true)))
   {
     memcached_io_reset(instance);
-    return (rc == MEMCACHED_SUCCESS) ? MEMCACHED_WRITE_FAILURE : rc;
+    return MEMCACHED_WRITE_FAILURE;
   }
 
-  if (no_reply)
+  if (reply == false)
   {
     return MEMCACHED_SUCCESS;
   }
@@ -194,7 +172,7 @@ memcached_return_t memcached_increment_by_key(memcached_st *ptr,
     value= &local_value;
   }
 
-  if (memcached_failed(rc= initialize_query(ptr)))
+  if (memcached_failed(rc= initialize_query(ptr, true)))
   {
     return rc;
   }
@@ -204,17 +182,28 @@ memcached_return_t memcached_increment_by_key(memcached_st *ptr,
     return rc;
   }
 
+  if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
+  {
+    return memcached_set_error(*ptr, rc, MEMCACHED_AT);
+  }
+
+  uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
+  memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
+
+  bool reply= memcached_is_replying(instance->root);
+
   LIBMEMCACHED_MEMCACHED_INCREMENT_START();
-  if (ptr->flags.binary_protocol)
+  if (memcached_is_binary(ptr))
   {
-    rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT,
-                         group_key, group_key_length, key, key_length,
-                         (uint64_t)offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
+    rc= binary_incr_decr(instance, PROTOCOL_BINARY_CMD_INCREMENT,
+                         key, key_length,
+                         uint64_t(offset), 0, MEMCACHED_EXPIRATION_NOT_ADD,
+                         reply,
                          value);
   }
   else
   {
-     rc= text_incr_decr(ptr, "incr", group_key, group_key_length, key, key_length, offset, value);
+    rc= text_incr_decr(instance, true, key, key_length, offset, reply, *value);
   }
 
   LIBMEMCACHED_MEMCACHED_INCREMENT_END();
@@ -235,28 +224,34 @@ memcached_return_t memcached_decrement_by_key(memcached_st *ptr,
   }
 
   memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(ptr)))
+  if (memcached_failed(rc= initialize_query(ptr, true)))
   {
     return rc;
   }
 
-  if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
+  if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
   {
-    return rc;
+    return memcached_set_error(*ptr, rc, MEMCACHED_AT);
   }
 
 
+  uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
+  memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
+
+  bool reply= memcached_is_replying(instance->root);
+
   LIBMEMCACHED_MEMCACHED_DECREMENT_START();
-  if (ptr->flags.binary_protocol)
+  if (memcached_is_binary(ptr))
   {
-    rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_DECREMENT,
-                         group_key, group_key_length, key, key_length,
-                         (uint64_t)offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
+    rc= binary_incr_decr(instance, PROTOCOL_BINARY_CMD_DECREMENT,
+                         key, key_length,
+                         offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
+                         reply,
                          value);
   }
   else
   {
-    rc= text_incr_decr(ptr, "decr", group_key, group_key_length, key, key_length, offset, value);
+    rc= text_incr_decr(instance, false, key, key_length, offset, reply, *value);
   }
 
   LIBMEMCACHED_MEMCACHED_DECREMENT_END();
@@ -272,12 +267,6 @@ memcached_return_t memcached_increment_with_initial(memcached_st *ptr,
                                                     time_t expiration,
                                                     uint64_t *value)
 {
-  uint64_t local_value;
-  if (value == NULL)
-  {
-    value= &local_value;
-  }
-
   return memcached_increment_with_initial_by_key(ptr, key, key_length,
                                                  key, key_length,
                                                  offset, initial, expiration, value);
@@ -300,27 +289,34 @@ memcached_return_t memcached_increment_with_initial_by_key(memcached_st *ptr,
   }
 
   memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(ptr)))
+  if (memcached_failed(rc= initialize_query(ptr, true)))
   {
     return rc;
   }
 
-  if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
+  if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
   {
-    return rc;
+    return memcached_set_error(*ptr, rc, MEMCACHED_AT);
   }
 
+  uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
+  memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
+
+  bool reply= memcached_is_replying(instance->root);
+
   LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
-  if (ptr->flags.binary_protocol)
+  if (memcached_is_binary(ptr))
   {
-    rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT,
-                         group_key, group_key_length, key, key_length,
-                         offset, initial, (uint32_t)expiration,
+    rc= binary_incr_decr(instance, PROTOCOL_BINARY_CMD_INCREMENT,
+                         key, key_length,
+                         offset, initial, uint32_t(expiration),
+                         reply,
                          value);
   }
   else
   {
-    rc= MEMCACHED_PROTOCOL_ERROR;
+    rc=  memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+                             memcached_literal_param("memcached_increment_with_initial_by_key() is not supported via the ASCII protocol"));
   }
 
   LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
@@ -336,12 +332,6 @@ memcached_return_t memcached_decrement_with_initial(memcached_st *ptr,
                                                     time_t expiration,
                                                     uint64_t *value)
 {
-  uint64_t local_value;
-  if (value == NULL)
-  {
-    value= &local_value;
-  }
-
   return memcached_decrement_with_initial_by_key(ptr, key, key_length,
                                                  key, key_length,
                                                  offset, initial, expiration, value);
@@ -364,32 +354,38 @@ memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *ptr,
   }
 
   memcached_return_t rc;
-  if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
+  if (memcached_failed(rc= initialize_query(ptr, true)))
   {
     return rc;
   }
 
-  if (memcached_failed(rc= initialize_query(ptr)))
+  if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
   {
-    return rc;
+    return memcached_set_error(*ptr, rc, MEMCACHED_AT);
   }
 
+  uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
+  memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
+
+  bool reply= memcached_is_replying(instance->root);
+
 
   LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
-  if (ptr->flags.binary_protocol)
+  if (memcached_is_binary(ptr))
   {
-    rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_DECREMENT,
-                         group_key, group_key_length, key, key_length,
-                         offset, initial, (uint32_t)expiration,
+    rc= binary_incr_decr(instance, PROTOCOL_BINARY_CMD_DECREMENT,
+                         key, key_length,
+                         offset, initial, uint32_t(expiration),
+                         reply,
                          value);
   }
   else
   {
-    rc= MEMCACHED_PROTOCOL_ERROR;
+    rc=  memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+                             memcached_literal_param("memcached_decrement_with_initial_by_key() is not supported via the ASCII protocol"));
   }
 
   LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
 
   return rc;
 }
-
index bc8846bae820703799945342223cb968547f30f0..8fb8acc7ec3938e694108e52a5fa43e23cae4261 100644 (file)
 #include <cstring>
 #include <cstdlib>
 
-#ifdef __GNUC__
-#ifdef HAVE_BACKTRACE
+#ifdef HAVE_EXECINFO_H
 #include <execinfo.h>
+#endif
+
+#ifdef HAVE_CXXABI_H
 #include <cxxabi.h>
-#endif // HAVE_BACKTRACE
-#endif // __GNUC__
+#endif
 
+#ifdef HAVE_GCC_ABI_DEMANGLE
+#define USE_DEMANGLE 1
+#else
+#define USE_DEMANGLE 0
+#endif
 
 void custom_backtrace(void)
 {
-#ifdef __GNUC__
-#ifdef HAVE_BACKTRACE
+#ifdef HAVE_EXECINFO_H
   void *array[50];
 
   size_t size= backtrace(array, 50);
   char **strings= backtrace_symbols(array, size);
 
+  if (strings == NULL)
+  {
+    return;
+  }
+
   fprintf(stderr, "Number of stack frames obtained: %lu\n", (unsigned long)size);
 
-  for (size_t x= 1; x < size; x++) 
+  char *named_function= (char *)::realloc(NULL, 1024);
+  
+  if (named_function == NULL)
   {
-    size_t sz= 200;
-    char *function= (char *)malloc(sz);
-    char *begin= 0;
-    char *end= 0;
+    ::free(strings);
+    return;
+  }
 
-    for (char *j = strings[x]; *j; ++j)
+  for (size_t x= 1; x < size; x++) 
+  {
+    if (USE_DEMANGLE)
     {
-      if (*j == '(') {
-        begin = j;
+      size_t sz= 200;
+      char *named_function_ptr= (char *)::realloc(named_function, sz);
+      if (named_function_ptr == NULL)
+      {
+        continue;
       }
-      else if (*j == '+') {
-        end = j;
+      named_function= named_function_ptr;
+
+      char *begin_name= 0;
+      char *begin_offset= 0;
+      char *end_offset= 0;
+
+      for (char *j= strings[x]; *j; ++j)
+      {
+        if (*j == '(')
+        {
+          begin_name= j;
+        }
+        else if (*j == '+')
+        {
+          begin_offset= j;
+        }
+        else if (*j == ')' and begin_offset) 
+        {
+          end_offset= j;
+          break;
+        }
       }
-    }
-    if (begin && end)
-    {
-      begin++;
-      *end= '\0';
 
-      int status;
-      char *ret = abi::__cxa_demangle(begin, function, &sz, &status);
-      if (ret) 
+      if (begin_name and begin_offset and end_offset and begin_name < begin_offset)
       {
-        function= ret;
+        *begin_name++= '\0';
+        *begin_offset++= '\0';
+        *end_offset= '\0';
+
+        int status;
+        char *ret= abi::__cxa_demangle(begin_name, named_function, &sz, &status);
+        if (ret) // realloc()'ed string
+        {
+          named_function= ret;
+          fprintf(stderr, "  %s : %s()+%s\n", strings[x], begin_name, begin_offset);
+        }
+        else
+        {
+          fprintf(stderr, "  %s : %s()+%s\n", strings[x], begin_name, begin_offset);
+        }
       }
       else
       {
-        strncpy(function, begin, sz);
-        strncat(function, "()", sz);
-        function[sz-1] = '\0';
+        fprintf(stderr, " %s\n", strings[x]);
       }
-      fprintf(stderr, "%s\n", function);
     }
     else
     {
-      fprintf(stderr, "%s\n", strings[x]);
+      fprintf(stderr, " unmangled: %s\n", strings[x]);
     }
-    free(function);
   }
 
-
-  free (strings);
-#endif // HAVE_BACKTRACE
-#endif // __GNUC__
+  ::free(named_function);
+  ::free(strings);
+#endif // HAVE_EXECINFO_H
 }
index 98db320c3d6291f72ad101c6441a63ce7524156d..330d02c4ae3c302d48be6a4fb86f54740cd1c3be 100644 (file)
@@ -37,5 +37,4 @@
 
 #pragma once
 
-LIBMEMCACHED_LOCAL
 void custom_backtrace(void);
index bb17f2bdaa7b68014ca38d1a87935e7f10cb028a..9769759ba884a58b8cb37067893cd50d0aaf9819 100644 (file)
@@ -114,7 +114,7 @@ memcached_return_t memcached_behavior_set(memcached_st *ptr,
     break;
 
   case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS:
-    if (ptr->flags.use_udp)
+    if (memcached_is_udp(ptr))
     {
       return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
                                  memcached_literal_param("MEMCACHED_BEHAVIOR_BUFFER_REQUESTS cannot be set while MEMCACHED_BEHAVIOR_USE_UDP is enabled."));
@@ -128,9 +128,13 @@ memcached_return_t memcached_behavior_set(memcached_st *ptr,
     ptr->flags.use_udp= bool(data);
     if (bool(data))
     {
-      ptr->flags.no_reply= true;
+      ptr->flags.reply= false;
       ptr->flags.buffer_requests= false;
     }
+    else
+    {
+      ptr->flags.reply= true;
+    }
     break;
 
   case MEMCACHED_BEHAVIOR_TCP_NODELAY:
@@ -231,12 +235,14 @@ memcached_return_t memcached_behavior_set(memcached_st *ptr,
     break;
 
   case MEMCACHED_BEHAVIOR_NOREPLY:
-    if (ptr->flags.use_udp and bool(data) == false)
+    if (memcached_is_udp(ptr) and bool(data) == false)
     {
       return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
                                  memcached_literal_param("MEMCACHED_BEHAVIOR_NOREPLY cannot be disabled while MEMCACHED_BEHAVIOR_USE_UDP is enabled."));
     }
-    ptr->flags.no_reply= bool(data);
+    // We reverse the logic here to make it easier to understand throughout the
+    // code.
+    ptr->flags.reply= bool(data) ? false : true;
     break;
 
   case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
@@ -310,7 +316,7 @@ uint64_t memcached_behavior_get(memcached_st *ptr,
     return ptr->flags.buffer_requests;
 
   case MEMCACHED_BEHAVIOR_USE_UDP:
-    return ptr->flags.use_udp;
+    return memcached_is_udp(ptr);
 
   case MEMCACHED_BEHAVIOR_TCP_NODELAY:
     return ptr->flags.tcp_nodelay;
@@ -364,7 +370,9 @@ uint64_t memcached_behavior_get(memcached_st *ptr,
       socklen_t sock_length= sizeof(int);
 
       if (ptr->send_size != -1) // If value is -1 then we are using the default
+      {
         return (uint64_t) ptr->send_size;
+      }
 
       memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, 0);
 
@@ -437,7 +445,7 @@ uint64_t memcached_behavior_get(memcached_st *ptr,
     return ptr->flags.hash_with_namespace;
 
   case MEMCACHED_BEHAVIOR_NOREPLY:
-    return ptr->flags.no_reply;
+    return ptr->flags.reply ? false : true;
 
   case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
     return ptr->flags.auto_eject_hosts;
index 5aaf797b795a9c916e106a54f42749fba7602c38..0f33a784c42b0b8f87d23e59613cb53676dfff3b 100644 (file)
@@ -105,6 +105,7 @@ memcached_return_t memcached_server_execute(memcached_st *ptr,
 #ifdef __cplusplus
 #include <libmemcached/string.hpp>
 #include <libmemcached/io.hpp>
+#include <libmemcached/udp.hpp>
 #include <libmemcached/do.hpp>
 #include <libmemcached/close_socket.hpp>
 #include <libmemcached/connect.hpp>
@@ -122,7 +123,9 @@ memcached_return_t memcached_server_execute(memcached_st *ptr,
 #include <libmemcached/memcached/protocol_binary.h>
 #include <libmemcached/byteorder.h>
 #include <libmemcached/initialize_query.h>
+#ifdef __cplusplus
 #include <libmemcached/response.h>
+#endif
 #include <libmemcached/namespace.h>
 #include <libmemcached/virtual_bucket.h>
 
index e04098c421db19d6297958d875fd967c0ae715ca..b81b25b992bf8fc57d5f7929cba9e2a4ff71b3cb 100644 (file)
@@ -231,7 +231,7 @@ static inline void set_socket_nonblocking(memcached_server_st *server)
 
 static void set_socket_options(memcached_server_st *server)
 {
-  assert_msg(server->fd != -1, "invalid socket was passed to set_socket_options()");
+  assert_msg(server->fd != INVALID_SOCKET, "invalid socket was passed to set_socket_options()");
 
   if (memcached_is_udp(server->root))
   {
index ed7510a61ec0dc034dfb9f10ead54ee4b4e7faf5..121ec91bf0e550bdf8c871c8cdc8452ff2ab6739 100644 (file)
@@ -44,50 +44,33 @@ memcached_return_t memcached_delete(memcached_st *ptr, const char *key, size_t k
   return memcached_delete_by_key(ptr, key, key_length, key, key_length, expiration);
 }
 
-static inline memcached_return_t ascii_delete(memcached_st *ptr,
-                                              memcached_server_write_instance_st instance,
+static inline memcached_return_t ascii_delete(memcached_server_write_instance_st instance,
                                               uint32_t ,
                                               const char *key,
-                                              size_t key_length,
-                                              bool& reply,
-                                              bool& flush)
+                                              const size_t key_length,
+                                              const bool reply,
+                                              const bool flush)
 {
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-  int send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
-                            "delete %.*s%.*s%s\r\n",
-                            memcached_print_array(ptr->_namespace),
-                            (int)key_length, key, 
-                            reply ? "" :  " noreply");
-
-  if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0)
+  libmemcached_io_vector_st vector[]=
   {
-    return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
-                               memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
-  }
-
-  if (ptr->flags.use_udp and flush == false)
-  {
-    if (send_length > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH)
-    {
-      return MEMCACHED_WRITE_FAILURE;
-    }
-
-    if (send_length +instance->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
-    {
-      memcached_io_write(instance, NULL, 0, true);
-    }
-  }
+    { NULL, 0 },
+    { memcached_literal_param("delete ") },
+    { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
+    { key, key_length },
+    { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
+    { memcached_literal_param("\r\n") }
+  };
 
-  return memcached_do(instance, buffer, (size_t)send_length, flush);
+  /* Send command header */
+  return memcached_vdo(instance, vector, 6, flush);
 }
 
-static inline memcached_return_t binary_delete(memcached_st *ptr,
-                                               memcached_server_write_instance_st instance,
+static inline memcached_return_t binary_delete(memcached_server_write_instance_st instance,
                                                uint32_t server_key,
                                                const char *key,
-                                               size_t key_length,
-                                               bool& reply,
-                                               bool& flush)
+                                               const size_t key_length,
+                                               const bool reply,
+                                               const bool flush)
 {
   protocol_binary_request_delete request= {};
 
@@ -100,53 +83,41 @@ static inline memcached_return_t binary_delete(memcached_st *ptr,
   {
     request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ;
   }
-  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->_namespace)));
+  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(instance->root->_namespace)));
   request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-  request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(ptr->_namespace)));
-
-  if (ptr->flags.use_udp and flush == false)
-  {
-    size_t cmd_size= sizeof(request.bytes) + key_length;
-    if (cmd_size > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH)
-    {
-      return MEMCACHED_WRITE_FAILURE;
-    }
-
-    if (cmd_size +instance->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
-    {
-      memcached_io_write(instance, NULL, 0, true);
-    }
-  }
+  request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(instance->root->_namespace)));
 
-  struct libmemcached_io_vector_st vector[]=
+  libmemcached_io_vector_st vector[]=
   {
+    { NULL, 0 },
     { request.bytes, sizeof(request.bytes) },
-    { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
+    { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
     { key, key_length }
   };
 
   memcached_return_t rc= MEMCACHED_SUCCESS;
 
-  if ((rc= memcached_vdo(instance, vector,  3, flush)) != MEMCACHED_SUCCESS)
+  if ((rc= memcached_vdo(instance, vector,  4, flush)) != MEMCACHED_SUCCESS)
   {
     memcached_io_reset(instance);
   }
 
-  if (ptr->number_of_replicas > 0)
+  if (instance->root->number_of_replicas > 0)
   {
     request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ;
 
-    for (uint32_t x= 0; x < ptr->number_of_replicas; ++x)
+    for (uint32_t x= 0; x < instance->root->number_of_replicas; ++x)
     {
-      memcached_server_write_instance_st replica;
 
       ++server_key;
-      if (server_key == memcached_server_count(ptr))
+      if (server_key == memcached_server_count(instance->root))
+      {
         server_key= 0;
+      }
 
-      replica= memcached_server_instance_fetch(ptr, server_key);
+      memcached_server_write_instance_st replica= memcached_server_instance_fetch(instance->root, server_key);
 
-      if (memcached_vdo(replica, vector, 3, flush) != MEMCACHED_SUCCESS)
+      if (memcached_vdo(replica, vector, 4, flush) != MEMCACHED_SUCCESS)
       {
         memcached_io_reset(replica);
       }
@@ -168,7 +139,7 @@ memcached_return_t memcached_delete_by_key(memcached_st *ptr,
   LIBMEMCACHED_MEMCACHED_DELETE_START();
 
   memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(ptr)))
+  if (memcached_failed(rc= initialize_query(ptr, true)))
   {
     return rc;
   }
@@ -184,63 +155,63 @@ memcached_return_t memcached_delete_by_key(memcached_st *ptr,
     return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, 
                                memcached_literal_param("Memcached server version does not allow expiration of deleted items"));
   }
+
+  uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
+  memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
   
+  bool buffering= memcached_is_buffering(instance->root);
+  bool reply= memcached_is_replying(instance->root);
+
   // If a delete trigger exists, we need a response, so no buffering/noreply
   if (ptr->delete_trigger)
   {
-    if (ptr->flags.buffer_requests)
+    if (buffering)
     {
       return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, 
                                  memcached_literal_param("Delete triggers cannot be used if buffering is enabled"));
     }
 
-    if (ptr->flags.no_reply)
+    if (reply == false)
     {
       return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, 
                                  memcached_literal_param("Delete triggers cannot be used if MEMCACHED_BEHAVIOR_NOREPLY is set"));
     }
   }
 
-
-  uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
-  memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
-
-  bool to_write= (ptr->flags.buffer_requests) ? false : true;
-
-  // Invert the logic to make it simpler to read the code
-  bool reply= (ptr->flags.no_reply) ? false : true;
-
-  if (ptr->flags.binary_protocol)
+  if (memcached_is_binary(ptr))
   {
-    rc= binary_delete(ptr, instance, server_key, key, key_length, reply, to_write);
+    rc= binary_delete(instance, server_key, key, key_length, reply, buffering ? false : true);
   }
   else
   {
-    rc= ascii_delete(ptr, instance, server_key, key, key_length, reply, to_write);
+    rc= ascii_delete(instance, server_key, key, key_length, reply, buffering ? false : true);
   }
 
   if (rc == MEMCACHED_SUCCESS)
   {
-    if (to_write == false)
+    if (buffering == true)
     {
       rc= MEMCACHED_BUFFERED;
     }
-    else if (reply)
+    else if (reply == false)
+    {
+      rc= MEMCACHED_SUCCESS;
+    }
+    else
     {
       char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
       rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
       if (rc == MEMCACHED_DELETED)
       {
         rc= MEMCACHED_SUCCESS;
+        if (ptr->delete_trigger)
+        {
+          ptr->delete_trigger(ptr, key, key_length);
+        }
       }
     }
-
-    if (rc == MEMCACHED_SUCCESS and ptr->delete_trigger)
-    {
-      ptr->delete_trigger(ptr, key, key_length);
-    }
   }
 
   LIBMEMCACHED_MEMCACHED_DELETE_END();
-  return rc;
+  return memcached_set_error(*ptr, rc, MEMCACHED_AT );
 }
index c3cfab9389b4339dfc8c0e5d49aeb3210223d550..3c3519c27b9cccb29df440a9e4719735bb3be424 100644 (file)
 
 #include <libmemcached/common.h>
 
-memcached_return_t memcached_do(memcached_server_write_instance_st ptr, const void *command,
-                                size_t command_length, bool with_flush)
+memcached_return_t memcached_vdo(memcached_server_write_instance_st instance,
+                                 libmemcached_io_vector_st vector[],
+                                 const size_t count,
+                                 const bool with_flush)
 {
-  assert_msg(command_length, "Programming error, somehow a command had a length of zero");
-  assert_msg(command, "Programming error, somehow a command was NULL");
-
   memcached_return_t rc;
-  if (memcached_failed(rc= memcached_connect(ptr)))
+
+  assert_msg(vector, "Invalid vector passed");
+
+  if (memcached_failed(rc= memcached_connect(instance)))
   {
-    WATCHPOINT_ASSERT(rc == memcached_last_error(ptr->root));
     WATCHPOINT_ERROR(rc);
+    assert_msg(instance->error_messages, "memcached_connect() returned an error but the memcached_server_write_instance_st showed none.");
     return rc;
   }
 
@@ -30,57 +32,33 @@ memcached_return_t memcached_do(memcached_server_write_instance_st ptr, const vo
   ** before they start writing, if there is any data in buffer, clear it out,
   ** otherwise we might get a partial write.
   **/
-  if (memcached_is_udp(ptr->root) and with_flush and ptr->write_buffer_offset > UDP_DATAGRAM_HEADER_LENGTH)
-  {
-    memcached_io_write(ptr, NULL, 0, true);
-  }
-
-  ssize_t sent_length= memcached_io_write(ptr, command, command_length, with_flush);
-
-  if (sent_length == -1 or size_t(sent_length) != command_length)
+  if (memcached_is_udp(instance->root))
   {
-    rc= MEMCACHED_WRITE_FAILURE;
-  }
-  else if ((ptr->root->flags.no_reply) == 0)
-  {
-    memcached_server_response_increment(ptr);
-  }
-
-  return rc;
-}
+    if (vector[0].buffer or vector[0].length)
+    {
+      return memcached_set_error(*instance->root, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT, 
+                                 memcached_literal_param("UDP messages was attempted, but vector was not setup for it"));
+    }
 
-memcached_return_t memcached_vdo(memcached_server_write_instance_st ptr,
-                                 const struct libmemcached_io_vector_st *vector, size_t count,
-                                 bool with_flush)
-{
-  memcached_return_t rc;
+    struct msghdr msg;
+    memset(&msg, 0, sizeof(msg));
 
-  WATCHPOINT_ASSERT(count);
-  WATCHPOINT_ASSERT(vector);
+    increment_udp_message_id(instance);
+    vector[0].buffer= instance->write_buffer;
+    vector[0].length= UDP_DATAGRAM_HEADER_LENGTH;
 
-  if (memcached_failed(rc= memcached_connect(ptr)))
-  {
-    WATCHPOINT_ERROR(rc);
-    assert_msg(ptr->error_messages, "memcached_connect() returned an error but the memcached_server_write_instance_st showed none.");
-    return rc;
-  }
+    msg.msg_iov= (struct iovec*)vector;
+    msg.msg_iovlen= count;
 
-  /*
-  ** Since non buffering ops in UDP mode dont check to make sure they will fit
-  ** before they start writing, if there is any data in buffer, clear it out,
-  ** otherwise we might get a partial write.
-  **/
-  if (memcached_is_udp(ptr->root) and with_flush and ptr->write_buffer_offset > UDP_DATAGRAM_HEADER_LENGTH)
-  {
-    if (memcached_io_write(ptr, NULL, 0, true) == -1)
+    if (::sendmsg(instance->fd, &msg, 0) < 1)
     {
-      memcached_io_reset(ptr);
-      return memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+      return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
     }
-  }
 
-  ssize_t sent_length= memcached_io_writev(ptr, vector, count, with_flush);
+    return MEMCACHED_SUCCESS;
+  }
 
+  ssize_t sent_length= memcached_io_writev(instance, vector, count, with_flush);
   size_t command_length= 0;
   for (uint32_t x= 0; x < count; ++x, vector++)
   {
@@ -93,9 +71,9 @@ memcached_return_t memcached_vdo(memcached_server_write_instance_st ptr,
     WATCHPOINT_ERROR(rc);
     WATCHPOINT_ERRNO(errno);
   }
-  else if ((ptr->root->flags.no_reply) == 0)
+  else if (memcached_is_replying(instance->root))
   {
-    memcached_server_response_increment(ptr);
+    memcached_server_response_increment(instance);
   }
 
   return rc;
index f123266290d845534879e273e3bbefff5ebf6009..560c131829f3daef0906d9fc598d4c57395a3a36 100644 (file)
 
 #pragma once
 
-LIBMEMCACHED_LOCAL
-memcached_return_t memcached_do(memcached_server_write_instance_st ptr,
-                                const void *commmand,
-                                size_t command_length,
-                                bool with_flush);
-
-LIBMEMCACHED_LOCAL
 memcached_return_t memcached_vdo(memcached_server_write_instance_st ptr,
-                                 const struct libmemcached_io_vector_st *vector, size_t count,
-                                 bool with_flush);
+                                 libmemcached_io_vector_st vector[],
+                                 const size_t count,
+                                 const bool with_flush);
index dcbe15b81c5104448b811880582215bf73fdb412..830c3ff405c02d66d67e3a6600bfe87d99813081 100644 (file)
@@ -1,3 +1,39 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
 /*
   We use this to dump all keys.
 
@@ -21,17 +57,21 @@ static memcached_return_t ascii_dump(memcached_st *ptr, memcached_dump_fn *callb
     for (uint32_t x= 0; x < 256; x++)
     {
       char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-      int send_length;
-      send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
-                            "stats cachedump %u 0 0\r\n", x);
-
-      if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0)
+      int buffer_length= snprintf(buffer, sizeof(buffer), "%u", x);
+      if (buffer_length >= MEMCACHED_DEFAULT_COMMAND_SIZE or buffer_length < 0)
       {
         return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
                                    memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
       }
 
-      rc= memcached_do(instance, buffer, (size_t)send_length, true);
+      libmemcached_io_vector_st vector[]=
+      {
+        { memcached_literal_param("stats cachedump ") },
+        { buffer, buffer_length },
+        { memcached_literal_param(" 0 0\r\n") }
+      };
+
+      rc= memcached_vdo(instance, vector, 3, true);
 
       if (rc != MEMCACHED_SUCCESS)
       {
@@ -76,7 +116,7 @@ static memcached_return_t ascii_dump(memcached_st *ptr, memcached_dump_fn *callb
            * This isn't really a fatal error, so let's just skip it. I want to
            * fix the return value from the memcached server to a CLIENT_ERROR,
            * so let's add support for that as well right now.
-           */
+         */
           rc= MEMCACHED_END;
           break;
         }
@@ -102,7 +142,7 @@ error:
 memcached_return_t memcached_dump(memcached_st *ptr, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks)
 {
   memcached_return_t rc;
-  if ((rc= initialize_query(ptr)) != MEMCACHED_SUCCESS)
+  if (memcached_failed(rc= initialize_query(ptr, true)))
   {
     return rc;
   }
index f7764d0f6470a636a3ce4eab4015a3640c88f06b..becffd23014b3a10256fa61672f905def9587ab3 100644 (file)
@@ -395,11 +395,11 @@ static void _error_print(const memcached_error_t *error)
 
   if (error->size == 0)
   {
-    fprintf(stderr, "%s\n", memcached_strerror(NULL, error->rc) );
+    fprintf(stderr, "\t%s\n", memcached_strerror(NULL, error->rc) );
   }
   else
   {
-    fprintf(stderr, "%s %s\n", memcached_strerror(NULL, error->rc), error->message);
+    fprintf(stderr, "\t%s %s\n", memcached_strerror(NULL, error->rc), error->message);
   }
 
   _error_print(error->next);
@@ -407,10 +407,19 @@ static void _error_print(const memcached_error_t *error)
 
 void memcached_error_print(const memcached_st *self)
 {
-  if (not self)
+  if (self == NULL)
+  {
     return;
+  }
 
   _error_print(self->error_messages);
+
+  for (uint32_t x= 0; x < memcached_server_count(self); x++)
+  {
+    memcached_server_instance_st instance= memcached_server_instance_by_position(self, x);
+
+    _error_print(instance->error_messages);
+  }
 }
 
 static void _error_free(memcached_error_t *error)
index b68ba466db760fab7683c66d2c61c5a884575a69..d2dc34dd6a1126f7e8afc463405d82a0da698525 100644 (file)
@@ -38,8 +38,9 @@
 
 static memcached_return_t ascii_exist(memcached_st *memc, memcached_server_write_instance_st instance, const char *key, size_t key_length)
 {
-  struct libmemcached_io_vector_st vector[]=
+  libmemcached_io_vector_st vector[]=
   {
+    { NULL, 0 },
     { memcached_literal_param("add ") },
     { memcached_array_string(memc->_namespace), memcached_array_size(memc->_namespace) },
     { key, key_length },
@@ -51,21 +52,27 @@ static memcached_return_t ascii_exist(memcached_st *memc, memcached_server_write
   };
 
   /* Send command header */
-  memcached_return_t rc=  memcached_vdo(instance, vector, 8, true);
+  memcached_return_t rc=  memcached_vdo(instance, vector, 9, true);
   if (rc == MEMCACHED_SUCCESS)
   {
     char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
     rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
 
     if (rc == MEMCACHED_NOTSTORED)
+    {
       rc= MEMCACHED_SUCCESS;
+    }
 
     if (rc == MEMCACHED_STORED)
+    {
       rc= MEMCACHED_NOTFOUND;
+    }
   }
 
   if (rc == MEMCACHED_WRITE_FAILURE)
+  {
     memcached_io_reset(instance);
+  }
 
   return rc;
 }
@@ -87,8 +94,9 @@ static memcached_return_t binary_exist(memcached_st *memc, memcached_server_writ
                                                             +memcached_array_size(memc->_namespace)
                                                             +request.message.header.request.extlen));
 
-  struct libmemcached_io_vector_st vector[]=
+  libmemcached_io_vector_st vector[]=
   {
+    { NULL, 0 },
     { request.bytes, send_length },
     { memcached_array_string(memc->_namespace), memcached_array_size(memc->_namespace) },
     { key, key_length }
@@ -96,7 +104,7 @@ static memcached_return_t binary_exist(memcached_st *memc, memcached_server_writ
 
   /* write the header */
   memcached_return_t rc;
-  if ((rc= memcached_vdo(instance, vector, 3, true)) != MEMCACHED_SUCCESS)
+  if ((rc= memcached_vdo(instance, vector, 4, true)) != MEMCACHED_SUCCESS)
   {
     memcached_io_reset(instance);
     return (rc == MEMCACHED_SUCCESS) ? MEMCACHED_WRITE_FAILURE : rc;
@@ -123,17 +131,16 @@ memcached_return_t memcached_exist_by_key(memcached_st *memc,
                                           const char *key, size_t key_length)
 {
   memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(memc)))
+  if (memcached_failed(rc= initialize_query(memc, true)))
   {
     return rc;
   }
 
-  if (memc->flags.use_udp)
+  if (memcached_is_udp(memc))
   {
     return MEMCACHED_NOT_SUPPORTED;
   }
 
-
   uint32_t server_key= memcached_generate_hash_with_redistribution(memc, group_key, group_key_length);
   memcached_server_write_instance_st instance;
   instance= memcached_server_instance_fetch(memc, server_key);
index 8867d53d0cc711bc5b6cee9c001bd573015c361f..2b5b800693c495245a3265ff49acdf65e81c344c 100644 (file)
@@ -44,23 +44,32 @@ char *memcached_fetch(memcached_st *ptr, char *key, size_t *key_length,
 {
   memcached_result_st *result_buffer= &ptr->result;
   memcached_return_t unused;
-  if (not error)
+  if (error == NULL)
+  {
     error= &unused;
+  }
 
-
-  unlikely (ptr->flags.use_udp)
+  if (memcached_is_udp(ptr))
   {
     if (value_length)
+    {
       *value_length= 0;
+    }
 
     if (key_length)
+    {
       *key_length= 0;
+    }
 
     if (flags)
+    {
       *flags= 0;
+    }
 
     if (key)
+    {
       *key= 0;
+    }
 
     *error= MEMCACHED_NOT_SUPPORTED;
     return NULL;
@@ -71,16 +80,24 @@ char *memcached_fetch(memcached_st *ptr, char *key, size_t *key_length,
   {
     WATCHPOINT_ASSERT(result_buffer == NULL);
     if (value_length)
+    {
       *value_length= 0;
+    }
 
     if (key_length)
+    {
       *key_length= 0;
+    }
 
     if (flags)
+    {
       *flags= 0;
+    }
 
     if (key)
+    {
       *key= 0;
+    }
 
     return NULL;
   }
@@ -96,26 +113,39 @@ char *memcached_fetch(memcached_st *ptr, char *key, size_t *key_length,
     {
       *error= MEMCACHED_KEY_TOO_BIG;
       if (value_length)
+      {
         *value_length= 0;
+      }
 
-    if (key_length)
-      *key_length= 0;
+      if (key_length)
+      {
+        *key_length= 0;
+      }
 
-    if (flags)
-      *flags= 0;
+      if (flags)
+      {
+        *flags= 0;
+      }
 
-    if (key)
-      *key= 0;
+      if (key)
+      {
+        *key= 0;
+      }
 
       return NULL;
     }
+
     strncpy(key, result_buffer->item_key, result_buffer->key_length); // For the binary protocol we will cut off the key :(
     if (key_length)
+    {
       *key_length= result_buffer->key_length;
+    }
   }
 
   if (flags)
+  {
     *flags= result_buffer->item_flags;
+  }
 
   return memcached_string_take_value(&result_buffer->value);
 }
@@ -134,13 +164,13 @@ memcached_result_st *memcached_fetch_result(memcached_st *ptr,
     return NULL;
   }
 
-  if (ptr->flags.use_udp)
+  if (memcached_is_udp(ptr))
   {
     *error= MEMCACHED_NOT_SUPPORTED;
     return NULL;
   }
 
-  if (not result)
+  if (result == NULL)
   {
     // If we have already initialized (ie it is in use) our internal, we
     // create one.
index f2c490ba6726c074f84a71e44bbc71a3c57a942b..6b8ea4b0815a7b6ae4daf7bfd4832a1aff934f94 100644 (file)
 #include <libmemcached/common.h>
 
 static memcached_return_t memcached_flush_binary(memcached_st *ptr, 
-                                                 time_t expiration);
-static memcached_return_t memcached_flush_textual(memcached_st *ptr, 
-                                                  time_t expiration);
-
-memcached_return_t memcached_flush(memcached_st *ptr, time_t expiration)
+                                                 time_t expiration,
+                                                 const bool reply)
 {
-  memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(ptr)))
-  {
-    return rc;
-  }
+  protocol_binary_request_flush request= {};
 
-  LIBMEMCACHED_MEMCACHED_FLUSH_START();
-  if (ptr->flags.binary_protocol)
+  request.message.header.request.magic= (uint8_t)PROTOCOL_BINARY_REQ;
+  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSH;
+  request.message.header.request.extlen= 4;
+  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+  request.message.header.request.bodylen= htonl(request.message.header.request.extlen);
+  request.message.body.expiration= htonl((uint32_t) expiration);
+
+  memcached_return_t rc= MEMCACHED_SUCCESS;
+
+  for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
   {
-    rc= memcached_flush_binary(ptr, expiration);
+    memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
+
+    if (reply)
+    {
+      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSH;
+    }
+    else
+    {
+      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSHQ;
+    }
+
+    libmemcached_io_vector_st vector[]=
+    {
+      { NULL, 0 },
+      { request.bytes, sizeof(request.bytes) }
+    };
+
+    memcached_return_t rrc;
+    if (memcached_failed(rrc= memcached_vdo(instance, vector, 2, true)))
+    {
+      if (instance->error_messages == NULL or instance->root->error_messages == NULL)
+      {
+        memcached_set_error(*instance, rrc, MEMCACHED_AT);
+      }
+      memcached_io_reset(instance);
+      rc= MEMCACHED_SOME_ERRORS;
+    } 
   }
-  else
+
+  for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
   {
-    rc= memcached_flush_textual(ptr, expiration);
+    memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
+
+    if (memcached_server_response_count(instance) > 0)
+    {
+      (void)memcached_response(instance, NULL, 0, NULL);
+    }
   }
-  LIBMEMCACHED_MEMCACHED_FLUSH_END();
 
   return rc;
 }
 
 static memcached_return_t memcached_flush_textual(memcached_st *ptr, 
-                                                  time_t expiration)
+                                                  time_t expiration,
+                                                  const bool reply)
 {
-  bool reply= ptr->flags.no_reply ? false : true;
-
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-  int send_length;
+  char buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+  int send_length= 0;
   if (expiration)
   {
-    send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
-                          "flush_all %llu%s\r\n",
-                          (unsigned long long)expiration, reply ? "" :  " noreply");
-  }
-  else
-  {
-    send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
-                          "flush_all%s\r\n", reply ? "" : " noreply");
+    send_length= snprintf(buffer, sizeof(buffer), "%llu", (unsigned long long)expiration);
   }
 
-  if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE or send_length < 0)
+  if (size_t(send_length) >= sizeof(buffer) or send_length < 0)
   {
     return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
                                memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
   }
 
-
   memcached_return_t rc= MEMCACHED_SUCCESS;
-  for (unsigned int x= 0; x < memcached_server_count(ptr); x++)
+  for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
   {
     memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
 
-    memcached_return_t rrc= memcached_do(instance, buffer, (size_t)send_length, true);
-    if (rrc == MEMCACHED_SUCCESS and reply == true)
+    libmemcached_io_vector_st vector[]=
+    {
+      { NULL, 0 },
+      { memcached_literal_param("flush_all ") },
+      { buffer, send_length },
+      { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
+      { memcached_literal_param("\r\n") }
+    };
+
+    memcached_return_t rrc= memcached_vdo(instance, vector, 5, true);
+    if (memcached_success(rrc) and reply == true)
     {
       char response_buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
       rrc= memcached_response(instance, response_buffer, sizeof(response_buffer), NULL);
@@ -104,7 +136,7 @@ static memcached_return_t memcached_flush_textual(memcached_st *ptr,
     if (memcached_failed(rrc))
     {
       // If an error has already been reported, then don't add to it
-      if (instance->error_messages == NULL)
+      if (instance->error_messages == NULL or instance->root->error_messages == NULL)
       {
         memcached_set_error(*instance, rrc, MEMCACHED_AT);
       }
@@ -115,51 +147,26 @@ static memcached_return_t memcached_flush_textual(memcached_st *ptr,
   return rc;
 }
 
-static memcached_return_t memcached_flush_binary(memcached_st *ptr, 
-                                                 time_t expiration)
+memcached_return_t memcached_flush(memcached_st *ptr, time_t expiration)
 {
-  protocol_binary_request_flush request= {};
-
-  request.message.header.request.magic= (uint8_t)PROTOCOL_BINARY_REQ;
-  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSH;
-  request.message.header.request.extlen= 4;
-  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-  request.message.header.request.bodylen= htonl(request.message.header.request.extlen);
-  request.message.body.expiration= htonl((uint32_t) expiration);
-
-  memcached_return_t rc= MEMCACHED_SUCCESS;
-
-  for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(ptr, true)))
   {
-    memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
+    return rc;
+  }
 
-    if (ptr->flags.no_reply)
-    {
-      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSHQ;
-    }
-    else
-    {
-      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSH;
-    }
+  bool reply= memcached_is_replying(ptr);
 
-    memcached_return_t rrc;
-    if ((rrc= memcached_do(instance, request.bytes, sizeof(request.bytes), true)))
-    {
-      memcached_set_error(*instance, rrc, MEMCACHED_AT);
-      memcached_io_reset(instance);
-      rc= MEMCACHED_SOME_ERRORS;
-    } 
+  LIBMEMCACHED_MEMCACHED_FLUSH_START();
+  if (memcached_is_binary(ptr))
+  {
+    rc= memcached_flush_binary(ptr, expiration, reply);
   }
-
-  for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
+  else
   {
-    memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
-
-    if (memcached_server_response_count(instance) > 0)
-    {
-      (void)memcached_response(instance, NULL, 0, NULL);
-    }
+    rc= memcached_flush_textual(ptr, expiration, reply);
   }
+  LIBMEMCACHED_MEMCACHED_FLUSH_END();
 
   return rc;
 }
index bb3c4dec33d171f6ce46026883e41c467a26991a..58260fc10cb785dc7fe44749f92ddb43aca930db 100644 (file)
@@ -48,14 +48,14 @@ memcached_return_t memcached_flush_buffers(memcached_st *memc)
 
     if (instance->write_buffer_offset != 0) 
     {
-      if (instance->fd == -1 &&
+      if (instance->fd == INVALID_SOCKET and
           (ret= memcached_connect(instance)) != MEMCACHED_SUCCESS)
       {
         WATCHPOINT_ERROR(ret);
         return ret;
       }
 
-      if (memcached_io_write(instance, NULL, 0, true) == -1)
+      if (memcached_io_write(instance) == false)
       {
         ret= MEMCACHED_SOME_ERRORS;
       }
index c10f234171def1771630a0ed7e6557d1c3eb05e2..b24283869a668eb001fc58f8c101213592ebd538 100644 (file)
@@ -72,36 +72,35 @@ char *memcached_get_by_key(memcached_st *ptr,
     error= &unused;
   }
 
-  if (ptr->flags.use_udp)
+  uint64_t query_id= 0;
+  if (ptr)
   {
-    if (value_length) 
-    {
-      *value_length= 0;
-    }
-
-    *error= memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
-    return NULL;
+    query_id= ptr->query_id;
   }
 
-  uint64_t query_id= ptr->query_id;
-  (void)query_id;
-
   /* Request the key */
   *error= memcached_mget_by_key_real(ptr, group_key, group_key_length,
                                      (const char * const *)&key, &key_length, 
                                      1, false);
-  assert_msg(ptr->query_id == query_id +1, "Programmer error, the query_id was not incremented.");
-
+  if (ptr)
+  {
+    assert_msg(ptr->query_id == query_id +1, "Programmer error, the query_id was not incremented.");
+  }
 
   if (memcached_failed(*error))
   {
-    if (memcached_has_current_error(*ptr)) // Find the most accurate error
+    if (ptr)
     {
-      *error= memcached_last_error(ptr);
+      if (memcached_has_current_error(*ptr)) // Find the most accurate error
+      {
+        *error= memcached_last_error(ptr);
+      }
     }
 
     if (value_length) 
+    {
       *value_length= 0;
+    }
 
     return NULL;
   }
@@ -209,12 +208,12 @@ static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr,
   unsigned int master_server_key= (unsigned int)-1; /* 0 is a valid server id! */
 
   memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(ptr)))
+  if (memcached_failed(rc= initialize_query(ptr, true)))
   {
     return rc;
   }
 
-  if (ptr->flags.use_udp)
+  if (memcached_is_udp(ptr))
   {
     return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
   }
@@ -259,10 +258,14 @@ static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr,
       char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
 
       if (ptr->flags.no_block)
-        (void)memcached_io_write(instance, NULL, 0, true);
+      {
+        memcached_io_write(instance);
+      }
 
       while(memcached_server_response_count(instance))
+      {
         (void)memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, &ptr->result);
+      }
     }
   }
 
@@ -300,7 +303,7 @@ static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr,
 
     instance= memcached_server_instance_fetch(ptr, server_key);
 
-    struct libmemcached_io_vector_st vector[]=
+    libmemcached_io_vector_st vector[]=
     {
       { get_command, get_command_length },
       { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
@@ -345,7 +348,9 @@ static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr,
     LIBMEMCACHED_MEMCACHED_MGET_END();
 
     if (memcached_failed(rc))
+    {
       return rc;
+    }
 
     return memcached_set_error(*ptr, MEMCACHED_NO_SERVERS, MEMCACHED_AT);
   }
@@ -421,12 +426,22 @@ memcached_return_t memcached_mget_execute_by_key(memcached_st *ptr,
                                                  void *context,
                                                  unsigned int number_of_callbacks)
 {
-  if ((ptr->flags.binary_protocol) == 0)
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(ptr, false)))
+  {
+    return rc;
+  }
+
+  if (memcached_is_udp(ptr))
+  {
+    return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
+  }
+
+  if (memcached_is_binary(ptr) == false)
   {
     return MEMCACHED_NOT_SUPPORTED;
   }
 
-  memcached_return_t rc;
   memcached_callback_st *original_callbacks= ptr->callbacks;
   memcached_callback_st cb= {
     callback,
@@ -504,7 +519,7 @@ static memcached_return_t simple_binary_mget(memcached_st *ptr,
     request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
     request.message.header.request.bodylen= htonl((uint32_t)( key_length[x] + memcached_array_size(ptr->_namespace)));
 
-    struct libmemcached_io_vector_st vector[]=
+    libmemcached_io_vector_st vector[]=
     {
       { request.bytes, sizeof(request.bytes) },
       { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
@@ -539,12 +554,11 @@ static memcached_return_t simple_binary_mget(memcached_st *ptr,
 
     for (uint32_t x= 0; x < memcached_server_count(ptr); ++x)
     {
-      memcached_server_write_instance_st instance=
-        memcached_server_instance_fetch(ptr, x);
+      memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
 
       if (memcached_server_response_count(instance))
       {
-        if (memcached_io_write(instance, NULL, 0, true) == -1)
+        if (memcached_io_write(instance) == false)
         {
           memcached_server_response_reset(instance);
           memcached_io_reset(instance);
@@ -638,7 +652,7 @@ static memcached_return_t replication_binary_mget(memcached_st *ptr,
        * that we might have processed some of the responses etc. For now,
        * just make sure we work _correctly_
      */
-      struct libmemcached_io_vector_st vector[]=
+      libmemcached_io_vector_st vector[]=
       {
         { request.bytes, sizeof(request.bytes) },
         { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
index af49d2d54c1481b2f4898312cd21ba50427cca4c..a1e47ab9fac483795afc8cd4846e2446ee2d9cdf 100644 (file)
@@ -42,6 +42,7 @@ noinst_HEADERS+= \
                 libmemcached/server.hpp \
                 libmemcached/server_instance.h \
                 libmemcached/string.hpp \
+                libmemcached/udp.hpp \
                 libmemcached/virtual_bucket.h \
                 libmemcached/watchpoint.h
 
@@ -98,6 +99,7 @@ libmemcached_libmemcached_la_SOURCES+= \
                                       libmemcached/touch.cc \
                                       libmemcached/verbosity.cc \
                                       libmemcached/version.cc \
+                                      libmemcached/udp.cc \
                                       libmemcached/virtual_bucket.c
 
 libmemcached/options.cc: libmemcached/csl/parser.h
index 84fc2290e647d8f3913d2e58915f59b735bdd043..dca3c4d8276cc0c33c188f663571c5ad0a106812 100644 (file)
 
 #include <libmemcached/common.h>
 
-memcached_return_t initialize_query(memcached_st *self)
+memcached_return_t initialize_query(memcached_st *self, bool increment_query_id)
 {
   if (self == NULL)
   {
     return MEMCACHED_INVALID_ARGUMENTS;
   }
 
-  self->query_id++;
+  if (increment_query_id)
+  {
+    self->query_id++;
+  }
 
   if (self->state.is_time_for_rebuild)
   {
index 86c8e2d81db6ff44b15ffc271690e7afc8a5a336..943a37a3b996532801e4d030a36bf02610ec9103 100644 (file)
 
 #pragma once
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+memcached_return_t initialize_query(memcached_st *self, bool increment_query_id);
 
-LIBMEMCACHED_LOCAL
-  memcached_return_t initialize_query(memcached_st *self);
-
-LIBMEMCACHED_LOCAL
 memcached_return_t initialize_const_query(const memcached_st *self);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
index 85e5ed42b82460a69d6c6b364b0af682ed189919..7a321adeed1f4ee7ca6a38b57b43f84b7595105e 100644 (file)
@@ -44,30 +44,6 @@ enum memc_read_or_write {
   MEM_WRITE
 };
 
-/*
- * The udp request id consists of two seperate sections
- *   1) The thread id
- *   2) The message number
- * The thread id should only be set when the memcached_st struct is created
- * and should not be changed.
- *
- * The message num is incremented for each new message we send, this function
- * 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_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);
-  int msg_num= get_msg_num_from_request_id(cur_req);
-  int thread_id= get_thread_id_from_request_id(cur_req);
-
-  if (((++msg_num) & UDP_REQUEST_ID_THREAD_MASK) != 0)
-    msg_num= 0;
-
-  header->request_id= htons((uint16_t) (thread_id | msg_num));
-}
-
 /**
  * Try to fill the input buffer for a server with as much
  * data as possible.
@@ -192,7 +168,7 @@ static bool process_input_buffer(memcached_server_write_instance_st ptr)
 }
 
 static memcached_return_t io_wait(memcached_server_write_instance_st ptr,
-                                  memc_read_or_write read_or_write)
+                                  const memc_read_or_write read_or_write)
 {
   struct pollfd fds;
   fds.fd= ptr->fd;
@@ -294,9 +270,9 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr,
   return memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
 }
 
-static ssize_t io_flush(memcached_server_write_instance_st ptr,
-                        const bool with_flush,
-                        memcached_return_t *error)
+static bool io_flush(memcached_server_write_instance_st ptr,
+                     const bool with_flush,
+                     memcached_return_t& error)
 {
   /*
    ** We might want to purge the input buffer if we haven't consumed
@@ -310,27 +286,26 @@ static ssize_t io_flush(memcached_server_write_instance_st ptr,
 
     if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_STORED)
     {
-      return -1;
+      return false;
     }
   }
-  size_t return_length;
   char *local_write_ptr= ptr->write_buffer;
   size_t write_length= ptr->write_buffer_offset;
 
-  *error= MEMCACHED_SUCCESS;
+  error= MEMCACHED_SUCCESS;
 
   WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
 
   // UDP Sanity check, make sure that we are not sending somthing too big
   if (memcached_is_udp(ptr->root) and write_length > MAX_UDP_DATAGRAM_LENGTH)
   {
-    *error= MEMCACHED_WRITE_FAILURE;
-    return -1;
+    error= memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+    return false;
   }
 
   if (ptr->write_buffer_offset == 0 or (memcached_is_udp(ptr->root) and ptr->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH))
   {
-    return 0;
+    return true;
   }
 
   /* Looking for memory overflows */
@@ -340,7 +315,6 @@ static ssize_t io_flush(memcached_server_write_instance_st ptr,
   WATCHPOINT_ASSERT((ptr->write_buffer + MEMCACHED_MAX_BUFFER) >= (local_write_ptr + write_length));
 #endif
 
-  return_length= 0;
   while (write_length)
   {
     WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
@@ -354,11 +328,11 @@ static ssize_t io_flush(memcached_server_write_instance_st ptr,
     WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
     if (with_flush)
     {
-      sent_length= send(ptr->fd, local_write_ptr, write_length, MSG_NOSIGNAL|MSG_DONTWAIT);
+      sent_length= ::send(ptr->fd, local_write_ptr, write_length, MSG_NOSIGNAL|MSG_DONTWAIT);
     }
     else
     {
-      sent_length= send(ptr->fd, local_write_ptr, write_length, MSG_NOSIGNAL|MSG_DONTWAIT|MSG_MORE);
+      sent_length= ::send(ptr->fd, local_write_ptr, write_length, MSG_NOSIGNAL|MSG_DONTWAIT|MSG_MORE);
     }
 
     if (sent_length == SOCKET_ERROR)
@@ -395,44 +369,38 @@ static ssize_t io_flush(memcached_server_write_instance_st ptr,
           }
           else if (rc == MEMCACHED_TIMEOUT)
           {
-            *error= memcached_set_error(*ptr, MEMCACHED_TIMEOUT, MEMCACHED_AT);
-            return -1;
+            error= memcached_set_error(*ptr, MEMCACHED_TIMEOUT, MEMCACHED_AT);
+            return false;
           }
 
           memcached_quit_server(ptr, true);
-          *error= memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
-          return -1;
+          error= memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
+          return false;
         }
       case ENOTCONN:
       case EPIPE:
       default:
         memcached_quit_server(ptr, true);
-        *error= memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
-        WATCHPOINT_ASSERT(ptr->fd == -1);
-        return -1;
+        error= memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
+        WATCHPOINT_ASSERT(ptr->fd == INVALID_SOCKET);
+        return false;
       }
     }
 
     if (memcached_is_udp(ptr->root) and size_t(sent_length) != write_length)
     {
       memcached_quit_server(ptr, true);
-      *error= memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
-      return -1;
+      error= memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+      return false;
     }
 
     ptr->io_bytes_sent+= uint32_t(sent_length);
 
     local_write_ptr+= sent_length;
     write_length-= uint32_t(sent_length);
-    return_length+= uint32_t(sent_length);
   }
 
   WATCHPOINT_ASSERT(write_length == 0);
-  // Need to study this assert() WATCHPOINT_ASSERT(return_length ==
-  // ptr->write_buffer_offset);
-
-  // if we are a udp server, the begining of the buffer is reserverd for
-  // the upd frame header
   if (memcached_is_udp(ptr->root))
   {
     ptr->write_buffer_offset= UDP_DATAGRAM_HEADER_LENGTH;
@@ -442,7 +410,7 @@ static ssize_t io_flush(memcached_server_write_instance_st ptr,
     ptr->write_buffer_offset= 0;
   }
 
-  return (ssize_t) return_length;
+  return true;
 }
 
 memcached_return_t memcached_io_wait_for_write(memcached_server_write_instance_st ptr)
@@ -451,14 +419,16 @@ memcached_return_t memcached_io_wait_for_write(memcached_server_write_instance_s
 }
 
 memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr,
-                                     void *buffer, size_t length, ssize_t *nread)
+                                     void *buffer, size_t length, ssize_tnread)
 {
   assert_msg(ptr, "Programmer error, memcached_io_read() recieved an invalid memcached_server_write_instance_st"); // Programmer error
   char *buffer_ptr= static_cast<char *>(buffer);
 
   if (ptr->fd == INVALID_SOCKET)
   {
+#if 0
     assert_msg(int(ptr->state) <= int(MEMCACHED_SERVER_STATE_ADDRINFO), "Programmer error, invalid socket state");
+#endif
     return MEMCACHED_CONNECTION_FAILURE;
   }
 
@@ -469,7 +439,7 @@ memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr,
       ssize_t data_read;
       do
       {
-        data_read= recv(ptr->fd, ptr->read_buffer, MEMCACHED_MAX_BUFFER, MSG_DONTWAIT);
+        data_read= ::recv(ptr->fd, ptr->read_buffer, MEMCACHED_MAX_BUFFER, MSG_DONTWAIT);
         if (data_read == SOCKET_ERROR)
         {
           switch (get_socket_errno())
@@ -505,7 +475,7 @@ memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr,
           default:
             {
               memcached_quit_server(ptr, true);
-              *nread= -1;
+              nread= -1;
               return memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
             }
           }
@@ -523,8 +493,9 @@ memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr,
           */
           WATCHPOINT_STRING("We had a zero length recv()");
           memcached_quit_server(ptr, true);
-          *nread= -1;
-          return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+          nread= -1;
+          return memcached_set_error(*ptr, MEMCACHED_CONNECTION_FAILURE, MEMCACHED_AT, 
+                                     memcached_literal_param("::rec() returned zero, server has disconnected"));
         }
       } while (data_read <= 0);
 
@@ -556,7 +527,7 @@ memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr,
     }
   }
 
-  *nread = (ssize_t)(buffer_ptr - (char*)buffer);
+  nread= ssize_t(buffer_ptr - (char*)buffer);
 
   return MEMCACHED_SUCCESS;
 }
@@ -659,17 +630,10 @@ static ssize_t _io_write(memcached_server_write_instance_st ptr,
       WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
 
       memcached_return_t rc;
-      ssize_t sent_length= io_flush(ptr, with_flush, &rc);
-      if (sent_length == -1)
+      if (io_flush(ptr, with_flush, rc) == false)
       {
         return -1;
       }
-
-      /* If io_flush calls memcached_purge, sent_length may be 0 */
-      unlikely (sent_length != 0)
-      {
-        WATCHPOINT_ASSERT(sent_length == (ssize_t)buffer_end);
-      }
     }
   }
 
@@ -677,7 +641,7 @@ static ssize_t _io_write(memcached_server_write_instance_st ptr,
   {
     memcached_return_t rc;
     WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
-    if (io_flush(ptr, with_flush, &rc) == -1)
+    if (io_flush(ptr, with_flush, rc) == false)
     {
       return -1;
     }
@@ -686,15 +650,20 @@ static ssize_t _io_write(memcached_server_write_instance_st ptr,
   return (ssize_t) original_length;
 }
 
+bool memcached_io_write(memcached_server_write_instance_st ptr)
+{
+  return (_io_write(ptr, NULL, 0, true) >= 0);
+}
+
 ssize_t memcached_io_write(memcached_server_write_instance_st ptr,
-                           const void *buffer, size_t length, bool with_flush)
+                           const void *buffer, const size_t length, const bool with_flush)
 {
   return _io_write(ptr, buffer, length, with_flush);
 }
 
 ssize_t memcached_io_writev(memcached_server_write_instance_st ptr,
-                            const struct libmemcached_io_vector_st *vector,
-                            size_t number_of, bool with_flush)
+                            libmemcached_io_vector_st vector[],
+                            const size_t number_of, const bool with_flush)
 {
   ssize_t total= 0;
 
@@ -702,16 +671,19 @@ ssize_t memcached_io_writev(memcached_server_write_instance_st ptr,
   {
     ssize_t returnable;
 
-    if ((returnable= _io_write(ptr, vector->buffer, vector->length, false)) == -1)
+    if (vector->length)
     {
-      return -1;
+      if ((returnable= _io_write(ptr, vector->buffer, vector->length, false)) == -1)
+      {
+        return -1;
+      }
+      total+= returnable;
     }
-    total+= returnable;
   }
 
   if (with_flush)
   {
-    if (memcached_io_write(ptr, NULL, 0, true) == -1)
+    if (memcached_io_write(ptr) == false)
     {
       return -1;
     }
@@ -752,11 +724,12 @@ memcached_server_write_instance_st memcached_io_get_readable_server(memcached_st
 
   for (uint32_t x= 0; x < memcached_server_count(memc) && host_index < MAX_SERVERS_TO_POLL; ++x)
   {
-    memcached_server_write_instance_st instance=
-      memcached_server_instance_fetch(memc, x);
+    memcached_server_write_instance_st instance= memcached_server_instance_fetch(memc, x);
 
     if (instance->read_buffer_length > 0) /* I have data in the buffer */
+    {
       return instance;
+    }
 
     if (memcached_server_response_count(instance) > 0)
     {
@@ -827,7 +800,7 @@ void memcached_io_reset(memcached_server_write_instance_st ptr)
  */
 memcached_return_t memcached_safe_read(memcached_server_write_instance_st ptr,
                                        void *dta,
-                                       size_t size)
+                                       const size_t size)
 {
   size_t offset= 0;
   char *data= static_cast<char *>(dta);
@@ -837,14 +810,14 @@ memcached_return_t memcached_safe_read(memcached_server_write_instance_st ptr,
     ssize_t nread;
     memcached_return_t rc;
 
-    while (memcached_continue(rc= memcached_io_read(ptr, data + offset, size - offset, &nread))) { };
+    while (memcached_continue(rc= memcached_io_read(ptr, data + offset, size - offset, nread))) { };
 
     if (memcached_failed(rc))
     {
       return rc;
     }
 
-    offset+= (size_t) nread;
+    offset+= size_t(nread);
   }
 
   return MEMCACHED_SUCCESS;
@@ -858,7 +831,7 @@ memcached_return_t memcached_io_readline(memcached_server_write_instance_st ptr,
   total_nr= 0;
   bool line_complete= false;
 
-  while (not line_complete)
+  while (line_complete == false)
   {
     if (ptr->read_buffer_length == 0)
     {
@@ -868,7 +841,7 @@ memcached_return_t memcached_io_readline(memcached_server_write_instance_st ptr,
        * the logic.
      */
       ssize_t nread;
-      memcached_return_t rc= memcached_io_read(ptr, buffer_ptr, 1, &nread);
+      memcached_return_t rc= memcached_io_read(ptr, buffer_ptr, 1, nread);
       if (memcached_failed(rc) and rc == MEMCACHED_IN_PROGRESS)
       {
         memcached_quit_server(ptr, true);
@@ -880,7 +853,9 @@ memcached_return_t memcached_io_readline(memcached_server_write_instance_st ptr,
       }
 
       if (*buffer_ptr == '\n')
+      {
         line_complete= true;
+      }
 
       ++buffer_ptr;
       ++total_nr;
@@ -891,7 +866,9 @@ memcached_return_t memcached_io_readline(memcached_server_write_instance_st ptr,
     {
       *buffer_ptr = *ptr->read_ptr;
       if (*buffer_ptr == '\n')
+      {
         line_complete = true;
+      }
       --ptr->read_buffer_length;
       ++ptr->read_ptr;
       ++total_nr;
@@ -899,21 +876,10 @@ memcached_return_t memcached_io_readline(memcached_server_write_instance_st ptr,
     }
 
     if (total_nr == size)
+    {
       return MEMCACHED_PROTOCOL_ERROR;
+    }
   }
 
   return MEMCACHED_SUCCESS;
 }
-
-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;
-
-  struct udp_datagram_header_st *header= (struct udp_datagram_header_st *)ptr->write_buffer;
-  header->request_id= htons((uint16_t) (generate_udp_request_thread_id(thread_id)));
-  header->num_datagrams= htons(1);
-  header->sequence_number= htons(0);
-
-  return MEMCACHED_SUCCESS;
-}
index 6d3e2fa248831f4c7bceec1d6d9302eb0e475a16..c2711e28928ba8f71363ad0b3decf446dd62fd51 100644 (file)
 
 #pragma once
 
-#define MAX_UDP_DATAGRAM_LENGTH 1400
-#define UDP_DATAGRAM_HEADER_LENGTH 8
-#define UDP_REQUEST_ID_MSG_SIG_DIGITS 10
-#define UDP_REQUEST_ID_THREAD_MASK 0xFFFF << UDP_REQUEST_ID_MSG_SIG_DIGITS
-#define get_udp_datagram_request_id(A) ntohs((A)->request_id)
-#define get_udp_datagram_seq_num(A) ntohs((A)->sequence_number)
-#define get_udp_datagram_num_datagrams(A) ntohs((A)->num_datagrams)
-#define get_msg_num_from_request_id(A) ( (A) & (~(UDP_REQUEST_ID_THREAD_MASK)) )
-#define get_thread_id_from_request_id(A) ( (A) & (UDP_REQUEST_ID_THREAD_MASK) ) >> UDP_REQUEST_ID_MSG_SIG_DIGITS
-#define generate_udp_request_thread_id(A) (A) << UDP_REQUEST_ID_MSG_SIG_DIGITS
-#define UDP_REQUEST_ID_MAX_THREAD_ID get_thread_id_from_request_id(0xFFFF)
-
-struct udp_datagram_header_st
-{
-  uint16_t request_id;
-  uint16_t sequence_number;
-  uint16_t num_datagrams;
-  uint16_t reserved;
-};
-
 struct libmemcached_io_vector_st
 {
   const void *buffer;
   size_t length;
 };
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_LOCAL
-ssize_t memcached_io_write(memcached_server_write_instance_st ptr,
-                           const void *buffer, size_t length, bool with_flush);
-
-LIBMEMCACHED_LOCAL
-ssize_t memcached_io_writev(memcached_server_write_instance_st ptr,
-                            const struct libmemcached_io_vector_st *vector,
-                            size_t number_of, bool with_flush);
-
-#ifdef __cplusplus
-}
-#endif
index 23a4a6b412109812d1f761c9db4b5fe3442c5d5a..549f86a058eb2e4939b566bdbfad5c9fa5b352cf 100644 (file)
 
 #pragma once
 
-LIBMEMCACHED_LOCAL
+bool memcached_io_write(memcached_server_write_instance_st ptr);
+
+ssize_t memcached_io_write(memcached_server_write_instance_st ptr,
+                           const void *buffer, size_t length, bool with_flush);
+
+ssize_t memcached_io_writev(memcached_server_write_instance_st ptr,
+                            libmemcached_io_vector_st vector[],
+                            const size_t number_of, const bool with_flush);
+
 memcached_return_t memcached_io_wait_for_write(memcached_server_write_instance_st ptr);
 
-LIBMEMCACHED_LOCAL
 void memcached_io_reset(memcached_server_write_instance_st ptr);
 
-LIBMEMCACHED_LOCAL
 memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr,
-                                     void *buffer, size_t length, ssize_t *nread);
+                                     void *buffer, size_t length, ssize_tnread);
 
 /* Read a line (terminated by '\n') into the buffer */
-LIBMEMCACHED_LOCAL
 memcached_return_t memcached_io_readline(memcached_server_write_instance_st ptr,
                                          char *buffer_ptr,
                                          size_t size,
                                          size_t& total);
 
-LIBMEMCACHED_LOCAL
 void 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_write_instance_st ptr,
                                        void *dta,
-                                       size_t size);
-
-LIBMEMCACHED_LOCAL
-memcached_return_t memcached_io_init_udp_header(memcached_server_write_instance_st ptr,
-                                                uint16_t thread_id);
+                                       const size_t size);
 
-LIBMEMCACHED_LOCAL
 memcached_server_write_instance_st memcached_io_get_readable_server(memcached_st *memc);
 
-LIBMEMCACHED_LOCAL
 memcached_return_t memcached_io_slurp(memcached_server_write_instance_st ptr);
index 9f8783d8df4bee1097f3a03f720e486683aea6b8..6f8241d9deb5cdfafb4c30392bc1d7e00a345b47 100644 (file)
 /* These are private */ 
 #define memcached_is_allocated(__object) ((__object)->options.is_allocated)
 #define memcached_is_udp(__object) ((__object)->flags.use_udp)
+#define memcached_is_verify_key(__object) ((__object)->flags.verify_key)
+#define memcached_is_binary(__object) ((__object)->flags.binary_protocol)
 #define memcached_is_initialized(__object) ((__object)->options.is_initialized)
 #define memcached_is_purging(__object) ((__object)->state.is_purging)
 #define memcached_is_processing_input(__object) ((__object)->state.is_processing_input)
+
+#define memcached_is_buffering(__object) ((__object)->flags.buffer_requests)
+#define memcached_is_replying(__object) ((__object)->flags.reply)
+
+#define memcached_has_error(__object) ((__object)->error_messages)
+
 #define memcached_set_purging(__object, __value) ((__object)->state.is_purging= (__value))
 #define memcached_set_processing_input(__object, __value) ((__object)->state.is_processing_input= (__value))
 #define memcached_set_initialized(__object, __value) ((__object)->options.is_initialized(= (__value))
index ea98c729f02b92f5fdf187623dba9ec4a37b0ad0..e92468811ccf8b80ca3338eb7fffad7c9bb22b9c 100644 (file)
@@ -47,25 +47,15 @@ memcached_return_t memcached_key_test(memcached_st &memc,
     return memcached_set_error(memc, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT);
   }
 
-  if (not memc.flags.verify_key)
+  // If we don't need to verify the key, or we are using the binary protoocol,
+  // we just check the size of the key
+  if (memc.flags.verify_key == false or memc.flags.binary_protocol == true)
   {
     for (uint32_t x= 0; x < number_of_keys; x++)
     {
-      memcached_return_t rc= memcached_validate_key_length(*(key_length +x), false);
-      if (memcached_failed(rc))
-      {
-        return rc;
-      }
-    }
-
-    return MEMCACHED_SUCCESS;
-  }
-
-  if (memc.flags.binary_protocol)
-  {
-    for (uint32_t x= 0; x < number_of_keys; x++)
-    {
-      memcached_return_t rc= memcached_validate_key_length(*(key_length +x), false);
+      // We should set binary key, but the memcached server is broken for
+      // longer keys at the moment.
+      memcached_return_t rc= memcached_validate_key_length(*(key_length +x), false /* memc.flags.binary_protocol */);
       if (memcached_failed(rc))
       {
         return rc;
index 8c1e3acb12b1ac4a397dcf8e3a44aea25ee0f728..62052ada5ac25ec75bbd6759d6fb37567aa9cfab 100644 (file)
 #include <libmemcached/options.hpp>
 #include <libmemcached/virtual_bucket.h>
 
-#if 0
-static const memcached_st global_copy= {
-  .state= {
-    .is_purging= false, // .is_purging
-    .is_processing_input= false, // is_processing_input
-    .is_time_for_rebuild= false,
-  },
-  .flags= {
-    .auto_eject_hosts= false,
-    .binary_protocol= false,
-    .buffer_requests= false,
-    .hash_with_namespace= false,
-    .no_block= false,
-    .no_reply= false,
-    .randomize_replica_read= false,
-    .support_cas= false,
-    .tcp_nodelay= false,
-    .use_sort_hosts= false,
-    .use_udp= false,
-    .verify_key= false,
-    .tcp_keepalive= false,
-  },
-};
-#endif
-
 static inline bool _memcached_init(memcached_st *self)
 {
   self->state.is_purging= false;
@@ -76,7 +51,7 @@ static inline bool _memcached_init(memcached_st *self)
   self->flags.buffer_requests= false;
   self->flags.hash_with_namespace= false;
   self->flags.no_block= false;
-  self->flags.no_reply= false;
+  self->flags.reply= true;
   self->flags.randomize_replica_read= false;
   self->flags.support_cas= false;
   self->flags.tcp_nodelay= false;
index 36a33ae987b46feb06bba06734312e86dc95b5bd..4dd654199ed0cb858460140023c7af7dd1996392 100644 (file)
@@ -1,4 +1,44 @@
-#include "common.h"
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libmemcached/common.h>
+
 
 memcached_return_t memcached_purge(memcached_server_write_instance_st ptr)
 {
@@ -14,27 +54,30 @@ memcached_return_t memcached_purge(memcached_server_write_instance_st ptr)
     return MEMCACHED_SUCCESS;
   }
 
-  /* memcached_io_write and memcached_response may call memcached_purge
-    so we need to be able stop any recursion.. */
+  /*
+    memcached_io_write and memcached_response may call memcached_purge
+    so we need to be able stop any recursion.. 
+  */
   memcached_set_purging(root, true);
 
-  WATCHPOINT_ASSERT(ptr->fd != -1);
-  /* Force a flush of the buffer to ensure that we don't have the n-1 pending
-    requests buffered up.. */
-  if (memcached_io_write(ptr, NULL, 0, true) == -1)
+  WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
+  /* 
+    Force a flush of the buffer to ensure that we don't have the n-1 pending
+    requests buffered up.. 
+  */
+  if (memcached_io_write(ptr) == false)
   {
     memcached_set_purging(root, true);
 
     return memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
   }
-  WATCHPOINT_ASSERT(ptr->fd != -1);
+  WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
 
   uint32_t no_msg= memcached_server_response_count(ptr) - 1;
   if (no_msg > 0)
   {
     memcached_result_st result;
     memcached_result_st *result_ptr;
-    char buffer[SMALL_STRING_LEN];
 
     /*
      * We need to increase the timeout, because we might be waiting for
@@ -50,32 +93,34 @@ memcached_return_t memcached_purge(memcached_server_write_instance_st ptr)
     for (uint32_t x= 0; x < no_msg; x++)
     {
       memcached_result_reset(result_ptr);
-      memcached_return_t rc= memcached_read_one_response(ptr, buffer,
-                                                         sizeof (buffer),
-                                                         result_ptr);
+      memcached_return_t rc= memcached_read_one_response(ptr, result_ptr);
       /*
        * Purge doesn't care for what kind of command results that is received.
        * The only kind of errors I care about if is I'm out of sync with the
        * protocol or have problems reading data from the network..
      */
-      if (rc== MEMCACHED_PROTOCOL_ERROR || rc == MEMCACHED_UNKNOWN_READ_FAILURE)
+      if (rc== MEMCACHED_PROTOCOL_ERROR or rc == MEMCACHED_UNKNOWN_READ_FAILURE or rc == MEMCACHED_READ_FAILURE)
       {
         WATCHPOINT_ERROR(rc);
-        ret= rc;
         memcached_io_reset(ptr);
-        memcached_set_error(*ptr, rc, MEMCACHED_AT);
+        ret= rc;
+#if 0
+        ret= memcached_set_error(*ptr, rc, MEMCACHED_AT);
+#endif
       }
 
       if (ptr->root->callbacks != NULL)
       {
         memcached_callback_st cb = *ptr->root->callbacks;
-        if (rc == MEMCACHED_SUCCESS)
+        if (memcached_success(rc))
         {
           for (uint32_t y= 0; y < cb.number_of_callback; y++)
           {
             rc = (*cb.callback[y])(ptr->root, result_ptr, cb.context);
             if (rc != MEMCACHED_SUCCESS)
+            {
               break;
+            }
           }
         }
       }
index ffd4cd459cd767e71537e4e0971546f7fe53d70e..9aadd605f71ea802009686c1b20bb897507b2203 100644 (file)
@@ -61,11 +61,22 @@ void memcached_quit_server(memcached_server_st *ptr, bool io_death)
         request.message.header.request.magic = PROTOCOL_BINARY_REQ;
         request.message.header.request.opcode = PROTOCOL_BINARY_CMD_QUIT;
         request.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
-        rc= memcached_do(ptr, request.bytes, sizeof(request.bytes), true);
+
+        libmemcached_io_vector_st vector[]=
+        {
+          { request.bytes, sizeof(request.bytes) }
+        };
+
+        rc= memcached_vdo(ptr, vector, 1, true);
       }
       else
       {
-        rc= memcached_do(ptr, memcached_literal_param("quit\r\n"), true);
+        libmemcached_io_vector_st vector[]=
+        {
+          { memcached_literal_param("quit\r\n") }
+        };
+
+        rc= memcached_vdo(ptr, vector, 1, true);
       }
 
       WATCHPOINT_ASSERT(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_FETCH_NOTFINISHED);
@@ -129,7 +140,8 @@ void send_quit(memcached_st *ptr)
 
 void memcached_quit(memcached_st *ptr)
 {
-  if (memcached_failed(initialize_query(ptr)))
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(ptr, true)))
   {
     return;
   }
index 061f7401fee84a19dbd462a0564601ebce5a7276..e876123d4290ef9a468ac1ff7946a29875c2b777 100644 (file)
 #include <libmemcached/common.h>
 #include <libmemcached/string.hpp>
 
-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_write_instance_st ptr,
-                                                   char *buffer, size_t buffer_length,
-                                                   memcached_result_st *result);
-
-memcached_return_t memcached_read_one_response(memcached_server_write_instance_st ptr,
-                                               char *buffer, size_t buffer_length,
-                                               memcached_result_st *result)
-{
-  memcached_server_response_decrement(ptr);
-
-  if (result == NULL)
-  {
-    memcached_st *root= (memcached_st *)ptr->root;
-    result = &root->result;
-  }
-
-  memcached_return_t rc;
-  if (ptr->root->flags.binary_protocol)
-  {
-    rc= binary_read_one_response(ptr, buffer, buffer_length, result);
-  }
-  else
-  {
-    rc= textual_read_one_response(ptr, buffer, buffer_length, result);
-  }
-
-  unlikely(rc == MEMCACHED_UNKNOWN_READ_FAILURE or
-           rc == MEMCACHED_PROTOCOL_ERROR or
-           rc == MEMCACHED_CLIENT_ERROR or
-           rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE)
-  {
-    memcached_io_reset(ptr);
-  }
-
-  return rc;
-}
-
-memcached_return_t memcached_response(memcached_server_write_instance_st ptr,
-                                      char *buffer, size_t buffer_length,
-                                      memcached_result_st *result)
-{
-  /* We may have old commands in the buffer not set, first purge */
-  if ((ptr->root->flags.no_block) && (memcached_is_processing_input(ptr->root) == false))
-  {
-    (void)memcached_io_write(ptr, NULL, 0, true);
-  }
-
-  /*
-   * The previous implementation purged all pending requests and just
-   * returned the last one. Purge all pending messages to ensure backwards
-   * compatibility.
- */
-  if (ptr->root->flags.binary_protocol == false)
-  {
-    while (memcached_server_response_count(ptr) > 1)
-    {
-      memcached_return_t rc= memcached_read_one_response(ptr, buffer, buffer_length, result);
-
-      unlikely (rc != MEMCACHED_END &&
-                rc != MEMCACHED_STORED &&
-                rc != MEMCACHED_SUCCESS &&
-                rc != MEMCACHED_STAT &&
-                rc != MEMCACHED_DELETED &&
-                rc != MEMCACHED_NOTFOUND &&
-                rc != MEMCACHED_NOTSTORED &&
-                rc != MEMCACHED_DATA_EXISTS)
-        return rc;
-    }
-  }
-
-  return memcached_read_one_response(ptr, buffer, buffer_length, result);
-}
-
 static memcached_return_t textual_value_fetch(memcached_server_write_instance_st ptr,
                                               char *buffer,
                                               memcached_result_st *result)
 {
-  char *string_ptr;
-  char *end_ptr;
   char *next_ptr;
-  size_t value_length;
-  size_t to_read;
   ssize_t read_length= 0;
-
-  if (ptr->root->flags.use_udp)
-  {
-    return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
-  }
+  size_t value_length;
 
   WATCHPOINT_ASSERT(ptr->root);
-  end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;
+  char *end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;
 
   memcached_result_reset(result);
 
-  string_ptr= buffer;
+  char *string_ptr= buffer;
   string_ptr+= 6; /* "VALUE " */
 
 
@@ -162,29 +78,39 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
   }
 
   if (end_ptr == string_ptr)
+  {
     goto read_error;
+  }
 
   /* Flags fetch move past space */
   string_ptr++;
   if (end_ptr == string_ptr)
+  {
     goto read_error;
+  }
 
   for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++) {};
   result->item_flags= (uint32_t) strtoul(next_ptr, &string_ptr, 10);
 
   if (end_ptr == string_ptr)
+  {
     goto read_error;
+  }
 
   /* Length fetch move past space*/
   string_ptr++;
   if (end_ptr == string_ptr)
+  {
     goto read_error;
+  }
 
   for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++) {};
   value_length= (size_t)strtoull(next_ptr, &string_ptr, 10);
 
   if (end_ptr == string_ptr)
+  {
     goto read_error;
+  }
 
   /* Skip spaces */
   if (*string_ptr == '\r')
@@ -200,7 +126,9 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
   }
 
   if (end_ptr < string_ptr)
+  {
     goto read_error;
+  }
 
   /* We add two bytes so that we can walk the \r\n */
   if (memcached_failed(memcached_string_check(&result->value, value_length +2)))
@@ -217,8 +145,8 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
       We are null terminating through, which will most likely make
       some people lazy about using the return length.
     */
-    to_read= (value_length) + 2;
-    memcached_return_t rrc= memcached_io_read(ptr, value_ptr, to_read, &read_length);
+    size_t to_read= (value_length) + 2;
+    memcached_return_t rrc= memcached_io_read(ptr, value_ptr, to_read, read_length);
     if (memcached_failed(rrc) and rrc == MEMCACHED_IN_PROGRESS)
     {
       memcached_quit_server(ptr, true);
@@ -253,9 +181,11 @@ read_error:
 }
 
 static memcached_return_t textual_read_one_response(memcached_server_write_instance_st ptr,
-                                                    char *buffer, size_t buffer_length,
-                                                    memcached_result_st *result)
+                                                    char *buffer, const size_t buffer_length,
+                                                    memcached_result_st *result,
+                                                    uint64_t& numeric_value)
 {
+  numeric_value= UINT64_MAX;
   size_t total_read;
   memcached_return_t rc= memcached_io_readline(ptr, buffer, buffer_length, total_read);
 
@@ -263,36 +193,49 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta
   {
     return rc;
   }
+  assert(total_read);
 
   switch(buffer[0])
   {
-  case 'V': /* VALUE || VERSION */
-    if (buffer[1] == 'A') /* VALUE */
-    {
-      /* We add back in one because we will need to search for END */
-      memcached_server_response_increment(ptr);
-      return textual_value_fetch(ptr, buffer, result);
-    }
-    else if (buffer[1] == 'E') /* VERSION */
+  case 'V':
     {
-      return MEMCACHED_SUCCESS;
+      // VALUE
+      if (buffer[1] == 'A' and buffer[2] == 'L' and buffer[3] == 'U' and buffer[4] == 'E') /* VALUE */
+      {
+        /* We add back in one because we will need to search for END */
+        memcached_server_response_increment(ptr);
+        return textual_value_fetch(ptr, buffer, result);
+      }
+      // VERSION
+      else if (buffer[1] == 'E' and buffer[2] == 'R' and buffer[3] == 'S' and buffer[4] == 'I' and buffer[5] == 'O' and buffer[6] == 'N') /* VERSION */
+      {
+        return MEMCACHED_SUCCESS;
+      }
     }
-    else
+    break;
+
+  case 'O':
     {
-      WATCHPOINT_STRING(buffer);
-      return MEMCACHED_UNKNOWN_READ_FAILURE;
+      // OK
+      if (buffer[1] == 'K')
+      {
+        return MEMCACHED_SUCCESS;
+      }
     }
-  case 'O': /* OK */
-    return MEMCACHED_SUCCESS;
+    break;
 
-  case 'S': /* STORED STATS SERVER_ERROR */
+  case 'S':
     {
-      if (buffer[2] == 'A') /* STORED STATS */
+      // STAT
+      if (buffer[1] == 'T' and buffer[2] == 'A' and buffer[3] == 'T') /* STORED STATS */
       {
         memcached_server_response_increment(ptr);
         return MEMCACHED_STAT;
       }
-      else if (buffer[1] == 'E') /* SERVER_ERROR */
+      // SERVER_ERROR
+      else if (buffer[1] == 'E' and buffer[2] == 'R' and buffer[3] == 'V' and buffer[4] == 'E' and buffer[5] == 'R'
+               and buffer[6] == '_' 
+               and buffer[7] == 'E' and buffer[8] == 'R' and buffer[9] == 'R' and buffer[10] == 'O' and buffer[11] == 'R' )
       {
         if (total_read == memcached_literal_param_size("SERVER_ERROR"))
         {
@@ -317,92 +260,150 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta
 
         return memcached_set_error(*ptr, MEMCACHED_SERVER_ERROR, MEMCACHED_AT, startptr, size_t(endptr - startptr));
       }
-      else if (buffer[1] == 'T')
+      // STORED
+      else if (buffer[1] == 'T' and buffer[2] == 'O' and buffer[3] == 'R') //  and buffer[4] == 'E' and buffer[5] == 'D')
       {
         return MEMCACHED_STORED;
       }
-      else
+    }
+    break;
+
+  case 'D':
+    {
+      // DELETED
+      if (buffer[1] == 'E' and buffer[2] == 'L' and buffer[3] == 'E' and buffer[4] == 'T' and buffer[5] == 'E' and buffer[6] == 'D')
       {
-        WATCHPOINT_STRING(buffer);
-        return MEMCACHED_UNKNOWN_READ_FAILURE;
+        return MEMCACHED_DELETED;
       }
     }
-  case 'D': /* DELETED */
-    return MEMCACHED_DELETED;
+    break;
 
-  case 'N': /* NOT_FOUND */
+  case 'N':
     {
-      if (buffer[4] == 'F')
+      // NOT_FOUND
+      if (buffer[1] == 'O' and buffer[2] == 'T' 
+          and buffer[3] == '_'
+          and buffer[4] == 'F' and buffer[5] == 'O' and buffer[6] == 'U' and buffer[7] == 'N' and buffer[8] == 'D')
       {
         return MEMCACHED_NOTFOUND;
       }
-      else if (buffer[4] == 'S')
+      // NOT_STORED
+      else if (buffer[1] == 'O' and buffer[2] == 'T' 
+               and buffer[3] == '_'
+               and buffer[4] == 'S' and buffer[5] == 'T' and buffer[6] == 'O' and buffer[7] == 'R' and buffer[8] == 'E' and buffer[9] == 'D')
       {
         return MEMCACHED_NOTSTORED;
       }
-      else
-      {
-        WATCHPOINT_STRING(buffer);
-        return MEMCACHED_UNKNOWN_READ_FAILURE;
-      }
     }
+    break;
+
   case 'E': /* PROTOCOL ERROR or END */
     {
-      if (buffer[1] == 'N')
+      // END
+      if (buffer[1] == 'N' and buffer[2] == 'D')
       {
         return MEMCACHED_END;
       }
-      else if (buffer[1] == 'R')
+#if 0
+      // PROTOCOL_ERROR
+      else if (buffer[1] == 'R' and buffer[2] == 'O' and buffer[3] == 'T' and buffer[4] == 'O' and buffer[5] == 'C' and buffer[6] == 'O' and buffer[7] == 'L'
+               and buffer[8] == '_'
+               and buffer[9] == 'E' and buffer[10] == 'R' and buffer[11] == 'R' and buffer[12] == 'O' and buffer[13] == 'R')
       {
         return MEMCACHED_PROTOCOL_ERROR;
       }
-      else if (buffer[1] == 'X')
+#endif
+      // EXISTS
+      else if (buffer[1] == 'X' and buffer[2] == 'I' and buffer[3] == 'S' and buffer[4] == 'T' and buffer[5] == 'S')
       {
         return MEMCACHED_DATA_EXISTS;
       }
-      else
-      {
-        WATCHPOINT_STRING(buffer);
-        return MEMCACHED_UNKNOWN_READ_FAILURE;
-      }
-
     }
+    break;
+
   case 'T': /* TOUCHED */
     {
-      if (buffer[1] == 'O' and buffer[2] == 'U' 
-          and buffer[3] == 'C' and buffer[4] == 'H' 
-          and buffer[5] == 'E' and buffer[6] == 'D')
+      // TOUCHED
+      if (buffer[1] == 'O' and buffer[2] == 'U' and buffer[3] == 'C' and buffer[4] == 'H' and buffer[5] == 'E' and buffer[6] == 'D')
       {
         return MEMCACHED_SUCCESS;
       }
     }
-    return MEMCACHED_UNKNOWN_READ_FAILURE;
+    break;
 
-  case 'I': /* CLIENT ERROR */
-    /* We add back in one because we will need to search for END */
-    memcached_server_response_increment(ptr);
-    return MEMCACHED_ITEM;
+  case 'I': /* ITEM */
+    {
+      // ITEM
+      if (buffer[1] == 'T' and buffer[2] == 'E' and buffer[3] == 'M')
+      {
+        /* We add back in one because we will need to search for END */
+        memcached_server_response_increment(ptr);
+        return MEMCACHED_ITEM;
+      }
+    }
+    break;
 
   case 'C': /* CLIENT ERROR */
-    return MEMCACHED_CLIENT_ERROR;
-
-  default:
     {
-      unsigned long long auto_return_value;
+      // CLIENT_ERROR
+      if (buffer[1] == 'L' and buffer[2] == 'I' and buffer[3] == 'E' and buffer[4] == 'N' and buffer[5] == 'T'
+          and buffer[6] == '_'
+          and buffer[7] == 'E' and buffer[8] == 'R' and buffer[9] == 'R' and buffer[10] == 'O' and buffer[11] == 'R')
+      {
+        return MEMCACHED_CLIENT_ERROR;
+      }
+    }
+    break;
+
+  case '0': /* INCR/DECR response */
+  case '1': /* INCR/DECR response */
+  case '2': /* INCR/DECR response */
+  case '3': /* INCR/DECR response */
+  case '4': /* INCR/DECR response */
+  case '5': /* INCR/DECR response */
+  case '6': /* INCR/DECR response */
+  case '7': /* INCR/DECR response */
+  case '8': /* INCR/DECR response */
+  case '9': /* INCR/DECR response */
+    {
+      unsigned long long int auto_return_value= strtoull(buffer, (char **)NULL, 10);
 
-      if (sscanf(buffer, "%llu", &auto_return_value) == 1)
-        return MEMCACHED_SUCCESS;
+      if (auto_return_value == ULLONG_MAX and errno == ERANGE)
+      {
+        return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT,
+                                   memcached_literal_param("Numeric response was out of range"));
+      }
+      else if (errno == EINVAL)
+      {
+        return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT,
+                                   memcached_literal_param("Numeric response was out of range"));
+      }
+
+      numeric_value= uint64_t(auto_return_value);
 
       WATCHPOINT_STRING(buffer);
-      return MEMCACHED_UNKNOWN_READ_FAILURE;
+      return MEMCACHED_SUCCESS;
     }
+
+  default:
+    break;
   }
 
-  /* NOTREACHED */
+  buffer[total_read]= 0;
+#if 0
+  if (total_read >= sizeof("STORSTORED") -1)
+  {
+    fprintf(stderr, "%s:%d '%s', %.*s\n", __FILE__, __LINE__,
+            buffer, MEMCACHED_MAX_BUFFER, ptr->read_buffer);
+    assert(memcmp(buffer,"STORSTORED", sizeof("STORSTORED") -1));
+  }
+#endif
+  return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT,
+                             buffer, total_read);
 }
 
 static memcached_return_t binary_read_one_response(memcached_server_write_instance_st ptr,
-                                                   char *buffer, size_t buffer_length,
+                                                   char *buffer, const size_t buffer_length,
                                                    memcached_result_st *result)
 {
   memcached_return_t rc;
@@ -416,7 +417,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
 
   if (header.response.magic != PROTOCOL_BINARY_RES)
   {
-    return MEMCACHED_PROTOCOL_ERROR;
+    return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
   }
 
   /*
@@ -497,9 +498,9 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
     case PROTOCOL_BINARY_CMD_INCREMENT:
     case PROTOCOL_BINARY_CMD_DECREMENT:
       {
-        if (bodylen != sizeof(uint64_t) || buffer_length != sizeof(uint64_t))
+        if (bodylen != sizeof(uint64_t) or buffer_length != sizeof(uint64_t))
         {
-          return MEMCACHED_PROTOCOL_ERROR;
+          return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
         }
 
         WATCHPOINT_ASSERT(bodylen == buffer_length);
@@ -599,8 +600,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
     default:
       {
         /* Command not implemented yet! */
-        WATCHPOINT_ASSERT(0);
-        return MEMCACHED_PROTOCOL_ERROR;
+        return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
       }
     }
   }
@@ -673,11 +673,122 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
     case PROTOCOL_BINARY_RESPONSE_EINVAL:
     case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND:
     default:
-      /* @todo fix the error mappings */
-      rc= MEMCACHED_PROTOCOL_ERROR;
+      return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
       break;
     }
   }
 
   return rc;
 }
+
+static memcached_return_t _read_one_response(memcached_server_write_instance_st ptr,
+                                             char *buffer, const size_t buffer_length,
+                                             memcached_result_st *result,
+                                             uint64_t& numeric_value)
+{
+  memcached_server_response_decrement(ptr);
+
+  if (result == NULL)
+  {
+    memcached_st *root= (memcached_st *)ptr->root;
+    result = &root->result;
+  }
+
+  memcached_return_t rc;
+  if (memcached_is_binary(ptr->root))
+  {
+    rc= binary_read_one_response(ptr, buffer, buffer_length, result);
+  }
+  else
+  {
+    rc= textual_read_one_response(ptr, buffer, buffer_length, result, numeric_value);
+    assert(rc != MEMCACHED_PROTOCOL_ERROR);
+  }
+
+  if (rc == MEMCACHED_UNKNOWN_READ_FAILURE or
+      rc == MEMCACHED_READ_FAILURE or
+      rc == MEMCACHED_PROTOCOL_ERROR or
+      rc == MEMCACHED_CLIENT_ERROR or
+      rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE)
+  {
+    memcached_io_reset(ptr);
+  }
+
+  return rc;
+}
+
+memcached_return_t memcached_read_one_response(memcached_server_write_instance_st ptr,
+                                               memcached_result_st *result)
+{
+  uint64_t numeric_value;
+  char buffer[SMALL_STRING_LEN];
+
+  if (memcached_is_udp(ptr->root))
+  {
+    return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
+  }
+
+
+  return _read_one_response(ptr, buffer, sizeof(buffer), result, numeric_value);
+}
+
+memcached_return_t memcached_response(memcached_server_write_instance_st ptr,
+                                      char *buffer, size_t buffer_length,
+                                      memcached_result_st *result)
+{
+  uint64_t numeric_value;
+
+  return memcached_response(ptr, buffer, buffer_length, result, numeric_value);
+}
+
+memcached_return_t memcached_response(memcached_server_write_instance_st ptr,
+                                      char *buffer, size_t buffer_length,
+                                      memcached_result_st *result,
+                                      uint64_t& numeric_value)
+{
+  if (memcached_is_udp(ptr->root))
+  {
+    return memcached_set_error(*ptr, 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))
+  {
+    (void)memcached_io_write(ptr);
+  }
+
+  /*
+   * The previous implementation purged all pending requests and just
+   * 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)
+  {
+    memcached_result_st junked_result;
+    memcached_result_st *junked_result_ptr= memcached_result_create(ptr->root, &junked_result);
+
+    assert(junked_result_ptr);
+
+    while (memcached_server_response_count(ptr) > 1)
+    {
+      memcached_return_t rc= _read_one_response(ptr, buffer, buffer_length, junked_result_ptr, numeric_value);
+
+      // @TODO should we return an error on another but a bad read case?
+      if (rc != MEMCACHED_END and
+          rc != MEMCACHED_STORED and
+          rc != MEMCACHED_SUCCESS and
+          rc != MEMCACHED_STAT and
+          rc != MEMCACHED_DELETED and
+          rc != MEMCACHED_NOTFOUND and
+          rc != MEMCACHED_NOTSTORED and
+          rc != MEMCACHED_DATA_EXISTS)
+      {
+        memcached_result_free(junked_result_ptr);
+        return rc;
+      }
+    }
+    memcached_result_free(junked_result_ptr);
+  }
+
+  return _read_one_response(ptr, buffer, buffer_length, result, numeric_value);
+}
index 51f09998deba41e3f905e8b791fefa6a9cf28772..d9abdb8a3d31d685f118705daf7986873f202d7a 100644 (file)
 
 #pragma once
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* Read a single response from the server */
-LIBMEMCACHED_LOCAL
 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_write_instance_st ptr,
                                       char *buffer, size_t buffer_length,
                                       memcached_result_st *result);
 
-#ifdef __cplusplus
-}
-#endif
+memcached_return_t memcached_response(memcached_server_write_instance_st ptr,
+                                      char *buffer, size_t buffer_length,
+                                      memcached_result_st *result,
+                                      uint64_t& numeric_value);
index 2e9bdc635d547514f1ef557cd5642e2dfee602f7..902ccd872cf77ee7ede0903730a31c6c9bd96f3d 100644 (file)
@@ -133,9 +133,10 @@ memcached_return_t memcached_sasl_authenticate_connection(memcached_server_st *s
   }
 
   /* SANITY CHECK: SASL can only be used with the binary protocol */
-  if (server->root->flags.binary_protocol == false)
+  if (memcached_is_binary(server->root) == false)
   {
-    return MEMCACHED_PROTOCOL_ERROR;
+    return  memcached_set_error(*server, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+                                memcached_literal_param("memcached_sasl_authenticate_connection() is not supported via the ASCII protocol"));
   }
 
   /* Try to get the supported mech from the server. Servers without SASL
@@ -229,7 +230,7 @@ memcached_return_t memcached_sasl_authenticate_connection(memcached_server_st *s
   do {
     /* send the packet */
 
-    struct libmemcached_io_vector_st vector[]=
+    libmemcached_io_vector_st vector[]=
     {
       { request.bytes, sizeof(request.bytes) },
       { chosenmech, keylen },
index 7011fd240c68843a93667af8dbfa2d3d6135550c..f08f8bf077cdcc150ee98721dbcf3054e0beeac3 100644 (file)
@@ -50,7 +50,7 @@ static inline void _server_init(memcached_server_st *self, memcached_st *root,
   self->number_of_hosts= 0;
   self->cursor_active= 0;
   self->port= port;
-  self->fd= -1;
+  self->fd= INVALID_SOCKET;
   self->io_bytes_sent= 0;
   self->server_failure_counter= 0;
   self->server_failure_counter_query_id= 0;
@@ -88,11 +88,11 @@ static inline void _server_init(memcached_server_st *self, memcached_st *root,
 
 static memcached_server_st *_server_create(memcached_server_st *self, const memcached_st *memc)
 {
-  if (not self)
+  if (self == NULL)
   {
    self= libmemcached_xmalloc(memc, struct memcached_server_st);
 
-    if (not self)
+    if (self == NULL)
     {
       return NULL; /*  MEMCACHED_MEMORY_ALLOCATION_FAILURE */
     }
@@ -131,9 +131,8 @@ memcached_server_st *__server_create_with(memcached_st *memc,
 
   _server_init(self, const_cast<memcached_st *>(memc), hostname, port, weight, type);
 
-
   if (memc and memcached_is_udp(memc))
-  {
+  { 
     self->write_buffer_offset= UDP_DATAGRAM_HEADER_LENGTH;
     memcached_io_init_udp_header(self, 0);
   }
index d5994e852560b03bb165e527bef9455dc4c4ffee..f03dc356b05d993aaa339dd8a6b145843320193d 100644 (file)
@@ -83,7 +83,7 @@ memcached_server_list_append_with_weight(memcached_server_list_st ptr,
 
   memcached_string_t _hostname= { memcached_string_make_from_cstr(hostname) };
   /* @todo Check return type */
-  if (not __server_create_with(NULL, &new_host_list[count-1], _hostname, port, weight, port ? MEMCACHED_CONNECTION_TCP : MEMCACHED_CONNECTION_UNIX_SOCKET))
+  if (__server_create_with(NULL, &new_host_list[count-1], _hostname, port, weight, port ? MEMCACHED_CONNECTION_TCP : MEMCACHED_CONNECTION_UNIX_SOCKET) == NULL)
   {
     *error= memcached_set_errno(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
     return NULL;
index 239c789dcb1d808764bd292fe2f6c6e8d0b04610..d5d1c234b589f18d205b158d42eee31e1ccaad7c 100644 (file)
@@ -1,7 +1,40 @@
-/*
-*/
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
 
-#include "common.h"
+#include <libmemcached/common.h>
 
 static const char *memcached_stat_keys[] = {
   "pid",
@@ -34,13 +67,16 @@ struct local_context
   memcached_stat_fn func;
   void *context;
   const char *args;
+  const size_t args_length;
 
   local_context(memcached_stat_fn func_arg,
-               void *context_arg,
-               const char *args_arg) :
+                void *context_arg,
+                const char *args_arg,
+                const size_t args_length_arg) :
     func(func_arg),
     context(context_arg),
-    args(args_arg)
+    args(args_arg),
+    args_length(args_length_arg)
   { }
 };
 
@@ -53,7 +89,7 @@ static memcached_return_t set_data(memcached_stat_st *memc_stat, char *key, char
     WATCHPOINT_STRING(key);
     return MEMCACHED_UNKNOWN_STAT_KEY;
   }
-  else if (not strcmp("pid", key))
+  else if (strcmp("pid", key) == 0)
   {
     int64_t temp= strtoll(value, (char **)NULL, 10);
 
@@ -200,7 +236,7 @@ char *memcached_stat_get_value(const memcached_st *ptr, memcached_stat_st *memc_
 
   *error= MEMCACHED_SUCCESS;
 
-  if (not memcmp("pid", key, sizeof("pid") -1))
+  if (memcmp("pid", key, sizeof("pid") -1) == 0)
   {
     length= snprintf(buffer, SMALL_STRING_LEN,"%lld", (signed long long)memc_stat->pid);
   }
@@ -309,6 +345,7 @@ char *memcached_stat_get_value(const memcached_st *ptr, memcached_stat_st *memc_
 
 static memcached_return_t binary_stats_fetch(memcached_stat_st *memc_stat,
                                              const char *args,
+                                             const size_t args_length,
                                              memcached_server_write_instance_st instance,
                                              struct local_context *check)
 {
@@ -318,23 +355,15 @@ static memcached_return_t binary_stats_fetch(memcached_stat_st *memc_stat,
   request.message.header.request.opcode= PROTOCOL_BINARY_CMD_STAT;
   request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
 
-  if (args)
+  if (args_length)
   {
-    size_t len= strlen(args);
+    request.message.header.request.keylen= htons(uint16_t(args_length));
+    request.message.header.request.bodylen= htonl(uint32_t( args_length));
 
-    memcached_return_t rc= memcached_validate_key_length(len, true);
-    if (rc != MEMCACHED_SUCCESS)
-    {
-      return rc;
-    }
-
-    request.message.header.request.keylen= htons((uint16_t)len);
-    request.message.header.request.bodylen= htonl((uint32_t) len);
-
-    struct libmemcached_io_vector_st vector[]=
+    libmemcached_io_vector_st vector[]=
     {
       { request.bytes, sizeof(request.bytes) },
-      { args, len }
+      { args, args_length }
     };
 
     if (memcached_vdo(instance, vector, 2, true) != MEMCACHED_SUCCESS)
@@ -345,8 +374,12 @@ static memcached_return_t binary_stats_fetch(memcached_stat_st *memc_stat,
   }
   else
   {
-    if (memcached_do(instance, request.bytes,
-                     sizeof(request.bytes), true) != MEMCACHED_SUCCESS)
+    libmemcached_io_vector_st vector[]=
+    {
+      { request.bytes, sizeof(request.bytes) }
+    };
+
+    if (memcached_vdo(instance, vector, 1, true) != MEMCACHED_SUCCESS)
     {
       memcached_io_reset(instance);
       return MEMCACHED_WRITE_FAILURE;
@@ -359,9 +392,11 @@ static memcached_return_t binary_stats_fetch(memcached_stat_st *memc_stat,
     memcached_return_t rc= memcached_response(instance, buffer, sizeof(buffer), NULL);
 
     if (rc == MEMCACHED_END)
+    {
       break;
+    }
 
-    unlikely (rc != MEMCACHED_SUCCESS)
+    if (rc != MEMCACHED_SUCCESS)
     {
       memcached_io_reset(instance);
       return rc;
@@ -369,7 +404,7 @@ static memcached_return_t binary_stats_fetch(memcached_stat_st *memc_stat,
 
     if (memc_stat)
     {
-      unlikely((set_data(memc_stat, buffer, buffer + strlen(buffer) + 1)) == MEMCACHED_UNKNOWN_STAT_KEY)
+      if ((set_data(memc_stat, buffer, buffer + strlen(buffer) + 1)) == MEMCACHED_UNKNOWN_STAT_KEY)
       {
         WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY);
         WATCHPOINT_ASSERT(0);
@@ -387,9 +422,10 @@ static memcached_return_t binary_stats_fetch(memcached_stat_st *memc_stat,
     }
   } while (1);
 
-  /* shit... memcached_response will decrement the counter, so I need to
-   ** reset it.. todo: look at this and try to find a better solution.
- */
+  /* 
+   * memcached_response will decrement the counter, so I need to reset it..
+   * todo: look at this and try to find a better solution.  
+   * */
   instance->cursor_active= 0;
 
   return MEMCACHED_SUCCESS;
@@ -397,30 +433,21 @@ static memcached_return_t binary_stats_fetch(memcached_stat_st *memc_stat,
 
 static memcached_return_t ascii_stats_fetch(memcached_stat_st *memc_stat,
                                             const char *args,
+                                            const size_t args_length,
                                             memcached_server_write_instance_st instance,
                                             struct local_context *check)
 {
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-  int send_length;
-
-  if (args)
+  libmemcached_io_vector_st vector[]=
   {
-    send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "stats %s\r\n", args);
-  }
-  else
-  {
-    send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "stats\r\n");
-  }
+    { memcached_literal_param("stats ") },
+    { args, args_length },
+    { memcached_literal_param("\r\n") }
+  };
 
-  if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0)
-  {
-    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
-                               memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
-  }
-
-  memcached_return_t rc= memcached_do(instance, buffer, (size_t)send_length, true);
+  memcached_return_t rc= memcached_vdo(instance, vector, 3, true);
   if (memcached_success(rc))
   {
+    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
     while ((rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL)) == MEMCACHED_STAT)
     {
       char *string_ptr, *end_ptr;
@@ -456,9 +483,11 @@ static memcached_return_t ascii_stats_fetch(memcached_stat_st *memc_stat,
   }
 
   if (rc == MEMCACHED_END)
+  {
     return MEMCACHED_SUCCESS;
-  else
-    return rc;
+  }
+
+  return rc;
 }
 
 memcached_stat_st *memcached_stat(memcached_st *self, char *args, memcached_return_t *error)
@@ -469,29 +498,36 @@ memcached_stat_st *memcached_stat(memcached_st *self, char *args, memcached_retu
     error= &unused;
   }
 
-  memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(self)))
+  if (memcached_failed(*error= initialize_query(self, true)))
   {
-    *error= rc;
-
     return NULL;
   }
 
-  WATCHPOINT_ASSERT(error);
-
-  if (self->flags.use_udp)
+  if (memcached_is_udp(self))
   {
     *error= memcached_set_error(*self, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
-
     return NULL;
   }
 
-  memcached_stat_st *stats= libmemcached_xcalloc(self, memcached_server_count(self), memcached_stat_st);
-
-  if (not stats)
+  memcached_return_t rc;
+  size_t args_length= 0;
+  if (args)
   {
-    *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    args_length= strlen(args);
+    rc= memcached_validate_key_length(args_length, self->flags.binary_protocol);
+    if (memcached_failed(rc))
+    {
+      *error= memcached_set_error(*self, rc, MEMCACHED_AT);
+      return NULL;
+    }
+  }
+
+  WATCHPOINT_ASSERT(error);
 
+  memcached_stat_st *stats= libmemcached_xcalloc(self, memcached_server_count(self), memcached_stat_st);
+  if (stats == NULL)
+  {
+    *error= memcached_set_error(*self, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
     return NULL;
   }
 
@@ -499,24 +535,21 @@ memcached_stat_st *memcached_stat(memcached_st *self, char *args, memcached_retu
   rc= MEMCACHED_SUCCESS;
   for (uint32_t x= 0; x < memcached_server_count(self); x++)
   {
-    memcached_return_t temp_return;
-    memcached_server_write_instance_st instance;
-    memcached_stat_st *stat_instance;
-
-    stat_instance= stats +x;
+    memcached_stat_st* stat_instance= stats +x;
 
     stat_instance->pid= -1;
     stat_instance->root= self;
 
-    instance= memcached_server_instance_fetch(self, x);
+    memcached_server_write_instance_st instance= memcached_server_instance_fetch(self, x);
 
-    if (self->flags.binary_protocol)
+    memcached_return_t temp_return;
+    if (memcached_is_binary(self))
     {
-      temp_return= binary_stats_fetch(stat_instance, args, instance, NULL);
+      temp_return= binary_stats_fetch(stat_instance, args, args_length, instance, NULL);
     }
     else
     {
-      temp_return= ascii_stats_fetch(stat_instance, args, instance, NULL);
+      temp_return= ascii_stats_fetch(stat_instance, args, args_length, instance, NULL);
     }
 
     if (memcached_failed(temp_return))
@@ -534,31 +567,43 @@ memcached_return_t memcached_stat_servername(memcached_stat_st *memc_stat, char
                                              const char *hostname, in_port_t port)
 {
   memcached_st memc;
-  memcached_server_write_instance_st instance;
 
   memset(memc_stat, 0, sizeof(memcached_stat_st));
 
   memcached_st *memc_ptr= memcached_create(&memc);
-  if (not memc_ptr)
+  if (memc_ptr == NULL)
+  {
     return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-
-  memcached_server_add(&memc, hostname, port);
+  }
 
   memcached_return_t rc;
-  if ((rc= initialize_query(memc_ptr)) != MEMCACHED_SUCCESS)
+  if (memcached_failed(rc= memcached_server_add(&memc, hostname, port)))
   {
+    memcached_free(&memc);
     return rc;
   }
 
-  instance= memcached_server_instance_fetch(memc_ptr, 0);
-
-  if (memc.flags.binary_protocol)
+  if (memcached_success(rc= initialize_query(memc_ptr, true)))
   {
-    rc= binary_stats_fetch(memc_stat, args, instance, NULL);
-  }
-  else
-  {
-    rc= ascii_stats_fetch(memc_stat, args, instance, NULL);
+    size_t args_length= 0;
+    if (args)
+    {
+      args_length= strlen(args);
+      rc= memcached_validate_key_length(args_length, memc.flags.binary_protocol);
+    }
+
+    if (memcached_success(rc))
+    {
+      memcached_server_write_instance_st instance= memcached_server_instance_fetch(memc_ptr, 0);
+      if (memc.flags.binary_protocol)
+      {
+        rc= binary_stats_fetch(memc_stat, args, args_length, instance, NULL);
+      }
+      else
+      {
+        rc= ascii_stats_fetch(memc_stat, args, args_length, instance, NULL);
+      }
+    }
   }
 
   memcached_free(&memc);
@@ -617,11 +662,11 @@ static memcached_return_t call_stat_fn(memcached_st *ptr,
 
   if (ptr->flags.binary_protocol)
   {
-    rc= binary_stats_fetch(NULL, check->args, instance, check);
+    rc= binary_stats_fetch(NULL, check->args, check->args_length, instance, check);
   }
   else
   {
-    rc= ascii_stats_fetch(NULL, check->args, instance, check);
+    rc= ascii_stats_fetch(NULL, check->args, check->args_length, instance, check);
   }
 
   return rc;
@@ -631,7 +676,7 @@ memcached_return_t memcached_stat_execute(memcached_st *memc, const char *args,
 {
   memcached_version(memc);
 
- struct local_context check(func, context, args);
+ struct local_context check(func, context, args, args ? strlen(args) : 0);
 
  return memcached_server_execute(memc, call_stat_fn, (void *)&check);
 }
index 89bc8e879232523f964182a0a8a816daa7fbe279..2d0ae8fc5b4ce7e2693fd61fe84a30c0113a8509 100644 (file)
@@ -1,14 +1,41 @@
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
  *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
  *
- * Summary: Storage related functions, aka set, replace,..
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  */
 
+
 #include <libmemcached/common.h>
 
 enum memcached_storage_action_t {
@@ -47,9 +74,9 @@ static inline const char *storage_op_string(memcached_storage_action_t verb)
   return "set ";
 }
 
-static inline uint8_t get_com_code(memcached_storage_action_t verb, bool noreply)
+static inline uint8_t get_com_code(const memcached_storage_action_t verb, const bool reply)
 {
-  if (noreply)
+  if (reply == false)
   {
     switch (verb)
     {
@@ -97,22 +124,21 @@ static memcached_return_t memcached_send_binary(memcached_st *ptr,
                                                 memcached_server_write_instance_st server,
                                                 uint32_t server_key,
                                                 const char *key,
-                                                size_t key_length,
+                                                const size_t key_length,
                                                 const char *value,
-                                                size_t value_length,
-                                                time_t expiration,
-                                                uint32_t flags,
-                                                uint64_t cas,
-                                                bool flush,
+                                                const size_t value_length,
+                                                const time_t expiration,
+                                                const uint32_t flags,
+                                                const uint64_t cas,
+                                                const bool flush,
+                                                const bool reply,
                                                 memcached_storage_action_t verb)
 {
   protocol_binary_request_set request= {};
   size_t send_length= sizeof(request.bytes);
 
-  bool noreply= server->root->flags.no_reply;
-
   request.message.header.request.magic= PROTOCOL_BINARY_REQ;
-  request.message.header.request.opcode= get_com_code(verb, noreply);
+  request.message.header.request.opcode= get_com_code(verb, reply);
   request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->_namespace)));
   request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
   if (verb == APPEND_OP or verb == PREPEND_OP)
@@ -134,22 +160,9 @@ static memcached_return_t memcached_send_binary(memcached_st *ptr,
     request.message.header.request.cas= memcached_htonll(cas);
   }
 
-  if (server->root->flags.use_udp and flush == false)
-  {
-    size_t cmd_size= send_length + key_length + value_length;
-
-    if (cmd_size > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH)
-    {
-      return MEMCACHED_WRITE_FAILURE;
-    }
-    if (cmd_size + server->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
-    {
-      memcached_io_write(server, NULL, 0, true);
-    }
-  }
-
-  struct libmemcached_io_vector_st vector[]=
+  libmemcached_io_vector_st vector[]=
   {
+    { NULL, 0 },
     { request.bytes, send_length },
     { memcached_array_string(ptr->_namespace),  memcached_array_size(ptr->_namespace) },
     { key, key_length },
@@ -158,11 +171,11 @@ static memcached_return_t memcached_send_binary(memcached_st *ptr,
 
   /* write the header */
   memcached_return_t rc;
-  if ((rc= memcached_vdo(server, vector, 4, flush)) != MEMCACHED_SUCCESS)
+  if ((rc= memcached_vdo(server, vector, 5, flush)) != MEMCACHED_SUCCESS)
   {
     memcached_io_reset(server);
 
-    if (ptr->error_messages == NULL)
+    if (memcached_has_error(ptr))
     {
       memcached_set_error(*server, rc, MEMCACHED_AT);
     }
@@ -170,7 +183,7 @@ static memcached_return_t memcached_send_binary(memcached_st *ptr,
     return MEMCACHED_WRITE_FAILURE;
   }
 
-  if (verb == SET_OP && ptr->number_of_replicas > 0)
+  if (verb == SET_OP and ptr->number_of_replicas > 0)
   {
     request.message.header.request.opcode= PROTOCOL_BINARY_CMD_SETQ;
     WATCHPOINT_STRING("replicating");
@@ -185,7 +198,7 @@ static memcached_return_t memcached_send_binary(memcached_st *ptr,
 
       memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
 
-      if (memcached_vdo(instance, vector, 4, false) != MEMCACHED_SUCCESS)
+      if (memcached_vdo(instance, vector, 5, false) != MEMCACHED_SUCCESS)
       {
         memcached_io_reset(instance);
       }
@@ -201,7 +214,8 @@ static memcached_return_t memcached_send_binary(memcached_st *ptr,
     return MEMCACHED_BUFFERED;
   }
 
-  if (noreply)
+  // No reply always assumes success
+  if (reply == false)
   {
     return MEMCACHED_SUCCESS;
   }
@@ -212,121 +226,90 @@ static memcached_return_t memcached_send_binary(memcached_st *ptr,
 static memcached_return_t memcached_send_ascii(memcached_st *ptr,
                                                memcached_server_write_instance_st instance,
                                                const char *key,
-                                               size_t key_length,
+                                               const size_t key_length,
                                                const char *value,
-                                               size_t value_length,
-                                               time_t expiration,
-                                               uint32_t flags,
-                                               uint64_t cas,
-                                               bool flush,
-                                               memcached_storage_action_t verb)
+                                               const size_t value_length,
+                                               const time_t expiration,
+                                               const uint32_t flags,
+                                               const uint64_t cas,
+                                               const bool flush,
+                                               const bool reply,
+                                               const memcached_storage_action_t verb)
 {
-  size_t write_length;
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-
-  if (cas)
+  char flags_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+  int flags_buffer_length= snprintf(flags_buffer, sizeof(flags_buffer), " %u", flags);
+  if (size_t(flags_buffer_length) >= sizeof(flags_buffer) or flags_buffer_length < 0)
   {
-    int check_length;
-    check_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
-                           "%s %.*s%.*s %u %llu %lu %llu%s\r\n",
-                           storage_op_string(verb),
-                           memcached_print_array(ptr->_namespace),
-                           (int)key_length, key, flags,
-                           (unsigned long long)expiration, (unsigned long)value_length,
-                           (unsigned long long)cas,
-                           (ptr->flags.no_reply) ? " noreply" : "");
-    if (check_length >= MEMCACHED_DEFAULT_COMMAND_SIZE or check_length < 0)
-    {
-      return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
-                                 memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
-    }
-    write_length= check_length;
+    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                               memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
   }
-  else
-  {
-    char *buffer_ptr= buffer;
-    const char *command= storage_op_string(verb);
-
-    /* Copy in the command, no space needed, we handle that in the command function*/
-    memcpy(buffer_ptr, command, strlen(command));
-
-    /* Copy in the key prefix, switch to the buffer_ptr */
-    buffer_ptr= (char *)memcpy((char *)(buffer_ptr + strlen(command)), (char *)memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace));
-
-    /* Copy in the key, adjust point if a key prefix was used. */
-    buffer_ptr= (char *)memcpy(buffer_ptr + memcached_array_size(ptr->_namespace),
-                               key, key_length);
-    buffer_ptr+= key_length;
-    buffer_ptr[0]=  ' ';
-    buffer_ptr++;
-
-    write_length= (size_t)(buffer_ptr - buffer);
-    int check_length= snprintf(buffer_ptr, MEMCACHED_DEFAULT_COMMAND_SIZE -(size_t)(buffer_ptr - buffer),
-                               "%u %llu %lu%s\r\n",
-                               flags,
-                               (unsigned long long)expiration, (unsigned long)value_length,
-                               ptr->flags.no_reply ? " noreply" : "");
-    if ((size_t)check_length >= MEMCACHED_DEFAULT_COMMAND_SIZE -size_t(buffer_ptr - buffer) or check_length < 0)
-    {
-      return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
-                              memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
-    }
 
-    write_length+= (size_t)check_length;
-    WATCHPOINT_ASSERT(write_length < MEMCACHED_DEFAULT_COMMAND_SIZE);
+  char expiration_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+  int expiration_buffer_length= snprintf(expiration_buffer, sizeof(expiration_buffer), " %llu", (unsigned long long)expiration);
+  if (size_t(expiration_buffer_length) >= sizeof(expiration_buffer) or expiration_buffer_length < 0)
+  {
+    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                               memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
   }
 
-  if (ptr->flags.use_udp)
+  char value_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+  int value_buffer_length= snprintf(value_buffer, sizeof(value_buffer), " %llu", (unsigned long long)value_length);
+  if (size_t(value_buffer_length) >= sizeof(value_buffer) or value_buffer_length < 0)
   {
-    size_t cmd_size= write_length + value_length +2;
-    if (cmd_size > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH)
-    {
-      return memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
-    }
-
-    if (cmd_size + instance->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
-    {
-      memcached_io_write(instance, NULL, 0, true);
-    }
+    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                               memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
   }
 
-  if (write_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
+  char cas_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+  int cas_buffer_length= 0;
+  if (cas)
   {
-    return memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+    cas_buffer_length= snprintf(cas_buffer, sizeof(cas_buffer), " %llu", (unsigned long long)cas);
+    if (size_t(cas_buffer_length) >= sizeof(cas_buffer) or cas_buffer_length < 0)
+    {
+      return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                                 memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
+    }
   }
 
-  struct libmemcached_io_vector_st vector[]=
+  libmemcached_io_vector_st vector[]=
   {
-    { buffer, write_length },
+    { NULL, 0 },
+    { storage_op_string(verb), strlen(storage_op_string(verb))},
+    { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
+    { key, key_length },
+    { flags_buffer, flags_buffer_length },
+    { expiration_buffer, expiration_buffer_length },
+    { value_buffer, value_buffer_length },
+    { cas_buffer, cas_buffer_length },
+    { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
+    { memcached_literal_param("\r\n") },
     { value, value_length },
     { memcached_literal_param("\r\n") }
   };
 
-  if (memcached_is_udp(instance->root) and  (write_length +value_length +memcached_literal_param_size("\r\n") +UDP_DATAGRAM_HEADER_LENGTH > MAX_UDP_DATAGRAM_LENGTH))
+  /* Send command header */
+  memcached_return_t rc=  memcached_vdo(instance, vector, 12, flush);
+
+  // If we should not reply, return with MEMCACHED_SUCCESS, unless error
+  if (reply == false)
   {
-    return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT, memcached_literal_param("UDP packet is too large"));
+    return memcached_success(rc) ? MEMCACHED_SUCCESS : rc; 
+  }
+
+  if (flush == false)
+  {
+    return memcached_success(rc) ? MEMCACHED_BUFFERED : rc; 
   }
 
-  /* Send command header */
-  memcached_return_t rc=  memcached_vdo(instance, vector, 3, flush);
   if (rc == MEMCACHED_SUCCESS)
   {
-    if (ptr->flags.no_reply and flush)
-    {
-      rc= MEMCACHED_SUCCESS;
-    }
-    else if (flush == false)
-    {
-      rc= MEMCACHED_BUFFERED;
-    }
-    else
-    {
-      rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+    rc= memcached_response(instance, buffer, sizeof(buffer), NULL);
 
-      if (rc == MEMCACHED_STORED)
-      {
-        rc= MEMCACHED_SUCCESS;
-      }
+    if (rc == MEMCACHED_STORED)
+    {
+      return MEMCACHED_SUCCESS;
     }
   }
 
@@ -335,9 +318,10 @@ static memcached_return_t memcached_send_ascii(memcached_st *ptr,
     memcached_io_reset(instance);
   }
 
-  if (memcached_failed(rc) and ptr->error_messages == NULL)
+  assert(memcached_failed(rc));
+  if (memcached_has_error(ptr) == false)
   {
-    memcached_set_error(*ptr, rc, MEMCACHED_AT);
+    return memcached_set_error(*ptr, rc, MEMCACHED_AT);
   }
 
   return rc;
@@ -347,18 +331,18 @@ static inline memcached_return_t memcached_send(memcached_st *ptr,
                                                 const char *group_key, size_t group_key_length,
                                                 const char *key, size_t key_length,
                                                 const char *value, size_t value_length,
-                                                time_t expiration,
-                                                uint32_t flags,
-                                                uint64_t cas,
+                                                const time_t expiration,
+                                                const uint32_t flags,
+                                                const uint64_t cas,
                                                 memcached_storage_action_t verb)
 {
   memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(ptr)))
+  if (memcached_failed(rc= initialize_query(ptr, true)))
   {
     return rc;
   }
 
-  if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
+  if (memcached_failed(rc= memcached_validate_key_length(key_length, memcached_is_binary(ptr))))
   {
     return rc;
   }
@@ -374,23 +358,27 @@ static inline memcached_return_t memcached_send(memcached_st *ptr,
   WATCHPOINT_SET(instance->io_wait_count.read= 0);
   WATCHPOINT_SET(instance->io_wait_count.write= 0);
 
-  bool flush= (bool) ((instance->root->flags.buffer_requests && verb == SET_OP) ? 0 : 1);
-  if (ptr->flags.binary_protocol)
+
+  bool flush= true;
+  if (memcached_is_buffering(instance->root) and verb == SET_OP)
   {
-    rc= memcached_send_binary(ptr, instance, server_key,
-                              key, key_length,
-                              value, value_length, expiration,
-                              flags, cas, flush, verb);
+    flush= false;
   }
-  else
+
+  bool reply= memcached_is_replying(ptr);
+
+  if (memcached_is_binary(ptr))
   {
-    rc= memcached_send_ascii(ptr, instance,
-                             key, key_length,
-                             value, value_length, expiration,
-                             flags, cas, flush, verb);
+    return memcached_send_binary(ptr, instance, server_key,
+                                 key, key_length,
+                                 value, value_length, expiration,
+                                 flags, cas, flush, reply, verb);
   }
 
-  return rc;
+  return memcached_send_ascii(ptr, instance,
+                              key, key_length,
+                              value, value_length, expiration,
+                              flags, cas, flush, reply, verb);
 }
 
 
@@ -419,6 +407,11 @@ memcached_return_t memcached_add(memcached_st *ptr,
   rc= memcached_send(ptr, key, key_length,
                      key, key_length, value, value_length,
                      expiration, flags, 0, ADD_OP);
+
+  if (rc == MEMCACHED_NOTSTORED or rc == MEMCACHED_DATA_EXISTS)
+  {
+    memcached_set_error(*ptr, rc, MEMCACHED_AT);
+  }
   LIBMEMCACHED_MEMCACHED_ADD_END();
   return rc;
 }
@@ -534,11 +527,9 @@ memcached_return_t memcached_prepend_by_key(memcached_st *ptr,
                                             time_t expiration,
                                             uint32_t flags)
 {
-  memcached_return_t rc;
-  rc= memcached_send(ptr, group_key, group_key_length,
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, PREPEND_OP);
-  return rc;
+  return memcached_send(ptr, group_key, group_key_length,
+                        key, key_length, value, value_length,
+                        expiration, flags, 0, PREPEND_OP);
 }
 
 memcached_return_t memcached_append_by_key(memcached_st *ptr,
@@ -548,11 +539,9 @@ memcached_return_t memcached_append_by_key(memcached_st *ptr,
                                            time_t expiration,
                                            uint32_t flags)
 {
-  memcached_return_t rc;
-  rc= memcached_send(ptr, group_key, group_key_length,
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, APPEND_OP);
-  return rc;
+  return memcached_send(ptr, group_key, group_key_length,
+                        key, key_length, value, value_length,
+                        expiration, flags, 0, APPEND_OP);
 }
 
 memcached_return_t memcached_cas_by_key(memcached_st *ptr,
@@ -563,10 +552,8 @@ memcached_return_t memcached_cas_by_key(memcached_st *ptr,
                                         uint32_t flags,
                                         uint64_t cas)
 {
-  memcached_return_t rc;
-  rc= memcached_send(ptr, group_key, group_key_length,
-                     key, key_length, value, value_length,
-                     expiration, flags, cas, CAS_OP);
-  return rc;
+  return  memcached_send(ptr, group_key, group_key_length,
+                         key, key_length, value, value_length,
+                         expiration, flags, cas, CAS_OP);
 }
 
index 1107139d4f2a2cd7c7a8f95a960bd4c6ce34f31c..8505d7e679528f8e3181306c627f79170e3ab621 100644 (file)
@@ -42,20 +42,26 @@ static memcached_return_t ascii_touch(memcached_server_write_instance_st instanc
                                       const char *key, size_t key_length,
                                       time_t expiration)
 {
-  char buffer[21];
+  char expiration_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+  int expiration_buffer_length= snprintf(expiration_buffer, sizeof(expiration_buffer), " %llu", (unsigned long long)expiration);
+  if (size_t(expiration_buffer_length) >= sizeof(expiration_buffer) or expiration_buffer_length < 0)
+  {
+    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                               memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
+  }
 
-  int buffer_length= snprintf(buffer, sizeof(buffer), " %u", uint32_t(expiration));
-  struct libmemcached_io_vector_st vector[]=
+  libmemcached_io_vector_st vector[]=
   {
+    { NULL, 0 },
     { memcached_literal_param("touch ") },
     { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
     { key, key_length },
-    { buffer, buffer_length },
+    { expiration_buffer, expiration_buffer_length },
     { memcached_literal_param("\r\n") }
   };
 
   memcached_return_t rc;
-  if (memcached_failed(rc= memcached_vdo(instance, vector, 5, true)))
+  if (memcached_failed(rc= memcached_vdo(instance, vector, 6, true)))
   {
     memcached_io_reset(instance);
     return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
@@ -77,15 +83,16 @@ static memcached_return_t binary_touch(memcached_server_write_instance_st instan
   request.message.header.request.bodylen= htonl((uint32_t)(key_length +memcached_array_size(instance->root->_namespace) +request.message.header.request.extlen));
   request.message.body.expiration= htonl((uint32_t) expiration);
 
-  struct libmemcached_io_vector_st vector[]=
+  libmemcached_io_vector_st vector[]=
   {
+    { NULL, 0 },
     { request.bytes, sizeof(request.bytes) },
     { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
     { key, key_length }
   };
 
   memcached_return_t rc;
-  if (memcached_failed(rc= memcached_vdo(instance, vector, 3, true)))
+  if (memcached_failed(rc= memcached_vdo(instance, vector, 4, true)))
   {
     memcached_io_reset(instance);
     return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
@@ -109,7 +116,7 @@ memcached_return_t memcached_touch_by_key(memcached_st *ptr,
   LIBMEMCACHED_MEMCACHED_TOUCH_START();
 
   memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(ptr)))
+  if (memcached_failed(rc= initialize_query(ptr, true)))
   {
     return rc;
   }
@@ -137,7 +144,7 @@ memcached_return_t memcached_touch_by_key(memcached_st *ptr,
   }
 
   char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-  rc= memcached_read_one_response(instance, buffer, sizeof(buffer), NULL);
+  rc= memcached_response(instance, buffer, sizeof(buffer), NULL);
 
   if (rc == MEMCACHED_SUCCESS or rc == MEMCACHED_NOTFOUND)
   {
diff --git a/libmemcached/udp.cc b/libmemcached/udp.cc
new file mode 100644 (file)
index 0000000..905eedd
--- /dev/null
@@ -0,0 +1,77 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+/*
+ * The udp request id consists of two seperate sections
+ *   1) The thread id
+ *   2) The message number
+ * The thread id should only be set when the memcached_st struct is created
+ * and should not be changed.
+ *
+ * The message num is incremented for each new message we send, this function
+ * extracts the message number from message_id, increments it and then
+ * writes the new value back into the header
+ */
+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);
+  int msg_num= get_msg_num_from_request_id(cur_req);
+  int thread_id= get_thread_id_from_request_id(cur_req);
+
+  if (((++msg_num) & UDP_REQUEST_ID_THREAD_MASK) != 0)
+    msg_num= 0;
+
+  header->request_id= htons((uint16_t) (thread_id | msg_num));
+}
+
+bool memcached_io_init_udp_header(memcached_server_write_instance_st ptr, const uint16_t thread_id)
+{
+  if (thread_id > UDP_REQUEST_ID_MAX_THREAD_ID)
+  {
+    return MEMCACHED_FAILURE;
+  }
+
+  struct udp_datagram_header_st *header= (struct udp_datagram_header_st *)ptr->write_buffer;
+  header->request_id= htons(uint16_t((generate_udp_request_thread_id(thread_id))));
+  header->num_datagrams= htons(1);
+  header->sequence_number= htons(0);
+
+  return MEMCACHED_SUCCESS;
+}
diff --git a/libmemcached/udp.hpp b/libmemcached/udp.hpp
new file mode 100644 (file)
index 0000000..9cc5388
--- /dev/null
@@ -0,0 +1,59 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define MAX_UDP_DATAGRAM_LENGTH 1400
+#define UDP_DATAGRAM_HEADER_LENGTH 8
+#define UDP_REQUEST_ID_MSG_SIG_DIGITS 10
+#define UDP_REQUEST_ID_THREAD_MASK 0xFFFF << UDP_REQUEST_ID_MSG_SIG_DIGITS
+#define get_udp_datagram_request_id(A) ntohs((A)->request_id)
+#define get_udp_datagram_seq_num(A) ntohs((A)->sequence_number)
+#define get_udp_datagram_num_datagrams(A) ntohs((A)->num_datagrams)
+#define get_msg_num_from_request_id(A) ( (A) & (~(UDP_REQUEST_ID_THREAD_MASK)) )
+#define get_thread_id_from_request_id(A) ( (A) & (UDP_REQUEST_ID_THREAD_MASK) ) >> UDP_REQUEST_ID_MSG_SIG_DIGITS
+#define generate_udp_request_thread_id(A) (A) << UDP_REQUEST_ID_MSG_SIG_DIGITS
+#define UDP_REQUEST_ID_MAX_THREAD_ID get_thread_id_from_request_id(0xFFFF)
+
+struct udp_datagram_header_st
+{
+  uint16_t request_id;
+  uint16_t sequence_number;
+  uint16_t num_datagrams;
+  uint16_t reserved;
+};
+
+bool memcached_io_init_udp_header(memcached_server_write_instance_st ptr, const uint16_t thread_id);
+void increment_udp_message_id(memcached_server_write_instance_st ptr);
index 5564c7a90f7b894cb88b8349749daf9ddcbd40fa..334a3316288afd971fc22bb75b2093e1347815d9 100644 (file)
@@ -47,7 +47,7 @@ static memcached_return_t _set_verbosity(const memcached_st *,
                                          const memcached_server_st *server,
                                          void *context)
 {
 struct context_st *execute= (struct context_st *)context;
libmemcached_io_vector_st *vector= (libmemcached_io_vector_st *)context;
 
   memcached_st local_memc;
   memcached_st *memc_ptr= memcached_create(&local_memc);
@@ -56,16 +56,15 @@ static memcached_return_t _set_verbosity(const memcached_st *,
 
   if (rc == MEMCACHED_SUCCESS)
   {
-    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-
     memcached_server_write_instance_st instance= memcached_server_instance_fetch(memc_ptr, 0);
 
 
-    rc= memcached_do(instance, execute->buffer, execute->length, true);
+    rc= memcached_vdo(instance, vector, 4, true);
 
     if (rc == MEMCACHED_SUCCESS)
     {
-      rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+      char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+      rc= memcached_response(instance, buffer, sizeof(buffer), NULL);
     }
   }
 
@@ -76,22 +75,32 @@ static memcached_return_t _set_verbosity(const memcached_st *,
 
 memcached_return_t memcached_verbosity(memcached_st *ptr, uint32_t verbosity)
 {
-  int send_length;
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(ptr, false)))
+  {
+    return rc;
+  }
+
   memcached_server_fn callbacks[1];
 
   char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
 
-  send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
-                                 "verbosity %u\r\n", verbosity);
-  if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0)
+  int send_length= snprintf(buffer, sizeof(buffer), "%u", verbosity);
+  if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE or send_length < 0)
   {
     return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
                                memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
   }
 
-  struct context_st context = { (size_t)send_length, buffer };
+  libmemcached_io_vector_st vector[]=
+  {
+    { NULL, 0 },
+    { memcached_literal_param("verbosity ") },
+    { buffer, send_length },
+    { memcached_literal_param("\r\n") }
+  };
 
   callbacks[0]= _set_verbosity;
 
-  return memcached_server_cursor(ptr, callbacks, &context, 1);
+  return memcached_server_cursor(ptr, callbacks, vector, 1);
 }
index b70cf672278c7421257ab9cacdd3269e071454bd..b889bf4f21667804dffed75f120e80cd2dc8e7b1 100644 (file)
@@ -41,37 +41,14 @@ const char * memcached_lib_version(void)
   return LIBMEMCACHED_VERSION_STRING;
 }
 
-static inline memcached_return_t memcached_version_binary(memcached_st *ptr);
-static inline memcached_return_t memcached_version_textual(memcached_st *ptr);
-
-memcached_return_t memcached_version(memcached_st *ptr)
-{
-  memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(ptr)))
-  {
-    return rc;
-  }
-
-  if (ptr->flags.use_udp)
-  {
-    return MEMCACHED_NOT_SUPPORTED;
-  }
-
-  if (ptr->flags.binary_protocol)
-  {
-    rc= memcached_version_binary(ptr);
-  }
-  else
-  {
-    rc= memcached_version_textual(ptr);      
-  }
-
-  return rc;
-}
-
 static inline memcached_return_t memcached_version_textual(memcached_st *ptr)
 {
+  libmemcached_io_vector_st vector[]=
+  {
+    { memcached_literal_param("version\r\n") },
+  };
   memcached_return_t rc= MEMCACHED_SUCCESS;
+
   for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
   {
     memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
@@ -82,7 +59,7 @@ static inline memcached_return_t memcached_version_textual(memcached_st *ptr)
       continue;
     }
 
-    memcached_return_t rrc= memcached_do(instance, memcached_literal_param("version\r\n"), true);
+    memcached_return_t rrc= memcached_vdo(instance, vector, 1, true);
     if (memcached_failed(rrc))
     {
       (void)memcached_set_error(*instance, rrc, MEMCACHED_AT);
@@ -92,7 +69,7 @@ static inline memcached_return_t memcached_version_textual(memcached_st *ptr)
     }
 
     char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-    rrc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+    rrc= memcached_response(instance, buffer, sizeof(buffer), NULL);
     if (memcached_failed(rrc))
     {
       memcached_set_error(*instance, rrc, MEMCACHED_AT);
@@ -152,6 +129,11 @@ static inline memcached_return_t memcached_version_binary(memcached_st *ptr)
   request.message.header.request.opcode= PROTOCOL_BINARY_CMD_VERSION;
   request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
 
+  libmemcached_io_vector_st vector[]=
+  {
+    { request.bytes, sizeof(request.bytes) }
+  };
+
   memcached_return_t rc= MEMCACHED_SUCCESS;
   for (uint32_t x= 0; x < memcached_server_count(ptr); x++) 
   {
@@ -162,7 +144,7 @@ static inline memcached_return_t memcached_version_binary(memcached_st *ptr)
       continue;
     }
 
-    memcached_return_t rrc= memcached_do(instance, request.bytes, sizeof(request.bytes), true);
+    memcached_return_t rrc= memcached_vdo(instance, vector, 1, true);
     if (memcached_failed(rrc))
     {
       memcached_io_reset(instance);
@@ -173,8 +155,7 @@ static inline memcached_return_t memcached_version_binary(memcached_st *ptr)
 
   for (uint32_t x= 0; x < memcached_server_count(ptr); x++) 
   {
-    memcached_server_write_instance_st instance=
-      memcached_server_instance_fetch(ptr, x);
+    memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x);
 
     if (instance->major_version != UINT8_MAX)
     {
@@ -228,3 +209,28 @@ static inline memcached_return_t memcached_version_binary(memcached_st *ptr)
 
   return rc;
 }
+
+memcached_return_t memcached_version(memcached_st *ptr)
+{
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(ptr, true)))
+  {
+    return rc;
+  }
+
+  if (memcached_is_udp(ptr))
+  {
+    return MEMCACHED_NOT_SUPPORTED;
+  }
+
+  if (memcached_is_binary(ptr))
+  {
+    rc= memcached_version_binary(ptr);
+  }
+  else
+  {
+    rc= memcached_version_textual(ptr);      
+  }
+
+  return rc;
+}
index 7ff665b646fc4a6bb594719070c6eb9160f4c8e1..99f378d1656c76572472718467e9720cc46a444f 100644 (file)
@@ -48,11 +48,13 @@ pid_t libmemcached_util_getpid(const char *hostname, in_port_t port, memcached_r
   pid_t pid= -1;
 
   memcached_return_t unused;
-  if (not ret)
+  if (ret == NULL)
+  {
     ret= &unused;
+  }
 
   memcached_st *memc_ptr= memcached_create(NULL);
-  if (not memc_ptr)
+  if (memc_ptr == NULL)
   {
     *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
     return -1;
@@ -72,8 +74,7 @@ pid_t libmemcached_util_getpid(const char *hostname, in_port_t port, memcached_r
     }
     else if (rc == MEMCACHED_SOME_ERRORS) // Generic answer, we will now find the specific reason (if one exists)
     {
-      memcached_server_instance_st instance=
-        memcached_server_instance_by_position(memc_ptr, 0);
+      memcached_server_instance_st instance= memcached_server_instance_by_position(memc_ptr, 0);
 
       assert_msg(instance and instance->error_messages, " ");
       if (instance and instance->error_messages)
index a520ae879361863cebb27bfa214010fa6b3ed26f..320407a23012715afb8d63f03c3dcaae9fc67e03 100644 (file)
@@ -1,3 +1,2 @@
 set environment LIBTEST_IN_GDB=1
 run
-quit
diff --git a/m4/ax_cxx_gcc_abi_demangle.m4 b/m4/ax_cxx_gcc_abi_demangle.m4
new file mode 100644 (file)
index 0000000..11e8728
--- /dev/null
@@ -0,0 +1,58 @@
+# ===========================================================================
+#  http://www.gnu.org/software/autoconf-archive/ax_cxx_gcc_abi_demangle.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CXX_GCC_ABI_DEMANGLE
+#
+# DESCRIPTION
+#
+#   If the compiler supports GCC C++ ABI name demangling (has header
+#   cxxabi.h and abi::__cxa_demangle() function), define
+#   HAVE_GCC_ABI_DEMANGLE
+#
+#   Adapted from AX_CXX_RTTI by Luc Maisonobe
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Neil Ferguson <nferguso@eso.org>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 9
+
+AC_DEFUN([AX_CXX_GCC_ABI_DEMANGLE],
+[AC_CACHE_CHECK(whether the compiler supports GCC C++ ABI name demangling,
+ax_cv_cxx_gcc_abi_demangle,
+[AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ AC_TRY_COMPILE([#include <typeinfo>
+#include <cxxabi.h>
+#include <cstdlib>
+#include <string>
+
+template<typename TYPE>
+class A {};
+],[A<int> instance;
+int status = 0;
+char* c_name = 0;
+
+c_name = abi::__cxa_demangle(typeid(instance).name(), 0, 0, &status);
+
+std::string name(c_name);
+::free(c_name);
+
+return name == "A<int>";
+],
+ ax_cv_cxx_gcc_abi_demangle=yes, ax_cv_cxx_gcc_abi_demangle=no)
+ AC_LANG_RESTORE
+])
+if test "$ax_cv_cxx_gcc_abi_demangle" = yes; then
+  AC_DEFINE(HAVE_GCC_ABI_DEMANGLE,1,
+            [define if the compiler supports GCC C++ ABI name demangling])
+fi
+])
index 35b0a9134f71345c8be3514f1048af206c761077..23f0f89916e18d8cbb88b4b64fb9fb7874a38d0e 100644 (file)
@@ -202,8 +202,8 @@ valgrind-memstat: clients/memstat
        @cat tests/Xumemc.pid | xargs kill || echo "Failed to kill memcached server"
        @rm tests/Xumemc.pid
 
-test-mem: tests/var tests/testapp
-       @tests/testapp
+test-mem: tests/var tests/libmemcached-1.0/testapp
+       @tests/libmemcached-1.0/testapp
 
 test-sasl: tests/sasl
        @tests/sasl
@@ -229,8 +229,8 @@ test-memcapable: tests/var tests/memcapable
 pahole-mem: tests/testapp
        @$(PAHOLE_COMMAND)  tests/testapp
 
-gdb-mem: tests/testapp
-       @$(DEBUG_COMMAND)  tests/testapp
+gdb-mem: tests/var tests/libmemcached-1.0/testapp
+       @$(DEBUG_COMMAND)  tests/libmemcached-1.0/testapp
 
 gdb-sasl: tests/sasl
        @$(DEBUG_COMMAND)  tests/sasl
@@ -238,9 +238,6 @@ gdb-sasl: tests/sasl
 gdb-atom: tests/atomsmasher
        @$(DEBUG_COMMAND) tests/atomsmasher
 
-gdb-udp: tests/testudp
-       @$(DEBUG_COMMAND) tests/testudp
-
 gdb-plus: tests/testplus
        $(DEBUG_COMMAND) tests/testplus
 
@@ -268,9 +265,6 @@ valgrind-failure: tests/failure
 valgrind-atom: tests/atomsmasher
        $(VALGRIND_COMMAND) tests/atomsmasher
 
-valgrind-udp: tests/testudp
-       $(VALGRIND_COMMAND) tests/testudp
-
 valgrind-plus: tests/testplus
        @$(VALGRIND_COMMAND) tests/testplus
 
@@ -292,9 +286,6 @@ helgrind-mem: tests/testapp
 helgrind-atom: tests/atomsmasher
        @$(HELGRIND_COMMAND) tests/atomsmasher
 
-helgrind-udp: tests/testudp
-       @$(HELGRIND_COMMAND) tests/testudp
-
 helgrind-plus: tests/testplus
        @$(HELGRIND_COMMAND) tests/testplus
 
index 29c02b32193464ea793c6e5e19180bcf5a8dbc72..81653a1c8e68987bd2dedc4f90523d6a53724be2 100644 (file)
@@ -123,6 +123,9 @@ tests_testudp_LDADD= $(tests_testudp_DEPENDENCIES)
 check_PROGRAMS+= tests/testudp
 noinst_PROGRAMS+= tests/testudp
 
+test-udp: tests/testudp
+       @tests/testudp
+
 tests_testplus_SOURCES= tests/libmemcached-1.0/plus.cpp
 tests_testplus_CXXFLAGS = $(AM_CXXFLAGS) $(NO_EFF_CXX)
 tests_testplus_DEPENDENCIES= $(TESTS_LDADDS)
index 29009ce3e2d9a73bfcf1da91f95fba474a2f1e8b..dd2abef27d18de63078e232672f244707fe826d4 100644 (file)
@@ -95,7 +95,7 @@ using namespace libtest;
 #define GLOBAL_COUNT 10000
 #define GLOBAL2_COUNT 100
 #define SERVERS_TO_CREATE 5
-static uint32_t global_count;
+static uint32_t global_count= GLOBAL2_COUNT;
 
 static pairs_st *global_pairs;
 static const char *global_keys[GLOBAL_COUNT];
@@ -112,6 +112,16 @@ static test_return_t pre_binary(memcached_st *memc)
   return TEST_SUCCESS;
 }
 
+static memcached_return_t return_value_based_on_buffering(memcached_st *memc)
+{
+  if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS))
+  {
+    return MEMCACHED_BUFFERED;
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
 static memcached_st * create_single_instance_memcached(const memcached_st *original_memc, const char *options)
 {
   /*
@@ -384,7 +394,7 @@ static test_return_t clone_test(memcached_st *memc)
       test_true(memc_clone->ketama.weighted == memc->ketama.weighted);
       test_true(memc_clone->flags.binary_protocol == memc->flags.binary_protocol);
       test_true(memc_clone->flags.hash_with_namespace == memc->flags.hash_with_namespace);
-      test_true(memc_clone->flags.no_reply == memc->flags.no_reply);
+      test_true(memc_clone->flags.reply == memc->flags.reply);
       test_true(memc_clone->flags.use_udp == memc->flags.use_udp);
       test_true(memc_clone->flags.auto_eject_hosts == memc->flags.auto_eject_hosts);
       test_true(memc_clone->flags.randomize_replica_read == memc->flags.randomize_replica_read);
@@ -512,7 +522,7 @@ static test_return_t set_test(memcached_st *memc)
                                        test_literal_param("foo"),
                                        test_literal_param("when we sanitize"),
                                        time_t(0), (uint32_t)0);
-  test_true_got(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED, memcached_strerror(NULL, rc));
+  test_true_got(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED, memcached_strerror(NULL, rc));
 
   return TEST_SUCCESS;
 }
@@ -520,32 +530,34 @@ static test_return_t set_test(memcached_st *memc)
 static test_return_t append_test(memcached_st *memc)
 {
   memcached_return_t rc;
-  const char *key= "fig";
   const char *in_value= "we";
-  char *out_value= NULL;
   size_t value_length;
   uint32_t flags;
 
-  rc= memcached_flush(memc, 0);
-  test_compare(MEMCACHED_SUCCESS, rc);
-
-  rc= memcached_set(memc, key, strlen(key),
-                    in_value, strlen(in_value),
-                    (time_t)0, (uint32_t)0);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_flush(memc, 0));
 
-  rc= memcached_append(memc, key, strlen(key),
-                       " the", strlen(" the"),
-                       (time_t)0, (uint32_t)0);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_set(memc,
+                             test_literal_param(__func__),
+                             in_value, strlen(in_value),
+                             time_t(0), uint32_t(0)));
 
-  rc= memcached_append(memc, key, strlen(key),
-                       " people", strlen(" people"),
-                       (time_t)0, (uint32_t)0);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_append(memc,
+                                test_literal_param(__func__),
+                                " the", strlen(" the"),
+                                time_t(0), uint32_t(0)));
 
-  out_value= memcached_get(memc, key, strlen(key),
-                           &value_length, &flags, &rc);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_append(memc,
+                                test_literal_param(__func__),
+                                " people", strlen(" people"),
+                                time_t(0), uint32_t(0)));
+
+  char *out_value= memcached_get(memc,
+                                 test_literal_param(__func__),
+                                 &value_length, &flags, &rc);
   test_memcmp(out_value, "we the people", strlen("we the people"));
   test_compare(strlen("we the people"), value_length);
   test_compare(MEMCACHED_SUCCESS, rc);
@@ -556,40 +568,40 @@ static test_return_t append_test(memcached_st *memc)
 
 static test_return_t append_binary_test(memcached_st *memc)
 {
-  memcached_return_t rc;
-  const char *key= "numbers";
   uint32_t store_list[] = { 23, 56, 499, 98, 32847, 0 };
-  uint32_t *value;
-  size_t value_length;
-  uint32_t flags;
-  uint32_t x;
 
-  rc= memcached_flush(memc, 0);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_flush(memc, 0));
 
-  rc= memcached_set(memc,
-                    key, strlen(key),
-                    NULL, 0,
-                    (time_t)0, (uint32_t)0);
-  test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc));
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_set(memc,
+                             test_literal_param(__func__),
+                             NULL, 0,
+                             time_t(0), uint32_t(0)));
 
-  for (x= 0; store_list[x] ; x++)
+  size_t count= 0;
+  for (uint32_t x= 0; store_list[x] ; x++)
   {
-    rc= memcached_append(memc,
-                         key, strlen(key),
+    test_compare(MEMCACHED_SUCCESS,
+                 memcached_append(memc,
+                         test_literal_param(__func__),
                          (char *)&store_list[x], sizeof(uint32_t),
-                         (time_t)0, (uint32_t)0);
-    test_compare(MEMCACHED_SUCCESS, rc);
+                         time_t(0), uint32_t(0)));
+    count++;
   }
 
-  value= (uint32_t *)memcached_get(memc, key, strlen(key),
-                                   &value_length, &flags, &rc);
-  test_compare(value_length, sizeof(uint32_t) * x);
+  size_t value_length;
+  uint32_t flags;
+  memcached_return_t rc;
+  uint32_t *value= (uint32_t *)memcached_get(memc,
+                                             test_literal_param(__func__),
+                                             &value_length, &flags, &rc);
+  test_compare(value_length, sizeof(uint32_t) * count);
   test_compare(MEMCACHED_SUCCESS, rc);
 
-  for (uint32_t counter= x, *ptr= value; counter; counter--)
+  for (uint32_t counter= count, *ptr= value; counter; counter--)
   {
-    test_compare(*ptr, store_list[x - counter]);
+    test_compare(*ptr, store_list[count - counter]);
     ptr++;
   }
   free(value);
@@ -599,34 +611,31 @@ static test_return_t append_binary_test(memcached_st *memc)
 
 static test_return_t cas2_test(memcached_st *memc)
 {
-  memcached_return_t rc;
   const char *keys[]= {"fudge", "son", "food"};
   size_t key_length[]= {5, 3, 4};
   const char *value= "we the people";
   size_t value_length= strlen("we the people");
-  memcached_result_st results_obj;
-  memcached_result_st *results;
-  unsigned int set= 1;
 
   test_compare(MEMCACHED_SUCCESS, memcached_flush(memc, 0));
 
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, set);
+  test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, true));
 
   for (uint32_t x= 0; x < 3; x++)
   {
-    rc= memcached_set(memc, keys[x], key_length[x],
-                      keys[x], key_length[x],
-                      (time_t)50, (uint32_t)9);
-    test_compare(MEMCACHED_SUCCESS, rc);
+    test_compare(MEMCACHED_SUCCESS,
+                 memcached_set(memc, keys[x], key_length[x],
+                               keys[x], key_length[x],
+                               time_t(50), uint32_t(9)));
   }
 
   test_compare(MEMCACHED_SUCCESS, 
                memcached_mget(memc, keys, key_length, 3));
 
-  results= memcached_result_create(memc, &results_obj);
+  memcached_result_st *results= memcached_result_create(memc, NULL);
   test_true(results);
 
-  results= memcached_fetch_result(memc, &results_obj, &rc);
+  memcached_return_t rc;
+  results= memcached_fetch_result(memc, results, &rc);
   test_true(results);
   test_true(results->item_cas);
   test_compare(MEMCACHED_SUCCESS, rc);
@@ -636,51 +645,44 @@ static test_return_t cas2_test(memcached_st *memc)
   test_compare(strlen("we the people"), value_length);
   test_compare(MEMCACHED_SUCCESS, rc);
 
-  memcached_result_free(&results_obj);
+  memcached_result_free(results);
 
   return TEST_SUCCESS;
 }
 
 static test_return_t cas_test(memcached_st *memc)
 {
-  memcached_return_t rc;
-  const char *key= "fun";
-  size_t key_length= strlen(key);
-  const char *value= "we the people";
-  const char* keys[2] = { key, NULL };
-  size_t keylengths[2] = { strlen(key), 0 };
-  size_t value_length= strlen(value);
-  const char *value2= "change the value";
-  size_t value2_length= strlen(value2);
+  const char* keys[2] = { __func__, NULL };
+  size_t keylengths[2] = { strlen(__func__), 0 };
 
   memcached_result_st results_obj;
-  memcached_result_st *results;
-  unsigned int set= 1;
 
-  rc= memcached_flush(memc, 0);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS, memcached_flush(memc, 0));
 
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, set);
+  test_skip(true, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, true));
 
-  rc= memcached_set(memc, key, strlen(key),
-                    value, strlen(value),
-                    (time_t)0, (uint32_t)0);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_set(memc,
+                             test_literal_param(__func__),
+                             test_literal_param("we the people"),
+                             (time_t)0, (uint32_t)0));
 
   test_compare(MEMCACHED_SUCCESS,
                memcached_mget(memc, keys, keylengths, 1));
 
-  results= memcached_result_create(memc, &results_obj);
+  memcached_result_st *results= memcached_result_create(memc, &results_obj);
   test_true(results);
 
+  memcached_return_t rc;
   results= memcached_fetch_result(memc, &results_obj, &rc);
   test_true(results);
   test_compare(MEMCACHED_SUCCESS, rc);
   test_true(memcached_result_cas(results));
-  test_memcmp(value, memcached_result_value(results), value_length);
-  test_compare(strlen(memcached_result_value(results)), value_length);
-  test_compare(MEMCACHED_SUCCESS, rc);
-  uint64_t cas = memcached_result_cas(results);
+  test_memcmp("we the people", memcached_result_value(results), test_literal_param_size("we the people"));
+  test_compare(test_literal_param_size("we the people"),
+               strlen(memcached_result_value(results)));
+
+  uint64_t cas= memcached_result_cas(results);
 
 #if 0
   results= memcached_fetch_result(memc, &results_obj, &rc);
@@ -688,15 +690,21 @@ static test_return_t cas_test(memcached_st *memc)
   test_true(results == NULL);
 #endif
 
-  rc= memcached_cas(memc, key, key_length, value2, value2_length, 0, 0, cas);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_cas(memc,
+                             test_literal_param(__func__),
+                             test_literal_param("change the value"),
+                             0, 0, cas));
 
   /*
    * The item will have a new cas value, so try to set it again with the old
    * value. This should fail!
    */
-  rc= memcached_cas(memc, key, key_length, value2, value2_length, 0, 0, cas);
-  test_compare(MEMCACHED_DATA_EXISTS, rc);
+  test_compare(MEMCACHED_DATA_EXISTS,
+               memcached_cas(memc,
+                             test_literal_param(__func__),
+                             test_literal_param("change the value"),
+                             0, 0, cas));
 
   memcached_result_free(&results_obj);
 
@@ -705,32 +713,31 @@ static test_return_t cas_test(memcached_st *memc)
 
 static test_return_t prepend_test(memcached_st *memc)
 {
-  memcached_return_t rc;
   const char *key= "fig";
   const char *value= "people";
-  char *out_value= NULL;
-  size_t value_length;
-  uint32_t flags;
 
-  rc= memcached_flush(memc, 0);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_flush(memc, 0));
 
-  rc= memcached_set(memc, key, strlen(key),
-                    value, strlen(value),
-                    (time_t)0, (uint32_t)0);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_set(memc, key, strlen(key),
+                             value, strlen(value),
+                             time_t(0), uint32_t(0)));
 
-  rc= memcached_prepend(memc, key, strlen(key),
-                       "the ", strlen("the "),
-                       (time_t)0, (uint32_t)0);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_prepend(memc, key, strlen(key),
+                                 "the ", strlen("the "),
+                                 time_t(0), uint32_t(0)));
 
-  rc= memcached_prepend(memc, key, strlen(key),
-                       "we ", strlen("we "),
-                       (time_t)0, (uint32_t)0);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_prepend(memc, key, strlen(key),
+                                 "we ", strlen("we "),
+                                 time_t(0), uint32_t(0)));
 
-  out_value= memcached_get(memc, key, strlen(key),
+  size_t value_length;
+  uint32_t flags;
+  memcached_return_t rc;
+  char *out_value= memcached_get(memc, key, strlen(key),
                        &value_length, &flags, &rc);
   test_memcmp(out_value, "we the people", strlen("we the people"));
   test_compare(strlen("we the people"), value_length);
@@ -746,31 +753,21 @@ static test_return_t prepend_test(memcached_st *memc)
 */
 static test_return_t add_test(memcached_st *memc)
 {
-  memcached_return_t rc;
-  const char *key= "foo";
-  const char *value= "when we sanitize";
-  unsigned long long setting_value;
-
-  setting_value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NO_BLOCK);
+  test_compare_hint(return_value_based_on_buffering(memc),
+                    memcached_set(memc,
+                                  test_literal_param(__func__),
+                                  test_literal_param("when we sanitize"),
+                                  time_t(0), uint32_t(0)),
+                    memcached_last_error_message(memc));
 
-  rc= memcached_set(memc, key, strlen(key),
-                    value, strlen(value),
-                    (time_t)0, (uint32_t)0);
-  test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
   memcached_quit(memc);
-  rc= memcached_add(memc, key, strlen(key),
-                    value, strlen(value),
-                    (time_t)0, (uint32_t)0);
 
-  /* Too many broken OS'es have broken loopback in async, so we can't be sure of the result */
-  if (setting_value)
-  {
-    test_true(rc == MEMCACHED_NOTSTORED || rc == MEMCACHED_STORED);
-  }
-  else
-  {
-    test_true(rc == MEMCACHED_NOTSTORED || rc == MEMCACHED_DATA_EXISTS);
-  }
+  test_compare_hint(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) ? MEMCACHED_DATA_EXISTS : MEMCACHED_NOTSTORED,
+                    memcached_add(memc,
+                                  test_literal_param(__func__),
+                                  test_literal_param("try something else"),
+                                  time_t(0), uint32_t(0)),
+                    memcached_last_error_message(memc));
 
   return TEST_SUCCESS;
 }
@@ -800,37 +797,34 @@ static test_return_t add_wrapper(memcached_st *memc)
 
 static test_return_t replace_test(memcached_st *memc)
 {
-  memcached_return_t rc;
-  const char *key= "foo";
-  const char *value= "when we sanitize";
-  const char *original= "first we insert some data";
-
-  rc= memcached_set(memc, key, strlen(key),
-                    original, strlen(original),
-                    (time_t)0, (uint32_t)0);
-  test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+  test_compare(return_value_based_on_buffering(memc),
+               memcached_set(memc,
+                             test_literal_param(__func__),
+                             test_literal_param("when we sanitize"),
+                             time_t(0), uint32_t(0)));
 
   test_compare(MEMCACHED_SUCCESS,
-               memcached_replace(memc, key, strlen(key),
-                                 value, strlen(value),
-                                 (time_t)0, (uint32_t)0));
+               memcached_replace(memc,
+                                 test_literal_param(__func__),
+                                 test_literal_param("first we insert some data"),
+                                 time_t(0), uint32_t(0)));
 
   return TEST_SUCCESS;
 }
 
 static test_return_t delete_test(memcached_st *memc)
 {
-  memcached_return_t rc;
-  const char *key= "foo";
-  const char *value= "when we sanitize";
-
-  rc= memcached_set(memc, key, strlen(key),
-                    value, strlen(value),
-                    (time_t)0, (uint32_t)0);
-  test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+  test_compare(return_value_based_on_buffering(memc), 
+               memcached_set(memc, 
+                             test_literal_param(__func__),
+                             test_literal_param("when we sanitize"),
+                             time_t(0), uint32_t(0)));
 
-  rc= memcached_delete(memc, key, strlen(key), (time_t)0);
-  test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+  test_compare_hint(return_value_based_on_buffering(memc),
+                    memcached_delete(memc, 
+                                     test_literal_param(__func__),
+                                     time_t(0)),
+                    memcached_last_error_message(memc));
 
   return TEST_SUCCESS;
 }
@@ -845,13 +839,11 @@ static test_return_t flush_test(memcached_st *memc)
   return TEST_SUCCESS;
 }
 
-static memcached_return_t  server_function(const memcached_st *ptr,
-                                           const memcached_server_st *server,
-                                           void *context)
+static memcached_return_t  server_function(const memcached_st *,
+                                           const memcached_server_st *,
+                                           void *)
 {
-  (void)ptr; (void)server; (void)context;
   /* Do Nothing */
-
   return MEMCACHED_SUCCESS;
 }
 
@@ -871,7 +863,6 @@ static test_return_t bad_key_test(memcached_st *memc)
   memcached_return_t rc;
   const char *key= "foo bad";
   uint32_t flags;
-  memcached_st *memc_clone;
 
   uint64_t query_id= memcached_query_id(memc);
   
@@ -880,7 +871,7 @@ static test_return_t bad_key_test(memcached_st *memc)
 
   test_compare(query_id, memcached_query_id(memc)); // We should not increase the query_id for memcached_behavior_get()
 
-  memc_clone= memcached_clone(NULL, memc);
+  memcached_st *memc_clone= memcached_clone(NULL, memc);
   test_true(memc_clone);
 
   query_id= memcached_query_id(memc_clone);
@@ -993,24 +984,24 @@ static memcached_return_t read_through_trigger(memcached_st *memc,
 
 static test_return_t read_through(memcached_st *memc)
 {
-  memcached_return_t rc;
-  const char *key= "foo";
-  char *string;
-  size_t string_length;
-  uint32_t flags;
   memcached_trigger_key_fn cb= (memcached_trigger_key_fn)read_through_trigger;
 
-  string= memcached_get(memc, key, strlen(key),
-                        &string_length, &flags, &rc);
+  size_t string_length;
+  uint32_t flags;
+  memcached_return_t rc;
+  char *string= memcached_get(memc,
+                              test_literal_param(__func__),
+                              &string_length, &flags, &rc);
 
   test_compare(MEMCACHED_NOTFOUND, rc);
   test_false(string_length);
   test_false(string);
 
-  rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_GET_FAILURE, *(void **)&cb);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_callback_set(memc, MEMCACHED_CALLBACK_GET_FAILURE, *(void **)&cb));
 
-  string= memcached_get(memc, key, strlen(key),
+  string= memcached_get(memc,
+                        test_literal_param(__func__),
                         &string_length, &flags, &rc);
 
   test_compare(MEMCACHED_SUCCESS, rc);
@@ -1019,7 +1010,8 @@ static test_return_t read_through(memcached_st *memc)
   test_strcmp(READ_THROUGH_VALUE, string);
   free(string);
 
-  string= memcached_get(memc, key, strlen(key),
+  string= memcached_get(memc,
+                        test_literal_param(__func__),
                         &string_length, &flags, &rc);
 
   test_compare(MEMCACHED_SUCCESS, rc);
@@ -1035,17 +1027,19 @@ static test_return_t read_through(memcached_st *memc)
 static test_return_t get_test(memcached_st *memc)
 {
   memcached_return_t rc;
-  const char *key= "foo";
   char *string;
   size_t string_length;
   uint32_t flags;
 
   uint64_t query_id= memcached_query_id(memc);
-  rc= memcached_delete(memc, key, strlen(key), (time_t)0);
-  test_true(rc == MEMCACHED_BUFFERED || rc == MEMCACHED_NOTFOUND);
+  rc= memcached_delete(memc,
+                       test_literal_param(__func__),
+                       time_t(0));
+  test_true_got(rc == MEMCACHED_BUFFERED or rc == MEMCACHED_NOTFOUND, memcached_last_error_message(memc));
   test_compare(query_id +1, memcached_query_id(memc));
 
-  string= memcached_get(memc, key, strlen(key),
+  string= memcached_get(memc,
+                        test_literal_param(__func__),
                         &string_length, &flags, &rc);
 
   test_compare_got(MEMCACHED_NOTFOUND, rc, memcached_strerror(NULL, rc));
@@ -1057,14 +1051,14 @@ static test_return_t get_test(memcached_st *memc)
 
 static test_return_t get_test2(memcached_st *memc)
 {
-  const char *key= "foo";
   const char *value= "when we sanitize";
 
   uint64_t query_id= memcached_query_id(memc);
-  memcached_return_t rc= memcached_set(memc, key, strlen(key),
-                                       value, strlen(value),
-                                       (time_t)0, (uint32_t)0);
-  test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+  test_compare(return_value_based_on_buffering(memc),
+               memcached_set(memc,
+                             test_literal_param(__func__),
+                             value, strlen(value),
+                             time_t(0), uint32_t(0)));
   test_compare(query_id +1, memcached_query_id(memc));
 
   query_id= memcached_query_id(memc);
@@ -1072,7 +1066,9 @@ static test_return_t get_test2(memcached_st *memc)
 
   uint32_t flags;
   size_t string_length;
-  char *string= memcached_get(memc, key, strlen(key),
+  memcached_return_t rc;
+  char *string= memcached_get(memc,
+                              test_literal_param(__func__),
                               &string_length, &flags, &rc);
   test_compare(query_id +1, memcached_query_id(memc));
 
@@ -1091,11 +1087,11 @@ static test_return_t set_test2(memcached_st *memc)
 {
   for (uint32_t x= 0; x < 10; x++)
   {
-    memcached_return_t rc= memcached_set(memc,
-                                         test_literal_param("foo"),
-                                         test_literal_param("train in the brain"),
-                                         time_t(0), uint32_t(0));
-    test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+    test_compare(return_value_based_on_buffering(memc),
+                 memcached_set(memc,
+                               test_literal_param("foo"),
+                               test_literal_param("train in the brain"),
+                               time_t(0), uint32_t(0)));
   }
 
   return TEST_SUCCESS;
@@ -1120,10 +1116,11 @@ static test_return_t set_test3(memcached_st *memc)
     snprintf(key, sizeof(key), "foo%u", x);
 
     uint64_t query_id= memcached_query_id(memc);
-    memcached_return_t rc= memcached_set(memc, key, strlen(key),
-                                         &value[0], value.size(),
-                                         (time_t)0, (uint32_t)0);
-    test_true_got(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED, memcached_strerror(NULL, rc));
+    test_compare_hint(return_value_based_on_buffering(memc),
+                      memcached_set(memc, key, strlen(key),
+                                    &value[0], value.size(),
+                                    time_t(0), uint32_t(0)),
+                      memcached_last_error_message(memc));
     test_compare(query_id +1, memcached_query_id(memc));
   }
 
@@ -1132,7 +1129,6 @@ static test_return_t set_test3(memcached_st *memc)
 
 static test_return_t get_test3(memcached_st *memc)
 {
-  const char *key= "foo";
   size_t value_length= 8191;
 
   std::vector<char> value;
@@ -1142,20 +1138,23 @@ static test_return_t get_test3(memcached_st *memc)
     value.push_back(char(x % 127));
   }
 
-  memcached_return_t rc;
-  rc= memcached_set(memc, key, strlen(key),
-                    &value[0], value.size(),
-                    (time_t)0, (uint32_t)0);
-  test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+  test_compare_hint(return_value_based_on_buffering(memc),
+                    memcached_set(memc,
+                                  test_literal_param(__func__),
+                                  &value[0], value.size(),
+                                  time_t(0), uint32_t(0)),
+                    memcached_last_error_message(memc));
 
   size_t string_length;
   uint32_t flags;
-  char *string= memcached_get(memc, key, strlen(key),
+  memcached_return_t rc;
+  char *string= memcached_get(memc,
+                              test_literal_param(__func__),
                               &string_length, &flags, &rc);
 
   test_compare(MEMCACHED_SUCCESS, rc);
   test_true(string);
-  test_compare(string_length, value_length);
+  test_compare(value.size(), string_length);
   test_memcmp(string, &value[0], string_length);
 
   free(string);
@@ -1165,7 +1164,6 @@ static test_return_t get_test3(memcached_st *memc)
 
 static test_return_t get_test4(memcached_st *memc)
 {
-  const char *key= "foo";
   size_t value_length= 8191;
 
   std::vector<char> value;
@@ -1175,21 +1173,25 @@ static test_return_t get_test4(memcached_st *memc)
     value.push_back(char(x % 127));
   }
 
-  memcached_return_t rc= memcached_set(memc, key, strlen(key),
-                                       &value[0], value.size(),
-                                       (time_t)0, (uint32_t)0);
-  test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+  test_compare_hint(return_value_based_on_buffering(memc),
+                    memcached_set(memc,
+                                  test_literal_param(__func__),
+                                  &value[0], value.size(),
+                                  time_t(0), uint32_t(0)),
+                    memcached_last_error_message(memc));
 
   for (uint32_t x= 0; x < 10; x++)
   {
     uint32_t flags;
     size_t string_length;
-    char *string= memcached_get(memc, key, strlen(key),
+    memcached_return_t rc;
+    char *string= memcached_get(memc,
+                                test_literal_param(__func__),
                                 &string_length, &flags, &rc);
 
     test_compare(MEMCACHED_SUCCESS, rc);
     test_true(string);
-    test_compare(string_length, value_length);
+    test_compare(value.size(), string_length);
     test_memcmp(string, &value[0], string_length);
     free(string);
   }
@@ -1213,14 +1215,18 @@ static test_return_t get_test5(memcached_st *memc)
   uint32_t flags;
   size_t rlen;
 
-  memcached_return_t rc= memcached_set(memc, keys[0], lengths[0],
-                                     keys[0], lengths[0], 0, 0);
+  test_compare_hint(return_value_based_on_buffering(memc),
+                    memcached_set(memc, keys[0], lengths[0],
+                                  keys[0], lengths[0],
+                                  time_t(0), uint32_t(0)),
+                    memcached_last_error_message(memc));
   test_compare(MEMCACHED_SUCCESS, memcached_mget(memc, keys, lengths, test_array_length(keys)));
 
   memcached_result_st results_obj;
   memcached_result_st *results= memcached_result_create(memc, &results_obj);
   test_true(results);
 
+  memcached_return_t rc;
   results= memcached_fetch_result(memc, &results_obj, &rc);
   test_true(results);
 
@@ -1247,12 +1253,14 @@ static test_return_t mget_end(memcached_st *memc)
   size_t lengths[]= { 3, 4 };
   const char *values[]= { "fjord", "41" };
 
-  memcached_return_t rc;
-
   // Set foo and foo2
   for (size_t x= 0; x < test_array_length(keys); x++)
   {
-    test_compare(MEMCACHED_SUCCESS, memcached_set(memc, keys[x], lengths[x], values[x], strlen(values[x]), (time_t)0, (uint32_t)0));
+    test_compare(MEMCACHED_SUCCESS,
+                 memcached_set(memc,
+                               keys[x], lengths[x],
+                               values[x], strlen(values[x]),
+                               time_t(0), uint32_t(0)));
   }
 
   char *string;
@@ -1260,10 +1268,14 @@ static test_return_t mget_end(memcached_st *memc)
   uint32_t flags;
 
   // retrieve both via mget
-  test_compare(MEMCACHED_SUCCESS, memcached_mget(memc, keys, lengths, test_array_length(keys)));
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_mget(memc,
+                              keys, lengths,
+                              test_array_length(keys)));
 
   char key[MEMCACHED_MAX_KEY];
   size_t key_length;
+  memcached_return_t rc;
 
   // this should get both
   for (size_t x= 0; x < test_array_length(keys); x++)
@@ -1288,8 +1300,8 @@ static test_return_t mget_end(memcached_st *memc)
   test_null(string);
 
   // now get just one
-  rc= memcached_mget(memc, keys, lengths, 1);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_mget(memc, keys, lengths, 1));
 
   string= memcached_fetch(memc, key, &key_length, &string_length, &flags, &rc);
   test_compare(key_length, lengths[0]);
@@ -1369,25 +1381,24 @@ static test_return_t increment_with_initial_test(memcached_st *memc)
 
 static test_return_t decrement_test(memcached_st *memc)
 {
-  uint64_t new_number;
-  memcached_return_t rc;
-  const char *value= "3";
-
-  rc= memcached_set(memc,
-                    test_literal_param("number"),
-                    value, strlen(value),
-                    (time_t)0, (uint32_t)0);
-  test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+  test_compare(return_value_based_on_buffering(memc),
+               memcached_set(memc,
+                             test_literal_param(__func__),
+                             test_literal_param("3"),
+                             time_t(0), uint32_t(0)));
+  // Make sure we flush the value we just set
+  test_compare(MEMCACHED_SUCCESS, memcached_flush_buffers(memc));
 
+  uint64_t new_number;
   test_compare(MEMCACHED_SUCCESS,
                memcached_decrement(memc,
-                                   test_literal_param("number"),
+                                   test_literal_param(__func__),
                                    1, &new_number));
   test_compare(uint64_t(2), new_number);
 
   test_compare(MEMCACHED_SUCCESS,
                memcached_decrement(memc,
-                                   test_literal_param("number"),
+                                   test_literal_param(__func__),
                                    1, &new_number));
   test_compare(uint64_t(1), new_number);
 
@@ -1398,21 +1409,23 @@ static test_return_t decrement_with_initial_test(memcached_st *memc)
 {
   test_skip(true, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
 
-  uint64_t new_number;
   uint64_t initial= 3;
 
   test_compare(MEMCACHED_SUCCESS, memcached_flush_buffers(memc));
 
+  uint64_t new_number;
   test_compare(MEMCACHED_SUCCESS,
                memcached_decrement_with_initial(memc,
-                                                test_literal_param("number"),
-                                                1, initial, 0, &new_number));
+                                                test_literal_param(__func__),
+                                                1, initial, 
+                                                0, &new_number));
   test_compare(new_number, initial);
 
   test_compare(MEMCACHED_SUCCESS,
                memcached_decrement_with_initial(memc,
-                                                test_literal_param("number"),
-                                                1, initial, 0, &new_number));
+                                                test_literal_param(__func__),
+                                                1, initial, 
+                                                0, &new_number));
   test_compare(new_number, (initial - 1));
 
   return TEST_SUCCESS;
@@ -1420,24 +1433,28 @@ static test_return_t decrement_with_initial_test(memcached_st *memc)
 
 static test_return_t increment_by_key_test(memcached_st *memc)
 {
-  uint64_t new_number;
-  memcached_return_t rc;
   const char *master_key= "foo";
   const char *key= "number";
   const char *value= "0";
 
-  rc= memcached_set_by_key(memc, master_key, strlen(master_key),
-                           key, strlen(key),
-                           value, strlen(value),
-                           (time_t)0, (uint32_t)0);
-  test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+  test_compare(return_value_based_on_buffering(memc),
+               memcached_set_by_key(memc, master_key, strlen(master_key),
+                                    key, strlen(key),
+                                    value, strlen(value),
+                                    time_t(0), uint32_t(0)));
+  
+  // Make sure we flush the value we just set
+  test_compare(MEMCACHED_SUCCESS, memcached_flush_buffers(memc));
 
+  uint64_t new_number;
   test_compare(MEMCACHED_SUCCESS,
-               memcached_increment_by_key(memc, master_key, strlen(master_key), key, strlen(key), 1, &new_number));
+               memcached_increment_by_key(memc, master_key, strlen(master_key),
+                                          key, strlen(key), 1, &new_number));
   test_compare(uint64_t(1), new_number);
 
   test_compare(MEMCACHED_SUCCESS,
-               memcached_increment_by_key(memc, master_key, strlen(master_key), key, strlen(key), 1, &new_number));
+               memcached_increment_by_key(memc, master_key, strlen(master_key),
+                                          key, strlen(key), 1, &new_number));
   test_compare(uint64_t(2), new_number);
 
   return TEST_SUCCESS;
@@ -1448,21 +1465,20 @@ static test_return_t increment_with_initial_by_key_test(memcached_st *memc)
   test_skip(true, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
 
   uint64_t new_number;
-  memcached_return_t rc;
   const char *master_key= "foo";
   const char *key= "number";
   uint64_t initial= 0;
 
-  rc= memcached_increment_with_initial_by_key(memc, master_key, strlen(master_key),
-                                              key, strlen(key),
-                                              1, initial, 0, &new_number);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_increment_with_initial_by_key(memc, master_key, strlen(master_key),
+                                                       key, strlen(key),
+                                                       1, initial, 0, &new_number));
   test_compare(new_number, initial);
 
-  rc= memcached_increment_with_initial_by_key(memc, master_key, strlen(master_key),
-                                              key, strlen(key),
-                                              1, initial, 0, &new_number);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_increment_with_initial_by_key(memc, master_key, strlen(master_key),
+                                                       key, strlen(key),
+                                                       1, initial, 0, &new_number));
   test_compare(new_number, (initial +1));
 
   return TEST_SUCCESS;
@@ -1471,15 +1487,14 @@ static test_return_t increment_with_initial_by_key_test(memcached_st *memc)
 static test_return_t decrement_by_key_test(memcached_st *memc)
 {
   uint64_t new_number;
-  memcached_return_t rc;
   const char *value= "3";
 
-  rc= memcached_set_by_key(memc,
-                           test_literal_param("foo"),
-                           test_literal_param("number"),
-                           value, strlen(value),
-                           (time_t)0, (uint32_t)0);
-  test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+  test_compare(return_value_based_on_buffering(memc),
+               memcached_set_by_key(memc,
+                                    test_literal_param("foo"),
+                                    test_literal_param("number"),
+                                    value, strlen(value),
+                                    (time_t)0, (uint32_t)0));
 
   test_compare(MEMCACHED_SUCCESS,
                memcached_decrement_by_key(memc,
@@ -1529,12 +1544,11 @@ static test_return_t binary_increment_with_prefix_test(memcached_st *orig_memc)
 
   test_compare(MEMCACHED_SUCCESS, memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, (void *)"namespace:"));
 
-  memcached_return_t rc;
-  rc= memcached_set(memc,
-                    test_literal_param("number"),
-                    test_literal_param("0"),
-                    (time_t)0, (uint32_t)0);
-  test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+  test_compare(return_value_based_on_buffering(memc),
+               memcached_set(memc,
+                             test_literal_param("number"),
+                             test_literal_param("0"),
+                             (time_t)0, (uint32_t)0));
 
   uint64_t new_number;
   test_compare(MEMCACHED_SUCCESS, memcached_increment(memc, 
@@ -1553,20 +1567,20 @@ static test_return_t binary_increment_with_prefix_test(memcached_st *orig_memc)
 
 static test_return_t quit_test(memcached_st *memc)
 {
-  memcached_return_t rc;
-  const char *key= "fudge";
   const char *value= "sanford and sun";
 
-  rc= memcached_set(memc, key, strlen(key),
-                    value, strlen(value),
-                    (time_t)10, (uint32_t)3);
-  test_true_got(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED, memcached_strerror(NULL, rc));
+  test_compare(return_value_based_on_buffering(memc),
+               memcached_set(memc,
+                             test_literal_param(__func__),
+                             value, strlen(value),
+                             (time_t)10, (uint32_t)3));
   memcached_quit(memc);
 
-  rc= memcached_set(memc, key, strlen(key),
-                    value, strlen(value),
-                    (time_t)50, (uint32_t)9);
-  test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+  test_compare(return_value_based_on_buffering(memc),
+               memcached_set(memc,
+                             test_literal_param(__func__),
+                             value, strlen(value),
+                             (time_t)50, (uint32_t)9));
 
   return TEST_SUCCESS;
 }
@@ -1693,16 +1707,15 @@ static test_return_t mget_result_function(memcached_st *memc)
   size_t counter;
   memcached_execute_fn callbacks[1];
 
-  /* We need to empty the server before continueing test */
-  test_compare(MEMCACHED_SUCCESS,
-               memcached_flush(memc, 0));
   for (uint32_t x= 0; x < 3; x++)
   {
-    memcached_return_t rc= memcached_set(memc, keys[x], key_length[x],
-                                         keys[x], key_length[x],
-                                         (time_t)50, (uint32_t)9);
-    test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+    test_compare(return_value_based_on_buffering(memc), 
+                 memcached_set(memc, keys[x], key_length[x],
+                               keys[x], key_length[x],
+                               time_t(50), uint32_t(9)));
   }
+  test_compare(MEMCACHED_SUCCESS, memcached_flush_buffers(memc));
+  memcached_quit(memc);
 
   test_compare(MEMCACHED_SUCCESS,
                memcached_mget(memc, keys, key_length, 3));
@@ -1728,10 +1741,6 @@ static test_return_t mget_test(memcached_st *memc)
   char *return_value;
   size_t return_value_length;
 
-  /* We need to empty the server before continueing test */
-  test_compare(MEMCACHED_SUCCESS,
-               memcached_flush(memc, 0));
-
   test_compare(MEMCACHED_SUCCESS,
                memcached_mget(memc, keys, key_length, 3));
 
@@ -2106,36 +2115,25 @@ static test_return_t MEMCACHED_BEHAVIOR_TCP_KEEPIDLE_test(memcached_st *memc)
   return TEST_SUCCESS;
 }
 
-static test_return_t fetch_all_results(memcached_st *memc, unsigned int &keys_returned, const memcached_return_t expect)
+static test_return_t fetch_all_results(memcached_st *memc, unsigned int &keys_returned, memcached_return_t& rc)
 {
-  memcached_return_t rc;
-  char return_key[MEMCACHED_MAX_KEY];
-  size_t return_key_length;
-  char *return_value;
-  size_t return_value_length;
-  uint32_t flags;
-
   keys_returned= 0;
-  while ((return_value= memcached_fetch(memc, return_key, &return_key_length,
-                                        &return_value_length, &flags, &rc)))
+
+  memcached_result_st* result= NULL;
+  while ((result= memcached_fetch_result(memc, result, &rc)))
   {
-    test_true(return_value);
-    test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc));
-    free(return_value);
+    test_compare(MEMCACHED_SUCCESS, rc);
     keys_returned+= 1;
   }
+  memcached_result_free(result);
 
-  if (memcached_success(expect) and memcached_success(rc))
-  {
-    return TEST_SUCCESS;
-  }
-  else if (expect == rc)
-  {
-    return TEST_SUCCESS;
-  }
-  fprintf(stderr, "\n%s:%u %s(#%u)\n", __FILE__, __LINE__, memcached_strerror(NULL, rc), keys_returned);
+  return TEST_SUCCESS;
+}
 
-  return TEST_FAILURE;
+static test_return_t fetch_all_results(memcached_st *memc, unsigned int &keys_returned)
+{
+  memcached_return_t rc;
+  return fetch_all_results(memc, keys_returned, rc);
 }
 
 /* Test case provided by Cal Haldenbrand */
@@ -2167,10 +2165,12 @@ static test_return_t user_supplied_bug1(memcached_st *memc)
     }
 
     total+= size;
-    char key[22];
+    char key[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
     int key_length= snprintf(key, sizeof(key), "%u", x);
     test_compare(MEMCACHED_SUCCESS,
-                 memcached_set(memc, key, key_length, randomstuff, strlen(randomstuff), time_t(0), HALDENBRAND_FLAG_KEY));
+                 memcached_set(memc, key, key_length,
+                               randomstuff, strlen(randomstuff),
+                               time_t(0), HALDENBRAND_FLAG_KEY));
   }
   test_true(total > HALDENBRAND_KEY_COUNT);
 
@@ -2220,10 +2220,11 @@ static test_return_t user_supplied_bug2(memcached_st *memc)
       continue;
     }
     test_compare(uint32_t(HALDENBRAND_FLAG_KEY), flags);
+    test_true(getval);
 
     total_value_length+= val_len;
     errors= 0;
-    free(getval);
+    ::free(getval);
   }
 
   return TEST_SUCCESS;
@@ -2232,8 +2233,8 @@ static test_return_t user_supplied_bug2(memcached_st *memc)
 /* Do a large mget() over all the keys we think exist */
 static test_return_t user_supplied_bug3(memcached_st *memc)
 {
-  test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 1));
-  test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1));
+  test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, true));
+  test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, true));
 
 #ifdef NOT_YET
   memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE, 20 * 1024576);
@@ -2259,14 +2260,14 @@ static test_return_t user_supplied_bug3(memcached_st *memc)
                memcached_mget(memc, &keys[0], &key_lengths[0], key_lengths.size()));
 
   unsigned int keys_returned;
-  test_compare(TEST_SUCCESS, fetch_all_results(memc, keys_returned, MEMCACHED_SUCCESS));
+  test_compare(TEST_SUCCESS, fetch_all_results(memc, keys_returned));
   test_compare(HALDENBRAND_KEY_COUNT, keys_returned);
 
   for (std::vector<char *>::iterator iter= keys.begin();
        iter != keys.end();
        iter++)
   {
-    free(*iter);
+    ::free(*iter);
   }
 
   return TEST_SUCCESS;
@@ -2289,9 +2290,13 @@ static test_return_t user_supplied_bug4(memcached_st *memc)
   test_compare(MEMCACHED_NO_SERVERS,
                memcached_mget(memc, keys, key_length, 3));
 
-  unsigned int keys_returned;
-  test_compare(TEST_SUCCESS, fetch_all_results(memc, keys_returned, MEMCACHED_NOTFOUND));
-  test_zero(keys_returned);
+  {
+    unsigned int keys_returned;
+    memcached_return_t rc;
+    test_compare(TEST_SUCCESS, fetch_all_results(memc, keys_returned, rc));
+    test_compare(MEMCACHED_NOTFOUND, rc);
+    test_zero(keys_returned);
+  }
 
   for (uint32_t x= 0; x < 3; x++)
   {
@@ -2351,7 +2356,8 @@ static test_return_t user_supplied_bug5(memcached_st *memc)
                memcached_mget(memc, keys, key_length, 4));
 
   unsigned int count;
-  test_compare(TEST_SUCCESS, fetch_all_results(memc, count, MEMCACHED_NOTFOUND));
+  test_compare(TEST_SUCCESS, fetch_all_results(memc, count, rc));
+  test_compare(MEMCACHED_NOTFOUND, rc);
   test_zero(count);
 
   for (uint32_t x= 0; x < 4; x++)
@@ -2368,12 +2374,12 @@ static test_return_t user_supplied_bug5(memcached_st *memc)
                          &value_length, &flags, &rc);
     test_compare(rc, MEMCACHED_SUCCESS);
     test_true(value);
-    free(value);
+    ::free(value);
 
     test_compare(MEMCACHED_SUCCESS,
                  memcached_mget(memc, keys, key_length, 4));
 
-    test_compare(TEST_SUCCESS, fetch_all_results(memc, count, MEMCACHED_SUCCESS));
+    test_compare(TEST_SUCCESS, fetch_all_results(memc, count));
     test_compare(4U, count);
   }
   delete [] insert_data;
@@ -2483,37 +2489,36 @@ static test_return_t user_supplied_bug8(memcached_st *)
 /* Test flag store/retrieve */
 static test_return_t user_supplied_bug7(memcached_st *memc)
 {
-  const char *keys= "036790384900";
-  size_t key_length=  strlen(keys);
-  char return_key[MEMCACHED_MAX_KEY];
-  size_t return_key_length;
-  char *value;
-  size_t value_length;
-  uint32_t flags;
   char *insert_data= new (std::nothrow) char[VALUE_SIZE_BUG5];
+  test_true(insert_data);
 
-  for (unsigned int x= 0; x < VALUE_SIZE_BUG5; x++)
+  for (size_t x= 0; x < VALUE_SIZE_BUG5; x++)
   {
     insert_data[x]= (signed char)rand();
   }
 
   memcached_flush(memc, 0);
 
-  flags= 245;
-  test_compare(MEMCACHED_SUCCESS, memcached_set(memc, keys, key_length,
-                                                insert_data, VALUE_SIZE_BUG5,
-                                                (time_t)0, flags));
+  const char *keys= "036790384900";
+  size_t key_length=  strlen(keys);
+  test_compare_hint(MEMCACHED_SUCCESS, memcached_set(memc, keys, key_length,
+                                                     insert_data, VALUE_SIZE_BUG5,
+                                                     time_t(0), 245U),
+                    memcached_last_error_message(memc));
 
   memcached_return_t rc;
-  flags= 0;
-  value= memcached_get(memc, keys, key_length,
-                       &value_length, &flags, &rc);
+  size_t value_length;
+  uint32_t flags= 0;
+  char *value= memcached_get(memc, keys, key_length,
+                             &value_length, &flags, &rc);
   test_compare(245U, flags);
   test_true(value);
   free(value);
 
   test_compare(MEMCACHED_SUCCESS, memcached_mget(memc, &keys, &key_length, 1));
 
+  char return_key[MEMCACHED_MAX_KEY];
+  size_t return_key_length;
   flags= 0;
   value= memcached_fetch(memc, return_key, &return_key_length,
                          &value_length, &flags, &rc);
@@ -2795,19 +2800,20 @@ static test_return_t user_supplied_bug15(memcached_st *memc)
 /* Check the return sizes on FLAGS to make sure it stores 32bit unsigned values correctly */
 static test_return_t user_supplied_bug16(memcached_st *memc)
 {
-  memcached_return_t rc= memcached_set(memc, test_literal_param("mykey"),
-                                       NULL, 0,
-                                       (time_t)0, UINT32_MAX);
+  test_compare_hint(MEMCACHED_SUCCESS, memcached_set(memc, test_literal_param("mykey"),
+                                                     NULL, 0,
+                                                     (time_t)0, UINT32_MAX),
+                    memcached_last_error_message(memc));
 
-  test_compare(MEMCACHED_SUCCESS, rc);
 
   size_t length;
   uint32_t flags;
+  memcached_return_t rc;
   char *value= memcached_get(memc, test_literal_param("mykey"),
                              &length, &flags, &rc);
 
   test_compare(MEMCACHED_SUCCESS, rc);
-  test_true(value == NULL);
+  test_null(value);
   test_zero(length);
   test_compare(flags, UINT32_MAX);
 
@@ -3115,7 +3121,7 @@ static test_return_t generate_data(memcached_st *memc)
 {
   unsigned int check_execute= execute_set(memc, global_pairs, global_count);
 
-  test_compare(check_execute, global_count);
+  test_compare_warn_hint(global_count, check_execute, "Possible false, positive, memcached may have ejected key/value based on memory needs");
 
   return TEST_SUCCESS;
 }
@@ -3192,6 +3198,7 @@ static test_return_t get_read_count(memcached_st *memc)
 
 static test_return_t get_read(memcached_st *memc)
 {
+  size_t keys_returned= 0;
   for (size_t x= 0; x < global_count; x++)
   {
     size_t return_value_length;
@@ -3205,9 +3212,11 @@ static test_return_t get_read(memcached_st *memc)
     */
     if (rc == MEMCACHED_SUCCESS && return_value)
     {
+      keys_returned++;
       free(return_value);
     }
   }
+  test_compare_warn_hint(global_count, keys_returned, "Possible false, positive, memcached may have ejected key/value based on memory needs");
 
   return TEST_SUCCESS;
 }
@@ -3223,7 +3232,7 @@ static test_return_t mget_read(memcached_st *memc)
   // Go fetch the keys and test to see if all of them were returned
   {
     unsigned int keys_returned;
-    test_compare(TEST_SUCCESS, fetch_all_results(memc, keys_returned, MEMCACHED_SUCCESS));
+    test_compare(TEST_SUCCESS, fetch_all_results(memc, keys_returned));
     test_true(keys_returned > 0);
     test_compare_warn_hint(global_count, keys_returned, "Possible false, positive, memcached may have ejected key/value based on memory needs");
   }
@@ -3348,10 +3357,15 @@ static test_return_t mget_read_function(memcached_st *memc)
 
 static test_return_t delete_generate(memcached_st *memc)
 {
+  size_t total= 0;
   for (size_t x= 0; x < global_count; x++)
   {
-    (void)memcached_delete(memc, global_keys[x], global_keys_length[x], (time_t)0);
+    if (memcached_success(memcached_delete(memc, global_keys[x], global_keys_length[x], (time_t)0)))
+    {
+      total++;
+    }
   }
+  test_compare_warn_hint(global_count, total, "Possible false, positive, memcached may have ejected key/value based on memory needs");
 
   return TEST_SUCCESS;
 }
@@ -3360,10 +3374,15 @@ static test_return_t delete_buffer_generate(memcached_st *memc)
 {
   memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, true);
 
+  size_t total= 0;
   for (size_t x= 0; x < global_count; x++)
   {
-    (void)memcached_delete(memc, global_keys[x], global_keys_length[x], (time_t)0);
+    if (memcached_success(memcached_delete(memc, global_keys[x], global_keys_length[x], (time_t)0)))
+    {
+      total++;
+    }
   }
+  test_compare_warn_hint(global_count, total, "Possible false, positive, memcached may have ejected key/value based on memory needs");
 
   return TEST_SUCCESS;
 }
@@ -3934,11 +3953,11 @@ static test_return_t MEMCACHED_BEHAVIOR_POLL_TIMEOUT_test(memcached_st *memc)
 static test_return_t noreply_test(memcached_st *memc)
 {
   test_compare(MEMCACHED_SUCCESS, 
-               memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, 1));
+               memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, true));
   test_compare(MEMCACHED_SUCCESS, 
-               memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1));
+               memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, true));
   test_compare(MEMCACHED_SUCCESS, 
-               memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1));
+               memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, true));
   test_compare(1LLU, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NOREPLY));
   test_compare(1LLU, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS));
   test_compare(1LLU, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS));
@@ -5088,14 +5107,14 @@ static test_return_t memcached_stat_execute_test(memcached_st *memc)
   memcached_return_t rc= memcached_stat_execute(memc, NULL, stat_printer, NULL);
   test_compare(MEMCACHED_SUCCESS, rc);
 
-  rc= memcached_stat_execute(memc, "slabs", stat_printer, NULL);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_stat_execute(memc, "slabs", stat_printer, NULL));
 
-  rc= memcached_stat_execute(memc, "items", stat_printer, NULL);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_stat_execute(memc, "items", stat_printer, NULL));
 
-  rc= memcached_stat_execute(memc, "sizes", stat_printer, NULL);
-  test_compare(MEMCACHED_SUCCESS, rc);
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_stat_execute(memc, "sizes", stat_printer, NULL));
 
   return TEST_SUCCESS;
 }
@@ -5125,7 +5144,7 @@ static test_return_t wrong_failure_counter_test(memcached_st *memc)
   rc= memcached_set(memc, key, strlen(key),
                     value, strlen(value),
                     (time_t)0, (uint32_t)0);
-  test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+  test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
 
 
   instance= memcached_server_instance_by_position(memc, 0);
@@ -5155,53 +5174,45 @@ static test_return_t wrong_failure_counter_test(memcached_st *memc)
  */
 static test_return_t wrong_failure_counter_two_test(memcached_st *memc)
 {
-  memcached_return rc;
-
-  memcached_st *memc_clone;
-  memc_clone= memcached_clone(NULL, memc);
-  test_true(memc_clone);
-
   /* Set value to force connection to the server */
   const char *key= "marmotte";
   const char *value= "milka";
-  char *string = NULL;
-  size_t string_length;
-  uint32_t flags;
 
-  rc= memcached_set(memc_clone, key, strlen(key),
-                    value, strlen(value),
-                    (time_t)0, (uint32_t)0);
-  test_true_got(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED, memcached_strerror(NULL, rc));
+  test_compare_hint(MEMCACHED_SUCCESS,
+                    memcached_set(memc, key, strlen(key),
+                                  value, strlen(value),
+                                  (time_t)0, (uint32_t)0),
+                    memcached_last_error_message(memc));
 
 
   /* put failure limit to 1 */
   test_compare(MEMCACHED_SUCCESS,
-               memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, 1));
+               memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, true));
 
   /* Put a retry timeout to effectively activate failure_limit effect */
   test_compare(MEMCACHED_SUCCESS,
-               memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, 1));
+               memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, true));
 
   /* change behavior that triggers memcached_quit()*/
   test_compare(MEMCACHED_SUCCESS,
-               memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1));
+               memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, true));
 
 
   /* Check if we still are connected */
-  string= memcached_get(memc_clone, key, strlen(key),
-                        &string_length, &flags, &rc);
+  uint32_t flags;
+  size_t string_length;
+  memcached_return rc;
+  char *string= memcached_get(memc, key, strlen(key),
+                              &string_length, &flags, &rc);
 
   test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc));
   test_true(string);
   free(string);
-  memcached_free(memc_clone);
 
   return TEST_SUCCESS;
 }
 
 
-
-
 /*
  * Test that ensures mget_execute does not end into recursive calls that finally fails
  */
index 32b0d9d84c0ff15c7b1bdcf301f2277c66c855fa..03da195a5c7afab2022bebce15c40362610b8feb 100644 (file)
@@ -762,7 +762,11 @@ test_return_t regression_bug_71231153_poll(memcached_st *)
     char *value= memcached_get(memc, test_literal_param("test"), &value_len, NULL, &rc);
     test_false(value);
     test_zero(value_len);
+#ifdef __APPLE__
+    test_compare_got(MEMCACHED_CONNECTION_FAILURE, rc, memcached_last_error_message(memc));
+#else
     test_compare_got(MEMCACHED_TIMEOUT, rc, memcached_last_error_message(memc));
+#endif
 
     memcached_free(memc);
   }
index 16fc1c73cbc3f3f2356ade8468131ff7bb4a9df7..1591bdcf1c23f9263e76177bcb4f4d45f9312868 100644 (file)
@@ -1,11 +1,41 @@
-/* libMemcached Functions Test
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
  */
 
+
 /*
   Sample test application.
 */
@@ -18,6 +48,7 @@ using namespace libtest;
 #include <libmemcached-1.0/memcached.h>
 #include <libmemcached/server_instance.h>
 #include <libmemcached/io.h>
+#include <libmemcached/udp.hpp>
 #include <libmemcachedutil-1.0/util.h>
 
 #include <cassert>
@@ -111,8 +142,25 @@ static test_return_t init_udp(memcached_st *memc)
   return TEST_SUCCESS;
 }
 
+static test_return_t init_udp_valgrind(memcached_st *memc)
+{
+  if (getenv("TESTS_ENVIRONMENT"))
+  {
+    return TEST_SKIPPED; 
+  }
+
+  test_skip(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, true));
+
+  return TEST_SUCCESS;
+}
+
 static test_return_t binary_init_udp(memcached_st *memc)
 {
+  if (getenv("TESTS_ENVIRONMENT"))
+  {
+    return TEST_SKIPPED; 
+  }
+
   test_skip(TEST_SUCCESS, pre_binary(memc));
 
   return init_udp(memc);
@@ -152,26 +200,80 @@ static test_return_t add_udp_server_tcp_client_test(memcached_st *memc)
   return TEST_SUCCESS;
 }
 
+static test_return_t version_TEST(memcached_st *memc)
+{
+  test_compare(MEMCACHED_NOT_SUPPORTED, memcached_version(memc));
+  return TEST_SUCCESS;
+}
+
+static test_return_t verbosity_TEST(memcached_st *memc)
+{
+  test_compare(MEMCACHED_SUCCESS, memcached_verbosity(memc, 0));
+  return TEST_SUCCESS;
+}
+
+static test_return_t memcached_get_TEST(memcached_st *memc)
+{
+  memcached_return_t rc;
+  test_null(memcached_get(memc,
+                          test_literal_param(__func__),
+                          0, 0, &rc));
+  test_compare(MEMCACHED_NOT_SUPPORTED, rc);
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t memcached_mget_execute_by_key_TEST(memcached_st *memc)
+{
+  char **keys= NULL;
+  size_t *key_length= NULL;
+  test_compare(MEMCACHED_NOT_SUPPORTED,
+               memcached_mget_execute_by_key(memc,
+                                             test_literal_param(__func__), // Group key
+                                             keys, key_length, // Actual key
+                                             0, // Number of keys
+                                             0, // callbacks
+                                             0, // context
+                                             0)); // Number of callbacks
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t memcached_stat_TEST(memcached_st *memc)
+{
+  memcached_return_t rc;
+  test_null(memcached_stat(memc, 0, &rc));
+  test_compare(MEMCACHED_NOT_SUPPORTED, rc);
+
+  return TEST_SUCCESS;
+}
+
 static test_return_t set_udp_behavior_test(memcached_st *memc)
 {
   memcached_quit(memc);
 
   test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, memc->distribution));
   test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, true));
-  test_true(memc->flags.use_udp);
-  test_true(memc->flags.no_reply);
+  test_compare(true, memc->flags.use_udp);
+  test_compare(false, memc->flags.reply);
 
   test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, false));
-  test_false(memc->flags.use_udp);
+  test_compare(false, memc->flags.use_udp);
   test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, false));
-  test_false(memc->flags.no_reply);
+  test_compare(true, memc->flags.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
+  // Assume we are running under valgrind, and bail 
+  if (getenv("TESTS_ENVIRONMENT"))
+  {
+    return TEST_SUCCESS; 
+  }
+
+  const unsigned int num_iters= 1025; //request id rolls over at 1024
 
   test_true(memc);
 
@@ -184,29 +286,23 @@ static test_return_t udp_set_test(memcached_st *memc)
     memcached_server_instance_st instance= memcached_server_instance_by_position(memc, server_key);
     size_t init_offset= instance->write_buffer_offset;
 
-    memcached_return_t rc= memcached_set(memc, test_literal_param("foo"),
-                                         test_literal_param("when we sanitize"),
-                                         time_t(0), uint32_t(0));
-    test_true(rc == MEMCACHED_SUCCESS or 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 or instance->write_buffer_offset < init_offset)
+    test_compare_hint(MEMCACHED_SUCCESS, 
+                      memcached_set(memc,
+                                    test_literal_param("foo"),
+                                    test_literal_param("when we sanitize"),
+                                    time_t(0), uint32_t(0)),
+                      memcached_last_error_message(memc));
+
+    /*
+      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 (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_compare(TEST_SUCCESS, post_udp_op_check(memc, expected_ids));
   }
 
@@ -216,21 +312,27 @@ static test_return_t udp_set_test(memcached_st *memc)
 static test_return_t udp_buffered_set_test(memcached_st *memc)
 {
   test_true(memc);
-  test_compare(MEMCACHED_INVALID_ARGUMENTS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, true));
+  test_compare(MEMCACHED_INVALID_ARGUMENTS,
+               memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, true));
   return TEST_SUCCESS;
 }
 
 static test_return_t udp_set_too_big_test(memcached_st *memc)
 {
   test_true(memc);
-  char value[MAX_UDP_DATAGRAM_LENGTH];
   Expected expected_ids;
   get_udp_request_ids(memc, expected_ids);
 
-  memset(value, int('f'), sizeof(value));
+  std::vector<char> value;
+  value.resize(1024 * 1024 * 10);
 
-  test_compare_hint(MEMCACHED_WRITE_FAILURE, memcached_set(memc, test_literal_param("bar"), value, sizeof(value), time_t(0), uint32_t(0)),
+  test_compare_hint(MEMCACHED_WRITE_FAILURE,
+                    memcached_set(memc,
+                                  test_literal_param(__func__), 
+                                  &value[0], value.size(),
+                                  time_t(0), uint32_t(0)),
                     memcached_last_error_message(memc));
+  memcached_quit(memc);
 
   return post_udp_op_check(memc, expected_ids);
 }
@@ -249,23 +351,14 @@ static test_return_t udp_delete_test(memcached_st *memc)
     memcached_server_instance_st instance= memcached_server_instance_by_position(memc, server_key);
     size_t init_offset= instance->write_buffer_offset;
 
-    memcached_return_t rc= memcached_delete(memc, test_literal_param("foo"), 0);
-    test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+    test_compare(MEMCACHED_SUCCESS,
+                 memcached_delete(memc, test_literal_param("foo"), 0));
 
-    if (rc == MEMCACHED_SUCCESS or instance->write_buffer_offset < init_offset)
+    if (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_compare(TEST_SUCCESS, post_udp_op_check(memc, expected_ids));
   }
 
@@ -310,6 +403,7 @@ static test_return_t udp_flush_test(memcached_st *memc)
   {
     increment_request_id(&expected_ids[x]);
   }
+  memcached_error_print(memc);
   test_compare_hint(MEMCACHED_SUCCESS, memcached_flush(memc, 0), memcached_last_error_message(memc));
 
   return post_udp_op_check(memc, expected_ids);
@@ -317,9 +411,10 @@ static test_return_t udp_flush_test(memcached_st *memc)
 
 static test_return_t udp_incr_test(memcached_st *memc)
 {
-  test_compare(MEMCACHED_SUCCESS, memcached_set(memc, test_literal_param("incr"), 
-                                                test_literal_param("1"),
-                                                (time_t)0, (uint32_t)0));
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_set(memc, test_literal_param("incr"), 
+                             test_literal_param("1"),
+                             (time_t)0, (uint32_t)0));
 
   Expected expected_ids;
   get_udp_request_ids(memc, expected_ids);
@@ -335,19 +430,23 @@ static test_return_t udp_incr_test(memcached_st *memc)
 
 static test_return_t udp_decr_test(memcached_st *memc)
 {
-  test_compare(MEMCACHED_SUCCESS, memcached_set(memc, 
-                                                test_literal_param("decr"),
-                                                test_literal_param("1"),
-                                                (time_t)0, (uint32_t)0));
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_set(memc, 
+                             test_literal_param(__func__),
+                             test_literal_param("1"),
+                             (time_t)0, (uint32_t)0));
 
   Expected expected_ids;
   get_udp_request_ids(memc, expected_ids);
 
-  unsigned int server_key= memcached_generate_hash(memc, test_literal_param("decr"));
+  unsigned int server_key= memcached_generate_hash(memc,
+                                                   test_literal_param(__func__));
   increment_request_id(&expected_ids[server_key]);
 
   uint64_t newvalue;
-  test_compare(MEMCACHED_SUCCESS, memcached_decrement(memc, test_literal_param("decr"), 1, &newvalue));
+  test_compare(MEMCACHED_SUCCESS, memcached_decrement(memc,
+                                                      test_literal_param(__func__),
+                                                      1, &newvalue));
 
   return post_udp_op_check(memc, expected_ids);
 }
@@ -371,7 +470,8 @@ static test_return_t udp_version_test(memcached_st *memc)
   Expected expected_ids;
   get_udp_request_ids(memc, expected_ids);
 
-  test_compare(MEMCACHED_NOT_SUPPORTED, memcached_version(memc));
+  test_compare(MEMCACHED_NOT_SUPPORTED,
+               memcached_version(memc));
 
   return post_udp_op_check(memc, expected_ids);
 }
@@ -421,6 +521,15 @@ static test_return_t udp_mixed_io_test(memcached_st *memc)
   return TEST_SUCCESS;
 }
 
+test_st compatibility_TESTS[] ={
+  {"version", 0, (test_callback_fn*)version_TEST },
+  {"version", 0, (test_callback_fn*)verbosity_TEST },
+  {"memcached_get()", 0, (test_callback_fn*)memcached_get_TEST },
+  {"memcached_mget_execute_by_key()", 0, (test_callback_fn*)memcached_mget_execute_by_key_TEST },
+  {"memcached_stat()", 0, (test_callback_fn*)memcached_stat_TEST },
+  {0, 0, 0}
+};
+
 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},
@@ -448,7 +557,8 @@ test_st upd_io_tests[] ={
 
 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},
+  {"compatibility", (test_callback_fn*)init_udp, 0, compatibility_TESTS},
+  {"udp_io", (test_callback_fn*)init_udp_valgrind, 0, upd_io_tests},
   {"udp_binary_io", (test_callback_fn*)binary_init_udp, 0, upd_io_tests},
   {0, 0, 0, 0}
 };
index 23c8aec4f5947997d871bf766f70636c00851dca..19d01fcf913c4d5d805d9e7e6eded819521ffd9e 100644 (file)
@@ -192,7 +192,7 @@ bool Instance::run()
             switch(errno)
             {
             default:
-              std::cerr << "Failed during send(" << strerror(errno) << ")" << std::endl;
+              std::cerr << "Failed dureng send(" << strerror(errno) << ")" << std::endl;
               break;
             }
           }