Mercurial > dovecot > original-hg > dovecot-1.2
changeset 5951:e9b5d3d33b95 HEAD
Store virtual sizes to dovecot-uidlist if we want to use them all the time.
If nothing else than virtual size is wanted to be known (ie. POP3 or
POP3-like IMAP client), don't bother updating cache file at all.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 12 Jul 2007 02:44:47 +0300 |
parents | 49aebb3028f7 |
children | ba118a9eeb50 |
files | src/lib-storage/index/index-mail.c src/lib-storage/index/index-mail.h src/lib-storage/index/maildir/maildir-mail.c |
diffstat | 3 files changed, 132 insertions(+), 46 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/index-mail.c Thu Jul 12 02:42:32 2007 +0300 +++ b/src/lib-storage/index/index-mail.c Thu Jul 12 02:44:47 2007 +0300 @@ -110,17 +110,6 @@ return uoff; } -uoff_t index_mail_get_cached_virtual_size(struct index_mail *mail) -{ - return index_mail_get_cached_uoff_t(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE); -} - -static uoff_t index_mail_get_cached_physical_size(struct index_mail *mail) -{ - return index_mail_get_cached_uoff_t(mail, - MAIL_CACHE_PHYSICAL_FULL_SIZE); -} - enum mail_flags index_mail_get_flags(struct mail *_mail) { struct index_mail *mail = (struct index_mail *) _mail; @@ -296,6 +285,21 @@ return data->parts != NULL; } +uoff_t index_mail_get_cached_virtual_size(struct index_mail *mail) +{ + uoff_t size; + + if (mail->data.virtual_size != (uoff_t)-1) + return mail->data.virtual_size; + + size = index_mail_get_cached_uoff_t(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE); + if (size != (uoff_t)-1) + mail->data.virtual_size = size; + else + (void)get_cached_msgpart_sizes(mail); + return mail->data.virtual_size; +} + uoff_t index_mail_get_virtual_size(struct mail *_mail) { struct index_mail *mail = (struct index_mail *) _mail; @@ -303,20 +307,13 @@ struct message_size hdr_size, body_size; uoff_t old_offset; - if (data->virtual_size != (uoff_t)-1) - return data->virtual_size; - - data->virtual_size = index_mail_get_cached_virtual_size(mail); - if (data->virtual_size != (uoff_t)-1) + if (index_mail_get_cached_virtual_size(mail) != (uoff_t)-1) return data->virtual_size; - if (!get_cached_msgpart_sizes(mail)) { - old_offset = data->stream == NULL ? 0 : data->stream->v_offset; - - if (mail_get_stream(_mail, &hdr_size, &body_size) == NULL) - return (uoff_t)-1; - i_stream_seek(data->stream, old_offset); - } + old_offset = data->stream == NULL ? 0 : data->stream->v_offset; + if (mail_get_stream(_mail, &hdr_size, &body_size) == NULL) + return (uoff_t)-1; + i_stream_seek(data->stream, old_offset); i_assert(data->virtual_size != (uoff_t)-1); index_mail_cache_add(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE, @@ -328,18 +325,18 @@ { struct index_mail *mail = (struct index_mail *) _mail; struct index_mail_data *data = &mail->data; + uoff_t size; if (data->physical_size != (uoff_t)-1) return data->physical_size; - data->physical_size = index_mail_get_cached_physical_size(mail); - if (data->physical_size != (uoff_t)-1) - return data->physical_size; - - if (get_cached_msgpart_sizes(mail)) - return data->physical_size; - - return (uoff_t)-1; + size = index_mail_get_cached_uoff_t(mail, + MAIL_CACHE_PHYSICAL_FULL_SIZE); + if (size != (uoff_t)-1) + data->physical_size = size; + else + (void)get_cached_msgpart_sizes(mail); + return data->physical_size; } void index_mail_cache_add(struct index_mail *mail, enum index_cache_field field,
--- a/src/lib-storage/index/index-mail.h Thu Jul 12 02:42:32 2007 +0300 +++ b/src/lib-storage/index/index-mail.h Thu Jul 12 02:44:47 2007 +0300 @@ -118,6 +118,8 @@ enum mail_fetch_field wanted_fields; struct index_header_lookup_ctx *wanted_headers; + int pop3_state; + /* per-mail variables, here for performance reasons: */ uint32_t header_seq; string_t *header_data; @@ -125,6 +127,8 @@ ARRAY_DEFINE(header_match, uint8_t); ARRAY_DEFINE(header_match_lines, unsigned int); uint8_t header_match_value; + + unsigned int pop3_state_set:1; }; struct mail *
--- a/src/lib-storage/index/maildir/maildir-mail.c Thu Jul 12 02:42:32 2007 +0300 +++ b/src/lib-storage/index/maildir/maildir-mail.c Thu Jul 12 02:44:47 2007 +0300 @@ -7,6 +7,7 @@ #include "maildir-filename.h" #include "maildir-uidlist.h" +#include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <sys/stat.h> @@ -149,22 +150,75 @@ return TRUE; } +static int maildir_get_pop3_state(struct index_mail *mail) +{ + const struct mail_cache_field *fields; + unsigned int i, count, vsize_idx; + enum mail_cache_decision_type dec, vsize_dec; + enum mail_fetch_field allowed_pop3_fields; + bool not_pop3_only = FALSE; + + if (mail->pop3_state_set) + return mail->pop3_state; + + /* if this mail itself has non-pop3 fields we know we're not + pop3-only */ + allowed_pop3_fields = MAIL_FETCH_FLAGS | MAIL_FETCH_STREAM_HEADER | + MAIL_FETCH_STREAM_BODY | MAIL_FETCH_UIDL_FILE_NAME | + MAIL_FETCH_VIRTUAL_SIZE; + + if (mail->wanted_headers != NULL || + (mail->wanted_fields & allowed_pop3_fields) == 0) + not_pop3_only = TRUE; + + /* get vsize decision */ + vsize_idx = mail->ibox->cache_fields[MAIL_CACHE_VIRTUAL_FULL_SIZE].idx; + if (not_pop3_only) { + vsize_dec = mail_cache_field_get_decision(mail->ibox->cache, + vsize_idx); + vsize_dec &= ~MAIL_CACHE_DECISION_FORCED; + } else { + /* also check if there are any non-vsize cached fields */ + vsize_dec = MAIL_CACHE_DECISION_NO; + fields = mail_cache_register_get_list(mail->ibox->cache, + pool_datastack_create(), + &count); + for (i = 0; i < count; i++) { + dec = fields[i].decision & ~MAIL_CACHE_DECISION_FORCED; + if (fields[i].idx == vsize_idx) + vsize_dec = dec; + else if (dec != MAIL_CACHE_DECISION_NO) + not_pop3_only = TRUE; + } + } + + if (!not_pop3_only) { + /* either nothing is cached, or only vsize is cached. */ + mail->pop3_state = 1; + } else if (vsize_dec != MAIL_CACHE_DECISION_YES) { + /* if virtual size isn't cached permanently, + POP3 isn't being used */ + mail->pop3_state = -1; + } else { + /* possibly a mixed pop3/imap */ + mail->pop3_state = 0; + } + mail->pop3_state_set = TRUE; + return mail->pop3_state; +} + static uoff_t maildir_mail_get_virtual_size(struct mail *_mail) { struct index_mail *mail = (struct index_mail *)_mail; struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox; struct index_mail_data *data = &mail->data; - const char *path, *fname; - uoff_t virtual_size; - - if (data->virtual_size != (uoff_t)-1) - return data->virtual_size; + struct message_size hdr_size, body_size; + const char *path, *fname, *value; + uoff_t old_offset; + int pop3_state; - if ((mail->wanted_fields & MAIL_FETCH_VIRTUAL_SIZE) == 0) { - data->virtual_size = index_mail_get_cached_virtual_size(mail); - if (data->virtual_size != (uoff_t)-1) - return data->virtual_size; - } + if (index_mail_get_cached_virtual_size(mail) != (uoff_t)-1) + return data->virtual_size; if (_mail->uid != 0) { if (!maildir_mail_get_fname(mbox, _mail, &fname)) @@ -178,13 +232,44 @@ /* size can be included in filename */ if (maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE, - &virtual_size)) { - index_mail_cache_add(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE, - &virtual_size, sizeof(virtual_size)); - return virtual_size; + &data->virtual_size)) + return data->virtual_size; + + /* size can be included in uidlist entry */ + if (_mail->uid != 0) { + value = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid, + MAILDIR_UIDLIST_REC_EXT_VSIZE); + if (value != NULL) { + char *p; + + data->virtual_size = strtoull(value, &p, 10); + if (*p == '\0') + return data->virtual_size; + } } - return index_mail_get_virtual_size(_mail); + /* fallback to reading the file */ + old_offset = data->stream == NULL ? 0 : data->stream->v_offset; + if (mail_get_stream(_mail, &hdr_size, &body_size) == NULL) + return (uoff_t)-1; + i_stream_seek(data->stream, old_offset); + i_assert(data->virtual_size != (uoff_t)-1); + + /* 1 = pop3-only, 0 = mixed, -1 = no pop3 */ + pop3_state = maildir_get_pop3_state(mail); + if (pop3_state <= 0) { + index_mail_cache_add(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE, + &data->virtual_size, + sizeof(data->virtual_size)); + } + if (pop3_state >= 0) { + /* if virtual size is wanted permanently, store it to uidlist + so that in case cache file gets lost we can get it quickly */ + maildir_uidlist_set_ext(mbox->uidlist, _mail->uid, + MAILDIR_UIDLIST_REC_EXT_VSIZE, + dec2str(data->virtual_size)); + } + return data->virtual_size; } static const char *