Lossen up restrictions on the recv().
authorBrian Aker <brian@tangent.org>
Thu, 16 Jun 2011 00:56:49 +0000 (17:56 -0700)
committerBrian Aker <brian@tangent.org>
Thu, 16 Jun 2011 00:56:49 +0000 (17:56 -0700)
docs/memcached_get.rst
libmemcached/fetch.cc
libmemcached/io.cc
libmemcached/quit.cc
libmemcached/response.cc
libmemcached/result.cc
libmemcached/return.h
libmemcached/strerror.cc
tests/mem_functions.cc

index c563f396c73d3b271f0b6a65ea5460179302740c..556fcf7a7ad27060dbd622e0b31421df13eec7db 100644 (file)
@@ -65,7 +65,7 @@ a size_t pointer which will be filled with size of of the object, and a
 memcached_return_t pointer to hold any error. The object will be returned
 upon success and NULL will be returned on failure. MEMCACHD_END is returned
 by the \*error value when all objects that have been found are returned.
-The final value upon MEMCACHED_END is null. Values returned by
+The final value upon :c:type:`MEMCACHED_END` is null. Values returned by
 memcached_fetch() must be freed by the caller. memcached_fetch() will
 be DEPRECATED in the near future, memcached_fetch_result() should be used
 instead.
@@ -117,6 +117,10 @@ All objects returned must be freed by the calling application.
 memcached_get() and memcached_fetch() will return NULL on error. You must
 look at the value of error to determine what the actual error was.
 
+:c:func:`memcached_fetch()`, :c:func:`memcached_fetch_execute()`, and
+:c:func:`memcached_fetch_result()` all set error to :c:type:`MEMCACHED_END`
+upon success.
+
 MEMCACHED_KEY_TOO_BIG is set to error whenever memcached_fetch() was used
 and the key was set larger then MEMCACHED_MAX_KEY, which was the largest
 key allowed for the original memcached ascii server.
index 8977753489a33835f73d640289869893ab16442c..e8f794c9e07a611a654709c876842326e133ff59 100644 (file)
@@ -104,6 +104,7 @@ memcached_result_st *memcached_fetch_result(memcached_st *ptr,
   {
     if (not (result= memcached_result_create(ptr, NULL)))
     {
+      *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
       return NULL;
     }
   }
@@ -137,6 +138,12 @@ memcached_result_st *memcached_fetch_result(memcached_st *ptr,
     memcached_string_reset(&result->value);
   }
 
+  if (*error == MEMCACHED_NOTFOUND)
+    *error= MEMCACHED_END;
+
+  if (*error == MEMCACHED_SUCCESS)
+    *error= MEMCACHED_END;
+
   return NULL;
 }
 
@@ -148,14 +155,14 @@ memcached_return_t memcached_fetch_execute(memcached_st *ptr,
   memcached_result_st *result= &ptr->result;
   memcached_return_t rc= MEMCACHED_FAILURE;
 
-  while ((result= memcached_fetch_result(ptr, result, &rc)) != NULL) 
+  while ((result= memcached_fetch_result(ptr, result, &rc)))
   {
-    if (rc == MEMCACHED_SUCCESS)
+    if (memcached_success(rc))
     {
       for (uint32_t x= 0; x < number_of_callbacks; x++)
       {
         rc= (*callback[x])(ptr, result, context);
-        if (rc != MEMCACHED_SUCCESS)
+        if (memcached_failed(rc))
           break;
       }
     }
index fd719d6ee57410d52e2db8249cb8a0af48e8207b..fdb265acabf81bdf2482bd27581333da4c6d267a 100644 (file)
 
 
 #include <libmemcached/common.h>
+#include <cassert>
 
-typedef enum {
+enum memc_read_or_write {
   MEM_READ,
   MEM_WRITE
-} memc_read_or_write;
+};
 
 static ssize_t io_flush(memcached_server_write_instance_st ptr,
                         const bool with_flush,
@@ -249,20 +250,16 @@ static bool process_input_buffer(memcached_server_write_instance_st ptr)
 memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr,
                                      void *buffer, size_t length, ssize_t *nread)
 {
-  char *buffer_ptr;
-
-  buffer_ptr= static_cast<char *>(buffer);
+  char *buffer_ptr= static_cast<char *>(buffer);
 
   while (length)
   {
     if (not ptr->read_buffer_length)
     {
       ssize_t data_read;
-
       do
       {
         data_read= recv(ptr->fd, ptr->read_buffer, MEMCACHED_MAX_BUFFER, MSG_DONTWAIT);
-
         if (data_read == SOCKET_ERROR)
         {
           switch (get_socket_errno())
@@ -279,6 +276,7 @@ memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr,
             {
               continue;
             }
+            return MEMCACHED_IN_PROGRESS;
 
             /* fall through */
 
@@ -710,9 +708,13 @@ memcached_return_t memcached_safe_read(memcached_server_write_instance_st ptr,
   while (offset < size)
   {
     ssize_t nread;
-    memcached_return_t rc= memcached_io_read(ptr, data + offset, size - offset,
-                                             &nread);
-    if (rc != MEMCACHED_SUCCESS)
+    memcached_return_t rc= memcached_io_read(ptr, data + offset, size - offset, &nread);
+    if (memcached_failed(rc) and rc == MEMCACHED_IN_PROGRESS)
+    {
+      memcached_quit_server(ptr, true);
+      return memcached_set_error(*ptr, rc, MEMCACHED_AT);
+    }
+    else if (memcached_failed(rc))
     {
       return rc;
     }
@@ -730,7 +732,7 @@ memcached_return_t memcached_io_readline(memcached_server_write_instance_st ptr,
   bool line_complete= false;
   size_t total_nr= 0;
 
-  while (!line_complete)
+  while (not line_complete)
   {
     if (ptr->read_buffer_length == 0)
     {
@@ -741,7 +743,12 @@ memcached_return_t memcached_io_readline(memcached_server_write_instance_st ptr,
      */
       ssize_t nread;
       memcached_return_t rc= memcached_io_read(ptr, buffer_ptr, 1, &nread);
-      if (rc != MEMCACHED_SUCCESS)
+      if (memcached_failed(rc) and rc == MEMCACHED_IN_PROGRESS)
+      {
+        memcached_quit_server(ptr, true);
+        return memcached_set_error(*ptr, rc, MEMCACHED_AT);
+      }
+      else if (memcached_failed(rc))
       {
         return rc;
       }
index b44b508e27ea00eacd3e6738d417a9a319902208..5eeac084571d876f1002f2f8bcf044cc89f99954 100644 (file)
@@ -84,8 +84,7 @@ void memcached_quit_server(memcached_server_st *ptr, bool io_death)
       if (ptr->root->flags.buffer_requests || ptr->root->number_of_replicas)
       {
         ssize_t nread;
-        while (memcached_io_read(ptr, buffer, sizeof(buffer)/sizeof(*buffer),
-                                 &nread) == MEMCACHED_SUCCESS) {} ;
+        while (memcached_success(memcached_io_read(ptr, buffer, sizeof(buffer)/sizeof(*buffer), &nread))) {} ;
       }
 
 
@@ -101,6 +100,8 @@ void memcached_quit_server(memcached_server_st *ptr, bool io_death)
     memcached_io_close(ptr);
   }
 
+  ptr->state= MEMCACHED_SERVER_STATE_NEW;
+  ptr->cursor_active= 0;
   ptr->io_bytes_sent= 0;
   ptr->write_buffer_offset= (size_t) ((ptr->type == MEMCACHED_CONNECTION_UDP) ? UDP_DATAGRAM_HEADER_LENGTH : 0);
   ptr->read_buffer_length= 0;
@@ -132,7 +133,7 @@ void send_quit(memcached_st *ptr)
 
 void memcached_quit(memcached_st *ptr)
 {
-  if (initialize_query(ptr) != MEMCACHED_SUCCESS)
+  if (memcached_failed(initialize_query(ptr)))
   {
     return;
   }
index d3d2510e688fcd920f34a3fa5834277ed00c0d1a..e94ca31fffcca9c4ff675bd0d8e4d1af861af6d7 100644 (file)
@@ -211,8 +211,15 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
     */
     to_read= (value_length) + 2;
     memcached_return_t rrc= memcached_io_read(ptr, value_ptr, to_read, &read_length);
-    if (memcached_failed(rrc))
+    if (memcached_failed(rrc) and rrc == MEMCACHED_IN_PROGRESS)
+    {
+      memcached_quit_server(ptr, true);
+      return memcached_set_error(*ptr, rrc, MEMCACHED_AT);
+    }
+    else if (memcached_failed(rrc))
+    {
       return rrc;
+    }
   }
 
   if (read_length != (ssize_t)(value_length + 2))
@@ -225,7 +232,7 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
     char *char_ptr;
     char_ptr= memcached_string_value_mutable(&result->value);;
     char_ptr[value_length]= 0;
-    char_ptr[value_length + 1]= 0;
+    char_ptr[value_length +1]= 0;
     memcached_string_set_length(&result->value, value_length);
   }
 
@@ -242,8 +249,10 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta
                                                     memcached_result_st *result)
 {
   memcached_return_t rc= memcached_io_readline(ptr, buffer, buffer_length);
-  if (rc != MEMCACHED_SUCCESS)
+  if (memcached_failed(rc))
+  {
     return rc;
+  }
 
   switch(buffer[0])
   {
index f9d55a9412c1087d6ca0a0e0a2407b301aa8bf92..eb24fa3617c4f35889851be7e154f64d0e60dbe7 100644 (file)
@@ -69,8 +69,10 @@ memcached_result_st *memcached_result_create(const memcached_st *memc,
   {
     ptr= static_cast<memcached_result_st *>(libmemcached_malloc(memc, sizeof(memcached_result_st)));
 
-    if (ptr == NULL)
+    if (not ptr)
+    {
       return NULL;
+    }
 
     ptr->options.is_allocated= true;
   }
index 35ad69d9332450af1ecd129e9cc1dfabeb6a50a3..fd7194d08115a2e81570ca6841c969ffe8309aa9 100644 (file)
@@ -83,6 +83,7 @@ enum memcached_return_t {
   MEMCACHED_PARSE_ERROR,
   MEMCACHED_PARSE_USER_ERROR,
   MEMCACHED_DEPRECATED,
+  MEMCACHED_IN_PROGRESS,
   MEMCACHED_MAXIMUM_RETURN /* Always add new error code before */
 };
 
@@ -91,6 +92,6 @@ typedef enum memcached_return_t memcached_return_t;
 #endif
 
 
-#define memcached_success(X) ((X) == MEMCACHED_SUCCESS)
-#define memcached_failed(A) ((A) != MEMCACHED_SUCCESS)
+#define memcached_success(__memcached_return_t) ((__memcached_return_t) == MEMCACHED_SUCCESS or (__memcached_return_t) == MEMCACHED_END)
+#define memcached_failed(__memcached_return_t) ((__memcached_return_t) != MEMCACHED_SUCCESS and (__memcached_return_t) != MEMCACHED_END)
 
index d378182427e60154a022d1d5e26692163e772c14..c58b1f650e4020ab4591e40a6b57aa7339f52b6a 100644 (file)
@@ -53,8 +53,10 @@ const char *memcached_strerror(memcached_st *, memcached_return_t rc)
     return "CONNECTION BIND FAILURE";
   case MEMCACHED_READ_FAILURE:
     return "READ FAILURE";
+
   case MEMCACHED_UNKNOWN_READ_FAILURE:
     return "UNKNOWN READ FAILURE";
+
   case MEMCACHED_PROTOCOL_ERROR:
     return "PROTOCOL ERROR";
   case MEMCACHED_CLIENT_ERROR:
@@ -131,8 +133,13 @@ const char *memcached_strerror(memcached_st *, memcached_return_t rc)
     return "ERROR OCCURED WHILE PARSING";
   case MEMCACHED_PARSE_USER_ERROR:
     return "USER INITIATED ERROR OCCURED WHILE PARSING";
+
   case MEMCACHED_DEPRECATED:
     return "DEPRECATED";
+
+  case MEMCACHED_IN_PROGRESS:
+    return "OPERATION IN PROCESS";
+
   default:
   case MEMCACHED_MAXIMUM_RETURN:
     return "INVALID memcached_return_t";
index 97948f20a219318e6c11dad946bc599247d209f2..bc0f91f210b1e04ceaf6e14b5d088ae406afdc4d 100644 (file)
@@ -54,6 +54,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <iostream>
+
 #include <libtest/server.h>
 
 #include "clients/generator.h"
@@ -433,7 +435,7 @@ static test_return_t error_test(memcached_st *memc)
                         54481931U, 4186304426U, 1741088401U, 2979625118U,
                         4159057246U, 3425930182U, 2593724503U,  1868899624U,
                         1769812374U, 2302537950U, 1110330676U, 3365377466U, 
-                        1336171666U, 3021258493U, 3365377466U };
+                        1336171666U, 3021258493U, 2334992265U, 3365377466U };
 
   // You have updated the memcache_error messages but not updated docs/tests.
   for (int rc= int(MEMCACHED_SUCCESS); rc < int(MEMCACHED_MAXIMUM_RETURN); ++rc)
@@ -449,7 +451,7 @@ static test_return_t error_test(memcached_st *memc)
     }
     test_true(values[rc] == hash_val);
   }
-  test_true(MEMCACHED_MAXIMUM_RETURN == 46);
+  test_compare(MEMCACHED_MAXIMUM_RETURN, 47);
 
   return TEST_SUCCESS;
 }
@@ -519,7 +521,7 @@ static test_return_t append_binary_test(memcached_st *memc)
                     key, strlen(key),
                     NULL, 0,
                     (time_t)0, (uint32_t)0);
-  test_true(rc == MEMCACHED_SUCCESS);
+  test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc));
 
   for (x= 0; store_list[x] ; x++)
   {
@@ -552,22 +554,20 @@ static test_return_t cas2_test(memcached_st *memc)
   size_t key_length[]= {5, 3, 4};
   const char *value= "we the people";
   size_t value_length= strlen("we the people");
-  unsigned int x;
   memcached_result_st results_obj;
   memcached_result_st *results;
   unsigned int set= 1;
 
-  rc= memcached_flush(memc, 0);
-  test_true(rc == MEMCACHED_SUCCESS);
+  test_compare(MEMCACHED_SUCCESS, memcached_flush(memc, 0));
 
   memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, set);
 
-  for (x= 0; x < 3; x++)
+  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_true(rc == MEMCACHED_SUCCESS);
+    test_compare(MEMCACHED_SUCCESS, rc);
   }
 
   rc= memcached_mget(memc, keys, key_length, 3);
@@ -1668,7 +1668,8 @@ static test_return_t mget_result_function(memcached_st *memc)
 
   callbacks[0]= &callback_counter;
   counter= 0;
-  rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1);
+  test_compare(MEMCACHED_END, 
+               memcached_fetch_execute(memc, callbacks, (void *)&counter, 1));
 
   test_true(counter == 3);
 
@@ -1773,12 +1774,12 @@ static test_return_t mget_execute(memcached_st *memc)
   rc= memcached_mget_execute(memc, (const char**)keys, key_length,
                              max_keys, callbacks, &counter, 1);
 
-  if (rc == MEMCACHED_SUCCESS)
+  if (memcached_success(rc))
   {
     test_true(binary);
     uint64_t query_id= memcached_query_id(memc);
-    rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1);
-    test_true(rc == MEMCACHED_END);
+    test_compare(MEMCACHED_END, 
+                 memcached_fetch_execute(memc, callbacks, (void *)&counter, 1));
     test_compare(query_id, memcached_query_id(memc));
 
     /* Verify that we got all of the items */
@@ -3456,7 +3457,8 @@ static test_return_t mget_read_function(memcached_st *memc)
 
   memcached_execute_fn callbacks[]= { &callback_counter };
   size_t counter= 0;
-  rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1);
+  test_compare(MEMCACHED_END, 
+               memcached_fetch_execute(memc, callbacks, (void *)&counter, 1));
 
   return TEST_SUCCESS;
 }
@@ -5043,7 +5045,8 @@ static test_return_t regression_bug_434843(memcached_st *memc)
   {
     rc= memcached_mget(memc, (const char**)keys, key_length, max_keys);
     test_true(rc == MEMCACHED_SUCCESS);
-    rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1);
+    test_compare(MEMCACHED_END, 
+                 memcached_fetch_execute(memc, callbacks, (void *)&counter, 1));
 
     if (y == 0)
     {
@@ -5132,9 +5135,7 @@ static test_return_t regression_bug_421108(memcached_st *memc)
  */
 static test_return_t regression_bug_442914(memcached_st *memc)
 {
-  memcached_return_t rc;
-  rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, 1);
-  test_true(rc == MEMCACHED_SUCCESS);
+  test_skip(MEMCACHED_SUCCESS,  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, 1));
   memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1);
 
   uint32_t number_of_hosts= memcached_server_count(memc);
@@ -5146,20 +5147,18 @@ static test_return_t regression_bug_442914(memcached_st *memc)
   for (uint32_t x= 0; x < 250; ++x)
   {
      len= (size_t)snprintf(k, sizeof(k), "%0250u", x);
-     rc= memcached_delete(memc, k, len, 0);
+     memcached_return_t rc= memcached_delete(memc, k, len, 0);
      test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
   }
 
   (void)snprintf(k, sizeof(k), "%037u", 251U);
   len= strlen(k);
 
-  rc= memcached_delete(memc, k, len, 0);
+  memcached_return_t rc= memcached_delete(memc, k, len, 0);
   test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
 
-  rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, 0);
-  test_true(rc == MEMCACHED_SUCCESS);
-  rc= memcached_delete(memc, k, len, 0);
-  test_true(rc == MEMCACHED_NOTFOUND);
+  test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, 0));
+  test_compare(MEMCACHED_NOTFOUND, memcached_delete(memc, k, len, 0));
 
   memc->number_of_hosts= number_of_hosts;
 
@@ -5171,13 +5170,11 @@ static test_return_t regression_bug_447342(memcached_st *memc)
   memcached_server_instance_st instance_one;
   memcached_server_instance_st instance_two;
 
-  if (memcached_server_count(memc) < 3 || pre_replication(memc) != TEST_SUCCESS)
+  if (memcached_server_count(memc) < 3 or pre_replication(memc) != TEST_SUCCESS)
     return TEST_SKIPPED;
 
-  memcached_return_t rc;
-
-  rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 2);
-  test_true(rc == MEMCACHED_SUCCESS);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 2));
 
   const size_t max_keys= 100;
   char **keys= (char**)calloc(max_keys, sizeof(char*));
@@ -5189,9 +5186,9 @@ static test_return_t regression_bug_447342(memcached_st *memc)
 
     key_length[x]= (size_t)snprintf(k, sizeof(k), "0200%lu", (unsigned long)x);
     keys[x]= strdup(k);
-    test_true(keys[x] != NULL);
-    rc= memcached_set(memc, k, key_length[x], k, key_length[x], 0, 0);
-    test_true(rc == MEMCACHED_SUCCESS);
+    test_true(keys[x]);
+    test_compare(MEMCACHED_SUCCESS,
+                 memcached_set(memc, k, key_length[x], k, key_length[x], 0, 0));
   }
 
   /*
@@ -5212,14 +5209,20 @@ static test_return_t regression_bug_447342(memcached_st *memc)
   /* Verify that all messages are stored, and we didn't stuff too much
    * into the servers
    */
-  rc= memcached_mget(memc, (const char* const *)keys, key_length, max_keys);
-  test_true(rc == MEMCACHED_SUCCESS);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_mget(memc, (const char* const *)keys, key_length, max_keys));
+
+
 
   size_t counter= 0;
   memcached_execute_fn callbacks[]= { &callback_counter };
-  rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1);
+  memcached_return_t rc;
+  test_compare_got(MEMCACHED_END, 
+                   rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1),
+                   memcached_last_error_message(memc));
+
   /* Verify that we received all of the key/value pairs */
-  test_true(counter == max_keys);
+  test_compare(counter, max_keys);
 
   memcached_quit(memc);
   /*
@@ -5236,11 +5239,12 @@ static test_return_t regression_bug_447342(memcached_st *memc)
   ((memcached_server_write_instance_st)instance_one)->port= 0;
   ((memcached_server_write_instance_st)instance_two)->port= 0;
 
-  rc= memcached_mget(memc, (const char* const *)keys, key_length, max_keys);
-  test_true(rc == MEMCACHED_SUCCESS);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_mget(memc, (const char* const *)keys, key_length, max_keys));
 
   counter= 0;
-  rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1);
+  test_compare(MEMCACHED_END, 
+               memcached_fetch_execute(memc, callbacks, (void *)&counter, 1));
   test_true(counter == (unsigned int)max_keys);
 
   /* restore the memc handle */
@@ -5254,8 +5258,8 @@ static test_return_t regression_bug_447342(memcached_st *memc)
   {
     if (x & 1)
     {
-      rc= memcached_delete(memc, keys[x], key_length[x], 0);
-      test_true(rc == MEMCACHED_SUCCESS);
+      test_compare(MEMCACHED_SUCCESS,
+                   memcached_delete(memc, keys[x], key_length[x], 0));
     }
   }
 
@@ -5264,11 +5268,13 @@ static test_return_t regression_bug_447342(memcached_st *memc)
   ((memcached_server_write_instance_st)instance_two)->port= 0;
 
   /* now retry the command, this time we should have cache misses */
-  rc= memcached_mget(memc, (const char* const *)keys, key_length, max_keys);
-  test_true(rc == MEMCACHED_SUCCESS);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_mget(memc, (const char* const *)keys, key_length, max_keys));
 
   counter= 0;
-  rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1);
+  test_compare_got(MEMCACHED_END, 
+                   rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1),
+                   memcached_strerror(NULL, rc));
   test_true(counter == (unsigned int)(max_keys >> 1));
 
   /* Release allocated resources */
@@ -5289,7 +5295,7 @@ static test_return_t regression_bug_447342(memcached_st *memc)
 static test_return_t regression_bug_463297(memcached_st *memc)
 {
   memcached_st *memc_clone= memcached_clone(NULL, memc);
-  test_true(memc_clone != NULL);
+  test_true(memc_clone);
   test_true(memcached_version(memc_clone) == MEMCACHED_SUCCESS);
 
   memcached_server_instance_st instance=