Merge
[awesomized/libmemcached] / libmemcached / response.cc
index 44ce840ab722fa32e99f3ea4093c05fd9531fd56..669c633a95f1ed4ee9dc92526bd7aa81e39c32d7 100644 (file)
@@ -36,6 +36,7 @@
  */
 
 #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,
@@ -142,7 +143,7 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
     key= result->item_key;
     result->key_length= 0;
 
-    for (prefix_length= memcached_array_size(ptr->root->prefix_key); !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++)
+    for (prefix_length= memcached_array_size(ptr->root->_namespace); !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++)
     {
       if (prefix_length == 0)
       {
@@ -218,7 +219,7 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
     if (memcached_failed(rrc) and rrc == MEMCACHED_IN_PROGRESS)
     {
       memcached_quit_server(ptr, true);
-      return memcached_set_error(*ptr, rrc, MEMCACHED_AT);
+      return memcached_set_error(*ptr, MEMCACHED_IN_PROGRESS, MEMCACHED_AT);
     }
     else if (memcached_failed(rrc))
     {
@@ -252,7 +253,9 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta
                                                     char *buffer, size_t buffer_length,
                                                     memcached_result_st *result)
 {
-  memcached_return_t rc= memcached_io_readline(ptr, buffer, buffer_length);
+  size_t total_read;
+  memcached_return_t rc= memcached_io_readline(ptr, buffer, buffer_length, total_read);
+
   if (memcached_failed(rc))
   {
     return rc;
@@ -287,32 +290,28 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta
       }
       else if (buffer[1] == 'E') /* SERVER_ERROR */
       {
-        char *startptr= buffer + 13, *endptr= startptr;
+        if (total_read == memcached_literal_param_size("SERVER_ERROR"))
+        {
+          return MEMCACHED_SERVER_ERROR;
+        }
 
-        while (*endptr != '\r' && *endptr != '\n') endptr++;
+        if (total_read > memcached_literal_param_size("SERVER_ERROR object too large for cache") and
+            (memcmp(buffer, memcached_literal_param("SERVER_ERROR object too large for cache")) == 0))
+        {
+          return MEMCACHED_E2BIG;
+        }
 
-        /*
-          Yes, we could make this "efficent" but to do that we would need
-          to maintain more state for the size of the buffer. Why waste
-          memory in the struct, which is important, for something that
-          rarely should happen?
-        */
-        char *rel_ptr= (char *)libmemcached_realloc(ptr->root,
-                                                    ptr->cached_server_error,
-                                                    (size_t) (endptr - startptr + 1));
-
-        if (rel_ptr == NULL)
+        // Move past the basic error message and whitespace
+        char *startptr= buffer + memcached_literal_param_size("SERVER_ERROR");
+        if (startptr[0] == ' ')
         {
-          /* If we happened to have some memory, we just null it since we don't know the size */
-          if (ptr->cached_server_error)
-            ptr->cached_server_error[0]= 0;
-          return MEMCACHED_SERVER_ERROR;
+          startptr++;
         }
-        ptr->cached_server_error= rel_ptr;
 
-        memcpy(ptr->cached_server_error, startptr, (size_t) (endptr - startptr));
-        ptr->cached_server_error[endptr - startptr]= 0;
-        return MEMCACHED_SERVER_ERROR;
+        char *endptr= startptr;
+        while (*endptr != '\r' && *endptr != '\n') endptr++;
+
+        return memcached_set_error(*ptr, MEMCACHED_SERVER_ERROR, MEMCACHED_AT, startptr, size_t(endptr - startptr));
       }
       else if (buffer[1] == 'T')
       {
@@ -402,7 +401,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
   header.response.cas= memcached_ntohll(header.response.cas);
   uint32_t bodylen= header.response.bodylen;
 
-  if (header.response.status == PROTOCOL_BINARY_RESPONSE_SUCCESS ||
+  if (header.response.status == PROTOCOL_BINARY_RESPONSE_SUCCESS or
       header.response.status == PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE)
   {
     switch (header.response.opcode)
@@ -439,15 +438,15 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
         // Only bother with doing this if key_length > 0
         if (result->key_length)
         {
-          if (memcached_array_size(ptr->root->prefix_key) and memcached_array_size(ptr->root->prefix_key) >= result->key_length)
+          if (memcached_array_size(ptr->root->_namespace) and memcached_array_size(ptr->root->_namespace) >= result->key_length)
           {
             return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
           }
 
-          if (memcached_array_size(ptr->root->prefix_key))
+          if (memcached_array_size(ptr->root->_namespace))
           {
-            result->key_length-= memcached_array_size(ptr->root->prefix_key);
-            memmove(result->item_key, result->item_key +memcached_array_size(ptr->root->prefix_key), result->key_length);
+            result->key_length-= memcached_array_size(ptr->root->_namespace);
+            memmove(result->item_key, result->item_key +memcached_array_size(ptr->root->_namespace), result->key_length);
           }
         }
 
@@ -602,36 +601,45 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
     case PROTOCOL_BINARY_CMD_APPENDQ:
     case PROTOCOL_BINARY_CMD_PREPENDQ:
       return binary_read_one_response(ptr, buffer, buffer_length, result);
+
     default:
       break;
     }
   }
 
   rc= MEMCACHED_SUCCESS;
-  unlikely(header.response.status != 0)
+  if (header.response.status != 0)
+  {
     switch (header.response.status)
     {
     case PROTOCOL_BINARY_RESPONSE_KEY_ENOENT:
       rc= MEMCACHED_NOTFOUND;
       break;
+
     case PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS:
       rc= MEMCACHED_DATA_EXISTS;
       break;
+
     case PROTOCOL_BINARY_RESPONSE_NOT_STORED:
       rc= MEMCACHED_NOTSTORED;
       break;
+
     case PROTOCOL_BINARY_RESPONSE_E2BIG:
       rc= MEMCACHED_E2BIG;
       break;
+
     case PROTOCOL_BINARY_RESPONSE_ENOMEM:
       rc= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
       break;
+
     case PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE:
       rc= MEMCACHED_AUTH_CONTINUE;
       break;
+
     case PROTOCOL_BINARY_RESPONSE_AUTH_ERROR:
       rc= MEMCACHED_AUTH_FAILURE;
       break;
+
     case PROTOCOL_BINARY_RESPONSE_EINVAL:
     case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND:
     default:
@@ -639,6 +647,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
       rc= MEMCACHED_PROTOCOL_ERROR;
       break;
     }
+  }
 
   return rc;
 }