changeset 2504:98f6057f27a1 HEAD

Added mail.get_physical_size().
author Timo Sirainen <tss@iki.fi>
date Sat, 28 Aug 2004 13:32:16 +0300
parents 2946fa696774
children 847759a0ff75
files src/imap/imap-fetch-body.c src/imap/imap-sort.c src/lib-storage/index/index-mail.c src/lib-storage/index/index-mail.h src/lib-storage/index/index-search.c src/lib-storage/index/maildir/maildir-mail.c src/lib-storage/index/mbox/mbox-mail.c src/lib-storage/mail-storage.h src/lib-storage/proxy-mail.c src/pop3/client.c src/pop3/commands.c
diffstat 11 files changed, 157 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap/imap-fetch-body.c	Sat Aug 28 13:31:37 2004 +0300
+++ b/src/imap/imap-fetch-body.c	Sat Aug 28 13:32:16 2004 +0300
@@ -759,7 +759,7 @@
 {
 	uoff_t size;
 
-	size = mail->get_size(mail);
+	size = mail->get_virtual_size(mail);
 	if (size == (uoff_t)-1)
 		return -1;
 
@@ -858,7 +858,7 @@
 	}
 
 	if (strcmp(arg+6, ".SIZE") == 0) {
-		ctx->fetch_data |= MAIL_FETCH_SIZE;
+		ctx->fetch_data |= MAIL_FETCH_VIRTUAL_SIZE;
 		imap_fetch_add_handler(ctx, fetch_rfc822_size, NULL);
 		return TRUE;
 	}
--- a/src/imap/imap-sort.c	Sat Aug 28 13:31:37 2004 +0300
+++ b/src/imap/imap-sort.c	Sat Aug 28 13:32:16 2004 +0300
@@ -143,7 +143,7 @@
 	if (ctx->cache_mask & MAIL_SORT_DATE)
 		fields |= MAIL_FETCH_DATE;
 	if (ctx->cache_mask & MAIL_SORT_SIZE)
-		fields |= MAIL_FETCH_SIZE;
+		fields |= MAIL_FETCH_VIRTUAL_SIZE;
 
 	/* @UNSAFE */
 	i_assert(MAX_WANTED_HEADERS > 4);
@@ -349,7 +349,7 @@
 	}
 
 	if (ctx->common_mask & MAIL_SORT_SIZE) {
-		size = mail->get_size(mail);
+		size = mail->get_virtual_size(mail);
 		if (size != ctx->last_size) {
 			ctx->last_size = size;
 			changed = TRUE;
@@ -425,7 +425,7 @@
 		if (ctx->common_mask & MAIL_SORT_SIZE)
 			size = ctx->last_size;
 		else
-			size = mail->get_size(mail);
+			size = mail->get_virtual_size(mail);
 
 		memcpy(buf + pos, &size, sizeof(size)); pos += sizeof(size);
 	}
@@ -554,7 +554,7 @@
 
 		i_assert(type == MAIL_SORT_SIZE);
 
-		return mail->get_size(mail);
+		return mail->get_virtual_size(mail);
 	}
 
 	/* use memcpy() to avoid any alignment problems */
--- a/src/lib-storage/index/index-mail.c	Sat Aug 28 13:31:37 2004 +0300
+++ b/src/lib-storage/index/index-mail.c	Sat Aug 28 13:32:16 2004 +0300
@@ -21,6 +21,8 @@
 	  sizeof(time_t), 0 },
 	{ "size.virtual", 0, MAIL_CACHE_FIELD_FIXED_SIZE,
 	  sizeof(uoff_t), 0 },
+	{ "size.physical", 0, MAIL_CACHE_FIELD_FIXED_SIZE,
+	  sizeof(uoff_t), 0 },
 	{ "imap.body", 0, MAIL_CACHE_FIELD_STRING, 0, 0 },
 	{ "imap.bodystructure", 0, MAIL_CACHE_FIELD_STRING, 0, 0 },
 	{ "imap.envelope", 0, MAIL_CACHE_FIELD_STRING, 0, 0 },
@@ -125,6 +127,12 @@
 	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);
+}
+
 time_t index_mail_get_cached_received_date(struct index_mail *mail)
 {
 	time_t t;
@@ -251,36 +259,56 @@
 		}
 		data->body_size = data->parts->body_size;
 		data->body_size_set = TRUE;
-		data->size = data->parts->header_size.virtual_size +
+		data->virtual_size = data->parts->header_size.virtual_size +
 			data->body_size.virtual_size;
+		data->physical_size = data->parts->header_size.physical_size +
+			data->body_size.physical_size;
 	}
 
 	return data->parts != NULL;
 }
 
-uoff_t index_mail_get_size(struct mail *_mail)
+uoff_t index_mail_get_virtual_size(struct mail *_mail)
 {
 	struct index_mail *mail = (struct index_mail *) _mail;
 	struct index_mail_data *data = &mail->data;
 	struct message_size hdr_size, body_size;
 
-	if (data->size != (uoff_t)-1)
-		return data->size;
+	if (data->virtual_size != (uoff_t)-1)
+		return data->virtual_size;
 
-	data->size = index_mail_get_cached_virtual_size(mail);
-	if (data->size != (uoff_t)-1)
-		return data->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))
-		return data->size;
+		return data->virtual_size;
 
 	if (_mail->get_stream(_mail, &hdr_size, &body_size) == NULL)
 		return (uoff_t)-1;
 
 	mail_cache_add(mail->trans->cache_trans, mail->data.seq,
 		       cache_fields[MAIL_CACHE_VIRTUAL_FULL_SIZE].idx,
-		       &data->size, sizeof(data->size));
-	return data->size;
+		       &data->virtual_size, sizeof(data->virtual_size));
+	return data->virtual_size;
+}
+
+uoff_t index_mail_get_physical_size(struct mail *_mail)
+{
+	struct index_mail *mail = (struct index_mail *) _mail;
+	struct index_mail_data *data = &mail->data;
+
+	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;
 }
 
 static void parse_bodystructure_part_header(struct message_part *part,
@@ -295,7 +323,6 @@
 static void index_mail_parse_body(struct index_mail *mail, int need_parts)
 {
 	struct index_mail_data *data = &mail->data;
-        enum mail_cache_record_flag cache_flags;
 	enum mail_cache_decision_type decision;
 	buffer_t *buffer;
 	const void *buf_data;
@@ -398,8 +425,10 @@
 	}
 
 	if (data->hdr_size_set && data->body_size_set) {
-		data->size = data->hdr_size.virtual_size +
+		data->virtual_size = data->hdr_size.virtual_size +
 			data->body_size.virtual_size;
+		data->physical_size = data->hdr_size.physical_size +
+			data->body_size.physical_size;
 	}
 
 	i_stream_seek(data->stream, 0);
@@ -615,7 +644,8 @@
 
 	data->rec = rec;
 	data->seq = seq;
-	data->size = (uoff_t)-1;
+	data->virtual_size = (uoff_t)-1;
+	data->physical_size = (uoff_t)-1;
 	data->received_date = data->sent_date.time = (time_t)-1;
 
 	t_push();
@@ -633,8 +663,10 @@
 		data->bodystructure = index_mail_get_cached_string(mail,
 					MAIL_CACHE_BODYSTRUCTURE);
 	}
-	if (mail->wanted_fields & MAIL_FETCH_SIZE)
-		data->size = index_mail_get_cached_virtual_size(mail);
+	if (mail->wanted_fields & MAIL_FETCH_VIRTUAL_SIZE)
+		data->virtual_size = index_mail_get_cached_virtual_size(mail);
+	if (mail->wanted_fields & MAIL_FETCH_PHYSICAL_SIZE)
+		data->physical_size = index_mail_get_cached_physical_size(mail);
 	if (mail->wanted_fields & MAIL_FETCH_DATE)
 		get_cached_sent_date(mail, &data->sent_date);
 
--- a/src/lib-storage/index/index-mail.h	Sat Aug 28 13:31:37 2004 +0300
+++ b/src/lib-storage/index/index-mail.h	Sat Aug 28 13:32:16 2004 +0300
@@ -11,6 +11,7 @@
 	MAIL_CACHE_SENT_DATE,
 	MAIL_CACHE_RECEIVED_DATE,
 	MAIL_CACHE_VIRTUAL_FULL_SIZE,
+	MAIL_CACHE_PHYSICAL_FULL_SIZE,
 
 	/* variable sized field */
 	MAIL_CACHE_BODY,
@@ -54,7 +55,7 @@
 struct index_mail_data {
 	struct mail_full_flags flags;
 	time_t date, received_date;
-	uoff_t size;
+	uoff_t virtual_size, physical_size;
 
 	struct mail_sent_date sent_date;
 	struct index_mail_line parse_line;
@@ -130,7 +131,8 @@
 const struct message_part *index_mail_get_parts(struct mail *_mail);
 time_t index_mail_get_received_date(struct mail *_mail);
 time_t index_mail_get_date(struct mail *_mail, int *timezone);
-uoff_t index_mail_get_size(struct mail *_mail);
+uoff_t index_mail_get_virtual_size(struct mail *mail);
+uoff_t index_mail_get_physical_size(struct mail *mail);
 struct istream *index_mail_init_stream(struct index_mail *mail,
 				       struct message_size *hdr_size,
 				       struct message_size *body_size);
--- a/src/lib-storage/index/index-search.c	Sat Aug 28 13:31:37 2004 +0300
+++ b/src/lib-storage/index/index-search.c	Sat Aug 28 13:32:16 2004 +0300
@@ -236,7 +236,7 @@
 	/* sizes */
 	case SEARCH_SMALLER:
 	case SEARCH_LARGER:
-		virtual_size = ctx->mail->get_size(ctx->mail);
+		virtual_size = ctx->mail->get_virtual_size(ctx->mail);
 		if (virtual_size == (uoff_t)-1)
 			return -1;
 
--- a/src/lib-storage/index/maildir/maildir-mail.c	Sat Aug 28 13:31:37 2004 +0300
+++ b/src/lib-storage/index/maildir/maildir-mail.c	Sat Aug 28 13:32:16 2004 +0300
@@ -102,21 +102,21 @@
 	return data->received_date;
 }
 
-static uoff_t maildir_mail_get_size(struct mail *_mail)
+static uoff_t maildir_mail_get_virtual_size(struct mail *_mail)
 {
-	struct index_mail *mail = (struct index_mail *) _mail;
+	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	const char *fname, *p;
 	uoff_t virtual_size;
         enum maildir_uidlist_rec_flag flags;
 
-	if (data->size != (uoff_t)-1)
-		return data->size;
+	if (data->virtual_size != (uoff_t)-1)
+		return data->virtual_size;
 
-	if ((mail->wanted_fields & MAIL_FETCH_SIZE) == 0) {
-		data->size = index_mail_get_cached_virtual_size(mail);
-		if (data->size != (uoff_t)-1)
-			return data->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;
 	}
 
 	fname = maildir_uidlist_lookup(mail->ibox->uidlist,
@@ -142,7 +142,53 @@
 		}
 	}
 
-	return index_mail_get_size(_mail);
+	return index_mail_get_virtual_size(_mail);
+}
+
+static uoff_t maildir_mail_get_physical_size(struct mail *_mail)
+{
+	struct index_mail *mail = (struct index_mail *)_mail;
+	struct index_mail_data *data = &mail->data;
+	struct stat st;
+	const char *fname, *p;
+	uoff_t size;
+	enum maildir_uidlist_rec_flag flags;
+
+	size = index_mail_get_physical_size(_mail);
+	if (size != (uoff_t)-1)
+		return size;
+
+	fname = maildir_uidlist_lookup(mail->ibox->uidlist,
+				       mail->mail.uid, &flags);
+	if (fname == NULL)
+		return (uoff_t)-1;
+
+	/* size can be included in filename */
+	p = strstr(fname, ",S=");
+	if (p != NULL) {
+		p += 3;
+		size = 0;
+		while (*p >= '0' && *p <= '9') {
+			size = size * 10 + (*p - '0');
+			p++;
+		}
+
+		if (*p != ':' && *p != ',' && *p != '\0')
+			size = (uoff_t)-1;
+	}
+
+	if (size == (uoff_t)-1) {
+		if (maildir_file_do(mail->ibox, mail->mail.uid,
+				    do_stat, &st) <= 0)
+			return (uoff_t)-1;
+		size = st.st_size;
+	}
+
+	mail_cache_add(mail->trans->cache_trans, mail->data.seq,
+		       MAIL_CACHE_PHYSICAL_FULL_SIZE, &size, sizeof(size));
+	data->physical_size = size;
+	return size;
+
 }
 
 static struct istream *maildir_mail_get_stream(struct mail *_mail,
@@ -172,7 +218,8 @@
 	index_mail_get_parts,
 	maildir_mail_get_received_date,
 	index_mail_get_date,
-	maildir_mail_get_size,
+	maildir_mail_get_virtual_size,
+	maildir_mail_get_physical_size,
 	index_mail_get_header,
 	index_mail_get_headers,
 	maildir_mail_get_stream,
--- a/src/lib-storage/index/mbox/mbox-mail.c	Sat Aug 28 13:31:37 2004 +0300
+++ b/src/lib-storage/index/mbox/mbox-mail.c	Sat Aug 28 13:32:16 2004 +0300
@@ -111,6 +111,24 @@
 	return index_mail_get_special(_mail, field);
 }
 
+static uoff_t mbox_mail_get_physical_size(struct mail *_mail)
+{
+	struct index_mail *mail = (struct index_mail *)_mail;
+	struct index_mail_data *data = &mail->data;
+	struct istream *stream;
+	uoff_t hdr_offset, body_offset, body_size;
+
+	/* our header size varies, so don't do any caching */
+	stream = mail->ibox->mbox_stream;
+	hdr_offset = istream_raw_mbox_get_header_offset(stream);
+	body_offset = istream_raw_mbox_get_body_offset(stream);
+	body_size = istream_raw_mbox_get_body_size(stream, (uoff_t)-1);
+
+	data->physical_size = (body_offset - hdr_offset) + body_size;
+	return data->physical_size;
+
+}
+
 static struct istream *mbox_mail_get_stream(struct mail *_mail,
 					    struct message_size *hdr_size,
 					    struct message_size *body_size)
@@ -147,7 +165,8 @@
 	index_mail_get_parts,
 	mbox_mail_get_received_date,
 	index_mail_get_date,
-	index_mail_get_size,
+	index_mail_get_virtual_size,
+	mbox_mail_get_physical_size,
 	index_mail_get_header,
 	index_mail_get_headers,
 	mbox_mail_get_stream,
--- a/src/lib-storage/mail-storage.h	Sat Aug 28 13:31:37 2004 +0300
+++ b/src/lib-storage/mail-storage.h	Sat Aug 28 13:32:16 2004 +0300
@@ -70,10 +70,11 @@
 
 	MAIL_FETCH_RECEIVED_DATE	= 0x00000004,
 	MAIL_FETCH_DATE			= 0x00000008,
-	MAIL_FETCH_SIZE			= 0x00000010,
+	MAIL_FETCH_VIRTUAL_SIZE		= 0x00000010,
+	MAIL_FETCH_PHYSICAL_SIZE	= 0x00000020,
 
-	MAIL_FETCH_STREAM_HEADER	= 0x00000020,
-	MAIL_FETCH_STREAM_BODY		= 0x00000040,
+	MAIL_FETCH_STREAM_HEADER	= 0x00000040,
+	MAIL_FETCH_STREAM_BODY		= 0x00000080,
 
 	/* specials: */
 	MAIL_FETCH_IMAP_BODY		= 0x00001000,
@@ -366,7 +367,10 @@
 	time_t (*get_date)(struct mail *mail, int *timezone);
 	/* Get the full virtual size of mail (IMAP RFC822.SIZE).
 	   Returns (uoff_t)-1 if error occured */
-	uoff_t (*get_size)(struct mail *mail);
+	uoff_t (*get_virtual_size)(struct mail *mail);
+	/* Get the full physical size of mail.
+	   Returns (uoff_t)-1 if error occured */
+	uoff_t (*get_physical_size)(struct mail *mail);
 
 	/* Get value for single header field */
 	const char *(*get_header)(struct mail *mail, const char *field);
--- a/src/lib-storage/proxy-mail.c	Sat Aug 28 13:31:37 2004 +0300
+++ b/src/lib-storage/proxy-mail.c	Sat Aug 28 13:32:16 2004 +0300
@@ -31,11 +31,18 @@
 	return p->mail->get_date(p->mail, timezone);
 }
 
-static uoff_t _get_size(struct mail *mail)
+static uoff_t _get_virtual_size(struct mail *mail)
 {
 	struct proxy_mail *p = (struct proxy_mail *) mail;
 
-	return p->mail->get_size(p->mail);
+	return p->mail->get_virtual_size(p->mail);
+}
+
+static uoff_t _get_physical_size(struct mail *mail)
+{
+	struct proxy_mail *p = (struct proxy_mail *) mail;
+
+	return p->mail->get_physical_size(p->mail);
 }
 
 static const char *_get_header(struct mail *mail, const char *field)
@@ -97,7 +104,8 @@
 	pm->get_parts = _get_parts;
 	pm->get_received_date = _get_received_date;
 	pm->get_date = _get_date;
-	pm->get_size = _get_size;
+	pm->get_virtual_size = _get_virtual_size;
+	pm->get_physical_size = _get_physical_size;
 	pm->get_header = _get_header;
 	pm->get_headers = _get_headers;
 	pm->get_stream = _get_stream;
--- a/src/pop3/client.c	Sat Aug 28 13:31:37 2004 +0300
+++ b/src/pop3/client.c	Sat Aug 28 13:32:16 2004 +0300
@@ -82,7 +82,7 @@
 
 		t = mailbox_transaction_begin(client->mailbox, FALSE);
 		ctx = mailbox_search_init(t, NULL, &search_arg, NULL,
-					  MAIL_FETCH_SIZE, NULL);
+					  MAIL_FETCH_VIRTUAL_SIZE, NULL);
 		if (ctx == NULL) {
 			client_send_storage_error(client);
                         mailbox_transaction_rollback(t);
@@ -93,7 +93,7 @@
 		client->deleted_size = 0;
 		failed = FALSE;
 		while ((mail = mailbox_search_next(ctx)) != NULL) {
-			uoff_t size = mail->get_size(mail);
+			uoff_t size = mail->get_virtual_size(mail);
 
 			if (size == (uoff_t)-1) {
 				failed = TRUE;
--- a/src/pop3/commands.c	Sat Aug 28 13:31:37 2004 +0300
+++ b/src/pop3/commands.c	Sat Aug 28 13:32:16 2004 +0300
@@ -186,7 +186,7 @@
 
 	t = mailbox_transaction_begin(box, FALSE);
 	ctx = mailbox_search_init(t, NULL, &search_arg, NULL,
-				  MAIL_FETCH_SIZE, NULL);
+				  MAIL_FETCH_VIRTUAL_SIZE, NULL);
 	if (ctx == NULL) {
 		mailbox_transaction_rollback(t);
 		return FALSE;