dsync-brain-mailbox.c revision 70058d29cf8c77501741ddbc39178cfc87ca459e
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2013-2014 Dovecot authors, see the included COPYING file */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#include "lib.h"
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#include "array.h"
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen#include "hash.h"
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#include "mail-cache-private.h"
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#include "mail-namespace.h"
e8434aad92ea6ff1c915b708294dbd0c7ff5908dMichael M Slusarz#include "mail-storage-private.h"
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#include "dsync-ibc.h"
de5f478d9e7ae7b8e58082e0b30b6ce1f034236aTimo Sirainen#include "dsync-mailbox-tree.h"
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen#include "dsync-mailbox-import.h"
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen#include "dsync-mailbox-export.h"
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#include "dsync-transaction-log-scan.h"
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen#include "dsync-brain-private.h"
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainenstatic int
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenns_mailbox_try_alloc(struct mail_namespace *ns, const guid_128_t guid,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct mailbox **box_r, const char **error_r)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct mailbox *box;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen enum mailbox_existence existence;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen enum mail_error err;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen int ret;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen box = mailbox_alloc_guid(ns->list, guid, 0);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen ret = mailbox_exists(box, FALSE, &existence);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen if (ret < 0) {
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen *error_r = mailbox_get_last_error(box, &err);
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen mailbox_free(&box);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return -1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen if (existence != MAILBOX_EXISTENCE_SELECT) {
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen mailbox_free(&box);
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen *error_r = existence == MAILBOX_EXISTENCE_NONE ?
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen "Mailbox was already deleted" :
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen "Mailbox is no longer selectable";
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen return 0;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen }
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen *box_r = box;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen return 1;
01aca4a521410be85e1f39e37c662435d052f48aAki Tuomi}
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainenint dsync_brain_mailbox_alloc(struct dsync_brain *brain, const guid_128_t guid,
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen struct mailbox **box_r, const char **error_r)
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen{
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen struct mail_namespace *ns;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen int ret;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen *box_r = NULL;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen if (!dsync_brain_want_namespace(brain, ns))
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen continue;
01aca4a521410be85e1f39e37c662435d052f48aAki Tuomi if ((ret = ns_mailbox_try_alloc(ns, guid, box_r, error_r)) != 0) {
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen if (ret < 0)
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen brain->failed = TRUE;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen return ret;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen }
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen }
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen return 0;
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen}
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainenstatic void
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainendsync_mailbox_cache_field_dup(ARRAY_TYPE(mailbox_cache_field) *dest,
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen const ARRAY_TYPE(mailbox_cache_field) *src,
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen pool_t pool)
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const struct mailbox_cache_field *src_field;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct mailbox_cache_field *dest_field;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen p_array_init(dest, pool, array_count(src));
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen array_foreach(src, src_field) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dest_field = array_append_space(dest);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dest_field->name = p_strdup(pool, src_field->name);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dest_field->decision = src_field->decision;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dest_field->last_used = src_field->last_used;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainenstatic const struct dsync_mailbox_state *
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainendsync_mailbox_state_find(struct dsync_brain *brain,
14189e0d0af45ddcb888d026bd8d7e4609912ec5Timo Sirainen const guid_128_t mailbox_guid)
e564ff0581fc44b78badf8da36e68f9f7a27807eTimo Sirainen{
f9eee365367f37b1692c07db6c23d30243844aaaTimo Sirainen const uint8_t *guid_p;
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen
7cd055a212d44067e2d94452c05691d696c9f699Timo Sirainen guid_p = mailbox_guid;
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen return hash_table_lookup(brain->mailbox_states, guid_p);
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen}
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi
e8434aad92ea6ff1c915b708294dbd0c7ff5908dMichael M Slusarzstatic void
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendsync_mailbox_state_remove(struct dsync_brain *brain,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const guid_128_t mailbox_guid)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
f0e416aa42058e7ccc0dc6deec0d4f4a19ee6ebeTimo Sirainen const uint8_t *guid_p;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen guid_p = mailbox_guid;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (hash_table_lookup(brain->mailbox_states, guid_p) != NULL)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen hash_table_remove(brain->mailbox_states, guid_p);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenvoid dsync_brain_sync_init_box_states(struct dsync_brain *brain)
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen{
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen if (brain->backup_send) {
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen /* we have an exporter, but no importer. */
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen brain->box_send_state = DSYNC_BOX_STATE_ATTRIBUTES;
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen brain->box_recv_state = brain->mail_requests ?
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen DSYNC_BOX_STATE_MAIL_REQUESTS :
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen DSYNC_BOX_STATE_RECV_LAST_COMMON;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen } else if (brain->backup_recv) {
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen /* we have an importer, but no exporter */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->box_send_state = brain->mail_requests ?
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen DSYNC_BOX_STATE_MAIL_REQUESTS :
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen DSYNC_BOX_STATE_DONE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->box_recv_state = DSYNC_BOX_STATE_ATTRIBUTES;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen } else {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->box_send_state = DSYNC_BOX_STATE_ATTRIBUTES;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->box_recv_state = DSYNC_BOX_STATE_ATTRIBUTES;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendsync_brain_sync_mailbox_init(struct dsync_brain *brain,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct mailbox *box,
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen const struct dsync_mailbox *local_dsync_box,
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen bool wait_for_remote_box)
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen{
37e8420b32a0fa3442c405616980e45beb494104Timo Sirainen const struct dsync_mailbox_state *state;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(brain->box_importer == NULL);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(brain->box_exporter == NULL);
61f39b0358a72ebc693d84ba5bac74489ee7df41Timo Sirainen i_assert(box->synced);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->box = box;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->pre_box_state = brain->state;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (wait_for_remote_box) {
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen brain->box_send_state = DSYNC_BOX_STATE_MAILBOX;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen brain->box_recv_state = DSYNC_BOX_STATE_MAILBOX;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen } else {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_brain_sync_init_box_states(brain);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->local_dsync_box = *local_dsync_box;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (brain->dsync_box_pool != NULL)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen p_clear(brain->dsync_box_pool);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen else {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->dsync_box_pool =
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen pool_alloconly_create("dsync brain box pool", 1024);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen dsync_mailbox_cache_field_dup(&brain->local_dsync_box.cache_fields,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen &local_dsync_box->cache_fields,
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen brain->dsync_box_pool);
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen memset(&brain->remote_dsync_box, 0, sizeof(brain->remote_dsync_box));
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen state = dsync_mailbox_state_find(brain, local_dsync_box->mailbox_guid);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (state != NULL)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->mailbox_state = *state;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen else {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen memset(&brain->mailbox_state, 0, sizeof(brain->mailbox_state));
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen memcpy(brain->mailbox_state.mailbox_guid,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen local_dsync_box->mailbox_guid,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen sizeof(brain->mailbox_state.mailbox_guid));
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->mailbox_state.last_uidvalidity =
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen local_dsync_box->uid_validity;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendsync_brain_sync_mailbox_init_remote(struct dsync_brain *brain,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const struct dsync_mailbox *remote_dsync_box)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen enum dsync_mailbox_import_flags import_flags = 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const struct dsync_mailbox_state *state;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen uint32_t last_common_uid;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen uint64_t last_common_modseq, last_common_pvt_modseq;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(brain->box_importer == NULL);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(brain->log_scan != NULL);
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen i_assert(memcmp(brain->local_dsync_box.mailbox_guid,
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen remote_dsync_box->mailbox_guid,
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen sizeof(remote_dsync_box->mailbox_guid)) == 0);
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen brain->remote_dsync_box = *remote_dsync_box;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen dsync_mailbox_cache_field_dup(&brain->remote_dsync_box.cache_fields,
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen &remote_dsync_box->cache_fields,
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen brain->dsync_box_pool);
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen state = dsync_mailbox_state_find(brain, remote_dsync_box->mailbox_guid);
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen if (state != NULL) {
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen last_common_uid = state->last_common_uid;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen last_common_modseq = state->last_common_modseq;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen last_common_pvt_modseq = state->last_common_pvt_modseq;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen } else {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen last_common_uid = 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen last_common_modseq = 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen last_common_pvt_modseq = 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (brain->mail_requests)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen import_flags |= DSYNC_MAILBOX_IMPORT_FLAG_WANT_MAIL_REQUESTS;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (brain->master_brain)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen import_flags |= DSYNC_MAILBOX_IMPORT_FLAG_MASTER_BRAIN;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (brain->backup_recv && !brain->no_backup_overwrite)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen import_flags |= DSYNC_MAILBOX_IMPORT_FLAG_REVERT_LOCAL_CHANGES;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (brain->debug)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen import_flags |= DSYNC_MAILBOX_IMPORT_FLAG_DEBUG;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen if (brain->local_dsync_box.have_save_guids &&
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen (remote_dsync_box->have_save_guids ||
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen (brain->backup_recv && remote_dsync_box->have_guids)))
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen import_flags |= DSYNC_MAILBOX_IMPORT_FLAG_MAILS_HAVE_GUIDS;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen if (brain->local_dsync_box.have_only_guid128 ||
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen remote_dsync_box->have_only_guid128)
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen import_flags |= DSYNC_MAILBOX_IMPORT_FLAG_MAILS_USE_GUID128;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen brain->box_importer = brain->backup_send ? NULL :
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen dsync_mailbox_import_init(brain->box, brain->log_scan,
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen last_common_uid, last_common_modseq,
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen last_common_pvt_modseq,
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen remote_dsync_box->uid_next,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen remote_dsync_box->first_recent_uid,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen remote_dsync_box->highest_modseq,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen remote_dsync_box->highest_pvt_modseq,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen import_flags);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenint dsync_brain_sync_mailbox_open(struct dsync_brain *brain,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const struct dsync_mailbox *remote_dsync_box)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct mailbox_status status;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen enum dsync_mailbox_exporter_flags exporter_flags = 0;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen uint32_t last_common_uid, highest_wanted_uid;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen uint64_t last_common_modseq, last_common_pvt_modseq;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen const char *desync_reason = "";
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen bool pvt_too_old;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen int ret;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(brain->log_scan == NULL);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(brain->box_exporter == NULL);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen last_common_uid = brain->mailbox_state.last_common_uid;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen last_common_modseq = brain->mailbox_state.last_common_modseq;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen last_common_pvt_modseq = brain->mailbox_state.last_common_pvt_modseq;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen highest_wanted_uid = last_common_uid == 0 ?
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen (uint32_t)-1 : last_common_uid;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen ret = dsync_transaction_log_scan_init(brain->box->view,
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen brain->box->view_pvt,
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen highest_wanted_uid,
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen last_common_modseq,
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen last_common_pvt_modseq,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen &brain->log_scan, &pvt_too_old);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (ret < 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_error("Failed to read transaction log for mailbox %s",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen mailbox_get_vname(brain->box));
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->failed = TRUE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return -1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (ret == 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (pvt_too_old) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen desync_reason = t_strdup_printf(
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen "Private modseq %llu no longer in transaction log",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (unsigned long long)last_common_pvt_modseq);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen } else {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen desync_reason = t_strdup_printf(
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen "Modseq %llu no longer in transaction log",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (unsigned long long)last_common_modseq);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (last_common_uid != 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen mailbox_get_open_status(brain->box, STATUS_UIDNEXT |
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen STATUS_HIGHESTMODSEQ |
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen STATUS_HIGHESTPVTMODSEQ, &status);
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen /* if last_common_* is higher than our current ones it means
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen that the incremental sync state is stale and we need to do
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen a full resync */
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen if (status.uidnext < last_common_uid) {
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen desync_reason = t_strdup_printf("uidnext %u < %u",
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen status.uidnext, last_common_uid);
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen ret = 0;
7c04ede0da5749691624a1fb962ac29cd0167050Timo Sirainen } else if (status.highest_modseq < last_common_modseq) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen desync_reason = t_strdup_printf("highest_modseq %llu < %llu",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (unsigned long long)status.highest_modseq,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (unsigned long long)last_common_modseq);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ret = 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen } else if (status.highest_pvt_modseq < last_common_pvt_modseq) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen desync_reason = t_strdup_printf("highest_pvt_modseq %llu < %llu",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (unsigned long long)status.highest_pvt_modseq,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (unsigned long long)last_common_pvt_modseq);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ret = 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (ret == 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_warning("Failed to do incremental sync for mailbox %s, "
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen "retry with a full sync (%s)",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen mailbox_get_vname(brain->box), desync_reason);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->changes_during_sync = TRUE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->require_full_resync = TRUE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (!brain->mail_requests)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen exporter_flags |= DSYNC_MAILBOX_EXPORTER_FLAG_AUTO_EXPORT_MAILS;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (remote_dsync_box->have_save_guids &&
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (brain->local_dsync_box.have_save_guids ||
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (brain->backup_send && brain->local_dsync_box.have_guids)))
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen exporter_flags |= DSYNC_MAILBOX_EXPORTER_FLAG_MAILS_HAVE_GUIDS;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->box_exporter = brain->backup_recv ? NULL :
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_mailbox_export_init(brain->box, brain->log_scan,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen last_common_uid,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen exporter_flags);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_brain_sync_mailbox_init_remote(brain, remote_dsync_box);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return 1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenvoid dsync_brain_sync_mailbox_deinit(struct dsync_brain *brain)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(brain->box != NULL);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (brain->require_full_resync) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->mailbox_state.last_uidvalidity = 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->require_full_resync = FALSE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen array_append(&brain->remote_mailbox_states, &brain->mailbox_state, 1);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (brain->box_exporter != NULL) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const char *error;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen i_assert(brain->failed ||
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->sync_type == DSYNC_BRAIN_SYNC_TYPE_CHANGED);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (void)dsync_mailbox_export_deinit(&brain->box_exporter, &error);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (brain->box_importer != NULL) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen uint32_t last_common_uid, last_messages_count;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen uint64_t last_common_modseq, last_common_pvt_modseq;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen bool changes_during_sync;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(brain->failed);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (void)dsync_mailbox_import_deinit(&brain->box_importer,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen FALSE,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen &last_common_uid,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen &last_common_modseq,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen &last_common_pvt_modseq,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen &last_messages_count,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen &changes_during_sync);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (brain->log_scan != NULL)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_transaction_log_scan_deinit(&brain->log_scan);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen mailbox_free(&brain->box);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->state = brain->pre_box_state;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic int dsync_box_get(struct mailbox *box, struct dsync_mailbox *dsync_box_r)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const enum mailbox_status_items status_items =
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen STATUS_UIDVALIDITY | STATUS_UIDNEXT | STATUS_MESSAGES |
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen STATUS_FIRST_RECENT_UID | STATUS_HIGHESTMODSEQ |
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen STATUS_HIGHESTPVTMODSEQ;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const enum mailbox_metadata_items metadata_items =
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen MAILBOX_METADATA_CACHE_FIELDS | MAILBOX_METADATA_GUID;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct mailbox_status status;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct mailbox_metadata metadata;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const char *errstr;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen enum mail_error error;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen /* get metadata first, since it may autocreate the mailbox */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (mailbox_get_metadata(box, metadata_items, &metadata) < 0 ||
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen mailbox_get_status(box, status_items, &status) < 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen errstr = mailbox_get_last_error(box, &error);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (error == MAIL_ERROR_NOTFOUND ||
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen error == MAIL_ERROR_NOTPOSSIBLE) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* Mailbox isn't selectable, try the next one. We
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen should have already caught \Noselect mailboxes, but
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen check them anyway here. The NOTPOSSIBLE check is
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen mainly for invalid mbox files. */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_error("Failed to access mailbox %s: %s",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen mailbox_get_vname(box), errstr);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return -1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(status.uidvalidity != 0 || status.messages == 0);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen memset(dsync_box_r, 0, sizeof(*dsync_box_r));
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen memcpy(dsync_box_r->mailbox_guid, metadata.guid,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen sizeof(dsync_box_r->mailbox_guid));
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_box_r->uid_validity = status.uidvalidity;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_box_r->uid_next = status.uidnext;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_box_r->messages_count = status.messages;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_box_r->first_recent_uid = status.first_recent_uid;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_box_r->highest_modseq = status.highest_modseq;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen dsync_box_r->highest_pvt_modseq = status.highest_pvt_modseq;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_mailbox_cache_field_dup(&dsync_box_r->cache_fields,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen metadata.cache_fields,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen pool_datastack_create());
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_box_r->have_guids = status.have_guids;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_box_r->have_save_guids = status.have_save_guids;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_box_r->have_only_guid128 = status.have_only_guid128;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return 1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic bool
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendsync_brain_has_mailbox_state_changed(struct dsync_brain *brain,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const struct dsync_mailbox *dsync_box)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const struct dsync_mailbox_state *state;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (brain->sync_type != DSYNC_BRAIN_SYNC_TYPE_STATE)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return TRUE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen state = dsync_mailbox_state_find(brain, dsync_box->mailbox_guid);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return state == NULL ||
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen state->last_uidvalidity != dsync_box->uid_validity ||
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen state->last_common_uid+1 != dsync_box->uid_next ||
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen state->last_common_modseq != dsync_box->highest_modseq ||
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen state->last_common_pvt_modseq != dsync_box->highest_pvt_modseq ||
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen state->last_messages_count != dsync_box->messages_count;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainenstatic int
6ea145a99eeee923602f04d3c9183bbdba6cd190Timo Sirainendsync_brain_try_next_mailbox(struct dsync_brain *brain, struct mailbox **box_r,
6ea145a99eeee923602f04d3c9183bbdba6cd190Timo Sirainen struct dsync_mailbox *dsync_box_r)
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen{
7cd055a212d44067e2d94452c05691d696c9f699Timo Sirainen enum mailbox_flags flags = 0;
7cd055a212d44067e2d94452c05691d696c9f699Timo Sirainen struct dsync_mailbox dsync_box;
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen struct mailbox *box;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen struct dsync_mailbox_node *node;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const char *vname = NULL;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen bool synced = FALSE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen int ret;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen *box_r = NULL;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen while (dsync_mailbox_tree_iter_next(brain->local_tree_iter, &vname, &node)) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (node->existence == DSYNC_MAILBOX_NODE_EXISTS &&
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen !guid_128_is_empty(node->mailbox_guid))
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen break;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen vname = NULL;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (vname == NULL) {
e8434aad92ea6ff1c915b708294dbd0c7ff5908dMichael M Slusarz /* no more mailboxes */
e8434aad92ea6ff1c915b708294dbd0c7ff5908dMichael M Slusarz dsync_mailbox_tree_iter_deinit(&brain->local_tree_iter);
e8434aad92ea6ff1c915b708294dbd0c7ff5908dMichael M Slusarz return -1;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (brain->backup_send) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* make sure mailbox isn't modified */
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen flags |= MAILBOX_FLAG_READONLY;
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen }
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen box = mailbox_alloc(node->ns->list, vname, flags);
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen for (;;) {
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen if ((ret = dsync_box_get(box, &dsync_box)) <= 0) {
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen if (ret < 0)
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen brain->failed = TRUE;
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen mailbox_free(&box);
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen return ret;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen }
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen /* if mailbox's last_common_* state equals the current state,
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen we can skip the mailbox */
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen if (!dsync_brain_has_mailbox_state_changed(brain, &dsync_box)) {
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen if (brain->debug) {
ce74395e2a932342e04fb682395bcce111574969Timo Sirainen i_debug("brain %c: Skipping mailbox %s with unchanged state "
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen "uidvalidity=%u uidnext=%u highestmodseq=%llu highestpvtmodseq=%llu messages=%u",
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen brain->master_brain ? 'M' : 'S',
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen guid_128_to_string(dsync_box.mailbox_guid),
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen dsync_box.uid_validity,
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen dsync_box.uid_next,
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen (unsigned long long)dsync_box.highest_modseq,
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen (unsigned long long)dsync_box.highest_pvt_modseq,
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen dsync_box.messages_count);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen }
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen mailbox_free(&box);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen return 0;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen }
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen if (synced) {
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen /* ok, the mailbox really changed */
14189e0d0af45ddcb888d026bd8d7e4609912ec5Timo Sirainen break;
14189e0d0af45ddcb888d026bd8d7e4609912ec5Timo Sirainen }
e564ff0581fc44b78badf8da36e68f9f7a27807eTimo Sirainen
e564ff0581fc44b78badf8da36e68f9f7a27807eTimo Sirainen /* mailbox appears to have changed. do a full sync here and get the
f9eee365367f37b1692c07db6c23d30243844aaaTimo Sirainen state again */
f9eee365367f37b1692c07db6c23d30243844aaaTimo Sirainen if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
f9eee365367f37b1692c07db6c23d30243844aaaTimo Sirainen i_error("Can't sync mailbox %s: %s",
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen mailbox_get_vname(box),
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen mailbox_get_last_error(box, NULL));
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen brain->failed = TRUE;
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen mailbox_free(&box);
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen return -1;
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen }
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen synced = TRUE;
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen }
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen *box_r = box;
7cd055a212d44067e2d94452c05691d696c9f699Timo Sirainen *dsync_box_r = dsync_box;
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen return 1;
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen}
7cd055a212d44067e2d94452c05691d696c9f699Timo Sirainen
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainenstatic bool
8952d797eca36f997ec36569e783871b597a9216Timo Sirainendsync_brain_next_mailbox(struct dsync_brain *brain, struct mailbox **box_r,
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen struct dsync_mailbox *dsync_box_r)
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen{
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen int ret;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen if (brain->no_mail_sync)
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi return FALSE;
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi while ((ret = dsync_brain_try_next_mailbox(brain, box_r, dsync_box_r)) == 0)
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi ;
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi return ret > 0;
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi}
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomivoid dsync_brain_master_send_mailbox(struct dsync_brain *brain)
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi{
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi struct dsync_mailbox dsync_box;
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi struct mailbox *box;
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(brain->master_brain);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(brain->box == NULL);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (!dsync_brain_next_mailbox(brain, &box, &dsync_box)) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->state = DSYNC_STATE_DONE;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen dsync_ibc_send_end_of_list(brain->ibc, DSYNC_IBC_EOL_MAILBOX);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen return;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen }
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen /* start exporting this mailbox (wait for remote to start importing) */
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen dsync_ibc_send_mailbox(brain->ibc, &dsync_box);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen dsync_brain_sync_mailbox_init(brain, box, &dsync_box, TRUE);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->state = DSYNC_STATE_SYNC_MAILS;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenbool dsync_boxes_need_sync(struct dsync_brain *brain,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const struct dsync_mailbox *box1,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const struct dsync_mailbox *box2)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen{
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen if (brain->no_mail_sync)
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen return FALSE;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen if (brain->sync_type != DSYNC_BRAIN_SYNC_TYPE_CHANGED)
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen return TRUE;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen return box1->highest_modseq != box2->highest_modseq ||
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen box1->highest_pvt_modseq != box2->highest_pvt_modseq ||
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen box1->messages_count != box2->messages_count ||
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen box1->uid_next != box2->uid_next ||
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen box1->uid_validity != box2->uid_validity ||
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen box1->first_recent_uid != box2->first_recent_uid;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen}
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainenstatic int
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainenmailbox_cache_field_name_cmp(const struct mailbox_cache_field *f1,
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen const struct mailbox_cache_field *f2)
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen{
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen return strcmp(f1->name, f2->name);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen}
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainenstatic void
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainendsync_cache_fields_update(const struct dsync_mailbox *local_box,
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen const struct dsync_mailbox *remote_box,
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen struct mailbox_update *update)
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen{
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ARRAY_TYPE(mailbox_cache_field) local_sorted, remote_sorted, changes;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen const struct mailbox_cache_field *local_fields, *remote_fields;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen unsigned int li, ri, local_count, remote_count;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen time_t drop_older_timestamp;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen int ret;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen if (array_count(&remote_box->cache_fields) == 0) {
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen /* remote has no cached fields. there's nothing to update. */
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen return;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen }
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen t_array_init(&local_sorted, array_count(&local_box->cache_fields));
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen t_array_init(&remote_sorted, array_count(&remote_box->cache_fields));
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen array_append_array(&local_sorted, &local_box->cache_fields);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen array_append_array(&remote_sorted, &remote_box->cache_fields);
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen array_sort(&local_sorted, mailbox_cache_field_name_cmp);
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen array_sort(&remote_sorted, mailbox_cache_field_name_cmp);
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen if (array_count(&local_sorted) == 0) {
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen /* local has no cached fields. set them to same as remote. */
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen array_append_zero(&remote_sorted);
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen update->cache_updates = array_idx(&remote_sorted, 0);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen return;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen }
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen /* figure out what to change */
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen local_fields = array_get(&local_sorted, &local_count);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen remote_fields = array_get(&remote_sorted, &remote_count);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen t_array_init(&changes, local_count + remote_count);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen drop_older_timestamp = ioloop_time - MAIL_CACHE_FIELD_DROP_SECS;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen for (li = ri = 0; li < local_count || ri < remote_count; ) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen ret = li == local_count ? 1 :
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen ri == remote_count ? -1 :
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen strcmp(local_fields[li].name, remote_fields[ri].name);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (ret == 0) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen /* field exists in both local and remote */
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen const struct mailbox_cache_field *lf = &local_fields[li];
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen const struct mailbox_cache_field *rf = &remote_fields[ri];
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen if (lf->last_used > rf->last_used ||
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen (lf->last_used == rf->last_used &&
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen lf->decision > rf->decision)) {
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen /* use local decision and timestamp */
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen } else {
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen array_append(&changes, rf, 1);
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen }
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen li++; ri++;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen } else if (ret < 0) {
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen /* remote field doesn't exist */
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen li++;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen } else {
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen /* local field doesn't exist */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (remote_fields[ri].last_used < drop_older_timestamp) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* field hasn't be used for a long time, remote
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen will probably drop this soon as well */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen } else {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen array_append(&changes, &remote_fields[ri], 1);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ri++;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(li == local_count && ri == remote_count);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (array_count(&changes) > 0) {
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen array_append_zero(&changes);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen update->cache_updates = array_idx(&changes, 0);
be59f9ae981dbe4bdd264053e9febd4ea5dad75bTimo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen}
f0e416aa42058e7ccc0dc6deec0d4f4a19ee6ebeTimo Sirainen
7cd055a212d44067e2d94452c05691d696c9f699Timo Sirainenbool dsync_brain_mailbox_update_pre(struct dsync_brain *brain,
7cd055a212d44067e2d94452c05691d696c9f699Timo Sirainen struct mailbox *box,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const struct dsync_mailbox *local_box,
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen const struct dsync_mailbox *remote_box)
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen{
e8434aad92ea6ff1c915b708294dbd0c7ff5908dMichael M Slusarz struct mailbox_update update;
e8434aad92ea6ff1c915b708294dbd0c7ff5908dMichael M Slusarz const struct dsync_mailbox_state *state;
f9eee365367f37b1692c07db6c23d30243844aaaTimo Sirainen bool ret = TRUE;
f9eee365367f37b1692c07db6c23d30243844aaaTimo Sirainen
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen memset(&update, 0, sizeof(update));
f7d018e7e0980044e3d537958126e44ef4c45056Timo Sirainen
e564ff0581fc44b78badf8da36e68f9f7a27807eTimo Sirainen if (local_box->uid_validity != remote_box->uid_validity) {
00bcc83b18793b9ec5e5d264480a88bf78b10b33Timo Sirainen /* Keep the UIDVALIDITY for the mailbox that has more
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen messages. If they equal, use the higher UIDVALIDITY. */
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen if (remote_box->messages_count > local_box->messages_count ||
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen (remote_box->messages_count == local_box->messages_count &&
2599a77a28bde0653fa090802424469904d518eeTimo Sirainen remote_box->uid_validity > local_box->uid_validity))
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi update.uid_validity = remote_box->uid_validity;
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi state = dsync_mailbox_state_find(brain, local_box->mailbox_guid);
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi if (state != NULL && state->last_common_uid > 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* we can't continue syncing this mailbox in this
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen session, because the other side already started
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen sending mailbox changes, but not for all mails. */
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen dsync_mailbox_state_remove(brain, local_box->mailbox_guid);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen ret = FALSE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_cache_fields_update(local_box, remote_box, &update);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (update.uid_validity == 0 &&
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen update.cache_updates == NULL) {
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen /* no changes */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return ret;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen if (mailbox_update(box, &update) < 0) {
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen i_error("Couldn't update mailbox %s metadata: %s",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen mailbox_get_vname(box),
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen mailbox_get_last_error(box, NULL));
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->failed = TRUE;
f0e416aa42058e7ccc0dc6deec0d4f4a19ee6ebeTimo Sirainen }
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen return ret;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen}
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic void
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendsync_brain_slave_send_mailbox_lost(struct dsync_brain *brain,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const struct dsync_mailbox *dsync_box)
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen{
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen struct dsync_mailbox delete_box;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (brain->debug) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_debug("brain %c: We don't have mailbox %s",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->master_brain ? 'M' : 'S',
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen guid_128_to_string(dsync_box->mailbox_guid));
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen memset(&delete_box, 0, sizeof(delete_box));
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen memcpy(delete_box.mailbox_guid, dsync_box->mailbox_guid,
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen sizeof(delete_box.mailbox_guid));
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen t_array_init(&delete_box.cache_fields, 0);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen delete_box.mailbox_lost = TRUE;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen dsync_ibc_send_mailbox(brain->ibc, &delete_box);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen}
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainenbool dsync_brain_slave_recv_mailbox(struct dsync_brain *brain)
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen{
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen const struct dsync_mailbox *dsync_box;
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen struct dsync_mailbox local_dsync_box;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen struct mailbox *box;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen const char *error;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen int ret;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen bool resync;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(!brain->master_brain);
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen i_assert(brain->box == NULL);
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen if ((ret = dsync_ibc_recv_mailbox(brain->ibc, &dsync_box)) == 0)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return FALSE;
b457d2ecf97fb52064f9dd563fd4e8065af39dfbTimo Sirainen if (ret < 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->state = DSYNC_STATE_DONE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return TRUE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (dsync_brain_mailbox_alloc(brain, dsync_box->mailbox_guid,
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen &box, &error) < 0) {
14189e0d0af45ddcb888d026bd8d7e4609912ec5Timo Sirainen i_error("Couldn't allocate mailbox GUID %s: %s",
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen guid_128_to_string(dsync_box->mailbox_guid), error);
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen i_assert(brain->failed);
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen return TRUE;
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen }
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen if (box == NULL) {
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen /* mailbox was probably deleted/renamed during sync */
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen if (brain->backup_send && brain->no_backup_overwrite) {
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen if (brain->debug) {
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen i_debug("brain %c: Ignore nonexistent "
01aca4a521410be85e1f39e37c662435d052f48aAki Tuomi "mailbox GUID %s with -1 sync",
01aca4a521410be85e1f39e37c662435d052f48aAki Tuomi brain->master_brain ? 'M' : 'S',
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen guid_128_to_string(dsync_box->mailbox_guid));
01aca4a521410be85e1f39e37c662435d052f48aAki Tuomi }
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen dsync_brain_slave_send_mailbox_lost(brain, dsync_box);
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen return TRUE;
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen }
f0e811f0e306bb20d3da9c26353bdd5669132f29Timo Sirainen //FIXME: verify this from log, and if not log an error.
f0e811f0e306bb20d3da9c26353bdd5669132f29Timo Sirainen if (brain->debug) {
f0e811f0e306bb20d3da9c26353bdd5669132f29Timo Sirainen i_debug("brain %c: Change during sync: "
f0e811f0e306bb20d3da9c26353bdd5669132f29Timo Sirainen "Mailbox GUID %s was lost",
3e8842470a4a17017529d43b39c40a7549c2ecf2Timo Sirainen brain->master_brain ? 'M' : 'S',
3e8842470a4a17017529d43b39c40a7549c2ecf2Timo Sirainen guid_128_to_string(dsync_box->mailbox_guid));
3e8842470a4a17017529d43b39c40a7549c2ecf2Timo Sirainen }
3e8842470a4a17017529d43b39c40a7549c2ecf2Timo Sirainen brain->changes_during_sync = TRUE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_brain_slave_send_mailbox_lost(brain, dsync_box);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return TRUE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_error("Can't sync mailbox %s: %s",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen mailbox_get_vname(box),
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen mailbox_get_last_error(box, NULL));
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen mailbox_free(&box);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->failed = TRUE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return TRUE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen if ((ret = dsync_box_get(box, &local_dsync_box)) <= 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen mailbox_free(&box);
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainen if (ret < 0) {
b650f04c3b2e7dea2295bdbe3239eb82ec03ada0Timo Sirainen brain->failed = TRUE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return TRUE;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* another process just deleted this mailbox? */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (brain->debug) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_debug("brain %c: Skipping lost mailbox %s",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->master_brain ? 'M' : 'S',
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen guid_128_to_string(dsync_box->mailbox_guid));
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen }
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_brain_slave_send_mailbox_lost(brain, dsync_box);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen return TRUE;
1856c361aad526948d56d8aafd576bca94516b92Timo Sirainen }
1856c361aad526948d56d8aafd576bca94516b92Timo Sirainen i_assert(local_dsync_box.uid_validity != 0);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(memcmp(dsync_box->mailbox_guid, local_dsync_box.mailbox_guid,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen sizeof(dsync_box->mailbox_guid)) == 0);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen resync = !dsync_brain_mailbox_update_pre(brain, box, &local_dsync_box,
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen dsync_box);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen if (!dsync_boxes_need_sync(brain, &local_dsync_box, dsync_box)) {
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen /* no fields appear to have changed, skip this mailbox */
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen if (brain->debug) {
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen i_debug("brain %c: Skipping unchanged mailbox %s",
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen brain->master_brain ? 'M' : 'S',
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen guid_128_to_string(dsync_box->mailbox_guid));
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen }
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen dsync_ibc_send_mailbox(brain->ibc, &local_dsync_box);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen mailbox_free(&box);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen return TRUE;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen }
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen
2a24f3565c61cb429d1e428601f153ce53b8bae3Timo Sirainen /* start export/import */
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen dsync_brain_sync_mailbox_init(brain, box, &local_dsync_box, FALSE);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen if ((ret = dsync_brain_sync_mailbox_open(brain, dsync_box)) < 0)
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen return TRUE;
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen if (ret == 0 || resync) {
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen brain->changes_during_sync = TRUE;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen brain->require_full_resync = TRUE;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen dsync_brain_sync_mailbox_deinit(brain);
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen dsync_brain_slave_send_mailbox_lost(brain, dsync_box);
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen return TRUE;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen }
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen dsync_ibc_send_mailbox(brain->ibc, &local_dsync_box);
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen brain->state = DSYNC_STATE_SYNC_MAILS;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen return TRUE;
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen}
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen