From 3bcf5c0efffbf64b6b6eccf140f057d2373fa974 Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Tue, 13 Nov 2007 21:03:08 -0800 Subject: [PATCH] Rework of the server connect so that "hostname" lookup does not occur for each reconnect. Some framework for UDP protocol added. --- .hgignore | 3 ++ ChangeLog | 1 + configure.ac | 2 +- include/memcached.h | 5 +++ lib/memcached_connect.c | 91 ++++++++++++++++++++++++++++++++++------- lib/memcached_hosts.c | 22 +++++++--- lib/memcached_io.c | 42 ++++++++++++------- tests/function.c | 17 ++++++++ 8 files changed, 149 insertions(+), 34 deletions(-) diff --git a/.hgignore b/.hgignore index ff7c01f6..1f6ec646 100644 --- a/.hgignore +++ b/.hgignore @@ -20,3 +20,6 @@ Makefile(.in)?$ # Generated man files \.1$ \.3$ + +# Merged files +\.orig$ diff --git a/ChangeLog b/ChangeLog index bda930f2..3ce19953 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ * Modified increment/decrement functions to return uint64_t values * Fixed bug in cases where zero length keys were provided * Thread cleanup issue in memslap + * No hostname lookup on reconnect 0.8 Mon Nov 5 10:40:41 PST 2007 * Adding support for CRC hash method diff --git a/configure.ac b/configure.ac index 58fac5ba..203f7e91 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ MEMCACHED_LIBRARY_NAME=libmemcached #release versioning MEMCACHED_MAJOR_VERSION=0 -MEMCACHED_MINOR_VERSION=8 +MEMCACHED_MINOR_VERSION=9 MEMCACHED_MICRO_VERSION=0 #API version diff --git a/include/memcached.h b/include/memcached.h index bd056ade..29195de0 100644 --- a/include/memcached.h +++ b/include/memcached.h @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -107,6 +108,7 @@ struct memcached_server_st { char read_buffer[MEMCACHED_MAX_BUFFER]; size_t read_buffer_length; char *read_ptr; + struct sockaddr_in servAddr; memcached_connection type; }; @@ -235,6 +237,9 @@ memcached_result_st *memcached_fetch_result(memcached_st *ptr, #define memcached_server_list(A) A->hosts #define memcached_server_response_count(A,B) A->hosts[B].stack_responses +memcached_return memcached_server_add_udp(memcached_st *ptr, + char *hostname, + unsigned int port); memcached_return memcached_server_add_unix_socket(memcached_st *ptr, char *filename); memcached_return memcached_server_add(memcached_st *ptr, char *hostname, diff --git a/lib/memcached_connect.c b/lib/memcached_connect.c index 025fdf6e..cbf57fdc 100644 --- a/lib/memcached_connect.c +++ b/lib/memcached_connect.c @@ -7,6 +7,22 @@ #include #include +static memcached_return set_hostinfo(memcached_server_st *server) +{ + struct hostent *h; + + if ((h= gethostbyname(server->hostname)) == NULL) + { + return MEMCACHED_HOST_LOCKUP_FAILURE; + } + + 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); + + return MEMCACHED_SUCCESS; +} + static memcached_return unix_socket_connect(memcached_st *ptr, unsigned int server_key) { struct sockaddr_un servAddr; @@ -22,12 +38,14 @@ static memcached_return unix_socket_connect(memcached_st *ptr, unsigned int serv memset(&servAddr, 0, sizeof (struct sockaddr_un)); servAddr.sun_family= AF_UNIX; - strcpy(servAddr.sun_path, ptr->hosts[server_key].hostname); + strcpy(servAddr.sun_path, ptr->hosts[server_key].hostname); /* Copy filename */ addrlen= strlen(servAddr.sun_path) + sizeof(servAddr.sun_family); test_connect: - if (connect(ptr->hosts[server_key].fd, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0) + if (connect(ptr->hosts[server_key].fd, + (struct sockaddr *)&servAddr, + sizeof(servAddr)) < 0) { switch (errno) { /* We are spinning waiting on connect */ @@ -47,25 +65,48 @@ test_connect: return MEMCACHED_SUCCESS; } -static memcached_return tcp_connect(memcached_st *ptr, unsigned int server_key) +static memcached_return udp_connect(memcached_st *ptr, unsigned int server_key) { - struct sockaddr_in servAddr; - struct hostent *h; - if (ptr->hosts[server_key].fd == -1) { /* Old connection junk still is in the structure */ WATCHPOINT_ASSERT(ptr->hosts[server_key].stack_responses == 0); - if ((h= gethostbyname(ptr->hosts[server_key].hostname)) == NULL) + if (ptr->hosts[server_key].servAddr.sin_family == 0) { - ptr->cached_errno= h_errno; - return MEMCACHED_HOST_LOCKUP_FAILURE; + memcached_return rc; + + rc= set_hostinfo(&ptr->hosts[server_key]); + if (rc != MEMCACHED_SUCCESS) + return rc; } - servAddr.sin_family= h->h_addrtype; - memcpy((char *) &servAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length); - servAddr.sin_port = htons(ptr->hosts[server_key].port); + /* Create the socket */ + if ((ptr->hosts[server_key].fd= socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + ptr->cached_errno= errno; + return MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE; + } + } + + return MEMCACHED_SUCCESS; +} + +static memcached_return tcp_connect(memcached_st *ptr, unsigned int server_key) +{ + if (ptr->hosts[server_key].fd == -1) + { + /* Old connection junk still is in the structure */ + WATCHPOINT_ASSERT(ptr->hosts[server_key].stack_responses == 0); + + if (ptr->hosts[server_key].servAddr.sin_family == 0) + { + memcached_return rc; + + rc= set_hostinfo(&ptr->hosts[server_key]); + if (rc != MEMCACHED_SUCCESS) + return rc; + } /* Create the socket */ if ((ptr->hosts[server_key].fd= socket(AF_INET, SOCK_STREAM, 0)) < 0) @@ -106,7 +147,9 @@ 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 *)&servAddr, sizeof(servAddr)) < 0) + if (connect(ptr->hosts[server_key].fd, + (struct sockaddr *)&ptr->hosts[server_key].servAddr, + sizeof(struct sockaddr)) < 0) { switch (errno) { /* We are spinning waiting on connect */ @@ -142,7 +185,25 @@ memcached_return memcached_connect(memcached_st *ptr, unsigned int server_key) /* We need to clean up the multi startup piece */ if (server_key) + { rc= tcp_connect(ptr, server_key); + switch (ptr->hosts[server_key].type) + { + case MEMCACHED_CONNECTION_UNKNOWN: + WATCHPOINT_ASSERT(0); + rc= MEMCACHED_NOT_SUPPORTED; + break; + case MEMCACHED_CONNECTION_UDP: + rc= udp_connect(ptr, server_key); + break; + case MEMCACHED_CONNECTION_TCP: + rc= tcp_connect(ptr, server_key); + break; + case MEMCACHED_CONNECTION_UNIX_SOCKET: + rc= unix_socket_connect(ptr, server_key); + break; + } + } else { unsigned int x; @@ -156,10 +217,12 @@ memcached_return memcached_connect(memcached_st *ptr, unsigned int server_key) switch (ptr->hosts[x].type) { case MEMCACHED_CONNECTION_UNKNOWN: - case MEMCACHED_CONNECTION_UDP: WATCHPOINT_ASSERT(0); possible_rc= MEMCACHED_NOT_SUPPORTED; break; + case MEMCACHED_CONNECTION_UDP: + possible_rc= udp_connect(ptr, x); + break; case MEMCACHED_CONNECTION_TCP: possible_rc= tcp_connect(ptr, x); break; diff --git a/lib/memcached_hosts.c b/lib/memcached_hosts.c index c77e5583..f16052b3 100644 --- a/lib/memcached_hosts.c +++ b/lib/memcached_hosts.c @@ -9,14 +9,11 @@ static memcached_return server_add(memcached_st *ptr, char *hostname, static void host_reset(memcached_server_st *host, char *new_hostname, unsigned int port, memcached_connection type) { - host->stack_responses= 0; - host->cursor_active= 0; + memset(host, 0, sizeof(memcached_server_st)); host->hostname= new_hostname; host->port= port; host->fd= -1; host->type= type; - host->write_buffer_offset= 0; - host->read_buffer_length= 0; host->read_ptr= host->read_buffer; } @@ -64,7 +61,22 @@ memcached_return memcached_server_add_unix_socket(memcached_st *ptr, char *filen return server_add(ptr, filename, 0, MEMCACHED_CONNECTION_UNIX_SOCKET); } -memcached_return memcached_server_add(memcached_st *ptr, char *hostname, unsigned int port) +memcached_return memcached_server_add_udp(memcached_st *ptr, + char *hostname, + unsigned int port) +{ + if (!port) + port= MEMCACHED_DEFAULT_PORT; + + if (!hostname) + hostname= "localhost"; + + return server_add(ptr, hostname, port, MEMCACHED_CONNECTION_UDP); +} + +memcached_return memcached_server_add(memcached_st *ptr, + char *hostname, + unsigned int port) { if (!port) port= MEMCACHED_DEFAULT_PORT; diff --git a/lib/memcached_io.c b/lib/memcached_io.c index 473b8881..c0215ac0 100644 --- a/lib/memcached_io.c +++ b/lib/memcached_io.c @@ -140,24 +140,38 @@ ssize_t memcached_io_flush(memcached_st *ptr, unsigned int server_key) } sent_length= 0; - if ((ssize_t)(sent_length= write(ptr->hosts[server_key].fd, write_ptr, - write_length)) == -1) + if (ptr->hosts[server_key].type == MEMCACHED_CONNECTION_UDP) { - switch (errno) + + sent_length= sendto(ptr->hosts[server_key].fd, write_ptr, write_length, + 0, 0, 0); + /* + rc = sendto(sd, argv[i], strlen(argv[i])+1, 0, + (struct sockaddr *) &remoteServAddr, + sizeof(remoteServAddr)); + */ + } + else + { + if ((ssize_t)(sent_length= write(ptr->hosts[server_key].fd, write_ptr, + write_length)) == -1) { - case ENOBUFS: - case EAGAIN: - WATCHPOINT; - continue; - if (loop < 100) + switch (errno) { - loop++; - break; + case ENOBUFS: + case EAGAIN: + WATCHPOINT; + continue; + if (loop < 100) + { + loop++; + break; + } + /* Yes, we want to fall through */ + default: + ptr->cached_errno= errno; + return -1; } - /* Yes, we want to fall through */ - default: - ptr->cached_errno= errno; - return -1; } } diff --git a/tests/function.c b/tests/function.c index 1e2c6f07..7d2de703 100644 --- a/tests/function.c +++ b/tests/function.c @@ -1379,6 +1379,22 @@ memcached_return pre_unix_socket(memcached_st *memc) return rc; } +memcached_return pre_udp(memcached_st *memc) +{ + memcached_return rc; + + memcached_server_list_free(memc->hosts); + memc->hosts= NULL; + memc->number_of_hosts= 0; + + if (0) + return MEMCACHED_FAILURE; + + rc= memcached_server_add_udp(memc, "localhost", MEMCACHED_DEFAULT_PORT); + + return rc; +} + memcached_return pre_nodelay(memcached_st *memc) { memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, NULL); @@ -1467,6 +1483,7 @@ collection_st collection[] ={ {"ketama", pre_hash_ketama, 0, tests}, {"unix_socket", pre_unix_socket, 0, tests}, {"unix_socket_nodelay", pre_nodelay, 0, tests}, +// {"udp", pre_udp, 0, tests}, {"string", 0, 0, string_tests}, {"result", 0, 0, result_tests}, {"user", 0, 0, user_tests}, -- 2.30.2