dovecot-2.2: lib-imap-storage: Don't waste effort getting mail's...

dovecot at dovecot.org dovecot at dovecot.org
Thu Apr 3 22:03:30 UTC 2014


details:   http://hg.dovecot.org/dovecot-2.2/rev/95ae49692ccb
changeset: 17198:95ae49692ccb
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Apr 04 01:03:17 2014 +0300
description:
lib-imap-storage: Don't waste effort getting mail's physical size if it can't be done quickly.

diffstat:

 src/lib-imap-storage/imap-msgpart.c |  71 +++++++++++++++++++++---------------
 1 files changed, 42 insertions(+), 29 deletions(-)

diffs (199 lines):

diff -r cba3890dafdb -r 95ae49692ccb src/lib-imap-storage/imap-msgpart.c
--- a/src/lib-imap-storage/imap-msgpart.c	Fri Apr 04 00:53:34 2014 +0300
+++ b/src/lib-imap-storage/imap-msgpart.c	Fri Apr 04 01:03:17 2014 +0300
@@ -336,11 +336,12 @@
 static int
 imap_msgpart_get_partial_header(struct mail *mail, struct istream *mail_input,
 				const struct imap_msgpart *msgpart,
-				struct message_size *hdr_size_r,
+				uoff_t *virtual_size_r, bool *have_crlfs_r,
 				struct imap_msgpart_open_result *result_r)
 {
 	const char *const *hdr_fields = msgpart->headers;
 	unsigned int hdr_count = str_array_length(hdr_fields);
+	struct message_size hdr_size;
 	struct istream *input;
 	bool has_nuls;
 
@@ -361,7 +362,7 @@
 						      (void *)NULL);
 	}
 
-	if (message_get_header_size(input, hdr_size_r, &has_nuls) < 0) {
+	if (message_get_header_size(input, &hdr_size, &has_nuls) < 0) {
 		errno = input->stream_errno;
 		mail_storage_set_critical(mail->box->storage,
 			"read(%s) failed: %m", i_stream_get_name(mail_input));
@@ -370,7 +371,10 @@
 	}
 	i_stream_seek(input, 0);
 	result_r->input = input;
-	result_r->size = hdr_size_r->virtual_size;
+	result_r->size = hdr_size.virtual_size;
+	result_r->size_field = 0;
+	*virtual_size_r = hdr_size.virtual_size;
+	*have_crlfs_r = hdr_size.physical_size == hdr_size.virtual_size;
 	return 0;
 }
 
@@ -426,7 +430,7 @@
 static void
 imap_msgpart_get_partial(struct mail *mail, const struct imap_msgpart *msgpart,
 			 bool convert_nuls, bool use_partial_cache,
-			 const struct message_size *part_size,
+			 uoff_t virtual_size, bool have_crlfs,
 			 struct imap_msgpart_open_result *result)
 {
 	struct istream *input2;
@@ -434,7 +438,7 @@
 
 	/* input is already seeked to the beginning of the wanted data */
 
-	if (msgpart->partial_offset >= part_size->virtual_size) {
+	if (msgpart->partial_offset >= virtual_size) {
 		/* can't seek past the MIME part */
 		i_stream_unref(&result->input);
 		result->input = i_stream_create_from_data("", 0);
@@ -442,7 +446,7 @@
 		return;
 	}
 
-	if (part_size->virtual_size == part_size->physical_size) {
+	if (have_crlfs) {
 		/* input has CRLF linefeeds, we can quickly seek to
 		   wanted position */
 		i_stream_skip(result->input, msgpart->partial_offset);
@@ -454,7 +458,7 @@
 						       msgpart);
 	}
 
-	bytes_left = part_size->virtual_size - msgpart->partial_offset;
+	bytes_left = virtual_size - msgpart->partial_offset;
 	if (msgpart->partial_size <= bytes_left) {
 		/* limit output to specified number of bytes */
 		result->size = msgpart->partial_size;
@@ -527,15 +531,16 @@
 static int
 imap_msgpart_open_normal(struct mail *mail, struct imap_msgpart *msgpart,
 			 const struct message_part *part,
-			 struct message_size *part_size_r,
+			 uoff_t *virtual_size_r, bool *have_crlfs_r,
 			 struct imap_msgpart_open_result *result_r)
 {
-	struct message_size hdr_size, body_size;
+	struct message_size hdr_size, body_size, part_size;
 	struct istream *input = NULL;
+	bool unknown_crlfs = FALSE;
 
 	memset(&hdr_size, 0, sizeof(hdr_size));
 	memset(&body_size, 0, sizeof(body_size));
-	memset(part_size_r, 0, sizeof(*part_size_r));
+	memset(&part_size, 0, sizeof(part_size));
 
 	if (*msgpart->section_number != '\0') {
 		/* find the MIME part */
@@ -549,10 +554,15 @@
 	case FETCH_FULL:
 		/* fetch the whole message */
 		if (mail_get_stream(mail, NULL, NULL, &input) < 0 ||
-		    mail_get_virtual_size(mail, &body_size.virtual_size) < 0 ||
-		    mail_get_physical_size(mail, &body_size.physical_size) < 0)
+		    mail_get_virtual_size(mail, &body_size.virtual_size) < 0)
 			return -1;
 		result_r->size_field = MAIL_FETCH_VIRTUAL_SIZE;
+
+		i_assert(mail->lookup_abort == MAIL_LOOKUP_ABORT_NEVER);
+		mail->lookup_abort = MAIL_LOOKUP_ABORT_READ_MAIL;
+		if (mail_get_physical_size(mail, &body_size.physical_size) < 0)
+			unknown_crlfs = TRUE;
+		mail->lookup_abort = MAIL_LOOKUP_ABORT_NEVER;
 		break;
 	case FETCH_MIME:
 	case FETCH_MIME_BODY:
@@ -587,18 +597,19 @@
 	if (msgpart->headers != NULL) {
 		/* return specific headers */
 		return imap_msgpart_get_partial_header(mail, input, msgpart,
-						       part_size_r, result_r);
+						       virtual_size_r,
+						       have_crlfs_r, result_r);
 	}
 
 	switch (msgpart->fetch_type) {
 	case FETCH_FULL:
-		part_size_r->physical_size += body_size.physical_size;
-		part_size_r->virtual_size += body_size.virtual_size;
+		part_size.physical_size += body_size.physical_size;
+		part_size.virtual_size += body_size.virtual_size;
 		/* fall through */
 	case FETCH_MIME:
 	case FETCH_HEADER:
-		part_size_r->physical_size += hdr_size.physical_size;
-		part_size_r->virtual_size += hdr_size.virtual_size;
+		part_size.physical_size += hdr_size.physical_size;
+		part_size.virtual_size += hdr_size.virtual_size;
 		break;
 	case FETCH_HEADER_FIELDS:
 	case FETCH_HEADER_FIELDS_NOT:
@@ -606,13 +617,16 @@
 	case FETCH_BODY:
 	case FETCH_MIME_BODY:
 		i_stream_skip(input, hdr_size.physical_size);
-		part_size_r->physical_size += body_size.physical_size;
-		part_size_r->virtual_size += body_size.virtual_size;
+		part_size.physical_size += body_size.physical_size;
+		part_size.virtual_size += body_size.virtual_size;
 		break;
 	}
 
 	result_r->input = input;
 	i_stream_ref(input);
+	*virtual_size_r = part_size.virtual_size;
+	*have_crlfs_r = !unknown_crlfs &&
+		part_size.virtual_size == part_size.physical_size;
 	return 0;
 }
 
@@ -620,9 +634,8 @@
 		      struct imap_msgpart_open_result *result_r)
 {
 	struct message_part *part;
-	struct message_size part_size;
-	uoff_t size;
-	bool include_hdr, binary, use_partial_cache;
+	uoff_t virtual_size;
+	bool include_hdr, binary, use_partial_cache, have_crlfs;
 	int ret;
 
 	memset(result_r, 0, sizeof(*result_r));
@@ -645,15 +658,15 @@
 			if (mail_get_parts(mail, &part) < 0)
 				return -1;
 		}
-		if (mail_get_binary_stream(mail, part, include_hdr, &size,
-					   &binary, &result_r->input) < 0)
+		if (mail_get_binary_stream(mail, part, include_hdr,
+					   &virtual_size, &binary,
+					   &result_r->input) < 0)
 			return -1;
-		part_size.virtual_size = size;
-		part_size.physical_size = size;
+		have_crlfs = TRUE;
 		use_partial_cache = FALSE;
 	} else {
-		if (imap_msgpart_open_normal(mail, msgpart, part, &part_size,
-					     result_r) < 0)
+		if (imap_msgpart_open_normal(mail, msgpart, part, &virtual_size,
+					     &have_crlfs, result_r) < 0)
 			return -1;
 		binary = FALSE;
 		use_partial_cache = TRUE;
@@ -663,7 +676,7 @@
 		result_r->binary_decoded_input_has_nuls = TRUE;
 
 	imap_msgpart_get_partial(mail, msgpart, !binary, use_partial_cache,
-				 &part_size, result_r);
+				 virtual_size, have_crlfs, result_r);
 	return 0;
 }
 


More information about the dovecot-cvs mailing list