]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Added support for listing/adding cache fields.
authorTimo Sirainen <tss@iki.fi>
Tue, 17 Nov 2009 00:38:13 +0000 (19:38 -0500)
committerTimo Sirainen <tss@iki.fi>
Tue, 17 Nov 2009 00:38:13 +0000 (19:38 -0500)
--HG--
branch : HEAD

src/lib-storage/index/index-status.c
src/lib-storage/index/index-storage.c
src/lib-storage/mail-storage.h

index 4adf23e3b0a7a18b06f638086ecb7d16da37277b..64661e1f928950ef454cf9f0bddff83aadffbb92 100644 (file)
@@ -1,9 +1,35 @@
 /* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
+#include "array.h"
+#include "mail-cache.h"
 #include "index-storage.h"
 #include "mail-index-modseq.h"
 
+static void
+index_storage_get_status_cache_fields(struct index_mailbox *ibox,
+                                     struct mailbox_status *status_r)
+{
+       const struct mail_cache_field *fields;
+       enum mail_cache_decision_type dec;
+       ARRAY_TYPE(const_string) *cache_fields;
+       unsigned int i, count;
+
+       fields = mail_cache_register_get_list(ibox->cache,
+                                             pool_datastack_create(), &count);
+
+       /* a bit leaky to allocate memory from mailbox pool every time, but this
+          is unlikely to be called more than once for the mailbox anyway. */
+       cache_fields = p_new(ibox->box.pool, ARRAY_TYPE(const_string), 1);
+       p_array_init(cache_fields, ibox->box.pool, count);
+       for (i = 0; i < count; i++) {
+               dec = fields[i].decision & ~MAIL_CACHE_DECISION_FORCED;
+               if (dec != MAIL_CACHE_DECISION_NO)
+                       array_append(cache_fields, &fields[i].name, 1);
+       }
+       status_r->cache_fields = cache_fields;
+}
+
 void index_storage_get_status(struct mailbox *box,
                              enum mailbox_status_items items,
                              struct mailbox_status *status_r)
@@ -35,11 +61,13 @@ void index_storage_get_status(struct mailbox *box,
                }
        }
 
-       if (items & STATUS_FIRST_UNSEEN_SEQ) {
+       if ((items & STATUS_FIRST_UNSEEN_SEQ) != 0) {
                mail_index_lookup_first(ibox->view, 0, MAIL_SEEN,
                                        &status_r->first_unseen_seq);
        }
 
-       if (items & STATUS_KEYWORDS)
+       if ((items & STATUS_KEYWORDS) != 0)
                status_r->keywords = mail_index_get_keywords(ibox->index);
+       if ((items & STATUS_CACHE_FIELDS) != 0)
+               index_storage_get_status_cache_fields(ibox, status_r);
 }
index b34fb221c626c9f2b1f58733bd38e24493f9fb82..6b738f1048ac14e6bac45a4c0fbc9fea41a4881d 100644 (file)
@@ -539,6 +539,52 @@ void index_storage_mailbox_close(struct mailbox *box)
        pool_unref(&box->pool);
 }
 
+static void
+index_storage_mailbox_update_cache_fields(struct index_mailbox *ibox,
+                                         const struct mailbox_update *update)
+{
+       const char *const *field_names = update->cache_fields;
+       ARRAY_DEFINE(new_fields, struct mail_cache_field);
+       const struct mail_cache_field *old_fields;
+       struct mail_cache_field field;
+       unsigned int i, j, old_count;
+
+       old_fields = mail_cache_register_get_list(ibox->cache,
+                                                 pool_datastack_create(),
+                                                 &old_count);
+
+       /* There shouldn't be many fields, so don't worry about O(n^2). */
+       t_array_init(&new_fields, 32);
+       for (i = 0; field_names[i] != NULL; i++) {
+               /* see if it's an existing field */
+               for (j = 0; j < old_count; j++) {
+                       if (strcmp(field_names[i], old_fields[j].name) == 0)
+                               break;
+               }
+               if (j != old_count) {
+                       field = old_fields[i];
+                       if (field.decision == MAIL_CACHE_DECISION_NO)
+                               field.decision = MAIL_CACHE_DECISION_TEMP;
+                       array_append(&new_fields, &field, 1);
+               } else if (strncmp(field_names[i], "hdr.", 4) == 0) {
+                       /* new header */
+                       memset(&field, 0, sizeof(field));
+                       field.name = field_names[i];
+                       field.type = MAIL_CACHE_FIELD_HEADER;
+                       field.decision = MAIL_CACHE_DECISION_TEMP;
+                       array_append(&new_fields, &field, 1);
+               } else {
+                       /* new unknown field. we can't do anything about
+                          this since we don't know its type */
+               }
+       }
+       if (array_count(&new_fields) > 0) {
+               mail_cache_register_fields(ibox->cache,
+                                          array_idx_modifiable(&new_fields, 0),
+                                          array_count(&new_fields));
+       }
+}
+
 int index_storage_mailbox_update(struct mailbox *box,
                                 const struct mailbox_update *update)
 {
@@ -552,6 +598,8 @@ int index_storage_mailbox_update(struct mailbox *box,
                if (mailbox_open(box) < 0)
                        return -1;
        }
+       if (update->cache_fields != NULL)
+               index_storage_mailbox_update_cache_fields(ibox, update);
 
        /* make sure we get the latest index info */
        (void)mail_index_refresh(ibox->index);
index 84fb4cf051492a3af1bfa742dc307192e8a12898..3903581920876a7816aac8f2e16a28c21a5cbd1b 100644 (file)
@@ -60,7 +60,8 @@ enum mailbox_status_items {
        STATUS_FIRST_UNSEEN_SEQ = 0x20,
        STATUS_KEYWORDS         = 0x40,
        STATUS_HIGHESTMODSEQ    = 0x80,
-       STATUS_GUID             = 0x100
+       STATUS_GUID             = 0x100,
+       STATUS_CACHE_FIELDS     = 0x200
 };
 
 enum mailbox_search_result_flags {
@@ -185,6 +186,8 @@ struct mailbox_status {
        uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
 
        const ARRAY_TYPE(keywords) *keywords;
+       /* Fields that have "temp" or "yes" caching decision. */
+       const ARRAY_TYPE(const_string) *cache_fields;
 
        /* There are expunges that haven't been synced yet */
        unsigned int sync_delayed_expunges:1;
@@ -198,6 +201,8 @@ struct mailbox_update {
        uint32_t uid_validity;
        uint32_t min_next_uid;
        uint64_t min_highest_modseq;
+       /* Add these fields to be temporarily cached, if they aren't already. */
+       const char *const *cache_fields;
 };
 
 struct mail_transaction_commit_changes {