]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
maildir: mail_update_uid() now updates uidlist also.
authorTimo Sirainen <tss@iki.fi>
Thu, 6 Aug 2009 00:17:13 +0000 (20:17 -0400)
committerTimo Sirainen <tss@iki.fi>
Thu, 6 Aug 2009 00:17:13 +0000 (20:17 -0400)
--HG--
branch : HEAD

src/lib-storage/index/maildir/maildir-mail.c
src/lib-storage/index/maildir/maildir-save.c
src/lib-storage/index/maildir/maildir-storage.h

index 69e04f5fd1d411e79393c7a4ae036112e0b754b8..1acd7e2188fc58c471134cefa93d123c18838d10 100644 (file)
@@ -484,6 +484,12 @@ static int maildir_mail_get_stream(struct mail *_mail,
        return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
 }
 
+static void maildir_mail_update_uid(struct mail *_mail, uint32_t new_uid)
+{
+       maildir_save_add_conflict(_mail->transaction, _mail->uid, new_uid);
+       index_mail_update_uid(_mail, new_uid);
+}
+
 static void maildir_mail_set_cache_corrupted(struct mail *_mail,
                                             enum mail_fetch_field field)
 {
@@ -544,7 +550,7 @@ struct mail_vfuncs maildir_mail_vfuncs = {
        index_mail_update_flags,
        index_mail_update_keywords,
        index_mail_update_modseq,
-       index_mail_update_uid,
+       maildir_mail_update_uid,
        index_mail_expunge,
        maildir_mail_set_cache_corrupted,
        index_mail_get_index_mail
index 59a14f3e8d9eba1c43cfb7a446d752eb0e3f73fa..04cd28fa9598c729c2dd6cad5cf4f996fccb2590 100644 (file)
@@ -37,6 +37,10 @@ struct maildir_filename {
        /* unsigned int keywords[]; */
 };
 
+struct maildir_save_conflict {
+       uint32_t old_uid, new_uid;
+};
+
 struct maildir_save_context {
        struct mail_save_context ctx;
        pool_t pool;
@@ -52,6 +56,8 @@ struct maildir_save_context {
        struct maildir_filename *files, **files_tail, *file_last;
        unsigned int files_count;
 
+       ARRAY_DEFINE(conflicts, struct maildir_save_conflict);
+
        buffer_t keywords_buffer;
        ARRAY_TYPE(keyword_indexes) keywords_array;
 
@@ -602,6 +608,55 @@ void maildir_save_cancel(struct mail_save_context *_ctx)
        (void)maildir_save_finish(_ctx);
 }
 
+void maildir_save_add_conflict(struct mailbox_transaction_context *t,
+                              uint32_t old_uid, uint32_t new_uid)
+{
+       struct maildir_save_context *save_ctx;
+       struct maildir_save_conflict *c;
+
+       save_ctx = (struct maildir_save_context *)maildir_save_alloc(t);
+
+       if (!array_is_created(&save_ctx->conflicts))
+               i_array_init(&save_ctx->conflicts, 64);
+
+       c = array_append_space(&save_ctx->conflicts);
+       c->old_uid = old_uid;
+       c->new_uid = new_uid;
+}
+
+static void maildir_sync_conflict(struct maildir_save_context *ctx,
+                                 const struct maildir_save_conflict *conflict)
+{
+       const char *filename;
+       enum maildir_uidlist_rec_flag flags;
+
+       if (maildir_uidlist_lookup(ctx->mbox->uidlist, conflict->old_uid,
+                                  &flags, &filename) <= 0) {
+               i_error("maildir %s: uid %u update failed: lost filename",
+                       ctx->mbox->ibox.box.path, conflict->old_uid);
+               return;
+       }
+       maildir_uidlist_sync_remove(ctx->uidlist_sync_ctx, filename);
+       if (maildir_uidlist_sync_next_uid(ctx->uidlist_sync_ctx, filename,
+                                         conflict->new_uid, 0) < 0) {
+               i_error("maildir %s: uid %u update failed: sync failed",
+                       ctx->mbox->ibox.box.path, conflict->old_uid);
+       }
+}
+
+static void maildir_sync_conflicts(struct maildir_save_context *ctx)
+{
+       const struct maildir_save_conflict *conflicts;
+       unsigned int i, count;
+
+       if (!array_is_created(&ctx->conflicts))
+               return;
+
+       conflicts = array_get(&ctx->conflicts, &count);
+       for (i = 0; i < count; i++)
+               maildir_sync_conflict(ctx, &conflicts[i]);
+}
+
 static void
 maildir_save_unlink_files(struct maildir_save_context *ctx)
 {
@@ -740,6 +795,9 @@ maildir_save_rollback_index_changes(struct maildir_save_context *ctx)
                (struct index_transaction_context *)ctx->ctx.transaction;
        uint32_t seq;
 
+       if (ctx->seq == 0)
+               return;
+
        for (seq = ctx->seq; seq >= ctx->first_seq; seq--)
                mail_index_expunge(ctx->trans, seq);
 
@@ -817,6 +875,9 @@ int maildir_transaction_save_commit_pre(struct mail_save_context *_ctx)
        i_assert(_ctx->output == NULL);
        i_assert(ctx->last_save_finished);
 
+       if (ctx->files_count == 0 && !array_is_created(&ctx->conflicts))
+               return 0;
+
        sync_flags = MAILDIR_UIDLIST_SYNC_PARTIAL |
                MAILDIR_UIDLIST_SYNC_NOREFRESH;
 
@@ -837,6 +898,7 @@ int maildir_transaction_save_commit_pre(struct mail_save_context *_ctx)
                        maildir_transaction_save_rollback(_ctx);
                        return -1;
                }
+               maildir_sync_conflicts(ctx);
        } else if (ret == 0 &&
                   (sync_flags & MAILDIR_UIDLIST_SYNC_TRYLOCK) != 0) {
                ctx->locked = FALSE;
@@ -909,6 +971,8 @@ void maildir_transaction_save_commit_post(struct mail_save_context *_ctx)
 
        if (ctx->locked)
                maildir_uidlist_unlock(ctx->mbox->uidlist);
+       if (array_is_created(&ctx->conflicts))
+               array_free(&ctx->conflicts);
        pool_unref(&ctx->pool);
 }
 
@@ -933,5 +997,7 @@ void maildir_transaction_save_rollback(struct mail_save_context *_ctx)
 
        if (ctx->mail != NULL)
                mail_free(&ctx->mail);
+       if (array_is_created(&ctx->conflicts))
+               array_free(&ctx->conflicts);
        pool_unref(&ctx->pool);
 }
index 90852feda3e401a91bee9276981749f6269c8373..92ce5c1d871277a16bcaf8f95ade1b2028577cfb 100644 (file)
@@ -121,6 +121,9 @@ int maildir_save_continue(struct mail_save_context *ctx);
 int maildir_save_finish(struct mail_save_context *ctx);
 void maildir_save_cancel(struct mail_save_context *ctx);
 
+void maildir_save_add_conflict(struct mailbox_transaction_context *t,
+                              uint32_t old_uid, uint32_t new_uid);
+
 struct maildir_filename *
 maildir_save_add(struct mail_save_context *_ctx, const char *base_fname);
 const char *maildir_save_file_get_path(struct mailbox_transaction_context *t,