dovecot-2.2: replicator: Have remote dsync notify the replicator...

dovecot at dovecot.org dovecot at dovecot.org
Sun Apr 7 14:46:51 EEST 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/f1ba737bc241
changeset: 16217:f1ba737bc241
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Apr 07 14:46:45 2013 +0300
description:
replicator: Have remote dsync notify the replicator that the user was just synced.
This way the replicators are roughly in sync.

diffstat:

 src/doveadm/dsync/doveadm-dsync.c               |  58 ++++++++++++++++++++++--
 src/replication/replicator/doveadm-connection.c |  28 ++++++++++++
 src/replication/replicator/dsync-client.c       |   2 +-
 3 files changed, 82 insertions(+), 6 deletions(-)

diffs (170 lines):

diff -r 9824f8df62a3 -r f1ba737bc241 src/doveadm/dsync/doveadm-dsync.c
--- a/src/doveadm/dsync/doveadm-dsync.c	Sat Apr 06 21:01:41 2013 +0300
+++ b/src/doveadm/dsync/doveadm-dsync.c	Sun Apr 07 14:46:45 2013 +0300
@@ -36,7 +36,7 @@
 #include <ctype.h>
 #include <sys/wait.h>
 
-#define DSYNC_COMMON_GETOPT_ARGS "+dEfg:l:m:n:Nr:Rs:"
+#define DSYNC_COMMON_GETOPT_ARGS "+dEfg:l:m:n:Nr:Rs:U"
 #define DSYNC_REMOTE_CMD_EXIT_WAIT_SECS 30
 
 enum dsync_run_type {
@@ -78,6 +78,7 @@
 	unsigned int remote_user_prefix:1;
 	unsigned int no_mail_sync:1;
 	unsigned int local_location_from_arg:1;
+	unsigned int replicator_notify:1;
 };
 
 static bool legacy_dsync = FALSE;
@@ -441,6 +442,42 @@
 				     name, temp_prefix);
 }
 
+static void
+dsync_replicator_notify(struct dsync_cmd_context *ctx, const char *state_str)
+{
+#define REPLICATOR_HANDSHAKE "VERSION\treplicator-doveadm-client\t1\t0\n"
+	const char *path;
+	string_t *str;
+	int fd;
+
+	path = t_strdup_printf("%s/replicator-doveadm",
+			       ctx->ctx.cur_mail_user->set->base_dir);
+	fd = net_connect_unix(path);
+	if (fd == -1) {
+		if (errno == ECONNREFUSED || errno == ENOENT) {
+			/* replicator not running on this server. ignore. */
+			return;
+		}
+		i_error("net_connect_unix(%s) failed: %m", path);
+		return;
+	}
+	str = t_str_new(128);
+	str_append(str, REPLICATOR_HANDSHAKE"NOTIFY\t");
+	str_append_tabescaped(str, ctx->ctx.cur_mail_user->username);
+	str_append_c(str, '\t');
+	if (ctx->sync_type == DSYNC_BRAIN_SYNC_TYPE_FULL)
+		str_append_c(str, 'f');
+	str_append_c(str, '\t');
+	str_append_tabescaped(str, state_str);
+	str_append_c(str, '\n');
+	if (write_full(fd, str_data(str), str_len(str)) < 0)
+		i_error("write(%s) failed: %m", path);
+	/* we only wanted to notify replicator. we don't care enough about the
+	   answer to wait for it. */
+	if (close(fd) < 0)
+		i_error("close(%s) failed: %m", path);
+}
+
 static int
 cmd_dsync_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
 {
@@ -450,6 +487,7 @@
 	struct mail_namespace *sync_ns = NULL;
 	enum dsync_brain_flags brain_flags;
 	bool remote_errors_logged = FALSE;
+	string_t *state_str = NULL;
 	int status = 0, ret = 0;
 
 	user->admin = TRUE;
@@ -501,13 +539,15 @@
 	}
 
 	if (ctx->state_input != NULL) {
-		string_t *str = t_str_new(128);
-		dsync_brain_get_state(brain, str);
-		doveadm_print(str_c(str));
+		state_str = t_str_new(128);
+		dsync_brain_get_state(brain, state_str);
+		doveadm_print(str_c(state_str));
 	}
 
-	if (dsync_brain_deinit(&brain) < 0)
+	if (dsync_brain_deinit(&brain) < 0) {
 		ctx->ctx.exit_code = EX_TEMPFAIL;
+		ret = -1;
+	}
 	dsync_ibc_deinit(&ibc);
 	if (ibc2 != NULL)
 		dsync_ibc_deinit(&ibc2);
@@ -540,6 +580,11 @@
 		i_close_fd(&ctx->fd_err);
 	ctx->input = NULL;
 	ctx->output = NULL;
+
+	if (ctx->replicator_notify) {
+		dsync_replicator_notify(ctx, state_str == NULL ? "" :
+					str_c(state_str));
+	}
 	return ret;
 }
 
@@ -820,6 +865,9 @@
 			ctx->sync_type = DSYNC_BRAIN_SYNC_TYPE_STATE;
 		ctx->state_input = optarg;
 		break;
+	case 'U':
+		ctx->replicator_notify = TRUE;
+		break;
 	default:
 		return FALSE;
 	}
diff -r 9824f8df62a3 -r f1ba737bc241 src/replication/replicator/doveadm-connection.c
--- a/src/replication/replicator/doveadm-connection.c	Sat Apr 06 21:01:41 2013 +0300
+++ b/src/replication/replicator/doveadm-connection.c	Sun Apr 07 14:46:45 2013 +0300
@@ -137,6 +137,32 @@
 	return 0;
 }
 
+static int
+client_input_notify(struct doveadm_connection *client, const char *const *args)
+{
+	struct replicator_user *user;
+
+	/* <username> <flags> <state> */
+	if (str_array_length(args) < 3) {
+		i_error("%s: NOTIFY: Invalid parameters", client->conn.name);
+		return -1;
+	}
+
+	user = replicator_queue_add(client->queue, args[0],
+				    REPLICATION_PRIORITY_NONE);
+	if (args[1][0] == 'f')
+		user->last_full_sync = ioloop_time;
+	user->last_fast_sync = ioloop_time;
+	user->last_update = ioloop_time;
+
+	if (args[2][0] != '\0') {
+		i_free(user->state);
+		user->state = i_strdup(args[2]);
+	}
+	o_stream_send_str(client->conn.output, "+\n");
+	return 0;
+}
+
 static int client_input_args(struct connection *conn, const char *const *args)
 {
 	struct doveadm_connection *client = (struct doveadm_connection *)conn;
@@ -152,6 +178,8 @@
 		return client_input_status(client, args);
 	else if (strcmp(cmd, "REPLICATE") == 0)
 		return client_input_replicate(client, args);
+	else if (strcmp(cmd, "NOTIFY") == 0)
+		return client_input_notify(client, args);
 	i_error("%s: Unknown command: %s", conn->name, cmd);
 	return -1;
 }
diff -r 9824f8df62a3 -r f1ba737bc241 src/replication/replicator/dsync-client.c
--- a/src/replication/replicator/dsync-client.c	Sat Apr 06 21:01:41 2013 +0300
+++ b/src/replication/replicator/dsync-client.c	Sun Apr 07 14:46:45 2013 +0300
@@ -209,7 +209,7 @@
 		str_printfa(cmd, "\tsync\t-d\t-N\t-l\t%u", DSYNC_LOCK_TIMEOUT_SECS);
 		if (full)
 			str_append(cmd, "\t-f");
-		str_append(cmd, "\t-s\t");
+		str_append(cmd, "\t-U\t-s\t");
 		if (state != NULL)
 			str_append(cmd, state);
 		str_append_c(cmd, '\n');


More information about the dovecot-cvs mailing list