Mercurial > dovecot > core-2.2
changeset 19660:7a3a138a4986
doveadm backup: Detect and handle conflicts earlier.
This avoids doing a lot of work, only for the next doveadm backup to just
delete the entire mailbox and start from the beginning.
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Thu, 28 Jan 2016 16:43:37 +0200 |
parents | c198a998082c |
children | 166d2d3f57f8 |
files | src/doveadm/dsync/dsync-brain-mails.c src/doveadm/dsync/dsync-mailbox-import.c src/doveadm/dsync/dsync-mailbox-import.h |
diffstat | 3 files changed, 34 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/src/doveadm/dsync/dsync-brain-mails.c Thu Jan 28 16:26:53 2016 +0200 +++ b/src/doveadm/dsync/dsync-brain-mails.c Thu Jan 28 16:43:37 2016 +0200 @@ -117,7 +117,8 @@ if ((ret = dsync_ibc_recv_change(brain->ibc, &change)) == 0) return FALSE; if (ret == DSYNC_IBC_RECV_RET_FINISHED) { - dsync_mailbox_import_changes_finish(brain->box_importer); + if (dsync_mailbox_import_changes_finish(brain->box_importer) < 0) + brain->failed = TRUE; if (brain->mail_requests && brain->box_exporter != NULL) brain->box_recv_state = DSYNC_BOX_STATE_MAIL_REQUESTS; else
--- a/src/doveadm/dsync/dsync-mailbox-import.c Thu Jan 28 16:26:53 2016 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-import.c Thu Jan 28 16:43:37 2016 +0200 @@ -709,6 +709,21 @@ } } +static void +dsync_mailbox_revert_existing_uid(struct dsync_mailbox_importer *importer, + uint32_t uid, const char *reason) +{ + i_assert(importer->revert_local_changes); + + /* UID either already exists or UIDNEXT is too high. we can't set the + wanted UID, so we'll need to delete the whole mailbox and resync */ + i_warning("Deleting mailbox '%s': UID=%u already exists locally for a different mail: %s", + mailbox_get_vname(importer->box), uid, reason); + importer->delete_mailbox = TRUE; + importer->mail_error = MAIL_ERROR_TEMP; + importer->failed = TRUE; +} + static bool dsync_mailbox_try_save_cur(struct dsync_mailbox_importer *importer, struct dsync_mail_change *save_change) { @@ -758,6 +773,11 @@ newmail->uid_in_local = FALSE; newmail->uid_is_usable = newmail->final_uid >= importer->local_uid_next; + if (!newmail->uid_is_usable && importer->revert_local_changes) { + dsync_mailbox_revert_existing_uid(importer, newmail->final_uid, + t_strdup_printf("UID >= local UIDNEXT=%u", importer->local_uid_next)); + return TRUE; + } remote_saved = TRUE; } else { /* identical */ @@ -1619,11 +1639,15 @@ /* unknown */ return; } - if (ret == 0) { + if (ret > 0) { + importer->last_common_uid = change->uid; + } else if (!importer->revert_local_changes) { /* mismatch - found the first non-common UID */ dsync_mailbox_common_uid_found(importer); } else { - importer->last_common_uid = change->uid; + /* mismatch and we want to revert local changes - + need to delete the mailbox. */ + dsync_mailbox_revert_existing_uid(importer, change->uid, *result_r); } return; } @@ -1746,6 +1770,7 @@ this mail */ new_uid = newmail->link->final_uid; } else { + i_assert(!importer->revert_local_changes); new_uid = common_uid_next++; imp_debug(importer, "UID %u isn't usable, assigning new UID %u", newmail->final_uid, new_uid); @@ -2088,7 +2113,7 @@ hash_table_iterate_deinit(&iter); } -void dsync_mailbox_import_changes_finish(struct dsync_mailbox_importer *importer) +int dsync_mailbox_import_changes_finish(struct dsync_mailbox_importer *importer) { i_assert(!importer->new_uids_assigned); @@ -2117,7 +2142,9 @@ dsync_mailbox_import_assign_new_uids(importer); /* save mails from local sources where possible, request the rest from remote */ - dsync_mailbox_import_handle_local_mails(importer); + if (!importer->failed) + dsync_mailbox_import_handle_local_mails(importer); + return importer->failed ? -1 : 0; } const struct dsync_mail_request *
--- a/src/doveadm/dsync/dsync-mailbox-import.h Thu Jan 28 16:26:53 2016 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-import.h Thu Jan 28 16:43:37 2016 +0200 @@ -37,7 +37,7 @@ const struct dsync_mailbox_attribute *attr); int dsync_mailbox_import_change(struct dsync_mailbox_importer *importer, const struct dsync_mail_change *change); -void dsync_mailbox_import_changes_finish(struct dsync_mailbox_importer *importer); +int dsync_mailbox_import_changes_finish(struct dsync_mailbox_importer *importer); const struct dsync_mail_request * dsync_mailbox_import_next_request(struct dsync_mailbox_importer *importer); void dsync_mailbox_import_mail(struct dsync_mailbox_importer *importer,