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