]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Always create mail_save_context.dest_mail
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 9 Feb 2017 14:53:47 +0000 (16:53 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 17 Feb 2017 09:32:31 +0000 (11:32 +0200)
This allows removing similar mail_alloc() from storage backends and plugins
that need it.

As a side effect, this changes mbox code to always assign UIDs to saved
mails. This shouldn't be much of a problem, since it happened practically
always already.

src/lib-storage/index/index-transaction.c
src/lib-storage/mail-storage-private.h
src/lib-storage/mail-storage.c

index bdd35a08242556b78caf32705f5c73ec425f439c..ac521b9fc50b74c2565ee0258ba4bcdf6fa3346e 100644 (file)
@@ -47,6 +47,7 @@ index_transaction_index_commit(struct mail_index_transaction *index_trans,
        }
 
        if (t->save_ctx != NULL) {
+               mailbox_save_context_deinit(t->save_ctx);
                if (ret < 0) {
                        t->box->v.transaction_save_rollback(t->save_ctx);
                        t->save_ctx = NULL;
@@ -76,8 +77,10 @@ index_transaction_index_commit(struct mail_index_transaction *index_trans,
                }
        }
 
-       if (t->save_ctx != NULL)
+       if (t->save_ctx != NULL) {
+               i_assert(t->save_ctx->dest_mail == NULL);
                t->box->v.transaction_save_commit_post(t->save_ctx, result_r);
+       }
 
        if (pvt_sync_ctx != NULL) {
                if (index_mailbox_sync_pvt_newmails(pvt_sync_ctx, t) < 0) {
@@ -97,8 +100,10 @@ index_transaction_index_rollback(struct mail_index_transaction *index_trans)
        struct mailbox_transaction_context *t =
                MAIL_STORAGE_CONTEXT(index_trans);
 
-       if (t->save_ctx != NULL)
+       if (t->save_ctx != NULL) {
+               mailbox_save_context_deinit(t->save_ctx);
                t->box->v.transaction_save_rollback(t->save_ctx);
+       }
 
        i_assert(t->mail_ref_count == 0);
        t->super.rollback(index_trans);
index 818c37ae28e54b8a47e1a6bef540fe376b65b2d1..02948733e944c1212234dc1ccc93d68bbc8494de 100644 (file)
@@ -674,6 +674,8 @@ struct mail_save_context {
        /* mail is being copied or moved. However, this is set also with
           mailbox_save_using_mail() and then saving==TRUE. */
        unsigned int copying_or_moving:1;
+       /* dest_mail was set via mailbox_save_set_dest_mail() */
+       unsigned int dest_mail_external:1;
 };
 
 struct mailbox_sync_context {
@@ -766,5 +768,6 @@ void mail_storage_free_binary_cache(struct mail_storage *storage);
 
 enum mail_index_open_flags
 mail_storage_settings_to_index_flags(const struct mail_storage_settings *set);
+void mailbox_save_context_deinit(struct mail_save_context *ctx);
 
 #endif
index 34d275b69318faee779dd57452894bf101f31b4b..5e74b7461193e18de6380498b093aa9681a5675b 100644 (file)
@@ -2008,6 +2008,13 @@ mailbox_transaction_get_mailbox(const struct mailbox_transaction_context *t)
        return t->box;
 }
 
+static void mailbox_save_dest_mail_close(struct mail_save_context *ctx)
+{
+       struct mail_private *mail = (struct mail_private *)ctx->dest_mail;
+
+       mail->v.close(&mail->mail);
+}
+
 struct mail_save_context *
 mailbox_save_alloc(struct mailbox_transaction_context *t)
 {
@@ -2020,9 +2027,28 @@ mailbox_save_alloc(struct mailbox_transaction_context *t)
        ctx->unfinished = TRUE;
        ctx->data.received_date = (time_t)-1;
        ctx->data.save_date = (time_t)-1;
+
+       /* Always have a dest_mail available. A lot of plugins make use
+          of this. */
+       if (ctx->dest_mail == NULL)
+               ctx->dest_mail = mail_alloc(t, 0, NULL);
+       else {
+               /* make sure the mail isn't used before mail_set_seq_saving() */
+               mailbox_save_dest_mail_close(ctx);
+       }
        return ctx;
 }
 
+void mailbox_save_context_deinit(struct mail_save_context *ctx)
+{
+       i_assert(ctx->dest_mail != NULL);
+
+       if (!ctx->dest_mail_external)
+               mail_free(&ctx->dest_mail);
+       else
+               ctx->dest_mail = NULL;
+}
+
 void mailbox_save_set_flags(struct mail_save_context *ctx,
                            enum mail_flags flags,
                            struct mail_keywords *keywords)
@@ -2117,7 +2143,12 @@ void mailbox_save_set_pop3_order(struct mail_save_context *ctx,
 void mailbox_save_set_dest_mail(struct mail_save_context *ctx,
                                struct mail *mail)
 {
+       i_assert(mail != NULL);
+
+       if (!ctx->dest_mail_external)
+               mail_free(&ctx->dest_mail);
        ctx->dest_mail = mail;
+       ctx->dest_mail_external = TRUE;
 }
 
 int mailbox_save_begin(struct mail_save_context **ctx, struct istream *input)
@@ -2244,7 +2275,6 @@ void mailbox_save_cancel(struct mail_save_context **_ctx)
 {
        struct mail_save_context *ctx = *_ctx;
        struct mail_keywords *keywords = ctx->data.keywords;
-       struct mail_private *mail;
 
        *_ctx = NULL;
        T_BEGIN {
@@ -2252,13 +2282,12 @@ void mailbox_save_cancel(struct mail_save_context **_ctx)
        } T_END;
        if (keywords != NULL && !ctx->finishing)
                mailbox_keywords_unref(&keywords);
-       if (ctx->dest_mail != NULL) {
-               /* the dest_mail is no longer valid. if we're still saving
-                  more mails, the mail sequence may get reused. make sure
-                  the mail gets reset in between */
-               mail = (struct mail_private *)ctx->dest_mail;
-               mail->v.close(&mail->mail);
-       }
+
+       /* the dest_mail is no longer valid. if we're still saving
+          more mails, the mail sequence may get reused. make sure
+          the mail gets reset in between */
+       mailbox_save_dest_mail_close(ctx);
+
        mailbox_save_context_reset(ctx, FALSE);
 }