We now check return key size for memcached_fetch() to make sure it is not
[m6w6/libmemcached] / libmemcached / response.c
index a87ac2491bad3690d4db473f7efdb1d0a41a3b09..cbb49784b18d1cb270e519f6db56ddc5a8255ba7 100644 (file)
@@ -1,27 +1,34 @@
-/*
-  Memcached library
-
-  memcached_response() is used to determine the return result
-  from an issued command.
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: memcached_response() is used to determine the return result from an issued command.
+ *
 */
 
 #include "common.h"
 
-static memcached_return_t textual_read_one_response(memcached_server_st *ptr,
-                                                  char *buffer, size_t buffer_length,
-                                                  memcached_result_st *result);
-static memcached_return_t binary_read_one_response(memcached_server_st *ptr,
-                                                 char *buffer, size_t buffer_length,
-                                                 memcached_result_st *result);
+static memcached_return_t textual_read_one_response(memcached_server_instance_st *ptr,
+                                                    char *buffer, size_t buffer_length,
+                                                    memcached_result_st *result);
+static memcached_return_t binary_read_one_response(memcached_server_instance_st *ptr,
+                                                   char *buffer, size_t buffer_length,
+                                                   memcached_result_st *result);
 
-memcached_return_t memcached_read_one_response(memcached_server_st *ptr,
-                                             char *buffer, size_t buffer_length,
-                                             memcached_result_st *result)
+memcached_return_t memcached_read_one_response(memcached_server_instance_st *ptr,
+                                               char *buffer, size_t buffer_length,
+                                               memcached_result_st *result)
 {
   memcached_server_response_decrement(ptr);
 
   if (result == NULL)
-    result = &ptr->root->result;
+  {
+    memcached_st *root= (memcached_st *)ptr->root;
+    result = &root->result;
+  }
 
   memcached_return_t rc;
   if (ptr->root->flags.binary_protocol)
@@ -33,29 +40,31 @@ memcached_return_t memcached_read_one_response(memcached_server_st *ptr,
            rc == MEMCACHED_PROTOCOL_ERROR ||
            rc == MEMCACHED_CLIENT_ERROR ||
            rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE)
-     memcached_io_reset(ptr);
+    memcached_io_reset(ptr);
 
   return rc;
 }
 
-memcached_return_t memcached_response(memcached_server_st *ptr, 
-                                    char *buffer, size_t buffer_length,
-                                    memcached_result_st *result)
+memcached_return_t memcached_response(memcached_server_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)
+  if ((ptr->root->flags.no_block) && (memcached_is_processing_input(ptr->root) == false))
+  {
     (void)memcached_io_write(ptr, NULL, 0, 1);
+  }
 
   /*
    * 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 &&
@@ -64,15 +73,15 @@ memcached_return_t memcached_response(memcached_server_st *ptr,
                 rc != MEMCACHED_NOTFOUND &&
                 rc != MEMCACHED_NOTSTORED && 
                 rc != MEMCACHED_DATA_EXISTS)
-       return rc;
+        return rc;
     }
 
   return memcached_read_one_response(ptr, buffer, buffer_length, result);
 }
 
-static memcached_return_t textual_value_fetch(memcached_server_st *ptr,
-                                            char *buffer,
-                                            memcached_result_st *result)
+static memcached_return_t textual_value_fetch(memcached_server_instance_st *ptr,
+                                              char *buffer,
+                                              memcached_result_st *result)
 {
   memcached_return_t rc= MEMCACHED_SUCCESS;
   char *string_ptr;
@@ -81,6 +90,8 @@ static memcached_return_t textual_value_fetch(memcached_server_st *ptr,
   size_t value_length;
   size_t to_read;
   char *value_ptr;
+  ssize_t read_length= 0;
+  memcached_return_t rrc;
 
   if (ptr->root->flags.use_udp)
     return MEMCACHED_NOT_SUPPORTED;
@@ -99,7 +110,7 @@ static memcached_return_t textual_value_fetch(memcached_server_st *ptr,
     char *key;
     size_t prefix_length;
 
-    key= result->key;
+    key= result->item_key;
     result->key_length= 0;
 
     for (prefix_length= ptr->root->prefix_key_length; !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++)
@@ -113,7 +124,7 @@ static memcached_return_t textual_value_fetch(memcached_server_st *ptr,
       else
         prefix_length--;
     }
-    result->key[result->key_length]= 0;
+    result->item_key[result->key_length]= 0;
   }
 
   if (end_ptr == string_ptr)
@@ -124,7 +135,7 @@ static memcached_return_t textual_value_fetch(memcached_server_st *ptr,
   if (end_ptr == string_ptr)
     goto read_error;
   for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++);
-  result->flags= (uint32_t) strtoul(next_ptr, &string_ptr, 10);
+  result->item_flags= (uint32_t) strtoul(next_ptr, &string_ptr, 10);
 
   if (end_ptr == string_ptr)
     goto read_error;
@@ -150,7 +161,7 @@ static memcached_return_t textual_value_fetch(memcached_server_st *ptr,
   {
     string_ptr++;
     for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++);
-    result->cas= strtoull(next_ptr, &string_ptr, 10);
+    result->item_cas= strtoull(next_ptr, &string_ptr, 10);
   }
 
   if (end_ptr < string_ptr)
@@ -173,8 +184,7 @@ static memcached_return_t textual_value_fetch(memcached_server_st *ptr,
     some people lazy about using the return length.
   */
   to_read= (value_length) + 2;
-  ssize_t read_length= 0;
-  memcached_return_t rrc= memcached_io_read(ptr, value_ptr, to_read, &read_length);
+  rrc= memcached_io_read(ptr, value_ptr, to_read, &read_length);
   if (rrc != MEMCACHED_SUCCESS)
     return rrc;
 
@@ -183,7 +193,7 @@ static memcached_return_t textual_value_fetch(memcached_server_st *ptr,
     goto read_error;
   }
 
-/* This next bit blows the API, but this is internal....*/
+  /* This next bit blows the API, but this is internal....*/
   {
     char *char_ptr;
     char_ptr= memcached_string_value(&result->value);;
@@ -200,9 +210,9 @@ read_error:
   return MEMCACHED_PARTIAL_READ;
 }
 
-static memcached_return_t textual_read_one_response(memcached_server_st *ptr,
-                                                  char *buffer, size_t buffer_length,
-                                                  memcached_result_st *result)
+static memcached_return_t textual_read_one_response(memcached_server_instance_st *ptr,
+                                                    char *buffer, size_t buffer_length,
+                                                    memcached_result_st *result)
 {
   memcached_return_t rc= memcached_io_readline(ptr, buffer, buffer_length);
   if (rc != MEMCACHED_SUCCESS)
@@ -237,35 +247,35 @@ static memcached_return_t textual_read_one_response(memcached_server_st *ptr,
         return MEMCACHED_STAT;
       }
       else if (buffer[1] == 'E') /* SERVER_ERROR */ 
-       {
-          char *rel_ptr;
-         char *startptr= buffer + 13, *endptr= startptr;
-
-         while (*endptr != '\r' && *endptr != '\n') endptr++;
-
-          /* 
-            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?
-          */
-         rel_ptr= (char *)ptr->root->call_realloc(ptr->root, 
-                                                   ptr->cached_server_error, 
-                                                   (size_t) (endptr - startptr + 1));
-
-          if (rel_ptr == NULL)
-          {
-            /* 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;
-          }
-         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 *rel_ptr;
+        char *startptr= buffer + 13, *endptr= startptr;
+
+        while (*endptr != '\r' && *endptr != '\n') endptr++;
+
+        /* 
+          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?
+        */
+        rel_ptr= (char *)libmemcached_realloc(ptr->root,
+                                              ptr->cached_server_error, 
+                                              (size_t) (endptr - startptr + 1));
+
+        if (rel_ptr == NULL)
+        {
+          /* 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;
+        }
+        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;
+      }
       else if (buffer[1] == 'T')
         return MEMCACHED_STORED;
       else
@@ -298,8 +308,8 @@ static memcached_return_t textual_read_one_response(memcached_server_st *ptr,
         return MEMCACHED_UNKNOWN_READ_FAILURE;
     }
   case 'I': /* CLIENT ERROR */
-      /* We add back in one because we will need to search for END */
-      memcached_server_response_increment(ptr);
+    /* We add back in one because we will need to search for END */
+    memcached_server_response_increment(ptr);
     return MEMCACHED_ITEM;
   case 'C': /* CLIENT ERROR */
     return MEMCACHED_CLIENT_ERROR;
@@ -317,24 +327,12 @@ static memcached_return_t textual_read_one_response(memcached_server_st *ptr,
   /* NOTREACHED */
 }
 
-char *memcached_result_value(memcached_result_st *ptr)
-{
-  memcached_string_st *sptr= &ptr->value;
-  return memcached_string_value(sptr);
-}
-
-size_t memcached_result_length(memcached_result_st *ptr)
-{
-  memcached_string_st *sptr= &ptr->value;
-  return memcached_string_length(sptr);
-}
-
-static memcached_return_t binary_read_one_response(memcached_server_st *ptr,
-                                                 char *buffer, size_t buffer_length,
-                                                 memcached_result_st *result)
+static memcached_return_t binary_read_one_response(memcached_server_instance_st *ptr,
+                                                   char *buffer, size_t buffer_length,
+                                                   memcached_result_st *result)
 {
   protocol_binary_response_header header;
-   
+
   unlikely (memcached_safe_read(ptr, &header.bytes, 
                                 sizeof(header.bytes)) != MEMCACHED_SUCCESS)
     return MEMCACHED_UNKNOWN_READ_FAILURE;
@@ -343,8 +341,8 @@ static memcached_return_t binary_read_one_response(memcached_server_st *ptr,
     return MEMCACHED_PROTOCOL_ERROR;
 
   /*
-  ** Convert the header to host local endian!
 */
+   ** Convert the header to host local endian!
+ */
   header.response.keylen= ntohs(header.response.keylen);
   header.response.status= ntohs(header.response.status);
   header.response.bodylen= ntohl(header.response.bodylen);
@@ -366,17 +364,17 @@ static memcached_return_t binary_read_one_response(memcached_server_st *ptr,
       {
         uint16_t keylen= header.response.keylen;
         memcached_result_reset(result);
-        result->cas= header.response.cas;
+        result->item_cas= header.response.cas;
 
-        if (memcached_safe_read(ptr, &result->flags,
-                                sizeof (result->flags)) != MEMCACHED_SUCCESS)
+        if (memcached_safe_read(ptr, &result->item_flags,
+                                sizeof (result->item_flags)) != MEMCACHED_SUCCESS)
           return MEMCACHED_UNKNOWN_READ_FAILURE;
 
-        result->flags= ntohl(result->flags);
+        result->item_flags= ntohl(result->item_flags);
         bodylen -= header.response.extlen;
 
         result->key_length= keylen;
-        if (memcached_safe_read(ptr, result->key, keylen) != MEMCACHED_SUCCESS) 
+        if (memcached_safe_read(ptr, result->item_key, keylen) != MEMCACHED_SUCCESS) 
           return MEMCACHED_UNKNOWN_READ_FAILURE;
 
         bodylen -= keylen;
@@ -461,7 +459,7 @@ static memcached_return_t binary_read_one_response(memcached_server_st *ptr,
   } 
   else if (header.response.bodylen) 
   {
-     /* What should I do with the error message??? just discard it for now */
+    /* What should I do with the error message??? just discard it for now */
     char hole[SMALL_STRING_LEN];
     while (bodylen > 0) 
     {
@@ -474,7 +472,7 @@ static memcached_return_t binary_read_one_response(memcached_server_st *ptr,
     /* This might be an error from one of the quiet commands.. if
      * so, just throw it away and get the next one. What about creating
      * a callback to the user with the error information?
-     */
+   */
     switch (header.response.opcode)
     {
     case PROTOCOL_BINARY_CMD_SETQ:
@@ -514,6 +512,6 @@ static memcached_return_t binary_read_one_response(memcached_server_st *ptr,
       rc= MEMCACHED_PROTOCOL_ERROR;
       break;
     }
-    
+
   return rc;
 }