diff src/director/director-connection.c @ 13940:9e43af01f147

director: Make sure ring syncing doesn't get lost when directors get disconnected.
author Timo Sirainen <tss@iki.fi>
date Tue, 17 Jan 2012 22:21:57 +0200
parents c70965e8b27d
children 493ebb2cfc73
line wrap: on
line diff
--- a/src/director/director-connection.c	Tue Jan 17 17:20:07 2012 +0200
+++ b/src/director/director-connection.c	Tue Jan 17 22:21:57 2012 +0200
@@ -675,6 +675,41 @@
 	return FALSE;
 }
 
+static void
+director_connection_sync_host(struct director_connection *conn,
+			      struct director_host *host,
+			      uint32_t seq, const char *line)
+{
+	struct director *dir = conn->dir;
+
+	if (host->self) {
+		if (dir->sync_seq != seq) {
+			/* stale SYNC event */
+			return;
+		}
+
+		if (!dir->ring_handshaked) {
+			/* the ring is handshaked */
+			director_set_ring_handshaked(dir);
+		} else if (dir->ring_synced) {
+			/* duplicate SYNC (which was sent just in case the
+			   previous one got lost) */
+		} else {
+			if (dir->debug) {
+				i_debug("Ring is synced (%s sent seq=%u)",
+					conn->name, seq);
+			}
+			director_set_ring_synced(dir);
+		}
+	} else {
+		/* forward it to the connection on right */
+		if (dir->right != NULL) {
+			director_connection_send(dir->right,
+				t_strconcat(line, "\n", NULL));
+		}
+	}
+}
+
 static bool director_connection_sync(struct director_connection *conn,
 				     const char *const *args, const char *line)
 {
@@ -693,36 +728,16 @@
 	/* find the originating director. if we don't see it, it was already
 	   removed and we can ignore this sync. */
 	host = director_host_lookup(dir, &ip, port);
-	if (host == NULL)
-		return TRUE;
-
-	if (host->self) {
-		if (dir->sync_seq != seq) {
-			/* stale SYNC event */
-			return TRUE;
-		}
+	if (host != NULL)
+		director_connection_sync_host(conn, host, seq, line);
 
-		if (!dir->ring_handshaked) {
-			/* the ring is handshaked */
-			director_set_ring_handshaked(dir);
-		} else if (dir->ring_synced) {
-			i_error("Received SYNC from %s (seq=%u) "
-				"while already synced", conn->name, seq);
-			return TRUE;
-		} else {
-			if (dir->debug) {
-				i_debug("Ring is synced (%s sent seq=%u)",
-					conn->name, seq);
-			}
-			director_set_ring_synced(dir);
-		}
-		return TRUE;
-	}
-
-	/* forward it to the connection on right */
-	if (dir->right != NULL) {
+	if (!dir->ring_synced && dir->left != NULL && dir->right != NULL &&
+	    (host == NULL || !host->self)) {
+		/* send a new SYNC in case the previous one got dropped */
 		director_connection_send(dir->right,
-					 t_strconcat(line, "\n", NULL));
+			t_strdup_printf("SYNC\t%s\t%u\t%u\n",
+					net_ip2addr(&dir->self_ip),
+					dir->self_port, dir->sync_seq));
 	}
 	return TRUE;
 }