]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Maildir: If mail's virtual size can be found from filename/uidlist, do it instead...
authorTimo Sirainen <tss@iki.fi>
Wed, 29 Sep 2010 17:38:29 +0000 (18:38 +0100)
committerTimo Sirainen <tss@iki.fi>
Wed, 29 Sep 2010 17:38:29 +0000 (18:38 +0100)
This is especially useful with POP3 to avoid opening cache file.

src/lib-storage/index/index-mail.c
src/lib-storage/index/index-mail.h
src/lib-storage/index/maildir/maildir-mail.c
src/lib-storage/index/maildir/maildir-uidlist.c
src/lib-storage/index/maildir/maildir-uidlist.h

index 01c39cde2344449cef42cf04d0c41e8bc2f0025a..4847688f1b1c6c6dcb775ceb4573de6b962a6efa 100644 (file)
@@ -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);
 
index d5340c6c7c1d4a5b66703da6ae9023ab250d23fb..3a7c97c308161799c6296ce0a6d208715d15a342 100644 (file)
@@ -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
index 7bebdaf8a7e8f877540b261b05cc3c402aa36590..9a125ea81070b9fe23703833c5336f753d482d20 100644 (file)
@@ -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;
index e4edddb28ab593d624d9f5a3cb775a60c3f01576..0cc1252feda52d6cde7bd7ac456a9ede3ff904bf 100644 (file)
@@ -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);
index bdd9cb8cc12ba1fb94efa7a3e04e37f9650a8684..614a5e2822bb29698e975c7c9d989b454e91985a 100644 (file)
@@ -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);