changeset 22214:1b4a0735b158

lib-http: client: Only drop queued requests when a DNS lookup fails; not also the ones that are already in progress.
author Stephan Bosch <stephan.bosch@dovecot.fi>
date Wed, 24 May 2017 20:19:11 +0200
parents f8d4ae988e7f
children 05aff1909f97
files src/lib-http/http-client-host.c src/lib-http/http-client-private.h src/lib-http/http-client-queue.c
diffstat 3 files changed, 39 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-http/http-client-host.c	Wed May 24 21:59:32 2017 +0200
+++ b/src/lib-http/http-client-host.c	Wed May 24 20:19:11 2017 +0200
@@ -53,8 +53,7 @@
 	error = t_strdup_printf("Failed to lookup host %s: %s",
 				host->name, error);
 	array_foreach_modifiable(&host->queues, queue_idx) {
-		http_client_queue_fail(*queue_idx,
-			HTTP_CLIENT_REQUEST_ERROR_HOST_LOOKUP_FAILED, error);
+		http_client_queue_host_lookup_failure(*queue_idx, error);
 	}
 
 	http_client_host_check_idle(host);
--- a/src/lib-http/http-client-private.h	Wed May 24 21:59:32 2017 +0200
+++ b/src/lib-http/http-client-private.h	Wed May 24 20:19:11 2017 +0200
@@ -486,11 +486,11 @@
 http_client_queue_create(struct http_client_host *host,
 	const struct http_client_peer_addr *addr);
 void http_client_queue_free(struct http_client_queue *queue);
-void http_client_queue_fail(struct http_client_queue *queue,
-	unsigned int status, const char *error);
 void http_client_queue_connection_setup(struct http_client_queue *queue);
 unsigned int
 http_client_queue_host_lookup_done(struct http_client_queue *queue);
+void http_client_queue_host_lookup_failure(
+	struct http_client_queue *queue, const char *error);
 void http_client_queue_submit_request(struct http_client_queue *queue,
 	struct http_client_request *req);
 void
--- a/src/lib-http/http-client-queue.c	Wed May 24 21:59:32 2017 +0200
+++ b/src/lib-http/http-client-queue.c	Wed May 24 20:19:11 2017 +0200
@@ -19,13 +19,15 @@
 #define TIMEOUT_CMP_MARGIN_USECS 2000
 
 static void
+http_client_queue_fail(struct http_client_queue *queue,
+	unsigned int status, const char *error);
+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
  */
@@ -165,26 +167,43 @@
  * Error handling
  */
 
-void http_client_queue_fail(struct http_client_queue *queue,
-	unsigned int status, const char *error)
+static void
+http_client_queue_fail_full(struct http_client_queue *queue,
+	unsigned int status, const char *error, bool queued_only)
 {
 	ARRAY_TYPE(http_client_request) *req_arr, treqs;
 	struct http_client_request **req_idx;
+	unsigned int retained = 0;
 
-	/* abort all pending requests */
+	/* abort requests */
 	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) {
-		http_client_request_error(req_idx, status, error);
+		struct http_client_request *req = *req_idx;
+
+		i_assert(req->state >= HTTP_REQUEST_STATE_QUEUED);
+		if (queued_only &&
+			req->state != HTTP_REQUEST_STATE_QUEUED)
+			retained++;
+		else
+			http_client_request_error(&req, status, error);
 	}
 
-	/* all queues should be empty now... unless new requests were submitted
-	   from the callback. this invariant captures it all: */
-	i_assert((array_count(&queue->delayed_requests) +
+  /* all queues should be empty now... unless new requests were submitted
+     from the callback. this invariant captures it all: */
+	i_assert((retained +
+		array_count(&queue->delayed_requests) +
 		array_count(&queue->queued_requests) +
 		array_count(&queue->queued_urgent_requests)) ==
-		array_count(&queue->requests));
+			array_count(&queue->requests));
+}
+
+static void
+http_client_queue_fail(struct http_client_queue *queue,
+	unsigned int status, const char *error)
+{
+	http_client_queue_fail_full(queue, status, error, FALSE);
 }
 
 /*
@@ -423,6 +442,14 @@
 	return reqs_pending;
 }
 
+void http_client_queue_host_lookup_failure(
+	struct http_client_queue *queue, const char *error)
+{
+	http_client_queue_fail_full(queue,
+		HTTP_CLIENT_REQUEST_ERROR_HOST_LOOKUP_FAILED,
+		error, TRUE);
+}
+
 void
 http_client_queue_connection_success(struct http_client_queue *queue,
 					 const struct http_client_peer_addr *addr)