From 385cc099521ab79b8ecb289cd25c46d7cf3caa5c Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Mon, 21 Mar 2011 13:03:49 -0700 Subject: [PATCH] Fix prefix key so that it is not statically built. --- libmemcached/array.c | 52 +++++++++++++++++++++++++++++++++------- libmemcached/array.h | 17 ++++++++++++- libmemcached/auto.c | 11 ++++----- libmemcached/callback.c | 30 ++++++++++------------- libmemcached/common.h | 1 + libmemcached/delete.c | 12 ++++------ libmemcached/get.c | 14 +++++------ libmemcached/hash.c | 6 ++--- libmemcached/memcached.c | 11 ++++----- libmemcached/memcached.h | 3 +-- libmemcached/response.c | 2 +- libmemcached/storage.c | 13 +++++----- tests/mem_functions.c | 6 ++++- 13 files changed, 112 insertions(+), 66 deletions(-) diff --git a/libmemcached/array.c b/libmemcached/array.c index f8facbaa..657bcdad 100644 --- a/libmemcached/array.c +++ b/libmemcached/array.c @@ -35,30 +35,66 @@ * */ -#include - #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; } diff --git a/libmemcached/array.h b/libmemcached/array.h index 78846b61..08938494 100644 --- a/libmemcached/array.h +++ b/libmemcached/array.h @@ -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(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" diff --git a/libmemcached/auto.c b/libmemcached/auto.c index c2033b37..7bd0cc12 100644 --- a/libmemcached/auto.c +++ b/libmemcached/auto.c @@ -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 } }; diff --git a/libmemcached/callback.c b/libmemcached/callback.c index aba1a383..69e47d4d 100644 --- a/libmemcached/callback.c +++ b/libmemcached/callback.c @@ -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 { diff --git a/libmemcached/common.h b/libmemcached/common.h index 26182b19..e6f845ea 100644 --- a/libmemcached/common.h +++ b/libmemcached/common.h @@ -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" diff --git a/libmemcached/delete.c b/libmemcached/delete.c index ef1fa6da..2f205cd6 100644 --- a/libmemcached/delete.c +++ b/libmemcached/delete.c @@ -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 }, }; diff --git a/libmemcached/get.c b/libmemcached/get.c index aa4e6f53..13fe6079 100644 --- a/libmemcached/get.c +++ b/libmemcached/get.c @@ -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] } }; diff --git a/libmemcached/hash.c b/libmemcached/hash.c index abad4f5b..a9c1f8ed 100644 --- a/libmemcached/hash.c +++ b/libmemcached/hash.c @@ -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); } diff --git a/libmemcached/memcached.c b/libmemcached/memcached.c index 3a4e4c4a..3d255fc0 100644 --- a/libmemcached/memcached.c +++ b/libmemcached/memcached.c @@ -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) diff --git a/libmemcached/memcached.h b/libmemcached/memcached.h index bef6354a..9d0d2f0b 100644 --- a/libmemcached/memcached.h +++ b/libmemcached/memcached.h @@ -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; diff --git a/libmemcached/response.c b/libmemcached/response.c index 867a999e..49825fb1 100644 --- a/libmemcached/response.c +++ b/libmemcached/response.c @@ -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) { diff --git a/libmemcached/storage.c b/libmemcached/storage.c index 191802ab..c31a473a 100644 --- a/libmemcached/storage.c +++ b/libmemcached/storage.c @@ -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 } }; diff --git a/tests/mem_functions.c b/tests/mem_functions.c index 090d00cc..7eb8e83b 100644 --- a/tests/mem_functions.c +++ b/tests/mem_functions.c @@ -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); -- 2.30.2