dovecot-2.1: director: Delay disconnecting director after sendin...

dovecot at dovecot.org dovecot at dovecot.org
Fri Apr 20 19:13:13 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.1/rev/d27b743c9921
changeset: 14458:d27b743c9921
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Apr 20 19:09:55 2012 +0300
description:
director: Delay disconnecting director after sending CONNECT command.
The director may not otherwise read the CONNECT.

diffstat:

 src/director/director-connection.c |  47 +++++++++++++++++++++++++------------
 1 files changed, 32 insertions(+), 15 deletions(-)

diffs (143 lines):

diff -r 1856e9085f94 -r d27b743c9921 src/director/director-connection.c
--- a/src/director/director-connection.c	Fri Apr 20 19:08:25 2012 +0300
+++ b/src/director/director-connection.c	Fri Apr 20 19:09:55 2012 +0300
@@ -70,6 +70,7 @@
 /* If outgoing director connection exists for less than this many seconds,
    mark the host as failed so we won't try to reconnect to it immediately */
 #define DIRECTOR_SUCCESS_MIN_CONNECT_SECS 40
+#define DIRECTOR_WAIT_DISCONNECT_MSECS 10
 
 #if DIRECTOR_CONNECTION_DONE_TIMEOUT_MSECS <= DIRECTOR_CONNECTION_PING_TIMEOUT_MSECS
 #  error DIRECTOR_CONNECTION_DONE_TIMEOUT_MSECS is too low
@@ -96,7 +97,7 @@
 	struct io *io;
 	struct istream *input;
 	struct ostream *output;
-	struct timeout *to, *to_ping, *to_pong;
+	struct timeout *to_disconnect, *to_ping, *to_pong;
 
 	struct user_directory_iter *user_iter;
 
@@ -166,16 +167,28 @@
 	conn->to_ping = timeout_add(msecs, director_connection_ping, conn);
 }
 
+static void director_connection_wait_timeout(struct director_connection *conn)
+{
+	director_connection_deinit(&conn);
+}
+
 static void director_connection_send_connect(struct director_connection *conn,
 					     struct director_host *host)
 {
 	const char *connect_str;
 
+	if (conn->to_disconnect != NULL)
+		return;
+
 	connect_str = t_strdup_printf("CONNECT\t%s\t%u\n",
 				      net_ip2addr(&host->ip), host->port);
 	director_connection_send(conn, connect_str);
 	(void)o_stream_flush(conn->output);
 	o_stream_uncork(conn->output);
+
+	conn->to_disconnect =
+		timeout_add(DIRECTOR_WAIT_DISCONNECT_MSECS,
+			    director_connection_wait_timeout, conn);
 }
 
 static void director_connection_assigned(struct director_connection *conn)
@@ -226,7 +239,7 @@
 			  "us, should use %s instead",
 			  conn->name, dir->left->host->name);
 		director_connection_send_connect(conn, dir->left->host);
-		return FALSE;
+		return TRUE;
 	} else {
 		/* this new connection is the correct one, but wait until the
 		   old connection gets disconnected before using this one.
@@ -249,7 +262,8 @@
 	array_foreach(&dir->connections, connp) {
 		conn = *connp;
 
-		if (conn->in && conn->handshake_received && conn != dir->left) {
+		if (conn->in && conn->handshake_received &&
+		    conn->to_disconnect == NULL && conn != dir->left) {
 			/* either use this or disconnect it */
 			if (!director_connection_assign_left(conn)) {
 				/* we don't want this */
@@ -266,7 +280,7 @@
 	struct director_connection *const *connp;
 
 	array_foreach(&dir->connections, connp) {
-		if (!(*connp)->in)
+		if (!(*connp)->in && (*connp)->to_disconnect == NULL)
 			return TRUE;
 	}
 	return FALSE;
@@ -1104,15 +1118,13 @@
 		conn = *connp;
 
 		if (conn->in && conn != dir->left && conn->me_received &&
+		    conn->to_disconnect == NULL &&
 		    director_host_cmp_to_self(dir->left->host, conn->host,
 					      dir->self_host) < 0) {
 			i_warning("Director connection %s tried to connect to "
 				  "us, should use %s instead",
 				  conn->name, dir->left->host->name);
 			director_connection_send_connect(conn, dir->left->host);
-			director_connection_deinit(&conn);
-			director_disconnect_wrong_lefts(dir);
-			return;
 		}
 	}
 }
@@ -1234,6 +1246,17 @@
 		return;
 	}
 
+	if (conn->to_disconnect != NULL) {
+		/* just read everything the remote sends, and wait for it
+		   to disconnect. we mainly just want the remote to read the
+		   CONNECT we sent it. */
+		size_t size;
+
+		(void)i_stream_get_data(conn->input, &size);
+		i_stream_skip(conn->input, size);
+		return;
+	}
+
 	director_sync_freeze(dir);
 	while ((line = i_stream_next_line(conn->input)) != NULL) {
 		T_BEGIN {
@@ -1451,8 +1474,8 @@
 
 	if (conn->user_iter != NULL)
 		user_directory_iter_deinit(&conn->user_iter);
-	if (conn->to != NULL)
-		timeout_remove(&conn->to);
+	if (conn->to_disconnect != NULL)
+		timeout_remove(&conn->to_disconnect);
 	if (conn->to_pong != NULL)
 		timeout_remove(&conn->to_pong);
 	timeout_remove(&conn->to_ping);
@@ -1501,11 +1524,6 @@
 		director_connect(dir);
 }
 
-static void director_connection_timeout(struct director_connection *conn)
-{
-	director_connection_disconnected(&conn);
-}
-
 void director_connection_send(struct director_connection *conn,
 			      const char *data)
 {
@@ -1524,7 +1542,6 @@
 				"disconnecting", conn->name);
 		}
 		o_stream_close(conn->output);
-		conn->to = timeout_add(0, director_connection_timeout, conn);
 	}
 }
 


More information about the dovecot-cvs mailing list