dovecot-2.1: director: Keep track of the highest supported proto...

dovecot at dovecot.org dovecot at dovecot.org
Wed Mar 7 20:16:44 EET 2012


details:   http://hg.dovecot.org/dovecot-2.1/rev/334424e7465e
changeset: 14270:334424e7465e
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Mar 07 20:16:33 2012 +0200
description:
director: Keep track of the highest supported protocol version in the ring.

diffstat:

 src/director/director-connection.c |  41 +++++++++++++++++++------------------
 src/director/director.c            |  27 ++++++++++++++++++------
 src/director/director.h            |   8 +++++++
 3 files changed, 49 insertions(+), 27 deletions(-)

diffs (194 lines):

diff -r 94de7605f50f -r 334424e7465e src/director/director-connection.c
--- a/src/director/director-connection.c	Wed Mar 07 16:58:37 2012 +0200
+++ b/src/director/director-connection.c	Wed Mar 07 20:16:33 2012 +0200
@@ -19,10 +19,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 
-#define DIRECTOR_VERSION_NAME "director"
-#define DIRECTOR_VERSION_MAJOR 1
-#define DIRECTOR_VERSION_MINOR 0
-
 #define MAX_INBUF_SIZE 1024
 #define MAX_OUTBUF_SIZE (1024*1024*10)
 #define OUTBUF_FLUSH_THRESHOLD (1024*128)
@@ -586,10 +582,8 @@
 		   finished by sending a SYNC. if we get it back, it's done. */
 		dir->sync_seq++;
 		director_set_ring_unsynced(dir);
-		director_connection_send(dir->right,
-			t_strdup_printf("SYNC\t%s\t%u\t%u\n",
-					net_ip2addr(&dir->self_ip),
-					dir->self_port, dir->sync_seq));
+		director_sync_send(dir, dir->self_host, dir->sync_seq,
+				   DIRECTOR_VERSION_MINOR);
 	}
 	if (conn->to_ping != NULL)
 		timeout_remove(&conn->to_ping);
@@ -693,16 +687,22 @@
 static void
 director_connection_sync_host(struct director_connection *conn,
 			      struct director_host *host,
-			      uint32_t seq, const char *line)
+			      uint32_t seq, unsigned int minor_version)
 {
 	struct director *dir = conn->dir;
 
+	if (minor_version > DIRECTOR_VERSION_MINOR) {
+		/* we're not up to date */
+		minor_version = DIRECTOR_VERSION_MINOR;
+	}
+
 	if (host->self) {
 		if (dir->sync_seq != seq) {
 			/* stale SYNC event */
 			return;
 		}
 
+		dir->synced_minor_version = minor_version;
 		if (!dir->ring_handshaked) {
 			/* the ring is handshaked */
 			director_set_ring_handshaked(dir);
@@ -716,35 +716,36 @@
 			}
 			director_set_ring_synced(dir);
 		}
-	} else {
+	} else if (dir->right != NULL) {
 		/* forward it to the connection on right */
-		if (dir->right != NULL) {
-			director_connection_send(dir->right,
-				t_strconcat(line, "\n", NULL));
-		}
+		director_sync_send(dir, host, seq, minor_version);
 	}
 }
 
 static bool director_connection_sync(struct director_connection *conn,
-				     const char *const *args, const char *line)
+				     const char *const *args)
 {
 	struct director *dir = conn->dir;
 	struct director_host *host;
 	struct ip_addr ip;
-	unsigned int port, seq;
+	unsigned int port, seq, minor_version = 0;
 
-	if (str_array_length(args) != 3 ||
+	if (str_array_length(args) < 3 ||
 	    !director_args_parse_ip_port(conn, args, &ip, &port) ||
 	    str_to_uint(args[2], &seq) < 0) {
 		i_error("director(%s): Invalid SYNC args", conn->name);
 		return FALSE;
 	}
+	if (args[3] != NULL)
+		minor_version = atoi(args[3]);
 
 	/* 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)
-		director_connection_sync_host(conn, host, seq, line);
+	if (host != NULL) {
+		director_connection_sync_host(conn, host, seq,
+					      minor_version);
+	}
 
 	if (host == NULL || !host->self)
 		director_resend_sync(dir);
@@ -866,7 +867,7 @@
 	if (strcmp(cmd, "DIRECTOR") == 0)
 		return director_cmd_director(conn, args);
 	if (strcmp(cmd, "SYNC") == 0)
-		return director_connection_sync(conn, args, line);
+		return director_connection_sync(conn, args);
 	if (strcmp(cmd, "CONNECT") == 0)
 		return director_cmd_connect(conn, args);
 
diff -r 94de7605f50f -r 334424e7465e src/director/director.c
--- a/src/director/director.c	Wed Mar 07 16:58:37 2012 +0200
+++ b/src/director/director.c	Wed Mar 07 20:16:33 2012 +0200
@@ -155,6 +155,7 @@
 			   it must have failed recently */
 			director_connection_deinit(&dir->left);
 		}
+		dir->synced_minor_version = DIRECTOR_VERSION_MINOR;
 		if (!dir->ring_handshaked)
 			director_set_ring_handshaked(dir);
 		else
@@ -232,14 +233,27 @@
 	director_set_state_changed(dir);
 }
 
+void director_sync_send(struct director *dir, struct director_host *host,
+			uint32_t seq, unsigned int minor_version)
+{
+	string_t *str = t_str_new(128);
+
+	str_printfa(str, "SYNC\t%s\t%u\t%u",
+		    net_ip2addr(&host->ip), host->port, seq);
+	if (minor_version > 0) {
+		/* only minor_version>0 supports this parameter */
+		str_printfa(str, "\t%u", minor_version);
+	}
+	str_append_c(str, '\n');
+	director_connection_send(dir->right, str_c(str));
+}
+
 bool director_resend_sync(struct director *dir)
 {
 	if (!dir->ring_synced && dir->left != NULL && dir->right != NULL) {
 		/* send a new SYNC in case the previous one got dropped */
-		director_connection_send(dir->right,
-			t_strdup_printf("SYNC\t%s\t%u\t%u\n",
-					net_ip2addr(&dir->self_ip),
-					dir->self_port, dir->sync_seq));
+		director_sync_send(dir, dir->self_host, dir->sync_seq,
+				   DIRECTOR_VERSION_MINOR);
 		if (dir->to_sync != NULL)
 			timeout_reset(dir->to_sync);
 		return TRUE;
@@ -295,9 +309,8 @@
 	if (dir->left != NULL)
 		director_connection_wait_sync(dir->left);
 	director_connection_wait_sync(dir->right);
-	director_connection_send(dir->right, t_strdup_printf(
-		"SYNC\t%s\t%u\t%u\n", net_ip2addr(&dir->self_ip),
-		dir->self_port, dir->sync_seq));
+	director_sync_send(dir, dir->self_host, dir->sync_seq,
+			   DIRECTOR_VERSION_MINOR);
 }
 
 void director_sync_freeze(struct director *dir)
diff -r 94de7605f50f -r 334424e7465e src/director/director.h
--- a/src/director/director.h	Wed Mar 07 16:58:37 2012 +0200
+++ b/src/director/director.h	Wed Mar 07 20:16:33 2012 +0200
@@ -4,6 +4,10 @@
 #include "network.h"
 #include "director-settings.h"
 
+#define DIRECTOR_VERSION_NAME "director"
+#define DIRECTOR_VERSION_MAJOR 1
+#define DIRECTOR_VERSION_MINOR 0
+
 struct director;
 struct mail_host;
 struct user;
@@ -46,6 +50,8 @@
 
 	struct ipc_client *ipc_proxy;
 	unsigned int sync_seq;
+	/* the lowest minor version supported by the ring */
+	unsigned int synced_minor_version;
 	time_t ring_last_sync_time;
 
 	/* director ring handshaking is complete.
@@ -76,6 +82,8 @@
 void director_set_ring_synced(struct director *dir);
 void director_set_ring_unsynced(struct director *dir);
 void director_set_state_changed(struct director *dir);
+void director_sync_send(struct director *dir, struct director_host *host,
+			uint32_t seq, unsigned int minor_version);
 bool director_resend_sync(struct director *dir);
 
 void director_update_host(struct director *dir, struct director_host *src,


More information about the dovecot-cvs mailing list