static void dsync_brain_sync_mailbox_init(struct dsync_brain *brain, struct mailbox *box, const struct dsync_mailbox *local_dsync_box, bool wait_for_remote_box) { const struct dsync_mailbox_state *state; i_assert(brain->box_importer == NULL); i_assert(brain->box_exporter == NULL); i_assert(box->synced); brain->box = box; brain->pre_box_state = brain->state; if (wait_for_remote_box) { brain->box_send_state = DSYNC_BOX_STATE_MAILBOX; brain->box_recv_state = DSYNC_BOX_STATE_MAILBOX; } else { dsync_brain_sync_init_box_states(brain); } brain->local_dsync_box = *local_dsync_box; memset(&brain->remote_dsync_box, 0, sizeof(brain->remote_dsync_box)); state = dsync_mailbox_state_find(brain, local_dsync_box->mailbox_guid); if (state != NULL) brain->mailbox_state = *state; else { memset(&brain->mailbox_state, 0, sizeof(brain->mailbox_state)); memcpy(brain->mailbox_state.mailbox_guid, local_dsync_box->mailbox_guid, sizeof(brain->mailbox_state.mailbox_guid)); brain->mailbox_state.last_uidvalidity = local_dsync_box->uid_validity; } }
static void dsync_brain_sync_mailbox_init_remote(struct dsync_brain *brain, const struct dsync_mailbox *remote_dsync_box) { enum dsync_mailbox_import_flags import_flags = 0; const struct dsync_mailbox_state *state; uint32_t last_common_uid; uint64_t last_common_modseq, last_common_pvt_modseq; i_assert(brain->box_importer == NULL); i_assert(brain->log_scan != NULL); i_assert(memcmp(brain->local_dsync_box.mailbox_guid, remote_dsync_box->mailbox_guid, sizeof(remote_dsync_box->mailbox_guid)) == 0); brain->remote_dsync_box = *remote_dsync_box; state = dsync_mailbox_state_find(brain, remote_dsync_box->mailbox_guid); if (state != NULL) { last_common_uid = state->last_common_uid; last_common_modseq = state->last_common_modseq; last_common_pvt_modseq = state->last_common_pvt_modseq; } else { last_common_uid = 0; last_common_modseq = 0; last_common_pvt_modseq = 0; } if (brain->mail_requests) import_flags |= DSYNC_MAILBOX_IMPORT_FLAG_WANT_MAIL_REQUESTS; if (brain->master_brain) import_flags |= DSYNC_MAILBOX_IMPORT_FLAG_MASTER_BRAIN; if (brain->backup_recv && !brain->no_backup_overwrite) import_flags |= DSYNC_MAILBOX_IMPORT_FLAG_REVERT_LOCAL_CHANGES; if (brain->debug) import_flags |= DSYNC_MAILBOX_IMPORT_FLAG_DEBUG; if (brain->local_dsync_box.have_save_guids && (remote_dsync_box->have_save_guids || (brain->backup_recv && remote_dsync_box->have_guids))) import_flags |= DSYNC_MAILBOX_IMPORT_FLAG_MAILS_HAVE_GUIDS; if (brain->local_dsync_box.have_only_guid128 || remote_dsync_box->have_only_guid128) import_flags |= DSYNC_MAILBOX_IMPORT_FLAG_MAILS_USE_GUID128; brain->box_importer = brain->backup_send ? NULL : dsync_mailbox_import_init(brain->box, brain->log_scan, last_common_uid, last_common_modseq, last_common_pvt_modseq, remote_dsync_box->uid_next, remote_dsync_box->first_recent_uid, remote_dsync_box->highest_modseq, remote_dsync_box->highest_pvt_modseq, import_flags); }
static bool dsync_brain_has_mailbox_state_changed(struct dsync_brain *brain, const struct dsync_mailbox *dsync_box) { const struct dsync_mailbox_state *state; if (brain->sync_type != DSYNC_BRAIN_SYNC_TYPE_STATE) return TRUE; state = dsync_mailbox_state_find(brain, dsync_box->mailbox_guid); return state == NULL || state->last_uidvalidity != dsync_box->uid_validity || state->last_common_uid+1 != dsync_box->uid_next || state->last_common_modseq != dsync_box->highest_modseq || state->last_common_pvt_modseq != dsync_box->highest_pvt_modseq; }
void dsync_brain_mailbox_update_pre(struct dsync_brain *brain, struct mailbox *box, const struct dsync_mailbox *local_box, const struct dsync_mailbox *remote_box) { struct mailbox_update update; const struct dsync_mailbox_state *state; memset(&update, 0, sizeof(update)); if (local_box->uid_validity != remote_box->uid_validity) { /* Keep the UIDVALIDITY for the mailbox that has more messages. If they equal, use the higher UIDVALIDITY. */ if (remote_box->messages_count > local_box->messages_count || (remote_box->messages_count == local_box->messages_count && remote_box->uid_validity > local_box->uid_validity)) update.uid_validity = remote_box->uid_validity; state = dsync_mailbox_state_find(brain, local_box->mailbox_guid); if (state != NULL && state->last_common_uid > 0) { /* we can't continue syncing this mailbox in this session, because the other side already started sending mailbox changes, but not for all mails. */ dsync_mailbox_state_remove(brain, local_box->mailbox_guid); // FIXME: handle this properly } } dsync_cache_fields_update(local_box, remote_box, &update); if (update.uid_validity == 0 && update.cache_updates == NULL) { /* no changes */ return; } if (mailbox_update(box, &update) < 0) { i_error("Couldn't update mailbox %s metadata: %s", mailbox_get_vname(box), mailbox_get_last_error(box, NULL)); brain->failed = TRUE; } }