From: Timo Sirainen Date: Wed, 19 May 2010 11:08:33 +0000 (+0200) Subject: director: If connecting to director fails, try connecting to next one. X-Git-Tag: 2.0.beta6~203 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4fe3f07477bae6da3fb8d8fa9bab10ab82ada2bd;p=thirdparty%2Fdovecot%2Fcore.git director: If connecting to director fails, try connecting to next one. --HG-- branch : HEAD --- diff --git a/src/director/director-connection.c b/src/director/director-connection.c index 1e0f7b020f..088747ca90 100644 --- a/src/director/director-connection.c +++ b/src/director/director-connection.c @@ -370,7 +370,7 @@ director_connection_handle_handshake(struct director_connection *conn, director_handshake_cmd_done(conn); return TRUE; } - i_error("director(%s): Unknown command (in this state): %s", + i_error("director(%s): Invalid handshake command: %s", conn->name, cmd); return FALSE; } @@ -456,8 +456,15 @@ director_connection_handle_line(struct director_connection *conn, i_error("director(%s): Received empty line", conn->name); return FALSE; } - if (!conn->handshake_received) - return director_connection_handle_handshake(conn, cmd, args); + if (!conn->handshake_received) { + if (!director_connection_handle_handshake(conn, cmd, args)) { + /* invalid commands during handshake, + we probably don't want to reconnect here */ + conn->host->last_failed = ioloop_time; + return FALSE; + } + return TRUE; + } if (strcmp(cmd, "USER") == 0) return director_cmd_user(conn, args); @@ -623,13 +630,18 @@ director_connection_init_in(struct director *dir, int fd) static void director_connection_connected(struct director_connection *conn) { + struct director *dir = conn->dir; string_t *str = t_str_new(1024); int err; if ((err = net_geterror(conn->fd)) != 0) { + conn->host->last_failed = ioloop_time; i_error("director(%s): connect() failed: %s", conn->name, strerror(err)); director_connection_deinit(&conn); + + /* try connecting to next server */ + director_connect(dir); return; } conn->connected = TRUE; @@ -641,7 +653,7 @@ static void director_connection_connected(struct director_connection *conn) director_connection_send_hosts(str); director_connection_send(conn, str_c(str)); - conn->user_iter = user_directory_iter_init(conn->dir->users); + conn->user_iter = user_directory_iter_init(dir->users); (void)director_connection_send_users(conn); } diff --git a/src/director/director-host.h b/src/director/director-host.h index 77c3a4cec8..fb9015ccfa 100644 --- a/src/director/director-host.h +++ b/src/director/director-host.h @@ -17,6 +17,9 @@ struct director_host { trust the one that has the highest sequence. */ unsigned int last_seq; + /* Last time host was detected to be down/broken */ + time_t last_failed; + /* we are this director */ unsigned int self:1; }; diff --git a/src/director/director.c b/src/director/director.c index 00dd700fe3..67ce78a558 100644 --- a/src/director/director.c +++ b/src/director/director.c @@ -10,6 +10,8 @@ #include "director-connection.h" #include "director.h" +#define DIRECTOR_RECONNECT_RETRY_SECS 60 + static bool director_is_self_ip_set(struct director *dir) { struct ip_addr ip; @@ -90,14 +92,20 @@ int director_connect_host(struct director *dir, struct director_host *host) i_assert(dir->right == NULL); + if (host->last_failed + DIRECTOR_RECONNECT_RETRY_SECS > ioloop_time) { + /* failed recently, don't try retrying here */ + return -1; + } + fd = net_connect_ip(&host->ip, host->port, NULL); if (fd == -1) { + host->last_failed = ioloop_time; i_error("connect(%s) failed: %m", host->name); return -1; } dir->right = director_connection_init_out(dir, fd, host); - return 1; + return 0; } void director_connect(struct director *dir) @@ -114,7 +122,7 @@ void director_connect(struct director *dir) for (i = 1; i < count; i++) { unsigned int idx = (self_idx + i) % count; - if (director_connect_host(dir, hosts[idx]) > 0) + if (director_connect_host(dir, hosts[idx]) == 0) break; } if (i == count) {