[dovecot-cvs] dovecot/src/lib-storage/index index-mail-headers.c, 1.31, 1.32 index-mail.c, 1.46, 1.47 index-mail.h, 1.19, 1.20

cras at dovecot.org cras at dovecot.org
Fri Jul 23 19:28:42 EEST 2004


Update of /home/cvs/dovecot/src/lib-storage/index
In directory talvi:/tmp/cvs-serv10631/lib-storage/index

Modified Files:
	index-mail-headers.c index-mail.c index-mail.h 
Log Message:
get_index() wasn't working with caching disabled



Index: index-mail-headers.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-mail-headers.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -d -r1.31 -r1.32
--- index-mail-headers.c	22 Jul 2004 13:46:59 -0000	1.31
+++ index-mail-headers.c	23 Jul 2004 16:28:40 -0000	1.32
@@ -61,6 +61,9 @@
 		       match_idx < match_size) {
 			if (match[match_idx] == mail->header_match_value) {
 				/* this header doesn't exist. remember that. */
+				buffer_write(mail->header_offsets,
+					     match_idx * sizeof(null),
+					     &null, sizeof(null));
 				mail_cache_add(mail->trans->cache_trans,
 					       mail->data.seq, match_idx,
 					       NULL, 0);
@@ -120,6 +123,7 @@
 		(struct index_header_lookup_ctx *)_headers;
 	size_t i;
 
+	mail->header_seq = mail->data.seq;
 	if (mail->header_data == NULL) {
 		mail->header_data =
 			buffer_create_dynamic(default_pool, 4096, (size_t)-1);
@@ -127,16 +131,20 @@
 			buffer_create_dynamic(default_pool, 256, (size_t)-1);
 		mail->header_match =
 			buffer_create_dynamic(default_pool, 64, (size_t)-1);
+		mail->header_offsets =
+			buffer_create_dynamic(default_pool, 256, (size_t)-1);
 	} else {
 		buffer_set_used_size(mail->header_data, 0);
 		buffer_set_used_size(mail->header_lines, 0);
+		buffer_set_used_size(mail->header_offsets, 0);
 	}
 
-	if (++mail->header_match_value == 0) {
+        mail->header_match_value += 2;
+	if (mail->header_match_value == 0) {
 		/* wrapped, we'll have to clear the buffer */
 		memset(buffer_get_modifyable_data(mail->header_match, NULL), 0,
 		       buffer_get_size(mail->header_match));
-		mail->header_match_value++;
+		mail->header_match_value = 2;
 	}
 
 	if (headers != NULL) {
@@ -175,7 +183,7 @@
 	enum mail_cache_decision_type decision;
 	const char *cache_field_name;
 	unsigned int field_idx;
-	int timezone;
+	int timezone, first_hdr = FALSE;
 
         data->parse_line_num++;
 
@@ -257,15 +265,20 @@
 	}
 
 	if (!data->parse_line.cache) {
-		const uint8_t *match;
+		uint8_t *match;
 		size_t size;
 
-		match = buffer_get_data(mail->header_match, &size);
+		match = buffer_get_modifyable_data(mail->header_match, &size);
 		if (field_idx >= size ||
-		    match[field_idx] != mail->header_match_value) {
+		    (match[field_idx] & ~1) != mail->header_match_value) {
 			/* we don't need to do anything with this header */
 			return TRUE;
 		}
+		if (match[field_idx] == mail->header_match_value) {
+			/* first header */
+			first_hdr = TRUE;
+			match[field_idx]++;
+		}
 	}
 
 	if (!hdr->continued) {
@@ -273,6 +286,14 @@
 		data->parse_line.line_num = data->parse_line_num;
 		str_append(mail->header_data, hdr->name);
 		str_append(mail->header_data, ": ");
+
+		if (first_hdr) {
+			/* save the offset to first header */
+			uint32_t pos = str_len(mail->header_data);
+			buffer_write(mail->header_offsets,
+				     field_idx * sizeof(pos),
+				     &pos, sizeof(pos));
+		}
 	}
 	str_append_n(mail->header_data, hdr->value, hdr->value_len);
 	if (!hdr->no_newline)
@@ -377,6 +398,57 @@
 	return field_idx;
 }
 
+static size_t get_header_size(buffer_t *buffer, size_t pos)
+{
+	const unsigned char *data;
+	size_t i, size;
+
+	data = buffer_get_data(buffer, &size);
+	i_assert(pos <= size);
+
+	for (i = pos; i < size; i++) {
+		if (data[i] == '\n') {
+			if (i+1 == size ||
+			    (data[i+1] != ' ' && data[i+1] != '\t'))
+				return i - pos;
+		}
+	}
+	return size - pos;
+}
+
+static int index_mail_header_is_parsed(struct index_mail *mail,
+				       unsigned int field_idx)
+{
+	const uint8_t *match;
+	size_t size;
+
+	match = buffer_get_data(mail->header_match, &size);
+	if (field_idx >= size)
+		return -1;
+
+	if (match[field_idx] == mail->header_match_value)
+		return 0;
+	else if (match[field_idx] == mail->header_match_value + 1)
+		return 1;
+	return -1;
+}
+
+static const char *
+index_mail_get_parsed_header(struct index_mail *mail, unsigned int field_idx)
+{
+	const unsigned char *data;
+	const uint32_t *offsets;
+	size_t size;
+
+	offsets = buffer_get_data(mail->header_offsets, &size);
+	i_assert(field_idx * sizeof(*offsets) >= size &&
+		 offsets[field_idx] != 0);
+
+	data = buffer_get_data(mail->header_data, &size);
+        size = get_header_size(mail->header_data, offsets[field_idx]);
+	return p_strndup(mail->pool, data + offsets[field_idx], size);
+}
+
 const char *index_mail_get_header(struct mail *_mail, const char *field)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
@@ -385,7 +457,7 @@
 	const unsigned char *data;
 	unsigned int field_idx;
 	string_t *dest;
-	size_t i, len, value_pos;
+	size_t i, len;
 	int ret;
 
 	field_idx = get_header_field_idx(mail->ibox, field);
@@ -393,21 +465,30 @@
 	dest = str_new(mail->pool, 128);
 	if (mail_cache_lookup_headers(mail->trans->cache_view, dest,
 				      mail->data.seq, &field_idx, 1) <= 0) {
-		/* not in cache / error */
+		/* not in cache / error - first see if it's already parsed */
+		p_free(mail->pool, dest);
+		if (mail->header_seq == mail->data.seq) {
+			ret = index_mail_header_is_parsed(mail, field_idx);
+			if (ret != -1) {
+				return ret == 0 ? NULL :
+					index_mail_get_parsed_header(mail,
+								     field_idx);
+			}
+		}
+
+		/* parse */
 		headers[0] = field; headers[1] = NULL;
 		headers_ctx = mailbox_header_lookup_init(&mail->ibox->box,
 							 headers);
 		ret = index_mail_parse_headers(mail, headers_ctx);
 		mailbox_header_lookup_deinit(headers_ctx);
-
 		if (ret < 0)
 			return NULL;
 
-		ret = mail_cache_lookup_headers(mail->trans->cache_view, dest,
-						mail->data.seq, &field_idx, 1);
-		i_assert(ret != 0);
-		if (ret < 0)
-			return NULL;
+		ret = index_mail_header_is_parsed(mail, field_idx);
+		i_assert(ret != -1);
+		return ret == 0 ? NULL :
+			index_mail_get_parsed_header(mail, field_idx);
 	}
 
 	/* cached. skip "header name: " in dest. */
@@ -419,20 +500,11 @@
 			break;
 		}
 	}
-	value_pos = i;
 
 	/* return only the first field in case there's multiple. */
-	for (; i < len; i++) {
-		if (data[i] == '\n') {
-			if (i+1 == len ||
-			    (data[i+1] != ' ' && data[i+1] != '\t')) {
-				buffer_set_used_size(dest, i);
-				break;
-			}
-		}
-	}
-
-	return str_c(dest) + value_pos;
+        len = get_header_size(dest, i);
+	buffer_set_used_size(dest, i + len);
+	return str_c(dest) + i;
 }
 
 static void header_cache_callback(struct message_header_line *hdr,

Index: index-mail.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-mail.c,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -d -r1.46 -r1.47
--- index-mail.c	20 Jul 2004 16:50:56 -0000	1.46
+++ index-mail.c	23 Jul 2004 16:28:40 -0000	1.47
@@ -671,6 +671,8 @@
 		buffer_free(mail->header_lines);
 	if (mail->header_match != NULL)
 		buffer_free(mail->header_match);
+	if (mail->header_offsets != NULL)
+		buffer_free(mail->header_offsets);
 
 	pool_unref(mail->pool);
 	memset(mail, 0, sizeof(*mail));

Index: index-mail.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-mail.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- index-mail.h	18 Jul 2004 17:34:32 -0000	1.19
+++ index-mail.h	23 Jul 2004 16:28:40 -0000	1.20
@@ -96,9 +96,11 @@
 	struct index_header_lookup_ctx *wanted_headers;
 
 	/* per-mail variables, here for performance reasons: */
+	uint32_t header_seq;
 	string_t *header_data;
 	buffer_t *header_lines;
 	buffer_t *header_match;
+	buffer_t *header_offsets;
 	uint8_t header_match_value;
 };
 



More information about the dovecot-cvs mailing list