Mercurial > dovecot > core-2.2
changeset 14306:334424e7465e
director: Keep track of the highest supported protocol version in the ring.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 07 Mar 2012 20:16:33 +0200 |
parents | 94de7605f50f |
children | 8c6ff808902c |
files | src/director/director-connection.c src/director/director.c src/director/director.h |
diffstat | 3 files changed, 49 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- 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);
--- 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)
--- 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,