From a0aedab7cd06125e4d73638b1bd0c01c7caa2626 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Wed, 29 Sep 2010 18:38:29 +0100 Subject: [PATCH] Maildir: If mail's virtual size can be found from filename/uidlist, do it instead of using cache. This is especially useful with POP3 to avoid opening cache file. --- src/lib-storage/index/index-mail.c | 37 +++++++++++++------ src/lib-storage/index/index-mail.h | 2 + src/lib-storage/index/maildir/maildir-mail.c | 27 ++++++++++---- .../index/maildir/maildir-uidlist.c | 5 +++ .../index/maildir/maildir-uidlist.h | 1 + 5 files changed, 53 insertions(+), 19 deletions(-) diff --git a/src/lib-storage/index/index-mail.c b/src/lib-storage/index/index-mail.c index 01c39cde23..4847688f1b 100644 --- a/src/lib-storage/index/index-mail.c +++ b/src/lib-storage/index/index-mail.c @@ -802,13 +802,34 @@ static void index_mail_stream_destroy_callback(struct index_mail *mail) mail->data.destroying_stream = FALSE; } +enum index_mail_access_part index_mail_get_access_part(struct index_mail *mail) +{ + struct mail_cache_field *cache_fields = mail->ibox->cache_fields; + + if ((mail->data.access_part & (READ_HDR | PARSE_HDR)) != 0 && + (mail->data.access_part & (READ_BODY | PARSE_BODY)) != 0) + return mail->data.access_part; + + /* lazy virtual size access check */ + if ((mail->wanted_fields & MAIL_FETCH_VIRTUAL_SIZE) != 0) { + unsigned int cache_field = + cache_fields[MAIL_CACHE_VIRTUAL_FULL_SIZE].idx; + + if (mail_cache_field_exists(mail->trans->cache_view, + mail->mail.mail.seq, + cache_field) <= 0) + mail->data.access_part |= READ_HDR | READ_BODY; + } + return mail->data.access_part; +} + void index_mail_set_read_buffer_size(struct mail *_mail, struct istream *input) { struct index_mail *mail = (struct index_mail *)_mail; unsigned int block_size; i_stream_set_max_buffer_size(input, MAIL_READ_FULL_BLOCK_SIZE); - block_size = (mail->data.access_part & READ_BODY) != 0 ? + block_size = (index_mail_get_access_part(mail) & READ_BODY) != 0 ? MAIL_READ_FULL_BLOCK_SIZE : MAIL_READ_HDR_BLOCK_SIZE; i_stream_set_init_buffer_size(input, block_size); } @@ -844,7 +865,7 @@ int index_mail_init_stream(struct index_mail *mail, if (hdr_size != NULL || body_size != NULL) { i_stream_seek(data->stream, 0); if (!data->hdr_size_set) { - if ((data->access_part & PARSE_HDR) != 0) { + if ((index_mail_get_access_part(mail) & PARSE_HDR) != 0) { (void)get_cached_parts(mail); if (index_mail_parse_headers(mail, NULL) < 0) return -1; @@ -865,7 +886,7 @@ int index_mail_init_stream(struct index_mail *mail, if (!data->body_size_set) { i_stream_seek(data->stream, data->hdr_size.physical_size); - if ((data->access_part & PARSE_BODY) != 0) { + if ((index_mail_get_access_part(mail) & PARSE_BODY) != 0) { if (index_mail_parse_body(mail, 0) < 0) return -1; } else { @@ -1181,7 +1202,7 @@ static void check_envelope(struct index_mail *mail) mail->ibox->cache_fields[MAIL_CACHE_IMAP_ENVELOPE].idx; unsigned int cache_field_hdr; - if ((mail->data.access_part & PARSE_HDR) != 0) { + if ((index_mail_get_access_part(mail) & PARSE_HDR) != 0) { mail->data.save_envelope = TRUE; return; } @@ -1255,14 +1276,6 @@ void index_mail_set_seq(struct mail *_mail, uint32_t seq) } } - if ((mail->wanted_fields & MAIL_FETCH_VIRTUAL_SIZE) != 0) { - unsigned int cache_field = - cache_fields[MAIL_CACHE_VIRTUAL_FULL_SIZE].idx; - - if (mail_cache_field_exists(cache_view, seq, cache_field) <= 0) - data->access_part |= READ_HDR | READ_BODY; - } - if ((mail->wanted_fields & MAIL_FETCH_IMAP_ENVELOPE) != 0) check_envelope(mail); diff --git a/src/lib-storage/index/index-mail.h b/src/lib-storage/index/index-mail.h index d5340c6c7c..3a7c97c308 100644 --- a/src/lib-storage/index/index-mail.h +++ b/src/lib-storage/index/index-mail.h @@ -225,4 +225,6 @@ void index_mail_cache_parse_deinit(struct mail *mail, time_t received_date, int index_mail_cache_lookup_field(struct index_mail *mail, buffer_t *buf, unsigned int field_idx); +enum index_mail_access_part index_mail_get_access_part(struct index_mail *mail); + #endif diff --git a/src/lib-storage/index/maildir/maildir-mail.c b/src/lib-storage/index/maildir/maildir-mail.c index 7bebdaf8a7..9a125ea810 100644 --- a/src/lib-storage/index/maildir/maildir-mail.c +++ b/src/lib-storage/index/maildir/maildir-mail.c @@ -112,7 +112,8 @@ static int maildir_mail_stat(struct mail *mail, struct stat *st) if (mail->lookup_abort == MAIL_LOOKUP_ABORT_NOT_IN_CACHE) return mail_set_aborted(mail); - if (imail->data.access_part != 0 && imail->data.stream == NULL) { + if (index_mail_get_access_part(imail) != 0 && + imail->data.stream == NULL) { /* we're going to open the mail anyway */ struct istream *input; @@ -364,20 +365,32 @@ maildir_handle_size_caching(struct index_mail *mail, bool quick_check, static int maildir_mail_get_virtual_size(struct mail *_mail, uoff_t *size_r) { + struct maildir_mailbox *mbox = (struct maildir_mailbox *)_mail->box; struct index_mail *mail = (struct index_mail *)_mail; struct index_mail_data *data = &mail->data; struct message_size hdr_size, body_size; struct istream *input; uoff_t old_offset; - if (index_mail_get_cached_virtual_size(mail, size_r)) { - i_assert(mail->data.virtual_size != (uoff_t)-1); - maildir_handle_size_caching(mail, TRUE, TRUE); - return 0; + if (maildir_uidlist_is_read(mbox->uidlist) || + (_mail->box->flags & MAILBOX_FLAG_POP3_SESSION) != 0) { + /* try to get the size from uidlist. this is especially useful + with pop3 to avoid unnecessarily opening the cache file. */ + if (maildir_quick_size_lookup(mail, TRUE, + &data->virtual_size) < 0) + return -1; } - if (maildir_quick_size_lookup(mail, TRUE, &data->virtual_size) < 0) - return -1; + if (data->virtual_size == (uoff_t)-1) { + if (index_mail_get_cached_virtual_size(mail, size_r)) { + i_assert(mail->data.virtual_size != (uoff_t)-1); + maildir_handle_size_caching(mail, TRUE, TRUE); + return 0; + } + + if (maildir_quick_size_lookup(mail, TRUE, &data->virtual_size) < 0) + return -1; + } if (data->virtual_size != (uoff_t)-1) { data->dont_cache_fetch_fields |= MAIL_FETCH_VIRTUAL_SIZE; *size_r = data->virtual_size; diff --git a/src/lib-storage/index/maildir/maildir-uidlist.c b/src/lib-storage/index/maildir/maildir-uidlist.c index e4edddb28a..0cc1252fed 100644 --- a/src/lib-storage/index/maildir/maildir-uidlist.c +++ b/src/lib-storage/index/maildir/maildir-uidlist.c @@ -227,6 +227,11 @@ bool maildir_uidlist_is_locked(struct maildir_uidlist *uidlist) return UIDLIST_IS_LOCKED(uidlist); } +bool maildir_uidlist_is_read(struct maildir_uidlist *uidlist) +{ + return uidlist->initial_read; +} + void maildir_uidlist_unlock(struct maildir_uidlist *uidlist) { i_assert(uidlist->lock_count > 0); diff --git a/src/lib-storage/index/maildir/maildir-uidlist.h b/src/lib-storage/index/maildir/maildir-uidlist.h index bdd9cb8cc1..614a5e2822 100644 --- a/src/lib-storage/index/maildir/maildir-uidlist.h +++ b/src/lib-storage/index/maildir/maildir-uidlist.h @@ -55,6 +55,7 @@ int maildir_uidlist_try_lock(struct maildir_uidlist *uidlist); int maildir_uidlist_lock_touch(struct maildir_uidlist *uidlist); void maildir_uidlist_unlock(struct maildir_uidlist *uidlist); bool maildir_uidlist_is_locked(struct maildir_uidlist *uidlist); +bool maildir_uidlist_is_read(struct maildir_uidlist *uidlist); struct maildir_uidlist *maildir_uidlist_init(struct maildir_mailbox *mbox); void maildir_uidlist_deinit(struct maildir_uidlist **uidlist); -- 2.47.3