From: Jean-Charles Redoutey Date: Sat, 10 Oct 2009 11:57:03 +0000 (+0200) Subject: Added reviewed version of memcached_server_get_last_disconnect X-Git-Tag: 0.34~6^2~1 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=e275a4d2b7f216c240eee6ee811ba1546642ea5e;p=m6w6%2Flibmemcached Added reviewed version of memcached_server_get_last_disconnect --- diff --git a/docs/memcached_servers.pod b/docs/memcached_servers.pod index 125e1f4b..a4495382 100644 --- a/docs/memcached_servers.pod +++ b/docs/memcached_servers.pod @@ -1,6 +1,6 @@ =head1 NAME -memcached_server_count, memcached_server_list, memcached_server_add, memcached_server_push - Manage server list +memcached_server_count, memcached_server_list, memcached_server_add, memcached_server_push, memcached_server_get_last_disconnect - Manage server list =head1 LIBRARY @@ -37,6 +37,9 @@ C Client Library for memcached (libmemcached, -lmemcached) memcached_server_by_key (memcached_st *ptr, const char *key, size_t key_length, memcached_return *error); + memcached_server_st * + memcached_server_get_last_disconnect (memcached_st *ptr) + =head1 DESCRIPTION @@ -81,6 +84,11 @@ 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(). +memcached_server_get_last_disconnect() returns a pointer to the last server +for which there was a connection problem. It does not mean this particular +server is currently dead but if the library is reporting a server is, +the returned server is a very good candidate. + =head1 RETURN Varies, see particular functions. diff --git a/libmemcached/memcached.h b/libmemcached/memcached.h index 5068f98b..08c66a2c 100644 --- a/libmemcached/memcached.h +++ b/libmemcached/memcached.h @@ -80,6 +80,7 @@ struct memcached_st { uint8_t hash; uint32_t continuum_points_counter; memcached_server_st *hosts; + memcached_server_st *last_disconnected_server; int32_t snd_timeout; int32_t rcv_timeout; uint32_t server_failure_limit; @@ -133,12 +134,12 @@ LIBMEMCACHED_API memcached_return memcached_delete(memcached_st *ptr, const char *key, size_t key_length, time_t expiration); LIBMEMCACHED_API -memcached_return memcached_increment(memcached_st *ptr, +memcached_return memcached_increment(memcached_st *ptr, const char *key, size_t key_length, uint32_t offset, uint64_t *value); LIBMEMCACHED_API -memcached_return memcached_decrement(memcached_st *ptr, +memcached_return memcached_decrement(memcached_st *ptr, const char *key, size_t key_length, uint32_t offset, uint64_t *value); @@ -163,7 +164,7 @@ void memcached_stat_free(memcached_st *, memcached_stat_st *); LIBMEMCACHED_API memcached_stat_st *memcached_stat(memcached_st *ptr, char *args, memcached_return *error); LIBMEMCACHED_API -memcached_return memcached_stat_servername(memcached_stat_st *memc_stat, char *args, +memcached_return memcached_stat_servername(memcached_stat_st *memc_stat, char *args, char *hostname, unsigned int port); LIBMEMCACHED_API memcached_return memcached_flush(memcached_st *ptr, time_t expiration); @@ -190,27 +191,27 @@ memcached_return memcached_flush_buffers(memcached_st *mem); /* Server Public functions */ LIBMEMCACHED_API -memcached_return memcached_server_add_udp(memcached_st *ptr, +memcached_return memcached_server_add_udp(memcached_st *ptr, const char *hostname, unsigned int port); LIBMEMCACHED_API -memcached_return memcached_server_add_unix_socket(memcached_st *ptr, +memcached_return memcached_server_add_unix_socket(memcached_st *ptr, const char *filename); LIBMEMCACHED_API -memcached_return memcached_server_add(memcached_st *ptr, const char *hostname, +memcached_return memcached_server_add(memcached_st *ptr, const char *hostname, unsigned int port); LIBMEMCACHED_API -memcached_return memcached_server_add_udp_with_weight(memcached_st *ptr, +memcached_return memcached_server_add_udp_with_weight(memcached_st *ptr, const char *hostname, unsigned int port, uint32_t weight); LIBMEMCACHED_API -memcached_return memcached_server_add_unix_socket_with_weight(memcached_st *ptr, +memcached_return memcached_server_add_unix_socket_with_weight(memcached_st *ptr, const char *filename, uint32_t weight); LIBMEMCACHED_API -memcached_return memcached_server_add_with_weight(memcached_st *ptr, const char *hostname, +memcached_return memcached_server_add_with_weight(memcached_st *ptr, const char *hostname, unsigned int port, uint32_t weight); LIBMEMCACHED_API @@ -219,14 +220,14 @@ LIBMEMCACHED_API memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *list); LIBMEMCACHED_API -memcached_server_st *memcached_server_list_append(memcached_server_st *ptr, - const char *hostname, - unsigned int port, +memcached_server_st *memcached_server_list_append(memcached_server_st *ptr, + const char *hostname, + unsigned int port, memcached_return *error); LIBMEMCACHED_API -memcached_server_st *memcached_server_list_append_with_weight(memcached_server_st *ptr, - const char *hostname, - unsigned int port, +memcached_server_st *memcached_server_list_append_with_weight(memcached_server_st *ptr, + const char *hostname, + unsigned int port, uint32_t weight, memcached_return *error); LIBMEMCACHED_API @@ -235,30 +236,30 @@ LIBMEMCACHED_API memcached_server_st *memcached_servers_parse(const char *server_strings); LIBMEMCACHED_API -char *memcached_stat_get_value(memcached_st *ptr, memcached_stat_st *memc_stat, +char *memcached_stat_get_value(memcached_st *ptr, memcached_stat_st *memc_stat, const char *key, memcached_return *error); LIBMEMCACHED_API -char ** memcached_stat_get_keys(memcached_st *ptr, memcached_stat_st *memc_stat, +char ** memcached_stat_get_keys(memcached_st *ptr, memcached_stat_st *memc_stat, memcached_return *error); LIBMEMCACHED_API -memcached_return memcached_delete_by_key(memcached_st *ptr, +memcached_return memcached_delete_by_key(memcached_st *ptr, const char *master_key, size_t master_key_length, const char *key, size_t key_length, time_t expiration); LIBMEMCACHED_API -memcached_return memcached_fetch_execute(memcached_st *ptr, +memcached_return memcached_fetch_execute(memcached_st *ptr, memcached_execute_function *callback, void *context, unsigned int number_of_callbacks); LIBMEMCACHED_API -memcached_return memcached_callback_set(memcached_st *ptr, - memcached_callback flag, +memcached_return memcached_callback_set(memcached_st *ptr, + memcached_callback flag, void *data); LIBMEMCACHED_API -void *memcached_callback_get(memcached_st *ptr, +void *memcached_callback_get(memcached_st *ptr, memcached_callback flag, memcached_return *error); diff --git a/libmemcached/memcached_connect.c b/libmemcached/memcached_connect.c index 833ad0ef..1c4069cf 100644 --- a/libmemcached/memcached_connect.c +++ b/libmemcached/memcached_connect.c @@ -60,7 +60,7 @@ static memcached_return set_socket_options(memcached_server_st *ptr) waittime.tv_sec= 0; waittime.tv_usec= ptr->root->snd_timeout; - error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDTIMEO, + error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDTIMEO, &waittime, (socklen_t)sizeof(struct timeval)); WATCHPOINT_ASSERT(error == 0); } @@ -75,7 +75,7 @@ static memcached_return set_socket_options(memcached_server_st *ptr) waittime.tv_sec= 0; waittime.tv_usec= ptr->root->rcv_timeout; - error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVTIMEO, + error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVTIMEO, &waittime, (socklen_t)sizeof(struct timeval)); WATCHPOINT_ASSERT(error == 0); } @@ -86,9 +86,9 @@ static memcached_return set_socket_options(memcached_server_st *ptr) int error; struct linger linger; - linger.l_onoff= 1; - linger.l_linger= 0; /* By default on close() just drop the socket */ - error= setsockopt(ptr->fd, SOL_SOCKET, SO_LINGER, + linger.l_onoff= 1; + linger.l_linger= 0; /* By default on close() just drop the socket */ + error= setsockopt(ptr->fd, SOL_SOCKET, SO_LINGER, &linger, (socklen_t)sizeof(struct linger)); WATCHPOINT_ASSERT(error == 0); } @@ -98,7 +98,7 @@ static memcached_return set_socket_options(memcached_server_st *ptr) int flag= 1; int error; - error= setsockopt(ptr->fd, IPPROTO_TCP, TCP_NODELAY, + error= setsockopt(ptr->fd, IPPROTO_TCP, TCP_NODELAY, &flag, (socklen_t)sizeof(int)); WATCHPOINT_ASSERT(error == 0); } @@ -107,7 +107,7 @@ static memcached_return set_socket_options(memcached_server_st *ptr) { int error; - error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDBUF, + error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDBUF, &ptr->root->send_size, (socklen_t)sizeof(int)); WATCHPOINT_ASSERT(error == 0); } @@ -116,7 +116,7 @@ static memcached_return set_socket_options(memcached_server_st *ptr) { int error; - error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVBUF, + error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVBUF, &ptr->root->recv_size, (socklen_t)sizeof(int)); WATCHPOINT_ASSERT(error == 0); } @@ -156,7 +156,7 @@ static memcached_return unix_socket_connect(memcached_server_st *ptr) addrlen= (socklen_t) (strlen(servAddr.sun_path) + sizeof(servAddr.sun_family)); test_connect: - if (connect(ptr->fd, + if (connect(ptr->fd, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0) { @@ -208,8 +208,8 @@ static memcached_return network_connect(memcached_server_st *ptr) continue; } - if ((ptr->fd= socket(use->ai_family, - use->ai_socktype, + if ((ptr->fd= socket(use->ai_family, + use->ai_socktype, use->ai_protocol)) < 0) { ptr->cached_errno= errno; @@ -228,7 +228,7 @@ static memcached_return network_connect(memcached_server_st *ptr) } /* connect to server */ - while (ptr->fd != -1 && + while (ptr->fd != -1 && connect(ptr->fd, use->ai_addr, use->ai_addrlen) < 0) { ptr->cached_errno= errno; @@ -253,23 +253,23 @@ static memcached_return network_connect(memcached_server_st *ptr) (void)close(ptr->fd); ptr->fd= -1; } - } + } else if (errno == EISCONN) /* we are connected :-) */ { break; - } + } else if (errno != EINTR) { (void)close(ptr->fd); ptr->fd= -1; break; - } + } } if (ptr->fd != -1) { - /* restore flags */ - if (ptr->root->connect_timeout && (ptr->root->flags & MEM_NO_BLOCK) == 0) + /* restore flags */ + if (ptr->root->connect_timeout && (ptr->root->flags & MEM_NO_BLOCK) == 0) (void)fcntl(ptr->fd, F_SETFL, flags & ~O_NONBLOCK); WATCHPOINT_ASSERT(ptr->cursor_active == 0); @@ -348,6 +348,8 @@ memcached_return memcached_connect(memcached_server_st *ptr) WATCHPOINT_ASSERT(0); } + unlikely ( rc != MEMCACHED_SUCCESS) ptr->root->last_disconnected_server = ptr; + LIBMEMCACHED_MEMCACHED_CONNECT_END(); return rc; diff --git a/libmemcached/memcached_hosts.c b/libmemcached/memcached_hosts.c index f56c89f1..d664ab2b 100644 --- a/libmemcached/memcached_hosts.c +++ b/libmemcached/memcached_hosts.c @@ -2,7 +2,7 @@ #include /* Protoypes (static) */ -static memcached_return server_add(memcached_st *ptr, const char *hostname, +static memcached_return server_add(memcached_st *ptr, const char *hostname, unsigned int port, uint32_t weight, memcached_connection type); @@ -36,7 +36,7 @@ static void sort_hosts(memcached_st *ptr) memcached_return run_distribution(memcached_st *ptr) { - switch (ptr->distribution) + switch (ptr->distribution) { case MEMCACHED_DISTRIBUTION_CONSISTENT: case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA: @@ -51,6 +51,8 @@ memcached_return run_distribution(memcached_st *ptr) WATCHPOINT_ASSERT(0); /* We have added a distribution without extending the logic */ } + ptr->last_disconnected_server = NULL; + return MEMCACHED_SUCCESS; } @@ -77,7 +79,7 @@ void server_list_free(memcached_st *ptr, memcached_server_st *servers) static uint32_t ketama_server_hash(const char *key, unsigned int key_length, int alignment) { unsigned char results[16]; - + md5_signature((unsigned char*)key, key_length, results); return ((uint32_t) (results[3 + alignment * 4] & 0xFF) << 24) | ((uint32_t) (results[2 + alignment * 4] & 0xFF) << 16) @@ -155,7 +157,7 @@ memcached_return update_continuum(memcached_st *ptr) { memcached_continuum_item_st *new_ptr; - new_ptr= ptr->call_realloc(ptr, ptr->continuum, + new_ptr= ptr->call_realloc(ptr, ptr->continuum, sizeof(memcached_continuum_item_st) * (live_servers + MEMCACHED_CONTINUUM_ADDITION) * points_per_server); if (new_ptr == 0) @@ -165,9 +167,9 @@ memcached_return update_continuum(memcached_st *ptr) ptr->continuum_count= live_servers + MEMCACHED_CONTINUUM_ADDITION; } - if (is_ketama_weighted) + if (is_ketama_weighted) { - for (host_index = 0; host_index < ptr->number_of_hosts; ++host_index) + for (host_index = 0; host_index < ptr->number_of_hosts; ++host_index) { if (list[host_index].weight == 0) { @@ -178,27 +180,27 @@ memcached_return update_continuum(memcached_st *ptr) } } - for (host_index = 0; host_index < ptr->number_of_hosts; ++host_index) + for (host_index = 0; host_index < ptr->number_of_hosts; ++host_index) { if (is_auto_ejecting && list[host_index].next_retry > now.tv_sec) continue; - if (is_ketama_weighted) + if (is_ketama_weighted) { float pct = (float)list[host_index].weight / (float)total_weight; pointer_per_server= (uint32_t) ((floorf((float) (pct * MEMCACHED_POINTS_PER_SERVER_KETAMA / 4 * (float)live_servers + 0.0000000001))) * 4); pointer_per_hash= 4; #ifdef DEBUG - printf("ketama_weighted:%s|%d|%llu|%u\n", - list[host_index].hostname, - list[host_index].port, - (unsigned long long)list[host_index].weight, + printf("ketama_weighted:%s|%d|%llu|%u\n", + list[host_index].hostname, + list[host_index].port, + (unsigned long long)list[host_index].weight, pointer_per_server); #endif } for (pointer_index= 1; pointer_index <= pointer_per_server / pointer_per_hash; - ++pointer_index) + ++pointer_index) { char sort_host[MEMCACHED_MAX_HOST_SORT_LENGTH]= ""; size_t sort_host_length; @@ -214,7 +216,7 @@ memcached_return update_continuum(memcached_st *ptr) else { sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH, - "%s:%d-%d", + "%s:%d-%d", list[host_index].hostname, list[host_index].port, pointer_index - 1); } @@ -247,7 +249,7 @@ memcached_return update_continuum(memcached_st *ptr) qsort(ptr->continuum, ptr->continuum_points_counter, sizeof(memcached_continuum_item_st), continuum_item_cmp); #ifdef DEBUG - for (pointer_index= 0; ptr->number_of_hosts && pointer_index < ((live_servers * MEMCACHED_POINTS_PER_SERVER) - 1); pointer_index++) + for (pointer_index= 0; ptr->number_of_hosts && pointer_index < ((live_servers * MEMCACHED_POINTS_PER_SERVER) - 1); pointer_index++) { WATCHPOINT_ASSERT(ptr->continuum[pointer_index].value <= ptr->continuum[pointer_index + 1].value); } @@ -267,7 +269,7 @@ memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *l return MEMCACHED_SUCCESS; count= list[0].count; - new_host_list= ptr->call_realloc(ptr, ptr->hosts, + new_host_list= ptr->call_realloc(ptr, ptr->hosts, sizeof(memcached_server_st) * (count + ptr->number_of_hosts)); if (!new_host_list) @@ -285,7 +287,7 @@ memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *l WATCHPOINT_ASSERT(list[x].hostname[0] != 0); memcached_server_create(ptr, &ptr->hosts[ptr->number_of_hosts]); /* TODO check return type */ - (void)memcached_server_create_with(ptr, &ptr->hosts[ptr->number_of_hosts], list[x].hostname, + (void)memcached_server_create_with(ptr, &ptr->hosts[ptr->number_of_hosts], list[x].hostname, list[x].port, list[x].weight, list[x].type); ptr->number_of_hosts++; } @@ -294,14 +296,14 @@ memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *l return run_distribution(ptr); } -memcached_return memcached_server_add_unix_socket(memcached_st *ptr, +memcached_return memcached_server_add_unix_socket(memcached_st *ptr, const char *filename) { return memcached_server_add_unix_socket_with_weight(ptr, filename, 0); } -memcached_return memcached_server_add_unix_socket_with_weight(memcached_st *ptr, - const char *filename, +memcached_return memcached_server_add_unix_socket_with_weight(memcached_st *ptr, + const char *filename, uint32_t weight) { if (!filename) @@ -310,41 +312,41 @@ memcached_return memcached_server_add_unix_socket_with_weight(memcached_st *ptr, return server_add(ptr, filename, 0, weight, MEMCACHED_CONNECTION_UNIX_SOCKET); } -memcached_return memcached_server_add_udp(memcached_st *ptr, +memcached_return memcached_server_add_udp(memcached_st *ptr, const char *hostname, unsigned int port) { return memcached_server_add_udp_with_weight(ptr, hostname, port, 0); } -memcached_return memcached_server_add_udp_with_weight(memcached_st *ptr, +memcached_return memcached_server_add_udp_with_weight(memcached_st *ptr, const char *hostname, unsigned int port, uint32_t weight) { if (!port) - port= MEMCACHED_DEFAULT_PORT; + port= MEMCACHED_DEFAULT_PORT; if (!hostname) - hostname= "localhost"; + hostname= "localhost"; return server_add(ptr, hostname, port, weight, MEMCACHED_CONNECTION_UDP); } -memcached_return memcached_server_add(memcached_st *ptr, - const char *hostname, +memcached_return memcached_server_add(memcached_st *ptr, + const char *hostname, unsigned int port) { return memcached_server_add_with_weight(ptr, hostname, port, 0); } -memcached_return memcached_server_add_with_weight(memcached_st *ptr, - const char *hostname, +memcached_return memcached_server_add_with_weight(memcached_st *ptr, + const char *hostname, unsigned int port, uint32_t weight) { if (!port) - port= MEMCACHED_DEFAULT_PORT; + port= MEMCACHED_DEFAULT_PORT; if (!hostname) hostname= "localhost"; @@ -352,7 +354,7 @@ memcached_return memcached_server_add_with_weight(memcached_st *ptr, return server_add(ptr, hostname, port, weight, MEMCACHED_CONNECTION_TCP); } -static memcached_return server_add(memcached_st *ptr, const char *hostname, +static memcached_return server_add(memcached_st *ptr, const char *hostname, unsigned int port, uint32_t weight, memcached_connection type) @@ -362,8 +364,8 @@ static memcached_return server_add(memcached_st *ptr, const char *hostname, if ( (ptr->flags & MEM_USE_UDP && type != MEMCACHED_CONNECTION_UDP) || ( (type == MEMCACHED_CONNECTION_UDP) && !(ptr->flags & MEM_USE_UDP) ) ) return MEMCACHED_INVALID_HOST_PROTOCOL; - - new_host_list= ptr->call_realloc(ptr, ptr->hosts, + + new_host_list= ptr->call_realloc(ptr, ptr->hosts, sizeof(memcached_server_st) * (ptr->number_of_hosts+1)); if (new_host_list == NULL) @@ -385,18 +387,18 @@ memcached_return memcached_server_remove(memcached_server_st *st_ptr) memcached_st *ptr= st_ptr->root; memcached_server_st *list= ptr->hosts; - for (x= 0, host_index= 0; x < ptr->number_of_hosts; x++) + for (x= 0, host_index= 0; x < ptr->number_of_hosts; x++) { - if (strncmp(list[x].hostname, st_ptr->hostname, MEMCACHED_MAX_HOST_LENGTH) != 0 || list[x].port != st_ptr->port) + if (strncmp(list[x].hostname, st_ptr->hostname, MEMCACHED_MAX_HOST_LENGTH) != 0 || list[x].port != st_ptr->port) { if (host_index != x) memcpy(list+host_index, list+x, sizeof(memcached_server_st)); host_index++; - } + } } ptr->number_of_hosts= host_index; - if (st_ptr->address_info) + if (st_ptr->address_info) { freeaddrinfo(st_ptr->address_info); st_ptr->address_info= NULL; @@ -406,16 +408,16 @@ memcached_return memcached_server_remove(memcached_server_st *st_ptr) return MEMCACHED_SUCCESS; } -memcached_server_st *memcached_server_list_append(memcached_server_st *ptr, +memcached_server_st *memcached_server_list_append(memcached_server_st *ptr, const char *hostname, unsigned int port, memcached_return *error) { return memcached_server_list_append_with_weight(ptr, hostname, port, 0, error); } -memcached_server_st *memcached_server_list_append_with_weight(memcached_server_st *ptr, +memcached_server_st *memcached_server_list_append_with_weight(memcached_server_st *ptr, const char *hostname, unsigned int port, - uint32_t weight, + uint32_t weight, memcached_return *error) { unsigned int count; @@ -425,14 +427,14 @@ memcached_server_st *memcached_server_list_append_with_weight(memcached_server_s return NULL; if (!port) - port= MEMCACHED_DEFAULT_PORT; + port= MEMCACHED_DEFAULT_PORT; /* Increment count for hosts */ count= 1; if (ptr != NULL) { count+= ptr[0].count; - } + } new_host_list= (memcached_server_st *)realloc(ptr, sizeof(memcached_server_st) * count); if (!new_host_list) diff --git a/libmemcached/memcached_server.c b/libmemcached/memcached_server.c index 7b9c2117..2ecbe214 100644 --- a/libmemcached/memcached_server.c +++ b/libmemcached/memcached_server.c @@ -16,14 +16,14 @@ memcached_server_st *memcached_server_create(memcached_st *memc, memcached_serve } else memset(ptr, 0, sizeof(memcached_server_st)); - + ptr->root= memc; return ptr; } -memcached_server_st *memcached_server_create_with(memcached_st *memc, memcached_server_st *host, - const char *hostname, unsigned int port, +memcached_server_st *memcached_server_create_with(memcached_st *memc, memcached_server_st *host, + const char *hostname, unsigned int port, uint32_t weight, memcached_connection type) { host= memcached_server_create(memc, host); @@ -76,7 +76,7 @@ memcached_server_st *memcached_server_clone(memcached_server_st *clone, memcache if (ptr == NULL) return NULL; - rv = memcached_server_create_with(ptr->root, clone, + rv = memcached_server_create_with(ptr->root, clone, ptr->hostname, ptr->port, ptr->weight, ptr->type); if (rv != NULL) @@ -90,7 +90,7 @@ memcached_server_st *memcached_server_clone(memcached_server_st *clone, memcache } -memcached_return memcached_server_cursor(memcached_st *ptr, +memcached_return memcached_server_cursor(memcached_st *ptr, memcached_server_function *callback, void *context, unsigned int number_of_callbacks) @@ -119,7 +119,7 @@ memcached_server_st *memcached_server_by_key(memcached_st *ptr, const char *key { uint32_t server_key; - *error= memcached_validate_key_length(key_length, + *error= memcached_validate_key_length(key_length, ptr->flags & MEM_BINARY_PROTOCOL); unlikely (*error != MEMCACHED_SUCCESS) return NULL; @@ -146,7 +146,7 @@ const char *memcached_server_error(memcached_server_st *ptr) { if (ptr) return ptr->cached_server_error; - else + else return NULL; } @@ -154,3 +154,8 @@ void memcached_server_error_reset(memcached_server_st *ptr) { ptr->cached_server_error[0]= 0; } + +memcached_server_st *memcached_server_get_last_disconnect(memcached_st *ptr) +{ + return ptr->last_disconnected_server; +} diff --git a/libmemcached/memcached_server.h b/libmemcached/memcached_server.h index ec1014a6..de57eaec 100644 --- a/libmemcached/memcached_server.h +++ b/libmemcached/memcached_server.h @@ -49,13 +49,13 @@ struct memcached_server_st { #define memcached_server_response_count(A) (A)->cursor_active LIBMEMCACHED_API -memcached_return memcached_server_cursor(memcached_st *ptr, +memcached_return memcached_server_cursor(memcached_st *ptr, memcached_server_function *callback, void *context, unsigned int number_of_callbacks); LIBMEMCACHED_API -memcached_server_st *memcached_server_by_key(memcached_st *ptr, const char *key, +memcached_server_st *memcached_server_by_key(memcached_st *ptr, const char *key, size_t key_length, memcached_return *error); LIBMEMCACHED_API @@ -71,8 +71,8 @@ LIBMEMCACHED_API memcached_server_st *memcached_server_create(memcached_st *memc, memcached_server_st *ptr); LIBMEMCACHED_API -memcached_server_st *memcached_server_create_with(memcached_st *memc, memcached_server_st *host, - const char *hostname, unsigned int port, +memcached_server_st *memcached_server_create_with(memcached_st *memc, memcached_server_st *host, + const char *hostname, unsigned int port, uint32_t weight, memcached_connection type); LIBMEMCACHED_API @@ -86,6 +86,9 @@ memcached_analysis_st *memcached_analyze(memcached_st *memc, memcached_stat_st * LIBMEMCACHED_API memcached_return memcached_server_remove(memcached_server_st *st_ptr); +LIBMEMCACHED_API +memcached_server_st *memcached_server_get_last_disconnect(memcached_st *ptr); + #ifdef __cplusplus } #endif diff --git a/tests/function.c b/tests/function.c index 914e17f2..9e048784 100644 --- a/tests/function.c +++ b/tests/function.c @@ -4732,6 +4732,60 @@ static test_return_t regression_bug_442914(memcached_st *memc) return TEST_SUCCESS; } + + +/* Test memcached_server_get_last_disconnect + * For a working server set, shall be NULL + * For a set of non existing server, shall not be NULL + */ +static test_return_t test_get_last_disconnect(memcached_st *memc) +{ + memcached_return rc; + memcached_server_st *disconnected_server; + + /* With the working set of server */ + const char *key= "marmotte"; + const char *value= "milka"; + + rc= memcached_set(memc, key, strlen(key), + value, strlen(value), + (time_t)0, (uint32_t)0); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); + + disconnected_server = memcached_server_get_last_disconnect(memc); + assert(disconnected_server == NULL); + + /* With a non existing server */ + memcached_st *mine; + memcached_server_st *servers; + + const char *server_list= "localhost:9"; + + servers= memcached_servers_parse(server_list); + assert(servers); + mine= memcached_create(NULL); + rc= memcached_server_push(mine, servers); + assert(rc == MEMCACHED_SUCCESS); + memcached_server_list_free(servers); + assert(mine); + + rc= memcached_set(mine, key, strlen(key), + value, strlen(value), + (time_t)0, (uint32_t)0); + assert(rc != MEMCACHED_SUCCESS); + + disconnected_server = memcached_server_get_last_disconnect(mine); + assert(disconnected_server != NULL); + assert(disconnected_server->port == 9); + assert(strncmp(disconnected_server->hostname,"localhost",9) == 0); + + memcached_quit(mine); + memcached_free(mine); + + return TEST_SUCCESS; +} + + test_st udp_setup_server_tests[] ={ {"set_udp_behavior_test", 0, set_udp_behavior_test}, {"add_tcp_server_udp_client_test", 0, add_tcp_server_udp_client_test}, @@ -4811,6 +4865,7 @@ test_st tests[] ={ #ifdef HAVE_LIBMEMCACHEDUTIL {"connectionpool", 1, connection_pool_test }, #endif + {"test_get_last_disconnect", 1, test_get_last_disconnect}, {0, 0, 0} };