changeset 6842:d2c8269a0679 HEAD

Cleanups/rewrites to how/when date/size caching is done.
author Timo Sirainen <tss@iki.fi>
date Thu, 22 Nov 2007 09:36:57 +0200
parents 0c970b3493ac
children 9ca7f055b646
files src/lib-storage/index/cydir/cydir-mail.c src/lib-storage/index/dbox/dbox-mail.c src/lib-storage/index/index-mail-headers.c src/lib-storage/index/index-mail.c src/lib-storage/index/index-mail.h src/lib-storage/index/maildir/maildir-mail.c src/lib-storage/index/mbox/mbox-mail.c
diffstat 7 files changed, 214 insertions(+), 154 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/index/cydir/cydir-mail.c	Thu Nov 22 07:56:38 2007 +0200
+++ b/src/lib-storage/index/cydir/cydir-mail.c	Thu Nov 22 09:36:57 2007 +0200
@@ -40,17 +40,14 @@
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	struct stat st;
-	uint32_t t;
 
-	(void)index_mail_get_received_date(_mail, date_r);
-	if (*date_r != (time_t)-1)
+	if (index_mail_get_received_date(_mail, date_r) == 0)
 		return 0;
 
 	if (cydir_mail_stat(_mail, &st) < 0)
 		return -1;
 
-	data->received_date = t = st.st_mtime;
-	index_mail_cache_add(mail, MAIL_CACHE_RECEIVED_DATE, &t, sizeof(t));
+	data->received_date = st.st_mtime;
 	*date_r = data->received_date;
 	return 0;
 }
@@ -60,17 +57,14 @@
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	struct stat st;
-	uint32_t t;
 
-	(void)index_mail_get_save_date(_mail, date_r);
-	if (*date_r != (time_t)-1)
+	if (index_mail_get_save_date(_mail, date_r) == 0)
 		return 0;
 
 	if (cydir_mail_stat(_mail, &st) < 0)
 		return (time_t)-1;
 
-	data->save_date = t = st.st_ctime;
-	index_mail_cache_add(mail, MAIL_CACHE_SAVE_DATE, &t, sizeof(t));
+	data->save_date = st.st_ctime;
 	*date_r = data->save_date;
 	return 0;
 }
@@ -81,16 +75,13 @@
 	struct index_mail_data *data = &mail->data;
 	struct stat st;
 
-	(void)index_mail_get_physical_size(_mail, size_r);
-	if (*size_r != (uoff_t)-1)
+	if (index_mail_get_physical_size(_mail, size_r) == 0)
 		return 0;
 
 	if (cydir_mail_stat(_mail, &st) < 0)
 		return -1;
 
 	data->physical_size = data->virtual_size = st.st_size;
-	index_mail_cache_add(mail, MAIL_CACHE_PHYSICAL_FULL_SIZE,
-			     &data->physical_size, sizeof(data->physical_size));
 	*size_r = data->physical_size;
 	return 0;
 }
--- a/src/lib-storage/index/dbox/dbox-mail.c	Thu Nov 22 07:56:38 2007 +0200
+++ b/src/lib-storage/index/dbox/dbox-mail.c	Thu Nov 22 09:36:57 2007 +0200
@@ -91,19 +91,15 @@
 	struct index_mail_data *data = &mail->imail.data;
 	struct dbox_file *file;
 	const char *value;
-	uint32_t t;
 
-	(void)index_mail_get_received_date(_mail, date_r);
-	if (*date_r != (time_t)-1)
+	if (index_mail_get_received_date(_mail, date_r) == 0)
 		return 0;
 
 	if (dbox_mail_metadata_seek(mail, &file) < 0)
 		return -1;
 
 	value = dbox_file_metadata_get(file, DBOX_METADATA_RECEIVED_TIME);
-	data->received_date = t = value == NULL ? 0 : strtoul(value, NULL, 16);
-	index_mail_cache_add(&mail->imail, MAIL_CACHE_RECEIVED_DATE,
-			     &t, sizeof(t));
+	data->received_date = value == NULL ? 0 : strtoul(value, NULL, 16);
 	*date_r = data->received_date;
 	return 0;
 }
@@ -114,18 +110,15 @@
 	struct index_mail_data *data = &mail->imail.data;
 	struct dbox_file *file;
 	const char *value;
-	uint32_t t;
 
-	(void)index_mail_get_save_date(_mail, date_r);
-	if (*date_r != (time_t)-1)
+	if (index_mail_get_save_date(_mail, date_r) == 0)
 		return 0;
 
 	if (dbox_mail_metadata_seek(mail, &file) < 0)
 		return -1;
 
 	value = dbox_file_metadata_get(file, DBOX_METADATA_SAVE_TIME);
-	data->save_date = t = value == NULL ? 0 : strtoul(value, NULL, 16);
-	index_mail_cache_add(&mail->imail, MAIL_CACHE_SAVE_DATE, &t, sizeof(t));
+	data->save_date = value == NULL ? 0 : strtoul(value, NULL, 16);
 	*date_r = data->save_date;
 	return 0;
 }
@@ -148,8 +141,6 @@
 		return index_mail_get_virtual_size(_mail, size_r);
 
 	data->virtual_size = strtoul(value, NULL, 16);
-	index_mail_cache_add(&mail->imail, MAIL_CACHE_VIRTUAL_FULL_SIZE,
-			     &data->virtual_size, sizeof(data->virtual_size));
 	*size_r = data->virtual_size;
 	return 0;
 }
@@ -160,16 +151,13 @@
 	struct index_mail_data *data = &mail->data;
 	struct istream *input;
 
-	(void)index_mail_get_physical_size(_mail, size_r);
-	if (*size_r != (uoff_t)-1)
+	if (index_mail_get_physical_size(_mail, size_r) == 0)
 		return 0;
 
 	if (mail_get_stream(_mail, NULL, NULL, &input) < 0)
 		return -1;
 
 	i_assert(data->physical_size != (uoff_t)-1);
-	index_mail_cache_add(mail, MAIL_CACHE_PHYSICAL_FULL_SIZE,
-			     &data->physical_size, sizeof(data->physical_size));
 	*size_r = data->physical_size;
 	return 0;
 }
--- a/src/lib-storage/index/index-mail-headers.c	Thu Nov 22 07:56:38 2007 +0200
+++ b/src/lib-storage/index/index-mail-headers.c	Thu Nov 22 09:36:57 2007 +0200
@@ -164,8 +164,14 @@
 
 bool index_mail_want_parse_headers(struct index_mail *mail)
 {
-	return mail->wanted_headers != NULL || mail->data.save_sent_date ||
-		mail->data.save_bodystructure_header;
+	if (mail->wanted_headers != NULL ||
+	    mail->data.save_bodystructure_header)
+		return TRUE;
+
+	if ((mail->data.cache_fetch_fields & MAIL_FETCH_DATE) != 0 &&
+	    !mail->data.sent_date_parsed)
+		return TRUE;
+	return FALSE;
 }
 
 void index_mail_parse_header_init(struct index_mail *mail,
@@ -213,9 +219,7 @@
 		}
 	}
 
-	if (mail->data.save_sent_date) {
-                mail->data.save_sent_date = FALSE;
-
+	if ((mail->data.cache_fetch_fields & MAIL_FETCH_DATE) != 0) {
 		array_idx_set(&mail->header_match,
 			      get_header_field_idx(mail->ibox, "Date"),
 			      &mail->header_match_value);
@@ -242,13 +246,18 @@
 static void index_mail_parse_finish_imap_envelope(struct index_mail *mail)
 {
 	string_t *str;
+	unsigned int cache_field;
 
 	str = str_new(mail->data_pool, 256);
 	imap_envelope_write_part_data(mail->data.envelope_data, str);
 	mail->data.envelope = str_c(str);
 
-	index_mail_cache_add(mail, MAIL_CACHE_IMAP_ENVELOPE,
-			     str_data(str), str_len(str));
+	cache_field = mail->ibox->cache_fields[MAIL_CACHE_IMAP_ENVELOPE].idx;
+	if (mail_cache_field_want_add(mail->trans->cache_trans,
+				      mail->data.seq, cache_field)) {
+		index_mail_cache_add_idx(mail, cache_field,
+					 str_data(str), str_len(str));
+	}
 }
 
 void index_mail_parse_header(struct message_part *part,
@@ -277,11 +286,8 @@
 
 	if (hdr == NULL) {
 		/* end of headers */
-		if (data->sent_date.time != (uint32_t)-1) {
-			index_mail_cache_add(mail, MAIL_CACHE_SENT_DATE,
-					     &data->sent_date,
-					     sizeof(data->sent_date));
-		}
+		if (mail->data.save_sent_date)
+			mail->data.sent_date_parsed = TRUE;
 		index_mail_parse_header_finish(mail);
                 data->save_bodystructure_header = FALSE;
 		return;
--- a/src/lib-storage/index/index-mail.c	Thu Nov 22 07:56:38 2007 +0200
+++ b/src/lib-storage/index/index-mail.c	Thu Nov 22 09:36:57 2007 +0200
@@ -164,6 +164,7 @@
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 
+	data->cache_fetch_fields |= MAIL_FETCH_MESSAGE_PARTS;
 	if (data->parts != NULL || get_cached_parts(mail)) {
 		*parts_r = data->parts;
 		return 0;
@@ -187,6 +188,7 @@
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 
+	data->cache_fetch_fields |= MAIL_FETCH_RECEIVED_DATE;
 	if (data->received_date == (time_t)-1) {
 		uint32_t t;
 
@@ -196,7 +198,7 @@
 	}
 
 	*date_r = data->received_date;
-	return 0;
+	return *date_r == (time_t)-1 ? -1 : 0;
 }
 
 int index_mail_get_save_date(struct mail *_mail, time_t *date_r)
@@ -204,6 +206,7 @@
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 
+	data->cache_fetch_fields |= MAIL_FETCH_SAVE_DATE;
 	if (data->save_date == (time_t)-1) {
 		uint32_t t;
 
@@ -213,7 +216,7 @@
 	}
 
 	*date_r = data->save_date;
-	return 0;
+	return *date_r == (time_t)-1 ? -1 : 0;
 }
 
 static int index_mail_cache_sent_date(struct index_mail *mail)
@@ -248,6 +251,7 @@
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 
+	data->cache_fetch_fields |= MAIL_FETCH_DATE;
 	if (data->sent_date.time != (uint32_t)-1) {
 		*date_r = data->sent_date.time;
 		return 0;
@@ -288,6 +292,7 @@
 
 bool index_mail_get_cached_virtual_size(struct index_mail *mail, uoff_t *size_r)
 {
+	mail->data.cache_fetch_fields |= MAIL_FETCH_VIRTUAL_SIZE;
 	if (mail->data.virtual_size == (uoff_t)-1) {
 		if (!index_mail_get_cached_uoff_t(mail,
 						  MAIL_CACHE_VIRTUAL_FULL_SIZE,
@@ -317,8 +322,6 @@
 	i_stream_seek(data->stream, old_offset);
 
 	i_assert(data->virtual_size != (uoff_t)-1);
-	index_mail_cache_add(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE,
-			     &data->virtual_size, sizeof(data->virtual_size));
 	*size_r = data->virtual_size;
 	return 0;
 }
@@ -328,6 +331,7 @@
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 
+	data->cache_fetch_fields |= MAIL_FETCH_PHYSICAL_SIZE;
 	if (data->physical_size == (uoff_t)-1) {
 		if (!index_mail_get_cached_uoff_t(mail,
 						  MAIL_CACHE_PHYSICAL_FULL_SIZE,
@@ -335,7 +339,7 @@
 			(void)get_cached_msgpart_sizes(mail);
 	}
 	*size_r = data->physical_size;
-	return 0;
+	return *size_r == (uoff_t)-1 ? -1 : 0;
 }
 
 void index_mail_cache_add(struct index_mail *mail, enum index_cache_field field,
@@ -465,8 +469,7 @@
 	t_push();
 	buffer = buffer_create_dynamic(pool_datastack_create(), 1024);
 	message_part_serialize(mail->data.parts, buffer);
-	index_mail_cache_add(mail, MAIL_CACHE_MESSAGE_PARTS,
-			     buffer->data, buffer->used);
+	index_mail_cache_add_idx(mail, cache_field, buffer->data, buffer->used);
 	t_pop();
 
 	data->messageparts_saved_to_cache = TRUE;
@@ -560,30 +563,93 @@
 	}
 }
 
-static void index_mail_body_parsed_cache_sizes(struct index_mail *mail)
+static bool
+index_mail_want_cache(struct index_mail *mail, enum index_cache_field field)
 {
-	static enum index_cache_field date_fields[] = {
+	enum mail_fetch_field fetch_field;
+	unsigned int cache_field;
+
+	switch (field) {
+	case MAIL_CACHE_SENT_DATE:
+		fetch_field = MAIL_FETCH_DATE;
+		break;
+	case MAIL_CACHE_RECEIVED_DATE:
+		fetch_field = MAIL_FETCH_RECEIVED_DATE;
+		break;
+	case MAIL_CACHE_SAVE_DATE:
+		fetch_field = MAIL_FETCH_SAVE_DATE;
+		break;
+	case MAIL_CACHE_VIRTUAL_FULL_SIZE:
+		fetch_field = MAIL_FETCH_VIRTUAL_SIZE;
+		break;
+	case MAIL_CACHE_PHYSICAL_FULL_SIZE:
+		fetch_field = MAIL_FETCH_PHYSICAL_SIZE;
+		break;
+	default:
+		i_unreached();
+	}
+
+	if ((mail->data.dont_cache_fetch_fields & fetch_field) != 0)
+		return FALSE;
+
+	cache_field = mail->ibox->cache_fields[field].idx;
+	if ((mail->data.cache_fetch_fields & fetch_field) != 0) {
+		return mail_cache_field_can_add(mail->trans->cache_trans,
+						mail->data.seq, cache_field);
+	} else {
+		return mail_cache_field_want_add(mail->trans->cache_trans,
+						 mail->data.seq, cache_field);
+	}
+}
+
+static void index_mail_cache_sizes(struct index_mail *mail)
+{
+	static enum index_cache_field size_fields[] = {
 		MAIL_CACHE_VIRTUAL_FULL_SIZE,
 		MAIL_CACHE_PHYSICAL_FULL_SIZE
 	};
-	uoff_t sizes[N_ELEMENTS(date_fields)];
-	unsigned int i, cache_field;
+	uoff_t sizes[N_ELEMENTS(size_fields)];
+	unsigned int i;
 
 	sizes[0] = mail->data.virtual_size;
 	sizes[1] = mail->data.physical_size;
 
-	for (i = 0; i < N_ELEMENTS(date_fields); i++) {
-		cache_field = mail->ibox->cache_fields[date_fields[i]].idx;
-
-		i_assert(sizes[i] != (uoff_t)-1);
-		if (mail_cache_field_want_add(mail->trans->cache_trans,
-					      mail->data.seq, cache_field)) {
-			index_mail_cache_add(mail, date_fields[i],
+	for (i = 0; i < N_ELEMENTS(size_fields); i++) {
+		if (sizes[i] != (uoff_t)-1 &&
+		    index_mail_want_cache(mail, size_fields[i])) {
+			index_mail_cache_add(mail, size_fields[i],
 					     &sizes[i], sizeof(sizes[i]));
 		}
 	}
 }
 
+static void index_mail_cache_dates(struct index_mail *mail)
+{
+	static enum index_cache_field date_fields[] = {
+		MAIL_CACHE_RECEIVED_DATE,
+		MAIL_CACHE_SAVE_DATE
+	};
+	time_t dates[N_ELEMENTS(date_fields)];
+	unsigned int i;
+	uint32_t t;
+
+	dates[0] = mail->data.received_date;
+	dates[1] = mail->data.save_date;
+
+	for (i = 0; i < N_ELEMENTS(date_fields); i++) {
+		if (dates[i] != (time_t)-1 &&
+		    index_mail_want_cache(mail, date_fields[i])) {
+			t = dates[i];
+			index_mail_cache_add(mail, date_fields[i],
+					     &t, sizeof(t));
+		}
+	}
+
+	if (mail->data.sent_date_parsed &&
+	    index_mail_want_cache(mail, MAIL_CACHE_SENT_DATE))
+		(void)index_mail_cache_sent_date(mail);
+}
+
 static void index_mail_parse_body_finish(struct index_mail *mail,
 					 enum index_cache_field field)
 {
@@ -594,7 +660,8 @@
 	index_mail_body_parsed_cache_flags(mail);
 	index_mail_body_parsed_cache_message_parts(mail);
 	index_mail_body_parsed_cache_bodystructure(mail, field);
-	index_mail_body_parsed_cache_sizes(mail);
+	index_mail_cache_sizes(mail);
+	index_mail_cache_dates(mail);
 }
 
 static int index_mail_stream_check_failure(struct index_mail *mail)
@@ -900,6 +967,11 @@
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 
+	if (mail->mail.mail.seq != 0) {
+		index_mail_cache_sizes(mail);
+		index_mail_cache_dates(mail);
+	}
+
 	if (mail->data.parser_ctx != NULL)
 		(void)message_parser_deinit(&mail->data.parser_ctx);
 	if (mail->data.stream != NULL)
@@ -1054,7 +1126,7 @@
 		if (mail_cache_field_exists(cache_view, seq,
 					    cache_field) <= 0) {
 			data->access_part |= PARSE_HDR;
-			data->save_sent_date = TRUE;
+			data->save_sent_date = TRUE;;
 		}
 	}
 
@@ -1128,37 +1200,6 @@
 	}
 }
 
-static void index_mail_cache_dates(struct index_mail *mail)
-{
-	static enum index_cache_field date_fields[] = {
-		MAIL_CACHE_RECEIVED_DATE,
-		MAIL_CACHE_SAVE_DATE
-	};
-	time_t dates[N_ELEMENTS(date_fields)];
-	unsigned int i, cache_field;
-	uint32_t t;
-
-	dates[0] = mail->data.received_date;
-	dates[1] = mail->data.save_date;
-
-	for (i = 0; i < N_ELEMENTS(date_fields); i++) {
-		cache_field = mail->ibox->cache_fields[date_fields[i]].idx;
-
-		i_assert(dates[i] != (time_t)-1);
-		if (mail_cache_field_want_add(mail->trans->cache_trans,
-					      mail->data.seq, cache_field)) {
-			t = dates[i];
-			index_mail_cache_add(mail, date_fields[i],
-					     &t, sizeof(t));
-		}
-	}
-
-	cache_field = mail->ibox->cache_fields[MAIL_CACHE_SENT_DATE].idx;
-	if (mail_cache_field_want_add(mail->trans->cache_trans,
-				      mail->data.seq, cache_field))
-		(void)index_mail_cache_sent_date(mail);
-}
-
 void index_mail_cache_parse_deinit(struct mail *_mail, time_t received_date)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
@@ -1175,7 +1216,6 @@
 	mail->data.save_bodystructure_body = FALSE;
 	mail->data.parsed_bodystructure = TRUE;
 	index_mail_parse_body_finish(mail, 0);
-	index_mail_cache_dates(mail);
 }
 
 void index_mail_update_flags(struct mail *mail, enum modify_type modify_type,
--- a/src/lib-storage/index/index-mail.h	Thu Nov 22 07:56:38 2007 +0200
+++ b/src/lib-storage/index/index-mail.h	Thu Nov 22 09:36:57 2007 +0200
@@ -81,7 +81,9 @@
 
 	uint32_t seq;
 	uint32_t cache_flags;
-        enum index_mail_access_part access_part;
+	enum index_mail_access_part access_part;
+	/* dont_cache_fields overrides cache_fields */
+	enum mail_fetch_field cache_fetch_fields, dont_cache_fetch_fields;
 
 	struct istream *stream, *filter_stream;
 	struct message_size hdr_size, body_size;
@@ -90,6 +92,7 @@
 	ARRAY_TYPE(keywords) keywords;
 
 	unsigned int save_sent_date:1;
+	unsigned int sent_date_parsed:1;
 	unsigned int save_envelope:1;
 	unsigned int save_bodystructure_header:1;
 	unsigned int save_bodystructure_body:1;
--- a/src/lib-storage/index/maildir/maildir-mail.c	Thu Nov 22 07:56:38 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-mail.c	Thu Nov 22 09:36:57 2007 +0200
@@ -111,17 +111,14 @@
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	struct stat st;
-	uint32_t t;
 
-	(void)index_mail_get_received_date(_mail, date_r);
-	if (*date_r != (time_t)-1)
+	if (index_mail_get_received_date(_mail, date_r) == 0)
 		return 0;
 
 	if (maildir_mail_stat(_mail, &st) < 0)
 		return -1;
 
-	*date_r = data->received_date = t = st.st_mtime;
-	index_mail_cache_add(mail, MAIL_CACHE_RECEIVED_DATE, &t, sizeof(t));
+	*date_r = data->received_date = st.st_mtime;
 	return 0;
 }
 
@@ -130,17 +127,14 @@
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	struct stat st;
-	uint32_t t;
 
-	(void)index_mail_get_save_date(_mail, date_r);
-	if (*date_r != (time_t)-1)
+	if (index_mail_get_save_date(_mail, date_r) == 0)
 		return 0;
 
 	if (maildir_mail_stat(_mail, &st) < 0)
 		return -1;
 
-	*date_r = data->save_date = t = st.st_ctime;
-	index_mail_cache_add(mail, MAIL_CACHE_SAVE_DATE, &t, sizeof(t));
+	*date_r = data->save_date = st.st_ctime;
 	return data->save_date;
 }
 
@@ -215,19 +209,14 @@
 	return mail->pop3_state;
 }
 
-static int maildir_mail_get_virtual_size(struct mail *_mail, uoff_t *size_r)
+static int maildir_quick_virtual_size_lookup(struct index_mail *mail)
 {
-	struct index_mail *mail = (struct index_mail *)_mail;
+	struct mail *_mail = &mail->mail.mail;
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
 	struct index_mail_data *data = &mail->data;
-	struct message_size hdr_size, body_size;
-	struct istream *input;
 	const char *path, *fname, *value;
-	uoff_t old_offset, size;
-	int pop3_state;
-
-	if (index_mail_get_cached_virtual_size(mail, size_r))
-		return 0;
+	uoff_t size;
+	char *p;
 
 	if (_mail->uid != 0) {
 		if (!maildir_mail_get_fname(mbox, _mail, &fname))
@@ -241,47 +230,78 @@
 
 	/* size can be included in filename */
 	if (maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE,
-				      &data->virtual_size)) {
-		*size_r = data->virtual_size;
-		return 0;
-	}
+				      &data->virtual_size))
+		return 1;
 
 	/* size can be included in uidlist entry */
 	if (_mail->uid != 0) {
 		value = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
 						MAILDIR_UIDLIST_REC_EXT_VSIZE);
 		if (value != NULL) {
-			char *p;
-
 			size = strtoull(value, &p, 10);
 			if (*p == '\0') {
-				data->virtual_size = *size_r = size;
-				return 0;
+				data->virtual_size = size;
+				return 1;
 			}
 		}
 	}
+	return 0;
+}
+
+static void
+maildir_handle_virtual_size_caching(struct index_mail *mail, bool quick_check)
+{
+	struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
+	int pop3_state;
+
+	i_assert(mail->data.virtual_size != (uoff_t)-1);
+
+	if ((mail->data.dont_cache_fetch_fields & MAIL_FETCH_VIRTUAL_SIZE) != 0)
+		return;
+
+	if (quick_check && maildir_quick_virtual_size_lookup(mail) > 0)
+		mail->data.dont_cache_fetch_fields |= MAIL_FETCH_VIRTUAL_SIZE;
+
+	/* 1 = pop3-only, 0 = mixed, -1 = no pop3 */
+	pop3_state = maildir_get_pop3_state(mail);
+	if (pop3_state >= 0) {
+		/* if virtual size is wanted permanently, store it to uidlist
+		   so that in case cache file gets lost we can get it quickly */
+		mail->data.dont_cache_fetch_fields |= MAIL_FETCH_VIRTUAL_SIZE;
+		maildir_uidlist_set_ext(mbox->uidlist, mail->mail.mail.uid,
+					MAILDIR_UIDLIST_REC_EXT_VSIZE,
+					dec2str(mail->data.virtual_size));
+	}
+}
+
+static int maildir_mail_get_virtual_size(struct mail *_mail, uoff_t *size_r)
+{
+	struct index_mail *mail = (struct index_mail *)_mail;
+	struct index_mail_data *data = &mail->data;
+	struct message_size hdr_size, body_size;
+	struct istream *input;
+	uoff_t old_offset;
+
+	if (index_mail_get_cached_virtual_size(mail, size_r)) {
+		maildir_handle_virtual_size_caching(mail, TRUE);
+		return 0;
+	}
+
+	if (maildir_quick_virtual_size_lookup(mail) < 0)
+		return -1;
+	if (data->virtual_size != (uoff_t)-1) {
+		data->dont_cache_fetch_fields |= MAIL_FETCH_VIRTUAL_SIZE;
+		*size_r = data->virtual_size;
+		return 0;
+	}
 
 	/* fallback to reading the file */
 	old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
 	if (mail_get_stream(_mail, &hdr_size, &body_size, &input) < 0)
 		return -1;
 	i_stream_seek(data->stream, old_offset);
-	i_assert(data->virtual_size != (uoff_t)-1);
 
-	/* 1 = pop3-only, 0 = mixed, -1 = no pop3 */
-	pop3_state = maildir_get_pop3_state(mail);
-	if (pop3_state <= 0) {
-		index_mail_cache_add(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE,
-				     &data->virtual_size,
-				     sizeof(data->virtual_size));
-	}
-	if (pop3_state >= 0) {
-		/* if virtual size is wanted permanently, store it to uidlist
-		   so that in case cache file gets lost we can get it quickly */
-		maildir_uidlist_set_ext(mbox->uidlist, _mail->uid,
-					MAILDIR_UIDLIST_REC_EXT_VSIZE,
-					dec2str(data->virtual_size));
-	}
+	maildir_handle_virtual_size_caching(mail, FALSE);
 	*size_r = data->virtual_size;
 	return 0;
 }
@@ -322,8 +342,7 @@
 	uoff_t size;
 	int ret;
 
-	(void)index_mail_get_physical_size(_mail, size_r);
-	if (*size_r != (uoff_t)-1)
+	if (index_mail_get_physical_size(_mail, size_r) == 0)
 		return 0;
 
 	if (_mail->uid != 0) {
@@ -338,7 +357,11 @@
 	}
 
 	/* size can be included in filename */
-	if (!maildir_filename_get_size(fname, MAILDIR_EXTRA_FILE_SIZE, &size)) {
+	if (maildir_filename_get_size(fname, MAILDIR_EXTRA_FILE_SIZE, &size)) {
+		/* since the size is already in the file name, don't bother
+		   adding it to cache file */
+		data->dont_cache_fetch_fields |= MAIL_FETCH_PHYSICAL_SIZE;
+	} else {
 		if (_mail->uid != 0) {
 			ret = maildir_file_do(mbox, _mail->uid, do_stat, &st);
 			if (ret <= 0) {
@@ -357,8 +380,6 @@
 		size = st.st_size;
 	}
 
-	index_mail_cache_add(mail, MAIL_CACHE_PHYSICAL_FULL_SIZE,
-			     &size, sizeof(size));
 	data->physical_size = size;
 	*size_r = size;
 	return 0;
--- a/src/lib-storage/index/mbox/mbox-mail.c	Thu Nov 22 07:56:38 2007 +0200
+++ b/src/lib-storage/index/mbox/mbox-mail.c	Thu Nov 22 09:36:57 2007 +0200
@@ -96,10 +96,8 @@
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	struct mbox_mailbox *mbox = (struct mbox_mailbox *)mail->ibox;
-	uint32_t t;
 
-	(void)index_mail_get_received_date(_mail, date_r);
-	if (*date_r != (time_t)-1)
+	if (index_mail_get_received_date(_mail, date_r) == 0)
 		return 0;
 
 	if (mbox_mail_seek(mail) < 0)
@@ -112,8 +110,6 @@
 		data->received_date = 0;
 	}
 
-	t = data->received_date;
-	index_mail_cache_add(mail, MAIL_CACHE_RECEIVED_DATE, &t, sizeof(t));
 	*date_r = data->received_date;
 	return 0;
 }
@@ -123,16 +119,13 @@
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 
-	(void)index_mail_get_save_date(_mail, date_r);
-	if (*date_r != (time_t)-1)
+	if (index_mail_get_save_date(_mail, date_r) == 0)
 		return 0;
 
 	/* no way to know this. save the current time into cache and use
 	   that from now on. this works only as long as the index files
 	   are permanent */
 	data->save_date = ioloop_time;
-	index_mail_cache_add(mail, MAIL_CACHE_SAVE_DATE,
-			     &data->save_date, sizeof(data->save_date));
 	*date_r = data->save_date;
 	return 0;
 }
@@ -230,11 +223,29 @@
 	return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
 }
 
+static void mbox_mail_set_seq(struct mail *_mail, uint32_t seq)
+{
+	struct index_mail *mail = (struct index_mail *)_mail;
+
+	index_mail_set_seq(_mail, seq);
+	mail->data.dont_cache_fetch_fields |= MAIL_FETCH_PHYSICAL_SIZE;
+}
+
+static bool mbox_mail_set_uid(struct mail *_mail, uint32_t uid)
+{
+	struct index_mail *mail = (struct index_mail *)_mail;
+	bool ret;
+
+	ret = index_mail_set_uid(_mail, uid);
+	mail->data.dont_cache_fetch_fields |= MAIL_FETCH_PHYSICAL_SIZE;
+	return ret;
+}
+
 struct mail_vfuncs mbox_mail_vfuncs = {
 	index_mail_close,
 	index_mail_free,
-	index_mail_set_seq,
-	index_mail_set_uid,
+	mbox_mail_set_seq,
+	mbox_mail_set_uid,
 
 	index_mail_get_flags,
 	index_mail_get_keywords,