New evhttp function to adjust initial retry timeout

This commit is contained in:
Nick Mathewson 2012-01-24 14:34:04 -05:00
parent ab14f7c140
commit 350a3c400f
3 changed files with 40 additions and 20 deletions

View File

@ -86,6 +86,9 @@ struct evhttp_connection {
struct timeval timeout; /* timeout for events */
int retry_cnt; /* retry count */
int retry_max; /* maximum number of retries */
struct timeval initial_retry_timeout; /* Timeout for low long to wait
* after first failing attempt
* before retry */
enum evhttp_connection_state state;

50
http.c
View File

@ -352,23 +352,6 @@ evhttp_response_needs_body(struct evhttp_request *req)
req->type != EVHTTP_REQ_HEAD);
}
/** Helper: adds the event 'ev' with the timeout 'timeout', or with
* default_timeout if timeout is -1.
*/
static int
evhttp_add_event(struct event *ev, int timeout, int default_timeout)
{
if (timeout != 0) {
struct timeval tv;
evutil_timerclear(&tv);
tv.tv_sec = timeout != -1 ? timeout : default_timeout;
return event_add(ev, &tv);
} else {
return event_add(ev, NULL);
}
}
/** Helper: called after we've added some data to an evcon's bufferevent's
* output buffer. Sets the evconn's writing-is-done callback, and puts
* the bufferevent into writing mode.
@ -1284,11 +1267,23 @@ evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
struct evcon_requestq requests;
if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
struct timeval tv_retry = evcon->initial_retry_timeout;
int i;
evtimer_assign(&evcon->retry_ev, evcon->base, evhttp_connection_retry, evcon);
/* XXXX handle failure from evhttp_add_event */
evhttp_add_event(&evcon->retry_ev,
MIN(3600, 2 << evcon->retry_cnt),
HTTP_CONNECT_TIMEOUT);
for (i=0; i < evcon->retry_cnt; ++i) {
tv_retry.tv_usec *= 2;
if (tv_retry.tv_usec > 1000000) {
tv_retry.tv_usec -= 1000000;
tv_retry.tv_sec += 1;
}
tv_retry.tv_sec *= 2;
if (tv_retry.tv_sec > 3600) {
tv_retry.tv_sec = 3600;
tv_retry.tv_usec = 0;
}
}
event_add(&evcon->retry_ev, &tv_retry);
evcon->retry_cnt++;
return;
}
@ -2193,6 +2188,9 @@ evhttp_connection_base_bufferevent_new(struct event_base *base, struct evdns_bas
evcon->state = EVCON_DISCONNECTED;
TAILQ_INIT(&evcon->requests);
evcon->initial_retry_timeout.tv_sec = 2;
evcon->initial_retry_timeout.tv_usec = 0;
if (base != NULL) {
evcon->base = base;
if (bufferevent_get_base(bev) != base)
@ -2263,6 +2261,18 @@ evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon,
}
}
void
evhttp_connection_set_initial_retry_tv(struct evhttp_connection *evcon,
const struct timeval *tv)
{
if (tv) {
evcon->initial_retry_timeout = *tv;
} else {
evutil_timerclear(&evcon->initial_retry_timeout);
evcon->initial_retry_timeout.tv_sec = 2;
}
}
void
evhttp_connection_set_retries(struct evhttp_connection *evcon,
int retry_max)

View File

@ -538,6 +538,13 @@ void evhttp_connection_set_timeout(struct evhttp_connection *evcon,
void evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon,
const struct timeval *tv);
/** Sets the delay before retrying requests on this connection. This is only
* used if evhttp_connection_set_retries is used to make the number of retries
* at least one. Each retry after the first is twice as long as the one before
* it. */
void evhttp_connection_set_initial_retry_tv(struct evhttp_connection *evcon,
const struct timeval *tv);
/** Sets the retry limit for this connection - -1 repeats indefinitely */
void evhttp_connection_set_retries(struct evhttp_connection *evcon,
int retry_max);