From: Brian Aker Date: Thu, 26 Jan 2012 20:01:56 +0000 (-0800) Subject: Rollup from build trunk. X-Git-Tag: 1.0.4~2 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=77eab04d2140f8e2bd904f7ac4a59b4eef54244f;hp=331dfbb4650c36cda0a773876251e3eba0766175;p=awesomized%2Flibmemcached Rollup from build trunk. --- diff --git a/configure.ac b/configure.ac index aa91153c..d2183085 100644 --- a/configure.ac +++ b/configure.ac @@ -129,9 +129,12 @@ AC_CHECK_HEADERS([sys/time.h]) AC_CHECK_HEADERS([sasl/sasl.h]) AC_CHECK_HEADERS([execinfo.h]) AC_CHECK_HEADERS([cxxabi.h], - AC_DEFINE([HAVE_CXXABI_H], [1], [Have cxxabi.h]), - AC_DEFINE([HAVE_CXXABI_H], [0], [Have cxxabi.h])) + AC_DEFINE([HAVE_CXXABI_H], [1], [Have cxxabi.h]), + AC_DEFINE([HAVE_CXXABI_H], [0], [Have cxxabi.h])) + +AX_COMPILER_VENDOR AC_CXX_HEADER_STDCXX_98 +AX_TLS AC_FUNC_ALLOCA AC_FUNC_ERROR_AT_LINE @@ -162,7 +165,8 @@ AX_CXX_GCC_ABI_DEMANGLE AC_CHECK_LIB([rt], [clock_gettime], [ - rt_lib="-lrt" + RT_LIB="-lrt" + AC_SUBST(RT_LIB) AC_DEFINE([HAVE_LIBRT], [ 1 ], [Have clock_gettime]) ], [ diff --git a/libmemcached-1.0/return.h b/libmemcached-1.0/return.h index 28b4a97d..65dc63af 100644 --- a/libmemcached-1.0/return.h +++ b/libmemcached-1.0/return.h @@ -61,12 +61,20 @@ static inline bool memcached_failed(memcached_return_t rc) static inline bool memcached_fatal(memcached_return_t rc) { - return (rc != MEMCACHED_SUCCESS && + return ( + rc != MEMCACHED_BUFFERED && + rc != MEMCACHED_DATA_EXISTS && + rc != MEMCACHED_DELETED && + rc != MEMCACHED_E2BIG && rc != MEMCACHED_END && - rc != MEMCACHED_STORED && + rc != MEMCACHED_ITEM && + rc != MEMCACHED_ERROR && + rc != MEMCACHED_NOTFOUND && + rc != MEMCACHED_NOTSTORED && + rc != MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE && rc != MEMCACHED_STAT && - rc != MEMCACHED_DELETED && - rc != MEMCACHED_BUFFERED && + rc != MEMCACHED_STORED && + rc != MEMCACHED_SUCCESS && rc != MEMCACHED_VALUE); } diff --git a/libmemcached-1.0/types/return.h b/libmemcached-1.0/types/return.h index e57442e4..f4ec9b08 100644 --- a/libmemcached-1.0/types/return.h +++ b/libmemcached-1.0/types/return.h @@ -47,8 +47,8 @@ enum memcached_return_t { MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_CLIENT_ERROR, - MEMCACHED_SERVER_ERROR, - MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE, // DEPRECATED + MEMCACHED_SERVER_ERROR, // Server returns "SERVER_ERROR" + MEMCACHED_ERROR, // Server returns "ERROR" MEMCACHED_DATA_EXISTS, MEMCACHED_DATA_DOES_NOT_EXIST, MEMCACHED_NOTSTORED, @@ -86,7 +86,8 @@ enum memcached_return_t { MEMCACHED_IN_PROGRESS, MEMCACHED_SERVER_TEMPORARILY_DISABLED, MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE, - MEMCACHED_MAXIMUM_RETURN /* Always add new error code before */ + MEMCACHED_MAXIMUM_RETURN, /* Always add new error code before */ + MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE= MEMCACHED_ERROR }; #ifndef __cplusplus diff --git a/libmemcached/auto.cc b/libmemcached/auto.cc index 28550a18..c64ccda4 100644 --- a/libmemcached/auto.cc +++ b/libmemcached/auto.cc @@ -177,14 +177,9 @@ memcached_return_t memcached_increment_by_key(memcached_st *ptr, return rc; } - if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol))) - { - return rc; - } - if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1))) { - return memcached_set_error(*ptr, rc, MEMCACHED_AT); + return rc; } uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length); @@ -231,7 +226,7 @@ memcached_return_t memcached_decrement_by_key(memcached_st *ptr, if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1))) { - return memcached_set_error(*ptr, rc, MEMCACHED_AT); + return rc; } @@ -296,7 +291,7 @@ memcached_return_t memcached_increment_with_initial_by_key(memcached_st *ptr, if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1))) { - return memcached_set_error(*ptr, rc, MEMCACHED_AT); + return rc; } uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length); @@ -361,7 +356,7 @@ memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *ptr, if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1))) { - return memcached_set_error(*ptr, rc, MEMCACHED_AT); + return rc; } uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length); diff --git a/libmemcached/common.h b/libmemcached/common.h index 0f33a784..53481880 100644 --- a/libmemcached/common.h +++ b/libmemcached/common.h @@ -158,9 +158,6 @@ memcached_return_t memcached_server_execute(memcached_st *ptr, extern "C" { #endif -LIBMEMCACHED_LOCAL -memcached_return_t memcached_connect(memcached_server_write_instance_st ptr); - LIBMEMCACHED_LOCAL memcached_return_t run_distribution(memcached_st *ptr); diff --git a/libmemcached/connect.cc b/libmemcached/connect.cc index 42cbe9bc..1c7da465 100644 --- a/libmemcached/connect.cc +++ b/libmemcached/connect.cc @@ -129,8 +129,9 @@ static memcached_return_t connect_poll(memcached_server_st *server) return memcached_set_errno(*server, get_socket_errno(), MEMCACHED_AT); } -memcached_return_t set_hostinfo(memcached_server_st *server) +static memcached_return_t set_hostinfo(memcached_server_st *server) { + assert(server->type != MEMCACHED_CONNECTION_UNIX_SOCKET); if (server->address_info) { freeaddrinfo(server->address_info); @@ -619,7 +620,7 @@ static memcached_return_t backoff_handling(memcached_server_write_instance_st se return MEMCACHED_SUCCESS; } -memcached_return_t memcached_connect(memcached_server_write_instance_st server) +static memcached_return_t _memcached_connect(memcached_server_write_instance_st server, const bool set_last_disconnected) { if (server->fd != INVALID_SOCKET) { @@ -641,6 +642,11 @@ memcached_return_t memcached_connect(memcached_server_write_instance_st server) return memcached_set_error(*server, MEMCACHED_INVALID_HOST_PROTOCOL, MEMCACHED_AT, memcached_literal_param("SASL is not supported for UDP connections")); } + if (server->hostname[0] == '/') + { + server->type= MEMCACHED_CONNECTION_UNIX_SOCKET; + } + /* We need to clean up the multi startup piece */ switch (server->type) { @@ -673,25 +679,39 @@ memcached_return_t memcached_connect(memcached_server_write_instance_st server) memcached_mark_server_as_clean(server); return rc; } - - set_last_disconnected_host(server); - if (memcached_has_current_error(*server)) + else if (set_last_disconnected) { - memcached_mark_server_for_timeout(server); - assert(memcached_failed(memcached_server_error_return(server))); - } - else - { - memcached_set_error(*server, rc, MEMCACHED_AT); - memcached_mark_server_for_timeout(server); - } + set_last_disconnected_host(server); + if (memcached_has_current_error(*server)) + { + memcached_mark_server_for_timeout(server); + assert(memcached_failed(memcached_server_error_return(server))); + } + else + { + memcached_set_error(*server, rc, MEMCACHED_AT); + memcached_mark_server_for_timeout(server); + } - LIBMEMCACHED_MEMCACHED_CONNECT_END(); + LIBMEMCACHED_MEMCACHED_CONNECT_END(); - if (in_timeout) - { - return memcached_set_error(*server, MEMCACHED_SERVER_TEMPORARILY_DISABLED, MEMCACHED_AT); + if (in_timeout) + { + char buffer[1024]; + int snprintf_length= snprintf(buffer, sizeof(buffer), "%s:%d", server->hostname, int(server->port)); + return memcached_set_error(*server, MEMCACHED_SERVER_TEMPORARILY_DISABLED, MEMCACHED_AT, buffer, snprintf_length); + } } return rc; } + +memcached_return_t memcached_connect_try(memcached_server_write_instance_st server) +{ + return _memcached_connect(server, false); +} + +memcached_return_t memcached_connect(memcached_server_write_instance_st server) +{ + return _memcached_connect(server, true); +} diff --git a/libmemcached/connect.hpp b/libmemcached/connect.hpp index 78ed7960..a37dbd76 100644 --- a/libmemcached/connect.hpp +++ b/libmemcached/connect.hpp @@ -37,4 +37,6 @@ #pragma once -memcached_return_t set_hostinfo(memcached_server_st *server); +memcached_return_t memcached_connect_try(memcached_server_write_instance_st ptr); +memcached_return_t memcached_connect(memcached_server_write_instance_st ptr); + diff --git a/libmemcached/delete.cc b/libmemcached/delete.cc index 121ec91b..1ffdbfac 100644 --- a/libmemcached/delete.cc +++ b/libmemcached/delete.cc @@ -144,8 +144,7 @@ memcached_return_t memcached_delete_by_key(memcached_st *ptr, return rc; } - rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol); - if (memcached_failed(rc)) + if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1))) { return rc; } diff --git a/libmemcached/do.cc b/libmemcached/do.cc index 3c3519c2..ed66028c 100644 --- a/libmemcached/do.cc +++ b/libmemcached/do.cc @@ -50,9 +50,24 @@ memcached_return_t memcached_vdo(memcached_server_write_instance_st instance, msg.msg_iov= (struct iovec*)vector; msg.msg_iovlen= count; - if (::sendmsg(instance->fd, &msg, 0) < 1) + uint32_t retry= 5; + while (--retry) { - return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT); + ssize_t sendmsg_length= ::sendmsg(instance->fd, &msg, 0); + if (sendmsg_length > 0) + { + break; + } + else if (sendmsg_length < 0) + { + if (errno == EMSGSIZE) + { + return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT); + } + + perror(__func__); + return memcached_set_errno(*instance, errno, MEMCACHED_AT); + } } return MEMCACHED_SUCCESS; diff --git a/libmemcached/dump.cc b/libmemcached/dump.cc index 830c3ff4..5ba4ce16 100644 --- a/libmemcached/dump.cc +++ b/libmemcached/dump.cc @@ -44,99 +44,96 @@ #include -static memcached_return_t ascii_dump(memcached_st *ptr, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks) +static memcached_return_t ascii_dump(memcached_st *memc, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks) { - memcached_return_t rc= MEMCACHED_SUCCESS; - - for (uint32_t server_key= 0; server_key < memcached_server_count(ptr); server_key++) + /* MAX_NUMBER_OF_SLAB_CLASSES is defined to 200 in Memcached 1.4.10 */ + for (uint32_t x= 0; x < 200; x++) { - memcached_server_write_instance_st instance; - instance= memcached_server_instance_fetch(ptr, server_key); - - /* 256 I BELIEVE is the upper limit of slabs */ - for (uint32_t x= 0; x < 256; x++) + char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; + int buffer_length= snprintf(buffer, sizeof(buffer), "%u", x); + if (size_t(buffer_length) >= sizeof(buffer) or buffer_length < 0) { - char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; - int buffer_length= snprintf(buffer, sizeof(buffer), "%u", x); - if (buffer_length >= MEMCACHED_DEFAULT_COMMAND_SIZE or buffer_length < 0) - { - return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, - memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)")); - } + return memcached_set_error(*memc, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, + memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)")); + } - libmemcached_io_vector_st vector[]= - { - { memcached_literal_param("stats cachedump ") }, - { buffer, buffer_length }, - { memcached_literal_param(" 0 0\r\n") } - }; + // @NOTE the hard coded zero means "no limit" + libmemcached_io_vector_st vector[]= + { + { memcached_literal_param("stats cachedump ") }, + { buffer, buffer_length }, + { memcached_literal_param(" 0\r\n") } + }; - rc= memcached_vdo(instance, vector, 3, true); + // Send message to all servers + for (uint32_t server_key= 0; server_key < memcached_server_count(memc); server_key++) + { + memcached_server_write_instance_st instance= memcached_server_instance_fetch(memc, server_key); - if (rc != MEMCACHED_SUCCESS) + memcached_return_t vdo_rc; + if (memcached_success((vdo_rc= memcached_vdo(instance, vector, 3, true)))) { - goto error; + // We have sent the message to the server successfully } - - while (1) + else { - uint32_t callback_counter; - rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); + return memcached_set_error(*instance, vdo_rc, MEMCACHED_AT); + } + } - if (rc == MEMCACHED_ITEM) - { - char *string_ptr, *end_ptr; + // Collect the returned items + memcached_server_write_instance_st instance; + while ((instance= memcached_io_get_readable_server(memc))) + { + memcached_return_t response_rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); + if (response_rc == MEMCACHED_ITEM) + { + char *string_ptr, *end_ptr; - string_ptr= buffer; - string_ptr+= 5; /* Move past ITEM */ + string_ptr= buffer; + string_ptr+= 5; /* Move past ITEM */ - for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++) {} ; + for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++) {} ; - char *key= string_ptr; - key[(size_t)(end_ptr-string_ptr)]= 0; + char *key= string_ptr; + key[(size_t)(end_ptr-string_ptr)]= 0; - for (callback_counter= 0; callback_counter < number_of_callbacks; callback_counter++) + for (uint32_t callback_counter= 0; callback_counter < number_of_callbacks; callback_counter++) + { + memcached_return_t callback_rc= (*callback[callback_counter])(memc, key, (size_t)(end_ptr-string_ptr), context); + if (callback_rc != MEMCACHED_SUCCESS) { - rc= (*callback[callback_counter])(ptr, key, (size_t)(end_ptr-string_ptr), context); - if (rc != MEMCACHED_SUCCESS) - { - break; - } + // @todo build up a message for the error from the value + memcached_set_error(*instance, callback_rc, MEMCACHED_AT); + break; } } - else if (rc == MEMCACHED_END) - { - break; - } - else if (rc == MEMCACHED_SERVER_ERROR or rc == MEMCACHED_CLIENT_ERROR) - { - /* If we try to request stats cachedump for a slab class that is too big - * the server will return an incorrect error message: - * "MEMCACHED_SERVER_ERROR failed to allocate memory" - * This isn't really a fatal error, so let's just skip it. I want to - * fix the return value from the memcached server to a CLIENT_ERROR, - * so let's add support for that as well right now. - */ - rc= MEMCACHED_END; - break; - } - else - { - goto error; - } + } + else if (response_rc == MEMCACHED_END) + { + // All items have been returned + } + else if (response_rc == MEMCACHED_SERVER_ERROR or response_rc == MEMCACHED_CLIENT_ERROR or response_rc == MEMCACHED_ERROR) + { + /* If we try to request stats cachedump for a slab class that is too big + * the server will return an incorrect error message: + * "MEMCACHED_SERVER_ERROR failed to allocate memory" + * This isn't really a fatal error, so let's just skip it. I want to + * fix the return value from the memcached server to a CLIENT_ERROR, + * so let's add support for that as well right now. + */ + assert(response_rc == MEMCACHED_SUCCESS); // Just fail + return response_rc; + } + else + { + // IO error of some sort must have occurred + return memcached_set_error(*instance, response_rc, MEMCACHED_AT); } } } -error: - if (rc == MEMCACHED_END) - { - return MEMCACHED_SUCCESS; - } - else - { - return rc; - } + return memcached_has_current_error(*memc) ? MEMCACHED_SOME_ERRORS : MEMCACHED_SUCCESS; } memcached_return_t memcached_dump(memcached_st *ptr, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks) @@ -151,9 +148,9 @@ memcached_return_t memcached_dump(memcached_st *ptr, memcached_dump_fn *callback No support for Binary protocol yet @todo Fix this so that we just flush, switch to ascii, and then go back to binary. */ - if (ptr->flags.binary_protocol) + if (memcached_is_binary(ptr)) { - return MEMCACHED_FAILURE; + return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT, memcached_literal_param("Binary protocol is not supported for memcached_dump()")); } return ascii_dump(ptr, callback, context, number_of_callbacks); diff --git a/libmemcached/error.cc b/libmemcached/error.cc index becffd23..1ca355b8 100644 --- a/libmemcached/error.cc +++ b/libmemcached/error.cc @@ -73,6 +73,10 @@ static void _set(memcached_server_st& server, memcached_st& memc) server.error_messages= error; } +#if 0 +static int error_log_fd= -1; +#endif + static void _set(memcached_st& memc, memcached_string_t *str, memcached_return_t &rc, const char *at, int local_errno= 0) { if (memc.error_messages && memc.error_messages->query_id != memc.query_id) @@ -141,37 +145,56 @@ static void _set(memcached_st& memc, memcached_string_t *str, memcached_return_t if (str and str->size and local_errno) { - error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s(%s), %.*s -> %s", + error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%lu) %s(%s), %.*s -> %s", + long(error->root), memcached_strerror(&memc, rc), errmsg_ptr, memcached_string_printf(*str), at); } else if (local_errno) { - error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s(%s) -> %s", + error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%lu) %s(%s) -> %s", + long(error->root), memcached_strerror(&memc, rc), errmsg_ptr, at); } else if (rc == MEMCACHED_PARSE_ERROR and str and str->size) { - error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%.*s -> %s", + error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%lu) %.*s -> %s", + long(error->root), int(str->size), str->c_str, at); } else if (str and str->size) { - error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s, %.*s -> %s", + error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%lu) %s, %.*s -> %s", + long(error->root), memcached_strerror(&memc, rc), int(str->size), str->c_str, at); } else { - error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s -> %s", + error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%lu) %s -> %s", + long(error->root), memcached_strerror(&memc, rc), at); } error->next= memc.error_messages; memc.error_messages= error; + +#if 0 + if (error_log_fd == -1) + { +// unlink("/tmp/libmemcachd.log"); + if ((error_log_fd= open("/tmp/libmemcachd.log", O_CREAT | O_WRONLY | O_APPEND, 0644)) < 0) + { + perror("open"); + error_log_fd= -1; + } + } + ::write(error_log_fd, error->message, error->size); + ::write(error_log_fd, "\n", 1); +#endif } memcached_return_t memcached_set_error(memcached_st& memc, memcached_return_t rc, const char *at, const char *str, size_t length) @@ -192,7 +215,7 @@ memcached_return_t memcached_set_error(memcached_server_st& self, memcached_retu memcached_return_t memcached_set_error(memcached_st& memc, memcached_return_t rc, const char *at, memcached_string_t& str) { assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client"); - if (memcached_success(rc)) + if (memcached_fatal(rc) == false) { return rc; } @@ -220,7 +243,7 @@ memcached_return_t memcached_set_error(memcached_server_st& self, memcached_retu { assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client"); assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a memcached_server_st"); - if (memcached_success(rc)) + if (memcached_fatal(rc) == false) { return rc; } @@ -258,7 +281,7 @@ memcached_return_t memcached_set_error(memcached_server_st& self, memcached_retu memcached_return_t memcached_set_error(memcached_server_st& self, memcached_return_t rc, const char *at) { assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a memcached_server_st"); - if (memcached_success(rc)) + if (memcached_fatal(rc) == false) { return rc; } @@ -282,7 +305,7 @@ memcached_return_t memcached_set_error(memcached_server_st& self, memcached_retu memcached_return_t memcached_set_error(memcached_st& self, memcached_return_t rc, const char *at) { assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client"); - if (memcached_success(rc)) + if (memcached_fatal(rc) == false) { return rc; } @@ -354,8 +377,10 @@ memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errn memcached_string_t error_host= { hostname_port_message, size }; memcached_return_t rc= MEMCACHED_ERRNO; - if (not self.root) + if (self.root == NULL) + { return rc; + } _set(*self.root, &error_host, rc, at, local_errno); _set(self, (*self.root)); @@ -377,8 +402,10 @@ memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errn memcached_string_t error_host= { hostname_port_message, size }; memcached_return_t rc= MEMCACHED_ERRNO; - if (not self.root) + if (self.root == NULL) + { return rc; + } _set(*self.root, &error_host, rc, at, local_errno); _set(self, (*self.root)); @@ -498,7 +525,9 @@ memcached_return_t memcached_last_error(memcached_st *memc) } if (not memc->error_messages) + { return MEMCACHED_SUCCESS; + } return memc->error_messages->rc; } @@ -526,10 +555,14 @@ const char *memcached_server_error(memcached_server_instance_st server) } if (not server->error_messages) + { return memcached_strerror(server->root, MEMCACHED_SUCCESS); + } if (not server->error_messages->size) + { return memcached_strerror(server->root, server->error_messages->rc); + } return server->error_messages->message; } diff --git a/libmemcached/exist.cc b/libmemcached/exist.cc index d2dc34dd..67c6902e 100644 --- a/libmemcached/exist.cc +++ b/libmemcached/exist.cc @@ -52,26 +52,23 @@ static memcached_return_t ascii_exist(memcached_st *memc, memcached_server_write }; /* Send command header */ - memcached_return_t rc= memcached_vdo(instance, vector, 9, true); - if (rc == MEMCACHED_SUCCESS) + memcached_return_t rc; + if (memcached_fatal(rc= memcached_vdo(instance, vector, 9, true))) { - char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; - rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); - - if (rc == MEMCACHED_NOTSTORED) - { - rc= MEMCACHED_SUCCESS; - } - - if (rc == MEMCACHED_STORED) - { - rc= MEMCACHED_NOTFOUND; - } + return rc; } - if (rc == MEMCACHED_WRITE_FAILURE) + char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; + rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); + + if (rc == MEMCACHED_NOTSTORED) { - memcached_io_reset(instance); + rc= MEMCACHED_SUCCESS; + } + + if (rc == MEMCACHED_STORED) + { + rc= MEMCACHED_NOTFOUND; } return rc; @@ -104,19 +101,22 @@ static memcached_return_t binary_exist(memcached_st *memc, memcached_server_writ /* write the header */ memcached_return_t rc; - if ((rc= memcached_vdo(instance, vector, 4, true)) != MEMCACHED_SUCCESS) + if (memcached_fatal(rc= memcached_vdo(instance, vector, 4, true))) { - memcached_io_reset(instance); - return (rc == MEMCACHED_SUCCESS) ? MEMCACHED_WRITE_FAILURE : rc; + return rc; } rc= memcached_response(instance, NULL, 0, NULL); if (rc == MEMCACHED_SUCCESS) + { rc= MEMCACHED_NOTFOUND; + } if (rc == MEMCACHED_DATA_EXISTS) + { rc= MEMCACHED_SUCCESS; + } return rc; } @@ -138,19 +138,25 @@ memcached_return_t memcached_exist_by_key(memcached_st *memc, if (memcached_is_udp(memc)) { - return MEMCACHED_NOT_SUPPORTED; + return memcached_set_error(*memc, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT); } uint32_t server_key= memcached_generate_hash_with_redistribution(memc, group_key, group_key_length); - memcached_server_write_instance_st instance; - instance= memcached_server_instance_fetch(memc, server_key); + memcached_server_write_instance_st instance= memcached_server_instance_fetch(memc, server_key); - if (memc->flags.binary_protocol) + if (memcached_is_binary(memc)) { - return binary_exist(memc, instance, key, key_length); + rc= binary_exist(memc, instance, key, key_length); } else { - return ascii_exist(memc, instance, key, key_length); + rc= ascii_exist(memc, instance, key, key_length); } + + if (memcached_fatal(rc)) + { + memcached_io_reset(instance); + } + + return rc; } diff --git a/libmemcached/get.cc b/libmemcached/get.cc index b2428386..a6fe4034 100644 --- a/libmemcached/get.cc +++ b/libmemcached/get.cc @@ -111,7 +111,9 @@ char *memcached_get_by_key(memcached_st *ptr, /* This is for historical reasons */ if (*error == MEMCACHED_END) + { *error= MEMCACHED_NOTFOUND; + } if (value == NULL) { @@ -121,14 +123,16 @@ char *memcached_get_by_key(memcached_st *ptr, memcached_return_t rc= ptr->get_key_failure(ptr, key, key_length, &ptr->result); /* On all failure drop to returning NULL */ - if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED) + if (rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED) { if (rc == MEMCACHED_BUFFERED) { uint64_t latch; /* We use latch to track the state of the original socket */ latch= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS); if (latch == 0) + { memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1); + } rc= memcached_set(ptr, key, key_length, (memcached_result_value(&ptr->result)), @@ -227,7 +231,7 @@ static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr, if (memcached_failed(memcached_key_test(*ptr, keys, key_length, number_of_keys))) { - return memcached_set_error(*ptr, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT, memcached_literal_param("A bad key value was provided")); + return memcached_last_error(ptr); } bool is_group_key_set= false; @@ -439,7 +443,8 @@ memcached_return_t memcached_mget_execute_by_key(memcached_st *ptr, if (memcached_is_binary(ptr) == false) { - return MEMCACHED_NOT_SUPPORTED; + return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT, + memcached_literal_param("ASCII protocol is not supported for memcached_mget_execute_by_key()")); } memcached_callback_st *original_callbacks= ptr->callbacks; @@ -498,14 +503,18 @@ static memcached_return_t simple_binary_mget(memcached_st *ptr, protocol_binary_request_getk request= { }; //= {.bytes= {0}}; request.message.header.request.magic= PROTOCOL_BINARY_REQ; if (mget_mode) + { request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETKQ; + } else + { request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETK; + } memcached_return_t vk; vk= memcached_validate_key_length(key_length[x], ptr->flags.binary_protocol); - unlikely (vk != MEMCACHED_SUCCESS) + if (vk != MEMCACHED_SUCCESS) { if (x > 0) { diff --git a/libmemcached/io.cc b/libmemcached/io.cc index ab98e486..8b297a7a 100644 --- a/libmemcached/io.cc +++ b/libmemcached/io.cc @@ -319,7 +319,6 @@ static bool io_flush(memcached_server_write_instance_st ptr, if (sent_length == SOCKET_ERROR) { - memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT); #if 0 // @todo I should look at why we hit this bit of code hard frequently WATCHPOINT_ERRNO(get_socket_errno()); WATCHPOINT_NUMBER(get_socket_errno()); diff --git a/libmemcached/key.cc b/libmemcached/key.cc index e9246881..39c1455b 100644 --- a/libmemcached/key.cc +++ b/libmemcached/key.cc @@ -44,7 +44,7 @@ memcached_return_t memcached_key_test(memcached_st &memc, { if (keys == NULL or key_length == NULL) { - return memcached_set_error(memc, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT); + return memcached_set_error(memc, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT, memcached_literal_param("Key was NULL or length of key was zero.")); } // If we don't need to verify the key, or we are using the binary protoocol, @@ -58,7 +58,7 @@ memcached_return_t memcached_key_test(memcached_st &memc, memcached_return_t rc= memcached_validate_key_length(*(key_length +x), false /* memc.flags.binary_protocol */); if (memcached_failed(rc)) { - return rc; + return memcached_set_error(memc, rc, MEMCACHED_AT, memcached_literal_param("Key provided was too long.")); } } @@ -70,14 +70,14 @@ memcached_return_t memcached_key_test(memcached_st &memc, memcached_return_t rc= memcached_validate_key_length(*(key_length + x), false); if (memcached_failed(rc)) { - return rc; + return memcached_set_error(memc, rc, MEMCACHED_AT, memcached_literal_param("Key provided was too long.")); } for (size_t y= 0; y < *(key_length + x); y++) { if ((isgraph(keys[x][y])) == 0) { - return MEMCACHED_BAD_KEY_PROVIDED; + return memcached_set_error(memc, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT, memcached_literal_param("Key provided had invalid character.")); } } } diff --git a/libmemcached/namespace.cc b/libmemcached/namespace.cc index 5cefae56..8278dd56 100644 --- a/libmemcached/namespace.cc +++ b/libmemcached/namespace.cc @@ -58,7 +58,7 @@ memcached_return_t memcached_set_namespace(memcached_st *self, const char *key, if (memcached_failed(memcached_key_test(*self, (const char **)&key, &key_length, 1))) { self->flags.verify_key= orig; - return memcached_set_error(*self, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT); + return memcached_last_error(self); } self->flags.verify_key= orig; diff --git a/libmemcached/response.cc b/libmemcached/response.cc index e876123d..ac1fb057 100644 --- a/libmemcached/response.cc +++ b/libmemcached/response.cc @@ -242,12 +242,18 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta return MEMCACHED_SERVER_ERROR; } - if (total_read > memcached_literal_param_size("SERVER_ERROR object too large for cache") and + 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; } + if (total_read >= memcached_literal_param_size("SERVER_ERROR out of memory storing object") and + (memcmp(buffer, memcached_literal_param("SERVER_ERROR out of memory storing object")) == 0)) + { + return MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE; + } + // Move past the basic error message and whitespace char *startptr= buffer + memcached_literal_param_size("SERVER_ERROR"); if (startptr[0] == ' ') @@ -313,6 +319,11 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta return MEMCACHED_PROTOCOL_ERROR; } #endif + // ERROR + else if (buffer[1] == 'R' and buffer[2] == 'R' and buffer[3] == 'O' and buffer[4] == 'R') + { + return MEMCACHED_ERROR; + } // EXISTS else if (buffer[1] == 'X' and buffer[2] == 'I' and buffer[3] == 'S' and buffer[4] == 'T' and buffer[5] == 'S') { @@ -705,11 +716,7 @@ static memcached_return_t _read_one_response(memcached_server_write_instance_st assert(rc != MEMCACHED_PROTOCOL_ERROR); } - if (rc == MEMCACHED_UNKNOWN_READ_FAILURE or - rc == MEMCACHED_READ_FAILURE or - rc == MEMCACHED_PROTOCOL_ERROR or - rc == MEMCACHED_CLIENT_ERROR or - rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE) + if (memcached_fatal(rc)) { memcached_io_reset(ptr); } @@ -774,14 +781,22 @@ memcached_return_t memcached_response(memcached_server_write_instance_st ptr, memcached_return_t rc= _read_one_response(ptr, buffer, buffer_length, junked_result_ptr, numeric_value); // @TODO should we return an error on another but a bad read case? - if (rc != MEMCACHED_END and - rc != MEMCACHED_STORED and - rc != MEMCACHED_SUCCESS and - rc != MEMCACHED_STAT and + if ( + rc != MEMCACHED_DATA_EXISTS and rc != MEMCACHED_DELETED and + rc != MEMCACHED_E2BIG and + rc != MEMCACHED_END and + rc != MEMCACHED_ERROR and + rc != MEMCACHED_ITEM and rc != MEMCACHED_NOTFOUND and rc != MEMCACHED_NOTSTORED and - rc != MEMCACHED_DATA_EXISTS) + rc != MEMCACHED_SERVER_ERROR and + rc != MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE and + rc != MEMCACHED_STAT and + rc != MEMCACHED_STORED and + rc != MEMCACHED_SUCCESS and + rc != MEMCACHED_VALUE + ) { memcached_result_free(junked_result_ptr); return rc; diff --git a/libmemcached/server.cc b/libmemcached/server.cc index f08f8bf0..2f415844 100644 --- a/libmemcached/server.cc +++ b/libmemcached/server.cc @@ -139,7 +139,7 @@ memcached_server_st *__server_create_with(memcached_st *memc, if (memc) { - set_hostinfo(self); + memcached_connect_try(self); } return self; @@ -241,18 +241,28 @@ memcached_return_t memcached_server_execute(memcached_st *ptr, memcached_server_execute_fn callback, void *context) { + if (callback == NULL) + { + return MEMCACHED_INVALID_ARGUMENTS; + } + + bool some_errors= false;; for (uint32_t x= 0; x < memcached_server_count(ptr); x++) { memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x); - unsigned int iferror= (*callback)(ptr, instance, context); - - if (iferror) + memcached_return_t rc= (*callback)(ptr, instance, context); + if (rc == MEMCACHED_INVALID_ARGUMENTS) + { + return rc; + } + else if (memcached_fatal(rc)) { - continue; + some_errors= true; } } + (void)some_errors; return MEMCACHED_SUCCESS; } @@ -275,18 +285,12 @@ memcached_server_instance_st memcached_server_by_key(memcached_st *ptr, return NULL; } - if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol))) + if (memcached_failed(rc= (memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))) { *error= rc; return NULL; } - if (memcached_failed((memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))) - { - *error= MEMCACHED_BAD_KEY_PROVIDED; - return NULL; - } - uint32_t server_key= memcached_generate_hash(ptr, key, key_length); return memcached_server_instance_by_position(ptr, server_key); @@ -295,7 +299,7 @@ memcached_server_instance_st memcached_server_by_key(memcached_st *ptr, void memcached_server_error_reset(memcached_server_st *self) { WATCHPOINT_ASSERT(self); - if (not self) + if (self == NULL) { return; } diff --git a/libmemcached/stats.cc b/libmemcached/stats.cc index d5d1c234..49dfab01 100644 --- a/libmemcached/stats.cc +++ b/libmemcached/stats.cc @@ -81,7 +81,7 @@ struct local_context }; -static memcached_return_t set_data(memcached_stat_st *memc_stat, char *key, char *value) +static memcached_return_t set_data(memcached_stat_st *memc_stat, const char *key, const char *value) { if (strlen(key) < 1) @@ -127,7 +127,7 @@ static memcached_return_t set_data(memcached_stat_st *memc_stat, char *key, char else if (not strcmp("rusage_user", key)) { char *walk_ptr; - for (walk_ptr= value; (!ispunct(*walk_ptr)); walk_ptr++) {}; + for (walk_ptr= (char*)value; (!ispunct(*walk_ptr)); walk_ptr++) {}; *walk_ptr= 0; walk_ptr++; memc_stat->rusage_user_seconds= strtoul(value, (char **)NULL, 10); @@ -136,7 +136,7 @@ static memcached_return_t set_data(memcached_stat_st *memc_stat, char *key, char else if (not strcmp("rusage_system", key)) { char *walk_ptr; - for (walk_ptr= value; (!ispunct(*walk_ptr)); walk_ptr++) {}; + for (walk_ptr= (char*)value; (!ispunct(*walk_ptr)); walk_ptr++) {}; *walk_ptr= 0; walk_ptr++; memc_stat->rusage_system_seconds= strtoul(value, (char **)NULL, 10); @@ -402,15 +402,6 @@ static memcached_return_t binary_stats_fetch(memcached_stat_st *memc_stat, return rc; } - if (memc_stat) - { - if ((set_data(memc_stat, buffer, buffer + strlen(buffer) + 1)) == MEMCACHED_UNKNOWN_STAT_KEY) - { - WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY); - WATCHPOINT_ASSERT(0); - } - } - if (check && check->func) { size_t key_length= strlen(buffer); @@ -420,6 +411,15 @@ static memcached_return_t binary_stats_fetch(memcached_stat_st *memc_stat, buffer+key_length+1, strlen(buffer+key_length+1), check->context); } + + if (memc_stat) + { + if ((set_data(memc_stat, buffer, buffer + strlen(buffer) + 1)) == MEMCACHED_UNKNOWN_STAT_KEY) + { + WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY); + WATCHPOINT_ASSERT(0); + } + } } while (1); /* @@ -448,40 +448,50 @@ static memcached_return_t ascii_stats_fetch(memcached_stat_st *memc_stat, if (memcached_success(rc)) { char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; - while ((rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL)) == MEMCACHED_STAT) + while ((rc= memcached_response(instance, buffer, sizeof(buffer), NULL)) == MEMCACHED_STAT) { - char *string_ptr, *end_ptr; - char *key, *value; - - string_ptr= buffer; + char *string_ptr= buffer; string_ptr+= 5; /* Move past STAT */ + + char *end_ptr; for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++) {}; - key= string_ptr; - key[(size_t)(end_ptr-string_ptr)]= 0; + char *key= string_ptr; + key[size_t(end_ptr-string_ptr)]= 0; string_ptr= end_ptr + 1; for (end_ptr= string_ptr; !(isspace(*end_ptr)); end_ptr++) {}; - value= string_ptr; + char *value= string_ptr; value[(size_t)(end_ptr -string_ptr)]= 0; - if (memc_stat) - { - unlikely((set_data(memc_stat, key, value)) == MEMCACHED_UNKNOWN_STAT_KEY) - { - WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY); - WATCHPOINT_ASSERT(0); - } - } +#if 0 + bool check_bool= bool(check); + bool check_func_bool= bool(check) ? bool(check->func) : false; + fprintf(stderr, "%s:%d %s %s %d:%d\n", __FILE__, __LINE__, key, value, check_bool, check_func_bool); +#endif - if (check && check->func) + if (check and check->func) { check->func(instance, key, strlen(key), value, strlen(value), check->context); } + + if (memc_stat) + { + if((set_data(memc_stat, key, value)) == MEMCACHED_UNKNOWN_STAT_KEY) + { + WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY); + WATCHPOINT_ASSERT(0); + } + } } } + if (rc == MEMCACHED_ERROR) + { + return MEMCACHED_INVALID_ARGUMENTS; + } + if (rc == MEMCACHED_END) { return MEMCACHED_SUCCESS; @@ -552,6 +562,13 @@ memcached_stat_st *memcached_stat(memcached_st *self, char *args, memcached_retu temp_return= ascii_stats_fetch(stat_instance, args, args_length, instance, NULL); } + // Special case where "args" is invalid + if (temp_return == MEMCACHED_INVALID_ARGUMENTS) + { + rc= MEMCACHED_INVALID_ARGUMENTS; + break; + } + if (memcached_failed(temp_return)) { rc= MEMCACHED_SOME_ERRORS; @@ -619,8 +636,10 @@ char ** memcached_stat_get_keys(memcached_st *ptr, memcached_stat_st *, memcached_return_t *error) { - if (not ptr) + if (ptr == NULL) + { return NULL; + } char **list= static_cast(libmemcached_malloc(ptr, sizeof(memcached_stat_keys))); if (not list) @@ -658,9 +677,9 @@ static memcached_return_t call_stat_fn(memcached_st *ptr, void *context) { memcached_return_t rc; - struct local_context *check= (struct local_context *)context; + local_context *check= (struct local_context *)context; - if (ptr->flags.binary_protocol) + if (memcached_is_binary(ptr)) { rc= binary_stats_fetch(NULL, check->args, check->args_length, instance, check); } @@ -676,7 +695,7 @@ memcached_return_t memcached_stat_execute(memcached_st *memc, const char *args, { memcached_version(memc); - struct local_context check(func, context, args, args ? strlen(args) : 0); + local_context check(func, context, args, args ? strlen(args) : 0); return memcached_server_execute(memc, call_stat_fn, (void *)&check); } diff --git a/libmemcached/storage.cc b/libmemcached/storage.cc index 2d0ae8fc..e5f67dbc 100644 --- a/libmemcached/storage.cc +++ b/libmemcached/storage.cc @@ -342,16 +342,11 @@ static inline memcached_return_t memcached_send(memcached_st *ptr, return rc; } - if (memcached_failed(rc= memcached_validate_key_length(key_length, memcached_is_binary(ptr)))) + if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1))) { return rc; } - if (memcached_failed(memcached_key_test(*ptr, (const char **)&key, &key_length, 1))) - { - return MEMCACHED_BAD_KEY_PROVIDED; - } - 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); diff --git a/libmemcached/strerror.cc b/libmemcached/strerror.cc index b70a60b9..7cd2ff2f 100644 --- a/libmemcached/strerror.cc +++ b/libmemcached/strerror.cc @@ -74,8 +74,8 @@ const char *memcached_strerror(memcached_st *, memcached_return_t rc) case MEMCACHED_WRITE_FAILURE: return "WRITE FAILURE"; - case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE: // DEPRECATED - return "CONNECTION SOCKET CREATE FAILURE"; + case MEMCACHED_ERROR: + return "ERROR was returned by server"; case MEMCACHED_DATA_EXISTS: return "CONNECTION DATA EXISTS"; diff --git a/libmemcached/string.cc b/libmemcached/string.cc index a94d4421..c7a47827 100644 --- a/libmemcached/string.cc +++ b/libmemcached/string.cc @@ -43,17 +43,19 @@ inline static memcached_return_t _string_check(memcached_string_st *string, size if (need && need > (size_t)(string->current_size - (size_t)(string->end - string->string))) { size_t current_offset= (size_t) (string->end - string->string); - size_t adjust; - size_t new_size; /* This is the block multiplier. To keep it larger and surive division errors we must round it up */ - adjust= (need - (size_t)(string->current_size - (size_t)(string->end - string->string))) / MEMCACHED_BLOCK_SIZE; + size_t adjust= (need - (size_t)(string->current_size - (size_t)(string->end - string->string))) / MEMCACHED_BLOCK_SIZE; adjust++; - new_size= sizeof(char) * (size_t)((adjust * MEMCACHED_BLOCK_SIZE) + string->current_size); + size_t new_size= sizeof(char) * (size_t)((adjust * MEMCACHED_BLOCK_SIZE) + string->current_size); /* Test for overflow */ if (new_size < need) - return memcached_set_error(*string->root, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT); + { + char error_message[1024]; + int error_message_length= snprintf(error_message, sizeof(error_message),"Needed %ld, got %ld", (long)need, (long)new_size); + return memcached_set_error(*string->root, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, error_message, error_message_length); + } char *new_value= libmemcached_xrealloc(string->root, string->string, new_size, char); diff --git a/libmemcached/touch.cc b/libmemcached/touch.cc index 8505d7e6..b7fa2475 100644 --- a/libmemcached/touch.cc +++ b/libmemcached/touch.cc @@ -123,7 +123,7 @@ memcached_return_t memcached_touch_by_key(memcached_st *ptr, if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol))) { - return memcached_set_error(*ptr, rc, MEMCACHED_AT); + return rc; } uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length); diff --git a/m4/ax_compiler_vendor.m4 b/m4/ax_compiler_vendor.m4 new file mode 100644 index 00000000..73e32ea9 --- /dev/null +++ b/m4/ax_compiler_vendor.m4 @@ -0,0 +1,84 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_COMPILER_VENDOR +# +# DESCRIPTION +# +# Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm, sun, +# hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi, microsoft, +# watcom, etc. The vendor is returned in the cache variable +# $ax_cv_c_compiler_vendor for C and $ax_cv_cxx_compiler_vendor for C++. +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson +# Copyright (c) 2008 Matteo Frigo +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 11 + +AC_DEFUN([AX_COMPILER_VENDOR], +[AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, + [# note: don't check for gcc first since some other compilers define __GNUC__ + vendors="intel: __ICC,__ECC,__INTEL_COMPILER + ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__ + pathscale: __PATHCC__,__PATHSCALE__ + clang: __clang__ + gnu: __GNUC__ + sun: __SUNPRO_C,__SUNPRO_CC + hp: __HP_cc,__HP_aCC + dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER + borland: __BORLANDC__,__TURBOC__ + comeau: __COMO__ + cray: _CRAYC + kai: __KCC + lcc: __LCC__ + sgi: __sgi,sgi + microsoft: _MSC_VER + metrowerks: __MWERKS__ + watcom: __WATCOMC__ + portland: __PGI + unknown: UNKNOWN" + for ventest in $vendors; do + case $ventest in + *:) vendor=$ventest; continue ;; + *) vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" ;; + esac + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ + #if !($vencpp) + thisisanerror; + #endif + ])], [break]) + done + ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1` + ]) +]) diff --git a/m4/ax_tls.m4 b/m4/ax_tls.m4 new file mode 100644 index 00000000..033e3b13 --- /dev/null +++ b/m4/ax_tls.m4 @@ -0,0 +1,76 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_tls.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_TLS([action-if-found], [action-if-not-found]) +# +# DESCRIPTION +# +# Provides a test for the compiler support of thread local storage (TLS) +# extensions. Defines TLS if it is found. Currently knows about GCC/ICC +# and MSVC. I think SunPro uses the same as GCC, and Borland apparently +# supports either. +# +# LICENSE +# +# Copyright (c) 2008 Alan Woodland +# Copyright (c) 2010 Diego Elio Petteno` +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 10 + +AC_DEFUN([AX_TLS], [ + AC_MSG_CHECKING(for thread local storage (TLS) class) + AC_CACHE_VAL(ac_cv_tls, [ + ax_tls_keywords="__thread __declspec(thread) none" + for ax_tls_keyword in $ax_tls_keywords; do + AS_CASE([$ax_tls_keyword], + [none], [ac_cv_tls=none ; break], + [AC_TRY_COMPILE( + [#include + static void + foo(void) { + static ] $ax_tls_keyword [ int bar; + exit(1); + }], + [], + [ac_cv_tls=$ax_tls_keyword ; break], + ac_cv_tls=none + )]) + done + ]) + AC_MSG_RESULT($ac_cv_tls) + + AS_IF([test "$ac_cv_tls" != "none"], + AC_DEFINE_UNQUOTED([TLS], $ac_cv_tls, [If the compiler supports a TLS storage class define it to that here]) + m4_ifnblank([$1], [$1]), + m4_ifnblank([$2], [$2]) + ) +]) diff --git a/support/libmemcached.spec.in b/support/libmemcached.spec.in index e610adaa..afca3049 100644 --- a/support/libmemcached.spec.in +++ b/support/libmemcached.spec.in @@ -47,7 +47,7 @@ you will need to install %{name}-devel. %setup -q %{__mkdir} examples -%{__cp} tests/*.{cc,cpp,h} examples/ +#%{__cp} tests/*.{cc,h} examples/ %build @@ -89,11 +89,11 @@ you will need to install %{name}-devel. %exclude %{_libdir}/libmemcachedutil.a %exclude %{_libdir}/libmemcachedprotocol.a %{_libdir}/libhashkit.so.1.0.0 -%{_libdir}/libmemcached.so.8.0.0 +%{_libdir}/libmemcached.so.9.0.0 %{_libdir}/libmemcachedutil.so.2.0.0 %{_libdir}/libmemcachedprotocol.so.0.0.0 %{_libdir}/libhashkit.so.1 -%{_libdir}/libmemcached.so.8 +%{_libdir}/libmemcached.so.9 %{_libdir}/libmemcachedprotocol.so.0 %{_libdir}/libmemcachedutil.so.2 %{_mandir}/man1/memcapable.1.gz @@ -142,25 +142,28 @@ you will need to install %{name}-devel. %{_includedir}/libmemcached/memcached.hpp %{_includedir}/libmemcached/util.h +%{_includedir}/libmemcached-1.0/alloc.h %{_includedir}/libmemcached-1.0/allocators.h %{_includedir}/libmemcached-1.0/analyze.h %{_includedir}/libmemcached-1.0/auto.h %{_includedir}/libmemcached-1.0/basic_string.h %{_includedir}/libmemcached-1.0/behavior.h %{_includedir}/libmemcached-1.0/callback.h +%{_includedir}/libmemcached-1.0/callbacks.h %{_includedir}/libmemcached-1.0/configure.h -%{_includedir}/libmemcached-1.0/constants.h +%{_includedir}/libmemcached-1.0/defaults.h %{_includedir}/libmemcached-1.0/delete.h +%{_includedir}/libmemcached-1.0/deprecated_types.h %{_includedir}/libmemcached-1.0/dump.h %{_includedir}/libmemcached-1.0/error.h -%{_includedir}/libmemcached-1.0/exist.h -%{_includedir}/libmemcached-1.0/touch.h %{_includedir}/libmemcached-1.0/exception.hpp +%{_includedir}/libmemcached-1.0/exist.h %{_includedir}/libmemcached-1.0/fetch.h %{_includedir}/libmemcached-1.0/flush.h %{_includedir}/libmemcached-1.0/flush_buffers.h %{_includedir}/libmemcached-1.0/get.h %{_includedir}/libmemcached-1.0/hash.h +%{_includedir}/libmemcached-1.0/limits.h %{_includedir}/libmemcached-1.0/memcached.h %{_includedir}/libmemcached-1.0/memcached.hpp %{_includedir}/libmemcached-1.0/options.h @@ -175,8 +178,24 @@ you will need to install %{name}-devel. %{_includedir}/libmemcached-1.0/stats.h %{_includedir}/libmemcached-1.0/storage.h %{_includedir}/libmemcached-1.0/strerror.h -%{_includedir}/libmemcached-1.0/string.h +%{_includedir}/libmemcached-1.0/struct/allocator.h +%{_includedir}/libmemcached-1.0/struct/analysis.h +%{_includedir}/libmemcached-1.0/struct/callback.h +%{_includedir}/libmemcached-1.0/struct/memcached.h +%{_includedir}/libmemcached-1.0/struct/result.h +%{_includedir}/libmemcached-1.0/struct/sasl.h +%{_includedir}/libmemcached-1.0/struct/server.h +%{_includedir}/libmemcached-1.0/struct/stat.h +%{_includedir}/libmemcached-1.0/struct/string.h +%{_includedir}/libmemcached-1.0/touch.h +%{_includedir}/libmemcached-1.0/triggers.h %{_includedir}/libmemcached-1.0/types.h +%{_includedir}/libmemcached-1.0/types/behavior.h +%{_includedir}/libmemcached-1.0/types/callback.h +%{_includedir}/libmemcached-1.0/types/connection.h +%{_includedir}/libmemcached-1.0/types/hash.h +%{_includedir}/libmemcached-1.0/types/return.h +%{_includedir}/libmemcached-1.0/types/server_distribution.h %{_includedir}/libmemcached-1.0/verbosity.h %{_includedir}/libmemcached-1.0/version.h %{_includedir}/libmemcached-1.0/visibility.h diff --git a/tests/libmemcached-1.0/dump.cc b/tests/libmemcached-1.0/dump.cc new file mode 100644 index 00000000..89f792a5 --- /dev/null +++ b/tests/libmemcached-1.0/dump.cc @@ -0,0 +1,147 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached library + * + * Copyright (C) 2012 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. + * + */ + +#include + +#include +#include + +#include + +#include +#include + +using namespace libtest; + +#include "tests/libmemcached-1.0/dump.h" + +static memcached_return_t callback_dump_counter(const memcached_st *, + const char*, // key, + size_t, // length, + void *context) +{ + size_t *counter= (size_t *)context; + +#if 0 + std::cerr.write(key, length); + std::cerr << std::endl; +#endif + + *counter= *counter +1; + + return MEMCACHED_SUCCESS; +} + +static memcached_return_t item_counter(memcached_server_instance_st , + const char *key, size_t key_length, + const char *value, size_t, // value_length, + void *context) +{ + if ((key_length == (sizeof("curr_items") -1)) and (strncmp("curr_items", key, (sizeof("curr_items") -1)) == 0)) + { + uint64_t* counter= (uint64_t*)context; + unsigned long number_value= strtoul(value, (char **)NULL, 10); + if (number_value == ULONG_MAX) + { + return MEMCACHED_FAILURE; + } + *counter= *counter +number_value; + } + + return MEMCACHED_SUCCESS; +} + +#if 0 +test_return_t memcached_dump_TEST(memcached_st *memc) +{ + test_skip(false, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)); + + size_t count= 0; + memcached_dump_fn callbacks[1]; + callbacks[0]= &callback_dump_counter; + + uint64_t counter= 0; + test_compare_got(MEMCACHED_SUCCESS, + memcached_stat_execute(memc, NULL, item_counter, &counter), + memcached_last_error_message(memc)); + test_zero(counter); + + test_compare_got(MEMCACHED_SUCCESS, memcached_dump(memc, callbacks, &count, 1), memcached_last_error_message(memc)); + + return TEST_SUCCESS; +} +#endif + +#define memcached_dump_TEST2_COUNT 64 +test_return_t memcached_dump_TEST2(memcached_st *memc) +{ + test_skip(false, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)); + + /* The dump test relies on there being at least 32 items in memcached */ + for (uint32_t x= 0; x < memcached_dump_TEST2_COUNT; x++) + { + char key[1024]; + + int length= snprintf(key, sizeof(key), "%s%u", __func__, x); + + test_true(length > 0); + + test_compare_hint(MEMCACHED_SUCCESS, + memcached_set(memc, key, length, + NULL, 0, // Zero length values + time_t(0), uint32_t(0)), + memcached_last_error_message(memc)); + } + memcached_quit(memc); + + uint64_t counter= 0; + test_compare_got(MEMCACHED_SUCCESS, + memcached_stat_execute(memc, NULL, item_counter, &counter), + memcached_last_error_message(memc)); + test_true_got(counter > 0, counter); + + size_t count= 0; + memcached_dump_fn callbacks[1]; + callbacks[0]= &callback_dump_counter; + + test_compare_got(MEMCACHED_SUCCESS, + memcached_dump(memc, callbacks, &count, 1), + memcached_last_error_message(memc)); + + test_true(count); + + return TEST_SUCCESS; +} diff --git a/tests/libmemcached-1.0/dump.h b/tests/libmemcached-1.0/dump.h new file mode 100644 index 00000000..2a6b69d6 --- /dev/null +++ b/tests/libmemcached-1.0/dump.h @@ -0,0 +1,40 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached library + * + * Copyright (C) 2012 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 + +test_return_t memcached_dump_TEST(memcached_st *); +test_return_t memcached_dump_TEST2(memcached_st *); diff --git a/tests/libmemcached-1.0/exist.cc b/tests/libmemcached-1.0/exist.cc index 7d1178ff..5815d6cb 100644 --- a/tests/libmemcached-1.0/exist.cc +++ b/tests/libmemcached-1.0/exist.cc @@ -49,10 +49,10 @@ test_return_t memcached_exist_NOTFOUND(memcached_st *memc) test_return_t memcached_exist_SUCCESS(memcached_st *memc) { - test_compare(MEMCACHED_SUCCESS, memcached_set(memc, test_literal_param("frog"), 0, 0, 0, 0)); - test_compare(MEMCACHED_SUCCESS, memcached_exist(memc, test_literal_param("frog"))); - test_compare(MEMCACHED_SUCCESS, memcached_delete(memc, test_literal_param("frog"), 0)); - test_compare(MEMCACHED_NOTFOUND, memcached_exist(memc, test_literal_param("frog"))); + test_compare_got(MEMCACHED_SUCCESS, memcached_set(memc, test_literal_param("frog"), 0, 0, 0, 0), memcached_last_error_message(memc)); + test_compare_got(MEMCACHED_SUCCESS, memcached_exist(memc, test_literal_param("frog")), memcached_last_error_message(memc)); + test_compare_got(MEMCACHED_SUCCESS, memcached_delete(memc, test_literal_param("frog"), 0), memcached_last_error_message(memc)); + test_compare_got(MEMCACHED_NOTFOUND, memcached_exist(memc, test_literal_param("frog")), memcached_last_error_message(memc)); return TEST_SUCCESS; } @@ -65,10 +65,10 @@ test_return_t memcached_exist_by_key_NOTFOUND(memcached_st *memc) test_return_t memcached_exist_by_key_SUCCESS(memcached_st *memc) { - test_compare(MEMCACHED_SUCCESS, memcached_set_by_key(memc, test_literal_param("master"), test_literal_param("frog"), 0, 0, 0, 0)); - test_compare(MEMCACHED_SUCCESS, memcached_exist_by_key(memc, test_literal_param("master"), test_literal_param("frog"))); - test_compare(MEMCACHED_SUCCESS, memcached_delete_by_key(memc, test_literal_param("master"), test_literal_param("frog"), 0)); - test_compare(MEMCACHED_NOTFOUND, memcached_exist_by_key(memc, test_literal_param("master"), test_literal_param("frog"))); + test_compare_got(MEMCACHED_SUCCESS, memcached_set_by_key(memc, test_literal_param("master"), test_literal_param("frog"), 0, 0, 0, 0), memcached_last_error_message(memc)); + test_compare_got(MEMCACHED_SUCCESS, memcached_exist_by_key(memc, test_literal_param("master"), test_literal_param("frog")), memcached_last_error_message(memc)); + test_compare_got(MEMCACHED_SUCCESS, memcached_delete_by_key(memc, test_literal_param("master"), test_literal_param("frog"), 0), memcached_last_error_message(memc)); + test_compare_got(MEMCACHED_NOTFOUND, memcached_exist_by_key(memc, test_literal_param("master"), test_literal_param("frog")), memcached_last_error_message(memc)); return TEST_SUCCESS; } diff --git a/tests/libmemcached-1.0/include.am b/tests/libmemcached-1.0/include.am index 81653a1c..373fc6e7 100644 --- a/tests/libmemcached-1.0/include.am +++ b/tests/libmemcached-1.0/include.am @@ -12,20 +12,22 @@ noinst_HEADERS+= \ tests/basic.h \ tests/callbacks.h \ tests/debug.h \ + tests/deprecated.h \ tests/error_conditions.h \ tests/exist.h \ tests/ketama.h \ tests/ketama_test_cases.h \ tests/ketama_test_cases_spy.h \ + tests/libmemcached-1.0/dump.h \ + tests/libmemcached-1.0/stat.h \ tests/namespace.h \ tests/parser.h \ - tests/touch.h \ - tests/deprecated.h \ tests/pool.h \ tests/print.h \ tests/replication.h \ tests/server_add.h \ tests/string.h \ + tests/touch.h \ tests/virtual_buckets.h # Test internals @@ -44,20 +46,22 @@ noinst_PROGRAMS+= tests/libmemcached-1.0/internals tests_libmemcached_1_0_testapp_CXXFLAGS = $(AM_CXXFLAGS) ${PTHREAD_CFLAGS} tests_libmemcached_1_0_testapp_CFLAGS= $(AM_CFLAGS) $(NO_CONVERSION) $(NO_STRICT_ALIASING) tests_libmemcached_1_0_testapp_SOURCES= \ + tests/libmemcached-1.0/pool.cc \ + tests/libmemcached-1.0/print.cc \ + tests/libmemcached-1.0/replication.cc \ tests/libmemcached-1.0/basic.cc \ tests/libmemcached-1.0/callbacks.cc \ tests/libmemcached-1.0/debug.cc \ tests/libmemcached-1.0/deprecated.cc \ + tests/libmemcached-1.0/dump.cc \ tests/libmemcached-1.0/error_conditions.cc \ tests/libmemcached-1.0/exist.cc \ tests/libmemcached-1.0/ketama.cc \ tests/libmemcached-1.0/mem_functions.cc \ tests/libmemcached-1.0/namespace.cc \ - tests/libmemcached-1.0/pool.cc \ - tests/libmemcached-1.0/print.cc \ - tests/libmemcached-1.0/replication.cc \ tests/libmemcached-1.0/parser.cc \ tests/libmemcached-1.0/server_add.cc \ + tests/libmemcached-1.0/stat.cc \ tests/libmemcached-1.0/touch.cc \ tests/libmemcached-1.0/virtual_buckets.cc diff --git a/tests/libmemcached-1.0/mem_functions.cc b/tests/libmemcached-1.0/mem_functions.cc index 62b32473..0256588d 100644 --- a/tests/libmemcached-1.0/mem_functions.cc +++ b/tests/libmemcached-1.0/mem_functions.cc @@ -78,6 +78,8 @@ #include "tests/ketama.h" #include "tests/namespace.h" #include "tests/parser.h" +#include "tests/libmemcached-1.0/dump.h" +#include "tests/libmemcached-1.0/stat.h" #include "tests/touch.h" #include "tests/callbacks.h" #include "tests/pool.h" @@ -485,7 +487,7 @@ static test_return_t memcached_return_t_TEST(memcached_st *memc) { uint32_t values[] = { 851992627U, 2337886783U, 4109241422U, 4001849190U, 982370485U, 1263635348U, 4242906218U, 3829656100U, - 1891735253U, 334139633U, 2257084983U, 3088286104U, + 1891735253U, 334139633U, 2257084983U, 3351789013U, 13199785U, 2542027183U, 1097051614U, 199566778U, 2748246961U, 2465192557U, 1664094137U, 2405439045U, 1842224848U, 692413798U, 3479807801U, 919913813U, @@ -880,7 +882,7 @@ static test_return_t bad_key_test(memcached_st *memc) test_compare(query_id, memcached_query_id(memc_clone)); // We should not increase the query_id for memcached_behavior_set() /* All keys are valid in the binary protocol (except for length) */ - if (not memcached_behavior_get(memc_clone, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) + if (memcached_behavior_get(memc_clone, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) == false) { uint64_t before_query_id= memcached_query_id(memc_clone); { @@ -1536,11 +1538,9 @@ static test_return_t decrement_with_initial_by_key_test(memcached_st *memc) return TEST_SUCCESS; } -static test_return_t binary_increment_with_prefix_test(memcached_st *orig_memc) +static test_return_t binary_increment_with_prefix_test(memcached_st *memc) { - memcached_st *memc= memcached_clone(NULL, orig_memc); - - test_skip(TEST_SUCCESS, pre_binary(memc)); + test_skip(true, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)); test_compare(MEMCACHED_SUCCESS, memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, (void *)"namespace:")); @@ -1560,7 +1560,6 @@ static test_return_t binary_increment_with_prefix_test(memcached_st *orig_memc) test_literal_param("number"), 1, &new_number)); test_compare(uint64_t(2), new_number); - memcached_free(memc); return TEST_SUCCESS; } @@ -3967,7 +3966,7 @@ static test_return_t noreply_test(memcached_st *memc) { for (size_t x= 0; x < 100; ++x) { - char key[10]; + char key[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1]; int check_length= (size_t)snprintf(key, sizeof(key), "%lu", (unsigned long)x); test_false((size_t)check_length >= sizeof(key) || check_length < 0); @@ -4091,8 +4090,8 @@ static test_return_t noreply_test(memcached_st *memc) static test_return_t analyzer_test(memcached_st *memc) { - memcached_return_t rc; memcached_analysis_st *report; + memcached_return_t rc; memcached_stat_st *memc_stat= memcached_stat(memc, NULL, &rc); test_compare(MEMCACHED_SUCCESS, rc); @@ -4108,24 +4107,6 @@ static test_return_t analyzer_test(memcached_st *memc) return TEST_SUCCESS; } -/* Count the objects */ - -static test_return_t dump_test(memcached_st *memc) -{ - /* No support for Binary protocol yet */ - test_skip(false, memc->flags.binary_protocol); - - test_compare(TEST_SUCCESS, set_test3(memc)); - - // confirm_key_count() call dump - size_t counter= confirm_key_count(memc); - - /* We may have more then 32 if our previous flush has not completed */ - test_true(counter >= 32); - - return TEST_SUCCESS; -} - static test_return_t util_version_test(memcached_st *memc) { test_compare_hint(MEMCACHED_SUCCESS, memcached_version(memc), memcached_last_error_message(memc)); @@ -4681,6 +4662,8 @@ static test_return_t regression_bug_434843(memcached_st *original_memc) test_compare(MEMCACHED_SUCCESS, memcached_mget(memc, (const char**)keys, key_length, max_keys)); + // One the first run we should get a NOT_FOUND, but on the second some data + // should be returned. test_compare(y ? MEMCACHED_SUCCESS : MEMCACHED_NOTFOUND, memcached_fetch_execute(memc, callbacks, (void *)&counter, 1)); @@ -4791,8 +4774,7 @@ static test_return_t regression_bug_442914(memcached_st *memc) test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); } - (void)snprintf(k, sizeof(k), "%037u", 251U); - len= strlen(k); + len= snprintf(k, sizeof(k), "%037u", 251U); memcached_return_t rc= memcached_delete(memc, k, len, 0); test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); @@ -4929,6 +4911,10 @@ static test_return_t regression_bug_447342(memcached_st *memc) static test_return_t regression_bug_463297(memcached_st *memc) { + test_compare(MEMCACHED_INVALID_ARGUMENTS, memcached_delete(memc, "foo", 3, 1)); + + // Since we blocked timed delete, this test is no longer valid. +#if 0 memcached_st *memc_clone= memcached_clone(NULL, memc); test_true(memc_clone); test_true(memcached_version(memc_clone) == MEMCACHED_SUCCESS); @@ -4984,6 +4970,8 @@ static test_return_t regression_bug_463297(memcached_st *memc) } memcached_free(memc_clone); +#endif + return TEST_SUCCESS; } @@ -5451,7 +5439,7 @@ static test_return_t regression_bug_490520(memcached_st *memc) test_true(keys[x]); memcached_return rc= memcached_set(memc, keys[x], key_length[x], blob, sizeof(blob), 0, 0); - test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED); + test_true_got(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED, memcached_last_error_message(memc)); } for (uint32_t x= 0; x < regression_bug_490520_COUNT; ++x) @@ -5608,10 +5596,9 @@ test_st tests[] ={ {"connection_test", false, (test_callback_fn*)connection_test}, {"callback_test", false, (test_callback_fn*)callback_test}, {"userdata_test", false, (test_callback_fn*)userdata_test}, - {"set", false, (test_callback_fn*)set_test }, - {"set2", false, (test_callback_fn*)set_test2 }, - {"set3", false, (test_callback_fn*)set_test3 }, - {"dump", true, (test_callback_fn*)dump_test}, + {"memcached_set()", false, (test_callback_fn*)set_test }, + {"memcached_set() 2", false, (test_callback_fn*)set_test2 }, + {"memcached_set() 3", false, (test_callback_fn*)set_test3 }, {"add", true, (test_callback_fn*)add_test }, {"memcached_fetch_result(MEMCACHED_NOTFOUND)", true, (test_callback_fn*)memcached_fetch_result_NOT_FOUND }, {"replace", true, (test_callback_fn*)replace_test }, @@ -5664,6 +5651,10 @@ test_st tests[] ={ {"memcached_exist_by_key(MEMCACHED_SUCCESS)", true, (test_callback_fn*)memcached_exist_by_key_SUCCESS }, {"memcached_touch", 0, (test_callback_fn*)test_memcached_touch}, {"memcached_touch_with_prefix", 0, (test_callback_fn*)test_memcached_touch_by_key}, +#if 0 + {"memcached_dump() no data", true, (test_callback_fn*)memcached_dump_TEST }, +#endif + {"memcached_dump() with data", true, (test_callback_fn*)memcached_dump_TEST2 }, {0, 0, 0} }; @@ -5673,6 +5664,12 @@ test_st touch_tests[] ={ {0, 0, 0} }; +test_st memcached_stat_tests[] ={ + {"memcached_stat() INVALID ARG", 0, (test_callback_fn*)memcached_stat_TEST}, + {"memcached_stat()", 0, (test_callback_fn*)memcached_stat_TEST2}, + {0, 0, 0} +}; + test_st behavior_tests[] ={ {"libmemcached_string_behavior()", false, (test_callback_fn*)libmemcached_string_behavior_test}, {"libmemcached_string_distribution()", false, (test_callback_fn*)libmemcached_string_distribution_test}, @@ -6009,6 +6006,8 @@ collection_st collection[] ={ {"virtual buckets", 0, 0, virtual_bucket_tests}, {"memcached_server_get_last_disconnect", 0, 0, memcached_server_get_last_disconnect_tests}, {"touch", 0, 0, touch_tests}, + {"touch", (test_callback_fn*)pre_binary, 0, touch_tests}, + {"memcached_stat()", 0, 0, memcached_stat_tests}, {0, 0, 0, 0} }; diff --git a/tests/libmemcached-1.0/stat.cc b/tests/libmemcached-1.0/stat.cc new file mode 100644 index 00000000..209b70a6 --- /dev/null +++ b/tests/libmemcached-1.0/stat.cc @@ -0,0 +1,109 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached library + * + * Copyright (C) 2012 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. + * + */ + +#include + +#include +#include + +#include + +#include +#include + +using namespace libtest; + +#include "tests/libmemcached-1.0/stat.h" + +static memcached_return_t item_counter(memcached_server_instance_st , + const char *key, size_t key_length, + const char *value, size_t, // value_length, + void *context) +{ + if ((key_length == (sizeof("curr_items") -1)) and (strncmp("curr_items", key, (sizeof("curr_items") -1)) == 0)) + { + uint64_t* counter= (uint64_t*)context; + unsigned long number_value= strtoul(value, (char **)NULL, 10); + if (number_value == ULONG_MAX) + { + return MEMCACHED_FAILURE; + } + *counter= *counter +number_value; + } + + return MEMCACHED_SUCCESS; +} + +test_return_t memcached_stat_TEST(memcached_st *memc) +{ + uint64_t counter= 0; + test_compare_got(MEMCACHED_INVALID_ARGUMENTS, + memcached_stat_execute(memc, "BAD_ARG_VALUE", item_counter, &counter), + memcached_last_error_message(memc)); + + return TEST_SUCCESS; +} + +#define memcached_dump_TEST2_COUNT 64 +test_return_t memcached_stat_TEST2(memcached_st *memc) +{ + test_skip(false, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)); + + /* The dump test relies on there being at least 32 items in memcached */ + for (uint32_t x= 0; x < memcached_dump_TEST2_COUNT; x++) + { + char key[1024]; + + int length= snprintf(key, sizeof(key), "%s%u", __func__, x); + + test_true(length > 0); + + test_compare_hint(MEMCACHED_SUCCESS, + memcached_set(memc, key, length, + NULL, 0, // Zero length values + time_t(0), uint32_t(0)), + memcached_last_error_message(memc)); + } + memcached_quit(memc); + + uint64_t counter= 0; + test_compare_got(MEMCACHED_SUCCESS, + memcached_stat_execute(memc, NULL, item_counter, &counter), + memcached_last_error_message(memc)); + test_true_got(counter > 0, counter); + + return TEST_SUCCESS; +} diff --git a/tests/libmemcached-1.0/stat.h b/tests/libmemcached-1.0/stat.h new file mode 100644 index 00000000..3b85ba9c --- /dev/null +++ b/tests/libmemcached-1.0/stat.h @@ -0,0 +1,40 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached library + * + * Copyright (C) 2012 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 + +test_return_t memcached_stat_TEST(memcached_st *); +test_return_t memcached_stat_TEST2(memcached_st *); diff --git a/tests/libmemcached-1.0/touch.cc b/tests/libmemcached-1.0/touch.cc index 50e6a359..425e308c 100644 --- a/tests/libmemcached-1.0/touch.cc +++ b/tests/libmemcached-1.0/touch.cc @@ -63,20 +63,20 @@ test_return_t test_memcached_touch(memcached_st *memc) memcached_return rc; test_null(memcached_get(memc, - test_literal_param("touchkey"), + test_literal_param(__func__), &len, &flags, &rc)); test_zero(len); test_compare(MEMCACHED_NOTFOUND, rc); test_compare(MEMCACHED_SUCCESS, memcached_set(memc, - test_literal_param("touchkey"), + test_literal_param(__func__), test_literal_param("touchval"), 2, 0)); { char *value= memcached_get(memc, - test_literal_param("touchkey"), + test_literal_param(__func__), &len, &flags, &rc); test_compare(8U, test_literal_param_size("touchval")); test_true(value); @@ -86,15 +86,15 @@ test_return_t test_memcached_touch(memcached_st *memc) } test_compare(MEMCACHED_SUCCESS, - memcached_touch(memc, test_literal_param("touchkey"), 60 *60)); + memcached_touch(memc, test_literal_param(__func__), 60 *60)); test_skip(false ,memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)); - rc= memcached_touch(memc, test_literal_param("touchkey"), 60 *60 *24 *60); + rc= memcached_touch(memc, test_literal_param(__func__), 60 *60 *24 *60); test_compare_hint(MEMCACHED_SUCCESS, rc, memcached_last_error_message(memc)); test_compare(MEMCACHED_NOTFOUND, - memcached_exist(memc, test_literal_param("touchkey"))); + memcached_exist(memc, test_literal_param(__func__))); return TEST_SUCCESS; } @@ -110,7 +110,7 @@ test_return_t test_memcached_touch_by_key(memcached_st *memc) test_null(memcached_get_by_key(memc, test_literal_param("grouping_key"), - test_literal_param("touchkey"), + test_literal_param(__func__), &len, &flags, &rc)); test_zero(len); test_compare(MEMCACHED_NOTFOUND, rc); @@ -118,14 +118,14 @@ test_return_t test_memcached_touch_by_key(memcached_st *memc) test_compare(MEMCACHED_SUCCESS, memcached_set_by_key(memc, test_literal_param("grouping_key"), - test_literal_param("touchkey"), + test_literal_param(__func__), test_literal_param("touchval"), 2, 0)); { char *value= memcached_get_by_key(memc, test_literal_param("grouping_key"), - test_literal_param("touchkey"), + test_literal_param(__func__), &len, &flags, &rc); test_compare(8U, test_literal_param_size("touchval")); test_true(value); @@ -137,17 +137,17 @@ test_return_t test_memcached_touch_by_key(memcached_st *memc) test_compare(MEMCACHED_SUCCESS, memcached_touch_by_key(memc, test_literal_param("grouping_key"), - test_literal_param("touchkey"), + test_literal_param(__func__), 60 *60)); test_skip(false ,memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)); test_compare(MEMCACHED_SUCCESS, memcached_touch_by_key(memc, test_literal_param("grouping_key"), - test_literal_param("touchkey"), + test_literal_param(__func__), 60 *60 *24 *60)); test_compare(MEMCACHED_NOTFOUND, - memcached_exist_by_key(memc, test_literal_param("grouping_key"),test_literal_param("touchkey"))); + memcached_exist_by_key(memc, test_literal_param("grouping_key"),test_literal_param(__func__))); return TEST_SUCCESS; }