Mercurial > dovecot > core-2.2
changeset 14494:d27b743c9921
director: Delay disconnecting director after sending CONNECT command.
The director may not otherwise read the CONNECT.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 20 Apr 2012 19:09:55 +0300 |
parents | 1856e9085f94 |
children | 03f44d61d582 |
files | src/director/director-connection.c |
diffstat | 1 files changed, 32 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- 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); } }