From 1f34771f7ba527e3afb675f1a448d6c5ab66596b Mon Sep 17 00:00:00 2001 From: Date: Tue, 18 Sep 2007 06:14:16 +0200 Subject: [PATCH] Broke library up into multiple files. The single stats server function now returns valid data. --- include/memcached.h | 33 ++++- lib/Makefile.am | 7 +- lib/memcached.c | 313 --------------------------------------- lib/memcached_connect.c | 53 +++++++ lib/memcached_get.c | 94 ++++++++++++ lib/memcached_response.c | 54 +++++++ lib/memcached_stats.c | 182 +++++++++++++++++++++++ lib/memcached_storage.c | 80 ++++++++++ tests/test.c | 10 ++ 9 files changed, 506 insertions(+), 320 deletions(-) create mode 100644 lib/memcached_connect.c create mode 100644 lib/memcached_get.c create mode 100644 lib/memcached_response.c create mode 100644 lib/memcached_stats.c create mode 100644 lib/memcached_storage.c diff --git a/include/memcached.h b/include/memcached.h index a3ecf7e9..a798fef0 100644 --- a/include/memcached.h +++ b/include/memcached.h @@ -10,7 +10,17 @@ #ifndef __MEMCACHED_H__ #define __MEMCACHED_H__ +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #ifdef __cplusplus @@ -22,6 +32,7 @@ typedef struct memcached_stat_st memcached_stat_st; #define MEMCACHED_DEFAULT_PORT 11211 #define MEMCACHED_DEFAULT_COMMAND_SIZE 350 +#define HUGE_STRING_LEN 8196 typedef enum { MEMCACHED_SUCCESS, @@ -52,11 +63,15 @@ typedef enum { struct memcached_stat_st { unsigned int pid; unsigned int uptime; + unsigned int threads; time_t time; - char *version; - unsigned rusage_user_seconds; + char version[8]; + unsigned int pointer_size; + unsigned int rusage_user; + unsigned int rusage_system; + unsigned int rusage_user_seconds; unsigned int rusage_user_microseconds; - unsigned rusage_system_seconds; + unsigned int rusage_system_seconds; unsigned int rusage_system_microseconds; unsigned int curr_items; unsigned int total_items; @@ -102,7 +117,9 @@ memcached_return memcached_increment(memcached_st *ptr, char *key, size_t key_le unsigned int count); memcached_return memcached_decrement(memcached_st *ptr, char *key, size_t key_length, unsigned int count); -memcached_return memcached_stat(memcached_st *ptr, memcached_stat_st *stat); +memcached_stat_st **memcached_stat(memcached_st *ptr, memcached_return *error); +memcached_return memcached_stat_hostname(memcached_stat_st *stat, char *args, + char *hostname, unsigned int port); memcached_return memcached_flush(memcached_st *ptr, time_t expiration); char *memcached_version(memcached_st *ptr, memcached_return *error); memcached_return memcached_verbosity(memcached_st *ptr, unsigned int verbosity); @@ -112,10 +129,14 @@ char *memcached_get(memcached_st *ptr, char *key, size_t key_length, uint16_t *flags, memcached_return *error); void memcached_server_add(memcached_st *ptr, char *server_name, unsigned int port); -static memcached_return memcached_response(memcached_st *ptr, - char *buffer, size_t buffer_length); char *memcached_strerror(memcached_st *ptr, memcached_return rc); +/* These are all private, do not use. */ +memcached_return memcached_connect(memcached_st *ptr); +memcached_return memcached_response(memcached_st *ptr, + char *buffer, + size_t buffer_length); + #ifdef __cplusplus } #endif diff --git a/lib/Makefile.am b/lib/Makefile.am index 0b201b09..8be9da86 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -2,4 +2,9 @@ INCLUDES = -I$(top_builddir)/include LIBS = lib_LTLIBRARIES = libmemcached.la -libmemcached_la_SOURCES = memcached.c +libmemcached_la_SOURCES = memcached.c \ + memcached_connect.c \ + memcached_response.c \ + memcached_get.c \ + memcached_storage.c \ + memcached_stats.c diff --git a/lib/memcached.c b/lib/memcached.c index 8bd6589b..1ceee008 100644 --- a/lib/memcached.c +++ b/lib/memcached.c @@ -2,18 +2,6 @@ Memcached library */ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - memcached_st *memcached_init(memcached_st *ptr) { @@ -40,174 +28,6 @@ void memcached_server_add(memcached_st *ptr, char *server_name, unsigned int por { } -static memcached_return memcached_connect(memcached_st *ptr) -{ - int rc; - struct sockaddr_in localAddr, servAddr; - struct hostent *h; - char *server_name= "localhost"; - - if (ptr->connected) - return MEMCACHED_SUCCESS; - - - if ((h= gethostbyname(server_name)) == NULL) - { - fprintf(stderr, "unknown host '%s'\n", server_name); - 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(MEMCACHED_DEFAULT_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", MEMCACHED_DEFAULT_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'\n", server_name); - return MEMCACHED_HOST_LOCKUP_FAILURE; - } - - ptr->connected= 1; - - return MEMCACHED_SUCCESS; -} - -static memcached_return memcached_response(memcached_st *ptr, - char *buffer, size_t buffer_length) -{ - size_t send_length; - send_length= read(ptr->fd, buffer, buffer_length); - - /* This should never happen, if it does it means that key must now be quite large. */ - assert(send_length != buffer_length); - - if (send_length) - switch(buffer[0]) - { - case 'V': /* VALUE */ - return MEMCACHED_SUCCESS; - case 'O': /* OK */ - return MEMCACHED_SUCCESS; - case 'S': /* STORED */ - { - if (buffer[1] == 'T') - return MEMCACHED_SUCCESS; - else if (buffer[1] == 'E') - return MEMCACHED_SERVER_ERROR; - else - return MEMCACHED_UNKNOWN_READ_FAILURE; - } - case 'D': /* DELETED */ - return MEMCACHED_SUCCESS; - case 'N': /* NOT_FOUND */ - { - if (buffer[4] == 'F') - return MEMCACHED_NOTFOUND; - else if (buffer[4] == 'S') - return MEMCACHED_NOTSTORED; - else - return MEMCACHED_UNKNOWN_READ_FAILURE; - } - case 'E': /* PROTOCOL ERROR */ - return MEMCACHED_PROTOCOL_ERROR; - case 'C': /* CLIENT ERROR */ - return MEMCACHED_CLIENT_ERROR; - default: - return MEMCACHED_UNKNOWN_READ_FAILURE; - } - - return MEMCACHED_READ_FAILURE; -} - -static memcached_return memcached_send(memcached_st *ptr, - char *key, size_t key_length, - char *value, size_t value_length, - time_t expiration, - uint16_t flags, - char *verb) -{ - size_t send_length; - memcached_return rc; - char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; - - rc= memcached_connect(ptr); - - send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, - "%s %.*s %u %u %u\r\n", verb, - key_length, key, flags, expiration, value_length); - if ((send(ptr->fd, buffer, send_length, 0) == -1)) - { - fprintf(stderr, "failed set on %.*s TCP\n", key_length+1, key); - - return MEMCACHED_WRITE_FAILURE; - } - - send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, - "%.*s\r\n", - value_length, value); - if ((send(ptr->fd, buffer, send_length, 0) == -1)) - { - fprintf(stderr, "failed set on %.*s TCP\n", key_length+1, key); - - return MEMCACHED_WRITE_FAILURE; - } - - send_length= read(ptr->fd, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE); - - if (send_length && buffer[0] == 'S') /* STORED */ - return MEMCACHED_SUCCESS; - else if (send_length && buffer[0] == 'N') /* NOT_STORED */ - return MEMCACHED_NOTSTORED; - else - return MEMCACHED_READ_FAILURE; -} - -memcached_return memcached_set(memcached_st *ptr, char *key, size_t key_length, - char *value, size_t value_length, - time_t expiration, - uint16_t flags) -{ - return memcached_send(ptr, key, key_length, value, value_length, - expiration, flags, "set"); -} - -memcached_return memcached_add(memcached_st *ptr, char *key, size_t key_length, - char *value, size_t value_length, - time_t expiration, - uint16_t flags) -{ - return memcached_send(ptr, key, key_length, value, value_length, - expiration, flags, "add"); -} - -memcached_return memcached_replace(memcached_st *ptr, char *key, size_t key_length, - char *value, size_t value_length, - time_t expiration, - uint16_t flags) -{ - return memcached_send(ptr, key, key_length, value, value_length, - expiration, flags, "replace"); -} memcached_return memcached_delete(memcached_st *ptr, char *key, size_t key_length, time_t expiration) @@ -246,45 +66,6 @@ memcached_return memcached_decrement(memcached_st *ptr, char *key, size_t key_le return MEMCACHED_SUCCESS; } -memcached_return memcached_stat(memcached_st *ptr, memcached_stat_st *stat) -{ - size_t send_length; - memcached_return rc; - char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; - - rc= memcached_connect(ptr); - - send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, - "stats \r\n"); - if ((send(ptr->fd, buffer, send_length, 0) == -1)) - { - fprintf(stderr, "failed on stats\n"); - - return MEMCACHED_WRITE_FAILURE; - } - - while((send_length= read(ptr->fd, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE)) > 0) - { - if (send_length && buffer[0] == 'D') /* DELETED */ - return MEMCACHED_SUCCESS; - else if (send_length && buffer[0] == 'N') /* NOT FOUND */ - return MEMCACHED_NOTFOUND; - else if (send_length && buffer[0] == 'E') /* PROTOCOL ERROR */ - return MEMCACHED_PROTOCOL_ERROR; - else if (send_length && buffer[0] == 'C') /* CLIENT ERROR */ - return MEMCACHED_CLIENT_ERROR; - else if (send_length && buffer[0] == 'S') /* SERVER ERROR */ - return MEMCACHED_SERVER_ERROR; - else if (send_length) /* UNKNOWN READ FAILURE */ - { - fprintf(stderr, "UNKNOWN %.*s\n", send_length, buffer); - return MEMCACHED_UNKNOWN_READ_FAILURE; - } - else - return MEMCACHED_READ_FAILURE; - } -} - memcached_return memcached_flush(memcached_st *ptr, time_t expiration) { size_t send_length; @@ -324,100 +105,6 @@ memcached_return memcached_quit(memcached_st *ptr) return MEMCACHED_SUCCESS; } - -char *memcached_get(memcached_st *ptr, char *key, size_t key_length, - size_t *value_length, - uint16_t *flags, - memcached_return *error) -{ - size_t send_length; - char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; - char *string_ptr; - - *error= memcached_connect(ptr); - - send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "get %.*s\r\n", - key_length, key); - if (*error != MEMCACHED_SUCCESS) - return NULL; - - if ((send(ptr->fd, buffer, send_length, 0) == -1)) - { - fprintf(stderr, "failed fetch on %.*s TCP\n", key_length+1, key); - *error= MEMCACHED_WRITE_FAILURE; - return NULL; - } - - memset(buffer, 0, MEMCACHED_DEFAULT_COMMAND_SIZE); - *error= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE); - - if (*error == MEMCACHED_SUCCESS) - { - char *end_ptr; - - string_ptr= buffer; - string_ptr+= 6; /* "VALUE " */ - - /* We do nothing with the key, since we only asked for one key */ - for (end_ptr= string_ptr; *end_ptr != ' '; end_ptr++); - - /* Flags fetch */ - string_ptr= end_ptr + 1; - for (end_ptr= string_ptr; *end_ptr != ' '; end_ptr++); - *flags= (uint16_t)strtol(string_ptr, &end_ptr, 10); - - /* Length fetch */ - string_ptr= end_ptr + 1; - for (end_ptr= string_ptr; *end_ptr != ' '; end_ptr++); - *value_length= strtoll(string_ptr, &end_ptr, 10); - - /* Skip past the \r\n */ - string_ptr= end_ptr +2; - - if (*value_length) - { - size_t need_to_copy; - char *pos_ptr; - char *value; - - value= (char *)malloc(*value_length * sizeof(char)); - - if (!value) - { - *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE; - return NULL; - } - - need_to_copy= (*value_length < (size_t)(buffer-string_ptr)) - ? *value_length - : (size_t)(buffer-string_ptr) ; - - pos_ptr= memcpy(value, string_ptr, need_to_copy); - - if ( need_to_copy > *value_length) - { - size_t read_length; - size_t need_to_read; - - need_to_read= *value_length - need_to_copy; - - read_length= read(ptr->fd, pos_ptr, need_to_read); - if (read_length != need_to_read) - { - free(value); - *error= MEMCACHED_PARTIAL_READ; - - return NULL; - } - } - - return value; - } - } - - return NULL; -} - void memcached_deinit(memcached_st *ptr) { if (ptr->fd == -1) diff --git a/lib/memcached_connect.c b/lib/memcached_connect.c new file mode 100644 index 00000000..8a6acdd7 --- /dev/null +++ b/lib/memcached_connect.c @@ -0,0 +1,53 @@ +#include + +memcached_return memcached_connect(memcached_st *ptr) +{ + int rc; + struct sockaddr_in localAddr, servAddr; + struct hostent *h; + char *server_name= "localhost"; + + if (ptr->connected) + return MEMCACHED_SUCCESS; + + + if ((h= gethostbyname(server_name)) == NULL) + { + fprintf(stderr, "unknown host '%s'\n", server_name); + 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(MEMCACHED_DEFAULT_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", MEMCACHED_DEFAULT_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'\n", server_name); + return MEMCACHED_HOST_LOCKUP_FAILURE; + } + + ptr->connected= 1; + + return MEMCACHED_SUCCESS; +} diff --git a/lib/memcached_get.c b/lib/memcached_get.c new file mode 100644 index 00000000..ffecba29 --- /dev/null +++ b/lib/memcached_get.c @@ -0,0 +1,94 @@ +#include + +char *memcached_get(memcached_st *ptr, char *key, size_t key_length, + size_t *value_length, + uint16_t *flags, + memcached_return *error) +{ + size_t send_length; + char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; + char *string_ptr; + + *error= memcached_connect(ptr); + + send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "get %.*s\r\n", + key_length, key); + if (*error != MEMCACHED_SUCCESS) + return NULL; + + if ((send(ptr->fd, buffer, send_length, 0) == -1)) + { + fprintf(stderr, "failed fetch on %.*s TCP\n", key_length+1, key); + *error= MEMCACHED_WRITE_FAILURE; + return NULL; + } + + memset(buffer, 0, MEMCACHED_DEFAULT_COMMAND_SIZE); + *error= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE); + + if (*error == MEMCACHED_SUCCESS) + { + char *end_ptr; + + string_ptr= buffer; + string_ptr+= 6; /* "VALUE " */ + + /* We do nothing with the key, since we only asked for one key */ + for (end_ptr= string_ptr; *end_ptr != ' '; end_ptr++); + + /* Flags fetch */ + string_ptr= end_ptr + 1; + for (end_ptr= string_ptr; *end_ptr != ' '; end_ptr++); + *flags= (uint16_t)strtol(string_ptr, &end_ptr, 10); + + /* Length fetch */ + string_ptr= end_ptr + 1; + for (end_ptr= string_ptr; *end_ptr != ' '; end_ptr++); + *value_length= strtoll(string_ptr, &end_ptr, 10); + + /* Skip past the \r\n */ + string_ptr= end_ptr +2; + + if (*value_length) + { + size_t need_to_copy; + char *pos_ptr; + char *value; + + value= (char *)malloc(*value_length * sizeof(char)); + + if (!value) + { + *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE; + return NULL; + } + + need_to_copy= (*value_length < (size_t)(buffer-string_ptr)) + ? *value_length + : (size_t)(buffer-string_ptr) ; + + pos_ptr= memcpy(value, string_ptr, need_to_copy); + + if ( need_to_copy > *value_length) + { + size_t read_length; + size_t need_to_read; + + need_to_read= *value_length - need_to_copy; + + read_length= read(ptr->fd, pos_ptr, need_to_read); + if (read_length != need_to_read) + { + free(value); + *error= MEMCACHED_PARTIAL_READ; + + return NULL; + } + } + + return value; + } + } + + return NULL; +} diff --git a/lib/memcached_response.c b/lib/memcached_response.c new file mode 100644 index 00000000..09d1fa4d --- /dev/null +++ b/lib/memcached_response.c @@ -0,0 +1,54 @@ +/* + Memcached library + + memcached_response() is used to determine the return result + from an issued command. +*/ + +#include + +memcached_return memcached_response(memcached_st *ptr, + char *buffer, size_t buffer_length) +{ + size_t send_length; + + memset(buffer, 0, buffer_length); + send_length= read(ptr->fd, buffer, buffer_length); + + if (send_length) + switch(buffer[0]) + { + case 'V': /* VALUE */ + return MEMCACHED_SUCCESS; + case 'O': /* OK */ + return MEMCACHED_SUCCESS; + case 'S': /* STORED STATS SERVER_ERROR */ + { + if (buffer[1] == 'T') /* STORED STATS */ + return MEMCACHED_SUCCESS; + else if (buffer[1] == 'E') + return MEMCACHED_SERVER_ERROR; + else + return MEMCACHED_UNKNOWN_READ_FAILURE; + } + case 'D': /* DELETED */ + return MEMCACHED_SUCCESS; + case 'N': /* NOT_FOUND */ + { + if (buffer[4] == 'F') + return MEMCACHED_NOTFOUND; + else if (buffer[4] == 'S') + return MEMCACHED_NOTSTORED; + else + return MEMCACHED_UNKNOWN_READ_FAILURE; + } + case 'E': /* PROTOCOL ERROR */ + return MEMCACHED_PROTOCOL_ERROR; + case 'C': /* CLIENT ERROR */ + return MEMCACHED_CLIENT_ERROR; + default: + return MEMCACHED_UNKNOWN_READ_FAILURE; + } + + return MEMCACHED_READ_FAILURE; +} diff --git a/lib/memcached_stats.c b/lib/memcached_stats.c new file mode 100644 index 00000000..457bdc9c --- /dev/null +++ b/lib/memcached_stats.c @@ -0,0 +1,182 @@ +/* +*/ + +#include + +static void set_data(memcached_stat_st *stat, char *key, char *value) +{ + if (!memcmp("pid", key, strlen("pid"))) + { + stat->pid= strtol(value, (char **)NULL, 10); + } + else if (!memcmp("uptime", key, strlen("uptime"))) + { + stat->uptime= strtol(value, (char **)NULL, 10); + } + else if (!memcmp("time", key, strlen("time"))) + { + stat->time= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("version", key, strlen("version"))) + { + memcpy(stat->version, value, 8); + } + else if (!memcmp("pointer_size", key, strlen("pointer_size"))) + { + stat->pointer_size= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("rusage_user", key, strlen("rusage_user"))) + { + stat->rusage_user= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("rusage_system", key, strlen("rusage_system"))) + { + stat->rusage_system= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("rusage_user_seconds", key, strlen("rusage_user_seconds"))) + { + stat->rusage_user_seconds= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("rusage_user_microseconds", key, strlen("rusage_user_microseconds"))) + { + stat->rusage_user_microseconds= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("rusage_system_seconds", key, strlen("rusage_system_seconds"))) + { + stat->rusage_system_seconds= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("rusage_system_microseconds", key, strlen("rusage_system_microseconds"))) + { + stat->rusage_system_microseconds= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("curr_items", key, strlen("curr_items"))) + { + stat->curr_items= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("total_items", key, strlen("total_items"))) + { + stat->total_items= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("bytes", key, strlen("bytes"))) + { + stat->bytes= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("curr_connections", key, strlen("curr_connections"))) + { + stat->curr_connections= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("total_connections", key, strlen("total_connections"))) + { + stat->total_connections= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("connection_structures", key, strlen("connection_structures"))) + { + stat->connection_structures= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("cmd_get", key, strlen("cmd_get"))) + { + stat->cmd_get= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("cmd_set", key, strlen("cmd_set"))) + { + stat->cmd_set= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("get_hits", key, strlen("get_hits"))) + { + stat->get_hits= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("get_misses", key, strlen("get_misses"))) + { + stat->get_misses= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("evictions", key, strlen("evictions"))) + { + stat->evictions= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("bytes_read", key, strlen("bytes_read"))) + { + stat->bytes_read= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("bytes_written", key, strlen("bytes_written"))) + { + stat->bytes_written= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("limit_maxbytes", key, strlen("limit_maxbytes"))) + { + stat->limit_maxbytes= strtoll(value, (char **)NULL, 10); + } + else if (!memcmp("threads", key, strlen("threads"))) + { + stat->threads= strtol(key, (char **)NULL, 10); + } + else + { + fprintf(stderr, "Unknown key %s\n", key); + } +} + +memcached_stat_st **memcached_stat(memcached_st *ptr, memcached_return *error) +{ + return NULL; +} + +memcached_return memcached_stat_hostname(memcached_stat_st *stat, char *args, + char *hostname, unsigned int port) +{ + size_t send_length; + memcached_return rc; + char buffer[HUGE_STRING_LEN]; + memcached_st memc; + + memcached_init(&memc); + + rc= memcached_connect(&memc); + + if (args) + send_length= snprintf(buffer, HUGE_STRING_LEN, + "stats %s\r\n", args); + else + send_length= snprintf(buffer, HUGE_STRING_LEN, + "stats\r\n"); + + if ((send(memc.fd, buffer, send_length, 0) == -1)) + { + fprintf(stderr, "failed on stats\n"); + + rc= MEMCACHED_WRITE_FAILURE; + goto error; + } + + rc= memcached_response(&memc, buffer, HUGE_STRING_LEN); + + if (rc == MEMCACHED_SUCCESS) + { + char *string_ptr, *end_ptr; + char *key, *value; + + string_ptr= buffer; + while (1) + { + if (memcmp(string_ptr, "STAT ", 5)) + break; + string_ptr+= 5; + 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); + } + } + +error: + memcached_deinit(&memc); + + return rc; +} diff --git a/lib/memcached_storage.c b/lib/memcached_storage.c new file mode 100644 index 00000000..a40296df --- /dev/null +++ b/lib/memcached_storage.c @@ -0,0 +1,80 @@ +/* + Memcached library + + memcached_set() + memcached_replace() + memcached_add() + +*/ + +#include + +static memcached_return memcached_send(memcached_st *ptr, + char *key, size_t key_length, + char *value, size_t value_length, + time_t expiration, + uint16_t flags, + char *verb) +{ + size_t send_length; + memcached_return rc; + char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; + + rc= memcached_connect(ptr); + + send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, + "%s %.*s %u %u %u\r\n", verb, + key_length, key, flags, expiration, value_length); + if ((send(ptr->fd, buffer, send_length, 0) == -1)) + { + fprintf(stderr, "failed set on %.*s TCP\n", key_length+1, key); + + return MEMCACHED_WRITE_FAILURE; + } + + send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, + "%.*s\r\n", + value_length, value); + if ((send(ptr->fd, buffer, send_length, 0) == -1)) + { + fprintf(stderr, "failed set on %.*s TCP\n", key_length+1, key); + + return MEMCACHED_WRITE_FAILURE; + } + + send_length= read(ptr->fd, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE); + + if (send_length && buffer[0] == 'S') /* STORED */ + return MEMCACHED_SUCCESS; + else if (send_length && buffer[0] == 'N') /* NOT_STORED */ + return MEMCACHED_NOTSTORED; + else + return MEMCACHED_READ_FAILURE; +} + +memcached_return memcached_set(memcached_st *ptr, char *key, size_t key_length, + char *value, size_t value_length, + time_t expiration, + uint16_t flags) +{ + return memcached_send(ptr, key, key_length, value, value_length, + expiration, flags, "set"); +} + +memcached_return memcached_add(memcached_st *ptr, char *key, size_t key_length, + char *value, size_t value_length, + time_t expiration, + uint16_t flags) +{ + return memcached_send(ptr, key, key_length, value, value_length, + expiration, flags, "add"); +} + +memcached_return memcached_replace(memcached_st *ptr, char *key, size_t key_length, + char *value, size_t value_length, + time_t expiration, + uint16_t flags) +{ + return memcached_send(ptr, key, key_length, value, value_length, + expiration, flags, "replace"); +} diff --git a/tests/test.c b/tests/test.c index 4948c70a..2edcacd2 100644 --- a/tests/test.c +++ b/tests/test.c @@ -167,6 +167,15 @@ void get_test2(void) memcached_deinit(memc); } +void stats_hostname_test(void) +{ + memcached_return rc; + memcached_stat_st stat; + rc= memcached_stat_hostname(&stat, NULL, + "localhost", + MEMCACHED_DEFAULT_PORT); +} + int main(void) { /* Clean the server before beginning testing */ @@ -182,6 +191,7 @@ int main(void) flush_test(); get_test(); get_test2(); + stats_hostname_test(); /* Clean up whatever we might have left */ flush_test(); -- 2.30.2