From: Brian Aker Date: Sun, 2 Oct 2011 23:49:04 +0000 (-0700) Subject: Update all of the delete key logic (split it off for ASCII) X-Git-Tag: 1.0.2~9^2~2^2~6 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=54b757ae099fb3db5132bd8a84b99a9a85492af1;p=m6w6%2Flibmemcached Update all of the delete key logic (split it off for ASCII) --- diff --git a/docs/memcached_servers.rst b/docs/memcached_servers.rst index 72da2764..ae5e7bae 100644 --- a/docs/memcached_servers.rst +++ b/docs/memcached_servers.rst @@ -20,7 +20,7 @@ SYNOPSIS .. c:function:: memcached_return_t memcached_server_push (memcached_st *ptr, const memcached_server_st *list) -.. c:function:: memcached_server_instance_st memcached_server_by_key (const memcached_st *ptr, const char *key, size_t key_length, memcached_return_t *error) +.. c:function:: memcached_server_instance_st memcached_server_by_key (memcached_st *ptr, const char *key, size_t key_length, memcached_return_t *error) .. c:function:: memcached_server_instance_st memcached_server_get_last_disconnect (const memcached_st *ptr) diff --git a/libmemcached-1.0/constants.h b/libmemcached-1.0/constants.h index 106aec49..9c8ab643 100644 --- a/libmemcached-1.0/constants.h +++ b/libmemcached-1.0/constants.h @@ -122,11 +122,6 @@ enum memcached_callback_t { MEMCACHED_CALLBACK_USER_DATA = 1, MEMCACHED_CALLBACK_CLEANUP_FUNCTION = 2, MEMCACHED_CALLBACK_CLONE_FUNCTION = 3, -#ifdef MEMCACHED_ENABLE_DEPRECATED - MEMCACHED_CALLBACK_MALLOC_FUNCTION = 4, - MEMCACHED_CALLBACK_REALLOC_FUNCTION = 5, - MEMCACHED_CALLBACK_FREE_FUNCTION = 6, -#endif MEMCACHED_CALLBACK_GET_FAILURE = 7, MEMCACHED_CALLBACK_DELETE_TRIGGER = 8, MEMCACHED_CALLBACK_MAX, diff --git a/libmemcached-1.0/server.h b/libmemcached-1.0/server.h index 3ca1df32..38ab40a9 100644 --- a/libmemcached-1.0/server.h +++ b/libmemcached-1.0/server.h @@ -108,10 +108,10 @@ memcached_return_t memcached_server_cursor(const memcached_st *ptr, uint32_t number_of_callbacks); LIBMEMCACHED_API - memcached_server_instance_st memcached_server_by_key(const memcached_st *ptr, - const char *key, - size_t key_length, - memcached_return_t *error); + memcached_server_instance_st memcached_server_by_key(memcached_st *ptr, + const char *key, + size_t key_length, + memcached_return_t *error); LIBMEMCACHED_API void memcached_server_error_reset(memcached_server_st *ptr); diff --git a/libmemcached/allocators.cc b/libmemcached/allocators.cc index cc41f2c3..d18372b4 100644 --- a/libmemcached/allocators.cc +++ b/libmemcached/allocators.cc @@ -90,11 +90,11 @@ memcached_return_t memcached_set_memory_allocators(memcached_st *self, } /* All should be set, or none should be set */ - if (mem_malloc == NULL && mem_free == NULL && mem_realloc == NULL && mem_calloc == NULL) + if (mem_malloc == NULL and mem_free == NULL and mem_realloc == NULL and mem_calloc == NULL) { self->allocators= memcached_allocators_return_default(); } - else if (mem_malloc == NULL || mem_free == NULL || mem_realloc == NULL || mem_calloc == NULL) + else if (mem_malloc == NULL or mem_free == NULL or mem_realloc == NULL or mem_calloc == NULL) { return memcached_set_error(*self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("NULL parameter provided for one or more allocators")); } diff --git a/libmemcached/callback.cc b/libmemcached/callback.cc index 84f99359..32d85dcd 100644 --- a/libmemcached/callback.cc +++ b/libmemcached/callback.cc @@ -30,51 +30,46 @@ memcached_return_t memcached_callback_set(memcached_st *ptr, { return memcached_set_namespace(ptr, (char*)data, data ? strlen((char*)data) : 0); } + case MEMCACHED_CALLBACK_USER_DATA: { ptr->user_data= const_cast(data); break; } + case MEMCACHED_CALLBACK_CLEANUP_FUNCTION: { memcached_cleanup_fn func= *(memcached_cleanup_fn *)&data; ptr->on_cleanup= func; break; } + case MEMCACHED_CALLBACK_CLONE_FUNCTION: { memcached_clone_fn func= *(memcached_clone_fn *)&data; ptr->on_clone= func; break; } -#ifdef MEMCACHED_ENABLE_DEPRECATED - case MEMCACHED_CALLBACK_MALLOC_FUNCTION: - { - memcached_malloc_function func= *(memcached_malloc_fn *)&data; - ptr->call_malloc= func; - break; - } - case MEMCACHED_CALLBACK_REALLOC_FUNCTION: - { - memcached_realloc_function func= *(memcached_realloc_fn *)&data; - ptr->call_realloc= func; - break; - } - case MEMCACHED_CALLBACK_FREE_FUNCTION: - { - memcached_free_function func= *(memcached_free_fn *)&data; - ptr->call_free= func; - break; - } -#endif + case MEMCACHED_CALLBACK_GET_FAILURE: { memcached_trigger_key_fn func= *(memcached_trigger_key_fn *)&data; ptr->get_key_failure= func; break; } + case MEMCACHED_CALLBACK_DELETE_TRIGGER: { + if (memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS)) + { + return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Delete triggers cannot be used if buffering is enabled")); + } + + if (memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_NOREPLY)) + { + return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Delete triggers cannot be used if MEMCACHED_BEHAVIOR_NOREPLY is set")); + } + memcached_trigger_delete_key_fn func= *(memcached_trigger_delete_key_fn *)&data; ptr->delete_trigger= func; break; @@ -97,67 +92,59 @@ void *memcached_callback_get(memcached_st *ptr, error = &local_error; } + if (ptr == NULL) + { + *error= MEMCACHED_INVALID_ARGUMENTS; + return NULL; + } + switch (flag) { case MEMCACHED_CALLBACK_PREFIX_KEY: { + *error= MEMCACHED_SUCCESS; if (ptr->_namespace) { - *error= MEMCACHED_SUCCESS; return (void *)memcached_array_string(ptr->_namespace); } - else - { - *error= MEMCACHED_FAILURE; - return NULL; - } + return NULL; } + case MEMCACHED_CALLBACK_USER_DATA: { *error= ptr->user_data ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE; return (void *)ptr->user_data; } + case MEMCACHED_CALLBACK_CLEANUP_FUNCTION: { *error= ptr->on_cleanup ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE; return *(void **)&ptr->on_cleanup; } + case MEMCACHED_CALLBACK_CLONE_FUNCTION: { *error= ptr->on_clone ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE; return *(void **)&ptr->on_clone; } -#ifdef MEMCACHED_ENABLE_DEPRECATED - case MEMCACHED_CALLBACK_MALLOC_FUNCTION: - { - *error= ptr->call_malloc ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE; - return *(void **)&ptr->call_malloc; - } - case MEMCACHED_CALLBACK_REALLOC_FUNCTION: - { - *error= ptr->call_realloc ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE; - return *(void **)&ptr->call_realloc; - } - case MEMCACHED_CALLBACK_FREE_FUNCTION: - { - *error= ptr->call_free ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE; - return *(void **)&ptr->call_free; - } -#endif + case MEMCACHED_CALLBACK_GET_FAILURE: { *error= ptr->get_key_failure ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE; return *(void **)&ptr->get_key_failure; } + case MEMCACHED_CALLBACK_DELETE_TRIGGER: { *error= ptr->delete_trigger ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE; return *(void **)&ptr->delete_trigger; } + case MEMCACHED_CALLBACK_MAX: - default: - assert_msg(0, "Invalid behavior passed to memcached_behavior_set()"); - *error= MEMCACHED_FAILURE; - return NULL; + break; } + + assert_msg(0, "Invalid behavior passed to memcached_behavior_set()"); + *error= MEMCACHED_FAILURE; + return NULL; } diff --git a/libmemcached/common.h b/libmemcached/common.h index f4956e87..6867490c 100644 --- a/libmemcached/common.h +++ b/libmemcached/common.h @@ -120,6 +120,7 @@ memcached_return_t memcached_server_execute(memcached_st *ptr, #include #include #include +#include #endif #include @@ -154,43 +155,9 @@ memcached_return_t run_distribution(memcached_st *ptr); #define memcached_server_response_decrement(A) (A)->cursor_active-- #define memcached_server_response_reset(A) (A)->cursor_active=0 -#ifdef __cplusplus -LIBMEMCACHED_LOCAL -memcached_return_t memcached_key_test(const memcached_st& memc, - const char * const *keys, - const size_t *key_length, - size_t number_of_keys); -#endif - LIBMEMCACHED_LOCAL memcached_return_t memcached_purge(memcached_server_write_instance_st ptr); - -static inline memcached_return_t memcached_validate_key_length(size_t key_length, bool binary) -{ - if (key_length == 0) - { - return MEMCACHED_BAD_KEY_PROVIDED; - } - - if (binary) - { - if (key_length > 0xffff) - { - return MEMCACHED_BAD_KEY_PROVIDED; - } - } - else - { - if (key_length >= MEMCACHED_MAX_KEY) - { - return MEMCACHED_BAD_KEY_PROVIDED; - } - } - - return MEMCACHED_SUCCESS; -} - #ifdef __cplusplus } #endif diff --git a/libmemcached/delete.cc b/libmemcached/delete.cc index 5244f0db..6be7e224 100644 --- a/libmemcached/delete.cc +++ b/libmemcached/delete.cc @@ -45,188 +45,135 @@ memcached_return_t memcached_delete(memcached_st *ptr, const char *key, size_t k key, key_length, expiration); } -static inline memcached_return_t binary_delete(memcached_st *ptr, - uint32_t server_key, - const char *key, - size_t key_length, - bool flush); - -memcached_return_t memcached_delete_by_key(memcached_st *ptr, - const char *group_key, size_t group_key_length, - const char *key, size_t key_length, - time_t expiration) +static inline memcached_return_t ascii_delete(memcached_st *ptr, + memcached_server_write_instance_st instance, + uint32_t , + const char *key, + size_t key_length, + uint64_t expiration, + bool& reply, + bool& flush) { char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; - memcached_server_write_instance_st instance; + int send_length; - LIBMEMCACHED_MEMCACHED_DELETE_START(); - - memcached_return_t rc; - if (memcached_failed(rc= initialize_query(ptr))) + if (expiration) { - return rc; - } - - rc= memcached_validate_key_length(key_length, - ptr->flags.binary_protocol); - - if (memcached_failed(rc)) - { - return rc; - } - - uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length); - instance= memcached_server_instance_fetch(ptr, server_key); - - bool to_write= (ptr->flags.buffer_requests) ? false : true; - - bool no_reply= (ptr->flags.no_reply); - - if (ptr->flags.binary_protocol) - { - if (expiration == 0) + if ((instance->major_version == 1 and + instance->minor_version > 2) or + instance->major_version > 1) { - rc= binary_delete(ptr, server_key, key, key_length, to_write); + return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, + memcached_literal_param("Memcached server version does not allow expiration of deleted items")); } else { - rc= MEMCACHED_INVALID_ARGUMENTS; - } - } - else - { - int send_length; + /* ensure that we are connected, otherwise we might bump the + * command counter before connection */ + memcached_return_t rc; + if ((rc= memcached_connect(instance)) != MEMCACHED_SUCCESS) + { + WATCHPOINT_ERROR(rc); + return rc; + } - if (expiration) - { - if ((instance->major_version == 1 && - instance->minor_version > 2) || - instance->major_version > 1) - { - rc= MEMCACHED_INVALID_ARGUMENTS; - goto error; - } - else - { - /* ensure that we are connected, otherwise we might bump the - * command counter before connection */ - if ((rc= memcached_connect(instance)) != MEMCACHED_SUCCESS) + if (instance->minor_version == 0) + { + if (reply == false or flush == false) + { + /* We might get out of sync with the server if we send this command + * to a server newer than 1.2.x.. enable reply and buffered mode. + */ + flush= true; + if (reply == false) { - WATCHPOINT_ERROR(rc); - return rc; + memcached_server_response_increment(instance); } + reply= true; + } + } - if (instance->minor_version == 0) - { - if (no_reply or to_write == false) - { - /* We might get out of sync with the server if we - * send this command to a server newer than 1.2.x.. - * disable no_reply and buffered mode. - */ - to_write= true; - if (no_reply) - memcached_server_response_increment(instance); - no_reply= false; - } - } - send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, - "delete %.*s%.*s %u%s\r\n", - memcached_print_array(ptr->_namespace), - (int) key_length, key, - (uint32_t)expiration, - no_reply ? " noreply" :"" ); - } - } - else - { send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, - "delete %.*s%.*s%s\r\n", + "delete %.*s%.*s %u%s\r\n", memcached_print_array(ptr->_namespace), - (int)key_length, key, no_reply ? " noreply" :""); - } - - if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0) - { - rc= memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, - memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)")); - goto error; - } - - if (ptr->flags.use_udp and to_write == false) - { - if (send_length > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH) - return MEMCACHED_WRITE_FAILURE; - - if (send_length + instance->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH) - { - memcached_io_write(instance, NULL, 0, true); - } + (int) key_length, key, + (uint32_t)expiration, + reply ? "" : " noreply"); } - - rc= memcached_do(instance, buffer, (size_t)send_length, to_write); } - - if (rc != MEMCACHED_SUCCESS) + else { - goto error; + send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, + "delete %.*s%.*s%s\r\n", + memcached_print_array(ptr->_namespace), + (int)key_length, key, + reply ? "" : " noreply"); } - if (to_write == false) + if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0) { - rc= MEMCACHED_BUFFERED; + return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, + memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)")); } - else if (no_reply == false) + + if (ptr->flags.use_udp and flush == false) { - rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); - if (rc == MEMCACHED_DELETED) + if (send_length > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH) { - rc= MEMCACHED_SUCCESS; + return MEMCACHED_WRITE_FAILURE; } - } - if (rc == MEMCACHED_SUCCESS and ptr->delete_trigger) - { - ptr->delete_trigger(ptr, key, key_length); + if (send_length +instance->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH) + { + memcached_io_write(instance, NULL, 0, true); + } } -error: - LIBMEMCACHED_MEMCACHED_DELETE_END(); - return rc; + return memcached_do(instance, buffer, (size_t)send_length, flush); } static inline memcached_return_t binary_delete(memcached_st *ptr, + memcached_server_write_instance_st instance, uint32_t server_key, const char *key, size_t key_length, - bool flush) + time_t expiration, + bool& reply, + bool& flush) { - memcached_server_write_instance_st instance; protocol_binary_request_delete request= {}; - instance= memcached_server_instance_fetch(ptr, server_key); + // No expiration is supported in the binary protocol + if (expiration) + { + return MEMCACHED_INVALID_ARGUMENTS; + } request.message.header.request.magic= PROTOCOL_BINARY_REQ; - if (ptr->flags.no_reply) + if (reply) { - request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ; + request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETE; } else { - request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETE; + request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ; } request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->_namespace))); request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES; request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(ptr->_namespace))); - if (ptr->flags.use_udp && ! flush) + if (ptr->flags.use_udp and flush == false) { size_t cmd_size= sizeof(request.bytes) + key_length; if (cmd_size > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH) + { return MEMCACHED_WRITE_FAILURE; + } - if (cmd_size + instance->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH) + if (cmd_size +instance->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH) + { memcached_io_write(instance, NULL, 0, true); + } } struct libmemcached_io_vector_st vector[]= @@ -243,7 +190,7 @@ static inline memcached_return_t binary_delete(memcached_st *ptr, memcached_io_reset(instance); } - unlikely (ptr->number_of_replicas > 0) + if (ptr->number_of_replicas > 0) { request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ; @@ -270,3 +217,82 @@ static inline memcached_return_t binary_delete(memcached_st *ptr, return rc; } + +memcached_return_t memcached_delete_by_key(memcached_st *ptr, + const char *group_key, size_t group_key_length, + const char *key, size_t key_length, + time_t expiration) +{ + LIBMEMCACHED_MEMCACHED_DELETE_START(); + + memcached_return_t rc; + if (memcached_failed(rc= initialize_query(ptr))) + { + return rc; + } + + rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol); + if (memcached_failed(rc)) + { + return rc; + } + + // If a delete trigger exists, we need a response, so no buffering/noreply + if (ptr->delete_trigger) + { + if (ptr->flags.buffer_requests) + { + return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, + memcached_literal_param("Delete triggers cannot be used if buffering is enabled")); + } + + if (ptr->flags.no_reply) + { + return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, + memcached_literal_param("Delete triggers cannot be used if MEMCACHED_BEHAVIOR_NOREPLY is set")); + } + } + + + uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length); + memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key); + + bool to_write= (ptr->flags.buffer_requests) ? false : true; + + // Invert the logic to make it simpler to read the code + bool reply= (ptr->flags.no_reply) ? false : true; + + if (ptr->flags.binary_protocol) + { + rc= binary_delete(ptr, instance, server_key, key, key_length, expiration, reply, to_write); + } + else + { + rc= ascii_delete(ptr, instance, server_key, key, key_length, expiration, reply, to_write); + } + + if (rc == MEMCACHED_SUCCESS) + { + if (to_write == false) + { + rc= MEMCACHED_BUFFERED; + } + else if (reply) + { + char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; + rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); + if (rc == MEMCACHED_DELETED) + { + rc= MEMCACHED_SUCCESS; + } + } + + if (rc == MEMCACHED_SUCCESS and ptr->delete_trigger) + { + ptr->delete_trigger(ptr, key, key_length); + } + } + + LIBMEMCACHED_MEMCACHED_DELETE_END(); + return rc; +} diff --git a/libmemcached/error.cc b/libmemcached/error.cc index d6b7f166..85ce84e8 100644 --- a/libmemcached/error.cc +++ b/libmemcached/error.cc @@ -62,7 +62,9 @@ static void _set(memcached_server_st& server, memcached_st& memc) memcached_error_t *error= (struct memcached_error_t *)libmemcached_malloc(&memc, sizeof(struct memcached_error_t)); if (not error) // Bad business if this happens + { return; + } memcpy(error, memc.error_messages, sizeof(memcached_error_t)); error->next= server.error_messages; diff --git a/libmemcached/include.am b/libmemcached/include.am index 5ae58507..3097fdd0 100644 --- a/libmemcached/include.am +++ b/libmemcached/include.am @@ -25,12 +25,13 @@ noinst_HEADERS+= \ libmemcached/io.h \ libmemcached/io.hpp \ libmemcached/is.h \ + libmemcached/key.hpp \ libmemcached/libmemcached_probes.h \ + libmemcached/memcached/protocol_binary.h \ + libmemcached/memcached/vbucket.h \ libmemcached/memory.h \ libmemcached/namespace.h \ libmemcached/options.hpp \ - libmemcached/memcached/protocol_binary.h \ - libmemcached/memcached/vbucket.h \ libmemcached/protocol/ascii_handler.h \ libmemcached/protocol/binary_handler.h \ libmemcached/protocol/cache.h \ diff --git a/libmemcached/key.cc b/libmemcached/key.cc index 02e0c2b3..ea98c729 100644 --- a/libmemcached/key.cc +++ b/libmemcached/key.cc @@ -37,16 +37,43 @@ #include -memcached_return_t memcached_key_test(const memcached_st &memc, +memcached_return_t memcached_key_test(memcached_st &memc, const char * const *keys, const size_t *key_length, size_t number_of_keys) { + if (keys == NULL or key_length == NULL) + { + return memcached_set_error(memc, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT); + } + if (not memc.flags.verify_key) + { + for (uint32_t x= 0; x < number_of_keys; x++) + { + memcached_return_t rc= memcached_validate_key_length(*(key_length +x), false); + if (memcached_failed(rc)) + { + return rc; + } + } + return MEMCACHED_SUCCESS; + } if (memc.flags.binary_protocol) + { + for (uint32_t x= 0; x < number_of_keys; x++) + { + memcached_return_t rc= memcached_validate_key_length(*(key_length +x), false); + if (memcached_failed(rc)) + { + return rc; + } + } + return MEMCACHED_SUCCESS; + } for (uint32_t x= 0; x < number_of_keys; x++) { diff --git a/libmemcached/key.hpp b/libmemcached/key.hpp new file mode 100644 index 00000000..ddd557d8 --- /dev/null +++ b/libmemcached/key.hpp @@ -0,0 +1,67 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached library + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * The names of its contributors may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +memcached_return_t memcached_key_test(memcached_st& memc, + const char * const *keys, + const size_t *key_length, + size_t number_of_keys); + +static inline memcached_return_t memcached_validate_key_length(size_t key_length, bool binary) +{ + if (key_length == 0) + { + return MEMCACHED_BAD_KEY_PROVIDED; + } + + if (binary) + { + if (key_length > 0xffff) + { + return MEMCACHED_BAD_KEY_PROVIDED; + } + } + else + { + if (key_length >= MEMCACHED_MAX_KEY) + { + return MEMCACHED_BAD_KEY_PROVIDED; + } + } + + return MEMCACHED_SUCCESS; +} diff --git a/libmemcached/server.cc b/libmemcached/server.cc index 669979ef..b9151283 100644 --- a/libmemcached/server.cc +++ b/libmemcached/server.cc @@ -258,7 +258,7 @@ memcached_return_t memcached_server_execute(memcached_st *ptr, return MEMCACHED_SUCCESS; } -memcached_server_instance_st memcached_server_by_key(const memcached_st *ptr, +memcached_server_instance_st memcached_server_by_key(memcached_st *ptr, const char *key, size_t key_length, memcached_return_t *error) diff --git a/libmemcached/stats.cc b/libmemcached/stats.cc index 515adeeb..88e2d101 100644 --- a/libmemcached/stats.cc +++ b/libmemcached/stats.cc @@ -323,8 +323,10 @@ static memcached_return_t binary_stats_fetch(memcached_stat_st *memc_stat, size_t len= strlen(args); memcached_return_t rc= memcached_validate_key_length(len, true); - unlikely (rc != MEMCACHED_SUCCESS) + if (rc != MEMCACHED_SUCCESS) + { return rc; + } request.message.header.request.keylen= htons((uint16_t)len); request.message.header.request.bodylen= htonl((uint32_t) len); diff --git a/libtest/test.h b/libtest/test.h index 0f1e1e0a..74a20e05 100644 --- a/libtest/test.h +++ b/libtest/test.h @@ -160,6 +160,8 @@ do \ } \ } while (0) +#define test_compare_hint test_compare_got + #define test_compare_warn(__expected, __actual) \ do \ { \ diff --git a/tests/mem_functions.cc b/tests/mem_functions.cc index cca23464..c0e76be9 100644 --- a/tests/mem_functions.cc +++ b/tests/mem_functions.cc @@ -3802,10 +3802,10 @@ static test_return_t set_namespace(memcached_st *memc) const char *key= "mine"; char *value; - /* Make sure be default none exists */ + // Make sure we default to a null namespace value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc); test_null(value); - test_compare_got(MEMCACHED_FAILURE, rc, memcached_strerror(NULL, rc)); + test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc)); /* Test a clean set */ test_compare(MEMCACHED_SUCCESS, @@ -4358,6 +4358,10 @@ static void* connection_release(void *arg) static test_return_t connection_pool3_test(memcached_st *memc) { +#ifdef __APPLE__ + return TEST_SKIPPED; +#endif + memcached_pool_st* pool= memcached_pool_create(memc, 1, 1); test_true(pool); @@ -4385,6 +4389,7 @@ static test_return_t connection_pool3_test(memcached_st *memc) memcached_return_t rc; memcached_st *pop_memc; + // We do a hard loop, and try N times int counter= 5; do { @@ -4394,8 +4399,9 @@ static test_return_t connection_pool3_test(memcached_st *memc) if (memcached_failed(rc)) { test_null(pop_memc); + test_true(rc != MEMCACHED_TIMEOUT); // As long as relative_time is zero, MEMCACHED_TIMEOUT is invalid } - } while (rc == MEMCACHED_TIMEOUT and --counter); + } while (--counter); if (memcached_failed(rc)) // Cleanup thread since we will exit once we test. {