]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
dsync: Avoid finishing importer successfully on exporter failures.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 28 Jan 2016 17:56:38 +0000 (19:56 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 28 Jan 2016 17:56:38 +0000 (19:56 +0200)
At least dsync_mailbox_import_changes_finish() could have been called when
exporter was already failed.

src/doveadm/dsync/dsync-brain-mails.c
src/doveadm/dsync/dsync-mailbox-export.c
src/doveadm/dsync/dsync-mailbox-export.h

index 2def387e644a73eec897019c7ed658af9a39cf03..137e64b1e27575f84dfbf55ac3575d0163fcba1e 100644 (file)
@@ -97,14 +97,36 @@ static void dsync_brain_send_end_of_list(struct dsync_brain *brain,
        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 bool dsync_brain_recv_mail_change(struct dsync_brain *brain)
 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 @@ static bool dsync_brain_send_mail_request(struct dsync_brain *brain)
        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 @@ static void dsync_brain_sync_half_finished(struct dsync_brain *brain)
                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 @@ static bool dsync_brain_send_mail(struct dsync_brain *brain)
                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;
        }
index d08e0e1fced1ceef26e4c2fcc258f0943a298af0..c013eb0467cee45637c486a54cb4234361e3574a 100644 (file)
@@ -648,38 +648,41 @@ dsync_mailbox_export_iter_next_attr(struct dsync_mailbox_exporter *exporter)
        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 @@ void dsync_mailbox_export_want_mail(struct dsync_mailbox_exporter *exporter,
        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 @@ dsync_mailbox_export_next_mail(struct dsync_mailbox_exporter *exporter)
        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_next_mail(struct dsync_mailbox_exporter *exporter)
        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 @@ dsync_mailbox_export_next_mail(struct dsync_mailbox_exporter *exporter)
                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,
index fffeedbbb25a7398c9de3e0f475290dfd085fb46..c8f95488eb856fe70a7ec9550c38670f95e11edb 100644 (file)
@@ -14,15 +14,18 @@ dsync_mailbox_export_init(struct mailbox *box,
                          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);