changeset 21539:eafb085567bb

lib-storage: Always create mail_save_context.dest_mail 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.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Thu, 09 Feb 2017 16:53:47 +0200
parents cbb4cb127366
children 6a69f65921ea
files src/lib-storage/index/index-transaction.c src/lib-storage/mail-storage-private.h src/lib-storage/mail-storage.c
diffstat 3 files changed, 47 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/index/index-transaction.c	Thu Feb 09 16:34:52 2017 +0200
+++ b/src/lib-storage/index/index-transaction.c	Thu Feb 09 16:53:47 2017 +0200
@@ -47,6 +47,7 @@
 	}
 
 	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 @@
 		}
 	}
 
-	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 @@
 	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);
--- a/src/lib-storage/mail-storage-private.h	Thu Feb 09 16:34:52 2017 +0200
+++ b/src/lib-storage/mail-storage-private.h	Thu Feb 09 16:53:47 2017 +0200
@@ -674,6 +674,8 @@
 	/* 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 @@
 
 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
--- a/src/lib-storage/mail-storage.c	Thu Feb 09 16:34:52 2017 +0200
+++ b/src/lib-storage/mail-storage.c	Thu Feb 09 16:53:47 2017 +0200
@@ -2008,6 +2008,13 @@
 	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 @@
 	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_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 @@
 {
 	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 @@
 	} 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);
 }