]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
director: If SYNCs are received during handshake, send them later.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 24 Oct 2016 18:58:03 +0000 (21:58 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 25 Oct 2016 18:01:22 +0000 (21:01 +0300)
This fixes delays during handshake:
Error: Ring SYNC appears to have got lost, resending

src/director/director-connection.c
src/director/director-host.h

index 0bab7c4731edfccf7ff2fc03768a1b9f7569f137..973d1d051b0e4f4bead508c622ccbd43e9b8efcf 100644 (file)
@@ -316,6 +316,25 @@ static bool director_has_outgoing_connections(struct director *dir)
        return FALSE;
 }
 
+static void director_send_delayed_syncs(struct director *dir)
+{
+       struct director_host *const *hostp;
+
+       i_assert(dir->right != NULL);
+
+       dir_debug("director(%s): Sending delayed SYNCs", dir->right->name);
+       array_foreach(&dir->dir_hosts, hostp) {
+               if ((*hostp)->delayed_sync_seq == 0)
+                       continue;
+
+               director_sync_send(dir, *hostp, (*hostp)->delayed_sync_seq,
+                                  (*hostp)->delayed_sync_minor_version,
+                                  (*hostp)->delayed_sync_timestamp,
+                                  (*hostp)->delayed_sync_hosts_hash);
+               (*hostp)->delayed_sync_seq = 0;
+       }
+}
+
 static bool director_connection_assign_right(struct director_connection *conn)
 {
        struct director *dir = conn->dir;
@@ -343,6 +362,7 @@ static bool director_connection_assign_right(struct director_connection *conn)
        i_free(conn->name);
        conn->name = i_strdup_printf("%s/right", conn->host->name);
        director_connection_assigned(conn);
+       director_send_delayed_syncs(dir);
        return TRUE;
 }
 
@@ -1422,6 +1442,13 @@ director_connection_sync_host(struct director_connection *conn,
                        /* forward it to the connection on right */
                        director_sync_send(dir, host, seq, minor_version,
                                           timestamp, hosts_hash);
+               } else {
+                       dir_debug("director(%s): We have no right connection - "
+                                 "delay replying to SYNC until finished", conn->name);
+                       host->delayed_sync_seq = seq;
+                       host->delayed_sync_minor_version = minor_version;
+                       host->delayed_sync_timestamp = timestamp;
+                       host->delayed_sync_hosts_hash = hosts_hash;
                }
        }
        return TRUE;
index 08c1020da33b74f2bce3dc5a22b663cc87f1497d..68979c259eac0a55a6f46b85bbd6ebe3de2e45c9 100644 (file)
@@ -30,6 +30,14 @@ struct director_host {
        /* Last time host was detected to be down */
        time_t last_network_failure;
        time_t last_protocol_failure;
+
+       /* When we finish getting a right connection, send a SYNC with these
+          parameters (if delayed_sync_seq != 0) */
+       uint32_t delayed_sync_seq;
+       unsigned int delayed_sync_minor_version;
+       unsigned int delayed_sync_timestamp;
+       unsigned int delayed_sync_hosts_hash;
+
        /* we are this director */
        unsigned int self:1;
        unsigned int removed:1;