From 3fe67ec75ccae1230bb9eb9f16affc48377f6441 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Mon, 21 Dec 2009 15:17:08 -0500 Subject: [PATCH] dsync: Write mailbox changelog records using original timestamps. --HG-- branch : HEAD --- src/dsync/dsync-brain.c | 36 ++++++++++++-------- src/dsync/dsync-data.h | 2 +- src/dsync/dsync-proxy-client.c | 12 ++++--- src/dsync/dsync-proxy-server-cmd.c | 16 ++++++--- src/dsync/dsync-proxy.c | 4 +-- src/dsync/dsync-worker-local.c | 44 +++++++++++++++++-------- src/dsync/dsync-worker-private.h | 4 +-- src/dsync/dsync-worker.c | 8 ++--- src/dsync/dsync-worker.h | 5 +-- src/dsync/test-dsync-brain.c | 3 +- src/dsync/test-dsync-proxy-server-cmd.c | 14 ++++---- src/dsync/test-dsync-worker.c | 8 ++--- src/lib-storage/mailbox-list-private.h | 3 +- src/lib-storage/mailbox-list.c | 14 +++++--- src/lib-storage/mailbox-list.h | 7 ++-- 15 files changed, 113 insertions(+), 67 deletions(-) diff --git a/src/dsync/dsync-brain.c b/src/dsync/dsync-brain.c index df9ead81cc..1eb59bf9a7 100644 --- a/src/dsync/dsync-brain.c +++ b/src/dsync/dsync-brain.c @@ -279,13 +279,13 @@ static void dsync_brain_sync_mailboxes(struct dsync_brain *brain) /* delete from dest too */ if (!dest_deleted) { dsync_worker_delete_mailbox(brain->dest_worker, - &dest_boxes[dest]->mailbox_guid); + src_boxes[src]); } src++; dest++; } else if (dest_deleted) { /* delete from src too */ dsync_worker_delete_mailbox(brain->src_worker, - &src_boxes[src]->mailbox_guid); + dest_boxes[dest]); src++; dest++; } else { src++; dest++; @@ -315,7 +315,8 @@ static void dsync_brain_sync_mailboxes(struct dsync_brain *brain) static bool dsync_brain_is_unsubscribed(struct dsync_brain_subs_list *list, - const struct dsync_worker_subscription *subs) + const struct dsync_worker_subscription *subs, + time_t *last_change_r) { const struct dsync_worker_unsubscription *unsubs; struct dsync_worker_unsubscription lookup; @@ -324,16 +325,23 @@ dsync_brain_is_unsubscribed(struct dsync_brain_subs_list *list, dsync_str_sha_to_guid(subs->storage_name, &lookup.name_sha1); unsubs = array_bsearch(&list->unsubscriptions, &lookup, dsync_worker_unsubscription_cmp); - if (unsubs == NULL) + if (unsubs == NULL) { + *last_change_r = 0; return FALSE; - else - return unsubs->last_change > subs->last_change; + } else if (unsubs->last_change <= subs->last_change) { + *last_change_r = subs->last_change; + return FALSE; + } else { + *last_change_r = unsubs->last_change; + return TRUE; + } } static void dsync_brain_sync_subscriptions(struct dsync_brain *brain) { const struct dsync_worker_subscription *src_subs, *dest_subs; unsigned int src, dest, src_count, dest_count; + time_t last_change; int ret; /* subscriptions are sorted by name. */ @@ -358,27 +366,29 @@ static void dsync_brain_sync_subscriptions(struct dsync_brain *brain) if (ret < 0) { /* subscribed only in source */ if (dsync_brain_is_unsubscribed(brain->dest_subs_list, - &src_subs[src])) { + &src_subs[src], + &last_change)) { dsync_worker_set_subscribed(brain->src_worker, src_subs[src].vname, - FALSE); + last_change, FALSE); } else { dsync_worker_set_subscribed(brain->dest_worker, src_subs[src].vname, - TRUE); + last_change, TRUE); } src++; } else { /* subscribed only in dest */ if (dsync_brain_is_unsubscribed(brain->src_subs_list, - &dest_subs[dest])) { + &dest_subs[dest], + &last_change)) { dsync_worker_set_subscribed(brain->dest_worker, dest_subs[dest].vname, - FALSE); + last_change, FALSE); } else { dsync_worker_set_subscribed(brain->src_worker, dest_subs[dest].vname, - TRUE); + last_change, TRUE); } dest++; } @@ -532,7 +542,7 @@ static void dsync_brain_sync_rename_mailbox(struct dsync_brain *brain, const struct dsync_brain_mailbox *mailbox) { - if (mailbox->src->last_renamed > mailbox->dest->last_renamed) { + if (mailbox->src->last_changed > mailbox->dest->last_changed) { dsync_worker_rename_mailbox(brain->dest_worker, &mailbox->box.mailbox_guid, mailbox->src); diff --git a/src/dsync/dsync-data.h b/src/dsync/dsync-data.h index abff6be2d0..f303d51576 100644 --- a/src/dsync/dsync-data.h +++ b/src/dsync/dsync-data.h @@ -24,7 +24,7 @@ struct dsync_mailbox { uint32_t uid_validity, uid_next; uint64_t highest_modseq; - time_t last_renamed; + time_t last_changed; enum dsync_mailbox_flags flags; ARRAY_TYPE(const_string) cache_fields; }; diff --git a/src/dsync/dsync-proxy-client.c b/src/dsync/dsync-proxy-client.c index b9012b4dd4..11319dc6c9 100644 --- a/src/dsync/dsync-proxy-client.c +++ b/src/dsync/dsync-proxy-client.c @@ -545,7 +545,8 @@ proxy_client_worker_subs_iter_deinit(struct dsync_worker_subs_iter *_iter) static void proxy_client_worker_set_subscribed(struct dsync_worker *_worker, - const char *name, bool set) + const char *name, time_t last_change, + bool set) { struct proxy_client_dsync_worker *worker = (struct proxy_client_dsync_worker *)_worker; @@ -555,7 +556,8 @@ proxy_client_worker_set_subscribed(struct dsync_worker *_worker, str_append(str, "SUBS-SET\t"); str_tabescape_write(str, name); - str_printfa(str, "\t%d\n", set ? 1 : 0); + str_printfa(str, "\t%s\t%d\n", dec2str(last_change), + set ? 1 : 0); o_stream_send(worker->output, str_data(str), str_len(str)); } T_END; } @@ -678,7 +680,7 @@ proxy_client_worker_create_mailbox(struct dsync_worker *_worker, static void proxy_client_worker_delete_mailbox(struct dsync_worker *_worker, - const mailbox_guid_t *mailbox) + const struct dsync_mailbox *dsync_box) { struct proxy_client_dsync_worker *worker = (struct proxy_client_dsync_worker *)_worker; @@ -689,8 +691,8 @@ proxy_client_worker_delete_mailbox(struct dsync_worker *_worker, string_t *str = t_str_new(128); str_append(str, "BOX-DELETE\t"); - dsync_proxy_mailbox_guid_export(str, mailbox); - str_append_c(str, '\n'); + dsync_proxy_mailbox_guid_export(str, &dsync_box->mailbox_guid); + str_printfa(str, "\t%s\n", dec2str(dsync_box->last_changed)); o_stream_send(worker->output, str_data(str), str_len(str)); } T_END; } diff --git a/src/dsync/dsync-proxy-server-cmd.c b/src/dsync/dsync-proxy-server-cmd.c index 47260ded6a..879628f713 100644 --- a/src/dsync/dsync-proxy-server-cmd.c +++ b/src/dsync/dsync-proxy-server-cmd.c @@ -151,13 +151,14 @@ cmd_subs_list(struct dsync_proxy_server *server, static int cmd_subs_set(struct dsync_proxy_server *server, const char *const *args) { - if (args[0] == NULL || args[1] == NULL) { + if (str_array_length(args) < 3) { i_error("subs-set: Missing parameters"); return -1; } dsync_worker_set_subscribed(server->worker, args[0], - strcmp(args[1], "1") == 0); + strtoul(args[1], NULL, 10), + strcmp(args[2], "1") == 0); return 1; } @@ -244,14 +245,19 @@ static int cmd_box_delete(struct dsync_proxy_server *server, const char *const *args) { mailbox_guid_t guid; + struct dsync_mailbox dsync_box; - if (args[0] == NULL || - dsync_proxy_mailbox_guid_import(args[0], &guid) < 0) { + if (str_array_length(args) < 2) + return -1; + if (dsync_proxy_mailbox_guid_import(args[0], &guid) < 0) { i_error("box-delete: Invalid mailbox GUID '%s'", args[0]); return -1; } - dsync_worker_delete_mailbox(server->worker, &guid); + memset(&dsync_box, 0, sizeof(dsync_box)); + dsync_box.mailbox_guid = guid; + dsync_box.last_changed = strtoul(args[1], NULL, 10); + dsync_worker_delete_mailbox(server->worker, &dsync_box); return 1; } diff --git a/src/dsync/dsync-proxy.c b/src/dsync/dsync-proxy.c index ee644e56d9..1c9c804b64 100644 --- a/src/dsync/dsync-proxy.c +++ b/src/dsync/dsync-proxy.c @@ -163,7 +163,7 @@ void dsync_proxy_mailbox_export(string_t *str, str_tabescape_write(str, s); str_append_c(str, '\t'); dsync_proxy_mailbox_guid_export(str, &box->dir_guid); - str_printfa(str, "\t%lu\t%u", (unsigned long)box->last_renamed, + str_printfa(str, "\t%lu\t%u", (unsigned long)box->last_changed, box->flags); if (mail_guid_128_is_empty(box->mailbox_guid.guid)) { @@ -207,7 +207,7 @@ int dsync_proxy_mailbox_import_unescaped(pool_t pool, const char *const *args, *error_r = "Invalid dir GUID"; return -1; } - box_r->last_renamed = strtoul(args[i++], &p, 10); + box_r->last_changed = strtoul(args[i++], &p, 10); if (*p != '\0') { *error_r = "Invalid mailbox last_renamed"; return -1; diff --git a/src/dsync/dsync-worker-local.c b/src/dsync/dsync-worker-local.c index 54a1f26053..5414c71e7d 100644 --- a/src/dsync/dsync-worker-local.c +++ b/src/dsync/dsync-worker-local.c @@ -51,6 +51,7 @@ struct local_dsync_mailbox { struct local_dsync_mailbox_change { mailbox_guid_t guid; time_t last_renamed; + time_t last_deleted; unsigned int deleted_mailbox:1; unsigned int deleted_dir:1; }; @@ -126,15 +127,8 @@ struct dsync_worker * dsync_worker_init_local(struct mail_user *user, char alt_char) { struct local_dsync_worker *worker; - struct mail_namespace *ns; pool_t pool; - /* whatever we do, we do it because we're trying to sync, - not because of a user action. don't log these mailbox list changes - so we don't do wrong decisions on future syncs. */ - for (ns = user->namespaces; ns != NULL; ns = ns->next) - mailbox_list_set_changelog_writable(ns->list, FALSE); - pool = pool_alloconly_create("local dsync worker", 10240); worker = p_new(pool, struct local_dsync_worker, 1); worker->worker.v = local_dsync_worker; @@ -181,6 +175,7 @@ dsync_worker_save_mailbox_change(struct local_dsync_worker *worker, const struct mailbox_log_record *rec) { struct local_dsync_mailbox_change *change; + time_t stamp; change = hash_table_lookup(worker->mailbox_changes_hash, rec->mailbox_guid); @@ -191,16 +186,20 @@ dsync_worker_save_mailbox_change(struct local_dsync_worker *worker, hash_table_insert(worker->mailbox_changes_hash, change->guid.guid, change); } + + stamp = mailbox_log_record_get_timestamp(rec); switch (rec->type) { case MAILBOX_LOG_RECORD_DELETE_MAILBOX: change->deleted_mailbox = TRUE; + if (change->last_deleted < stamp) + change->last_deleted = stamp; break; case MAILBOX_LOG_RECORD_DELETE_DIR: change->deleted_dir = TRUE; break; case MAILBOX_LOG_RECORD_RENAME: - change->last_renamed = - mailbox_log_record_get_timestamp(rec); + if (change->last_renamed < stamp) + change->last_renamed = stamp; break; case MAILBOX_LOG_RECORD_SUBSCRIBE: case MAILBOX_LOG_RECORD_UNSUBSCRIBE: @@ -220,12 +219,14 @@ dsync_worker_save_subscription_change(struct local_dsync_worker *worker, const struct mailbox_log_record *rec) { struct local_dsync_subscription_change *change, new_change; + time_t stamp; memset(&new_change, 0, sizeof(new_change)); new_change.list = list; memcpy(new_change.name_sha1.guid, rec->mailbox_guid, sizeof(new_change.name_sha1.guid)); + stamp = mailbox_log_record_get_timestamp(rec); change = hash_table_lookup(worker->subscription_changes_hash, &new_change); if (change == NULL) { @@ -233,7 +234,13 @@ dsync_worker_save_subscription_change(struct local_dsync_worker *worker, *change = new_change; hash_table_insert(worker->subscription_changes_hash, change, change); + } else if (change->last_change > stamp) { + /* we've already seen a newer subscriptions state. this is + probably a stale record created by dsync */ + return; } + change->last_change = stamp; + switch (rec->type) { case MAILBOX_LOG_RECORD_DELETE_MAILBOX: case MAILBOX_LOG_RECORD_DELETE_DIR: @@ -246,7 +253,6 @@ dsync_worker_save_subscription_change(struct local_dsync_worker *worker, change->unsubscribed = TRUE; break; } - change->last_change = mailbox_log_record_get_timestamp(rec); } static int @@ -391,6 +397,7 @@ iter_next_deleted(struct local_dsync_worker_mailbox_iter *iter, /* the name doesn't matter */ dsync_box_r->name = ""; dsync_box_r->mailbox_guid = change->guid; + dsync_box_r->last_changed = change->last_deleted; dsync_box_r->flags |= DSYNC_MAILBOX_FLAG_DELETED_MAILBOX; return 1; @@ -399,6 +406,7 @@ iter_next_deleted(struct local_dsync_worker_mailbox_iter *iter, /* the name doesn't matter */ dsync_box_r->name = ""; dsync_box_r->dir_guid = change->guid; + dsync_box_r->last_changed = change->last_deleted; dsync_box_r->flags |= DSYNC_MAILBOX_FLAG_DELETED_DIR; return 1; } @@ -442,13 +450,13 @@ local_worker_mailbox_iter_next(struct dsync_worker_mailbox_iter *_iter, return -1; } - /* get last rename timestamp */ + /* get last change timestamp */ change = hash_table_lookup(worker->mailbox_changes_hash, dsync_box_r->dir_guid.guid); if (change != NULL) { /* it shouldn't be marked as deleted, but drop it to be sure */ change->deleted_dir = FALSE; - dsync_box_r->last_renamed = change->last_renamed; + dsync_box_r->last_changed = change->last_renamed; } storage_name = mail_namespace_get_storage_name(info->ns, info->name); @@ -615,7 +623,7 @@ local_worker_subs_iter_deinit(struct dsync_worker_subs_iter *_iter) static void local_worker_set_subscribed(struct dsync_worker *_worker, - const char *name, bool set) + const char *name, time_t last_change, bool set) { struct local_dsync_worker *worker = (struct local_dsync_worker *)_worker; @@ -629,11 +637,13 @@ local_worker_set_subscribed(struct dsync_worker *_worker, return; } + mailbox_list_set_changelog_timestamp(ns->list, last_change); if (mailbox_list_set_subscribed(ns->list, storage_name, set) < 0) { dsync_worker_set_failure(_worker); i_error("Can't update subscription %s: %s", name, mailbox_list_get_last_error(ns->list, NULL)); } + mailbox_list_set_changelog_timestamp(ns->list, (time_t)-1); } static int local_mailbox_open(struct local_dsync_worker *worker, @@ -1010,11 +1020,12 @@ local_worker_create_mailbox(struct dsync_worker *_worker, static void local_worker_delete_mailbox(struct dsync_worker *_worker, - const mailbox_guid_t *mailbox) + const struct dsync_mailbox *dsync_box) { struct local_dsync_worker *worker = (struct local_dsync_worker *)_worker; struct local_dsync_mailbox *lbox; + const mailbox_guid_t *mailbox = &dsync_box->mailbox_guid; lbox = hash_table_lookup(worker->mailbox_hash, mailbox); if (lbox == NULL) { @@ -1024,12 +1035,15 @@ local_worker_delete_mailbox(struct dsync_worker *_worker, return; } + mailbox_list_set_changelog_timestamp(lbox->ns->list, + dsync_box->last_changed); if (mailbox_list_delete_mailbox(lbox->ns->list, lbox->storage_name) < 0) { i_error("Can't delete mailbox %s: %s", lbox->storage_name, mailbox_list_get_last_error(lbox->ns->list, NULL)); dsync_worker_set_failure(_worker); } + mailbox_list_set_changelog_timestamp(lbox->ns->list, (time_t)-1); } static void @@ -1086,6 +1100,7 @@ local_worker_rename_mailbox(struct dsync_worker *_worker, return; } + mailbox_list_set_changelog_timestamp(list, dsync_box->last_changed); if (mailbox_list_rename_mailbox(list, lbox->storage_name, list, newname, TRUE) < 0) { i_error("Can't rename mailbox %s to %s: %s", lbox->storage_name, @@ -1097,6 +1112,7 @@ local_worker_rename_mailbox(struct dsync_worker *_worker, local_worker_rename_children(worker, oldname, newname, lbox->ns->sep); } + mailbox_list_set_changelog_timestamp(list, (time_t)-1); } static bool diff --git a/src/dsync/dsync-worker-private.h b/src/dsync/dsync-worker-private.h index caa58fb874..faa2c3b768 100644 --- a/src/dsync/dsync-worker-private.h +++ b/src/dsync/dsync-worker-private.h @@ -25,7 +25,7 @@ struct dsync_worker_vfuncs { struct dsync_worker_unsubscription *rec_r); int (*subs_iter_deinit)(struct dsync_worker_subs_iter *iter); void (*set_subscribed)(struct dsync_worker *worker, - const char *name, bool set); + const char *name, time_t last_change, bool set); struct dsync_worker_msg_iter * (*msg_iter_init)(struct dsync_worker *worker, @@ -39,7 +39,7 @@ struct dsync_worker_vfuncs { void (*create_mailbox)(struct dsync_worker *worker, const struct dsync_mailbox *dsync_box); void (*delete_mailbox)(struct dsync_worker *worker, - const mailbox_guid_t *mailbox); + const struct dsync_mailbox *dsync_box); void (*rename_mailbox)(struct dsync_worker *worker, const mailbox_guid_t *mailbox, const struct dsync_mailbox *dsync_box); diff --git a/src/dsync/dsync-worker.c b/src/dsync/dsync-worker.c index 90dea7968f..c528a5d896 100644 --- a/src/dsync/dsync-worker.c +++ b/src/dsync/dsync-worker.c @@ -88,9 +88,9 @@ int dsync_worker_subs_iter_deinit(struct dsync_worker_subs_iter **_iter) } void dsync_worker_set_subscribed(struct dsync_worker *worker, - const char *name, bool set) + const char *name, time_t last_change, bool set) { - worker->v.set_subscribed(worker, name, set); + worker->v.set_subscribed(worker, name, last_change, set); } struct dsync_worker_msg_iter * @@ -132,10 +132,10 @@ void dsync_worker_create_mailbox(struct dsync_worker *worker, } void dsync_worker_delete_mailbox(struct dsync_worker *worker, - const mailbox_guid_t *mailbox) + const struct dsync_mailbox *dsync_box) { if (!worker->readonly) - worker->v.delete_mailbox(worker, mailbox); + worker->v.delete_mailbox(worker, dsync_box); } void dsync_worker_rename_mailbox(struct dsync_worker *worker, diff --git a/src/dsync/dsync-worker.h b/src/dsync/dsync-worker.h index 8add5e953b..cd5717483e 100644 --- a/src/dsync/dsync-worker.h +++ b/src/dsync/dsync-worker.h @@ -75,7 +75,8 @@ int dsync_worker_subs_iter_next_un(struct dsync_worker_subs_iter *iter, int dsync_worker_subs_iter_deinit(struct dsync_worker_subs_iter **iter); /* Subscribe/unsubscribe mailbox */ void dsync_worker_set_subscribed(struct dsync_worker *worker, - const char *name, bool set); + const char *name, time_t last_change, + bool set); /* Iterate through all messages in given mailboxes. The mailboxes are iterated in the given order. */ @@ -99,7 +100,7 @@ void dsync_worker_create_mailbox(struct dsync_worker *worker, const struct dsync_mailbox *dsync_box); /* Delete mailbox/dir with given GUID. */ void dsync_worker_delete_mailbox(struct dsync_worker *worker, - const mailbox_guid_t *mailbox); + const struct dsync_mailbox *dsync_box); /* Change a mailbox and its childrens' name. The name is taken from the given dsync_box (applying name_sep if necessary). */ void dsync_worker_rename_mailbox(struct dsync_worker *worker, diff --git a/src/dsync/test-dsync-brain.c b/src/dsync/test-dsync-brain.c index c8ce958a86..f7a29cfb89 100644 --- a/src/dsync/test-dsync-brain.c +++ b/src/dsync/test-dsync-brain.c @@ -92,7 +92,8 @@ test_dsync_mailbox_delete_equals(const struct dsync_mailbox *dbox, const struct dsync_mailbox *obox) { return memcmp(dbox->mailbox_guid.guid, obox->mailbox_guid.guid, - sizeof(dbox->mailbox_guid.guid)) == 0; + sizeof(dbox->mailbox_guid.guid)) == 0 && + dbox->last_changed == obox->last_changed; } static void diff --git a/src/dsync/test-dsync-proxy-server-cmd.c b/src/dsync/test-dsync-proxy-server-cmd.c index a46624550a..2ceaf09ef1 100644 --- a/src/dsync/test-dsync-proxy-server-cmd.c +++ b/src/dsync/test-dsync-proxy-server-cmd.c @@ -75,7 +75,7 @@ static void test_dsync_proxy_box_list(void) memset(&box, 0, sizeof(box)); box.name = "\t\001\r\nname\t\001\n\r"; box.name_sep = '/'; - box.last_renamed = 992; + box.last_changed = 992; box.flags = 123; memcpy(box.dir_guid.guid, test_mailbox_guid1, MAIL_GUID_128_SIZE); test_worker->box_iter.next_box = &box; @@ -227,7 +227,7 @@ static void test_dsync_proxy_box_create(void) test_assert(strcmp(event.box.name, "noselect") == 0); test_assert(event.box.name_sep == '/'); test_assert(memcmp(event.box.dir_guid.guid, test_mailbox_guid2, MAIL_GUID_128_SIZE) == 0); - test_assert(event.box.last_renamed == 553); + test_assert(event.box.last_changed == 553); test_assert(event.box.flags == 99); test_assert(event.box.uid_validity == 0); @@ -244,7 +244,7 @@ static void test_dsync_proxy_box_create(void) test_assert(event.box.uid_validity == 1234567890); test_assert(event.box.uid_next == 9876); test_assert(event.box.highest_modseq == 28427847284728); - test_assert(event.box.last_renamed == 61); + test_assert(event.box.last_changed == 61); test_end(); } @@ -255,15 +255,17 @@ static void test_dsync_proxy_box_delete(void) test_begin("proxy server box delete"); - test_assert(run_cmd("BOX-DELETE", TEST_MAILBOX_GUID1, NULL) == 1); + test_assert(run_cmd("BOX-DELETE", TEST_MAILBOX_GUID1, "4351", NULL) == 1); test_assert(test_dsync_worker_next_box_event(test_worker, &event)); test_assert(event.type == LAST_BOX_TYPE_DELETE); test_assert(memcmp(event.box.mailbox_guid.guid, test_mailbox_guid1, MAIL_GUID_128_SIZE) == 0); + test_assert(event.box.last_changed == 4351); - test_assert(run_cmd("BOX-DELETE", TEST_MAILBOX_GUID2, NULL) == 1); + test_assert(run_cmd("BOX-DELETE", TEST_MAILBOX_GUID2, "653", NULL) == 1); test_assert(test_dsync_worker_next_box_event(test_worker, &event)); test_assert(event.type == LAST_BOX_TYPE_DELETE); test_assert(memcmp(event.box.mailbox_guid.guid, test_mailbox_guid2, MAIL_GUID_128_SIZE) == 0); + test_assert(event.box.last_changed == 653); test_end(); } @@ -310,7 +312,7 @@ static void test_dsync_proxy_box_update(void) test_assert(event.box.uid_validity == 34343); test_assert(event.box.uid_next == 22); test_assert(event.box.highest_modseq == 2238427847284728); - test_assert(event.box.last_renamed == 53); + test_assert(event.box.last_changed == 53); test_end(); } diff --git a/src/dsync/test-dsync-worker.c b/src/dsync/test-dsync-worker.c index a0f1dbfbc7..916791537f 100644 --- a/src/dsync/test-dsync-worker.c +++ b/src/dsync/test-dsync-worker.c @@ -212,12 +212,13 @@ bool test_dsync_worker_next_box_event(struct test_dsync_worker *worker, static void test_worker_set_subscribed(struct dsync_worker *_worker, - const char *name, bool set) + const char *name, time_t last_change, bool set) { struct dsync_mailbox dsync_box; memset(&dsync_box, 0, sizeof(dsync_box)); dsync_box.name = name; + dsync_box.last_changed = last_change; test_worker_set_last_box(_worker, &dsync_box, set ? LAST_BOX_TYPE_SUBSCRIBE : LAST_BOX_TYPE_UNSUBSCRIBE); @@ -232,7 +233,7 @@ test_worker_create_mailbox(struct dsync_worker *_worker, static void test_worker_delete_mailbox(struct dsync_worker *_worker, - const mailbox_guid_t *mailbox) + const struct dsync_mailbox *dsync_box) { struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker; struct test_dsync_box_event event; @@ -240,8 +241,7 @@ test_worker_delete_mailbox(struct dsync_worker *_worker, memset(&event, 0, sizeof(event)); event.type = LAST_BOX_TYPE_DELETE; - event.box.mailbox_guid = *mailbox; - event.box.name = ""; + event.box = *dsync_box; array_append(&worker->box_events, &event, 1); } diff --git a/src/lib-storage/mailbox-list-private.h b/src/lib-storage/mailbox-list-private.h index 8eb47f03e0..fb7107fe8f 100644 --- a/src/lib-storage/mailbox-list-private.h +++ b/src/lib-storage/mailbox-list-private.h @@ -101,14 +101,13 @@ struct mailbox_list { const char *file_create_gid_origin; struct mailbox_log *changelog; + time_t changelog_timestamp; char *error_string; enum mail_error error; bool temporary_error; ARRAY_DEFINE(module_contexts, union mailbox_list_module_context *); - - unsigned int changelog_disabled:1; }; struct mailbox_list_iterate_context { diff --git a/src/lib-storage/mailbox-list.c b/src/lib-storage/mailbox-list.c index 38f64fdcba..cab441bdde 100644 --- a/src/lib-storage/mailbox-list.c +++ b/src/lib-storage/mailbox-list.c @@ -123,6 +123,7 @@ int mailbox_list_create(const char *driver, struct mail_namespace *ns, list->file_create_mode = (mode_t)-1; list->dir_create_mode = (mode_t)-1; list->file_create_gid = (gid_t)-1; + list->changelog_timestamp = (time_t)-1; /* copy settings */ list->set.root_dir = p_strdup(list->pool, set->root_dir); @@ -697,15 +698,19 @@ void mailbox_list_add_change(struct mailbox_list *list, const uint8_t mailbox_guid[MAIL_GUID_128_SIZE]) { struct mailbox_log_record rec; + time_t stamp; - if (!mailbox_list_init_changelog(list) || list->changelog_disabled || + if (!mailbox_list_init_changelog(list) || mail_guid_128_is_empty(mailbox_guid)) return; + stamp = list->changelog_timestamp != (time_t)-1 ? + list->changelog_timestamp : ioloop_time; + memset(&rec, 0, sizeof(rec)); rec.type = type; memcpy(rec.mailbox_guid, mailbox_guid, sizeof(rec.mailbox_guid)); - mailbox_log_record_set_timestamp(&rec, ioloop_time); + mailbox_log_record_set_timestamp(&rec, stamp); (void)mailbox_log_append(list->changelog, &rec); } @@ -916,9 +921,10 @@ struct mailbox_log *mailbox_list_get_changelog(struct mailbox_list *list) return !mailbox_list_init_changelog(list) ? NULL : list->changelog; } -void mailbox_list_set_changelog_writable(struct mailbox_list *list, bool set) +void mailbox_list_set_changelog_timestamp(struct mailbox_list *list, + time_t stamp) { - list->changelog_disabled = !set; + list->changelog_timestamp = stamp; } static int mailbox_list_try_delete(struct mailbox_list *list, const char *dir) diff --git a/src/lib-storage/mailbox-list.h b/src/lib-storage/mailbox-list.h index 5cdacbe249..7f2335759c 100644 --- a/src/lib-storage/mailbox-list.h +++ b/src/lib-storage/mailbox-list.h @@ -194,8 +194,11 @@ int mailbox_list_get_guid(struct mailbox_list *list, const char *name, uint8_t mailbox_guid[MAIL_GUID_128_SIZE]); /* Returns mailbox's change log, or NULL if it doesn't have one. */ struct mailbox_log *mailbox_list_get_changelog(struct mailbox_list *list); -/* Enable/disable writing mailbox changes to changelog. */ -void mailbox_list_set_changelog_writable(struct mailbox_list *list, bool set); +/* Specify timestamp to use when writing mailbox changes to changelog. + The same timestamp is used until stamp is set to (time_t)-1, after which + current time is used */ +void mailbox_list_set_changelog_timestamp(struct mailbox_list *list, + time_t stamp); /* Returns a prefix that temporary files should use without conflicting with the namespace. */ -- 2.47.3