From: Brian Aker Date: Mon, 23 Jan 2012 07:21:54 +0000 (-0800) Subject: Fix fatal testing. X-Git-Tag: 1.0.4^2~3^2~1 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=387c65c94bec4333da574771fc82a40deabbc3e2;p=awesomized%2Flibmemcached Fix fatal testing. --- diff --git a/libmemcached-1.0/return.h b/libmemcached-1.0/return.h index 28b4a97d..b63953a5 100644 --- a/libmemcached-1.0/return.h +++ b/libmemcached-1.0/return.h @@ -61,12 +61,19 @@ 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_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/auto.cc b/libmemcached/auto.cc index e5054a0a..c64ccda4 100644 --- a/libmemcached/auto.cc +++ b/libmemcached/auto.cc @@ -179,7 +179,7 @@ memcached_return_t memcached_increment_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); @@ -226,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; } @@ -291,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); @@ -356,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 660a903c..1ffdbfac 100644 --- a/libmemcached/delete.cc +++ b/libmemcached/delete.cc @@ -146,7 +146,7 @@ memcached_return_t memcached_delete_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; } if (expiration) 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 b46ca179..899a4c3e 100644 --- a/libmemcached/dump.cc +++ b/libmemcached/dump.cc @@ -44,23 +44,21 @@ #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++) + for (uint32_t server_key= 0; server_key < memcached_server_count(memc); server_key++) { - memcached_server_write_instance_st instance; - instance= memcached_server_instance_fetch(ptr, server_key); + memcached_server_write_instance_st instance= memcached_server_instance_fetch(memc, server_key); + bool exit_slab_loop= false; /* MAX_NUMBER_OF_SLAB_CLASSESdefined to 200 in Memcached 1.4.10 */ - for (uint32_t x= 0; x < 200; x++) + for (uint32_t x= 0; x < 200 and (exit_slab_loop == false); x++) { 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) + if (size_t(buffer_length) >= sizeof(buffer) or buffer_length < 0) { - return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, + return memcached_set_error(*memc, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)")); } @@ -71,72 +69,72 @@ static memcached_return_t ascii_dump(memcached_st *ptr, memcached_dump_fn *callb { memcached_literal_param(" 0 0\r\n") } }; - rc= memcached_vdo(instance, vector, 3, true); - - if (rc != MEMCACHED_SUCCESS) + memcached_return_t vdo_rc; + if (memcached_success((vdo_rc= memcached_vdo(instance, vector, 3, true)))) { - goto error; - } - - while (1) - { - uint32_t callback_counter; - rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); - - if (rc == MEMCACHED_ITEM) + while (1) { - char *string_ptr, *end_ptr; + memcached_return_t response_rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); + fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, memcached_strerror(NULL, response_rc)); + 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++) - { - rc= (*callback[callback_counter])(ptr, key, (size_t)(end_ptr-string_ptr), context); - if (rc != MEMCACHED_SUCCESS) + for (uint32_t callback_counter= 0; callback_counter < number_of_callbacks; callback_counter++) { - break; + memcached_return_t callback_rc= (*callback[callback_counter])(memc, key, (size_t)(end_ptr-string_ptr), context); + if (callback_rc != MEMCACHED_SUCCESS) + { + // @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) + { + // No additional items were found + exit_slab_loop= true; + break; + } + else if (response_rc == MEMCACHED_SERVER_ERROR or response_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. + */ + exit_slab_loop= true; + break; + } + else + { + memcached_set_error(*instance, response_rc, MEMCACHED_AT); + exit_slab_loop= true; + break; + } } } + else + { + exit_slab_loop= true; + memcached_set_error(*instance, vdo_rc, MEMCACHED_AT); + } + fprintf(stderr, "Was able to request %u slab\n", x); } } -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) 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 fa76adae..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; 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..7af52ce4 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] == ' ') @@ -705,11 +711,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 +776,21 @@ 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_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 85ce8381..a86f09ad 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; 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/tests/libmemcached-1.0/dump.cc b/tests/libmemcached-1.0/dump.cc index 44391eff..1421bd47 100644 --- a/tests/libmemcached-1.0/dump.cc +++ b/tests/libmemcached-1.0/dump.cc @@ -45,12 +45,16 @@ using namespace libtest; #include "tests/libmemcached-1.0/dump.h" static memcached_return_t callback_dump_counter(const memcached_st *, - const char *, - size_t , + const char *key, + size_t length, void *context) { size_t *counter= (size_t *)context; + std::cerr.write(key, length); + std::cerr << std::endl; + + *counter= *counter +1; return MEMCACHED_SUCCESS; @@ -64,7 +68,44 @@ test_return_t memcached_dump_TEST(memcached_st *memc) memcached_dump_fn callbacks[1]; callbacks[0]= &callback_dump_counter; - test_compare_hint(MEMCACHED_SUCCESS, memcached_dump(memc, callbacks, &count, 1), memcached_last_error_message(memc)); + test_compare_got(MEMCACHED_SUCCESS, memcached_dump(memc, callbacks, &count, 1), memcached_last_error_message(memc)); + + return TEST_SUCCESS; +} + +#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); + + 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)); + +#if 0 + test_compare(size_t(memcached_dump_TEST2_COUNT), count); +#endif return TEST_SUCCESS; } diff --git a/tests/libmemcached-1.0/dump.h b/tests/libmemcached-1.0/dump.h index 37c4d5a2..2a6b69d6 100644 --- a/tests/libmemcached-1.0/dump.h +++ b/tests/libmemcached-1.0/dump.h @@ -37,3 +37,4 @@ #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/mem_functions.cc b/tests/libmemcached-1.0/mem_functions.cc index 74efe135..4127fa77 100644 --- a/tests/libmemcached-1.0/mem_functions.cc +++ b/tests/libmemcached-1.0/mem_functions.cc @@ -881,7 +881,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); { @@ -4089,8 +4089,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); @@ -4106,24 +4106,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)); @@ -4791,8 +4773,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 +4910,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 +4969,8 @@ static test_return_t regression_bug_463297(memcached_st *memc) } memcached_free(memc_clone); +#endif + return TEST_SUCCESS; } @@ -5451,7 +5438,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 +5595,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,7 +5650,8 @@ 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}, - {"memcached_dump()", 0, (test_callback_fn*)memcached_dump_TEST }, + {"memcached_dump() no data", true, (test_callback_fn*)memcached_dump_TEST }, + {"memcached_dump() with data", true, (test_callback_fn*)memcached_dump_TEST2 }, {0, 0, 0} };