Fix prefix key so that it is not statically built.
authorBrian Aker <brian@tangent.org>
Mon, 21 Mar 2011 20:03:49 +0000 (13:03 -0700)
committerBrian Aker <brian@tangent.org>
Mon, 21 Mar 2011 20:03:49 +0000 (13:03 -0700)
13 files changed:
libmemcached/array.c
libmemcached/array.h
libmemcached/auto.c
libmemcached/callback.c
libmemcached/common.h
libmemcached/delete.c
libmemcached/get.c
libmemcached/hash.c
libmemcached/memcached.c
libmemcached/memcached.h
libmemcached/response.c
libmemcached/storage.c
tests/mem_functions.c

index f8facbaa8cea5a861f254ef660ea8dfc4fc6efb6..657bcdad96840c3909fe5ccce3c93c41e8637250 100644 (file)
  *
  */
 
-#include <config.h>
-
 #include "libmemcached/common.h"
 
 struct memcached_array_st
 {
+  memcached_st *root;
   size_t size;
   char c_str[];
 };
 
-memcached_array_st *memcached_strcpy(const char *str, size_t str_length)
+memcached_array_st *memcached_array_clone(memcached_st *memc, const memcached_array_st *original)
+{
+  if (! original)
+    return NULL;
+
+  return memcached_strcpy(memc, original->c_str, original->size);
+}
+
+memcached_array_st *memcached_strcpy(memcached_st *memc, const char *str, size_t str_length)
 {
-  memcached_array_st *array= (struct memcached_array_st *)malloc(sizeof(struct memcached_array_st) +str_length +1);
+  memcached_array_st *array= (struct memcached_array_st *)libmemcached_malloc(memc, sizeof(struct memcached_array_st) +str_length +1);
+
+  if (! array)
+    return NULL;
 
-  array->size= str_length;
+  array->root= memc;
+  array->size= str_length -1; // We don't count the NULL ending
   memcpy(array->c_str, str, str_length);
-  array->c_str[str_length]= 0;
+  array->c_str[str_length +1]= 0;
 
   return array;
 }
 
 void memcached_array_free(memcached_array_st *array)
 {
-  WATCHPOINT_ASSERT(array);
-  if (array)
+  if (! array)
+    return;
+
+  WATCHPOINT_ASSERT(array->root);
+  if (array && array->root)
+  {
+    libmemcached_free(array->root, array);
+  }
+  else if (array)
+  {
     free(array);
+  }
+}
+
+size_t memcached_array_size(memcached_array_st *array)
+{
+  if (! array)
+    return 0;
+
+  return array->size;
+}
+
+const char *memcached_array_string(memcached_array_st *array)
+{
+  if (! array)
+    return NULL;
+
+  return array->c_str;
 }
index 78846b612c7021a07a6bcdca4f4859d248a0294d..08938494f7a7d24e427a1780894c093aacadd2a8 100644 (file)
@@ -42,11 +42,26 @@ extern "C" {
 #endif
 
 LIBMEMCACHED_LOCAL
-memcached_array_st *memcached_strcpy(const char *str, size_t str_length);
+memcached_array_st *memcached_array_clone(memcached_st *memc, const memcached_array_st *original);
+
+LIBMEMCACHED_LOCAL
+memcached_array_st *memcached_strcpy(memcached_st *memc, const char *str, size_t str_length);
 
 LIBMEMCACHED_LOCAL
 void memcached_array_free(memcached_array_st *array);
 
+LIBMEMCACHED_LOCAL
+size_t memcached_array_size(memcached_array_st *array);
+
+LIBMEMCACHED_LOCAL
+const char *memcached_array_string(memcached_array_st *array);
+
+#ifdef __cplusplus
+#define memcached_print_array(X) static_cast<int>(memcached_array_size(X)), memcached_array_string(X)
+#else
+#define memcached_print_array(X) (int)memcached_array_size((X)), memcached_array_string((X))
+#endif
+
 
 #ifdef __cplusplus
 } // extern "C"
index c2033b37ceb96dad9302e850ee39a90da4fed1d3..7bd0cc12518c100521466635c4f85f3901e967df 100644 (file)
@@ -9,7 +9,7 @@
  *
  */
 
-#include "common.h"
+#include "libmemcached/common.h"
 
 static memcached_return_t text_incr_decr(memcached_st *ptr,
                                          const char *verb,
@@ -36,8 +36,7 @@ static memcached_return_t text_incr_decr(memcached_st *ptr,
   int send_length;
   send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
                         "%s %.*s%.*s %" PRIu64 "%s\r\n", verb,
-                        (int)ptr->prefix_key_length,
-                        ptr->prefix_key,
+                        memcached_print_array(ptr->prefix_key),
                         (int)key_length, key,
                         offset, no_reply ? " noreply" : "");
   if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0)
@@ -108,10 +107,10 @@ static memcached_return_t binary_incr_decr(memcached_st *ptr, uint8_t cmd,
 
   request.message.header.request.magic= PROTOCOL_BINARY_REQ;
   request.message.header.request.opcode= cmd;
-  request.message.header.request.keylen= htons((uint16_t)(key_length + ptr->prefix_key_length));
+  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->prefix_key)));
   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 + ptr->prefix_key_length +  request.message.header.request.extlen));
+  request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(ptr->prefix_key) +request.message.header.request.extlen));
   request.message.body.delta= htonll(offset);
   request.message.body.initial= htonll(initial);
   request.message.body.expiration= htonl((uint32_t) expiration);
@@ -119,7 +118,7 @@ static memcached_return_t binary_incr_decr(memcached_st *ptr, uint8_t cmd,
   struct libmemcached_io_vector_st vector[]=
   {
     { .length= sizeof(request.bytes), .buffer= request.bytes },
-    { .length= ptr->prefix_key_length, .buffer= ptr->prefix_key },
+    { .length= memcached_array_size(ptr->prefix_key), .buffer= ptr->prefix_key },
     { .length= key_length, .buffer= key }
   };
 
index aba1a383670afd4cf0d297b9f54de423a259dc6f..69e47d4d78ad9bd5bdc3c507496928f324e3a87c 100644 (file)
@@ -31,25 +31,21 @@ memcached_return_t memcached_callback_set(memcached_st *ptr,
         size_t key_length= strlen(key);
 
         if (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED)
-        {
-          return MEMCACHED_BAD_KEY_PROVIDED;
-        }
+          return memcached_set_error(ptr, MEMCACHED_BAD_KEY_PROVIDED, NULL);
 
-        if ((key_length > MEMCACHED_PREFIX_KEY_MAX_SIZE -1)
-            || (strncpy(ptr->prefix_key, key, MEMCACHED_PREFIX_KEY_MAX_SIZE) == NULL))
-        {
-          ptr->prefix_key_length= 0;
-          return MEMCACHED_BAD_KEY_PROVIDED;
-        }
-        else
-        {
-          ptr->prefix_key_length= key_length;
-        }
+        if ((key_length > MEMCACHED_PREFIX_KEY_MAX_SIZE -1))
+          return memcached_set_error(ptr, MEMCACHED_KEY_TOO_BIG, NULL);
+
+        memcached_array_free(ptr->prefix_key);
+        ptr->prefix_key= memcached_strcpy(ptr, (const char *)data, strlen((const char*)data));
+
+        f (! ptr->prefix_key)
+          return memcached_set_error(ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, NULL);
       }
       else
       {
-        ptr->prefix_key[0]= 0;
-        ptr->prefix_key_length= 0;
+        memcached_array_free(ptr->prefix_key);
+        ptr->prefix_key= NULL;
       }
 
       break;
@@ -124,10 +120,10 @@ void *memcached_callback_get(memcached_st *ptr,
   {
   case MEMCACHED_CALLBACK_PREFIX_KEY:
     {
-      if (ptr->prefix_key_length)
+      if (ptr->prefix_key)
       {
         *error= MEMCACHED_SUCCESS;
-        return (void *)ptr->prefix_key;
+        return (void *)memcached_array_string(ptr->prefix_key);
       }
       else
       {
index 26182b19677dfc2790edcda19ce75a7702c39296..e6f845eacafb01b1d877c4db92d29983f9317646 100644 (file)
@@ -66,6 +66,7 @@ memcached_return_t memcached_server_execute(memcached_st *ptr,
 #include "libmemcached/io.h"
 #include "libmemcached/do.h"
 #include "libmemcached/internal.h"
+#include "libmemcached/array.h"
 #include "libmemcached/libmemcached_probes.h"
 #include "libmemcached/memcached/protocol_binary.h"
 #include "libmemcached/byteorder.h"
index ef1fa6da328e499e94d931e608f88db2ac6e5c81..2f205cd6f293b42d0a148bdf30995018a0a3d810 100644 (file)
@@ -92,8 +92,7 @@ memcached_return_t memcached_delete_by_key(memcached_st *ptr,
           }
           send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
                                 "delete %.*s%.*s %u%s\r\n",
-                                (int)ptr->prefix_key_length,
-                                ptr->prefix_key,
+                                memcached_print_array(ptr->prefix_key),
                                 (int) key_length, key,
                                 (uint32_t)expiration,
                                 no_reply ? " noreply" :"" );
@@ -103,8 +102,7 @@ memcached_return_t memcached_delete_by_key(memcached_st *ptr,
     {
       send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
                             "delete %.*s%.*s%s\r\n",
-                            (int)ptr->prefix_key_length,
-                            ptr->prefix_key,
+                            memcached_print_array(ptr->prefix_key),
                             (int)key_length, key, no_reply ? " noreply" :"");
     }
 
@@ -163,9 +161,9 @@ static inline memcached_return_t binary_delete(memcached_st *ptr,
     request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ;
   else
     request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETE;
-  request.message.header.request.keylen= htons((uint16_t)(key_length + ptr->prefix_key_length));
+  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->prefix_key)));
   request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-  request.message.header.request.bodylen= htonl((uint32_t)(key_length + ptr->prefix_key_length));
+  request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(ptr->prefix_key)));
 
   if (ptr->flags.use_udp && ! flush)
   {
@@ -179,7 +177,7 @@ static inline memcached_return_t binary_delete(memcached_st *ptr,
   struct libmemcached_io_vector_st vector[]=
   {
     { .length= sizeof(request.bytes), .buffer= request.bytes},
-    { .length= ptr->prefix_key_length, .buffer= ptr->prefix_key },
+    { .length= memcached_array_size(ptr->prefix_key), .buffer= memcached_array_string(ptr->prefix_key) },
     { .length= key_length, .buffer= key },
   };
 
index aa4e6f53de49eb2fba940dc08046f50c9ef6909e..13fe60799418e2bc8cc451f7d6009319553fe60a 100644 (file)
@@ -232,7 +232,7 @@ static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr,
     struct libmemcached_io_vector_st vector[]=
     {
       { .length= get_command_length, .buffer= get_command },
-      { .length= ptr->prefix_key_length, .buffer= ptr->prefix_key },
+      { .length= memcached_array_size(ptr->prefix_key), .buffer= memcached_array_string(ptr->prefix_key) },
       { .length= key_length[x], .buffer= keys[x] },
       { .length= 1, .buffer= " " }
     };
@@ -423,14 +423,14 @@ static memcached_return_t simple_binary_mget(memcached_st *ptr,
       return vk;
     }
 
-    request.message.header.request.keylen= htons((uint16_t)(key_length[x] + ptr->prefix_key_length));
+    request.message.header.request.keylen= htons((uint16_t)(key_length[x] + memcached_array_size(ptr->prefix_key)));
     request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-    request.message.header.request.bodylen= htonl((uint32_t)( key_length[x] + ptr->prefix_key_length));
+    request.message.header.request.bodylen= htonl((uint32_t)( key_length[x] + memcached_array_size(ptr->prefix_key)));
 
     struct libmemcached_io_vector_st vector[]=
     {
       { .length= sizeof(request.bytes), .buffer= request.bytes },
-      { .length= ptr->prefix_key_length, .buffer= ptr->prefix_key },
+      { .length= memcached_array_size(ptr->prefix_key), .buffer= memcached_array_string(ptr->prefix_key) },
       { .length= key_length[x], .buffer= keys[x] }
     };
 
@@ -545,9 +545,9 @@ static memcached_return_t replication_binary_mget(memcached_st *ptr,
         .message.header.request= {
           .magic= PROTOCOL_BINARY_REQ,
           .opcode= PROTOCOL_BINARY_CMD_GETK,
-          .keylen= htons((uint16_t)(key_length[x] + ptr->prefix_key_length)),
+          .keylen= htons((uint16_t)(key_length[x] + memcached_array_size(ptr->prefix_key))),
           .datatype= PROTOCOL_BINARY_RAW_BYTES,
-          .bodylen= htonl((uint32_t)(key_length[x] + ptr->prefix_key_length))
+          .bodylen= htonl((uint32_t)(key_length[x] + memcached_array_size(ptr->prefix_key)))
         }
       };
 
@@ -564,7 +564,7 @@ static memcached_return_t replication_binary_mget(memcached_st *ptr,
       struct libmemcached_io_vector_st vector[]=
       {
         { .length= sizeof(request.bytes), .buffer= request.bytes },
-        { .length= ptr->prefix_key_length, .buffer= ptr->prefix_key },
+        { .length= memcached_array_size(ptr->prefix_key), .buffer= memcached_array_string(ptr->prefix_key) },
         { .length= key_length[x], .buffer= keys[x] }
       };
 
index abad4f5bf3bce3951ee0f019560a733addca00fa..a9c1f8ed6026a6ba458bdcc1434e454c01762af2 100644 (file)
@@ -74,14 +74,14 @@ static inline uint32_t _generate_hash_wrapper(const memcached_st *ptr, const cha
 
   if (ptr->flags.hash_with_prefix_key)
   {
-    size_t temp_length= ptr->prefix_key_length + key_length;
+    size_t temp_length= memcached_array_size(ptr->prefix_key) + key_length;
     char temp[temp_length];
 
     if (temp_length > MEMCACHED_MAX_KEY -1)
       return EXIT_SUCCESS;
 
-    strncpy(temp, ptr->prefix_key, ptr->prefix_key_length);
-    strncpy(temp + ptr->prefix_key_length, key, key_length);
+    strncpy(temp, memcached_array_string(ptr->prefix_key), memcached_array_size(ptr->prefix_key));
+    strncpy(temp + memcached_array_size(ptr->prefix_key), key, key_length);
 
     return generate_hash(ptr, temp, temp_length);
   }
index 3a4e4c4a78d8edc6c1a18020e7b388d469f67c95..3d255fc0cab5c8cca2396de95a732ecbf93983b5 100644 (file)
@@ -80,7 +80,6 @@ static inline bool _memcached_init(memcached_st *self)
 
   self->user_data= NULL;
   self->next_distribution_rebuild= 0;
-  self->prefix_key_length= 0;
   self->number_of_replicas= 0;
   hash_ptr= hashkit_create(&self->distribution_hashkit);
   if (! hash_ptr)
@@ -98,6 +97,7 @@ static inline bool _memcached_init(memcached_st *self)
   self->sasl.is_allocated= false;
 
   self->error_messages= NULL;
+  self->prefix_key= NULL;
 
   return true;
 }
@@ -118,6 +118,9 @@ static void _free(memcached_st *ptr, bool release_st)
   if (ptr->continuum)
     libmemcached_free(ptr, ptr->continuum);
 
+  memcached_array_free(ptr->prefix_key);
+  ptr->prefix_key= NULL;
+
   memcached_error_free(ptr);
 
   if (ptr->sasl.callbacks)
@@ -290,11 +293,7 @@ memcached_st *memcached_clone(memcached_st *clone, const memcached_st *source)
   }
 
 
-  if (source->prefix_key_length)
-  {
-    strcpy(new_clone->prefix_key, source->prefix_key);
-    new_clone->prefix_key_length= source->prefix_key_length;
-  }
+  new_clone->prefix_key= memcached_array_clone(new_clone, source->prefix_key);
 
 #ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
   if (source->sasl.callbacks)
index bef6354a128280c56eb2295ca94082fda01752f3..9d0d2f0be30a814e949a7833f230dd60e3364a3c 100644 (file)
@@ -109,7 +109,6 @@ struct memcached_st {
   int recv_size;
   void *user_data;
   time_t next_distribution_rebuild; // Ketama
-  size_t prefix_key_length;
   uint32_t number_of_replicas;
   hashkit_st distribution_hashkit;
   memcached_result_st result;
@@ -130,7 +129,7 @@ struct memcached_st {
   memcached_callback_st *callbacks;
   struct memcached_sasl_st sasl;
   struct memcached_error_st *error_messages;
-  char prefix_key[MEMCACHED_PREFIX_KEY_MAX_SIZE];
+  struct memcached_array_st *prefix_key;
   struct {
     bool is_allocated:1;
   } options;
index 867a999ef039b16f190dce2f04c49166e722aa06..49825fb1881feae3517c6f21a2ff0a3f4d6c8ad2 100644 (file)
@@ -115,7 +115,7 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
     key= result->item_key;
     result->key_length= 0;
 
-    for (prefix_length= ptr->root->prefix_key_length; !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++)
+    for (prefix_length= memcached_array_size(ptr->root->prefix_key); !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++)
     {
       if (prefix_length == 0)
       {
index 191802ab6f48c67d012dbe8846253e422730567b..c31a473a3b50291cc56798c50b2900b129f2fec7 100644 (file)
@@ -108,8 +108,7 @@ static inline memcached_return_t memcached_send(memcached_st *ptr,
       check_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
                                     "%s %.*s%.*s %u %llu %lu %llu%s\r\n",
                                     storage_op_string(verb),
-                                    (int)ptr->prefix_key_length,
-                                    ptr->prefix_key,
+                                    memcached_print_array(ptr->prefix_key),
                                     (int)key_length, key, flags,
                                     (unsigned long long)expiration, (unsigned long)value_length,
                                     (unsigned long long)cas,
@@ -132,10 +131,10 @@ static inline memcached_return_t memcached_send(memcached_st *ptr,
       memcpy(buffer_ptr, command, strlen(command));
 
       /* Copy in the key prefix, switch to the buffer_ptr */
-      buffer_ptr= memcpy((buffer_ptr + strlen(command)), ptr->prefix_key, ptr->prefix_key_length);
+      buffer_ptr= memcpy((buffer_ptr + strlen(command)), memcached_array_string(ptr->prefix_key), memcached_array_size(ptr->prefix_key));
 
       /* Copy in the key, adjust point if a key prefix was used. */
-      buffer_ptr= memcpy(buffer_ptr + (ptr->prefix_key_length ? ptr->prefix_key_length : 0),
+      buffer_ptr= memcpy(buffer_ptr + memcached_array_size(ptr->prefix_key),
                          key, key_length);
       buffer_ptr+= key_length;
       buffer_ptr[0]=  ' ';
@@ -479,7 +478,7 @@ static memcached_return_t memcached_send_binary(memcached_st *ptr,
 
   request.message.header.request.magic= PROTOCOL_BINARY_REQ;
   request.message.header.request.opcode= get_com_code(verb, noreply);
-  request.message.header.request.keylen= htons((uint16_t)(key_length + ptr->prefix_key_length));
+  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->prefix_key)));
   request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
   if (verb == APPEND_OP || verb == PREPEND_OP)
     send_length -= 8; /* append & prepend does not contain extras! */
@@ -490,7 +489,7 @@ static memcached_return_t memcached_send_binary(memcached_st *ptr,
     request.message.body.expiration= htonl((uint32_t)expiration);
   }
 
-  request.message.header.request.bodylen= htonl((uint32_t) (key_length + ptr->prefix_key_length + value_length +
+  request.message.header.request.bodylen= htonl((uint32_t) (key_length + memcached_array_size(ptr->prefix_key) + value_length +
                                                             request.message.header.request.extlen));
 
   if (cas)
@@ -515,7 +514,7 @@ static memcached_return_t memcached_send_binary(memcached_st *ptr,
   struct libmemcached_io_vector_st vector[]=
   {
     { .length= send_length, .buffer= request.bytes },
-    { .length= ptr->prefix_key_length, .buffer= ptr->prefix_key },
+    { .length= memcached_array_size(ptr->prefix_key), .buffer= memcached_array_string(ptr->prefix_key) },
     { .length= key_length, .buffer= key },
     { .length= value_length, .buffer= value }
   };
index 090d00cc1978a71873b3e7d9740ea5d81ab05fba..7eb8e83b0de26889ccdaf12a688c7780f7510734 100644 (file)
@@ -3956,9 +3956,10 @@ static test_return_t set_prefix(memcached_st *memc)
 
   /* Test a clean set */
   rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, (void *)key);
-  test_true(rc == MEMCACHED_SUCCESS);
+  test_true_got(rc == MEMCACHED_SUCCESS, memcached_last_error_message(memc));
 
   value= memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc);
+  test_true(value);
   test_true(memcmp(value, key, 4) == 0);
   test_true(rc == MEMCACHED_SUCCESS);
 
@@ -3967,6 +3968,7 @@ static test_return_t set_prefix(memcached_st *memc)
   test_true(rc == MEMCACHED_SUCCESS);
 
   value= memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc);
+  test_false(value);
   test_true(rc == MEMCACHED_FAILURE);
 
   /* Now setup for main test */
@@ -3974,6 +3976,7 @@ static test_return_t set_prefix(memcached_st *memc)
   test_true(rc == MEMCACHED_SUCCESS);
 
   value= memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc);
+  test_true(value);
   test_true(rc == MEMCACHED_SUCCESS);
   test_true(memcmp(value, key, 4) == 0);
 
@@ -3986,6 +3989,7 @@ static test_return_t set_prefix(memcached_st *memc)
     test_true(rc == MEMCACHED_SUCCESS);
 
     value= memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc);
+    test_false(value);
     test_true(rc == MEMCACHED_FAILURE);
     test_true(value == NULL);