]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
director: Don't become desynced if two directors change the same backend in incompati...
authorTimo Sirainen <tss@iki.fi>
Sat, 10 Oct 2015 15:32:06 +0000 (18:32 +0300)
committerTimo Sirainen <tss@iki.fi>
Sat, 10 Oct 2015 15:32:06 +0000 (18:32 +0300)
This would have caused "User hash .. is being redirected to two hosts"
errors, which wouldn't easily go away as the directors have a different view
of what hosts currently exist.

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

index a068fcb030554c0e49424b2d713b7fe8f87192a7..6b02852b43c8bba3e166d0446a5639c75773e4d0 100644 (file)
@@ -842,6 +842,7 @@ static bool ATTR_NULL(3)
 director_cmd_host_int(struct director_connection *conn, const char *const *args,
                      struct director_host *dir_host)
 {
+       struct director_host *src_host = conn->host;
        struct mail_host *host;
        struct ip_addr ip;
        const char *tag = "";
@@ -889,6 +890,23 @@ director_cmd_host_int(struct director_connection *conn, const char *const *args,
                        mail_host_set_tag(host, tag);
                        update = TRUE;
                }
+               if (update && host->desynced) {
+                       vhost_count = I_MIN(vhost_count, host->vhost_count);
+                       if (host->down != down) {
+                               if (host->last_updown_change <= last_updown_change)
+                                       down = host->last_updown_change;
+                       }
+                       last_updown_change = I_MAX(last_updown_change,
+                                                  host->last_updown_change);
+                       i_warning("director(%s): Host %s is being updated before previous update had finished - "
+                                 "setting to state=%s vhosts=%u",
+                                 conn->name, net_ip2addr(&host->ip),
+                                 down ? "down" : "up", vhost_count);
+                       /* make the change appear to come from us, so it
+                          reaches the full ring */
+                       dir_host = NULL;
+                       src_host = conn->dir->self_host;
+               }
        }
 
        if (update) {
@@ -896,7 +914,7 @@ director_cmd_host_int(struct director_connection *conn, const char *const *args,
                                   down, last_updown_change);
                mail_host_set_vhost_count(conn->dir->mail_hosts,
                                          host, vhost_count);
-               director_update_host(conn->dir, conn->host, dir_host, host);
+               director_update_host(conn->dir, src_host, dir_host, host);
        }
        return TRUE;
 }
index 05460169a66341d093c498128acf4cb08462d5e7..f7465b48238ec49189d6a493f1efe871dab8c6a2 100644 (file)
@@ -314,6 +314,7 @@ void director_set_ring_synced(struct director *dir)
                timeout_remove(&dir->to_sync);
        dir->ring_synced = TRUE;
        dir->ring_last_sync_time = ioloop_time;
+       mail_hosts_set_synced(dir->mail_hosts);
        director_set_state_changed(dir);
 }
 
@@ -548,6 +549,8 @@ void director_update_host(struct director *dir, struct director_host *src,
        }
        str_append_c(str, '\n');
        director_update_send(dir, src, str_c(str));
+
+       host->desynced = TRUE;
        director_sync(dir);
 }
 
index bc62829014e26e5688eea0a406314024da7e0c27..6b1ec8a0cffe2c9f41457b5b23a2e4b425b8efeb 100644 (file)
@@ -388,6 +388,14 @@ mail_host_get_by_hash(struct mail_host_list *list, unsigned int hash,
                return mail_host_get_by_hash_direct(list, hash, tag);
 }
 
+void mail_hosts_set_synced(struct mail_host_list *list)
+{
+       struct mail_host *const *hostp;
+
+       array_foreach(&list->hosts, hostp)
+               (*hostp)->desynced = FALSE;
+}
+
 bool mail_hosts_have_usable(struct mail_host_list *list)
 {
        if (list->hosts_unsorted)
index 73947e1587c68e6f0224af2955ec4538542d89ce..f2afb43aeabb602e4845ca644d48b918cc8c77f0 100644 (file)
@@ -15,6 +15,9 @@ struct mail_host {
 
        struct ip_addr ip;
        char *tag;
+
+       /* host was recently changed and ring hasn't synced yet since */
+       unsigned int desynced:1;
 };
 ARRAY_DEFINE_TYPE(mail_host, struct mail_host *);
 
@@ -37,6 +40,7 @@ void mail_host_set_vhost_count(struct mail_host_list *list,
                               unsigned int vhost_count);
 void mail_host_remove(struct mail_host_list *list, struct mail_host *host);
 
+void mail_hosts_set_synced(struct mail_host_list *list);
 bool mail_hosts_have_usable(struct mail_host_list *list);
 const ARRAY_TYPE(mail_host) *mail_hosts_get(struct mail_host_list *list);