dovecot-2.0: login-proxy: If proxy destination is known to be do...

dovecot at dovecot.org dovecot at dovecot.org
Thu Aug 13 01:11:25 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/da0a48b243a2
changeset: 9774:da0a48b243a2
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Aug 12 18:11:15 2009 -0400
description:
login-proxy: If proxy destination is known to be down, fail immediately.
We'll use simple rules:

1. If connection to destination server failed more recently than it
succeeded AND there is currently at least one client trying to connect to
it, fail immediately without even trying to connect.

2. Whenever a connection to destination server fails because of timeout or
some connect failure AND last successful connection to server was before our
connect() started, update the "last failed" timestamp.

With these rules there are no unnecessary connect() attempts or waits to
servers that are down. When the server does come back up, it's noticed
immediately.

diffstat:

4 files changed, 51 insertions(+), 1 deletion(-)
src/login-common/Makefile.am   |    2 +
src/login-common/login-proxy.c |   48 +++++++++++++++++++++++++++++++++++++++-
src/login-common/login-proxy.h |    1 
src/login-common/main.c        |    1 

diffs (187 lines):

diff -r 8e099a00f8a9 -r da0a48b243a2 src/login-common/Makefile.am
--- a/src/login-common/Makefile.am	Wed Aug 12 18:02:20 2009 -0400
+++ b/src/login-common/Makefile.am	Wed Aug 12 18:11:15 2009 -0400
@@ -11,6 +11,7 @@ liblogin_la_SOURCES = \
 	client-common.c \
 	client-common-auth.c \
 	login-proxy.c \
+	login-proxy-state.c \
 	login-settings.c \
 	main.c \
 	sasl-server.c \
@@ -24,6 +25,7 @@ noinst_HEADERS = \
 noinst_HEADERS = \
 	client-common.h \
 	login-proxy.h \
+	login-proxy-state.h \
 	login-settings.h \
 	common.h \
 	sasl-server.h \
diff -r 8e099a00f8a9 -r da0a48b243a2 src/login-common/login-proxy.c
--- a/src/login-common/login-proxy.c	Wed Aug 12 18:02:20 2009 -0400
+++ b/src/login-common/login-proxy.c	Wed Aug 12 18:11:15 2009 -0400
@@ -6,9 +6,11 @@
 #include "ostream.h"
 #include "llist.h"
 #include "str-sanitize.h"
+#include "time-util.h"
 #include "master-service.h"
 #include "client-common.h"
 #include "ssl-proxy.h"
+#include "login-proxy-state.h"
 #include "login-proxy.h"
 
 #define MAX_PROXY_INPUT_SIZE 4096
@@ -25,7 +27,9 @@ struct login_proxy {
 	struct ip_addr ip;
 	struct ssl_proxy *ssl_proxy;
 
+	struct timeval created;
 	struct timeout *to;
+	struct login_proxy_record *state_rec;
 
 	char *host, *user;
 	unsigned int port;
@@ -38,6 +42,7 @@ struct login_proxy {
 	unsigned int disconnecting:1;
 };
 
+static struct login_proxy_state *proxy_state;
 static struct login_proxy *login_proxies = NULL;
 
 static void server_input(struct login_proxy *proxy)
@@ -129,6 +134,19 @@ static void proxy_plain_connected(struct
 		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;
@@ -137,9 +155,13 @@ static void proxy_wait_connect(struct lo
 	if (err != 0) {
 		i_error("proxy: connect(%s, %u) failed: %s",
 			proxy->host, proxy->port, strerror(err));
+		proxy_fail_connect(proxy);
                 login_proxy_free(&proxy);
 		return;
 	}
+	proxy->state_rec->last_success = ioloop_timeval;
+	proxy->state_rec->num_waiting_connections--;
+	proxy->state_rec = NULL;
 
 	if (proxy->to != NULL)
 		timeout_remove(&proxy->to);
@@ -159,6 +181,7 @@ static void proxy_connect_timeout(struct
 static void proxy_connect_timeout(struct login_proxy *proxy)
 {
 	i_error("proxy: connect(%s, %u) timed out", proxy->host, proxy->port);
+	proxy_fail_connect(proxy);
 	login_proxy_free(&proxy);
 }
 
@@ -168,6 +191,7 @@ login_proxy_new(struct client *client, c
 		proxy_callback_t *callback, void *context)
 {
 	struct login_proxy *proxy;
+	struct login_proxy_record *rec;
 	struct ip_addr ip;
 	int fd;
 
@@ -180,6 +204,13 @@ login_proxy_new(struct client *client, c
 		i_error("proxy(%s): %s is not a valid IP",
 			client->virtual_user, set->host);
 		return NULL;
+	}
+
+	rec = login_proxy_state_get(proxy_state, &ip);
+	if (timeval_cmp(&rec->last_failure, &rec->last_success) > 0 &&
+	    rec->num_waiting_connections != 0) {
+		/* the server is down. fail immediately */
+	       return NULL;
 	}
 
 	fd = net_connect_ip(&ip, set->port, NULL);
@@ -190,6 +221,7 @@ login_proxy_new(struct client *client, c
 	}
 
 	proxy = i_new(struct login_proxy, 1);
+	proxy->created = ioloop_timeval;
 	proxy->host = i_strdup(set->host);
 	proxy->user = i_strdup(client->virtual_user);
 	proxy->port = set->port;
@@ -208,6 +240,9 @@ login_proxy_new(struct client *client, c
 
 	proxy->ip = client->ip;
 	proxy->client_fd = -1;
+
+	proxy->state_rec = rec;
+	rec->num_waiting_connections++;
 	return proxy;
 }
 
@@ -222,6 +257,11 @@ void login_proxy_free(struct login_proxy
 		return;
 	proxy->destroying = TRUE;
 
+	if (proxy->to != NULL)
+		timeout_remove(&proxy->to);
+
+	if (proxy->state_rec != NULL)
+		proxy->state_rec->num_waiting_connections--;
 	if (proxy->to != NULL)
 		timeout_remove(&proxy->to);
 
@@ -390,6 +430,11 @@ int login_proxy_starttls(struct login_pr
 	return 0;
 }
 
+void login_proxy_init(void)
+{
+	proxy_state = login_proxy_state_init();
+}
+
 void login_proxy_deinit(void)
 {
 	struct login_proxy *proxy;
@@ -398,4 +443,5 @@ void login_proxy_deinit(void)
 		proxy = login_proxies;
 		login_proxy_free(&proxy);
 	}
-}
+	login_proxy_state_deinit(&proxy_state);
+}
diff -r 8e099a00f8a9 -r da0a48b243a2 src/login-common/login-proxy.h
--- a/src/login-common/login-proxy.h	Wed Aug 12 18:02:20 2009 -0400
+++ b/src/login-common/login-proxy.h	Wed Aug 12 18:11:15 2009 -0400
@@ -61,6 +61,7 @@ enum login_proxy_ssl_flags
 enum login_proxy_ssl_flags
 login_proxy_get_ssl_flags(const struct login_proxy *proxy) ATTR_PURE;
 
+void login_proxy_init(void);
 void login_proxy_deinit(void);
 
 #endif
diff -r 8e099a00f8a9 -r da0a48b243a2 src/login-common/main.c
--- a/src/login-common/main.c	Wed Aug 12 18:02:20 2009 -0400
+++ b/src/login-common/main.c	Wed Aug 12 18:11:15 2009 -0400
@@ -129,6 +129,7 @@ static void main_init(void)
         auth_client_set_connect_notify(auth_client, auth_connect_notify, NULL);
 
 	clients_init();
+	login_proxy_init();
 	master_auth_init(master_service);
 }
 


More information about the dovecot-cvs mailing list