]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: client: Fixed recovery after connection failure.
authorStephan Bosch <stephan@rename-it.nl>
Wed, 1 Oct 2014 07:33:49 +0000 (10:33 +0300)
committerStephan Bosch <stephan@rename-it.nl>
Wed, 1 Oct 2014 07:33:49 +0000 (10:33 +0300)
If a parallel already connected connection was active, the queue wasn't notified of the failure.
Only pending connections should be considered in this case and not established ones.

src/lib-http/http-client-peer.c
src/lib-http/http-client-private.h

index f26fe8ad5f66e803384104a0efb57558bf7555d4..8fc3b87fa5392f2fe6d0cc91896e4c5a81efccb8 100644 (file)
@@ -529,22 +529,28 @@ void http_client_peer_connection_failure(struct http_client_peer *peer,
 {
        const struct http_client_settings *set = &peer->client->set;
        struct http_client_queue *const *queue;
-       unsigned int num_urgent;
+       unsigned int pending;
 
-       i_assert(array_count(&peer->conns) > 0);
+       peer->last_failure = ioloop_timeval;
 
-       http_client_peer_debug(peer, "Failed to make connection");
+       /* count number of pending connections */
+       pending = http_client_peer_pending_connections(peer);
+       i_assert(pending > 0);
 
-       peer->last_failure = ioloop_timeval;
+       http_client_peer_debug(peer,
+               "Failed to make connection "
+               "(connections=%u, connecting=%u)",
+               array_count(&peer->conns), pending);
 
-       if (array_count(&peer->conns) == 1) {
+       /* manage backoff timer only when this was the only attempt */
+       if (pending == 1) {
                if (peer->backoff_time_msecs == 0)
                        peer->backoff_time_msecs = set->connect_backoff_time_msecs;
                else
                        peer->backoff_time_msecs *= 2;
        }
 
-       if (array_count(&peer->conns) > 1) {
+       if (pending > 1) {
                /* if there are other connections attempting to connect, wait
                   for them before failing the requests. remember that we had
                   trouble with connecting so in future we don't try to create
@@ -558,9 +564,6 @@ void http_client_peer_connection_failure(struct http_client_peer *peer,
                        http_client_queue_connection_failure(*queue, &peer->addr, reason);
                }
        }
-       if (array_count(&peer->conns) == 0 &&
-           http_client_peer_requests_pending(peer, &num_urgent) == 0)
-               http_client_peer_free(&peer);
 }
 
 void http_client_peer_connection_lost(struct http_client_peer *peer)
@@ -586,7 +589,8 @@ void http_client_peer_connection_lost(struct http_client_peer *peer)
                http_client_peer_free(&peer);
 }
 
-unsigned int http_client_peer_idle_connections(struct http_client_peer *peer)
+unsigned int
+http_client_peer_idle_connections(struct http_client_peer *peer)
 {
        struct http_client_connection *const *conn_idx;
        unsigned int idle = 0;
@@ -600,6 +604,21 @@ unsigned int http_client_peer_idle_connections(struct http_client_peer *peer)
        return idle;
 }
 
+unsigned int
+http_client_peer_pending_connections(struct http_client_peer *peer)
+{
+       struct http_client_connection *const *conn_idx;
+       unsigned int pending = 0;
+
+       /* find idle connections */
+       array_foreach(&peer->conns, conn_idx) {
+               if (!(*conn_idx)->closing && !(*conn_idx)->connected)
+                       pending++;
+       }
+
+       return pending;
+}
+
 void http_client_peer_switch_ioloop(struct http_client_peer *peer)
 {
        if (peer->to_req_handling != NULL) {
index 35badd4a4fa91e6d72853bed7d52362873c4cc78..f16b332a01a7696e5d8fb4ced4d0811b236b8ce9 100644 (file)
@@ -308,7 +308,10 @@ void http_client_peer_connection_failure(struct http_client_peer *peer,
                                         const char *reason);
 void http_client_peer_connection_lost(struct http_client_peer *peer);
 bool http_client_peer_is_connected(struct http_client_peer *peer);
-unsigned int http_client_peer_idle_connections(struct http_client_peer *peer);
+unsigned int
+http_client_peer_idle_connections(struct http_client_peer *peer);
+unsigned int
+http_client_peer_pending_connections(struct http_client_peer *peer);
 void http_client_peer_switch_ioloop(struct http_client_peer *peer);
 
 struct http_client_queue *