dovecot-2.2: http-client: Improved handing of delayed request er...

dovecot at dovecot.org dovecot at dovecot.org
Fri Nov 22 22:13:13 EET 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/6b48a5675512
changeset: 17003:6b48a5675512
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Fri Nov 22 22:08:20 2013 +0200
description:
http-client: Improved handing of delayed request errors.
Originally each request would have its own zero timeout, but now only one
timeout is put in the host object.

diffstat:

 src/lib-http/http-client-host.c    |  59 ++++++++++++++++++++++++++++++++-----
 src/lib-http/http-client-private.h |   7 +++-
 src/lib-http/http-client-request.c |  33 ++++----------------
 3 files changed, 64 insertions(+), 35 deletions(-)

diffs (199 lines):

diff -r 160e489d7c12 -r 6b48a5675512 src/lib-http/http-client-host.c
--- a/src/lib-http/http-client-host.c	Fri Nov 22 22:07:41 2013 +0200
+++ b/src/lib-http/http-client-host.c	Fri Nov 22 22:08:20 2013 +0200
@@ -205,7 +205,7 @@
 {
 	struct http_client_host *host = *_host;
 	struct http_client_queue *const *queue_idx;
-	struct http_client_request *req, *const *reqp;
+	struct http_client_request *req, *const *req_idx;
 	const char *hostname = host->name;
 
 	http_client_host_debug(host, "Host destroy");
@@ -223,30 +223,73 @@
 	array_free(&host->queues);
 
 	while (array_count(&host->delayed_failing_requests) > 0) {
-		reqp = array_idx(&host->delayed_failing_requests, 0);
-		req = *reqp;
+		req_idx = array_idx(&host->delayed_failing_requests, 0);
+		req = *req_idx;
 
 		i_assert(req->refcount == 1);
-		http_client_request_unref(&req);
+		http_client_request_error_delayed(&req);
 	}
 	array_free(&host->delayed_failing_requests);
 
+	if (host->to_failing_requests != NULL)
+		timeout_remove(&host->to_failing_requests);
+
 	i_free(host->ips);
 	i_free(host->name);
 	i_free(host);
 }
 
+static void
+http_client_host_handle_request_errors(struct http_client_host *host)
+{		
+	timeout_remove(&host->to_failing_requests);
+
+	while (array_count(&host->delayed_failing_requests) > 0) {
+		struct http_client_request *const *req_idx =
+			array_idx(&host->delayed_failing_requests, 0);
+		struct http_client_request *req = *req_idx;
+
+		i_assert(req->refcount == 1);
+		http_client_request_error_delayed(&req);
+	}
+	array_clear(&host->delayed_failing_requests);
+}
+
+void http_client_host_delay_request_error(struct http_client_host *host,
+	struct http_client_request *req)
+{
+	if (host->to_failing_requests == NULL) {
+		host->to_failing_requests = timeout_add_short(0,
+			http_client_host_handle_request_errors, host);
+	}
+	array_append(&host->delayed_failing_requests, &req, 1);
+}
+
+void http_client_host_remove_request_error(struct http_client_host *host,
+	struct http_client_request *req)
+{
+	struct http_client_request *const *reqs;
+	unsigned int i, count;
+
+	reqs = array_get(&host->delayed_failing_requests, &count);
+	for (i = 0; i < count; i++) {
+		if (reqs[i] == req) {
+			array_delete(&host->delayed_failing_requests, i, 1);
+			return;
+		}
+	}
+}
+
 void http_client_host_switch_ioloop(struct http_client_host *host)
 {
 	struct http_client_queue *const *queue_idx;
-	struct http_client_request *const *req_idx;
 
 	if (host->dns_lookup != NULL)
 		dns_lookup_switch_ioloop(host->dns_lookup);
 	array_foreach(&host->queues, queue_idx)
 		http_client_queue_switch_ioloop(*queue_idx);
-	array_foreach(&host->delayed_failing_requests, req_idx) {
-		(*req_idx)->to_delayed_error =
-			io_loop_move_timeout(&(*req_idx)->to_delayed_error);
+	if (host->to_failing_requests != NULL) {
+		host->to_failing_requests =
+			io_loop_move_timeout(&host->to_failing_requests);
 	}
 }
diff -r 160e489d7c12 -r 6b48a5675512 src/lib-http/http-client-private.h
--- a/src/lib-http/http-client-private.h	Fri Nov 22 22:07:41 2013 +0200
+++ b/src/lib-http/http-client-private.h	Fri Nov 22 22:08:20 2013 +0200
@@ -75,7 +75,6 @@
 
 	unsigned int delayed_error_status;
 	const char *delayed_error;
-	struct timeout *to_delayed_error;
 
 	http_client_request_callback_t *callback;
 	void *context;
@@ -200,6 +199,7 @@
 
 	/* list of requests in this host that are waiting for ioloop */
 	ARRAY(struct http_client_request *) delayed_failing_requests;
+	struct timeout *to_failing_requests;
 
 	/* requests are managed on a per-port basis */
 	ARRAY_TYPE(http_client_queue) queues;
@@ -247,6 +247,7 @@
 	struct http_response *response);
 void http_client_request_send_error(struct http_client_request *req,
 			       unsigned int status, const char *error);
+void http_client_request_error_delayed(struct http_client_request **_req);
 void http_client_request_error(struct http_client_request *req,
 	unsigned int status, const char *error);
 void http_client_request_redirect(struct http_client_request *req,
@@ -330,6 +331,10 @@
 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_delay_request_error(struct http_client_host *host,
+	struct http_client_request *req);
+void http_client_host_remove_request_error(struct http_client_host *host,
+	struct http_client_request *req);
 void http_client_host_switch_ioloop(struct http_client_host *host);
 
 static inline const char *
diff -r 160e489d7c12 -r 6b48a5675512 src/lib-http/http-client-request.c
--- a/src/lib-http/http-client-request.c	Fri Nov 22 22:07:41 2013 +0200
+++ b/src/lib-http/http-client-request.c	Fri Nov 22 22:08:20 2013 +0200
@@ -50,7 +50,6 @@
 /*
  * Request
  */
-static void http_client_request_remove_delayed(struct http_client_request *req);
 
 static struct http_client_request *
 http_client_request_new(struct http_client *client, const char *method, 
@@ -166,8 +165,8 @@
 	if (client->pending_requests == 0 && client->ioloop != NULL)
 		io_loop_stop(client->ioloop);
 
-	if (req->to_delayed_error != NULL)
-		http_client_request_remove_delayed(req);
+	if (req->delayed_error != NULL)
+		http_client_host_remove_request_error(req->host, req);
 	if (req->payload_input != NULL)
 		i_stream_unref(&req->payload_input);
 	if (req->payload_output != NULL)
@@ -718,30 +717,14 @@
 	}
 }
 
-static void http_client_request_remove_delayed(struct http_client_request *req)
+void http_client_request_error_delayed(struct http_client_request **_req)
 {
-	struct http_client_request *const *reqs;
-	unsigned int i, count;
+	struct http_client_request *req = *_req;
 
+	i_assert(req->delayed_error != NULL && req->delayed_error_status != 0);
 	http_client_request_send_error(req, req->delayed_error_status,
 				       req->delayed_error);
-
-	timeout_remove(&req->to_delayed_error);
-
-	reqs = array_get(&req->host->delayed_failing_requests, &count);
-	for (i = 0; i < count; i++) {
-		if (reqs[i] == req) {
-			array_delete(&req->host->delayed_failing_requests, i, 1);
-			return;
-		}
-	}
-	i_unreached();
-}
-
-static void http_client_request_error_delayed(struct http_client_request *req)
-{
-	http_client_request_remove_delayed(req);
-	http_client_request_unref(&req);
+	http_client_request_unref(_req);
 }
 
 void http_client_request_error(struct http_client_request *req,
@@ -754,9 +737,7 @@
 		i_assert(req->delayed_error == NULL);
 		req->delayed_error = p_strdup(req->pool, error);
 		req->delayed_error_status = status;
-		req->to_delayed_error = timeout_add_short(0,
-			http_client_request_error_delayed, req);
-		array_append(&req->host->delayed_failing_requests, &req, 1);
+		http_client_host_delay_request_error(req->host, req);
 	} else {
 		http_client_request_send_error(req, status, error);
 		http_client_request_unref(&req);


More information about the dovecot-cvs mailing list