changeset 21967:040667a0b3be

lib-storage: Allow mail_add_temp_wanted_fields() to be called before mail_set_seq*() Quota plugin was already doing this, but it didn't actually work. It was also crashing with imapc: Panic: file mail-cache-lookup.c: line 341 (mail_cache_field_exists): assertion failed: (seq > 0)
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Wed, 19 Apr 2017 15:01:19 +0300
parents 44eb00aedb43
children a85bccd23139
files src/lib-storage/index/imapc/imapc-mail.c src/lib-storage/index/index-mail.c
diffstat 2 files changed, 36 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/index/imapc/imapc-mail.c	Thu Apr 20 19:16:46 2017 +0300
+++ b/src/lib-storage/index/imapc/imapc-mail.c	Wed Apr 19 15:01:19 2017 +0300
@@ -411,7 +411,8 @@
 	struct index_mail *mail = (struct index_mail *)_mail;
 
 	index_mail_add_temp_wanted_fields(_mail, fields, headers);
-	imapc_mail_update_access_parts(mail);
+	if (_mail->seq != 0)
+		imapc_mail_update_access_parts(mail);
 }
 
 static void imapc_mail_close(struct mail *_mail)
--- a/src/lib-storage/index/index-mail.c	Thu Apr 20 19:16:46 2017 +0300
+++ b/src/lib-storage/index/index-mail.c	Wed Apr 19 15:01:19 2017 +0300
@@ -68,6 +68,7 @@
 	   just be moved here to the same struct. */
 };
 
+static void index_mail_init_data(struct index_mail *mail);
 static int index_mail_parse_body(struct index_mail *mail,
 				 enum index_cache_field field);
 
@@ -1562,6 +1563,7 @@
 		mail->mail.wanted_headers = wanted_headers;
 		mailbox_header_lookup_ref(wanted_headers);
 	}
+	index_mail_init_data(mail);
 }
 
 static void index_mail_close_streams_full(struct index_mail *mail, bool closing)
@@ -1610,13 +1612,10 @@
 	index_mail_close_streams_full(mail, FALSE);
 }
 
-static void index_mail_reset_data(struct index_mail *mail)
+static void index_mail_init_data(struct index_mail *mail)
 {
 	struct index_mail_data *data = &mail->data;
 
-	i_zero(data);
-	p_clear(mail->mail.data_pool);
-
 	data->virtual_size = (uoff_t)-1;
 	data->physical_size = (uoff_t)-1;
 	data->save_date = (time_t)-1;
@@ -1629,6 +1628,14 @@
 		data->wanted_headers = mail->mail.wanted_headers;
 		mailbox_header_lookup_ref(data->wanted_headers);
 	}
+}
+
+static void index_mail_reset_data(struct index_mail *mail)
+{
+	i_zero(&mail->data);
+	p_clear(mail->mail.data_pool);
+
+	index_mail_init_data(mail);
 
 	mail->mail.mail.seq = 0;
 	mail->mail.mail.uid = 0;
@@ -1645,6 +1652,16 @@
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 
+	if (mail->mail.mail.seq == 0) {
+		/* mail_set_seq*() hasn't been called yet, or is being called
+		   right now. Don't reset anything yet. We especially don't
+		   want to reset wanted_fields or wanted_headers so that
+		   mail_add_temp_wanted_fields() can be called by plugins
+		   before mail_set_seq_saving() for
+		   mail_save_context.dest_mail. */
+		return;
+	}
+
 	/* If uid == 0 but seq != 0, we came here from saving a (non-mbox)
 	   message. If that happens, don't bother checking if anything should
 	   be cached since it was already checked. Also by now the transaction
@@ -1699,6 +1716,14 @@
 	const struct mail_cache_field *cache_fields = mail->ibox->cache_fields;
 	struct mail_cache_view *cache_view = _mail->transaction->cache_view;
 
+	if (_mail->seq == 0) {
+		/* mail_add_temp_wanted_fields() called before mail_set_seq*().
+		   We'll allow this, since it can be useful for plugins to
+		   call it for mail_save_context.dest_mail. This function
+		   is called again in mail_set_seq*(). */
+		return;
+	}
+
 	if ((data->wanted_fields & (MAIL_FETCH_NUL_STATE |
 				    MAIL_FETCH_IMAP_BODY |
 				    MAIL_FETCH_IMAP_BODYSTRUCTURE)) != 0 &&
@@ -1803,6 +1828,11 @@
 	const struct mail_index_header *hdr;
 	struct istream *input;
 
+	if (_mail->seq == 0) {
+		/* see index_mail_update_access_parts_pre() */
+		return;
+	}
+
 	/* when mail_prefetch_count>1, at this point we've started the
 	   prefetching to all the mails and we're now starting to access the
 	   first mail. */