From 666a820df3605bf92a4ffefed6ec3b1649f37291 Mon Sep 17 00:00:00 2001 From: Date: Thu, 29 Nov 2007 08:59:19 -0800 Subject: [PATCH] IPV6 support, plus cleanup around consistent hashing. --- ChangeLog | 5 ++++ configure.ac | 3 +-- include/memcached.h | 4 ++-- lib/memcached.c | 18 +++++++------- lib/memcached_connect.c | 53 ++++++++++++++++++++++------------------- lib/memcached_hash.c | 2 +- lib/memcached_hosts.c | 6 +++++ lib/memcached_io.c | 2 +- tests/function.c | 1 + 9 files changed, 55 insertions(+), 39 deletions(-) diff --git a/ChangeLog b/ChangeLog index 99391fce..ffb487e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +0.12 + * Updates for consistent hashing + * IPV6 support + * Static allocation for hostname (performance) + 0.11 Mon Nov 26 01:05:52 PST 2007 * Added option to memcache_behavior_set() so that poll() can be timed out. * Fixed memory leak in case of using memcached_fetch_result() where no diff --git a/configure.ac b/configure.ac index 3c2310eb..0c8be6ff 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ MEMCACHED_LIBRARY_NAME=libmemcached #release versioning MEMCACHED_MAJOR_VERSION=0 -MEMCACHED_MINOR_VERSION=11 +MEMCACHED_MINOR_VERSION=12 MEMCACHED_MICRO_VERSION=0 #API version @@ -68,5 +68,4 @@ fi AC_C_CONST AC_TYPE_SIZE_T -AC_CHECK_FUNC(gethostbyname_r, AC_DEFINE([HAVE_GETHOSTBYNAME_R], [], [Looking for gethostbyname_r])) AC_OUTPUT(Makefile src/Makefile tests/Makefile docs/Makefile lib/Makefile include/Makefile support/Makefile support/libmemcached.pc support/libmemcached.spec) diff --git a/include/memcached.h b/include/memcached.h index 194170ef..971b4ab4 100644 --- a/include/memcached.h +++ b/include/memcached.h @@ -70,7 +70,7 @@ typedef enum { } memcached_return; typedef enum { - MEMCACHED_DISTRIBUTION_MODULUS, + MEMCACHED_DISTRIBUTION_MODULO, MEMCACHED_DISTRIBUTION_CONSISTENT, } memcached_server_distribution; @@ -124,7 +124,7 @@ struct memcached_server_st { size_t read_buffer_length; char *read_ptr; memcached_allocated sockaddr_inited; - struct sockaddr_in servAddr; + struct addrinfo *address_info; memcached_connection type; uint8_t major_version; uint8_t minor_version; diff --git a/lib/memcached.c b/lib/memcached.c index 1ed39a91..861bafda 100644 --- a/lib/memcached.c +++ b/lib/memcached.c @@ -23,20 +23,16 @@ memcached_st *memcached_create(memcached_st *ptr) string_ptr= memcached_string_create(ptr, &ptr->result_buffer, 0); WATCHPOINT_ASSERT(string_ptr); ptr->poll_timeout= -1; - ptr->distribution= MEMCACHED_DISTRIBUTION_MODULUS; + ptr->distribution= MEMCACHED_DISTRIBUTION_MODULO; return ptr; } void memcached_free(memcached_st *ptr) { - if (ptr->hosts) - { - memcached_quit(ptr); - memcached_server_list_free(ptr->hosts); - ptr->hosts= NULL; - } - + /* If we have anything open, lets close it now */ + memcached_quit(ptr); + memcached_server_list_free(ptr->hosts); memcached_string_free(&ptr->result_buffer); if (ptr->is_allocated == MEMCACHED_ALLOCATED) @@ -57,6 +53,12 @@ memcached_st *memcached_clone(memcached_st *clone, memcached_st *ptr) if (ptr == NULL) return memcached_create(clone); + + if (ptr->is_allocated == MEMCACHED_USED) + { + WATCHPOINT_ASSERT(0); + return NULL; + } new_clone= memcached_create(clone); diff --git a/lib/memcached_connect.c b/lib/memcached_connect.c index 0135fc9a..672b1c23 100644 --- a/lib/memcached_connect.c +++ b/lib/memcached_connect.c @@ -6,36 +6,33 @@ #include #include #include +#include static memcached_return set_hostinfo(memcached_server_st *server) { - struct hostent *h; -#ifdef HAVE_GETHOSTBYNAME_R - struct hostent h_static; - char buffer[SMALL_STRING_LEN]; - int tmp_error; - - if (gethostbyname_r(server->hostname, - &h_static, buffer, SMALL_STRING_LEN, - &h, &tmp_error)) - { - WATCHPOINT_STRING(server->hostname); - WATCHPOINT_STRING(hstrerror(tmp_error)); - return MEMCACHED_HOST_LOOKUP_FAILURE; - } -#else - if ((h= gethostbyname(server->hostname)) == NULL) + struct addrinfo *ai; + struct addrinfo hints; + int e; + char str_port[NI_MAXSERV]; + + sprintf(str_port, "%u", server->port); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family= AF_INET; + hints.ai_socktype= SOCK_STREAM; + hints.ai_protocol= 0; + + e= getaddrinfo(server->hostname, str_port, &hints, &ai); + if (e != 0) { WATCHPOINT_STRING(server->hostname); - WATCHPOINT_STRING(hstrerror(h_errno)); + WATCHPOINT_STRING(gai_strerror(e)); return MEMCACHED_HOST_LOOKUP_FAILURE; } -#endif - - server->servAddr.sin_family= h->h_addrtype; - memcpy((char *) &server->servAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length); - server->servAddr.sin_port = htons(server->port); + if (server->address_info) + freeaddrinfo(server->address_info); + server->address_info= ai; return MEMCACHED_SUCCESS; } @@ -73,6 +70,7 @@ test_connect: case EISCONN: /* We were spinning waiting on connect */ break; default: + WATCHPOINT_ERRNO(errno); ptr->cached_errno= errno; return MEMCACHED_ERRNO; } @@ -122,6 +120,7 @@ static memcached_return tcp_connect(memcached_st *ptr, unsigned int server_key) { /* Old connection junk still is in the structure */ WATCHPOINT_ASSERT(ptr->hosts[server_key].stack_responses == 0); + struct addrinfo *use; if (ptr->hosts[server_key].sockaddr_inited == MEMCACHED_NOT_ALLOCATED || (!(ptr->flags & MEM_USE_CACHE_LOOKUPS))) @@ -133,9 +132,12 @@ static memcached_return tcp_connect(memcached_st *ptr, unsigned int server_key) return rc; ptr->hosts[server_key].sockaddr_inited= MEMCACHED_ALLOCATED; } + use= ptr->hosts[server_key].address_info; /* Create the socket */ - if ((ptr->hosts[server_key].fd= socket(AF_INET, SOCK_STREAM, 0)) < 0) + if ((ptr->hosts[server_key].fd= socket(use->ai_family, + use->ai_socktype, + use->ai_protocol)) < 0) { ptr->cached_errno= errno; return MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE; @@ -174,8 +176,8 @@ static memcached_return tcp_connect(memcached_st *ptr, unsigned int server_key) /* connect to server */ test_connect: if (connect(ptr->hosts[server_key].fd, - (struct sockaddr *)&ptr->hosts[server_key].servAddr, - sizeof(struct sockaddr)) < 0) + use->ai_addr, + use->ai_addrlen) < 0) { switch (errno) { /* We are spinning waiting on connect */ @@ -187,6 +189,7 @@ test_connect: break; default: ptr->cached_errno= errno; + WATCHPOINT_ERRNO(ptr->cached_errno); return MEMCACHED_ERRNO; } ptr->connected++; diff --git a/lib/memcached_hash.c b/lib/memcached_hash.c index 95d7f862..3ea5df97 100644 --- a/lib/memcached_hash.c +++ b/lib/memcached_hash.c @@ -86,7 +86,7 @@ unsigned int memcached_generate_hash(memcached_st *ptr, char *key, size_t key_le WATCHPOINT_ASSERT(hash); - if (ptr->distribution == MEMCACHED_DISTRIBUTION_MODULUS) + if (ptr->distribution == MEMCACHED_DISTRIBUTION_MODULO) { return hash % ptr->number_of_hosts; } diff --git a/lib/memcached_hosts.c b/lib/memcached_hosts.c index 3517d824..402018b4 100644 --- a/lib/memcached_hosts.c +++ b/lib/memcached_hosts.c @@ -186,8 +186,14 @@ unsigned int memcached_server_list_count(memcached_server_st *ptr) void memcached_server_list_free(memcached_server_st *ptr) { + unsigned int x; + if (ptr == NULL) return; + for (x= 0; x < ptr->count; x++) + if (ptr[x].address_info) + freeaddrinfo(ptr[x].address_info); + free(ptr); } diff --git a/lib/memcached_io.c b/lib/memcached_io.c index 973ccf95..8a05ddb8 100644 --- a/lib/memcached_io.c +++ b/lib/memcached_io.c @@ -152,7 +152,7 @@ ssize_t memcached_io_flush(memcached_st *ptr, unsigned int server_key) { sent_length= sendto(ptr->hosts[server_key].fd, write_ptr, write_length, 0, - (struct sockaddr *)&ptr->hosts[server_key].servAddr, + (struct sockaddr *)&ptr->hosts[server_key].address_info->ai_addr, sizeof(struct sockaddr)); } else diff --git a/tests/function.c b/tests/function.c index c42cc82b..c3d764c4 100644 --- a/tests/function.c +++ b/tests/function.c @@ -112,6 +112,7 @@ uint8_t set_test(memcached_st *memc) rc= memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint16_t)0); + WATCHPOINT_ERROR(rc); assert(rc == MEMCACHED_SUCCESS); return 0; -- 2.30.2