Skip to content

Commit

Permalink
lib-http: client: Destroy host and associated queue objects after no …
Browse files Browse the repository at this point in the history
…more requests remain and an idle timeout expires.
  • Loading branch information
stephanbosch authored and GitLab committed Nov 2, 2016
1 parent 1e63e30 commit c4b2dba
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 7 deletions.
77 changes: 71 additions & 6 deletions src/lib-http/http-client-host.c
Expand Up @@ -15,6 +15,8 @@

#include "http-client-private.h"

#define HTTP_CLIENT_HOST_MINIMUM_IDLE_TIMEOUT_MSECS 100

/*
* Logging
*/
Expand Down Expand Up @@ -54,6 +56,8 @@ http_client_host_lookup_failure(struct http_client_host *host,
http_client_queue_fail(*queue_idx,
HTTP_CLIENT_REQUEST_ERROR_HOST_LOOKUP_FAILED, error);
}

http_client_host_check_idle(host);
}

static void
Expand All @@ -76,6 +80,7 @@ http_client_host_dns_callback(const struct dns_lookup_result *result,
"DNS lookup successful; got %d IPs", result->ips_count);

i_assert(result->ips_count > 0);
i_free(host->ips);
host->ips_count = result->ips_count;
host->ips = i_new(struct ip_addr, host->ips_count);
memcpy(host->ips, result->ips, sizeof(*host->ips) * host->ips_count);
Expand All @@ -101,6 +106,9 @@ static void http_client_host_lookup
int ret;

i_assert(!host->explicit_ip);
i_assert(host->dns_lookup == NULL);

host->ips_count = 0;

if (client->set.dns_client != NULL) {
http_client_host_debug(host,
Expand Down Expand Up @@ -135,6 +143,7 @@ static void http_client_host_lookup
http_client_host_debug(host,
"DNS lookup successful; got %d IPs", ips_count);

i_free(host->ips);
host->ips_count = ips_count;
host->ips = i_new(struct ip_addr, ips_count);
memcpy(host->ips, ips, ips_count * sizeof(*ips));
Expand All @@ -160,6 +169,9 @@ int http_client_host_refresh(struct http_client_host *host)
timeval_cmp(&host->ips_timeout, &ioloop_timeval) > 0)
return 0;

if (host->to_idle != NULL)
return 0;

http_client_host_debug(host,
"IPs have expired; need to refresh DNS lookup");

Expand Down Expand Up @@ -247,6 +259,10 @@ void http_client_host_submit_request(struct http_client_host *host,
queue = http_client_queue_create(host, &addr);
http_client_queue_submit_request(queue, req);

/* cancel host idle timeout */
if (host->to_idle != NULL)
timeout_remove(&host->to_idle);

if (host->unix_local) {
http_client_queue_connection_setup(queue);
return;
Expand All @@ -257,29 +273,37 @@ void http_client_host_submit_request(struct http_client_host *host,
http_client_host_lookup(host);

/* make a connection if we have an IP already */
if (host->ips_count == 0)
return;

http_client_queue_connection_setup(queue);
if (host->ips_count > 0)
http_client_queue_connection_setup(queue);
}

void http_client_host_free(struct http_client_host **_host)
{
struct http_client_host *host = *_host;
struct http_client_queue *const *queue_idx;
ARRAY_TYPE(http_client_queue) queues;
const char *hostname = host->name;

http_client_host_debug(host, "Host destroy");

if (host->to_idle != NULL)
timeout_remove(&host->to_idle);

DLLIST_REMOVE(&host->client->hosts_list, host);
if (host != host->client->unix_host)
if (host == host->client->unix_host)
host->client->unix_host = NULL;
else
hash_table_remove(host->client->hosts, hostname);

if (host->dns_lookup != NULL)
dns_lookup_abort(&host->dns_lookup);

/* drop request queues */
array_foreach(&host->queues, queue_idx) {
t_array_init(&queues, array_count(&host->queues));
array_copy(&queues.arr, 0,
&host->queues.arr, 0, array_count(&host->queues));
array_clear(&host->queues);
array_foreach(&queues, queue_idx) {
http_client_queue_free(*queue_idx);
}
array_free(&host->queues);
Expand All @@ -289,6 +313,45 @@ void http_client_host_free(struct http_client_host **_host)
i_free(host);
}

static void
http_client_host_idle_timeout(struct http_client_host *host)
{
http_client_host_debug(host, "Idle host timed out");
http_client_host_free(&host);
}

void http_client_host_check_idle(struct http_client_host *host)
{
struct http_client_queue *const *queue_idx;
unsigned int requests = 0;
int timeout = 0;

if (host->to_idle != NULL)
return;

array_foreach(&host->queues, queue_idx) {
requests += http_client_queue_requests_active(*queue_idx);
}

if (requests > 0)
return;

if (!host->unix_local && !host->explicit_ip &&
host->ips_timeout.tv_sec > 0) {
timeout = timeval_diff_msecs
(&host->ips_timeout, &ioloop_timeval);
}

if (timeout <= HTTP_CLIENT_HOST_MINIMUM_IDLE_TIMEOUT_MSECS)
timeout = HTTP_CLIENT_HOST_MINIMUM_IDLE_TIMEOUT_MSECS;

host->to_idle = timeout_add_short(timeout,
http_client_host_idle_timeout, host);

http_client_host_debug(host,
"Host is idle (timeout = %u msecs)", timeout);
}

void http_client_host_switch_ioloop(struct http_client_host *host)
{
struct http_client_queue *const *queue_idx;
Expand All @@ -297,4 +360,6 @@ void http_client_host_switch_ioloop(struct http_client_host *host)
dns_lookup_switch_ioloop(host->dns_lookup);
array_foreach(&host->queues, queue_idx)
http_client_queue_switch_ioloop(*queue_idx);
if (host->to_idle != NULL)
host->to_idle = io_loop_move_timeout(&host->to_idle);
}
4 changes: 4 additions & 0 deletions src/lib-http/http-client-private.h
Expand Up @@ -270,6 +270,9 @@ struct http_client_host {
/* active DNS lookup */
struct dns_lookup *dns_lookup;

/* timeouts */
struct timeout *to_idle;

bool unix_local:1;
bool explicit_ip:1;
};
Expand Down Expand Up @@ -528,6 +531,7 @@ void http_client_host_free(struct http_client_host **_host);
void http_client_host_submit_request(struct http_client_host *host,
struct http_client_request *req);
void http_client_host_switch_ioloop(struct http_client_host *host);
void http_client_host_check_idle(struct http_client_host *host);
int http_client_host_refresh(struct http_client_host *host);

/*
Expand Down
4 changes: 3 additions & 1 deletion src/lib-http/http-client-queue.c
Expand Up @@ -412,7 +412,6 @@ void http_client_queue_connection_setup(struct http_client_queue *queue)
(void)http_client_queue_connection_attempt(queue);
}


unsigned int
http_client_queue_host_lookup_done(struct http_client_queue *queue)
{
Expand Down Expand Up @@ -647,6 +646,9 @@ http_client_queue_drop_request(struct http_client_queue *queue,
}
req->queue = NULL;
array_delete(&queue->requests, i, 1);

if (array_count(&queue->requests) == 0)
http_client_host_check_idle(queue->host);
return;
}

Expand Down

0 comments on commit c4b2dba

Please sign in to comment.