From: Stephan Bosch Date: Mon, 20 Oct 2014 15:54:27 +0000 (-0700) Subject: lib-http: client: Fixed behavior of connection backoff timer when multiple IPs are... X-Git-Tag: 2.2.15~44 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8d5b57113f8f90003fd54a426fc70a8bdd5db099;p=thirdparty%2Fdovecot%2Fcore.git lib-http: client: Fixed behavior of connection backoff timer when multiple IPs are returned for hostname. Peer backoff data was lost because peer was destroyed quickly. Now the peer object is retained during the backoff period, so that new connection attempts adhere to the backoff period. --- diff --git a/src/lib-http/http-client-peer.c b/src/lib-http/http-client-peer.c index 8fc3b87fa5..c5c846c1aa 100644 --- a/src/lib-http/http-client-peer.c +++ b/src/lib-http/http-client-peer.c @@ -91,7 +91,6 @@ http_client_peer_do_connect(struct http_client_peer *peer, } } - static void http_client_peer_connect_backoff(struct http_client_peer *peer) { @@ -101,18 +100,25 @@ http_client_peer_connect_backoff(struct http_client_peer *peer) "Backoff timer expired"); timeout_remove(&peer->to_backoff); + + if (array_count(&peer->queues) == 0) { + http_client_peer_free(&peer); + return; + } + http_client_peer_do_connect(peer, 1); } -static void -http_client_peer_connect(struct http_client_peer *peer, unsigned int count) +static bool +http_client_peer_start_backoff_timer(struct http_client_peer *peer) { if (peer->to_backoff != NULL) - return; + return TRUE; if (peer->last_failure.tv_sec > 0) { int backoff_time_spent = timeval_diff_msecs(&ioloop_timeval, &peer->last_failure); + if (backoff_time_spent < (int)peer->backoff_time_msecs) { http_client_peer_debug(peer, "Starting backoff timer for %d msecs", @@ -120,9 +126,21 @@ http_client_peer_connect(struct http_client_peer *peer, unsigned int count) peer->to_backoff = timeout_add ((unsigned int)(peer->backoff_time_msecs - backoff_time_spent), http_client_peer_connect_backoff, peer); - return; + return TRUE; } + + http_client_peer_debug(peer, + "Backoff time already exceeded by %d msecs", + backoff_time_spent - peer->backoff_time_msecs); } + return FALSE; +} + +static void +http_client_peer_connect(struct http_client_peer *peer, unsigned int count) +{ + if (http_client_peer_start_backoff_timer(peer)) + return; http_client_peer_do_connect(peer, count); } @@ -483,8 +501,10 @@ void http_client_peer_unlink_queue(struct http_client_peer *peer, if (*queue_idx == queue) { array_delete(&peer->queues, array_foreach_idx(&peer->queues, queue_idx), 1); - if (array_count(&peer->queues) == 0) - http_client_peer_free(&peer); + if (array_count(&peer->queues) == 0) { + if (!http_client_peer_start_backoff_timer(peer)) + http_client_peer_free(&peer); + } return; } } @@ -511,6 +531,10 @@ void http_client_peer_connection_success(struct http_client_peer *peer) { struct http_client_queue *const *queue; + http_client_peer_debug(peer, + "Successfully connected (connections=%u)", + array_count(&peer->conns)); + peer->last_failure.tv_sec = peer->last_failure.tv_usec = 0; peer->backoff_time_msecs = 0;