Mercurial > dovecot > core-2.2
changeset 17198:95ae49692ccb
lib-imap-storage: Don't waste effort getting mail's physical size if it can't be done quickly.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 04 Apr 2014 01:03:17 +0300 |
parents | cba3890dafdb |
children | 3b9935fe9cb7 |
files | src/lib-imap-storage/imap-msgpart.c |
diffstat | 1 files changed, 42 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- 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; }