From: Brian Aker Date: Fri, 20 May 2011 01:36:14 +0000 (-0700) Subject: Merge in fetch updates/break out memory/create error bits for host failures. X-Git-Tag: 0.51~10^2~11 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=b16fffff43d822239ce79a366ec36873b0803df9;p=m6w6%2Flibmemcached Merge in fetch updates/break out memory/create error bits for host failures. --- diff --git a/libmemcached/array.c b/libmemcached/array.c index 2412369e..d9074e7f 100644 --- a/libmemcached/array.c +++ b/libmemcached/array.c @@ -35,16 +35,17 @@ * */ -#include "libmemcached/common.h" +#include struct memcached_array_st { - memcached_st *root; + struct memcached_st *root; size_t size; char c_str[]; }; -memcached_array_st *memcached_array_clone(memcached_st *memc, const memcached_array_st *original) + +memcached_array_st *memcached_array_clone(struct memcached_st *memc, const memcached_array_st *original) { if (! original) return NULL; @@ -52,7 +53,7 @@ memcached_array_st *memcached_array_clone(memcached_st *memc, const memcached_ar return memcached_strcpy(memc, original->c_str, original->size); } -memcached_array_st *memcached_strcpy(memcached_st *memc, const char *str, size_t str_length) +memcached_array_st *memcached_strcpy(struct memcached_st *memc, const char *str, size_t str_length) { memcached_array_st *array= (struct memcached_array_st *)libmemcached_malloc(memc, sizeof(struct memcached_array_st) +str_length +1); diff --git a/libmemcached/auto.cc b/libmemcached/auto.cc index 804b8e0c..9da3f138 100644 --- a/libmemcached/auto.cc +++ b/libmemcached/auto.cc @@ -44,7 +44,6 @@ static memcached_return_t text_incr_decr(memcached_st *ptr, uint64_t offset, uint64_t *value) { - memcached_return_t rc; char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; uint32_t server_key; memcached_server_write_instance_st instance; @@ -63,10 +62,10 @@ static memcached_return_t text_incr_decr(memcached_st *ptr, (int)key_length, key, offset, no_reply ? " noreply" : ""); if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0) - return memcached_set_error(ptr, MEMCACHED_WRITE_FAILURE); + return memcached_set_error_string(ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)")); - rc= memcached_do(instance, buffer, (size_t)send_length, true); - if (no_reply || rc != MEMCACHED_SUCCESS) + memcached_return_t rc= memcached_do(instance, buffer, (size_t)send_length, true); + if (no_reply or memcached_failed(rc)) return rc; rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); @@ -78,17 +77,17 @@ static memcached_return_t text_incr_decr(memcached_st *ptr, use it. We still called memcached_response() though since it worked its magic for non-blocking IO. */ - if (! strncmp(buffer, "ERROR\r\n", 7)) + if (not strncmp(buffer, memcached_literal_param("ERROR\r\n"))) { *value= 0; rc= MEMCACHED_PROTOCOL_ERROR; } - else if (! strncmp(buffer, "CLIENT_ERROR\r\n", 14)) + else if (not strncmp(buffer, memcached_literal_param("CLIENT_ERROR\r\n"))) { *value= 0; rc= MEMCACHED_PROTOCOL_ERROR; } - else if (!strncmp(buffer, "NOT_FOUND\r\n", 11)) + else if (not strncmp(buffer, memcached_literal_param("NOT_FOUND\r\n"))) { *value= 0; rc= MEMCACHED_NOTFOUND; @@ -99,7 +98,7 @@ static memcached_return_t text_incr_decr(memcached_st *ptr, rc= MEMCACHED_SUCCESS; } - return rc; + return memcached_set_error(*instance, rc); } static memcached_return_t binary_incr_decr(memcached_st *ptr, uint8_t cmd, diff --git a/libmemcached/basic_string.h b/libmemcached/basic_string.h new file mode 100644 index 00000000..50dbce63 --- /dev/null +++ b/libmemcached/basic_string.h @@ -0,0 +1,53 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached library + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * The names of its contributors may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +struct memcached_string_t { + size_t size; + const char *c_str; +}; + +#define memcached_size(X) (X).size; +#define memcached_c_str(X) (X).c_str; +#define memcached_string_param(X) (X).c_str, (X).size + +#ifdef __cplusplus +#define memcached_string_printf(X) int((X).size), (X).c_str +#else +#define memcached_string_printf(X) (int)((X).size), (X).c_str +#endif + diff --git a/libmemcached/behavior.cc b/libmemcached/behavior.cc index a6a2efde..9e91f820 100644 --- a/libmemcached/behavior.cc +++ b/libmemcached/behavior.cc @@ -122,12 +122,12 @@ memcached_return_t memcached_behavior_set(memcached_st *ptr, case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS: return memcached_set_error_string(ptr, MEMCACHED_DEPRECATED, - memcached_string_with_size("MEMCACHED_BEHAVIOR_CACHE_LOOKUPS has been deprecated.")); + memcached_literal_param("MEMCACHED_BEHAVIOR_CACHE_LOOKUPS has been deprecated.")); case MEMCACHED_BEHAVIOR_VERIFY_KEY: if (ptr->flags.binary_protocol) return memcached_set_error_string(ptr, MEMCACHED_INVALID_ARGUMENTS, - memcached_string_with_size("MEMCACHED_BEHAVIOR_VERIFY_KEY if the binary protocol has been enabled.")); + memcached_literal_param("MEMCACHED_BEHAVIOR_VERIFY_KEY if the binary protocol has been enabled.")); ptr->flags.verify_key= set_flag(data); break; case MEMCACHED_BEHAVIOR_SORT_HOSTS: @@ -160,7 +160,7 @@ memcached_return_t memcached_behavior_set(memcached_st *ptr, break; case MEMCACHED_BEHAVIOR_USER_DATA: return memcached_set_error_string(ptr, MEMCACHED_DEPRECATED, - memcached_string_with_size("MEMCACHED_BEHAVIOR_USER_DATA deprecated.")); + memcached_literal_param("MEMCACHED_BEHAVIOR_USER_DATA deprecated.")); case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY: ptr->flags.hash_with_prefix_key= set_flag(data); break; @@ -177,18 +177,18 @@ memcached_return_t memcached_behavior_set(memcached_st *ptr, case MEMCACHED_BEHAVIOR_CORK: { return memcached_set_error_string(ptr, MEMCACHED_DEPRECATED, - memcached_string_with_size("MEMCACHED_BEHAVIOR_CORK is now incorporated into the driver by default.")); + memcached_literal_param("MEMCACHED_BEHAVIOR_CORK is now incorporated into the driver by default.")); } break; case MEMCACHED_BEHAVIOR_LOAD_FROM_FILE: return memcached_set_error_string(ptr, MEMCACHED_INVALID_ARGUMENTS, - memcached_string_with_size("MEMCACHED_BEHAVIOR_LOAD_FROM_FILE can not be set with memcached_behavior_set()")); + memcached_literal_param("MEMCACHED_BEHAVIOR_LOAD_FROM_FILE can not be set with memcached_behavior_set()")); case MEMCACHED_BEHAVIOR_MAX: default: /* Shouldn't get here */ WATCHPOINT_ASSERT(0); return memcached_set_error_string(ptr, MEMCACHED_INVALID_ARGUMENTS, - memcached_string_with_size("Invalid behavior passed to memcached_behavior_set()")); + memcached_literal_param("Invalid behavior passed to memcached_behavior_set()")); } return MEMCACHED_SUCCESS; @@ -330,7 +330,7 @@ uint64_t memcached_behavior_get(memcached_st *ptr, } case MEMCACHED_BEHAVIOR_USER_DATA: memcached_set_error_string(ptr, MEMCACHED_DEPRECATED, - memcached_string_with_size("MEMCACHED_BEHAVIOR_USER_DATA deprecated.")); + memcached_literal_param("MEMCACHED_BEHAVIOR_USER_DATA deprecated.")); return 0; case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY: return ptr->flags.hash_with_prefix_key; @@ -378,7 +378,7 @@ memcached_return_t memcached_behavior_set_distribution(memcached_st *ptr, memcac } return memcached_set_error_string(ptr, MEMCACHED_INVALID_ARGUMENTS, - memcached_string_with_size("Invalid memcached_server_distribution_t")); + memcached_literal_param("Invalid memcached_server_distribution_t")); } @@ -393,7 +393,7 @@ memcached_return_t memcached_behavior_set_key_hash(memcached_st *ptr, memcached_ return MEMCACHED_SUCCESS; return memcached_set_error_string(ptr, MEMCACHED_INVALID_ARGUMENTS, - memcached_string_with_size("Invalid memcached_hash_t()")); + memcached_literal_param("Invalid memcached_hash_t()")); } memcached_hash_t memcached_behavior_get_key_hash(memcached_st *ptr) @@ -407,7 +407,7 @@ memcached_return_t memcached_behavior_set_distribution_hash(memcached_st *ptr, m return MEMCACHED_SUCCESS; return memcached_set_error_string(ptr, MEMCACHED_INVALID_ARGUMENTS, - memcached_string_with_size("Invalid memcached_hash_t()")); + memcached_literal_param("Invalid memcached_hash_t()")); } memcached_hash_t memcached_behavior_get_distribution_hash(memcached_st *ptr) diff --git a/libmemcached/common.h b/libmemcached/common.h index ec58fd8e..a90173bc 100644 --- a/libmemcached/common.h +++ b/libmemcached/common.h @@ -44,27 +44,24 @@ #include +#ifdef __cplusplus +#include +#include +#include +#include +#include +#else #include #include #include -#include -#include -#include -#include -#include -#include -#include -#ifdef TIME_WITH_SYS_TIME -# include -# include -#else -# ifdef HAVE_SYS_TIME_H -# include -# else -# include -# endif +#include #endif +#include +#include +#include +#include +#include #include #include @@ -91,6 +88,7 @@ memcached_return_t memcached_server_execute(memcached_st *ptr, /* These are private not to be installed headers */ +#include #include #include #include @@ -178,26 +176,6 @@ static inline memcached_return_t memcached_validate_key_length(size_t key_length return MEMCACHED_SUCCESS; } -static inline void libmemcached_free(const memcached_st *ptr, void *mem) -{ - ptr->allocators.free(ptr, mem, ptr->allocators.context); -} - -static inline void *libmemcached_malloc(const memcached_st *ptr, const size_t size) -{ - return ptr->allocators.malloc(ptr, size, ptr->allocators.context); -} - -static inline void *libmemcached_realloc(const memcached_st *ptr, void *mem, const size_t size) -{ - return ptr->allocators.realloc(ptr, mem, size, ptr->allocators.context); -} - -static inline void *libmemcached_calloc(const memcached_st *ptr, size_t nelem, size_t size) -{ - return ptr->allocators.calloc(ptr, nelem, size, ptr->allocators.context); -} - #ifdef __cplusplus } #endif diff --git a/libmemcached/connect.cc b/libmemcached/connect.cc index 0e642acc..5de143be 100644 --- a/libmemcached/connect.cc +++ b/libmemcached/connect.cc @@ -148,29 +148,46 @@ static memcached_return_t set_hostinfo(memcached_server_st *server) uint32_t counter= 5; while (--counter) { - int e= getaddrinfo(server->hostname, str_port, &hints, &server->address_info); - - if (e == 0) + int errcode; + switch(errcode= getaddrinfo(server->hostname, str_port, &hints, &server->address_info)) { + case 0: break; - } - else if (e == EAI_AGAIN) - { + case EAI_AGAIN: + if (counter > 1) + { #ifndef WIN32 - struct timespec dream, rem; + struct timespec dream, rem; - dream.tv_nsec= 1000; - dream.tv_sec= 0; + dream.tv_nsec= 1000; + dream.tv_sec= 0; - nanosleep(&dream, &rem); + nanosleep(&dream, &rem); #endif - continue; - } - else - { - WATCHPOINT_STRING(server->hostname); - WATCHPOINT_STRING(gai_strerror(e)); - return MEMCACHED_HOST_LOOKUP_FAILURE; + continue; + } + else + { + return memcached_set_error_string(*server, MEMCACHED_HOST_LOOKUP_FAILURE, gai_strerror(errcode), strlen(gai_strerror(errcode))); + } + + case EAI_SYSTEM: + { + static memcached_string_t mesg= { memcached_string_make("getaddrinfo") }; + return memcached_set_errno(*server, errno, &mesg); + } + case EAI_BADFLAGS: + return memcached_set_error_string(*server, MEMCACHED_HOST_LOOKUP_FAILURE, memcached_literal_param("getaddrinfo(EAI_BADFLAGS)")); + + case EAI_MEMORY: + return memcached_set_error_string(*server, MEMCACHED_ERRNO, memcached_literal_param("getaddrinfo(EAI_MEMORY)")); + + default: + { + WATCHPOINT_STRING(server->hostname); + WATCHPOINT_STRING(gai_strerror(e)); + return memcached_set_error_string(*server, MEMCACHED_HOST_LOOKUP_FAILURE, gai_strerror(errcode), strlen(gai_strerror(errcode))); + } } } diff --git a/libmemcached/error.cc b/libmemcached/error.cc index 894d8df9..5f991d7b 100644 --- a/libmemcached/error.cc +++ b/libmemcached/error.cc @@ -101,9 +101,17 @@ memcached_return_t memcached_set_error_string(memcached_st *memc, memcached_retu return memcached_set_error_message(memc, rc, &tmp); } +memcached_return_t memcached_set_error_string(memcached_server_st& self, memcached_return_t rc, const char *str, size_t length) +{ + memcached_string_t tmp; + tmp.c_str= str; + tmp.size= length; + return memcached_set_error_message(self, rc, &tmp); +} + memcached_return_t memcached_set_error_message(memcached_st *memc, memcached_return_t rc, memcached_string_t *str) { - if (rc == MEMCACHED_SUCCESS) + if (memcached_success(rc)) return MEMCACHED_SUCCESS; _set(memc, str, rc); @@ -111,9 +119,35 @@ memcached_return_t memcached_set_error_message(memcached_st *memc, memcached_ret return rc; } +memcached_return_t memcached_set_error_message(memcached_server_st& self, memcached_return_t rc, memcached_string_t *str) +{ + if (memcached_success(rc)) + return MEMCACHED_SUCCESS; + + char hostname_port_message[MAX_ERROR_LENGTH]; + int size; + if (str and str->size) + { + size= snprintf(hostname_port_message, sizeof(hostname_port_message), "%.*s, host: %s:%d", + memcached_string_printf(*str), + self.hostname, int(self.port)); + } + else + { + size= snprintf(hostname_port_message, sizeof(hostname_port_message), "host: %s:%d", + self.hostname, int(self.port)); + } + + memcached_string_t error_host= { size, hostname_port_message }; + + _set((memcached_st*)self.root, &error_host, rc); + + return rc; +} + memcached_return_t memcached_set_error(memcached_server_st& self, memcached_return_t rc) { - if (rc == MEMCACHED_SUCCESS) + if (memcached_success(rc)) return MEMCACHED_SUCCESS; char hostname_port[NI_MAXHOST +NI_MAXSERV + sizeof("host : ")]; @@ -154,14 +188,25 @@ memcached_return_t memcached_set_errno(memcached_st *memc, int local_errno, memc return rc; } -memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errno, memcached_string_t *) +memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errno, memcached_string_t *str) { - char hostname_port[NI_MAXHOST +NI_MAXSERV + sizeof("host : ")]; - int size= snprintf(hostname_port, sizeof(hostname_port), "host: %s:%d", self.hostname, int(self.port)); + char hostname_port_message[MAX_ERROR_LENGTH]; + int size; + if (str and str->size) + { + size= snprintf(hostname_port_message, sizeof(hostname_port_message), "%.*s, host: %s:%d", + memcached_string_printf(*str), + self.hostname, int(self.port)); + } + else + { + size= snprintf(hostname_port_message, sizeof(hostname_port_message), "host: %s:%d", + self.hostname, int(self.port)); + } - memcached_string_t error_host= { size, hostname_port }; + memcached_string_t error_host= { size, hostname_port_message }; - self.cached_errno= local_errno; + self.cached_errno= local_errno; // Store in the actual server memcached_return_t rc= MEMCACHED_ERRNO; _set((memcached_st*)self.root, &error_host, rc, local_errno); diff --git a/libmemcached/error.h b/libmemcached/error.h index e1084442..1dcf9ee0 100644 --- a/libmemcached/error.h +++ b/libmemcached/error.h @@ -55,15 +55,21 @@ LIBMEMCACHED_LOCAL LIBMEMCACHED_LOCAL memcached_return_t memcached_set_errno(memcached_server_st&, int local_errno, memcached_string_t *str); -extern "C" { -#endif - LIBMEMCACHED_LOCAL memcached_return_t memcached_set_error_message(memcached_st *memc, memcached_return_t rc, memcached_string_t *str); +LIBMEMCACHED_LOCAL + memcached_return_t memcached_set_error_message(memcached_server_st&, memcached_return_t rc, memcached_string_t *str); + LIBMEMCACHED_LOCAL memcached_return_t memcached_set_error_string(memcached_st *memc, memcached_return_t rc, const char *str, size_t length); +LIBMEMCACHED_LOCAL + memcached_return_t memcached_set_error_string(memcached_server_st&, memcached_return_t rc, const char *str, size_t length); + +extern "C" { +#endif + LIBMEMCACHED_LOCAL void memcached_error_free(memcached_st *error); diff --git a/libmemcached/fetch.c b/libmemcached/fetch.c deleted file mode 100644 index 3c819f38..00000000 --- a/libmemcached/fetch.c +++ /dev/null @@ -1,108 +0,0 @@ -#include "common.h" - -char *memcached_fetch(memcached_st *ptr, char *key, size_t *key_length, - size_t *value_length, - uint32_t *flags, - memcached_return_t *error) -{ - memcached_result_st *result_buffer= &ptr->result; - - unlikely (ptr->flags.use_udp) - { - *error= MEMCACHED_NOT_SUPPORTED; - return NULL; - } - - result_buffer= memcached_fetch_result(ptr, result_buffer, error); - - if (result_buffer == NULL || *error != MEMCACHED_SUCCESS) - { - WATCHPOINT_ASSERT(result_buffer == NULL); - *value_length= 0; - return NULL; - } - - *value_length= memcached_string_length(&result_buffer->value); - - if (key) - { - if (result_buffer->key_length > MEMCACHED_MAX_KEY) - { - *error= MEMCACHED_KEY_TOO_BIG; - *value_length= 0; - - return NULL; - } - strncpy(key, result_buffer->item_key, result_buffer->key_length); // For the binary protocol we will cut off the key :( - *key_length= result_buffer->key_length; - } - - *flags= result_buffer->item_flags; - - return memcached_string_c_copy(&result_buffer->value); -} - -memcached_result_st *memcached_fetch_result(memcached_st *ptr, - memcached_result_st *result, - memcached_return_t *error) -{ - memcached_server_st *server; - - unlikely (ptr->flags.use_udp) - { - *error= MEMCACHED_NOT_SUPPORTED; - return NULL; - } - - if (result == NULL) - if ((result= memcached_result_create(ptr, NULL)) == NULL) - return NULL; - - while ((server= memcached_io_get_readable_server(ptr)) != NULL) - { - char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; - *error= memcached_response(server, buffer, sizeof(buffer), result); - - if (*error == MEMCACHED_SUCCESS) - return result; - else if (*error == MEMCACHED_END) - memcached_server_response_reset(server); - else if (*error != MEMCACHED_NOTFOUND) - break; - } - - /* We have completed reading data */ - if (memcached_is_allocated(result)) - { - memcached_result_free(result); - } - else - { - memcached_string_reset(&result->value); - } - - return NULL; -} - -memcached_return_t memcached_fetch_execute(memcached_st *ptr, - memcached_execute_fn *callback, - void *context, - uint32_t number_of_callbacks) -{ - memcached_result_st *result= &ptr->result; - memcached_return_t rc= MEMCACHED_FAILURE; - - while ((result= memcached_fetch_result(ptr, result, &rc)) != NULL) - { - if (rc == MEMCACHED_SUCCESS) - { - for (uint32_t x= 0; x < number_of_callbacks; x++) - { - rc= (*callback[x])(ptr, result, context); - if (rc != MEMCACHED_SUCCESS) - break; - } - } - } - return rc; -} diff --git a/libmemcached/fetch.cc b/libmemcached/fetch.cc new file mode 100644 index 00000000..71d5820b --- /dev/null +++ b/libmemcached/fetch.cc @@ -0,0 +1,149 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached library + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * Copyright (C) 2006-2009 Brian Aker All rights reserved. + * + * 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 + +char *memcached_fetch(memcached_st *ptr, char *key, size_t *key_length, + size_t *value_length, + uint32_t *flags, + memcached_return_t *error) +{ + memcached_result_st *result_buffer= &ptr->result; + memcached_return_t unused; + if (not error) + error= &unused; + + + unlikely (ptr->flags.use_udp) + { + *error= MEMCACHED_NOT_SUPPORTED; + return NULL; + } + + result_buffer= memcached_fetch_result(ptr, result_buffer, error); + + if (result_buffer == NULL || *error != MEMCACHED_SUCCESS) + { + WATCHPOINT_ASSERT(result_buffer == NULL); + *value_length= 0; + return NULL; + } + + *value_length= memcached_string_length(&result_buffer->value); + + if (key) + { + if (result_buffer->key_length > MEMCACHED_MAX_KEY) + { + *error= MEMCACHED_KEY_TOO_BIG; + *value_length= 0; + + return NULL; + } + strncpy(key, result_buffer->item_key, result_buffer->key_length); // For the binary protocol we will cut off the key :( + *key_length= result_buffer->key_length; + } + + *flags= result_buffer->item_flags; + + return memcached_string_c_copy(&result_buffer->value); +} + +memcached_result_st *memcached_fetch_result(memcached_st *ptr, + memcached_result_st *result, + memcached_return_t *error) +{ + memcached_server_st *server; + + unlikely (ptr->flags.use_udp) + { + *error= MEMCACHED_NOT_SUPPORTED; + return NULL; + } + + if (result == NULL) + if ((result= memcached_result_create(ptr, NULL)) == NULL) + return NULL; + + while ((server= memcached_io_get_readable_server(ptr)) != NULL) + { + char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; + *error= memcached_response(server, buffer, sizeof(buffer), result); + + if (*error == MEMCACHED_SUCCESS) + return result; + else if (*error == MEMCACHED_END) + memcached_server_response_reset(server); + else if (*error != MEMCACHED_NOTFOUND) + break; + } + + /* We have completed reading data */ + if (memcached_is_allocated(result)) + { + memcached_result_free(result); + } + else + { + memcached_string_reset(&result->value); + } + + return NULL; +} + +memcached_return_t memcached_fetch_execute(memcached_st *ptr, + memcached_execute_fn *callback, + void *context, + uint32_t number_of_callbacks) +{ + memcached_result_st *result= &ptr->result; + memcached_return_t rc= MEMCACHED_FAILURE; + + while ((result= memcached_fetch_result(ptr, result, &rc)) != NULL) + { + if (rc == MEMCACHED_SUCCESS) + { + for (uint32_t x= 0; x < number_of_callbacks; x++) + { + rc= (*callback[x])(ptr, result, context); + if (rc != MEMCACHED_SUCCESS) + break; + } + } + } + return rc; +} diff --git a/libmemcached/hash.cc b/libmemcached/hash.cc index 0e6295b8..5eca0c6f 100644 --- a/libmemcached/hash.cc +++ b/libmemcached/hash.cc @@ -37,8 +37,10 @@ #include -#include +#include + +#include uint32_t memcached_generate_hash_value(const char *key, size_t key_length, memcached_hash_t hash_algorithm) { diff --git a/libmemcached/hosts.cc b/libmemcached/hosts.cc index 23d42341..152ff703 100644 --- a/libmemcached/hosts.cc +++ b/libmemcached/hosts.cc @@ -1,16 +1,44 @@ -/* LibMemcached - * Copyright (C) 2006-2010 Brian Aker - * All rights reserved. +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached library * - * Use and distribution licensed under the BSD license. See - * the COPYING file in the parent directory for full text. + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * Copyright (C) 2006-2010 Brian Aker All rights reserved. * - * Summary: + * 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 "common.h" -#include +#include + +#include +#include /* Protoypes (static) */ static memcached_return_t server_add(memcached_st *ptr, const char *hostname, diff --git a/libmemcached/include.am b/libmemcached/include.am index fe3c5fcd..a761ce08 100644 --- a/libmemcached/include.am +++ b/libmemcached/include.am @@ -20,6 +20,7 @@ noinst_HEADERS+= \ libmemcached/io.h \ libmemcached/is.h \ libmemcached/libmemcached_probes.h \ + libmemcached/memory.h \ libmemcached/protocol/ascii_handler.h \ libmemcached/protocol/binary_handler.h \ libmemcached/protocol/common.h \ @@ -31,6 +32,7 @@ nobase_include_HEADERS+= \ libmemcached/analyze.h \ libmemcached/array.h \ libmemcached/auto.h \ + libmemcached/basic_string.h \ libmemcached/behavior.h \ libmemcached/callback.h \ libmemcached/configure.h \ @@ -113,7 +115,7 @@ libmemcached_libmemcached_la_SOURCES+= \ libmemcached/do.cc \ libmemcached/dump.cc \ libmemcached/error.cc \ - libmemcached/fetch.c \ + libmemcached/fetch.cc \ libmemcached/flush.cc \ libmemcached/flush_buffers.cc \ libmemcached/get.cc \ diff --git a/libmemcached/memory.h b/libmemcached/memory.h new file mode 100644 index 00000000..7b30e371 --- /dev/null +++ b/libmemcached/memory.h @@ -0,0 +1,57 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached library + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * The names of its contributors may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +static inline void libmemcached_free(const memcached_st *self, void *mem) +{ + self->allocators.free(self, mem, self->allocators.context); +} + +static inline void *libmemcached_malloc(const memcached_st *self, const size_t size) +{ + return self->allocators.malloc(self, size, self->allocators.context); +} + +static inline void *libmemcached_realloc(const memcached_st *self, void *mem, const size_t size) +{ + return self->allocators.realloc(self, mem, size, self->allocators.context); +} + +static inline void *libmemcached_calloc(const memcached_st *self, size_t nelem, size_t size) +{ + return self->allocators.calloc(self, nelem, size, self->allocators.context); +} diff --git a/libmemcached/options/context.h b/libmemcached/options/context.h index 226284d9..7660d2d2 100644 --- a/libmemcached/options/context.h +++ b/libmemcached/options/context.h @@ -108,9 +108,9 @@ public: rc= MEMCACHED_PARSE_ERROR; memcached_string_st *error_string= memcached_string_create(memc, NULL, 1024); - memcached_string_append(error_string, memcached_string_with_size("Error occured while parsing: ")); + memcached_string_append(error_string, memcached_literal_param("Error occured while parsing: ")); memcached_string_append(error_string, memcached_string_make_from_cstr(begin)); - memcached_string_append(error_string, memcached_string_with_size(" (")); + memcached_string_append(error_string, memcached_literal_param(" (")); if (rc == MEMCACHED_PARSE_ERROR and error) { @@ -120,7 +120,7 @@ public: { memcached_string_append(error_string, memcached_string_make_from_cstr(memcached_strerror(NULL, rc))); } - memcached_string_append(error_string, memcached_string_with_size(")")); + memcached_string_append(error_string, memcached_literal_param(")")); memcached_set_error_string(memc, rc, memcached_string_value(error_string), memcached_string_length(error_string)); diff --git a/libmemcached/return.h b/libmemcached/return.h index 5b4a4041..1d605544 100644 --- a/libmemcached/return.h +++ b/libmemcached/return.h @@ -39,9 +39,9 @@ enum memcached_return_t { MEMCACHED_SUCCESS, MEMCACHED_FAILURE, - MEMCACHED_HOST_LOOKUP_FAILURE, - MEMCACHED_CONNECTION_FAILURE, - MEMCACHED_CONNECTION_BIND_FAILURE, + MEMCACHED_HOST_LOOKUP_FAILURE, // getaddrinfo() only + MEMCACHED_CONNECTION_FAILURE, // DEPRECATED + MEMCACHED_CONNECTION_BIND_FAILURE, // DEPRECATED MEMCACHED_WRITE_FAILURE, MEMCACHED_READ_FAILURE, MEMCACHED_UNKNOWN_READ_FAILURE, diff --git a/libmemcached/sasl.c b/libmemcached/sasl.c index 66920795..686b6a38 100644 --- a/libmemcached/sasl.c +++ b/libmemcached/sasl.c @@ -1,15 +1,41 @@ -/* LibMemcached - * Copyright (C) 2006-2010 Brian Aker - * All rights reserved. +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached library * - * Use and distribution licensed under the BSD license. See - * the COPYING file in the parent directory for full text. + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * Copyright (C) 2006-2009 Brian Aker All rights reserved. * - * Summary: interface for memcached server - * Description: main include file for libmemcached + * 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 "common.h" + +#include void memcached_set_sasl_callbacks(memcached_st *ptr, const sasl_callback_t *callbacks) @@ -64,7 +90,7 @@ memcached_return_t memcached_sasl_authenticate_connection(memcached_server_st *s memcached_return_t rc; /* SANITY CHECK: SASL can only be used with the binary protocol */ - unlikely (!server->root->flags.binary_protocol) + if (!server->root->flags.binary_protocol) return MEMCACHED_FAILURE; /* Try to get the supported mech from the server. Servers without SASL diff --git a/libmemcached/strerror.cc b/libmemcached/strerror.cc index b3ac2b75..39583152 100644 --- a/libmemcached/strerror.cc +++ b/libmemcached/strerror.cc @@ -9,9 +9,9 @@ const char *memcached_strerror(memcached_st *ptr, memcached_return_t rc) return "SUCCESS"; case MEMCACHED_FAILURE: return "FAILURE"; - case MEMCACHED_HOST_LOOKUP_FAILURE: - return "HOSTNAME LOOKUP FAILURE"; - case MEMCACHED_CONNECTION_FAILURE: + case MEMCACHED_HOST_LOOKUP_FAILURE: // getaddrinfo only + return "getaddrinfo() HOSTNAME LOOKUP FAILURE"; + case MEMCACHED_CONNECTION_FAILURE: // DEPRECATED return "CONNECTION FAILURE"; case MEMCACHED_CONNECTION_BIND_FAILURE: return "CONNECTION BIND FAILURE"; diff --git a/libmemcached/string.h b/libmemcached/string.h index 50ad98bb..29116ca5 100644 --- a/libmemcached/string.h +++ b/libmemcached/string.h @@ -37,6 +37,8 @@ #pragma once +#include + /** Strings are always under our control so we make some assumptions about them. @@ -58,15 +60,6 @@ struct memcached_string_st { } options; }; -struct memcached_string_t { - size_t size; - const char *c_str; -}; - -#define memcached_size(X) (X).size; -#define memcached_c_str(X) (X).c_str; -#define memcached_string_param(X) (X).c_str, (X).size - #ifdef BUILDING_LIBMEMCACHED #ifdef __cplusplus @@ -115,10 +108,10 @@ void memcached_string_set_length(memcached_string_st *self, size_t length); #endif #ifdef __cplusplus -#define memcached_string_with_size(X) (X), (static_cast((sizeof(X) - 1))) +#define memcached_literal_param(X) (X), (static_cast((sizeof(X) - 1))) #define memcached_string_make(X) (static_cast((sizeof(X) - 1))), (X) #else -#define memcached_string_with_size(X) (X), ((size_t)((sizeof(X) - 1))) +#define memcached_literal_param(X) (X), ((size_t)((sizeof(X) - 1))) #define memcached_string_make(X) (((size_t)((sizeof(X) - 1))), (X) #endif diff --git a/libmemcached/types.h b/libmemcached/types.h index b3d8f479..4317af3b 100644 --- a/libmemcached/types.h +++ b/libmemcached/types.h @@ -1,14 +1,41 @@ -/* LibMemcached - * Copyright (C) 2006-2009 Brian Aker - * All rights reserved. +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached library * - * Use and distribution licensed under the BSD license. See - * the COPYING file in the parent directory for full text. + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * Copyright (C) 2006-2009 Brian Aker All rights reserved. * - * Summary: Types for libmemcached + * 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 #ifndef __LIBMEMCACHED_TYPES_H__ #define __LIBMEMCACHED_TYPES_H__ diff --git a/libmemcached/virtual_bucket.c b/libmemcached/virtual_bucket.c index 26dd90c4..1428fba8 100644 --- a/libmemcached/virtual_bucket.c +++ b/libmemcached/virtual_bucket.c @@ -35,7 +35,8 @@ * */ -#include +#include +#include #include struct bucket_t { diff --git a/tests/error_conditions.cc b/tests/error_conditions.cc index d06f4225..50a64da5 100644 --- a/tests/error_conditions.cc +++ b/tests/error_conditions.cc @@ -44,29 +44,20 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif - -test_return_t memcached_increment_MEMCACHED_NO_SERVERS(memcached_st *junk) +test_return_t memcached_increment_MEMCACHED_NO_SERVERS(memcached_st *) { - (void)junk; memcached_st *memc_ptr; memc_ptr= memcached_create(NULL); test_true(memc_ptr); - memcached_increment(memc_ptr, memcached_string_with_size("dead key"), 1, NULL); + memcached_increment(memc_ptr, memcached_literal_param("dead key"), 1, NULL); test_true(memcached_last_error(memc_ptr) == MEMCACHED_NO_SERVERS); - memcached_increment(memc_ptr, memcached_string_with_size("dead key"), 1, NULL); + memcached_increment(memc_ptr, memcached_literal_param("dead key"), 1, NULL); test_true(memcached_last_error(memc_ptr) == MEMCACHED_NO_SERVERS); memcached_free(memc_ptr); return TEST_SUCCESS; } - -#ifdef __cplusplus -} -#endif diff --git a/tests/mem_functions.cc b/tests/mem_functions.cc index 7b0fe8bd..3bc38fcd 100644 --- a/tests/mem_functions.cc +++ b/tests/mem_functions.cc @@ -37,18 +37,16 @@ /* - Sample test application. + Test cases */ -#include "config.h" +#define BUILDING_LIBMEMCACHED +// !NEVER use common.h, always use memcached.h in your own apps +#include #include #include -#include -#include -#include -#include #include #include #include @@ -56,8 +54,6 @@ #include #include -#include "libmemcached/common.h" - #include #include "clients/generator.h" @@ -401,7 +397,7 @@ static test_return_t connection_test(memcached_st *memc) static test_return_t error_test(memcached_st *memc) { - uint32_t values[] = { 851992627U, 2337886783U, 3196981036U, 4001849190U, + uint32_t values[] = { 851992627U, 2337886783U, 646418395U, 4001849190U, 982370485U, 1263635348U, 4242906218U, 3829656100U, 1891735253U, 334139633U, 2257084983U, 3088286104U, 13199785U, 2542027183U, 1097051614U, 199566778U, @@ -435,13 +431,10 @@ static test_return_t error_test(memcached_st *memc) static test_return_t set_test(memcached_st *memc) { - memcached_return_t rc; - const char *key= "foo"; - const char *value= "when we sanitize"; - - rc= memcached_set(memc, key, strlen(key), - value, strlen(value), - (time_t)0, (uint32_t)0); + memcached_return_t rc= memcached_set(memc, + memcached_literal_param("foo"), + memcached_literal_param("when we sanitize"), + time_t(0), (uint32_t)0); test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); return TEST_SUCCESS; diff --git a/tests/string.cc b/tests/string.cc index aa8a7d6f..5c6175f8 100644 --- a/tests/string.cc +++ b/tests/string.cc @@ -155,12 +155,12 @@ test_return_t string_alloc_append_toobig(memcached_st *memc) test_return_t string_alloc_append_multiple(memcached_st *memc) { memcached_string_st *error_string= memcached_string_create(memc, NULL, 1024); - memcached_string_append(error_string, memcached_string_with_size("Error occured while parsing: ")); + memcached_string_append(error_string, memcached_literal_param("Error occured while parsing: ")); memcached_string_append(error_string, memcached_string_make_from_cstr("jog the strlen() method")); - memcached_string_append(error_string, memcached_string_with_size(" (")); + memcached_string_append(error_string, memcached_literal_param(" (")); memcached_string_append(error_string, memcached_string_make_from_cstr(memcached_strerror(NULL, MEMCACHED_SUCCESS))); - memcached_string_append(error_string, memcached_string_with_size(")")); + memcached_string_append(error_string, memcached_literal_param(")")); memcached_string_free(error_string);