dovecot-2.2: lib-http: client: Added support for absolute reques...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Oct 4 14:33:36 UTC 2014
details: http://hg.dovecot.org/dovecot-2.2/rev/4f175c27bea5
changeset: 17881:4f175c27bea5
user: Stephan Bosch <stephan at rename-it.nl>
date: Sat Oct 04 17:32:48 2014 +0300
description:
lib-http: client: Added support for absolute request timeout.
Requests cannot survive beyond this deadline.
diffstat:
src/lib-http/http-client-connection.c | 13 +-
src/lib-http/http-client-host.c | 7 +-
src/lib-http/http-client-private.h | 15 +-
src/lib-http/http-client-queue.c | 380 +++++++++++++++++++++++++++------
src/lib-http/http-client-request.c | 62 +++++-
src/lib-http/http-client.c | 2 +
src/lib-http/http-client.h | 11 +
7 files changed, 404 insertions(+), 86 deletions(-)
diffs (truncated from 862 to 300 lines):
diff -r c6431fb17158 -r 4f175c27bea5 src/lib-http/http-client-connection.c
--- a/src/lib-http/http-client-connection.c Sat Oct 04 17:31:38 2014 +0300
+++ b/src/lib-http/http-client-connection.c Sat Oct 04 17:32:48 2014 +0300
@@ -423,9 +423,8 @@
net_set_nonblock(conn->conn.fd_in, TRUE);
conn->incoming_payload = NULL;
-
+ conn->pending_request = NULL;
http_client_request_finish(&req);
- conn->pending_request = NULL;
/* room for new requests */
if (http_client_connection_is_ready(conn))
@@ -438,6 +437,9 @@
necessary. */
conn->to_input =
timeout_add_short(0, http_client_payload_destroyed_timeout, conn);
+
+ i_assert(req != NULL);
+ http_client_request_unref(&req);
}
static bool
@@ -451,6 +453,7 @@
i_assert(conn->incoming_payload == NULL);
i_assert(conn->pending_request == NULL);
+ http_client_request_ref(req);
req->state = HTTP_REQUEST_STATE_GOT_RESPONSE;
if (response->payload != NULL) {
@@ -480,6 +483,7 @@
/* the callback managed to get this connection destroyed */
if (!retrying)
http_client_request_finish(&req);
+ http_client_request_unref(&req);
return FALSE;
}
@@ -493,6 +497,7 @@
http_client_connection_input,
&conn->conn);
}
+ http_client_request_unref(&req);
return TRUE;
}
@@ -501,13 +506,17 @@
payload = response->payload;
response->payload = NULL;
conn->pending_request = req;
+
+ /* request is dereferenced in payload destroy callback */
i_stream_unref(&payload);
+
if (conn->to_input != NULL) {
/* already finished reading the payload */
http_client_payload_finished(conn);
}
} else {
http_client_request_finish(&req);
+ http_client_request_unref(&req);
}
if (conn->incoming_payload == NULL) {
diff -r c6431fb17158 -r 4f175c27bea5 src/lib-http/http-client-host.c
--- a/src/lib-http/http-client-host.c Sat Oct 04 17:31:38 2014 +0300
+++ b/src/lib-http/http-client-host.c Sat Oct 04 17:32:48 2014 +0300
@@ -82,11 +82,12 @@
/* make connections to requested ports */
array_foreach_modifiable(&host->queues, queue_idx) {
struct http_client_queue *queue = *queue_idx;
- unsigned int count = array_count(&queue->request_queue);
+ unsigned int reqs_pending =
+ http_client_queue_requests_pending(queue, NULL);
queue->ips_connect_idx = queue->ips_connect_start_idx = 0;
- if (count > 0)
+ if (reqs_pending > 0)
http_client_queue_connection_setup(queue);
- requests += count;
+ requests += reqs_pending;
}
if (requests == 0 && host->client->ioloop != NULL)
diff -r c6431fb17158 -r 4f175c27bea5 src/lib-http/http-client-private.h
--- a/src/lib-http/http-client-private.h Sat Oct 04 17:31:38 2014 +0300
+++ b/src/lib-http/http-client-private.h Sat Oct 04 17:32:48 2014 +0300
@@ -75,6 +75,8 @@
struct timeval submit_time;
struct timeval sent_time;
struct timeval response_time;
+ struct timeval timeout_time;
+ unsigned int timeout_msecs;
unsigned int attempts;
unsigned int redirects;
@@ -194,10 +196,17 @@
this can be more than one when soft connect timeouts are enabled */
ARRAY_TYPE(http_client_peer) pending_peers;
+ /* all requests associated to this queue
+ (ordered by earliest timeout first) */
+ ARRAY_TYPE(http_client_request) requests;
+
+ /* delayed requests waiting to be released after delay */
+ ARRAY_TYPE(http_client_request) delayed_requests;
+
/* requests pending in queue to be picked up by connections */
- ARRAY_TYPE(http_client_request) request_queue, delayed_request_queue;
+ ARRAY_TYPE(http_client_request) queued_requests, queued_urgent_requests;
- struct timeout *to_connect, *to_delayed;
+ struct timeout *to_connect, *to_request, *to_delayed;
};
struct http_client_host {
@@ -332,7 +341,7 @@
const struct http_client_peer_addr *addr, bool no_urgent);
unsigned int
http_client_queue_requests_pending(struct http_client_queue *queue,
- unsigned int *num_urgent_r);
+ unsigned int *num_urgent_r) ATTR_NULL(2);
void
http_client_queue_connection_success(struct http_client_queue *queue,
const struct http_client_peer_addr *addr);
diff -r c6431fb17158 -r 4f175c27bea5 src/lib-http/http-client-queue.c
--- a/src/lib-http/http-client-queue.c Sat Oct 04 17:31:38 2014 +0300
+++ b/src/lib-http/http-client-queue.c Sat Oct 04 17:32:48 2014 +0300
@@ -18,6 +18,14 @@
#define TIMEOUT_CMP_MARGIN_USECS 2000
+static void
+http_client_queue_set_delay_timer(struct http_client_queue *queue,
+ struct timeval time);
+static void
+http_client_queue_set_request_timer(struct http_client_queue *queue,
+ const struct timeval *time);
+
+
/*
* Logging
*/
@@ -42,13 +50,9 @@
}
/*
- * Queue
+ * Queue object
*/
-static void
-http_client_queue_set_delay_timer(struct http_client_queue *queue,
- struct timeval time);
-
static struct http_client_queue *
http_client_queue_find(struct http_client_host *host,
const struct http_client_peer_addr *addr)
@@ -99,8 +103,10 @@
queue->addr.https_name = queue->https_name;
queue->name = name;
queue->ips_connect_idx = 0;
- i_array_init(&queue->request_queue, 16);
- i_array_init(&queue->delayed_request_queue, 4);
+ i_array_init(&queue->requests, 16);
+ i_array_init(&queue->queued_requests, 16);
+ i_array_init(&queue->queued_urgent_requests, 16);
+ i_array_init(&queue->delayed_requests, 4);
array_append(&host->queues, &queue, 1);
}
@@ -114,8 +120,10 @@
i_free(queue->https_name);
if (array_is_created(&queue->pending_peers))
array_free(&queue->pending_peers);
- array_free(&queue->request_queue);
- array_free(&queue->delayed_request_queue);
+ array_free(&queue->requests);
+ array_free(&queue->queued_requests);
+ array_free(&queue->queued_urgent_requests);
+ array_free(&queue->delayed_requests);
if (queue->to_connect != NULL)
timeout_remove(&queue->to_connect);
if (queue->to_delayed != NULL)
@@ -124,6 +132,10 @@
i_free(queue);
}
+/*
+ * Error handling
+ */
+
void http_client_queue_fail(struct http_client_queue *queue,
unsigned int status, const char *error)
{
@@ -131,7 +143,7 @@
struct http_client_request **req_idx;
/* abort all pending requests */
- req_arr = &queue->request_queue;
+ req_arr = &queue->requests;
t_array_init(&treqs, array_count(req_arr));
array_copy(&treqs.arr, 0, &req_arr->arr, 0, array_count(req_arr));
array_foreach_modifiable(&treqs, req_idx) {
@@ -139,43 +151,15 @@
}
array_clear(req_arr);
- /* abort all delayed requests */
- req_arr = &queue->delayed_request_queue;
- array_clear(&treqs);
- array_copy(&treqs.arr, 0, &req_arr->arr, 0, array_count(req_arr));
- array_foreach_modifiable(&treqs, req_idx) {
- http_client_request_error(*req_idx, status, error);
- }
- array_clear(req_arr);
+ /* all queues must be empty now */
+ i_assert(array_count(&queue->delayed_requests) == 0);
+ i_assert(array_count(&queue->queued_requests) == 0);
+ i_assert(array_count(&queue->queued_urgent_requests) == 0);
}
-void
-http_client_queue_drop_request(struct http_client_queue *queue,
- struct http_client_request *req)
-{
- ARRAY_TYPE(http_client_request) *req_arr;
- struct http_client_request **req_idx;
-
- /* remove from main queue */
- req_arr = &queue->request_queue;
- array_foreach_modifiable(req_arr, req_idx) {
- if (*req_idx == req) {
- array_delete(req_arr, array_foreach_idx(req_arr, req_idx), 1);
- break;
- }
- }
-
- /* remove from delay queue */
- if (req->release_time.tv_sec > 0) {
- req_arr = &queue->delayed_request_queue;
- array_foreach_modifiable(req_arr, req_idx) {
- if (*req_idx == req) {
- array_delete(req_arr, array_foreach_idx(req_arr, req_idx), 1);
- break;
- }
- }
- }
-}
+/*
+ * Connection management
+ */
static bool
http_client_queue_is_last_connect_ip(struct http_client_queue *queue)
@@ -234,7 +218,9 @@
struct http_client_host *host = queue->host;
struct http_client_peer *peer = NULL;
const struct http_client_peer_addr *addr = &queue->addr;
- unsigned int num_requests = array_count(&queue->request_queue);
+ unsigned int num_requests =
+ array_count(&queue->queued_requests) +
+ array_count(&queue->queued_urgent_requests);
if (num_requests == 0)
return;
@@ -248,6 +234,7 @@
(addr->https_name == NULL ? "" :
t_strdup_printf(" (SSL=%s)", addr->https_name)), num_requests);
+
/* create/get peer */
peer = http_client_peer_get(queue->client, addr);
http_client_peer_link_queue(peer, queue);
@@ -285,7 +272,7 @@
/* start soft connect time-out (but only if we have another IP left) */
msecs = host->client->set.soft_connect_timeout_msecs;
if (!http_client_queue_is_last_connect_ip(queue) && msecs > 0 &&
- queue->to_connect == NULL) {
+ queue->to_connect == NULL) {
queue->to_connect =
timeout_add(msecs, http_client_queue_soft_connect_timeout, queue);
}
@@ -344,7 +331,7 @@
t_strdup_printf(" (SSL=%s)", addr->https_name)), reason,
(array_is_created(&queue->pending_peers) ?
array_count(&queue->pending_peers): 0),
- array_count(&queue->request_queue));
+ array_count(&queue->requests));
if (array_is_created(&queue->pending_peers) &&
array_count(&queue->pending_peers) > 0) {
struct http_client_peer *const *peer_idx;
@@ -391,18 +378,217 @@
return TRUE;
}
+/*
+ * Main request queue
+ */
More information about the dovecot-cvs
mailing list