#define MEMCACHED_EXPIRATION_NOT_ADD 0xffffffffU
#define MEMCACHED_SERVER_FAILURE_LIMIT 5
#define MEMCACHED_SERVER_FAILURE_RETRY_TIMEOUT 2
+#define MEMCACHED_SERVER_FAILURE_DEAD_TIMEOUT 0
int32_t poll_timeout;
int32_t connect_timeout; // How long we will wait on connect() before we will timeout
int32_t retry_timeout;
+ int32_t dead_timeout;
int send_size;
int recv_size;
void *user_data;
MEMCACHED_BEHAVIOR_TCP_KEEPIDLE,
MEMCACHED_BEHAVIOR_LOAD_FROM_FILE,
MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS,
+ MEMCACHED_BEHAVIOR_DEAD_TIMEOUT,
MEMCACHED_BEHAVIOR_MAX
};
ptr->retry_timeout= int32_t(data);
break;
+ case MEMCACHED_BEHAVIOR_DEAD_TIMEOUT:
+ ptr->dead_timeout= int32_t(data);
+ break;
+
case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE:
ptr->send_size= (int32_t)data;
send_quit(ptr);
case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT:
return (uint64_t)ptr->retry_timeout;
+ case MEMCACHED_BEHAVIOR_DEAD_TIMEOUT:
+ return uint64_t(ptr->dead_timeout);
+
case MEMCACHED_BEHAVIOR_SND_TIMEOUT:
return (uint64_t)ptr->snd_timeout;
case MEMCACHED_BEHAVIOR_VERIFY_KEY: return "MEMCACHED_BEHAVIOR_VERIFY_KEY";
case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT: return "MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT";
case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT: return "MEMCACHED_BEHAVIOR_RETRY_TIMEOUT";
+ case MEMCACHED_BEHAVIOR_DEAD_TIMEOUT: return "MEMCACHED_BEHAVIOR_DEAD_TIMEOUT";
case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED: return "MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED";
case MEMCACHED_BEHAVIOR_KETAMA_HASH: return "MEMCACHED_BEHAVIOR_KETAMA_HASH";
case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL: return "MEMCACHED_BEHAVIOR_BINARY_PROTOCOL";
*/
static memcached_return_t backoff_handling(memcached_server_write_instance_st server, bool& in_timeout)
{
+ struct timeval curr_time;
+ bool _gettime_success= (gettimeofday(&curr_time, NULL) == 0);
+
/*
If we hit server_failure_limit then something is completely wrong about the server.
if (_is_auto_eject_host(server->root))
{
set_last_disconnected_host(server);
- run_distribution((memcached_st *)server->root);
+
+ // Retry dead servers if requested
+ if (_gettime_success and server->root->dead_timeout > 0)
+ {
+ server->next_retry= curr_time.tv_sec +server->root->dead_timeout;
+
+ // We only retry dead servers once before assuming failure again
+ server->server_failure_counter= server->root->server_failure_limit -1;
+ }
+
+ memcached_return_t rc;
+ if (memcached_failed(rc= run_distribution((memcached_st *)server->root)))
+ {
+ return memcached_set_error(*server, rc, MEMCACHED_AT, memcached_literal_param("Backoff handling failed during run_distribution"));
+ }
return memcached_set_error(*server, MEMCACHED_SERVER_MARKED_DEAD, MEMCACHED_AT);
}
if (server->state == MEMCACHED_SERVER_STATE_IN_TIMEOUT)
{
- struct timeval curr_time;
- bool _gettime_success= (gettimeofday(&curr_time, NULL) == 0);
-
/*
If next_retry is less then our current time, then we reset and try everything again.
*/
self->poll_timeout= MEMCACHED_DEFAULT_TIMEOUT;
self->connect_timeout= MEMCACHED_DEFAULT_CONNECT_TIMEOUT;
self->retry_timeout= MEMCACHED_SERVER_FAILURE_RETRY_TIMEOUT;
+ self->dead_timeout= MEMCACHED_SERVER_FAILURE_DEAD_TIMEOUT;
self->send_size= -1;
self->recv_size= -1;
memcached_return_t memcached_reset(memcached_st *ptr)
{
WATCHPOINT_ASSERT(ptr);
- if (not ptr)
+ if (ptr == NULL)
{
return MEMCACHED_INVALID_ARGUMENTS;
}
new_clone->poll_timeout= source->poll_timeout;
new_clone->connect_timeout= source->connect_timeout;
new_clone->retry_timeout= source->retry_timeout;
+ new_clone->dead_timeout= source->dead_timeout;
new_clone->distribution= source->distribution;
if (hashkit_clone(&new_clone->hashkit, &source->hashkit) == NULL)
{
test_true(libmemcached_string_behavior(memcached_behavior_t(x)));
}
- test_compare(36, int(MEMCACHED_BEHAVIOR_MAX));
+ test_compare(37, int(MEMCACHED_BEHAVIOR_MAX));
return TEST_SUCCESS;
}
memcached_set(memc,
test_literal_param(__func__),
test_literal_param("1"),
- (time_t)0, (uint32_t)0));
+ time_t(0), uint32_t(0)));
Expected expected_ids;
get_udp_request_ids(memc, expected_ids);