dsync-brain-mailbox.c revision 70058d29cf8c77501741ddbc39178cfc87ca459e
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2013-2014 Dovecot authors, see the included COPYING file */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenns_mailbox_try_alloc(struct mail_namespace *ns, const guid_128_t guid,
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen *error_r = existence == MAILBOX_EXISTENCE_NONE ?
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen "Mailbox was already deleted" :
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen "Mailbox is no longer selectable";
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainenint dsync_brain_mailbox_alloc(struct dsync_brain *brain, const guid_128_t guid,
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
01aca4a521410be85e1f39e37c662435d052f48aAki Tuomi if ((ret = ns_mailbox_try_alloc(ns, guid, box_r, error_r)) != 0) {
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainendsync_mailbox_cache_field_dup(ARRAY_TYPE(mailbox_cache_field) *dest,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dest_field->name = p_strdup(pool, src_field->name);
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainenstatic const struct dsync_mailbox_state *
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainendsync_mailbox_state_find(struct dsync_brain *brain,
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen return hash_table_lookup(brain->mailbox_states, guid_p);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendsync_mailbox_state_remove(struct dsync_brain *brain,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (hash_table_lookup(brain->mailbox_states, guid_p) != NULL)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen hash_table_remove(brain->mailbox_states, guid_p);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenvoid dsync_brain_sync_init_box_states(struct dsync_brain *brain)
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 ?
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen /* we have an importer, but no exporter */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->box_send_state = brain->mail_requests ?
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->box_recv_state = DSYNC_BOX_STATE_ATTRIBUTES;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->box_send_state = DSYNC_BOX_STATE_ATTRIBUTES;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->box_recv_state = DSYNC_BOX_STATE_ATTRIBUTES;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendsync_brain_sync_mailbox_init(struct dsync_brain *brain,
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen brain->box_send_state = DSYNC_BOX_STATE_MAILBOX;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen brain->box_recv_state = DSYNC_BOX_STATE_MAILBOX;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen pool_alloconly_create("dsync brain box pool", 1024);
e22ec7998afd426c53c658483ce66b6e404e27c6Timo Sirainen dsync_mailbox_cache_field_dup(&brain->local_dsync_box.cache_fields,
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen memset(&brain->remote_dsync_box, 0, sizeof(brain->remote_dsync_box));
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen state = dsync_mailbox_state_find(brain, local_dsync_box->mailbox_guid);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen memset(&brain->mailbox_state, 0, sizeof(brain->mailbox_state));
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendsync_brain_sync_mailbox_init_remote(struct dsync_brain *brain,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen enum dsync_mailbox_import_flags import_flags = 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen uint64_t last_common_modseq, last_common_pvt_modseq;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen i_assert(memcmp(brain->local_dsync_box.mailbox_guid,
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen sizeof(remote_dsync_box->mailbox_guid)) == 0);
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen dsync_mailbox_cache_field_dup(&brain->remote_dsync_box.cache_fields,
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen state = dsync_mailbox_state_find(brain, remote_dsync_box->mailbox_guid);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen last_common_modseq = state->last_common_modseq;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen last_common_pvt_modseq = state->last_common_pvt_modseq;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen import_flags |= DSYNC_MAILBOX_IMPORT_FLAG_WANT_MAIL_REQUESTS;
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 import_flags |= DSYNC_MAILBOX_IMPORT_FLAG_DEBUG;
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 import_flags |= DSYNC_MAILBOX_IMPORT_FLAG_MAILS_USE_GUID128;
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen brain->box_importer = brain->backup_send ? NULL :
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen dsync_mailbox_import_init(brain->box, brain->log_scan,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenint dsync_brain_sync_mailbox_open(struct dsync_brain *brain,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen enum dsync_mailbox_exporter_flags exporter_flags = 0;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen uint64_t last_common_modseq, last_common_pvt_modseq;
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 ret = dsync_transaction_log_scan_init(brain->box->view,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_error("Failed to read transaction log for mailbox %s",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen "Private modseq %llu no longer in transaction log",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (unsigned long long)last_common_pvt_modseq);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen "Modseq %llu no longer in transaction log",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (unsigned long long)last_common_modseq);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen mailbox_get_open_status(brain->box, STATUS_UIDNEXT |
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 desync_reason = t_strdup_printf("uidnext %u < %u",
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)last_common_modseq);
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 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 exporter_flags |= DSYNC_MAILBOX_EXPORTER_FLAG_AUTO_EXPORT_MAILS;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (brain->backup_send && brain->local_dsync_box.have_guids)))
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen exporter_flags |= DSYNC_MAILBOX_EXPORTER_FLAG_MAILS_HAVE_GUIDS;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->box_exporter = brain->backup_recv ? NULL :
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_mailbox_export_init(brain->box, brain->log_scan,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_brain_sync_mailbox_init_remote(brain, remote_dsync_box);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenvoid dsync_brain_sync_mailbox_deinit(struct dsync_brain *brain)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen array_append(&brain->remote_mailbox_states, &brain->mailbox_state, 1);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen brain->sync_type == DSYNC_BRAIN_SYNC_TYPE_CHANGED);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (void)dsync_mailbox_export_deinit(&brain->box_exporter, &error);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen uint32_t last_common_uid, last_messages_count;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen uint64_t last_common_modseq, last_common_pvt_modseq;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen (void)dsync_mailbox_import_deinit(&brain->box_importer,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_transaction_log_scan_deinit(&brain->log_scan);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainenstatic int dsync_box_get(struct mailbox *box, struct dsync_mailbox *dsync_box_r)
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 const enum mailbox_metadata_items metadata_items =
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen MAILBOX_METADATA_CACHE_FIELDS | MAILBOX_METADATA_GUID;
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 /* 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 i_assert(status.uidvalidity != 0 || status.messages == 0);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen memcpy(dsync_box_r->mailbox_guid, metadata.guid,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_box_r->uid_validity = status.uidvalidity;
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 dsync_box_r->have_save_guids = status.have_save_guids;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_box_r->have_only_guid128 = status.have_only_guid128;
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendsync_brain_has_mailbox_state_changed(struct dsync_brain *brain,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (brain->sync_type != DSYNC_BRAIN_SYNC_TYPE_STATE)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen state = dsync_mailbox_state_find(brain, dsync_box->mailbox_guid);
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;
6ea145a99eeee923602f04d3c9183bbdba6cd190Timo Sirainendsync_brain_try_next_mailbox(struct dsync_brain *brain, struct mailbox **box_r,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen while (dsync_mailbox_tree_iter_next(brain->local_tree_iter, &vname, &node)) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (node->existence == DSYNC_MAILBOX_NODE_EXISTS &&
e8434aad92ea6ff1c915b708294dbd0c7ff5908dMichael M Slusarz /* no more mailboxes */
e8434aad92ea6ff1c915b708294dbd0c7ff5908dMichael M Slusarz dsync_mailbox_tree_iter_deinit(&brain->local_tree_iter);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* make sure mailbox isn't modified */
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen box = mailbox_alloc(node->ns->list, vname, flags);
c72cfe4a2bda39fff3b8a8bd64b31a7cc14d7d11Timo Sirainen if ((ret = dsync_box_get(box, &dsync_box)) <= 0) {
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 i_debug("brain %c: Skipping mailbox %s with unchanged state "
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen "uidvalidity=%u uidnext=%u highestmodseq=%llu highestpvtmodseq=%llu messages=%u",
4db61af2cfe2b206113bcc4b6153521679702bb4Timo Sirainen (unsigned long long)dsync_box.highest_pvt_modseq,
a1044a46a8f3512173f4ea2684ef1fc3e61645c7Timo Sirainen /* ok, the mailbox really changed */
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) {
8952d797eca36f997ec36569e783871b597a9216Timo Sirainendsync_brain_next_mailbox(struct dsync_brain *brain, struct mailbox **box_r,
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi while ((ret = dsync_brain_try_next_mailbox(brain, box_r, dsync_box_r)) == 0)
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomi return ret > 0;
07038d3a12a915e98f794566f56a0ed12e0653ebAki Tuomivoid dsync_brain_master_send_mailbox(struct dsync_brain *brain)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (!dsync_brain_next_mailbox(brain, &box, &dsync_box)) {
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen dsync_ibc_send_end_of_list(brain->ibc, DSYNC_IBC_EOL_MAILBOX);
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 Sirainenbool dsync_boxes_need_sync(struct dsync_brain *brain,
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen if (brain->sync_type != DSYNC_BRAIN_SYNC_TYPE_CHANGED)
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->first_recent_uid != box2->first_recent_uid;
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainenmailbox_cache_field_name_cmp(const struct mailbox_cache_field *f1,
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainendsync_cache_fields_update(const struct dsync_mailbox *local_box,
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 if (array_count(&remote_box->cache_fields) == 0) {
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen /* remote has no cached fields. there's nothing to update. */
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 /* local has no cached fields. set them to same as remote. */
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen update->cache_updates = array_idx(&remote_sorted, 0);
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 for (li = ri = 0; li < local_count || ri < remote_count; ) {
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen strcmp(local_fields[li].name, remote_fields[ri].name);
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];
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen /* use local decision and timestamp */
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen } else if (ret < 0) {
ba4626cd5be3d225a7a89aa338d92b8fb411fd1cTimo Sirainen /* remote field doesn't exist */
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 array_append(&changes, &remote_fields[ri], 1);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(li == local_count && ri == remote_count);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen update->cache_updates = array_idx(&changes, 0);
7cd055a212d44067e2d94452c05691d696c9f699Timo Sirainenbool dsync_brain_mailbox_update_pre(struct dsync_brain *brain,
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 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 dsync_cache_fields_update(local_box, remote_box, &update);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen /* no changes */
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen i_error("Couldn't update mailbox %s metadata: %s",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainendsync_brain_slave_send_mailbox_lost(struct dsync_brain *brain,
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen memcpy(delete_box.mailbox_guid, dsync_box->mailbox_guid,
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen dsync_ibc_send_mailbox(brain->ibc, &delete_box);
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainenbool dsync_brain_slave_recv_mailbox(struct dsync_brain *brain)
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen if ((ret = dsync_ibc_recv_mailbox(brain->ibc, &dsync_box)) == 0)
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (dsync_brain_mailbox_alloc(brain, dsync_box->mailbox_guid,
14189e0d0af45ddcb888d026bd8d7e4609912ec5Timo Sirainen i_error("Couldn't allocate mailbox GUID %s: %s",
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen guid_128_to_string(dsync_box->mailbox_guid), error);
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen /* mailbox was probably deleted/renamed during sync */
2ccb478c35972517721ce415d81fcbd11a73fad3Timo Sirainen if (brain->backup_send && brain->no_backup_overwrite) {
01aca4a521410be85e1f39e37c662435d052f48aAki Tuomi "mailbox GUID %s with -1 sync",
8952d797eca36f997ec36569e783871b597a9216Timo Sirainen dsync_brain_slave_send_mailbox_lost(brain, dsync_box);
f0e811f0e306bb20d3da9c26353bdd5669132f29Timo Sirainen //FIXME: verify this from log, and if not log an error.
f0e811f0e306bb20d3da9c26353bdd5669132f29Timo Sirainen "Mailbox GUID %s was lost",
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_brain_slave_send_mailbox_lost(brain, dsync_box);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
1fb5e50695bbbc0da082e5a6f19f29d2bb2f6531Timo Sirainen if ((ret = dsync_box_get(box, &local_dsync_box)) <= 0) {
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen /* another process just deleted this mailbox? */
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen dsync_brain_slave_send_mailbox_lost(brain, dsync_box);
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen i_assert(memcmp(dsync_box->mailbox_guid, local_dsync_box.mailbox_guid,
b772ddf3cfb606dddaa465b317a0dc01bf06c6e4Timo Sirainen resync = !dsync_brain_mailbox_update_pre(brain, box, &local_dsync_box,
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 i_debug("brain %c: Skipping unchanged mailbox %s",
1128c114416bdc4df0b41d3e15429a1522e5cfe4Timo Sirainen dsync_ibc_send_mailbox(brain->ibc, &local_dsync_box);
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)
f9cf9852b0338910f1a710297374943d66fea480Timo Sirainen dsync_brain_slave_send_mailbox_lost(brain, dsync_box);