From 7cbcd28d0e2958df0572d965996a65e22b18e66a Mon Sep 17 00:00:00 2001 From: Date: Tue, 18 Sep 2007 07:36:24 +0200 Subject: [PATCH] memcached_server_add() now works so you can connect to host other then localhost. More error checking on failures (and failures cascading properly). --- include/memcached.h | 11 +++- lib/Makefile.am | 1 + lib/memcached.c | 45 +++++----------- lib/memcached_connect.c | 110 ++++++++++++++++++++++++++++++---------- lib/memcached_delete.c | 26 ++++++++++ lib/memcached_get.c | 3 ++ lib/memcached_stats.c | 5 +- lib/memcached_storage.c | 3 ++ 8 files changed, 142 insertions(+), 62 deletions(-) create mode 100644 lib/memcached_delete.c diff --git a/include/memcached.h b/include/memcached.h index a798fef0..9ab209d3 100644 --- a/include/memcached.h +++ b/include/memcached.h @@ -22,6 +22,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -29,6 +30,7 @@ extern "C" { typedef struct memcached_st memcached_st; typedef struct memcached_stat_st memcached_stat_st; +typedef struct memcached_host_st memcached_host_st; #define MEMCACHED_DEFAULT_PORT 11211 #define MEMCACHED_DEFAULT_COMMAND_SIZE 350 @@ -60,6 +62,12 @@ typedef enum { MEMCACHED_ALLOCATED= 1, } memcached_allocated; +struct memcached_host_st { + char *hostname; + unsigned int port; + memcached_host_st *next; +}; + struct memcached_stat_st { unsigned int pid; unsigned int uptime; @@ -93,6 +101,7 @@ struct memcached_st { memcached_allocated is_allocated; int fd; char connected; + memcached_host_st *hosts; }; /* Public API */ @@ -128,7 +137,7 @@ char *memcached_get(memcached_st *ptr, char *key, size_t key_length, size_t *value_length, uint16_t *flags, memcached_return *error); -void memcached_server_add(memcached_st *ptr, char *server_name, unsigned int port); +memcached_return memcached_server_add(memcached_st *ptr, char *hostname, unsigned int port); char *memcached_strerror(memcached_st *ptr, memcached_return rc); /* These are all private, do not use. */ diff --git a/lib/Makefile.am b/lib/Makefile.am index 8be9da86..9cd6688f 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -7,4 +7,5 @@ libmemcached_la_SOURCES = memcached.c \ memcached_response.c \ memcached_get.c \ memcached_storage.c \ + memcached_delete.c \ memcached_stats.c diff --git a/lib/memcached.c b/lib/memcached.c index 1ceee008..944e0f43 100644 --- a/lib/memcached.c +++ b/lib/memcached.c @@ -24,36 +24,6 @@ memcached_st *memcached_init(memcached_st *ptr) return ptr; } -void memcached_server_add(memcached_st *ptr, char *server_name, unsigned int port) -{ -} - - -memcached_return memcached_delete(memcached_st *ptr, char *key, size_t key_length, - time_t expiration) -{ - size_t send_length; - memcached_return rc; - char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; - - rc= memcached_connect(ptr); - - if (expiration) - send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, - "delete %.*s %u\r\n", key_length, key, expiration); - else - send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, - "delete %.*s\r\n", key_length, key); - if ((write(ptr->fd, buffer, send_length) == -1)) - { - fprintf(stderr, "failed set on %.*s TCP\n", key_length+1, key); - - return MEMCACHED_WRITE_FAILURE; - } - - return memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE); -} - memcached_return memcached_increment(memcached_st *ptr, char *key, size_t key_length, unsigned int count) { @@ -107,9 +77,22 @@ memcached_return memcached_quit(memcached_st *ptr) void memcached_deinit(memcached_st *ptr) { - if (ptr->fd == -1) + memcached_host_st *host_ptr; + + if (ptr->fd > 0) close(ptr->fd); + for (host_ptr= ptr->hosts; host_ptr;) + { + memcached_host_st *temp; + + temp= host_ptr; + host_ptr= host_ptr->next; + if (temp->hostname) + free(temp->hostname); + free(temp); + } + if (ptr->is_allocated == MEMCACHED_ALLOCATED) free(ptr); else diff --git a/lib/memcached_connect.c b/lib/memcached_connect.c index 8a6acdd7..5b3644a1 100644 --- a/lib/memcached_connect.c +++ b/lib/memcached_connect.c @@ -1,50 +1,104 @@ #include -memcached_return memcached_connect(memcached_st *ptr) +memcached_return memcached_server_add(memcached_st *ptr, char *hostname, unsigned int port) { - int rc; - struct sockaddr_in localAddr, servAddr; - struct hostent *h; - char *server_name= "localhost"; + memcached_host_st *host_ptr, *prev_ptr; - if (ptr->connected) - return MEMCACHED_SUCCESS; + if (!port) + port= MEMCACHED_DEFAULT_PORT; + if (!hostname) + hostname= "localhost"; - if ((h= gethostbyname(server_name)) == NULL) + if (ptr->hosts) + { + for (host_ptr= ptr->hosts; host_ptr; host_ptr= host_ptr->next) + prev_ptr= host_ptr; + host_ptr= (memcached_host_st *)malloc(sizeof(memcached_host_st)); + if (!host_ptr) + return MEMCACHED_MEMORY_ALLOCATION_FAILURE; + prev_ptr->next= host_ptr; + } + else { - fprintf(stderr, "unknown host '%s'\n", server_name); - return MEMCACHED_HOST_LOCKUP_FAILURE; + ptr->hosts= + host_ptr= (memcached_host_st *)malloc(sizeof(memcached_host_st)); + if (!host_ptr) + return MEMCACHED_MEMORY_ALLOCATION_FAILURE; } - 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(MEMCACHED_DEFAULT_PORT); + memset(host_ptr, 0, sizeof(memcached_host_st)); + host_ptr->hostname= (char *)malloc(sizeof(char) * strlen(hostname)); - /* Create the socket */ - if ((ptr->fd= socket(AF_INET, SOCK_STREAM, 0)) < 0) + if (!host_ptr->hostname) { - fprintf(stderr, "cannot open socket"); - return MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE; + free(host_ptr); + return MEMCACHED_MEMORY_ALLOCATION_FAILURE; } + memcpy(host_ptr->hostname, hostname, strlen(hostname)); + host_ptr->port= port; + + return MEMCACHED_SUCCESS; +} +memcached_return memcached_connect(memcached_st *ptr) +{ + struct sockaddr_in localAddr, servAddr; + struct hostent *h; + memcached_host_st *host_ptr; - /* bind any port number */ - localAddr.sin_family = AF_INET; - localAddr.sin_addr.s_addr = htonl(INADDR_ANY); - localAddr.sin_port = htons(0); + if (ptr->connected) + return MEMCACHED_SUCCESS; - if (bind(ptr->fd, (struct sockaddr *) &localAddr, sizeof(localAddr)) < 0) + if (!ptr->hosts) { - fprintf(stderr, "cannot bind port TCP %u\n", MEMCACHED_DEFAULT_PORT); - return(MEMCACHED_CONNECTION_BIND_FAILURE); + memcached_return rc; + rc= memcached_server_add(ptr, NULL, 0); + + if (rc != MEMCACHED_SUCCESS) + return rc; } - /* connect to server */ - if (connect(ptr->fd, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) + + for (host_ptr= ptr->hosts; host_ptr; host_ptr= host_ptr->next) { - fprintf(stderr, "cannot connect to host '%s'\n", server_name); - return MEMCACHED_HOST_LOCKUP_FAILURE; + if ((h= gethostbyname(host_ptr->hostname)) == NULL) + { + fprintf(stderr, "unknown host '%s'\n", host_ptr->hostname); + return MEMCACHED_HOST_LOCKUP_FAILURE; + } + + 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(host_ptr->port); + + /* Create the socket */ + if ((ptr->fd= socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + fprintf(stderr, "cannot open socket"); + return MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE; + } + + + /* bind any port number */ + localAddr.sin_family = AF_INET; + localAddr.sin_addr.s_addr = htonl(INADDR_ANY); + localAddr.sin_port = htons(0); + + if (bind(ptr->fd, (struct sockaddr *) &localAddr, sizeof(localAddr)) < 0) + { + fprintf(stderr, "cannot bind port TCP %u\n", host_ptr->port); + return(MEMCACHED_CONNECTION_BIND_FAILURE); + } + + /* connect to server */ + if (connect(ptr->fd, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) + { + fprintf(stderr, "cannot connect to host '%s' (%u) (error: %s)\n", host_ptr->hostname, + host_ptr->port, + strerror(errno)); + return MEMCACHED_HOST_LOCKUP_FAILURE; + } } ptr->connected= 1; diff --git a/lib/memcached_delete.c b/lib/memcached_delete.c new file mode 100644 index 00000000..98aac143 --- /dev/null +++ b/lib/memcached_delete.c @@ -0,0 +1,26 @@ +#include + +memcached_return memcached_delete(memcached_st *ptr, char *key, size_t key_length, + time_t expiration) +{ + size_t send_length; + memcached_return rc; + char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; + + rc= memcached_connect(ptr); + + if (expiration) + send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, + "delete %.*s %u\r\n", key_length, key, expiration); + else + send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, + "delete %.*s\r\n", key_length, key); + if ((write(ptr->fd, buffer, send_length) == -1)) + { + fprintf(stderr, "failed set on %.*s TCP\n", key_length+1, key); + + return MEMCACHED_WRITE_FAILURE; + } + + return memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE); +} diff --git a/lib/memcached_get.c b/lib/memcached_get.c index ffecba29..1b53b119 100644 --- a/lib/memcached_get.c +++ b/lib/memcached_get.c @@ -11,6 +11,9 @@ char *memcached_get(memcached_st *ptr, char *key, size_t key_length, *error= memcached_connect(ptr); + if (*error != MEMCACHED_SUCCESS) + return NULL; + send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "get %.*s\r\n", key_length, key); if (*error != MEMCACHED_SUCCESS) diff --git a/lib/memcached_stats.c b/lib/memcached_stats.c index 457bdc9c..8fe5c822 100644 --- a/lib/memcached_stats.c +++ b/lib/memcached_stats.c @@ -132,6 +132,9 @@ memcached_return memcached_stat_hostname(memcached_stat_st *stat, char *args, rc= memcached_connect(&memc); + if (rc != MEMCACHED_SUCCESS) + return rc; + if (args) send_length= snprintf(buffer, HUGE_STRING_LEN, "stats %s\r\n", args); @@ -163,13 +166,11 @@ memcached_return memcached_stat_hostname(memcached_stat_st *stat, char *args, for (end_ptr= string_ptr; *end_ptr != ' '; end_ptr++); key= string_ptr; key[(size_t)(end_ptr-string_ptr)]= 0; - printf("Key %s\n", key); string_ptr= end_ptr + 1; for (end_ptr= string_ptr; *end_ptr != '\r'; end_ptr++); value= string_ptr; value[(size_t)(end_ptr-string_ptr)]= 0; - printf("Value %s\n", value); string_ptr= end_ptr + 2; set_data(stat, key, value); } diff --git a/lib/memcached_storage.c b/lib/memcached_storage.c index a40296df..5ed2fd55 100644 --- a/lib/memcached_storage.c +++ b/lib/memcached_storage.c @@ -22,6 +22,9 @@ static memcached_return memcached_send(memcached_st *ptr, rc= memcached_connect(ptr); + if (rc != MEMCACHED_SUCCESS) + return rc; + send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "%s %.*s %u %u %u\r\n", verb, key_length, key, flags, expiration, value_length); -- 2.30.2