Skip to content

Commit

Permalink
lib-http: client: peer: Notify all peers in a peer pool about a succe…
Browse files Browse the repository at this point in the history
…ssful connection.

This allows peers for which the last connection attempt failed (which was not
the last pending attempt in the pool) to try again. This solves a problem that
could potentially cause a hang with multiple parallel clients creating serveral
new connections at once.
  • Loading branch information
stephanbosch authored and villesavolainen committed Sep 7, 2018
1 parent 2ec17d0 commit 2335b99
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
42 changes: 42 additions & 0 deletions src/lib-http/http-client-peer.c
Expand Up @@ -24,6 +24,8 @@ static void
http_client_peer_shared_connection_failure(
struct http_client_peer_shared *pshared);
static void
http_client_peer_connection_succeeded_pool(struct http_client_peer *peer);
static void
http_client_peer_connection_failed_pool(struct http_client_peer *peer,
const char *reason);

Expand Down Expand Up @@ -219,6 +221,25 @@ http_client_peer_pool_connection_success(
array_count(&ppool->conns));

http_client_peer_shared_connection_success(ppool->peer);

if (array_count(&ppool->pending_conns) > 0) {
/* if there are other connections attempting to connect, wait
for them before notifying other peer objects about the
success (which may be premature). */
} else {
struct http_client_peer *peer;

/* this was the only/last connection and connecting to it
succeeded. notify all interested peers in this pool about the
success */
peer = ppool->peer->peers_list;
while (peer != NULL) {
struct http_client_peer *peer_next = peer->shared_next;
if (peer->ppool == ppool)
http_client_peer_connection_succeeded_pool(peer);
peer = peer_next;
}
}
}

static void
Expand Down Expand Up @@ -1207,6 +1228,25 @@ void http_client_peer_connection_failure(struct http_client_peer *peer,
array_count(&peer->conns));

http_client_peer_pool_connection_failure(ppool, reason);

peer->connect_failed = TRUE;
}

static void
http_client_peer_connection_succeeded_pool(struct http_client_peer *peer)
{
if (!peer->connect_failed)
return;
peer->connect_failed = FALSE;

e_debug(peer->event,
"A connection succeeded within our peer pool, "
"so this peer can retry connecting as well if needed "
"(%u connections exist)", array_count(&peer->conns));

/* if there are pending requests for this peer, try creating a new
connection for them. if not, this peer will wind itself down. */
http_client_peer_trigger_request_handler(peer);
}

static void
Expand All @@ -1219,6 +1259,8 @@ http_client_peer_connection_failed_pool(struct http_client_peer *peer,
"Failed to establish any connection within our peer pool: %s ",
reason);

peer->connect_failed = TRUE;

/* failed to make any connection. a second connect will probably also
fail, so just try another IP for the hosts(s) or abort all requests
if this was the only/last option. */
Expand Down
1 change: 1 addition & 0 deletions src/lib-http/http-client-private.h
Expand Up @@ -278,6 +278,7 @@ struct http_client_peer {
/* zero time-out for consolidating request handling */
struct timeout *to_req_handling;

bool connect_failed:1; /* last connection attempt failed */
bool connect_backoff:1; /* peer is waiting for backoff timout*/
bool disconnected:1; /* peer is already disconnected */
bool handling_requests:1;/* currently running request handler */
Expand Down

0 comments on commit 2335b99

Please sign in to comment.