From 8a5081c5ed9c33b1d6d5f070ba97b2b21b7a0da8 Mon Sep 17 00:00:00 2001 From: Date: Mon, 8 Sep 2008 16:19:01 -0700 Subject: [PATCH] Updated for the creation of memcached_server_by_key(). --- ChangeLog | 6 ++ docs/memcached_create.pod | 3 +- docs/memcached_servers.pod | 11 ++++ libmemcached/common.h | 4 ++ libmemcached/memcached.c | 69 ++++++++++++----------- libmemcached/memcached.h | 5 -- libmemcached/memcached_hosts.c | 6 +- libmemcached/memcached_io.c | 9 ++- libmemcached/memcached_server.c | 97 +++++++++++++++++++++++++++++++++ libmemcached/memcached_server.h | 14 +++++ tests/function.c | 2 + 11 files changed, 181 insertions(+), 45 deletions(-) diff --git a/ChangeLog b/ChangeLog index b870bd68..3abd6452 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ * Cleanup compile warnings. * Fix issues in partitioning by keys. + * Fixed "fail case" to make sure when calling memcached_clone() no + memcached_st is over written. + * New memcached_server_by_key() method for finding a server from + a key. + * memcached_server_free() was added for freeing server structures. + 0.23 Sun Sep 7 08:13:59 PDT 2008 * Added strings.h header for Solaris 9 diff --git a/docs/memcached_create.pod b/docs/memcached_create.pod index f76e9c7e..8d1a76b4 100755 --- a/docs/memcached_create.pod +++ b/docs/memcached_create.pod @@ -39,7 +39,8 @@ memcached_create() returns a pointer to the memcached_st that was created (or initialized). On an allocation failure, it returns NULL. memcached_clone() returns a pointer to the memcached_st that was created -(or initialized). On an allocation failure, it returns NULL. +(or initialized). On an allocation failure, it returns NULL. If you pass in +a preallocated structure it must be cleared first (aka memset()). =head1 HOME diff --git a/docs/memcached_servers.pod b/docs/memcached_servers.pod index d417dfd1..d1a61cd6 100755 --- a/docs/memcached_servers.pod +++ b/docs/memcached_servers.pod @@ -28,6 +28,11 @@ C Client Library for memcached (libmemcached, -lmemcached) memcached_server_push (memcached_st *ptr, memcached_server_st *list); + memcached_server_st * + memcached_server_by_key (memcached_st *ptr, + const char *key, size_t key_length, + memcached_return *error); + =head1 DESCRIPTION libmemcached(3) performs operations on a list of hosts. The order of these @@ -57,6 +62,12 @@ end. Duplicate servers are allowed, so duplication is not checked. A copy is made of structure so the list provided (and any operations on the list) are not saved. +memcached_server_by_key() allows you to provide a key and retrieve the +server which would be used for assignment. This structure is cloned +from its original structure and must be freed. If NULL is returned you +should consult *error. The returning structure should be freed with +memcached_server_free(). + =head1 RETURN Varies, see particular functions. diff --git a/libmemcached/common.h b/libmemcached/common.h index 3ad6c3d8..ff60c232 100644 --- a/libmemcached/common.h +++ b/libmemcached/common.h @@ -123,4 +123,8 @@ memcached_return memcached_server_remove(memcached_server_st *st_ptr); extern uint64_t ntohll(uint64_t); extern uint64_t htonll(uint64_t); +void host_reset(memcached_st *ptr, memcached_server_st *host, + char *hostname, unsigned int port, + memcached_connection type); + #endif /* __COMMON_H__ */ diff --git a/libmemcached/memcached.c b/libmemcached/memcached.c index 40f8e263..d5bfd190 100644 --- a/libmemcached/memcached.c +++ b/libmemcached/memcached.c @@ -61,21 +61,20 @@ void memcached_free(memcached_st *ptr) } /* - clone is the destination, while ptr is the structure to clone. - If ptr is NULL the call is the same as if a memcached_create() was + clone is the destination, while source is the structure to clone. + If source is NULL the call is the same as if a memcached_create() was called. */ -memcached_st *memcached_clone(memcached_st *clone, memcached_st *ptr) +memcached_st *memcached_clone(memcached_st *clone, memcached_st *source) { memcached_return rc= MEMCACHED_SUCCESS; memcached_st *new_clone; - if (ptr == NULL) + if (source == NULL) return memcached_create(clone); - if (ptr->is_allocated == MEMCACHED_USED) + if (clone && clone->is_allocated == MEMCACHED_USED) { - WATCHPOINT_ASSERT(0); return NULL; } @@ -84,8 +83,8 @@ memcached_st *memcached_clone(memcached_st *clone, memcached_st *ptr) if (new_clone == NULL) return NULL; - if (ptr->hosts) - rc= memcached_server_push(new_clone, ptr->hosts); + if (source->hosts) + rc= memcached_server_push(new_clone, source->hosts); if (rc != MEMCACHED_SUCCESS) { @@ -95,32 +94,32 @@ memcached_st *memcached_clone(memcached_st *clone, memcached_st *ptr) } - new_clone->flags= ptr->flags; - new_clone->send_size= ptr->send_size; - new_clone->recv_size= ptr->recv_size; - new_clone->poll_timeout= ptr->poll_timeout; - new_clone->connect_timeout= ptr->connect_timeout; - new_clone->retry_timeout= ptr->retry_timeout; - new_clone->distribution= ptr->distribution; - new_clone->hash= ptr->hash; - new_clone->hash_continuum= ptr->hash_continuum; - new_clone->user_data= ptr->user_data; - - new_clone->snd_timeout= ptr->snd_timeout; - new_clone->rcv_timeout= ptr->rcv_timeout; - - new_clone->on_clone= ptr->on_clone; - new_clone->on_cleanup= ptr->on_cleanup; - new_clone->call_free= ptr->call_free; - new_clone->call_malloc= ptr->call_malloc; - new_clone->call_realloc= ptr->call_realloc; - new_clone->get_key_failure= ptr->get_key_failure; - new_clone->delete_trigger= ptr->delete_trigger; - - if (ptr->prefix_key[0] != 0) + new_clone->flags= source->flags; + new_clone->send_size= source->send_size; + new_clone->recv_size= source->recv_size; + new_clone->poll_timeout= source->poll_timeout; + new_clone->connect_timeout= source->connect_timeout; + new_clone->retry_timeout= source->retry_timeout; + new_clone->distribution= source->distribution; + new_clone->hash= source->hash; + new_clone->hash_continuum= source->hash_continuum; + new_clone->user_data= source->user_data; + + new_clone->snd_timeout= source->snd_timeout; + new_clone->rcv_timeout= source->rcv_timeout; + + new_clone->on_clone= source->on_clone; + new_clone->on_cleanup= source->on_cleanup; + new_clone->call_free= source->call_free; + new_clone->call_malloc= source->call_malloc; + new_clone->call_realloc= source->call_realloc; + new_clone->get_key_failure= source->get_key_failure; + new_clone->delete_trigger= source->delete_trigger; + + if (source->prefix_key[0] != 0) { - strcpy(new_clone->prefix_key, ptr->prefix_key); - new_clone->prefix_key_length= ptr->prefix_key_length; + strcpy(new_clone->prefix_key, source->prefix_key); + new_clone->prefix_key_length= source->prefix_key_length; } rc= run_distribution(new_clone); @@ -131,8 +130,8 @@ memcached_st *memcached_clone(memcached_st *clone, memcached_st *ptr) return NULL; } - if (ptr->on_clone) - ptr->on_clone(ptr, new_clone); + if (source->on_clone) + source->on_clone(source, new_clone); return new_clone; } diff --git a/libmemcached/memcached.h b/libmemcached/memcached.h index 47cdaf84..3017fbb1 100644 --- a/libmemcached/memcached.h +++ b/libmemcached/memcached.h @@ -169,11 +169,6 @@ void *memcached_callback_get(memcached_st *ptr, memcached_callback flag, memcached_return *error); -memcached_return memcached_server_cursor(memcached_st *ptr, - memcached_server_function *callback, - void *context, - unsigned int number_of_callbacks); - #ifdef __cplusplus } diff --git a/libmemcached/memcached_hosts.c b/libmemcached/memcached_hosts.c index f87414da..13604d33 100644 --- a/libmemcached/memcached_hosts.c +++ b/libmemcached/memcached_hosts.c @@ -51,9 +51,9 @@ memcached_return run_distribution(memcached_st *ptr) return MEMCACHED_SUCCESS; } -static void host_reset(memcached_st *ptr, memcached_server_st *host, - char *hostname, unsigned int port, - memcached_connection type) +void host_reset(memcached_st *ptr, memcached_server_st *host, + char *hostname, unsigned int port, + memcached_connection type) { memset(host, 0, sizeof(memcached_server_st)); strncpy(host->hostname, hostname, MEMCACHED_MAX_HOST_LENGTH - 1); diff --git a/libmemcached/memcached_io.c b/libmemcached/memcached_io.c index c9e04c9b..47486d30 100644 --- a/libmemcached/memcached_io.c +++ b/libmemcached/memcached_io.c @@ -210,7 +210,14 @@ memcached_return memcached_io_close(memcached_server_st *ptr) /* in case of death shutdown to avoid blocking at close() */ r= shutdown(ptr->fd, SHUT_RDWR); - WATCHPOINT_ASSERT(r == 0); + +#ifdef HAVE_DEBUG + if (r && errno != ENOTCONN) + { + WATCHPOINT_ERRNO(errno); + WATCHPOINT_ASSERT(errno); + } +#endif r= close(ptr->fd); WATCHPOINT_ASSERT(r == 0); diff --git a/libmemcached/memcached_server.c b/libmemcached/memcached_server.c index fd86e6d6..6dff6940 100644 --- a/libmemcached/memcached_server.c +++ b/libmemcached/memcached_server.c @@ -1,5 +1,74 @@ +/* + This is a partial implementation for fetching/creating memcached_server_st objects. +*/ #include "common.h" +memcached_server_st *memcached_server_create(memcached_st *memc, memcached_server_st *ptr) +{ + if (ptr == NULL) + { + ptr= (memcached_server_st *)malloc(sizeof(memcached_server_st)); + + if (!ptr) + return NULL; /* MEMCACHED_MEMORY_ALLOCATION_FAILURE */ + + memset(ptr, 0, sizeof(memcached_server_st)); + ptr->is_allocated= MEMCACHED_ALLOCATED; + } + else + { + memset(ptr, 0, sizeof(memcached_server_st)); + } + + ptr->root= memc; + + return ptr; +} + +void memcached_server_free(memcached_server_st *ptr) +{ + if (ptr->is_allocated == MEMCACHED_ALLOCATED) + { + if (ptr->root && ptr->root->call_free) + ptr->root->call_free(ptr->root, ptr); + else + free(ptr); + } + else + ptr->is_allocated= MEMCACHED_USED; +} + +/* + If we do not have a valid object to clone from, we toss an error. +*/ +memcached_server_st *memcached_server_clone(memcached_server_st *clone, memcached_server_st *ptr) +{ + memcached_server_st *new_clone; + + /* We just do a normal create if ptr is missing */ + if (ptr == NULL) + return NULL; + + if (clone && clone->is_allocated == MEMCACHED_USED) + { + WATCHPOINT_ASSERT(0); + return NULL; + } + + new_clone= memcached_server_create(ptr->root, clone); + + if (new_clone == NULL) + return NULL; + + new_clone->root= ptr->root; + + host_reset(new_clone->root, new_clone, + ptr->hostname, ptr->port, + ptr->type); + + return new_clone; +} + memcached_return memcached_server_cursor(memcached_st *ptr, memcached_server_function *callback, void *context, @@ -24,3 +93,31 @@ memcached_return memcached_server_cursor(memcached_st *ptr, return MEMCACHED_SUCCESS; } + +memcached_server_st *memcached_server_by_key(memcached_st *ptr, const char *key, size_t key_length, memcached_return *error) +{ + uint32_t server_key; + + unlikely (key_length == 0) + { + *error= MEMCACHED_NO_KEY_PROVIDED; + return NULL; + } + + unlikely (ptr->number_of_hosts == 0) + { + *error= MEMCACHED_NO_SERVERS; + return NULL; + } + + if ((ptr->flags & MEM_VERIFY_KEY) && (memcachd_key_test((char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED)) + { + *error= MEMCACHED_BAD_KEY_PROVIDED; + return NULL; + } + + server_key= memcached_generate_hash(ptr, key, key_length); + + return memcached_server_clone(NULL, &ptr->hosts[server_key]); + +} diff --git a/libmemcached/memcached_server.h b/libmemcached/memcached_server.h index ad03898d..891c9c73 100644 --- a/libmemcached/memcached_server.h +++ b/libmemcached/memcached_server.h @@ -14,6 +14,7 @@ extern "C" { #endif struct memcached_server_st { + memcached_allocated is_allocated; char hostname[MEMCACHED_MAX_HOST_LENGTH]; unsigned int port; int fd; @@ -44,6 +45,19 @@ struct memcached_server_st { #define memcached_server_list(A) (A)->hosts #define memcached_server_response_count(A) (A)->cursor_active +memcached_return memcached_server_cursor(memcached_st *ptr, + memcached_server_function *callback, + void *context, + unsigned int number_of_callbacks); + +memcached_server_st *memcached_server_by_key(memcached_st *ptr, const char *key, + size_t key_length, memcached_return *error); + +/* These should not currently be used by end users */ +memcached_server_st *memcached_server_create(memcached_st *memc, memcached_server_st *ptr); +void memcached_server_free(memcached_server_st *ptr); +memcached_server_st *memcached_server_clone(memcached_server_st *clone, memcached_server_st *ptr); + #ifdef __cplusplus } diff --git a/tests/function.c b/tests/function.c index b03b06da..599a8868 100644 --- a/tests/function.c +++ b/tests/function.c @@ -211,6 +211,7 @@ static test_return clone_test(memcached_st *memc) { memcached_st declared_clone; memcached_st *clone; + memset(&declared_clone, 0 , sizeof(memcached_st)); clone= memcached_clone(&declared_clone, NULL); assert(clone); memcached_free(clone); @@ -220,6 +221,7 @@ static test_return clone_test(memcached_st *memc) { memcached_st declared_clone; memcached_st *clone; + memset(&declared_clone, 0 , sizeof(memcached_st)); clone= memcached_clone(&declared_clone, memc); assert(clone); memcached_free(clone); -- 2.30.2