changeset 9313:34179f0f4d6a HEAD

login proxy: Improvements to "fail immediately if server is down" handling. Now we use more precise timestamps. Also don't mark server as failed if another connect had succeeded after we started connecting.
author Timo Sirainen <tss@iki.fi>
date Wed, 12 Aug 2009 17:55:14 -0400
parents 00a1d109ecf6
children 68c1d3ab515d
files src/login-common/login-proxy-state.h src/login-common/login-proxy.c
diffstat 2 files changed, 22 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/login-common/login-proxy-state.h	Wed Aug 12 17:27:25 2009 -0400
+++ b/src/login-common/login-proxy-state.h	Wed Aug 12 17:55:14 2009 -0400
@@ -2,8 +2,8 @@
 #define LOGIN_PROXY_STATE_H
 
 struct login_proxy_record {
-	time_t last_failure;
-	time_t last_success;
+	struct timeval last_failure;
+	struct timeval last_success;
 	unsigned int num_waiting_connections;
 };
 
--- a/src/login-common/login-proxy.c	Wed Aug 12 17:27:25 2009 -0400
+++ b/src/login-common/login-proxy.c	Wed Aug 12 17:55:14 2009 -0400
@@ -6,6 +6,7 @@
 #include "ostream.h"
 #include "llist.h"
 #include "str-sanitize.h"
+#include "time-util.h"
 #include "client-common.h"
 #include "ssl-proxy.h"
 #include "login-proxy-state.h"
@@ -25,6 +26,7 @@
 	struct ip_addr ip;
 	struct ssl_proxy *ssl_proxy;
 
+	struct timeval created;
 	struct timeout *to;
 	struct login_proxy_record *state_rec;
 
@@ -132,6 +134,19 @@
 		io_add(proxy->server_fd, IO_READ, proxy_prelogin_input, proxy);
 }
 
+static void proxy_fail_connect(struct login_proxy *proxy)
+{
+	if (timeval_cmp(&proxy->created, &proxy->state_rec->last_success) < 0) {
+		/* there was a successful connection done since we started
+		   connecting. perhaps this is just a temporary one-off
+		   failure. */
+	} else {
+		proxy->state_rec->last_failure = ioloop_timeval;
+	}
+	proxy->state_rec->num_waiting_connections--;
+	proxy->state_rec = NULL;
+}
+
 static void proxy_wait_connect(struct login_proxy *proxy)
 {
 	int err;
@@ -140,11 +155,11 @@
 	if (err != 0) {
 		i_error("proxy: connect(%s, %u) failed: %s",
 			proxy->host, proxy->port, strerror(err));
-		proxy->state_rec->last_failure = ioloop_time;
+		proxy_fail_connect(proxy);
                 login_proxy_free(&proxy);
 		return;
 	}
-	proxy->state_rec->last_success = ioloop_time;
+	proxy->state_rec->last_success = ioloop_timeval;
 	proxy->state_rec->num_waiting_connections--;
 	proxy->state_rec = NULL;
 
@@ -166,7 +181,7 @@
 static void proxy_connect_timeout(struct login_proxy *proxy)
 {
 	i_error("proxy: connect(%s, %u) timed out", proxy->host, proxy->port);
-	proxy->state_rec->last_failure = ioloop_time;
+	proxy_fail_connect(proxy);
 	login_proxy_free(&proxy);
 }
 
@@ -194,7 +209,7 @@
 	}
 
 	rec = login_proxy_state_get(proxy_state, &ip);
-	if (rec->last_failure > rec->last_success &&
+	if (timeval_cmp(&rec->last_failure, &rec->last_success) > 0 &&
 	    rec->num_waiting_connections != 0) {
 		/* the server is down. fail immediately */
 		return NULL;
@@ -208,6 +223,7 @@
 	}
 
 	proxy = i_new(struct login_proxy, 1);
+	proxy->created = ioloop_timeval;
 	proxy->host = i_strdup(host);
 	proxy->user = i_strdup(client->virtual_user);
 	proxy->port = port;