]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
dsync: Update cache fields' decision and last_used fields explicitly.
authorTimo Sirainen <tss@iki.fi>
Sat, 10 Dec 2011 06:44:33 +0000 (08:44 +0200)
committerTimo Sirainen <tss@iki.fi>
Sat, 10 Dec 2011 06:44:33 +0000 (08:44 +0200)
This makes v2.1's dsync incompatible with v2.0's when used in different
servers.

18 files changed:
src/dsync/dsync-data.c
src/dsync/dsync-data.h
src/dsync/dsync-proxy-client.c
src/dsync/dsync-proxy-server-cmd.c
src/dsync/dsync-proxy.c
src/dsync/dsync-proxy.h
src/dsync/dsync-worker-local.c
src/dsync/dsync-worker-private.h
src/dsync/test-dsync-common.c
src/dsync/test-dsync-proxy.c
src/dsync/test-dsync-worker.c
src/dsync/test-dsync-worker.h
src/lib-storage/index/dbox-multi/mdbox-storage.c
src/lib-storage/index/dbox-single/sdbox-storage.c
src/lib-storage/index/index-status.c
src/lib-storage/index/index-storage.c
src/lib-storage/index/index-storage.h
src/lib-storage/mail-storage.h

index d986c5b973bd27f3952f6035246ea667ea0f54c3..48fad3f8297e1097534b4c0099065d62bf5c7fee 100644 (file)
@@ -10,7 +10,8 @@ struct dsync_mailbox *
 dsync_mailbox_dup(pool_t pool, const struct dsync_mailbox *box)
 {
        struct dsync_mailbox *dest;
-       const char *const *cache_fields = NULL, *dup;
+       const struct mailbox_cache_field *cache_fields = NULL;
+       struct mailbox_cache_field *dup;
        unsigned int i, count = 0;
 
        dest = p_new(pool, struct dsync_mailbox, 1);
@@ -24,8 +25,9 @@ dsync_mailbox_dup(pool_t pool, const struct dsync_mailbox *box)
        else {
                p_array_init(&dest->cache_fields, pool, count);
                for (i = 0; i < count; i++) {
-                       dup = p_strdup(pool, cache_fields[i]);
-                       array_append(&dest->cache_fields, &dup, 1);
+                       dup = array_append_space(&dest->cache_fields);
+                       *dup = cache_fields[i];
+                       dup->name = p_strdup(pool, dup->name);
                }
        }
        return dest;
index c80fbf0089ecd8ee99d544895379f8b5a77a402f..3f028c7fbd7b6d7ba3912ff1a54904841472dfa9 100644 (file)
@@ -28,7 +28,7 @@ struct dsync_mailbox {
           otherwise it's the last rename timestamp. */
        time_t last_change;
        enum dsync_mailbox_flags flags;
-       ARRAY_TYPE(const_string) cache_fields;
+       ARRAY_TYPE(mailbox_cache_field) cache_fields;
 };
 ARRAY_DEFINE_TYPE(dsync_mailbox, struct dsync_mailbox *);
 #define dsync_mailbox_is_noselect(dsync_box) \
index 6b002aa635463e9e31ecbfe5bb1fe0676208c357..ae32b0a2bb6f87284dfd80b10acdfd1759b6cbc4 100644 (file)
@@ -893,7 +893,7 @@ proxy_client_worker_update_mailbox(struct dsync_worker *_worker,
 static void
 proxy_client_worker_select_mailbox(struct dsync_worker *_worker,
                                   const mailbox_guid_t *mailbox,
-                                  const ARRAY_TYPE(const_string) *cache_fields)
+                                  const ARRAY_TYPE(mailbox_cache_field) *cache_fields)
 {
        struct proxy_client_dsync_worker *worker =
                (struct proxy_client_dsync_worker *)_worker;
@@ -908,7 +908,7 @@ proxy_client_worker_select_mailbox(struct dsync_worker *_worker,
                str_append(str, "BOX-SELECT\t");
                dsync_proxy_mailbox_guid_export(str, mailbox);
                if (cache_fields != NULL)
-                       dsync_proxy_strings_export(str, cache_fields);
+                       dsync_proxy_cache_fields_export(str, cache_fields);
                str_append_c(str, '\n');
                proxy_client_worker_cmd(worker, str);
        } T_END;
index f1549a9e92db428acdd5acfe3c95a000155301bf..d090778796f7eb9eaceadb72c4bbbfd5dc31df04 100644 (file)
@@ -315,7 +315,7 @@ static int
 cmd_box_select(struct dsync_proxy_server *server, const char *const *args)
 {
        struct dsync_mailbox box;
-       unsigned int i, count;
+       const char *error;
 
        memset(&box, 0, sizeof(box));
        if (args[0] == NULL ||
@@ -325,10 +325,11 @@ cmd_box_select(struct dsync_proxy_server *server, const char *const *args)
        }
        args++;
 
-       count = str_array_length(args);
-       t_array_init(&box.cache_fields, count + 1);
-       for (i = 0; i < count; i++)
-               array_append(&box.cache_fields, &args[i], 1);
+       if (dsync_proxy_cache_fields_import(args, pool_datastack_create(),
+                                           &box.cache_fields, &error) < 0) {
+               i_error("box-select: %s", error);
+               return -1;
+       }
        dsync_worker_select_mailbox(server->worker, &box);
        return 1;
 }
index bab578c0f4957234d2ddfb633da3549d4c0f7081..a2535accd8c3ecda31acf2ce9266d4a42adf0246 100644 (file)
 #include "hex-binary.h"
 #include "mail-types.h"
 #include "imap-util.h"
+#include "mail-cache.h"
 #include "dsync-data.h"
 #include "dsync-proxy.h"
 
 #include <stdlib.h>
 
-void dsync_proxy_strings_export(string_t *str,
-                               const ARRAY_TYPE(const_string) *strings)
+#define DSYNC_CACHE_DECISION_NO 'n'
+#define DSYNC_CACHE_DECISION_YES 'y'
+#define DSYNC_CACHE_DECISION_TEMP 't'
+#define DSYNC_CACHE_DECISION_FORCED 'f'
+
+void dsync_proxy_cache_fields_export(string_t *str,
+                                    const ARRAY_TYPE(mailbox_cache_field) *_fields)
 {
-       const char *const *fields;
+       const struct mailbox_cache_field *fields;
        unsigned int i, count;
 
-       if (!array_is_created(strings))
+       if (!array_is_created(_fields))
                return;
 
-       fields = array_get(strings, &count);
+       fields = array_get(_fields, &count);
        for (i = 0; i < count; i++) {
                str_append_c(str, '\t');
-               str_tabescape_write(str, fields[i]);
+               str_tabescape_write(str, fields[i].name);
+               str_append_c(str, '\t');
+               switch (fields[i].decision & ~MAIL_CACHE_DECISION_FORCED) {
+               case MAIL_CACHE_DECISION_NO:
+                       str_append_c(str, DSYNC_CACHE_DECISION_NO);
+                       break;
+               case MAIL_CACHE_DECISION_YES:
+                       str_append_c(str, DSYNC_CACHE_DECISION_YES);
+                       break;
+               case MAIL_CACHE_DECISION_TEMP:
+                       str_append_c(str, DSYNC_CACHE_DECISION_TEMP);
+                       break;
+               }
+               if ((fields[i].decision & MAIL_CACHE_DECISION_FORCED) != 0)
+                       str_append_c(str, DSYNC_CACHE_DECISION_FORCED);
+               str_printfa(str, "\t%ld", fields[i].last_used);
+       }
+}
+
+static int dsync_proxy_cache_dec_parse(const char *str,
+                                      enum mail_cache_decision_type *dec_r)
+{
+       switch (*str++) {
+       case DSYNC_CACHE_DECISION_NO:
+               *dec_r = MAIL_CACHE_DECISION_NO;
+               break;
+       case DSYNC_CACHE_DECISION_YES:
+               *dec_r = MAIL_CACHE_DECISION_YES;
+               break;
+       case DSYNC_CACHE_DECISION_TEMP:
+               *dec_r = MAIL_CACHE_DECISION_TEMP;
+               break;
+       default:
+               return -1;
+       }
+       if (*str == DSYNC_CACHE_DECISION_FORCED) {
+               *dec_r |= MAIL_CACHE_DECISION_FORCED;
+               str++;
+       }
+       if (*str != '\0')
+               return -1;
+       return 0;
+}
+
+int dsync_proxy_cache_fields_import(const char *const *args, pool_t pool,
+                                   ARRAY_TYPE(mailbox_cache_field) *fields,
+                                   const char **error_r)
+{
+       struct mailbox_cache_field *cache_field;
+       enum mail_cache_decision_type dec;
+       unsigned int i, count = str_array_length(args);
+
+       if (count % 3 != 0) {
+               *error_r = "Invalid mailbox cache fields";
+               return -1;
+       }
+       if (!array_is_created(fields))
+               p_array_init(fields, pool, (count/3) + 1);
+       for (i = 0; i < count; i += 3) {
+               cache_field = array_append_space(fields);
+               cache_field->name = p_strdup(pool, args[i]);
+
+               if (dsync_proxy_cache_dec_parse(args[i+1], &dec) < 0) {
+                       *error_r = "Invalid cache decision";
+                       return -1;
+               }
+               cache_field->decision = dec;
+               if (str_to_time(args[i+2], &cache_field->last_used) < 0) {
+                       *error_r = "Invalid cache last_used";
+                       return -1;
+               }
        }
+       return 0;
 }
 
 void dsync_proxy_msg_export(string_t *str,
@@ -178,7 +255,7 @@ void dsync_proxy_mailbox_export(string_t *str,
                    box->uid_validity, box->uid_next, box->message_count,
                    (unsigned long long)box->highest_modseq,
                    box->first_recent_uid);
-       dsync_proxy_strings_export(str, &box->cache_fields);
+       dsync_proxy_cache_fields_export(str, &box->cache_fields);
 }
 
 int dsync_proxy_mailbox_import_unescaped(pool_t pool, const char *const *args,
@@ -270,11 +347,9 @@ int dsync_proxy_mailbox_import_unescaped(pool_t pool, const char *const *args,
 
        args += i;
        count -= i;
-       p_array_init(&box_r->cache_fields, pool, count + 1);
-       for (i = 0; i < count; i++) {
-               const char *field_name = p_strdup(pool, args[i]);
-               array_append(&box_r->cache_fields, &field_name, 1);
-       }
+       if (dsync_proxy_cache_fields_import(args, pool, &box_r->cache_fields,
+                                           error_r) < 0)
+               return -1;
        return 0;
 }
 
index 063a9f3369312fcb45694d1b8d0aec80e52fb97b..b4ea94b520a1ac373158e200cd8bc1f5458f1165 100644 (file)
@@ -6,14 +6,17 @@
 #define DSYNC_PROXY_CLIENT_TIMEOUT_MSECS (14*60*1000)
 #define DSYNC_PROXY_SERVER_TIMEOUT_MSECS (15*60*1000)
 
-#define DSYNC_PROXY_CLIENT_GREETING_LINE "dsync-client\t1"
-#define DSYNC_PROXY_SERVER_GREETING_LINE "dsync-server\t1"
+#define DSYNC_PROXY_CLIENT_GREETING_LINE "dsync-client\t2"
+#define DSYNC_PROXY_SERVER_GREETING_LINE "dsync-server\t2"
 
 struct dsync_message;
 struct dsync_mailbox;
 
-void dsync_proxy_strings_export(string_t *str,
-                               const ARRAY_TYPE(const_string) *strings);
+void dsync_proxy_cache_fields_export(string_t *str,
+                                    const ARRAY_TYPE(mailbox_cache_field) *fields);
+int dsync_proxy_cache_fields_import(const char *const *args, pool_t pool,
+                                   ARRAY_TYPE(mailbox_cache_field) *fields,
+                                   const char **error_r);
 
 void dsync_proxy_msg_export(string_t *str, const struct dsync_message *msg);
 int dsync_proxy_msg_parse_flags(pool_t pool, const char *str,
index c61ed505d0942d7fab71b7c935f6400d8ac4e62c..7c642f2dd6b59704f1be4eac76b4135f4ad87b56 100644 (file)
@@ -528,8 +528,8 @@ local_worker_mailbox_iter_next(struct dsync_worker_mailbox_iter *_iter,
        struct local_dsync_dir_change *dir_change, change_lookup;
        struct local_dsync_mailbox *old_lbox;
        enum mail_error error;
-       const char *const *fields;
-       unsigned int i, field_count;
+       struct mailbox_cache_field *cache_fields;
+       unsigned int i, cache_field_count;
 
        memset(dsync_box_r, 0, sizeof(*dsync_box_r));
 
@@ -595,12 +595,14 @@ local_worker_mailbox_iter_next(struct dsync_worker_mailbox_iter *_iter,
        dsync_box_r->highest_modseq = status.highest_modseq;
 
        p_clear(iter->ret_pool);
-       fields = array_get(metadata.cache_fields, &field_count);
-       p_array_init(&dsync_box_r->cache_fields, iter->ret_pool, field_count);
-       for (i = 0; i < field_count; i++) {
-               const char *field_name = p_strdup(iter->ret_pool, fields[i]);
-
-               array_append(&dsync_box_r->cache_fields, &field_name, 1);
+       p_array_init(&dsync_box_r->cache_fields, iter->ret_pool,
+                    array_count(metadata.cache_fields));
+       array_append_array(&dsync_box_r->cache_fields, metadata.cache_fields);
+       cache_fields = array_get_modifiable(&dsync_box_r->cache_fields,
+                                           &cache_field_count);
+       for (i = 0; i < cache_field_count; i++) {
+               cache_fields[i].name =
+                       p_strdup(iter->ret_pool, cache_fields[i].name);
        }
 
        old_lbox = hash_table_lookup(worker->mailbox_hash,
@@ -1443,25 +1445,26 @@ local_worker_update_mailbox(struct dsync_worker *_worker,
 
 static void
 local_worker_set_cache_fields(struct local_dsync_worker *worker,
-                             const ARRAY_TYPE(const_string) *cache_fields)
+                             const ARRAY_TYPE(mailbox_cache_field) *cache_fields)
 {
        struct mailbox_update update;
-       const char *const *fields, **new_fields;
+       const struct mailbox_cache_field *fields;
+       struct mailbox_cache_field *new_fields;
        unsigned int count;
 
        fields = array_get(cache_fields, &count);
-       new_fields = t_new(const char *, count + 1);
-       memcpy(new_fields, fields, sizeof(const char *) * count);
+       new_fields = t_new(struct mailbox_cache_field, count + 1);
+       memcpy(new_fields, fields, sizeof(struct mailbox_cache_field) * count);
 
        memset(&update, 0, sizeof(update));
-       update.cache_fields = new_fields;
+       update.cache_updates = new_fields;
        mailbox_update(worker->selected_box, &update);
 }
 
 static void
 local_worker_select_mailbox(struct dsync_worker *_worker,
                            const mailbox_guid_t *mailbox,
-                           const ARRAY_TYPE(const_string) *cache_fields)
+                           const ARRAY_TYPE(mailbox_cache_field) *cache_fields)
 {
        struct local_dsync_worker *worker =
                (struct local_dsync_worker *)_worker;
index 6cf1a05b3809ca25b52a20d75c993d44e5e4763a..a5cd65f56b2ac38dca79006616e2a50aa4735734 100644 (file)
@@ -50,7 +50,7 @@ struct dsync_worker_vfuncs {
 
        void (*select_mailbox)(struct dsync_worker *worker,
                               const mailbox_guid_t *mailbox,
-                              const ARRAY_TYPE(const_string) *cache_fields);
+                              const ARRAY_TYPE(mailbox_cache_field) *cache_fields);
        void (*msg_update_metadata)(struct dsync_worker *worker,
                                    const struct dsync_message *msg);
        void (*msg_update_uid)(struct dsync_worker *worker,
index 9f28d7661598e13d3ca5e989e076916fda6bb4c6..ee0fb6c722d1d584d16709ae9900e1fa5f321ee2 100644 (file)
@@ -44,7 +44,7 @@ bool dsync_messages_equal(const struct dsync_message *m1,
 bool dsync_mailboxes_equal(const struct dsync_mailbox *box1,
                           const struct dsync_mailbox *box2)
 {
-       const char *const *f1 = NULL, *const *f2 = NULL;
+       const struct mailbox_cache_field *f1 = NULL, *f2 = NULL;
        unsigned int i, f1_count = 0, f2_count = 0;
 
        if (strcmp(box1->name, box2->name) != 0 ||
@@ -63,7 +63,9 @@ bool dsync_mailboxes_equal(const struct dsync_mailbox *box1,
        if (f1_count != f2_count)
                return FALSE;
        for (i = 0; i < f1_count; i++) {
-               if (strcmp(f1[i], f2[i]) != 0)
+               if (strcmp(f1[i].name, f2[i].name) != 0 ||
+                   f1[i].decision != f2[i].decision ||
+                   f1[i].last_used != f2[i].last_used)
                        return FALSE;
        }
        return TRUE;
index 8dc4e06db91ddad0a81b3304927533d5cff29db6..6759fb43e61d6517c1497cac5e1b384da2ba6c8e 100644 (file)
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "array.h"
 #include "str.h"
+#include "mail-cache.h"
 #include "dsync-proxy.h"
 #include "test-dsync-common.h"
 #include "test-common.h"
@@ -85,8 +86,10 @@ static void test_dsync_proxy_msg(void)
 
 static void test_dsync_proxy_mailbox(void)
 {
-       static const char *cache1 = "cache1";
-       static const char *cache2 = "cache2";
+       static struct mailbox_cache_field cache1 =
+               { "cache1", MAIL_CACHE_DECISION_NO, 1234 };
+       static struct mailbox_cache_field cache2 =
+               { "cache2", MAIL_CACHE_DECISION_TEMP | MAIL_CACHE_DECISION_FORCED, 0 };
        string_t *str;
        struct dsync_mailbox box_in, box_out;
        const char *error;
index e7026cdb164d2fb91dd95768a5f143388ed747ce..363738e4d7f5817920911c3e1d0efa6b09b3441d 100644 (file)
@@ -285,7 +285,7 @@ test_worker_update_mailbox(struct dsync_worker *_worker,
 static void
 test_worker_select_mailbox(struct dsync_worker *_worker,
                           const mailbox_guid_t *mailbox,
-                          const ARRAY_TYPE(const_string) *cache_fields)
+                          const ARRAY_TYPE(mailbox_cache_field) *cache_fields)
 {
        struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker;
        struct dsync_mailbox box;
index f2ce6bf0a061950ff5f0f1ca203203cea1ac72f9..c313552c3fba7383e0d687717328897762f9ceca 100644 (file)
@@ -83,7 +83,7 @@ struct test_dsync_worker {
        mailbox_guid_t selected_mailbox;
        mailbox_guid_t *msg_iter_mailboxes;
        unsigned int msg_iter_mailbox_count;
-       const ARRAY_TYPE(const_string) *cache_fields;
+       const ARRAY_TYPE(mailbox_cache_field) *cache_fields;
 };
 
 struct dsync_worker *dsync_worker_init_test(void);
index cd529646618b25356ec3b9c8e1beff9208845c3c..fa4b2e3116caf8c5662a309d7b759ba4c01fdae8 100644 (file)
@@ -401,8 +401,8 @@ mdbox_mailbox_update(struct mailbox *box, const struct mailbox_update *update)
                if (mailbox_open(box) < 0)
                        return -1;
        }
-       if (update->cache_fields != NULL)
-               index_storage_mailbox_update_cache_fields(box, update);
+       if (update->cache_updates != NULL)
+               index_storage_mailbox_update_cache(box, update);
        return mdbox_write_index_header(box, update, NULL);
 }
 
index bc57af6c342cc32133f3ea58cf19f075656b5583..4600f8e7385f28f503ebfd05aeec8e9e6d293cf7 100644 (file)
@@ -287,8 +287,8 @@ dbox_mailbox_update(struct mailbox *box, const struct mailbox_update *update)
                if (mailbox_open(box) < 0)
                        return -1;
        }
-       if (update->cache_fields != NULL)
-               index_storage_mailbox_update_cache_fields(box, update);
+       if (update->cache_updates != NULL)
+               index_storage_mailbox_update_cache(box, update);
        return sdbox_mailbox_create_indexes(box, update, NULL);
 }
 
index 48ad258d3f82b03add8676cfd8d45479d417fb87..8871ca0bef0f137c417ce2b13d3008394aff2220 100644 (file)
@@ -94,18 +94,23 @@ get_metadata_cache_fields(struct mailbox *box,
 {
        const struct mail_cache_field *fields;
        enum mail_cache_decision_type dec;
-       ARRAY_TYPE(const_string) *cache_fields;
+       ARRAY_TYPE(mailbox_cache_field) *cache_fields;
+       struct mailbox_cache_field *cf;
        unsigned int i, count;
 
        fields = mail_cache_register_get_list(box->cache,
                                              pool_datastack_create(), &count);
 
-       cache_fields = t_new(ARRAY_TYPE(const_string), 1);
+       cache_fields = t_new(ARRAY_TYPE(mailbox_cache_field), 1);
        t_array_init(cache_fields, 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);
+               if (dec != MAIL_CACHE_DECISION_NO) {
+                       cf = array_append_space(cache_fields);
+                       cf->name = fields[i].name;
+                       cf->decision = fields[i].decision;
+                       cf->last_used = fields[i].last_used;
+               }
        }
        metadata_r->cache_fields = cache_fields;
 }
index 9b55c9e478394a3c2cdfc416fe985289a9532571..77000cc723a7154e20a1eaeaee87d041965066e0 100644 (file)
@@ -353,10 +353,10 @@ void index_storage_mailbox_free(struct mailbox *box)
                mail_index_alloc_cache_unref(&box->index);
 }
 
-void index_storage_mailbox_update_cache_fields(struct mailbox *box,
-                                              const struct mailbox_update *update)
+void index_storage_mailbox_update_cache(struct mailbox *box,
+                                       const struct mailbox_update *update)
 {
-       const char *const *field_names = update->cache_fields;
+       const struct mailbox_cache_field *updates = update->cache_updates;
        ARRAY_DEFINE(new_fields, struct mail_cache_field);
        const struct mail_cache_field *old_fields;
        struct mail_cache_field field;
@@ -368,28 +368,28 @@ void index_storage_mailbox_update_cache_fields(struct mailbox *box,
 
        /* 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++) {
+       for (i = 0; updates[i].name != 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)
+                       if (strcmp(updates[i].name, old_fields[j].name) == 0)
                                break;
                }
                if (j != old_count) {
                        field = old_fields[j];
-                       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) {
+               } else if (strncmp(updates[i].name, "hdr.", 4) == 0) {
                        /* new header */
                        memset(&field, 0, sizeof(field));
-                       field.name = field_names[i];
+                       field.name = updates[i].name;
                        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 */
+                       continue;
                }
+               field.decision = updates[i].decision;
+               if (updates[i].last_used != (time_t)-1)
+                       field.last_used = updates[i].last_used;
+               array_append(&new_fields, &field, 1);
        }
        if (array_count(&new_fields) > 0) {
                mail_cache_register_fields(box->cache,
@@ -408,8 +408,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(box, update);
+       if (update->cache_updates != NULL)
+               index_storage_mailbox_update_cache(box, update);
 
        /* make sure we get the latest index info */
        (void)mail_index_refresh(box->index);
@@ -641,7 +641,7 @@ void index_copy_cache_fields(struct mail_save_context *ctx,
 {
        T_BEGIN {
                struct mailbox_metadata src_metadata;
-               const char *const *namep;
+               const struct mailbox_cache_field *field;
                buffer_t *buf;
 
                if (mailbox_get_metadata(src_mail->box,
@@ -650,9 +650,9 @@ void index_copy_cache_fields(struct mail_save_context *ctx,
                        i_unreached();
 
                buf = buffer_create_dynamic(pool_datastack_create(), 1024);
-               array_foreach(src_metadata.cache_fields, namep) {
+               array_foreach(src_metadata.cache_fields, field) {
                        mail_copy_cache_field(ctx, src_mail, dest_seq,
-                                             *namep, buf);
+                                             field->name, buf);
                }
        } T_END;
 }
index 2e4a38eb162e2811f6bc902d0403d25eb10524d4..eb7106fed49a3e256da8d02ee638f30a41256152 100644 (file)
@@ -69,8 +69,8 @@ void index_storage_mailbox_close(struct mailbox *box);
 void index_storage_mailbox_free(struct mailbox *box);
 int index_storage_mailbox_update(struct mailbox *box,
                                 const struct mailbox_update *update);
-void index_storage_mailbox_update_cache_fields(struct mailbox *box,
-                                              const struct mailbox_update *update);
+void index_storage_mailbox_update_cache(struct mailbox *box,
+                                       const struct mailbox_update *update);
 int index_storage_mailbox_delete(struct mailbox *box);
 int index_storage_mailbox_delete_dir(struct mailbox *box, bool mailbox_deleted);
 int index_storage_mailbox_rename(struct mailbox *src, struct mailbox *dest,
index ae42d19914578eea37cb9d13faa0b9541b0ca6cc..9bf156691b299a2a117e86bc06db6d9fb97d8183 100644 (file)
@@ -225,12 +225,20 @@ struct mailbox_status {
        unsigned int allow_new_keywords:1;
 };
 
+struct mailbox_cache_field {
+       const char *name;
+       int decision; /* enum mail_cache_decision_type */
+       /* last_used is unchanged, if it's (time_t)-1 */
+       time_t last_used;
+};
+ARRAY_DEFINE_TYPE(mailbox_cache_field, struct mailbox_cache_field);
+
 struct mailbox_metadata {
        guid_128_t guid;
        /* sum of virtual size of all messages in mailbox */
        uint64_t virtual_size;
        /* Fields that have "temp" or "yes" caching decision. */
-       const ARRAY_TYPE(const_string) *cache_fields;
+       const ARRAY_TYPE(mailbox_cache_field) *cache_fields;
        /* Fields that should be precached */
        enum mail_fetch_field precache_fields;
 };
@@ -242,8 +250,8 @@ struct mailbox_update {
        uint32_t min_next_uid;
        uint32_t min_first_recent_uid;
        uint64_t min_highest_modseq;
-       /* Add these fields to be temporarily cached, if they aren't already. */
-       const char *const *cache_fields;
+       /* Modify caching decisions, terminated by name=NULL */
+       const struct mailbox_cache_field *cache_updates;
 };
 
 struct mail_transaction_commit_changes {