dovecot-2.2: dsync: Added an extra "finish" state to allow slave...

dovecot at dovecot.org dovecot at dovecot.org
Fri Mar 13 18:09:39 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/b4dbe64c0032
changeset: 18351:b4dbe64c0032
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Mar 13 20:08:34 2015 +0200
description:
dsync: Added an extra "finish" state to allow slave-dsync to report error to master-dsync.
I'm not sure if that's actually necessary, but just trying to follow the
different possibilities on how dsync run can finish made me unsure about it.
This should make it at least clear that if a slave-dsync has a failure flag
set at deinit master-dsync will know about it before it returns success.

diffstat:

 src/doveadm/dsync/dsync-brain-mailbox.c |   4 +-
 src/doveadm/dsync/dsync-brain-private.h |   1 +
 src/doveadm/dsync/dsync-brain.c         |  24 +++++++++++++++
 src/doveadm/dsync/dsync-ibc-pipe.c      |  31 +++++++++++++++++++-
 src/doveadm/dsync/dsync-ibc-private.h   |   4 ++
 src/doveadm/dsync/dsync-ibc-stream.c    |  50 +++++++++++++++++++++++++++++++-
 src/doveadm/dsync/dsync-ibc.c           |  11 +++++++
 src/doveadm/dsync/dsync-ibc.h           |   4 ++
 8 files changed, 124 insertions(+), 5 deletions(-)

diffs (289 lines):

diff -r e86211e8d728 -r b4dbe64c0032 src/doveadm/dsync/dsync-brain-mailbox.c
--- a/src/doveadm/dsync/dsync-brain-mailbox.c	Fri Mar 13 20:05:03 2015 +0200
+++ b/src/doveadm/dsync/dsync-brain-mailbox.c	Fri Mar 13 20:08:34 2015 +0200
@@ -534,7 +534,7 @@
 	i_assert(brain->box == NULL);
 
 	if (!dsync_brain_next_mailbox(brain, &box, &dsync_box)) {
-		brain->state = DSYNC_STATE_DONE;
+		brain->state = DSYNC_STATE_FINISH;
 		dsync_ibc_send_end_of_list(brain->ibc, DSYNC_IBC_EOL_MAILBOX);
 		return;
 	}
@@ -722,7 +722,7 @@
 	if ((ret = dsync_ibc_recv_mailbox(brain->ibc, &dsync_box)) == 0)
 		return FALSE;
 	if (ret < 0) {
-		brain->state = DSYNC_STATE_DONE;
+		brain->state = DSYNC_STATE_FINISH;
 		return TRUE;
 	}
 
diff -r e86211e8d728 -r b4dbe64c0032 src/doveadm/dsync/dsync-brain-private.h
--- a/src/doveadm/dsync/dsync-brain-private.h	Fri Mar 13 20:05:03 2015 +0200
+++ b/src/doveadm/dsync/dsync-brain-private.h	Fri Mar 13 20:08:34 2015 +0200
@@ -32,6 +32,7 @@
 	   after the mails are synced, another mailbox is synced. */
 	DSYNC_STATE_SYNC_MAILS,
 
+	DSYNC_STATE_FINISH,
 	DSYNC_STATE_DONE
 };
 
diff -r e86211e8d728 -r b4dbe64c0032 src/doveadm/dsync/dsync-brain.c
--- a/src/doveadm/dsync/dsync-brain.c	Fri Mar 13 20:05:03 2015 +0200
+++ b/src/doveadm/dsync/dsync-brain.c	Fri Mar 13 20:08:34 2015 +0200
@@ -30,6 +30,7 @@
 	"master_send_mailbox",
 	"slave_recv_mailbox",
 	"sync_mails",
+	"finish",
 	"done"
 };
 
@@ -554,6 +555,26 @@
 	return changed;
 }
 
+static bool dsync_brain_finish(struct dsync_brain *brain)
+{
+	const char *error;
+
+	if (!brain->master_brain) {
+		dsync_ibc_send_finish(brain->ibc,
+				      brain->failed ? "dsync failed" : NULL);
+		brain->state = DSYNC_STATE_DONE;
+		return TRUE;
+	} 
+	if (dsync_ibc_recv_finish(brain->ibc, &error) == DSYNC_IBC_RECV_RET_TRYAGAIN)
+		return FALSE;
+	if (error != NULL) {
+		i_error("Remote dsync failed: %s", error);
+		brain->failed = TRUE;
+	}
+	brain->state = DSYNC_STATE_DONE;
+	return TRUE;
+}
+
 static bool dsync_brain_run_real(struct dsync_brain *brain, bool *changed_r)
 {
 	enum dsync_state orig_state = brain->state;
@@ -602,6 +623,9 @@
 	case DSYNC_STATE_SYNC_MAILS:
 		changed = dsync_brain_sync_mails(brain);
 		break;
+	case DSYNC_STATE_FINISH:
+		changed = dsync_brain_finish(brain);
+		break;
 	case DSYNC_STATE_DONE:
 		changed = TRUE;
 		ret = FALSE;
diff -r e86211e8d728 -r b4dbe64c0032 src/doveadm/dsync/dsync-ibc-pipe.c
--- a/src/doveadm/dsync/dsync-ibc-pipe.c	Fri Mar 13 20:05:03 2015 +0200
+++ b/src/doveadm/dsync/dsync-ibc-pipe.c	Fri Mar 13 20:08:34 2015 +0200
@@ -19,7 +19,8 @@
 	ITEM_MAILBOX_ATTRIBUTE,
 	ITEM_MAIL_CHANGE,
 	ITEM_MAIL_REQUEST,
-	ITEM_MAIL
+	ITEM_MAIL,
+	ITEM_FINISH
 };
 
 struct item {
@@ -41,6 +42,7 @@
 			unsigned int count;
 			char hierarchy_sep;
 		} mailbox_delete;
+		const char *finish_error;
 	} u;
 };
 
@@ -90,6 +92,7 @@
 	case ITEM_MAIL_CHANGE:
 	case ITEM_MAIL_REQUEST:
 	case ITEM_MAIL:
+	case ITEM_FINISH:
 		item->pool = dsync_ibc_pipe_get_pool(pipe);
 		break;
 	}
@@ -483,6 +486,30 @@
 	return DSYNC_IBC_RECV_RET_OK;
 }
 
+static void
+dsync_ibc_pipe_send_finish(struct dsync_ibc *ibc, const char *error)
+{
+	struct dsync_ibc_pipe *pipe = (struct dsync_ibc_pipe *)ibc;
+	struct item *item;
+
+	item = dsync_ibc_pipe_push_item(pipe->remote, ITEM_FINISH);
+	item->u.finish_error = p_strdup(item->pool, error);
+}
+
+static enum dsync_ibc_recv_ret
+dsync_ibc_pipe_recv_finish(struct dsync_ibc *ibc, const char **error_r)
+{
+	struct dsync_ibc_pipe *pipe = (struct dsync_ibc_pipe *)ibc;
+	struct item *item;
+
+	item = dsync_ibc_pipe_pop_item(pipe, ITEM_FINISH);
+	if (item == NULL)
+		return DSYNC_IBC_RECV_RET_TRYAGAIN;
+
+	*error_r = item->u.finish_error;
+	return DSYNC_IBC_RECV_RET_OK;
+}
+
 static void pipe_close_mail_streams(struct dsync_ibc_pipe *pipe)
 {
 	struct item *item;
@@ -524,6 +551,8 @@
 	dsync_ibc_pipe_recv_mail_request,
 	dsync_ibc_pipe_send_mail,
 	dsync_ibc_pipe_recv_mail,
+	dsync_ibc_pipe_send_finish,
+	dsync_ibc_pipe_recv_finish,
 	dsync_ibc_pipe_close_mail_streams,
 	dsync_ibc_pipe_is_send_queue_full,
 	dsync_ibc_pipe_has_pending_data
diff -r e86211e8d728 -r b4dbe64c0032 src/doveadm/dsync/dsync-ibc-private.h
--- a/src/doveadm/dsync/dsync-ibc-private.h	Fri Mar 13 20:05:03 2015 +0200
+++ b/src/doveadm/dsync/dsync-ibc-private.h	Fri Mar 13 20:08:34 2015 +0200
@@ -68,6 +68,10 @@
 		(*recv_mail)(struct dsync_ibc *ibc,
 			     struct dsync_mail **mail_r);
 
+	void (*send_finish)(struct dsync_ibc *ibc, const char *error);
+	enum dsync_ibc_recv_ret
+		(*recv_finish)(struct dsync_ibc *ibc, const char **error_r);
+
 	void (*close_mail_streams)(struct dsync_ibc *ibc);
 	bool (*is_send_queue_full)(struct dsync_ibc *ibc);
 	bool (*has_pending_data)(struct dsync_ibc *ibc);
diff -r e86211e8d728 -r b4dbe64c0032 src/doveadm/dsync/dsync-ibc-stream.c
--- a/src/doveadm/dsync/dsync-ibc-stream.c	Fri Mar 13 20:05:03 2015 +0200
+++ b/src/doveadm/dsync/dsync-ibc-stream.c	Fri Mar 13 20:08:34 2015 +0200
@@ -28,11 +28,12 @@
 #define DSYNC_IBC_STREAM_OUTBUF_THROTTLE_SIZE (1024*128)
 
 #define DSYNC_PROTOCOL_VERSION_MAJOR 3
-#define DSYNC_PROTOCOL_VERSION_MINOR 2
-#define DSYNC_HANDSHAKE_VERSION "VERSION\tdsync\t3\t2\n"
+#define DSYNC_PROTOCOL_VERSION_MINOR 3
+#define DSYNC_HANDSHAKE_VERSION "VERSION\tdsync\t3\t3\n"
 
 #define DSYNC_PROTOCOL_MINOR_HAVE_ATTRIBUTES 1
 #define DSYNC_PROTOCOL_MINOR_HAVE_SAVE_GUID 2
+#define DSYNC_PROTOCOL_MINOR_HAVE_FINISH 3
 
 enum item_type {
 	ITEM_NONE,
@@ -48,6 +49,7 @@
 	ITEM_MAIL_CHANGE,
 	ITEM_MAIL_REQUEST,
 	ITEM_MAIL,
+	ITEM_FINISH,
 
 	ITEM_MAILBOX_CACHE_FIELD,
 
@@ -122,6 +124,10 @@
 	  .chr = 'M',
 	  .optional_keys = "guid uid pop3_uidl pop3_order received_date saved_date stream"
 	},
+	{ .name = "finish",
+	  .chr = 'F',
+	  .optional_keys = "error"
+	},
 	{ .name = "mailbox_cache_field",
 	  .chr = 'c',
 	  .required_keys = "name decision",
@@ -1820,6 +1826,44 @@
 	return DSYNC_IBC_RECV_RET_OK;
 }
 
+static void
+dsync_ibc_stream_send_finish(struct dsync_ibc *_ibc, const char *error)
+{
+	struct dsync_ibc_stream *ibc = (struct dsync_ibc_stream *)_ibc;
+	struct dsync_serializer_encoder *encoder;
+	string_t *str = t_str_new(128);
+
+	str_append_c(str, items[ITEM_FINISH].chr);
+	encoder = dsync_serializer_encode_begin(ibc->serializers[ITEM_FINISH]);
+	if (error != NULL)
+		dsync_serializer_encode_add(encoder, "error", error);
+	dsync_serializer_encode_finish(&encoder, str);
+	dsync_ibc_stream_send_string(ibc, str);
+}
+
+static enum dsync_ibc_recv_ret
+dsync_ibc_stream_recv_finish(struct dsync_ibc *_ibc, const char **error_r)
+{
+	struct dsync_ibc_stream *ibc = (struct dsync_ibc_stream *)_ibc;
+	struct dsync_deserializer_decoder *decoder;
+	const char *value;
+	enum dsync_ibc_recv_ret ret;
+
+	*error_r = NULL;
+	p_clear(ibc->ret_pool);
+
+	if (ibc->minor_version < DSYNC_PROTOCOL_MINOR_HAVE_FINISH)
+		return DSYNC_IBC_RECV_RET_OK;
+
+	ret = dsync_ibc_stream_input_next(ibc, ITEM_FINISH, &decoder);
+	if (ret != DSYNC_IBC_RECV_RET_OK)
+		return ret;
+
+	if (dsync_deserializer_decode_try(decoder, "error", &value))
+		*error_r = p_strdup(ibc->ret_pool, value);
+	return DSYNC_IBC_RECV_RET_OK;
+}
+
 static void dsync_ibc_stream_close_mail_streams(struct dsync_ibc *_ibc)
 {
 	struct dsync_ibc_stream *ibc = (struct dsync_ibc_stream *)_ibc;
@@ -1874,6 +1918,8 @@
 	dsync_ibc_stream_recv_mail_request,
 	dsync_ibc_stream_send_mail,
 	dsync_ibc_stream_recv_mail,
+	dsync_ibc_stream_send_finish,
+	dsync_ibc_stream_recv_finish,
 	dsync_ibc_stream_close_mail_streams,
 	dsync_ibc_stream_is_send_queue_full,
 	dsync_ibc_stream_has_pending_data
diff -r e86211e8d728 -r b4dbe64c0032 src/doveadm/dsync/dsync-ibc.c
--- a/src/doveadm/dsync/dsync-ibc.c	Fri Mar 13 20:05:03 2015 +0200
+++ b/src/doveadm/dsync/dsync-ibc.c	Fri Mar 13 20:08:34 2015 +0200
@@ -195,6 +195,17 @@
 	return ibc->v.recv_mail(ibc, mail_r);
 }
 
+void dsync_ibc_send_finish(struct dsync_ibc *ibc, const char *error)
+{
+	ibc->v.send_finish(ibc, error);
+}
+
+enum dsync_ibc_recv_ret
+dsync_ibc_recv_finish(struct dsync_ibc *ibc, const char **error_r)
+{
+	return ibc->v.recv_finish(ibc, error_r);
+}
+
 void dsync_ibc_close_mail_streams(struct dsync_ibc *ibc)
 {
 	ibc->v.close_mail_streams(ibc);
diff -r e86211e8d728 -r b4dbe64c0032 src/doveadm/dsync/dsync-ibc.h
--- a/src/doveadm/dsync/dsync-ibc.h	Fri Mar 13 20:05:03 2015 +0200
+++ b/src/doveadm/dsync/dsync-ibc.h	Fri Mar 13 20:08:34 2015 +0200
@@ -144,6 +144,10 @@
 enum dsync_ibc_recv_ret
 dsync_ibc_recv_mail(struct dsync_ibc *ibc, struct dsync_mail **mail_r);
 
+void dsync_ibc_send_finish(struct dsync_ibc *ibc, const char *error);
+enum dsync_ibc_recv_ret
+dsync_ibc_recv_finish(struct dsync_ibc *ibc, const char **error_r);
+
 /* Close any mail input streams that are kept open. This needs to be called
    before the mail is attempted to be freed (usually on error conditions). */
 void dsync_ibc_close_mail_streams(struct dsync_ibc *ibc);


More information about the dovecot-cvs mailing list