changeset 19671:3b516415a5fa

dsync: Avoid finishing importer successfully on exporter failures. At least dsync_mailbox_import_changes_finish() could have been called when exporter was already failed.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Thu, 28 Jan 2016 19:56:38 +0200
parents b467f6d24fd5
children e7849490acd9
files src/doveadm/dsync/dsync-brain-mails.c src/doveadm/dsync/dsync-mailbox-export.c src/doveadm/dsync/dsync-mailbox-export.h
diffstat 3 files changed, 72 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- a/src/doveadm/dsync/dsync-brain-mails.c	Thu Jan 28 19:55:06 2016 +0200
+++ b/src/doveadm/dsync/dsync-brain-mails.c	Thu Jan 28 19:56:38 2016 +0200
@@ -97,14 +97,36 @@
 	dsync_ibc_send_end_of_list(brain->ibc, type);
 }
 
+static int dsync_brain_export_deinit(struct dsync_brain *brain)
+{
+	const char *errstr;
+	enum mail_error error;
+
+	if (dsync_mailbox_export_deinit(&brain->box_exporter,
+					&errstr, &error) < 0) {
+		i_error("Exporting mailbox %s failed: %s",
+			mailbox_get_vname(brain->box), errstr);
+		brain->mail_error = error;
+		brain->failed = TRUE;
+		return -1;
+	}
+	return 0;
+}
+
 static void dsync_brain_send_mailbox_attribute(struct dsync_brain *brain)
 {
 	const struct dsync_mailbox_attribute *attr;
+	int ret;
 
-	while ((attr = dsync_mailbox_export_next_attr(brain->box_exporter)) != NULL) {
+	while ((ret = dsync_mailbox_export_next_attr(brain->box_exporter, &attr)) > 0) {
 		if (dsync_ibc_send_mailbox_attribute(brain->ibc, attr) == 0)
 			return;
 	}
+	if (ret < 0) {
+		if (dsync_brain_export_deinit(brain) == 0)
+			i_unreached();
+		return;
+	}
 	dsync_brain_send_end_of_list(brain, DSYNC_IBC_EOL_MAILBOX_ATTRIBUTE);
 	brain->box_send_state = DSYNC_BOX_STATE_CHANGES;
 }
@@ -133,11 +155,17 @@
 static void dsync_brain_send_mail_change(struct dsync_brain *brain)
 {
 	const struct dsync_mail_change *change;
+	int ret;
 
-	while ((change = dsync_mailbox_export_next(brain->box_exporter)) != NULL) {
+	while ((ret = dsync_mailbox_export_next(brain->box_exporter, &change)) > 0) {
 		if (dsync_ibc_send_change(brain->ibc, change) == 0)
 			return;
 	}
+	if (ret < 0) {
+		if (dsync_brain_export_deinit(brain) == 0)
+			i_unreached();
+		return;
+	}
 	dsync_brain_send_end_of_list(brain, DSYNC_IBC_EOL_MAIL_CHANGES);
 	if (brain->mail_requests && brain->box_importer != NULL)
 		brain->box_send_state = DSYNC_BOX_STATE_MAIL_REQUESTS;
@@ -188,22 +216,6 @@
 	return TRUE;
 }
 
-static int dsync_brain_export_deinit(struct dsync_brain *brain)
-{
-	const char *errstr;
-	enum mail_error error;
-
-	if (dsync_mailbox_export_deinit(&brain->box_exporter,
-					&errstr, &error) < 0) {
-		i_error("Exporting mailbox %s failed: %s",
-			mailbox_get_vname(brain->box), errstr);
-		brain->mail_error = error;
-		brain->failed = TRUE;
-		return -1;
-	}
-	return 0;
-}
-
 static void dsync_brain_sync_half_finished(struct dsync_brain *brain)
 {
 	struct dsync_mailbox_state state;
@@ -227,7 +239,8 @@
 		state.last_messages_count =
 			brain->local_dsync_box.messages_count;
 	} else {
-		if (dsync_mailbox_import_deinit(&brain->box_importer, TRUE,
+		if (dsync_mailbox_import_deinit(&brain->box_importer,
+						!brain->failed,
 						&state.last_common_uid,
 						&state.last_common_modseq,
 						&state.last_common_pvt_modseq,
@@ -284,7 +297,7 @@
 		return FALSE;
 	}
 
-	while ((mail = dsync_mailbox_export_next_mail(brain->box_exporter)) != NULL) {
+	while (dsync_mailbox_export_next_mail(brain->box_exporter, &mail) > 0) {
 		if (dsync_ibc_send_mail(brain->ibc, mail) == 0)
 			return TRUE;
 	}
--- a/src/doveadm/dsync/dsync-mailbox-export.c	Thu Jan 28 19:55:06 2016 +0200
+++ b/src/doveadm/dsync/dsync-mailbox-export.c	Thu Jan 28 19:56:38 2016 +0200
@@ -648,38 +648,41 @@
 	return dsync_mailbox_export_iter_next_nonexistent_attr(exporter);
 }
 
-const struct dsync_mailbox_attribute *
-dsync_mailbox_export_next_attr(struct dsync_mailbox_exporter *exporter)
+int dsync_mailbox_export_next_attr(struct dsync_mailbox_exporter *exporter,
+				   const struct dsync_mailbox_attribute **attr_r)
 {
+	int ret;
+
 	if (exporter->error != NULL)
-		return NULL;
+		return -1;
 
 	if (exporter->attr.value_stream != NULL)
 		i_stream_unref(&exporter->attr.value_stream);
 
 	if (exporter->attr_iter != NULL) {
-		if (dsync_mailbox_export_iter_next_attr(exporter) <= 0)
-			return NULL;
+		ret = dsync_mailbox_export_iter_next_attr(exporter);
 	} else {
-		if (dsync_mailbox_export_iter_next_nonexistent_attr(exporter) <= 0)
-			return NULL;
+		ret = dsync_mailbox_export_iter_next_nonexistent_attr(exporter);
 	}
-	return &exporter->attr;
+	if (ret > 0)
+		*attr_r = &exporter->attr;
+	return ret;
 }
 
-const struct dsync_mail_change *
-dsync_mailbox_export_next(struct dsync_mailbox_exporter *exporter)
+int dsync_mailbox_export_next(struct dsync_mailbox_exporter *exporter,
+			      const struct dsync_mail_change **change_r)
 {
 	struct dsync_mail_change *const *changes;
 	unsigned int count;
 
 	if (exporter->error != NULL)
-		return NULL;
+		return -1;
 
 	changes = array_get(&exporter->sorted_changes, &count);
 	if (exporter->change_idx == count)
-		return NULL;
-	return changes[exporter->change_idx++];
+		return 0;
+	*change_r = changes[exporter->change_idx++];
+	return 1;
 }
 
 static int
@@ -837,8 +840,8 @@
 	instances->requested = TRUE;
 }
 
-const struct dsync_mail *
-dsync_mailbox_export_next_mail(struct dsync_mailbox_exporter *exporter)
+int dsync_mailbox_export_next_mail(struct dsync_mailbox_exporter *exporter,
+				   const struct dsync_mail **mail_r)
 {
 	struct mail *mail;
 	const char *const *guids;
@@ -846,22 +849,24 @@
 	int ret;
 
 	if (exporter->error != NULL)
-		return NULL;
+		return -1;
 	if (!exporter->body_search_initialized) {
 		exporter->body_search_initialized = TRUE;
 		if (dsync_mailbox_export_body_search_init(exporter) < 0) {
 			i_assert(exporter->error != NULL);
-			return NULL;
+			return -1;
 		}
 	}
 
 	while (mailbox_search_next(exporter->search_ctx, &mail)) {
 		exporter->search_pos++;
-		if ((ret = dsync_mailbox_export_mail(exporter, mail)) > 0)
-			return &exporter->dsync_mail;
+		if ((ret = dsync_mailbox_export_mail(exporter, mail)) > 0) {
+			*mail_r = &exporter->dsync_mail;
+			return 1;
+		}
 		if (ret < 0) {
 			i_assert(exporter->error != NULL);
-			return NULL;
+			return -1;
 		}
 		/* the message was expunged. if the GUID has another instance,
 		   try sending it later. */
@@ -872,11 +877,11 @@
 	dsync_mailbox_export_body_search_deinit(exporter);
 	if ((ret = dsync_mailbox_export_body_search_init(exporter)) < 0) {
 		i_assert(exporter->error != NULL);
-		return NULL;
+		return -1;
 	}
 	if (ret > 0) {
 		/* not finished yet */
-		return dsync_mailbox_export_next_mail(exporter);
+		return dsync_mailbox_export_next_mail(exporter, mail_r);
 	}
 
 	/* finished with messages. if there are any expunged messages,
@@ -886,9 +891,10 @@
 		memset(&exporter->dsync_mail, 0, sizeof(exporter->dsync_mail));
 		exporter->dsync_mail.guid =
 			guids[exporter->expunged_guid_idx++];
-		return &exporter->dsync_mail;
+		*mail_r = &exporter->dsync_mail;
+		return 1;
 	}
-	return NULL;
+	return 0;
 }
 
 int dsync_mailbox_export_deinit(struct dsync_mailbox_exporter **_exporter,
--- a/src/doveadm/dsync/dsync-mailbox-export.h	Thu Jan 28 19:55:06 2016 +0200
+++ b/src/doveadm/dsync/dsync-mailbox-export.h	Thu Jan 28 19:56:38 2016 +0200
@@ -14,15 +14,18 @@
 			  struct dsync_transaction_log_scan *log_scan,
 			  uint32_t last_common_uid,
 			  enum dsync_mailbox_exporter_flags flags);
-const struct dsync_mailbox_attribute *
-dsync_mailbox_export_next_attr(struct dsync_mailbox_exporter *exporter);
-const struct dsync_mail_change *
-dsync_mailbox_export_next(struct dsync_mailbox_exporter *exporter);
+/* Returns 1 if attribute was returned, 0 if no more attributes, -1 on error */
+int dsync_mailbox_export_next_attr(struct dsync_mailbox_exporter *exporter,
+				   const struct dsync_mailbox_attribute **attr_r);
+/* Returns 1 if change was returned, 0 if no more changes, -1 on error */
+int dsync_mailbox_export_next(struct dsync_mailbox_exporter *exporter,
+			      const struct dsync_mail_change **change_r);
 
 void dsync_mailbox_export_want_mail(struct dsync_mailbox_exporter *exporter,
 				    const struct dsync_mail_request *request);
-const struct dsync_mail *
-dsync_mailbox_export_next_mail(struct dsync_mailbox_exporter *exporter);
+/* Returns 1 if mail was returned, 0 if no more mails, -1 on error */
+int dsync_mailbox_export_next_mail(struct dsync_mailbox_exporter *exporter,
+				   const struct dsync_mail **mail_r);
 int dsync_mailbox_export_deinit(struct dsync_mailbox_exporter **exporter,
 				const char **errstr_r, enum mail_error *error_r);