Mercurial > dovecot > core-2.2
changeset 11350:5f77c91f3df0 HEAD
director: Preserve old mail server state when a new director connects to ring.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 20 May 2010 10:43:47 +0200 |
parents | 350208d17fcd |
children | c57c1ff9c5f1 |
files | src/director/director-connection.c |
diffstat | 1 files changed, 46 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/src/director/director-connection.c Thu May 20 10:43:19 2010 +0200 +++ b/src/director/director-connection.c Thu May 20 10:43:47 2010 +0200 @@ -47,6 +47,7 @@ unsigned int version_received:1; unsigned int me_received:1; unsigned int handshake_received:1; + unsigned int ignore_host_events:1; }; static void director_connection_ping(struct director_connection *conn); @@ -233,6 +234,34 @@ } static bool +director_cmd_host_hand_start(struct director_connection *conn, + const char *const *args) +{ + const ARRAY_TYPE(mail_host) *hosts; + struct mail_host *const *hostp; + unsigned int remote_ring_completed; + + if (args == NULL || str_to_uint(args[0], &remote_ring_completed) < 0) { + i_error("director(%s): Invalid HOST-HAND-START args", + conn->name); + return FALSE; + } + + if (remote_ring_completed && !conn->dir->ring_handshaked) { + /* clear everything we have and use only what remote sends us */ + hosts = mail_hosts_get(); + while (array_count(hosts) > 0) { + hostp = array_idx(hosts, 0); + director_remove_host(conn->dir, conn->host, *hostp); + } + } else if (!remote_ring_completed && conn->dir->ring_handshaked) { + /* ignore whatever remote sends */ + conn->ignore_host_events = TRUE; + } + return TRUE; +} + +static bool director_cmd_host(struct director_connection *conn, const char *const *args) { struct mail_host *host; @@ -246,6 +275,11 @@ i_error("director(%s): Invalid HOST args", conn->name); return FALSE; } + if (conn->ignore_host_events) { + /* remote is sending hosts in a handshake, but it doesn't have + a completed ring and we do. */ + return TRUE; + } host = mail_host_lookup(&ip); if (host == NULL) { @@ -363,6 +397,13 @@ return director_cmd_director(conn, args); if (conn->in && strcmp(cmd, "HOST") == 0 && conn->me_received) return director_cmd_host(conn, args); + if (strcmp(cmd, "HOST-HAND-START") == 0) + return director_cmd_host_hand_start(conn, args); + if (strcmp(cmd, "HOST-HAND-END") == 0) { + conn->ignore_host_events = TRUE; + return TRUE; + } + /* only incoming connections get a USER list */ if (conn->in && strcmp(cmd, "USER") == 0 && conn->me_received) return director_handshake_cmd_user(conn, args); @@ -536,14 +577,17 @@ } } -static void director_connection_send_hosts(string_t *str) +static void +director_connection_send_hosts(struct director_connection *conn, string_t *str) { struct mail_host *const *hostp; + str_printfa(str, "HOST-HAND-START\t%u\n", conn->dir->ring_handshaked); array_foreach(mail_hosts_get(), hostp) { str_printfa(str, "HOST\t%s\t%u\n", net_ip2addr(&(*hostp)->ip), (*hostp)->vhost_count); } + str_printfa(str, "HOST-HAND-END\t%u\n", conn->dir->ring_handshaked); } static int director_connection_send_users(struct director_connection *conn) @@ -650,7 +694,7 @@ director_connection_send_handshake(conn); director_connection_send_directors(conn, str); - director_connection_send_hosts(str); + director_connection_send_hosts(conn, str); director_connection_send(conn, str_c(str)); conn->user_iter = user_directory_iter_init(dir->users);