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