#define memcached_set_initialized(__object, __value) ((__object)->options.is_initialized(= (__value))
#define memcached_set_allocated(__object, __value) ((__object)->options.is_allocated(= (__value))
+LIBMEMCACHED_LOCAL
+void set_last_disconnected_host(memcached_server_write_instance_st ptr);
LIBMEMCACHED_LOCAL
memcached_return_t memcached_key_test(const char * const *keys,
#include <netdb.h>
#include <poll.h>
#include <sys/time.h>
+#include <time.h>
static memcached_return_t set_hostinfo(memcached_server_st *server)
{
struct addrinfo *ai;
struct addrinfo hints;
- int e;
char str_port[NI_MAXSERV];
+ uint32_t counter= 5;
snprintf(str_port, NI_MAXSERV, "%u", (uint32_t)server->port);
hints.ai_protocol= IPPROTO_TCP;
}
- e= getaddrinfo(server->hostname, str_port, &hints, &ai);
- if (e != 0)
+ while (--counter)
{
- WATCHPOINT_STRING(server->hostname);
- WATCHPOINT_STRING(gai_strerror(e));
- return MEMCACHED_HOST_LOOKUP_FAILURE;
+ int e= getaddrinfo(server->hostname, str_port, &hints, &ai);
+
+ if (e == 0)
+ {
+ break;
+ }
+ else if (e == EAI_AGAIN)
+ {
+ struct timespec dream, rem;
+
+ dream.tv_nsec= 1000;
+ dream.tv_sec= 0;
+
+ nanosleep(&dream, &rem);
+
+ continue;
+ }
+ else
+ {
+ WATCHPOINT_STRING(server->hostname);
+ WATCHPOINT_STRING(gai_strerror(e));
+ return MEMCACHED_HOST_LOOKUP_FAILURE;
+ }
}
if (server->address_info)
(void)set_socket_options(ptr);
/* connect to server */
- while (ptr->fd != -1 &&
- connect(ptr->fd, use->ai_addr, use->ai_addrlen) < 0)
+ if ((connect(ptr->fd, use->ai_addr, use->ai_addrlen) == -1))
{
ptr->cached_errno= errno;
if (errno == EINPROGRESS || /* nonblocking mode - first return, */
struct pollfd fds[1];
fds[0].fd = ptr->fd;
fds[0].events = POLLOUT;
- int error= poll(fds, 1, ptr->root->connect_timeout);
- if (error != 1 || fds[0].revents & POLLERR)
+ int timeout= ptr->root->connect_timeout;
+ if (ptr->root->flags.no_block == false)
+ timeout= -1;
+
+ size_t loop_max= 5;
+ while (--loop_max)
{
- if (fds[0].revents & POLLERR)
+ int error= poll(fds, 1, timeout);
+
+ switch (error)
{
- int err;
- socklen_t len = sizeof (err);
- (void)getsockopt(ptr->fd, SOL_SOCKET, SO_ERROR, &err, &len);
- ptr->cached_errno= (err == 0) ? errno : err;
+ case 1:
+ loop_max= 1;
+ break;
+ case 0:
+ continue;
+ // A real error occurred and we need to completely bail
+ default:
+ WATCHPOINT_ERRNO(errno);
+ switch (errno)
+ {
+#ifdef TARGET_OS_LINUX
+ case ERESTART:
+#endif
+ case EINTR:
+ continue;
+ default:
+ if (fds[0].revents & POLLERR)
+ {
+ int err;
+ socklen_t len= sizeof (err);
+ (void)getsockopt(ptr->fd, SOL_SOCKET, SO_ERROR, &err, &len);
+ ptr->cached_errno= (err == 0) ? errno : err;
+ }
+
+ (void)close(ptr->fd);
+ ptr->fd= -1;
+
+ break;
+ }
}
-
- (void)close(ptr->fd);
- ptr->fd= -1;
}
}
else if (errno == EISCONN) /* we are connected :-) */
if (ptr->fd == -1)
{
+ WATCHPOINT_STRING("Never got a good file descriptor");
+
/* Failed to connect. schedule next retry */
if (ptr->root->retry_timeout)
{
return MEMCACHED_SUCCESS; /* The last error should be from connect() */
}
-static inline void set_last_disconnected_host(memcached_server_write_instance_st ptr)
+void set_last_disconnected_host(memcached_server_write_instance_st ptr)
{
// const_cast
memcached_st *root= (memcached_st *)ptr->root;
+#if 0
+ WATCHPOINT_STRING(ptr->hostname);
+ WATCHPOINT_NUMBER(ptr->port);
+ WATCHPOINT_ERRNO(ptr->cached_errno);
+#endif
if (root->last_disconnected_server)
memcached_server_free(root->last_disconnected_server);
root->last_disconnected_server= memcached_server_clone(NULL, ptr);
#define MEMCACHED_CONTINUUM_SIZE MEMCACHED_POINTS_PER_SERVER*100 /* This would then set max hosts to 100 */
#define MEMCACHED_STRIDE 4
#define MEMCACHED_DEFAULT_TIMEOUT 1000
+#define MEMCACHED_DEFAULT_CONNECT_TIMEOUT 4000
#define MEMCACHED_CONTINUUM_ADDITION 10 /* How many extra slots we should build for in the continuum */
#define MEMCACHED_PREFIX_KEY_MAX_SIZE 128
#define MEMCACHED_EXPIRATION_NOT_ADD 0xffffffffU
if (sent_length == -1 || (size_t)sent_length != command_length)
{
rc= MEMCACHED_WRITE_FAILURE;
+ WATCHPOINT_ERROR(rc);
+ WATCHPOINT_ERRNO(errno);
}
else if ((ptr->root->flags.no_reply) == 0)
{
case 1:
return MEMCACHED_SUCCESS;
case 0:
- return MEMCACHED_TIMEOUT;
-#ifdef TARGET_OS_LINUX
- case ERESTART:
-#endif
- case EINTR:
continue;
default:
- ptr->cached_errno= error;
- memcached_quit_server(ptr, true);
+ WATCHPOINT_ERRNO(errno);
+ {
+ switch (errno)
+ {
+ default:
+ ptr->cached_errno= error;
+ memcached_quit_server(ptr, true);
- return MEMCACHED_FAILURE;
+ return MEMCACHED_FAILURE;
+ }
+ }
}
}
+ if (loop_max == 0 && error == 0)
+ return MEMCACHED_TIMEOUT;
+
/* Imposssible for anything other then -1 */
WATCHPOINT_ASSERT(error == -1);
ptr->cached_errno= error;
if (sent_length == -1)
{
ptr->cached_errno= errno;
+ WATCHPOINT_ERRNO(errno);
switch (errno)
{
case ENOBUFS:
self->io_key_prefetch= 0;
self->cached_errno= 0;
self->poll_timeout= MEMCACHED_DEFAULT_TIMEOUT;
- self->connect_timeout= MEMCACHED_DEFAULT_TIMEOUT;
+ self->connect_timeout= MEMCACHED_DEFAULT_CONNECT_TIMEOUT;
self->retry_timeout= 0;
self->continuum_count= 0;
ptr->server_failure_limit= 0;
}
+void memcached_reset_last_disconnected_server(memcached_st *ptr)
+{
+ if (ptr->last_disconnected_server)
+ {
+ memcached_server_free(ptr->last_disconnected_server);
+ ptr->last_disconnected_server= NULL;
+ }
+}
+
void memcached_free(memcached_st *ptr)
{
/* If we have anything open, lets close it now */
LIBMEMCACHED_API
void memcached_free(memcached_st *ptr);
+LIBMEMCACHED_API
+void memcached_reset_last_disconnected_server(memcached_st *ptr);
+
LIBMEMCACHED_API
memcached_st *memcached_clone(memcached_st *clone, const memcached_st *ptr);
if (io_death)
{
ptr->server_failure_counter++;
+ set_last_disconnected_host(ptr);
}
}
const char *key= "marmotte";
const char *value= "milka";
+ memcached_reset_last_disconnected_server(memc);
rc= memcached_set(memc, key, strlen(key),
value, strlen(value),
(time_t)0, (uint32_t)0);
(time_t)0, (uint32_t)0);
test_true(rc != MEMCACHED_SUCCESS);
- disconnected_server = memcached_server_get_last_disconnect(mine);
+ disconnected_server= memcached_server_get_last_disconnect(mine);
+ if (disconnected_server == NULL)
+ {
+ fprintf(stderr, "RC %s\n", memcached_strerror(mine, rc));
+ abort();
+ }
test_true(disconnected_server != NULL);
test_true(memcached_server_port(disconnected_server)== 9);
test_true(strncmp(memcached_server_name(disconnected_server),"localhost",9) == 0);
return TEST_SUCCESS;
}
-static void memcached_die(memcached_st* mc, memcached_return error, const char* what, int it)
+static void memcached_die(memcached_st* mc, memcached_return error, const char* what, uint32_t it)
{
- fprintf(stderr, "Iteration #%i: ", it);
+ fprintf(stderr, "Iteration #%u: ", it);
if(error == MEMCACHED_ERRNO)
{
fprintf(stderr, "error %d from %s: %s\n", error, what,
memcached_strerror(mc, error));
}
-
- abort();
}
-#define TEST_CONSTANT_CREATION 400
+#define TEST_CONSTANT_CREATION 200
static test_return_t regression_bug_(memcached_st *memc)
{
- memcached_server_instance_st instance= memcached_server_instance_by_position(memc, 0);
- const char *servername= memcached_server_name(instance);
- in_port_t port= memcached_server_port(instance);
+ const char *remote_server;
+ (void)memc;
+
+ if (! (remote_server= getenv("LIBMEMCACHED_REMOTE_SERVER")))
+ {
+ return TEST_SKIPPED;
+ }
for (uint32_t x= 0; x < TEST_CONSTANT_CREATION; x++)
{
memcached_die(mc, rc, "memcached_behavior_set", x);
}
- rc= memcached_server_add(mc, servername, port);
- if(rc != MEMCACHED_SUCCESS)
+ rc= memcached_server_add(mc, remote_server, 0);
+ if (rc != MEMCACHED_SUCCESS)
{
memcached_die(mc, rc, "memcached_server_add", x);
}
const char *set_value= "a value";
const size_t set_value_len= strlen(set_value);
- char *get_value=NULL;
- size_t get_value_len=0;
- uint32_t get_value_flags=0;
- if (x > 0)
+ if (rc == MEMCACHED_SUCCESS)
{
- get_value= memcached_get(mc, set_key, set_key_len, &get_value_len,
- &get_value_flags, &rc);
- if (rc != MEMCACHED_SUCCESS)
+ if (x > 0)
{
- memcached_die(mc, rc, "memcached_get", x);
+ size_t get_value_len;
+ char *get_value;
+ uint32_t get_value_flags;
+
+ get_value= memcached_get(mc, set_key, set_key_len, &get_value_len,
+ &get_value_flags, &rc);
+ if (rc != MEMCACHED_SUCCESS)
+ {
+ memcached_die(mc, rc, "memcached_get", x);
+ }
+ else
+ {
+
+ if (x != 0 &&
+ (get_value_len != set_value_len
+ || 0!=strncmp(get_value, set_value, get_value_len)))
+ {
+ fprintf(stderr, "Values don't match?\n");
+ rc= MEMCACHED_FAILURE;
+ }
+ free(get_value);
+ }
}
- if (x != 0 &&
- (get_value_len != set_value_len
- || 0!=strncmp(get_value, set_value, get_value_len)))
+ rc= memcached_set(mc,
+ set_key, set_key_len,
+ set_value, set_value_len,
+ 0, /* time */
+ 0 /* flags */
+ );
+ if (rc != MEMCACHED_SUCCESS)
{
- fprintf(stderr, "Values don't match?\n");
+ memcached_die(mc, rc, "memcached_set", x);
}
- free(get_value);
- get_value= NULL;
- get_value_len= 0;
}
- rc= memcached_set(mc,
- set_key, set_key_len,
- set_value, set_value_len,
- 0, /* time */
- 0 /* flags */
- );
+ memcached_quit(mc);
+ memcached_free(mc);
+
if (rc != MEMCACHED_SUCCESS)
{
- memcached_die(mc, rc, "memcached_set", x);
+ break;
}
-
- memcached_quit(mc);
- memcached_free(mc);
}
return MEMCACHED_SUCCESS;
test_st regression_tests[]= {
{"lp:434484", 1, (test_callback_fn)regression_bug_434484 },
{"lp:434843", 1, (test_callback_fn)regression_bug_434843 },
- {"lp:434843 buffered", 1, (test_callback_fn)regression_bug_434843_buffered },
+ {"lp:434843-buffered", 1, (test_callback_fn)regression_bug_434843_buffered },
{"lp:421108", 1, (test_callback_fn)regression_bug_421108 },
{"lp:442914", 1, (test_callback_fn)regression_bug_442914 },
{"lp:447342", 1, (test_callback_fn)regression_bug_447342 },