dovecot: Store virtual sizes to dovecot-uidlist if we want to us...

dovecot at dovecot.org dovecot at dovecot.org
Thu Jul 12 03:21:50 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/e9b5d3d33b95
changeset: 5951:e9b5d3d33b95
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Jul 12 02:44:47 2007 +0300
description:
Store virtual sizes to dovecot-uidlist if we want to use them all the time.
If nothing else than virtual size is wanted to be known (ie. POP3 or
POP3-like IMAP client), don't bother updating cache file at all.

diffstat:

3 files changed, 133 insertions(+), 47 deletions(-)
src/lib-storage/index/index-mail.c           |   59 ++++++-------
src/lib-storage/index/index-mail.h           |    4 
src/lib-storage/index/maildir/maildir-mail.c |  117 ++++++++++++++++++++++----

diffs (265 lines):

diff -r 49aebb3028f7 -r e9b5d3d33b95 src/lib-storage/index/index-mail.c
--- a/src/lib-storage/index/index-mail.c	Thu Jul 12 02:42:32 2007 +0300
+++ b/src/lib-storage/index/index-mail.c	Thu Jul 12 02:44:47 2007 +0300
@@ -110,17 +110,6 @@ uoff_t index_mail_get_cached_uoff_t(stru
 	return uoff;
 }
 
-uoff_t index_mail_get_cached_virtual_size(struct index_mail *mail)
-{
-	return index_mail_get_cached_uoff_t(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE);
-}
-
-static uoff_t index_mail_get_cached_physical_size(struct index_mail *mail)
-{
-	return index_mail_get_cached_uoff_t(mail,
-					    MAIL_CACHE_PHYSICAL_FULL_SIZE);
-}
-
 enum mail_flags index_mail_get_flags(struct mail *_mail)
 {
 	struct index_mail *mail = (struct index_mail *) _mail;
@@ -296,6 +285,21 @@ static bool get_cached_msgpart_sizes(str
 	return data->parts != NULL;
 }
 
+uoff_t index_mail_get_cached_virtual_size(struct index_mail *mail)
+{
+	uoff_t size;
+
+	if (mail->data.virtual_size != (uoff_t)-1)
+		return mail->data.virtual_size;
+
+	size = index_mail_get_cached_uoff_t(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE);
+	if (size != (uoff_t)-1)
+		mail->data.virtual_size = size;
+	else
+		(void)get_cached_msgpart_sizes(mail);
+	return mail->data.virtual_size;
+}
+
 uoff_t index_mail_get_virtual_size(struct mail *_mail)
 {
 	struct index_mail *mail = (struct index_mail *) _mail;
@@ -303,20 +307,13 @@ uoff_t index_mail_get_virtual_size(struc
 	struct message_size hdr_size, body_size;
 	uoff_t old_offset;
 
-	if (data->virtual_size != (uoff_t)-1)
+	if (index_mail_get_cached_virtual_size(mail) != (uoff_t)-1)
 		return data->virtual_size;
 
-	data->virtual_size = index_mail_get_cached_virtual_size(mail);
-	if (data->virtual_size != (uoff_t)-1)
-		return data->virtual_size;
-
-	if (!get_cached_msgpart_sizes(mail)) {
-		old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
-
-		if (mail_get_stream(_mail, &hdr_size, &body_size) == NULL)
-			return (uoff_t)-1;
-		i_stream_seek(data->stream, old_offset);
-	}
+	old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
+	if (mail_get_stream(_mail, &hdr_size, &body_size) == NULL)
+		return (uoff_t)-1;
+	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,
@@ -328,18 +325,18 @@ uoff_t index_mail_get_physical_size(stru
 {
 	struct index_mail *mail = (struct index_mail *) _mail;
 	struct index_mail_data *data = &mail->data;
+	uoff_t size;
 
 	if (data->physical_size != (uoff_t)-1)
 		return data->physical_size;
 
-	data->physical_size = index_mail_get_cached_physical_size(mail);
-	if (data->physical_size != (uoff_t)-1)
-		return data->physical_size;
-
-	if (get_cached_msgpart_sizes(mail))
-		return data->physical_size;
-
-	return (uoff_t)-1;
+	size = index_mail_get_cached_uoff_t(mail,
+					    MAIL_CACHE_PHYSICAL_FULL_SIZE);
+	if (size != (uoff_t)-1)
+		data->physical_size = size;
+	else
+		(void)get_cached_msgpart_sizes(mail);
+	return data->physical_size;
 }
 
 void index_mail_cache_add(struct index_mail *mail, enum index_cache_field field,
diff -r 49aebb3028f7 -r e9b5d3d33b95 src/lib-storage/index/index-mail.h
--- a/src/lib-storage/index/index-mail.h	Thu Jul 12 02:42:32 2007 +0300
+++ b/src/lib-storage/index/index-mail.h	Thu Jul 12 02:44:47 2007 +0300
@@ -118,6 +118,8 @@ struct index_mail {
 	enum mail_fetch_field wanted_fields;
 	struct index_header_lookup_ctx *wanted_headers;
 
+	int pop3_state;
+
 	/* per-mail variables, here for performance reasons: */
 	uint32_t header_seq;
 	string_t *header_data;
@@ -125,6 +127,8 @@ struct index_mail {
 	ARRAY_DEFINE(header_match, uint8_t);
 	ARRAY_DEFINE(header_match_lines, unsigned int);
 	uint8_t header_match_value;
+
+	unsigned int pop3_state_set:1;
 };
 
 struct mail *
diff -r 49aebb3028f7 -r e9b5d3d33b95 src/lib-storage/index/maildir/maildir-mail.c
--- a/src/lib-storage/index/maildir/maildir-mail.c	Thu Jul 12 02:42:32 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-mail.c	Thu Jul 12 02:44:47 2007 +0300
@@ -7,6 +7,7 @@
 #include "maildir-filename.h"
 #include "maildir-uidlist.h"
 
+#include <stdlib.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/stat.h>
@@ -149,22 +150,75 @@ maildir_mail_get_fname(struct maildir_ma
 	return TRUE;
 }
 
+static int maildir_get_pop3_state(struct index_mail *mail)
+{
+	const struct mail_cache_field *fields;
+	unsigned int i, count, vsize_idx;
+	enum mail_cache_decision_type dec, vsize_dec;
+	enum mail_fetch_field allowed_pop3_fields;
+	bool not_pop3_only = FALSE;
+
+	if (mail->pop3_state_set)
+		return mail->pop3_state;
+
+	/* if this mail itself has non-pop3 fields we know we're not
+	   pop3-only */
+	allowed_pop3_fields = MAIL_FETCH_FLAGS | MAIL_FETCH_STREAM_HEADER |
+		MAIL_FETCH_STREAM_BODY | MAIL_FETCH_UIDL_FILE_NAME |
+		MAIL_FETCH_VIRTUAL_SIZE;
+
+	if (mail->wanted_headers != NULL ||
+	    (mail->wanted_fields & allowed_pop3_fields) == 0)
+		not_pop3_only = TRUE;
+
+	/* get vsize decision */
+	vsize_idx = mail->ibox->cache_fields[MAIL_CACHE_VIRTUAL_FULL_SIZE].idx;
+	if (not_pop3_only) {
+		vsize_dec = mail_cache_field_get_decision(mail->ibox->cache,
+							  vsize_idx);
+		vsize_dec &= ~MAIL_CACHE_DECISION_FORCED;
+	} else {
+		/* also check if there are any non-vsize cached fields */
+		vsize_dec = MAIL_CACHE_DECISION_NO;
+		fields = mail_cache_register_get_list(mail->ibox->cache,
+						      pool_datastack_create(),
+						      &count);
+		for (i = 0; i < count; i++) {
+			dec = fields[i].decision & ~MAIL_CACHE_DECISION_FORCED;
+			if (fields[i].idx == vsize_idx)
+				vsize_dec = dec;
+			else if (dec != MAIL_CACHE_DECISION_NO)
+				not_pop3_only = TRUE;
+		}
+	}
+
+	if (!not_pop3_only) {
+		/* either nothing is cached, or only vsize is cached. */
+		mail->pop3_state = 1;
+	} else if (vsize_dec != MAIL_CACHE_DECISION_YES) {
+		/* if virtual size isn't cached permanently,
+		   POP3 isn't being used */
+		mail->pop3_state = -1;
+	} else {
+		/* possibly a mixed pop3/imap */
+		mail->pop3_state = 0;
+	}
+	mail->pop3_state_set = TRUE;
+	return mail->pop3_state;
+}
+
 static uoff_t maildir_mail_get_virtual_size(struct mail *_mail)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
 	struct index_mail_data *data = &mail->data;
-	const char *path, *fname;
-	uoff_t virtual_size;
-
-	if (data->virtual_size != (uoff_t)-1)
+	struct message_size hdr_size, body_size;
+	const char *path, *fname, *value;
+	uoff_t old_offset;
+	int pop3_state;
+
+	if (index_mail_get_cached_virtual_size(mail) != (uoff_t)-1)
 		return data->virtual_size;
-
-	if ((mail->wanted_fields & MAIL_FETCH_VIRTUAL_SIZE) == 0) {
-		data->virtual_size = index_mail_get_cached_virtual_size(mail);
-		if (data->virtual_size != (uoff_t)-1)
-			return data->virtual_size;
-	}
 
 	if (_mail->uid != 0) {
 		if (!maildir_mail_get_fname(mbox, _mail, &fname))
@@ -178,13 +232,44 @@ static uoff_t maildir_mail_get_virtual_s
 
 	/* size can be included in filename */
 	if (maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE,
-				      &virtual_size)) {
+				      &data->virtual_size))
+		return data->virtual_size;
+
+	/* 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;
+
+			data->virtual_size = strtoull(value, &p, 10);
+			if (*p == '\0')
+				return data->virtual_size;
+		}
+	}
+
+	/* fallback to reading the file */
+	old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
+	if (mail_get_stream(_mail, &hdr_size, &body_size) == NULL)
+		return (uoff_t)-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,
-				     &virtual_size, sizeof(virtual_size));
-		return virtual_size;
-	}
-
-	return index_mail_get_virtual_size(_mail);
+				     &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));
+	}
+	return data->virtual_size;
 }
 
 static const char *


More information about the dovecot-cvs mailing list