dovecot-2.2: lib-http: Always try to connect to host's all IPs w...

dovecot at dovecot.org dovecot at dovecot.org
Wed Jul 10 01:45:51 EEST 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/dee7822501b0
changeset: 16577:dee7822501b0
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Jul 10 01:44:40 2013 +0300
description:
lib-http: Always try to connect to host's all IPs when connections fail.
Previously this was done only when the new connections started from the
first IP.

diffstat:

 src/lib-http/http-client-host.c    |  44 +++++++++++++++++++++++++++++++------
 src/lib-http/http-client-private.h |   4 +++
 2 files changed, 41 insertions(+), 7 deletions(-)

diffs (121 lines):

diff -r 1fbac590b9d4 -r dee7822501b0 src/lib-http/http-client-host.c
--- a/src/lib-http/http-client-host.c	Fri Jun 28 19:48:37 2013 +0300
+++ b/src/lib-http/http-client-host.c	Wed Jul 10 01:44:40 2013 +0300
@@ -114,6 +114,20 @@
 	}
 }
 
+static bool
+http_client_hport_is_last_connect_ip(struct http_client_host_port *hport)
+{
+	i_assert(hport->ips_connect_idx < hport->host->ips_count);
+	i_assert(hport->ips_connect_start_idx < hport->host->ips_count);
+
+	/* we'll always go through all the IPs. we don't necessarily start
+	   connecting from the first IP, so we'll need to treat the IPs as
+	   a ring buffer where we automatically wrap back to the first IP
+	   when necessary. */
+	return (hport->ips_connect_idx + 1) % hport->host->ips_count ==
+		hport->ips_connect_start_idx;
+}
+
 static void
 http_client_host_port_soft_connect_timeout(struct http_client_host_port *hport)
 {
@@ -122,7 +136,7 @@
 	if (hport->to_connect != NULL)
 		timeout_remove(&hport->to_connect);
 
-	if (hport->ips_connect_idx + 1 >= host->ips_count)
+	if (http_client_hport_is_last_connect_ip(hport))
 		return;
 
 	/* if our our previous connection attempt takes longer than the
@@ -135,7 +149,7 @@
 		hport->https_name == NULL ? "" :
 			t_strdup_printf(" (SSL=%s)", hport->https_name));
 
-	hport->ips_connect_idx++;
+	hport->ips_connect_idx = (hport->ips_connect_idx + 1) % host->ips_count;
 	http_client_host_port_connection_setup(hport);
 }
 
@@ -161,7 +175,7 @@
 
 	/* start soft connect time-out (but only if we have another IP left) */
 	msecs = host->client->set.soft_connect_timeout_msecs;
-	if (host->ips_count - hport->ips_connect_idx > 1 && msecs > 0 &&
+	if (!http_client_hport_is_last_connect_ip(hport) && msecs > 0 &&
 	    hport->to_connect == NULL) {
 		hport->to_connect =
 			timeout_add(msecs, http_client_host_port_soft_connect_timeout, hport);
@@ -200,11 +214,26 @@
 	}
 }
 
+static unsigned int
+http_client_host_get_ip_idx(struct http_client_host *host,
+			    const struct ip_addr *ip)
+{
+	unsigned int i;
+
+	for (i = 0; i < host->ips_count; i++) {
+		if (net_ip_compare(&host->ips[i], ip))
+			return i;
+	}
+	i_unreached();
+}
+
 static void
 http_client_host_port_connection_success(struct http_client_host_port *hport,
 					 const struct http_client_peer_addr *addr)
 {
 	/* we achieved at least one connection the the addr->ip */
+	hport->ips_connect_start_idx =
+		http_client_host_get_ip_idx(hport->host, &addr->ip);
 
 	/* stop soft connect time-out */
 	if (hport->to_connect != NULL)
@@ -237,15 +266,16 @@
 	if (hport->to_connect != NULL)
 		timeout_remove(&hport->to_connect);
 
-	i_assert(hport->ips_connect_idx < host->ips_count);
-	if (++hport->ips_connect_idx == host->ips_count) {
+	if (http_client_hport_is_last_connect_ip(hport)) {
 		/* all IPs failed, but retry all of them again on the
 		   next request. */
-		hport->ips_connect_idx = 0;
+		hport->ips_connect_idx = hport->ips_connect_start_idx =
+			(hport->ips_connect_idx + 1) % host->ips_count;
 		http_client_host_port_error(hport,
 			HTTP_CLIENT_REQUEST_ERROR_CONNECT_FAILED, reason);
 		return FALSE;
 	}
+	hport->ips_connect_idx = (hport->ips_connect_idx + 1) % host->ips_count;
 
 	http_client_host_port_connection_setup(hport);
 	return TRUE;
@@ -329,7 +359,7 @@
 	/* make connections to requested ports */
 	array_foreach_modifiable(&host->ports, hport) {
 		unsigned int count = array_count(&hport->request_queue);
-		hport->ips_connect_idx = 0;
+		hport->ips_connect_idx = hport->ips_connect_start_idx = 0;
 		if (count > 0)
 			http_client_host_port_connection_setup(hport);
 		requests += count;
diff -r 1fbac590b9d4 -r dee7822501b0 src/lib-http/http-client-private.h
--- a/src/lib-http/http-client-private.h	Fri Jun 28 19:48:37 2013 +0300
+++ b/src/lib-http/http-client-private.h	Wed Jul 10 01:44:40 2013 +0300
@@ -78,6 +78,10 @@
 
 	/* current index in host->ips */
 	unsigned int ips_connect_idx;
+	/* the first IP that started the current round of connection attempts.
+	   initially 0, and later set to the (ip_idx+1) of the last successful
+	   connected IP */
+	unsigned int ips_connect_start_idx;
 	/* number of connections trying to connect for this host+port */
 	unsigned int pending_connection_count;
 


More information about the dovecot-cvs mailing list