[dovecot-cvs] dovecot/src/lib-storage/index index-mail.c, 1.80, 1.81 index-mail.h, 1.33, 1.34

cras at dovecot.org cras at dovecot.org
Sun Jul 3 17:18:30 EEST 2005


Update of /var/lib/cvs/dovecot/src/lib-storage/index
In directory talvi:/tmp/cvs-serv1597/index

Modified Files:
	index-mail.c index-mail.h 
Log Message:
Added MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII to compress simple BODY and
BODYSTRUCTURE replies into a single flag + message parts. Also did other
cleanups.



Index: index-mail.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/index-mail.c,v
retrieving revision 1.80
retrieving revision 1.81
diff -u -d -r1.80 -r1.81
--- index-mail.c	3 Jul 2005 13:07:50 -0000	1.80
+++ index-mail.c	3 Jul 2005 14:18:28 -0000	1.81
@@ -14,12 +14,6 @@
 #include "index-storage.h"
 #include "index-mail.h"
 
-struct fetch_cache_map {
-        enum mail_fetch_field fetch_field;
-	enum index_cache_field cache_field;
-	enum index_mail_access_part part;
-};
-
 struct mail_cache_field global_cache_fields[MAIL_CACHE_FIELD_COUNT] = {
 	{ "flags", 0, MAIL_CACHE_FIELD_BITMASK, sizeof(uint32_t), 0 },
 	{ "date.sent", 0, MAIL_CACHE_FIELD_FIXED_SIZE,
@@ -36,23 +30,9 @@
 	{ "mime.parts", 0, MAIL_CACHE_FIELD_VARIABLE_SIZE, 0, 0 }
 };
 
-static const struct fetch_cache_map fetch_cache_map[] = {
-	{ MAIL_FETCH_DATE, MAIL_CACHE_SENT_DATE, PARSE_HDR },
-
-	{ MAIL_FETCH_MESSAGE_PARTS,
-	  MAIL_CACHE_MESSAGEPART, PARSE_HDR | PARSE_BODY },
-	{ MAIL_FETCH_VIRTUAL_SIZE,
-	  MAIL_CACHE_VIRTUAL_FULL_SIZE, READ_HDR | READ_BODY },
-
-	{ MAIL_FETCH_IMAP_BODYSTRUCTURE,
-	  MAIL_CACHE_IMAP_BODYSTRUCTURE, PARSE_HDR | PARSE_BODY },
-
-	{ 0, 0, 0 }
-};
-
 static void index_mail_parse_body(struct index_mail *mail, int need_parts);
 
-static struct message_part *get_cached_parts(struct index_mail *mail)
+static int get_cached_parts(struct index_mail *mail)
 {
 	struct mail_cache_field *cache_fields = mail->ibox->cache_fields;
 	struct message_part *part;
@@ -65,7 +45,7 @@
 			mail->data.seq,
 			cache_fields[MAIL_CACHE_MESSAGEPART].idx) <= 0) {
 		t_pop();
-		return NULL;
+		return FALSE;
 	}
 
 	part = message_part_deserialize(mail->data_pool,
@@ -75,7 +55,7 @@
 	if (part == NULL) {
 		mail_cache_set_corrupted(mail->ibox->cache,
 			"Corrupted cached message_part data (%s)", error);
-		return NULL;
+		return FALSE;
 	}
 
 	/* we know the NULs now, update them */
@@ -87,7 +67,8 @@
 		mail->mail.mail.has_no_nuls = TRUE;
 	}
 
-	return part;
+	mail->data.parts = part;
+	return TRUE;
 }
 
 const char *index_mail_get_cached_string(struct index_mail *mail,
@@ -223,8 +204,7 @@
 	if (data->parts != NULL)
 		return data->parts;
 
-	data->parts = get_cached_parts(mail);
-	if (data->parts != NULL)
+	if (get_cached_parts(mail))
 		return data->parts;
 
 	if (data->parser_ctx == NULL) {
@@ -294,7 +274,7 @@
 	struct index_mail_data *data = &mail->data;
 
 	if (data->parts == NULL)
-		data->parts = get_cached_parts(mail);
+		get_cached_parts(mail);
 
 	if (data->parts != NULL) {
 		data->hdr_size_set = TRUE;
@@ -393,10 +373,21 @@
 	data->parts = message_parser_deinit(data->parser_ctx);
         data->parser_ctx = NULL;
 
+	if (data->parsed_bodystructure &&
+	    imap_bodystructure_is_plain_7bit(data->parts)) {
+		data->cache_flags |= MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII;
+		/* we need message_parts cached to be able to
+		   actually use it in BODY/BODYSTRUCTURE reply */
+		need_parts = TRUE;
+	}
+
 	data->body_size = data->parts->body_size;
 	data->body_size_set = TRUE;
 
-	cache_flags = 0;
+	cache_flags = data->cache_flags & ~(MAIL_CACHE_FLAG_BINARY_HEADER |
+					    MAIL_CACHE_FLAG_BINARY_BODY |
+					    MAIL_CACHE_FLAG_HAS_NULS |
+					    MAIL_CACHE_FLAG_HAS_NO_NULS);
 	if (!mail->mail.mail.has_nuls && !mail->mail.mail.has_no_nuls) {
 		/* we know the NULs now, update them */
 		if ((data->parts->flags & MESSAGE_PART_FLAG_HAS_NULS) != 0) {
@@ -418,7 +409,8 @@
 	if (data->body_size.virtual_size == data->body_size.physical_size)
 		cache_flags |= MAIL_CACHE_FLAG_BINARY_BODY;
 
-	if ((cache_flags & ~data->cache_flags) != 0) {
+	if (cache_flags != data->cache_flags) {
+		data->cache_flags = cache_flags;
 		mail_cache_add(mail->trans->cache_trans, mail->data.seq,
 			       cache_fields[MAIL_CACHE_FLAGS].idx,
 			       &cache_flags, sizeof(cache_flags));
@@ -443,6 +435,7 @@
 			       cache_fields[MAIL_CACHE_MESSAGEPART].idx,
 			       buf_data, buf_size);
 		t_pop();
+		data->messageparts_saved_to_cache = TRUE;
 	}
 }
 
@@ -504,6 +497,7 @@
 	enum mail_cache_decision_type dec;
 	string_t *str;
 	int bodystructure_cached = FALSE;
+	int plain_bodystructure = FALSE;
 
 	if (!data->parsed_bodystructure) {
 		if (data->save_bodystructure_header ||
@@ -529,6 +523,15 @@
 		}
 	}
 
+	if ((data->cache_flags & MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII) != 0) {
+		if (data->messageparts_saved_to_cache ||
+		    mail_cache_field_exists(mail->trans->cache_view, data->seq,
+				cache_fields[MAIL_CACHE_MESSAGEPART].idx) > 0) {
+			/* cached it as flag + message_parts */
+			plain_bodystructure = TRUE;
+		}
+	}
+
 	dec = mail_cache_field_get_decision(mail->ibox->cache,
 			cache_fields[MAIL_CACHE_IMAP_BODYSTRUCTURE].idx);
 	if (field == MAIL_CACHE_IMAP_BODYSTRUCTURE ||
@@ -539,8 +542,9 @@
 		imap_bodystructure_write(data->parts, str, TRUE);
 		data->bodystructure = str_c(str);
 
-		if (dec !=
-		    (MAIL_CACHE_DECISION_NO | MAIL_CACHE_DECISION_FORCED)) {
+		if (!plain_bodystructure &&
+		    dec != (MAIL_CACHE_DECISION_NO |
+			    MAIL_CACHE_DECISION_FORCED)) {
 			mail_cache_add(mail->trans->cache_trans, data->seq,
 				cache_fields[MAIL_CACHE_IMAP_BODYSTRUCTURE].idx,
 				str_c(str), str_len(str)+1);
@@ -558,8 +562,9 @@
 		imap_bodystructure_write(data->parts, str, FALSE);
 		data->body = str_c(str);
 
-		if (!bodystructure_cached && dec !=
-		    (MAIL_CACHE_DECISION_NO | MAIL_CACHE_DECISION_FORCED)) {
+		if (!bodystructure_cached && !plain_bodystructure &&
+		    dec != (MAIL_CACHE_DECISION_NO |
+			    MAIL_CACHE_DECISION_FORCED)) {
 			mail_cache_add(mail->trans->cache_trans, data->seq,
 				       cache_fields[MAIL_CACHE_IMAP_BODY].idx,
 				       str_c(str), str_len(str)+1);
@@ -567,6 +572,17 @@
 	}
 }
 
+static void
+index_mail_get_plain_bodystructure(struct index_mail *mail, string_t *str,
+				   int extended)
+{
+	str_printfa(str, IMAP_BODY_PLAIN_7BIT_ASCII" %"PRIuUOFF_T" %u",
+		    mail->data.parts->body_size.virtual_size,
+		    mail->data.parts->body_size.lines);
+	if (extended)
+		str_append(str, " NIL NIL NIL");
+}
+
 const char *index_mail_get_special(struct mail *_mail,
 				   enum mail_fetch_field field)
 {
@@ -585,12 +601,20 @@
 		if (data->body != NULL)
 			return data->body;
 
-		/* 1) get BODY if it exists
-		   2) get it using BODYSTRUCTURE if it exists
-		   3) parse body structure, and save BODY/BODYSTRUCTURE
+		/* 1) use plain-7bit-ascii flag if it exists
+		   2) get BODY if it exists
+		   3) get it using BODYSTRUCTURE if it exists
+		   4) parse body structure, and save BODY/BODYSTRUCTURE
 		      depending on what we want cached */
 
 		str = str_new(mail->data_pool, 128);
+		if ((mail->data.cache_flags &
+		     MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII) != 0 &&
+		    get_cached_parts(mail)) {
+			index_mail_get_plain_bodystructure(mail, str, FALSE);
+			return str_c(str);
+		}
+
 		if (mail_cache_lookup_field(mail->trans->cache_view, str,
 				mail->data.seq, body_cache_field) > 0) {
 			data->body = str_c(str);
@@ -628,6 +652,13 @@
 			return data->bodystructure;
 
 		str = str_new(mail->data_pool, 128);
+		if ((mail->data.cache_flags &
+		     MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII) != 0 &&
+		    get_cached_parts(mail)) {
+			index_mail_get_plain_bodystructure(mail, str, TRUE);
+			return str_c(str);
+		}
+
 		if (mail_cache_lookup_field(mail->trans->cache_view, str,
 					    mail->data.seq,
 					    bodystructure_cache_field) > 0) {
@@ -710,8 +741,8 @@
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	struct mail_cache_field *cache_fields = mail->ibox->cache_fields;
+        struct mail_cache_view *cache_view = mail->trans->cache_view;
 	const struct mail_index_record *rec;
-	unsigned int i;
 
 	if (mail_index_lookup(mail->trans->trans_view, seq, &rec) < 0) {
 		mail_storage_set_index_error(mail->ibox);
@@ -744,20 +775,22 @@
 
 	/* see if wanted_fields can tell us if we need to read/parse
 	   header/body */
-	for (i = 0; fetch_cache_map[i].part != 0; i++) {
-		const struct fetch_cache_map *map = &fetch_cache_map[i];
+	if ((mail->wanted_fields & MAIL_FETCH_MESSAGE_PARTS) != 0) {
+		unsigned int cache_field =
+			cache_fields[MAIL_FETCH_MESSAGE_PARTS].idx;
 
-		if ((mail->wanted_fields & map->fetch_field) != 0) {
-			unsigned int cache_field =
-				cache_fields[map->cache_field].idx;
+		if (mail_cache_field_exists(cache_view, seq, cache_field) == 0)
+			data->access_part |= PARSE_HDR | PARSE_BODY;
+	}
 
-			if (mail_cache_field_exists(mail->trans->cache_view,
-						    seq, cache_field) == 0)
-				data->access_part |= map->part;
-		}
+	if ((mail->wanted_fields & MAIL_FETCH_VIRTUAL_SIZE) != 0) {
+		unsigned int cache_field =
+			cache_fields[MAIL_FETCH_VIRTUAL_SIZE].idx;
+
+		if (mail_cache_field_exists(cache_view, seq, cache_field) == 0)
+			data->access_part |= READ_HDR | READ_BODY;
 	}
 
-	/* handle the special cases */
 	if ((mail->wanted_fields & MAIL_FETCH_IMAP_ENVELOPE) != 0 &&
 	    (data->access_part & PARSE_HDR) == 0) {
 		/* don't waste time doing full checks for all required
@@ -769,37 +802,55 @@
 		unsigned int cache_field2 =
 			cache_fields[MAIL_CACHE_IMAP_ENVELOPE].idx;
 
-		if (mail_cache_field_exists(mail->trans->cache_view,
-					    seq, cache_field1) == 0 &&
-		    mail_cache_field_exists(mail->trans->cache_view,
-					    seq, cache_field2) == 0)
+		if (mail_cache_field_exists(cache_view, seq,
+					    cache_field1) == 0 &&
+		    mail_cache_field_exists(cache_view, seq,
+					    cache_field2) == 0)
 			data->access_part |= PARSE_HDR;
 	}
 
 	if ((mail->wanted_fields & MAIL_FETCH_IMAP_BODY) != 0 &&
-	    ((data->access_part & PARSE_HDR) == 0 ||
-	     (data->access_part & PARSE_BODY) == 0)) {
+	    (data->cache_flags & MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII) == 0) {
 		/* we need either imap.body or imap.bodystructure */
 		unsigned int cache_field1 =
 			cache_fields[MAIL_CACHE_IMAP_BODY].idx;
 		unsigned int cache_field2 =
 			cache_fields[MAIL_CACHE_IMAP_BODYSTRUCTURE].idx;
 
-		if (mail_cache_field_exists(mail->trans->cache_view,
+		if (mail_cache_field_exists(cache_view,
 					    seq, cache_field1) == 0 &&
-		    mail_cache_field_exists(mail->trans->cache_view,
+		    mail_cache_field_exists(cache_view,
 					    seq, cache_field2) == 0)
 			data->access_part |= PARSE_HDR | PARSE_BODY;
+		else {
+			data->save_bodystructure_header = TRUE;
+			data->save_bodystructure_body = TRUE;
+		}
 	}
 
-	if ((mail->wanted_fields & (MAIL_FETCH_IMAP_BODY |
-				    MAIL_FETCH_IMAP_BODYSTRUCTURE)) != 0) {
-		data->save_bodystructure_header = TRUE;
-		data->save_bodystructure_body = TRUE;
+	if ((mail->wanted_fields & MAIL_FETCH_IMAP_BODYSTRUCTURE) != 0 &&
+	    (data->cache_flags & MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII) == 0) {
+		unsigned int cache_field =
+			cache_fields[MAIL_CACHE_IMAP_BODYSTRUCTURE].idx;
+
+		if (mail_cache_field_exists(cache_view, seq, cache_field) == 0)
+			data->access_part |= PARSE_HDR | PARSE_BODY;
+		else {
+			data->save_bodystructure_header = TRUE;
+			data->save_bodystructure_body = TRUE;
+		}
 	}
 
-	if ((mail->wanted_fields & MAIL_FETCH_DATE) != 0)
-		data->save_sent_date = TRUE;
+	if ((mail->wanted_fields & MAIL_FETCH_DATE) != 0) {
+		unsigned int cache_field =
+			cache_fields[MAIL_CACHE_SENT_DATE].idx;
+
+		if (mail_cache_field_exists(cache_view, seq,
+					    cache_field) == 0) {
+			data->access_part |= PARSE_HDR;
+			data->save_sent_date = TRUE;
+		}
+	}
 
 	if ((mail->wanted_fields & MAIL_FETCH_IMAP_ENVELOPE) != 0)
 		data->save_envelope = TRUE;

Index: index-mail.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/index-mail.h,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- index-mail.h	3 Jul 2005 13:07:50 -0000	1.33
+++ index-mail.h	3 Jul 2005 14:18:28 -0000	1.34
@@ -23,6 +23,9 @@
 };
 extern struct mail_cache_field global_cache_fields[MAIL_CACHE_FIELD_COUNT];
 
+#define IMAP_BODY_PLAIN_7BIT_ASCII \
+	"\"text\" \"plain\" (\"charset\" \"us-ascii\") NIL NIL \"7bit\""
+
 enum mail_cache_record_flag {
 	/* If binary flags are set, it's not checked whether mail is
 	   missing CRs. So this flag may be set as an optimization for
@@ -34,7 +37,11 @@
 	/* Mail header or body is known to contain NUL characters. */
 	MAIL_CACHE_FLAG_HAS_NULS		= 0x0004,
 	/* Mail header or body is known to not contain NUL characters. */
-	MAIL_CACHE_FLAG_HAS_NO_NULS		= 0x0008
+	MAIL_CACHE_FLAG_HAS_NO_NULS		= 0x0008,
+
+	/* BODY is IMAP_BODY_PLAIN_7BIT_ASCII and rest of BODYSTRUCTURE
+	   fields are NIL */
+	MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII	= 0x0010
 };
 
 enum index_mail_access_part {
@@ -89,6 +96,7 @@
 	unsigned int parsed_bodystructure:1;
 	unsigned int hdr_size_set:1;
 	unsigned int body_size_set:1;
+	unsigned int messageparts_saved_to_cache:1;
 };
 
 struct index_mail {



More information about the dovecot-cvs mailing list