dovecot: Don't cache all headers just because they're listed in ...

dovecot at dovecot.org dovecot at dovecot.org
Thu Nov 22 07:56:43 EET 2007


details:   http://hg.dovecot.org/dovecot/rev/efec8836586a
changeset: 6840:efec8836586a
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Nov 22 07:46:25 2007 +0200
description:
Don't cache all headers just because they're listed in cache file. First
check if we actually want to cache them.

diffstat:

2 files changed, 48 insertions(+), 53 deletions(-)
src/lib-storage/index/index-mail-headers.c |   96 ++++++++++++----------------
src/lib-storage/index/index-mail.h         |    5 +

diffs (184 lines):

diff -r af74d2e6f3c5 -r efec8836586a src/lib-storage/index/index-mail-headers.c
--- a/src/lib-storage/index/index-mail-headers.c	Thu Nov 22 06:32:59 2007 +0200
+++ b/src/lib-storage/index/index-mail-headers.c	Thu Nov 22 07:46:25 2007 +0200
@@ -70,16 +70,13 @@ static void index_mail_parse_header_fini
 		   until lines[i] weren't found */
 		while (match_idx < lines[i].field_idx &&
 		       match_idx < match_count) {
-			/* if match[] doesn't have header_match_value,
-			   it belongs to some older header parsing and we
-			   just want to ignore it. */
-			i_assert(match[match_idx] !=
-				 mail->header_match_value + 1);
-			if (match[match_idx] == mail->header_match_value &&
-			    mail_cache_field_exists(mail->trans->cache_view,
-						    mail->data.seq,
-						    match_idx) == 0) {
+			if (HEADER_MATCH_USABLE(mail, match[match_idx]) &&
+			    mail_cache_field_can_add(mail->trans->cache_trans,
+						     mail->data.seq,
+						     match_idx)) {
 				/* this header doesn't exist. remember that. */
+				i_assert((match[match_idx] &
+					  HEADER_MATCH_FLAG_FOUND) == 0);
 				index_mail_cache_add_idx(mail, match_idx,
 							 NULL, 0);
 			}
@@ -93,7 +90,9 @@ static void index_mail_parse_header_fini
 			match_idx++;
 		}
 
-		if (!lines[i].cache) {
+		if (!mail_cache_field_can_add(mail->trans->cache_trans,
+					      mail->data.seq,
+					      lines[i].field_idx)) {
 			/* header is already cached */
 			j = i + 1;
 			continue;
@@ -135,10 +134,13 @@ static void index_mail_parse_header_fini
 	}
 
 	for (; match_idx < match_count; match_idx++) {
-		if (match[match_idx] == mail->header_match_value &&
-		    mail_cache_field_exists(mail->trans->cache_view,
-					    mail->data.seq, match_idx) == 0) {
+		if (HEADER_MATCH_USABLE(mail, match[match_idx]) &&
+		    mail_cache_field_can_add(mail->trans->cache_trans,
+					     mail->data.seq,
+					     match_idx)) {
 			/* this header doesn't exist. remember that. */
+			i_assert((match[match_idx] &
+				  HEADER_MATCH_FLAG_FOUND) == 0);
 			index_mail_cache_add_idx(mail, match_idx, NULL, 0);
 		}
 	}
@@ -180,17 +182,20 @@ void index_mail_parse_header_init(struct
 		i_array_init(&mail->header_lines, 32);
 		i_array_init(&mail->header_match, 32);
 		i_array_init(&mail->header_match_lines, 32);
+		mail->header_match_value = HEADER_MATCH_SKIP_COUNT;
 	} else {
 		buffer_set_used_size(mail->header_data, 0);
 		array_clear(&mail->header_lines);
 		array_clear(&mail->header_match_lines);
-	}
-
-        mail->header_match_value += 2;
-	if (mail->header_match_value == 0) {
-		/* wrapped, we'll have to clear the buffer */
-		array_clear(&mail->header_match);
-		mail->header_match_value = 2;
+
+		mail->header_match_value += HEADER_MATCH_SKIP_COUNT;
+		i_assert((mail->header_match_value &
+			  (HEADER_MATCH_SKIP_COUNT-1)) == 0);
+		if (mail->header_match_value == 0) {
+			/* wrapped, we'll have to clear the buffer */
+			array_clear(&mail->header_match);
+			mail->header_match_value = HEADER_MATCH_SKIP_COUNT;
+		}
 	}
 
 	if (headers != NULL) {
@@ -222,11 +227,14 @@ void index_mail_parse_header_init(struct
 		mail_cache_register_get_list(mail->ibox->cache,
 					     pool_datastack_create(), &count);
 	for (i = 0; i < count; i++) {
-		if (strncasecmp(all_cache_fields[i].name, "hdr.", 4) == 0) {
-			array_idx_set(&mail->header_match,
-				      all_cache_fields[i].idx,
-				      &mail->header_match_value);
-		}
+		if (strncasecmp(all_cache_fields[i].name, "hdr.", 4) != 0)
+			continue;
+		if (!mail_cache_field_want_add(mail->trans->cache_trans,
+					       mail->data.seq, i))
+			continue;
+
+		array_idx_set(&mail->header_match, all_cache_fields[i].idx,
+			      &mail->header_match_value);
 	}
 	t_pop();
 }
@@ -288,34 +296,23 @@ void index_mail_parse_header(struct mess
 		t_pop();
 	}
 	field_idx = data->parse_line.field_idx;
-
-	if (field_idx == (unsigned int)-1) {
-		/* we don't want this field */
+	match = array_get_modifiable(&mail->header_match, &count);
+	if (field_idx >= count ||
+	    !HEADER_MATCH_USABLE(mail, match[field_idx])) {
+		/* we don't want this header. */
 		return;
 	}
 
 	if (!hdr->continued) {
-		data->parse_line.cache =
-			mail_cache_field_want_add(mail->trans->cache_trans,
-						  data->seq, field_idx);
-	}
-
-	match = array_get_modifiable(&mail->header_match, &count);
-	if (field_idx < count && match[field_idx] == mail->header_match_value) {
-		/* first header */
-		match[field_idx]++;
-	} else if (!data->parse_line.cache &&
-		   (field_idx >= count ||
-		    (match[field_idx] & ~1) != mail->header_match_value)) {
-		/* we don't need to do anything with this header */
-		return;
-	}
-
-	if (!hdr->continued) {
+		/* beginning of a line. add the header name. */
 		data->parse_line.start_pos = str_len(mail->header_data);
 		data->parse_line.line_num = data->parse_line_num;
 		str_append(mail->header_data, hdr->name);
 		str_append_n(mail->header_data, hdr->middle, hdr->middle_len);
+
+		/* remember that we saw this header so we don't add it to
+		   cache as nonexisting. */
+		match[field_idx] |= HEADER_MATCH_FLAG_FOUND;
 	}
 	str_append_n(mail->header_data, hdr->value, hdr->value_len);
 	if (!hdr->no_newline)
@@ -488,13 +485,8 @@ static int index_mail_header_is_parsed(s
 	unsigned int count;
 
 	match = array_get(&mail->header_match, &count);
-	if (field_idx >= count)
-		return -1;
-
-	if (match[field_idx] == mail->header_match_value)
-		return 0;
-	else if (match[field_idx] == mail->header_match_value + 1)
-		return 1;
+	if (field_idx < count && HEADER_MATCH_USABLE(mail, match[field_idx]))
+		return (match[field_idx] & HEADER_MATCH_FLAG_FOUND) != 0;
 	return -1;
 }
 
diff -r af74d2e6f3c5 -r efec8836586a src/lib-storage/index/index-mail.h
--- a/src/lib-storage/index/index-mail.h	Thu Nov 22 06:32:59 2007 +0200
+++ b/src/lib-storage/index/index-mail.h	Thu Nov 22 07:46:25 2007 +0200
@@ -62,7 +62,6 @@ struct index_mail_line {
 	unsigned int field_idx;
 	uint32_t start_pos, end_pos;
 	uint32_t line_num;
-	unsigned int cache:1;
 };
 
 struct message_header_line;
@@ -120,6 +119,10 @@ struct index_mail {
 	uint32_t header_seq;
 	string_t *header_data;
 	ARRAY_DEFINE(header_lines, struct index_mail_line);
+#define HEADER_MATCH_FLAG_FOUND 1
+#define HEADER_MATCH_SKIP_COUNT 2
+#define HEADER_MATCH_USABLE(mail, num) \
+	((num & ~1) == (mail)->header_match_value)
 	ARRAY_DEFINE(header_match, uint8_t);
 	ARRAY_DEFINE(header_match_lines, unsigned int);
 	uint8_t header_match_value;


More information about the dovecot-cvs mailing list