[dovecot-cvs] dovecot/src/lib-storage/index index-mail-headers.c,1.2,1.3 index-mail.c,1.18,1.19 index-mail.h,1.8,1.9

cras at procontrol.fi cras at procontrol.fi
Thu Aug 21 04:04:13 EEST 2003


Update of /home/cvs/dovecot/src/lib-storage/index
In directory danu:/tmp/cvs-serv9890/lib-storage/index

Modified Files:
	index-mail-headers.c index-mail.c index-mail.h 
Log Message:
Message parsing can now be done in two parts - header and body. We're now
more eager at parsing MIME structure for message. It's done whenever body
has to be fully read (eg. rfc822.size).



Index: index-mail-headers.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-mail-headers.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- index-mail-headers.c	20 Aug 2003 01:41:30 -0000	1.2
+++ index-mail-headers.c	21 Aug 2003 00:04:11 -0000	1.3
@@ -420,7 +420,7 @@
 	return TRUE;
 }
 
-int index_mail_parse_headers(struct index_mail *mail, int get_parts)
+int index_mail_parse_headers(struct index_mail *mail)
 {
 	struct mail_cache *cache = mail->ibox->index->cache;
 	struct index_mail_data *data = &mail->data;
@@ -491,21 +491,16 @@
 	data->bodystructure_header_parse = data->bodystructure_header_want;
 	index_mail_parse_header_init(mail, NULL);
 
-	if ((mail->wanted_fields & MAIL_FETCH_MESSAGE_PARTS) != 0)
-		get_parts = TRUE;
-	if (data->parts != NULL)
-		get_parts = FALSE;
-
-	if (!data->bodystructure_header_want && !get_parts) {
+	if (data->parts != NULL || data->parser_ctx != NULL) {
 		message_parse_header(data->parts, data->stream, &data->hdr_size,
 				     index_mail_parse_header, mail);
-	} else if (data->parts == NULL) {
-		data->parts = message_parse(mail->pool, data->stream,
-					    index_mail_parse_header, mail);
 	} else {
-		message_parse_from_parts(data->parts, data->stream,
-					 index_mail_parse_header, mail);
+		data->parser_ctx =
+			message_parser_init(mail->pool, data->stream);
+		message_parser_parse_header(data->parser_ctx, &data->hdr_size,
+					    index_mail_parse_header, mail);
 	}
+	data->hdr_size_set = TRUE;
 
 	if (data->bodystructure_header_want) {
 		data->bodystructure_header_want = FALSE;
@@ -513,19 +508,7 @@
 		data->bodystructure_header_parsed = TRUE;
 	}
 
-	if (get_parts) {
-		/* we know the NULs now, update them */
-		if ((data->parts->flags & MESSAGE_PART_FLAG_HAS_NULS) != 0) {
-			mail->mail.has_nuls = TRUE;
-			mail->mail.has_no_nuls = FALSE;
-		} else {
-			mail->mail.has_nuls = FALSE;
-			mail->mail.has_no_nuls = TRUE;
-		}
-	}
-
 	data->parse_header = FALSE;
-	data->hdr_size_set = TRUE;
 	data->header_fully_parsed = TRUE;
 
 	return TRUE;
@@ -554,7 +537,8 @@
 		}
 
 		if (idx < 0) {
-			index_mail_parse_headers(mail, FALSE);
+			if (!index_mail_parse_headers(mail))
+				return NULL;
 
 			/* might have been moved in memory, get it again */
 			hdr = cached_header_find(mail, field, NULL);
@@ -606,8 +590,10 @@
 				all_saved = FALSE;
 		}
 
-		if (!all_saved)
-			index_mail_parse_headers(mail, FALSE);
+		if (!all_saved) {
+			if (!index_mail_parse_headers(mail))
+				return NULL;
+		}
 	}
 
 	return i_stream_create_from_data(mail->pool,

Index: index-mail.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-mail.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- index-mail.c	20 Aug 2003 01:41:30 -0000	1.18
+++ index-mail.c	21 Aug 2003 00:04:11 -0000	1.19
@@ -14,7 +14,7 @@
 #include "index-expunge.h"
 #include "index-mail.h"
 
-#include <ctype.h>
+static int index_mail_parse_body(struct index_mail *mail);
 
 static struct message_part *get_cached_parts(struct index_mail *mail)
 {
@@ -242,7 +242,11 @@
 			return data->parts;
 	}
 
-	if (!index_mail_parse_headers(mail, TRUE))
+	if (data->parser_ctx == NULL) {
+		if (!index_mail_parse_headers(mail))
+			return NULL;
+	}
+	if (!index_mail_parse_body(mail))
 		return NULL;
 
         cache_parts(mail);
@@ -314,17 +318,20 @@
 {
 	struct index_mail_data *data = &mail->data;
 
-	if ((mail->wanted_fields & MAIL_FETCH_MESSAGE_PARTS) != 0)
-		(void)get_parts(&mail->mail);
-
-	if (data->parts == NULL)
-		data->parts = get_cached_parts(mail);
+	if (data->parts == NULL) {
+		if ((mail->wanted_fields & MAIL_FETCH_MESSAGE_PARTS) != 0)
+			(void)get_parts(&mail->mail);
+		else
+			data->parts = get_cached_parts(mail);
+	}
 
 	if (data->parts != NULL) {
 		data->hdr_size = data->parts->header_size;
 		data->body_size = data->parts->body_size;
 		data->hdr_size_set = TRUE;
 		data->body_size_set = TRUE;
+		data->size = data->hdr_size.virtual_size +
+			data->body_size.virtual_size;
 	}
 
 	return data->parts != NULL;
@@ -377,7 +384,7 @@
 {
 	struct index_mail *mail = (struct index_mail *) _mail;
 	struct index_mail_data *data = &mail->data;
-	uoff_t hdr_size, body_size, hdr_phys_size;
+	struct message_size hdr_size, body_size;
 
 	if (data->size != (uoff_t)-1)
 		return data->size;
@@ -388,58 +395,68 @@
 			return data->size;
 	}
 
-	if (!get_msgpart_sizes(mail)) {
-		/* this gives us header size for free */
-		if (data->parse_header)
-			index_mail_parse_headers(mail, FALSE);
-	}
-
-	hdr_size = data->hdr_size_set ?
-		data->hdr_size.virtual_size : (uoff_t)-1;
-	body_size = data->body_size_set ?
-		data->body_size.virtual_size : (uoff_t)-1;
-
-	if (body_size != (uoff_t)-1 && hdr_size != (uoff_t)-1) {
-		data->size = hdr_size + body_size;
+	if (get_msgpart_sizes(mail))
 		return data->size;
-	}
 
 	/* maybe it's binary */
 	get_binary_sizes(mail);
-	if (data->hdr_size_set && hdr_size == (uoff_t)-1)
-		hdr_size = data->hdr_size.virtual_size;
-	if (data->body_size_set && body_size == (uoff_t)-1)
-		body_size = data->body_size.virtual_size;
-
-	if (body_size != (uoff_t)-1 && hdr_size != (uoff_t)-1) {
-		data->size = hdr_size + body_size;
+	if (data->hdr_size_set && data->body_size_set) {
+		data->size = data->hdr_size.virtual_size +
+			data->body_size.virtual_size;
 		return data->size;
 	}
 
-	/* have to parse, slow.. */
-	hdr_phys_size = hdr_size != (uoff_t)-1 && data->hdr_size_set ?
-		data->hdr_size.physical_size : (uoff_t)-1;
-	if (!index_mail_open_stream(mail, hdr_phys_size != (uoff_t)-1 ?
-				    hdr_phys_size : 0))
+	/* do it the slow way */
+	if (_mail->get_stream(_mail, &hdr_size, &body_size) == NULL)
 		return (uoff_t)-1;
 
-	if (hdr_phys_size == (uoff_t)-1) {
-		message_get_header_size(data->stream, &data->hdr_size, NULL);
-		hdr_size = data->hdr_size.virtual_size;
-		data->hdr_size_set = TRUE;
-	}
-	if (body_size == (uoff_t)-1) {
-		message_get_body_size(data->stream, &data->body_size, NULL);
-		body_size = data->body_size.virtual_size;
-		data->body_size_set = TRUE;
+	return data->size;
+}
+
+static int index_mail_parse_body(struct index_mail *mail)
+{
+	struct index_mail_data *data = &mail->data;
+        enum mail_index_record_flag index_flags;
+
+	i_assert(data->parts == NULL);
+	i_assert(data->parser_ctx != NULL);
+
+	i_stream_seek(data->stream, data->hdr_size.physical_size);
+
+	message_parser_parse_body(data->parser_ctx, NULL, NULL, NULL);
+	data->parts = message_parser_deinit(data->parser_ctx);
+        data->parser_ctx = NULL;
+
+	data->body_size = data->parts->body_size;
+	data->body_size_set = TRUE;
+
+	if (mail->mail.has_nuls || mail->mail.has_no_nuls)
+		return TRUE;
+
+	/* we know the NULs now, update them */
+	if ((data->parts->flags & MESSAGE_PART_FLAG_HAS_NULS) != 0) {
+		mail->mail.has_nuls = TRUE;
+		mail->mail.has_no_nuls = FALSE;
+	} else {
+		mail->mail.has_nuls = FALSE;
+		mail->mail.has_no_nuls = TRUE;
 	}
-	data->size = hdr_size + body_size;
 
-	index_mail_cache_add_sizes(mail);
-	index_mail_cache_add(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE,
-			     &data->size, sizeof(data->size));
+	if (!index_mail_cache_transaction_begin(mail))
+		return TRUE;
 
-	return data->size;
+	index_flags = mail_cache_get_index_flags(mail->ibox->index->cache,
+						 mail->data.rec);
+	if (mail->mail.has_nuls)
+		index_flags |= MAIL_INDEX_FLAG_HAS_NULS;
+	else
+		index_flags |= MAIL_INDEX_FLAG_HAS_NO_NULS;
+
+	if (!mail_cache_update_index_flags(mail->ibox->index->cache,
+					   mail->data.rec, index_flags))
+		return FALSE;
+
+	return TRUE;
 }
 
 static struct istream *get_stream(struct mail *_mail,
@@ -459,9 +476,8 @@
 
 	if (hdr_size != NULL) {
 		if (!data->hdr_size_set) {
-			message_get_header_size(data->stream, &data->hdr_size,
-						NULL);
-			data->hdr_size_set = TRUE;
+			if (!index_mail_parse_headers(mail))
+				return NULL;
 		}
 
 		*hdr_size = data->hdr_size;
@@ -469,22 +485,42 @@
 
 	if (body_size != NULL) {
 		if (!data->body_size_set) {
-			i_stream_seek(data->stream,
-				      data->hdr_size.physical_size);
-
-			message_get_body_size(data->stream, &data->body_size,
-					      NULL);
-			data->body_size_set = TRUE;
+			if (!index_mail_parse_body(mail))
+				return NULL;
 		}
 
 		*body_size = data->body_size;
 	}
 
-	index_mail_cache_add_sizes(mail);
+	if (data->hdr_size_set && data->body_size_set) {
+		data->size = data->hdr_size.virtual_size +
+			data->body_size.virtual_size;
+		if (data->parts->children != NULL) {
+			/* cache the message parts only if this is a
+			   multipart message. it's pretty useless otherwise. */
+			cache_parts(mail);
+		} else {
+			index_mail_cache_add_sizes(mail);
+			index_mail_cache_add(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE,
+					     &data->size, sizeof(data->size));
+		}
+	} else {
+		index_mail_cache_add_sizes(mail);
+	}
+
 	i_stream_seek(data->stream, 0);
 	return data->stream;
 }
 
+static void parse_bodystructure_header(struct message_part *part,
+				       struct message_header_line *hdr,
+				       void *context)
+{
+	pool_t pool = context;
+
+	imap_bodystructure_parse_header(pool, part, hdr);
+}
+
 static const char *get_special(struct mail *_mail, enum mail_fetch_field field)
 {
 	struct index_mail *mail = (struct index_mail *) _mail;
@@ -529,7 +565,18 @@
 
 		if (!data->bodystructure_header_parsed) {
 			data->bodystructure_header_want = TRUE;
-			if (!index_mail_parse_headers(mail, FALSE))
+			if (!index_mail_parse_headers(mail))
+				return NULL;
+		}
+
+		if (data->parts != NULL) {
+			i_assert(data->parts->next == NULL);
+			message_parse_from_parts(data->parts->children,
+						 data->stream,
+						 parse_bodystructure_header,
+						 mail->pool);
+		} else {
+			if (!index_mail_parse_body(mail))
 				return NULL;
 		}
 

Index: index-mail.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-mail.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- index-mail.h	20 Aug 2003 01:41:30 -0000	1.8
+++ index-mail.h	21 Aug 2003 00:04:11 -0000	1.9
@@ -29,7 +29,8 @@
 	unsigned int idx_seq;
 
 	struct istream *stream;
-        struct message_size hdr_size, body_size;
+	struct message_size hdr_size, body_size;
+	struct message_parser_ctx *parser_ctx;
 
 	unsigned int parse_header:1;
 	unsigned int bodystructure_header_want:1;
@@ -76,7 +77,7 @@
 			  const void *data, size_t size);
 
 int index_mail_open_stream(struct index_mail *mail, uoff_t position);
-int index_mail_parse_headers(struct index_mail *mail, int get_parts);
+int index_mail_parse_headers(struct index_mail *mail);
 
 void index_mail_headers_init(struct index_mail *mail);
 void index_mail_headers_init_next(struct index_mail *mail);



More information about the dovecot-cvs mailing list