bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
ea245d7a9683e7bb9cd74fcdf1a26d049b2947ebTimo Sirainenconst char *dsync_box_state_names[DSYNC_BOX_STATE_DONE+1] = {
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen "attributes",
5332128f69ad688cc024897c2a92f6b37ef8d05cTimo Sirainen "mail_requests",
5332128f69ad688cc024897c2a92f6b37ef8d05cTimo Sirainen "recv_last_common",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic bool dsync_brain_master_sync_recv_mailbox(struct dsync_brain *brain)
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen if ((ret = dsync_ibc_recv_mailbox(brain->ibc, &dsync_box)) == 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_error("Remote sent end-of-list instead of a mailbox");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (memcmp(dsync_box->mailbox_guid, brain->local_dsync_box.mailbox_guid,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_error("Remote sent mailbox with a wrong GUID");
280bc7d8b07490dfa5cf0fc20aee8e9e2d15aa99Aki Tuomi /* ignore this box */
280bc7d8b07490dfa5cf0fc20aee8e9e2d15aa99Aki Tuomi i_debug("brain %c: Ignoring missing remote box GUID %s",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* remote lost the mailbox. it's probably already deleted, but
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen verify it on next sync just to be sure */
4f7951e71128c120d8a502d6406cc603fcc8eb0bTimo Sirainen dsync_brain_set_changes_during_sync(brain, t_strdup_printf(
4f7951e71128c120d8a502d6406cc603fcc8eb0bTimo Sirainen "Remote lost mailbox GUID %s (maybe it was just deleted?)",
4f7951e71128c120d8a502d6406cc603fcc8eb0bTimo Sirainen guid_128_to_string(dsync_box->mailbox_guid)));
40440c0fee87be994ba7eb60fc3512a9355708aaTimo Sirainen resync = !dsync_brain_mailbox_update_pre(brain, brain->box,
f48fdb57185ca68e8c079e174f3e04da36646880Timo Sirainen if (!dsync_boxes_need_sync(brain, &brain->local_dsync_box, dsync_box)) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* no fields appear to have changed, skip this mailbox */
40440c0fee87be994ba7eb60fc3512a9355708aaTimo Sirainen if ((ret = dsync_brain_sync_mailbox_open(brain, dsync_box)) < 0)
4f7951e71128c120d8a502d6406cc603fcc8eb0bTimo Sirainen dsync_brain_set_changes_during_sync(brain, resync_reason);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainenstatic bool dsync_brain_recv_mailbox_attribute(struct dsync_brain *brain)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if ((ret = dsync_ibc_recv_mailbox_attribute(brain->ibc, &attr)) == 0)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen brain->box_recv_state = DSYNC_BOX_STATE_CHANGES;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (dsync_mailbox_import_attribute(brain->box_importer, attr) < 0)
189f639bdf2845b1e8587db5dfb2aedc1c573aa7Timo Sirainenstatic void dsync_brain_send_end_of_list(struct dsync_brain *brain,
e1bef591ed45c5baf6b5bdc69fb7fa5ff05df2b6Timo Sirainenstatic int dsync_brain_export_deinit(struct dsync_brain *brain)
e1bef591ed45c5baf6b5bdc69fb7fa5ff05df2b6Timo Sirainen if (dsync_mailbox_export_deinit(&brain->box_exporter,
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainenstatic void dsync_brain_send_mailbox_attribute(struct dsync_brain *brain)
e1bef591ed45c5baf6b5bdc69fb7fa5ff05df2b6Timo Sirainen while ((ret = dsync_mailbox_export_next_attr(brain->box_exporter, &attr)) > 0) {
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (dsync_ibc_send_mailbox_attribute(brain->ibc, attr) == 0)
189f639bdf2845b1e8587db5dfb2aedc1c573aa7Timo Sirainen dsync_brain_send_end_of_list(brain, DSYNC_IBC_EOL_MAILBOX_ATTRIBUTE);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen brain->box_send_state = DSYNC_BOX_STATE_CHANGES;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic bool dsync_brain_recv_mail_change(struct dsync_brain *brain)
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen if ((ret = dsync_ibc_recv_change(brain->ibc, &change)) == 0)
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen if (dsync_mailbox_import_changes_finish(brain->box_importer) < 0)
887a9fbbb2ca6afd53365ba2ccae0ef8728d6948Timo Sirainen if (brain->mail_requests && brain->box_exporter != NULL)
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen brain->box_recv_state = DSYNC_BOX_STATE_MAIL_REQUESTS;
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen brain->box_recv_state = DSYNC_BOX_STATE_MAILS;
0c47c2096714b50880d48d00ce0bf28349eb4aceTimo Sirainen if (dsync_mailbox_import_change(brain->box_importer, change) < 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic void dsync_brain_send_mail_change(struct dsync_brain *brain)
e1bef591ed45c5baf6b5bdc69fb7fa5ff05df2b6Timo Sirainen while ((ret = dsync_mailbox_export_next(brain->box_exporter, &change)) > 0) {
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen if (dsync_ibc_send_change(brain->ibc, change) == 0)
189f639bdf2845b1e8587db5dfb2aedc1c573aa7Timo Sirainen dsync_brain_send_end_of_list(brain, DSYNC_IBC_EOL_MAIL_CHANGES);
887a9fbbb2ca6afd53365ba2ccae0ef8728d6948Timo Sirainen if (brain->mail_requests && brain->box_importer != NULL)
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen brain->box_send_state = DSYNC_BOX_STATE_MAIL_REQUESTS;
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen brain->box_send_state = DSYNC_BOX_STATE_MAILS;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic bool dsync_brain_recv_mail_request(struct dsync_brain *brain)
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen if ((ret = dsync_ibc_recv_mail_request(brain->ibc, &request)) == 0)
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen brain->box_recv_state = brain->box_importer != NULL ?
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dsync_mailbox_export_want_mail(brain->box_exporter, request);
b16de4d0b7d86168f0c6837ea5e65ca2870e2b3dTimo Sirainenstatic bool dsync_brain_send_mail_request(struct dsync_brain *brain)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen while ((request = dsync_mailbox_import_next_request(brain->box_importer)) != NULL) {
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen if (dsync_ibc_send_mail_request(brain->ibc, request) == 0)
4292c8c20c9740e42a214d190036b0cc2b618dbfTimo Sirainen if (brain->box_recv_state < DSYNC_BOX_STATE_MAIL_REQUESTS)
189f639bdf2845b1e8587db5dfb2aedc1c573aa7Timo Sirainen dsync_brain_send_end_of_list(brain, DSYNC_IBC_EOL_MAIL_REQUESTS);
b16de4d0b7d86168f0c6837ea5e65ca2870e2b3dTimo Sirainen brain->box_send_state = DSYNC_BOX_STATE_MAILS;
b16de4d0b7d86168f0c6837ea5e65ca2870e2b3dTimo Sirainen i_assert(brain->box_recv_state != DSYNC_BOX_STATE_DONE);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic void dsync_brain_sync_half_finished(struct dsync_brain *brain)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (brain->box_recv_state < DSYNC_BOX_STATE_RECV_LAST_COMMON ||
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->box_send_state < DSYNC_BOX_STATE_RECV_LAST_COMMON)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* finished with this mailbox */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen memcpy(state.mailbox_guid, brain->local_dsync_box.mailbox_guid,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen state.last_uidvalidity = brain->local_dsync_box.uid_validity;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* this mailbox didn't exist on remote */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen state.last_common_uid = brain->local_dsync_box.uid_next-1;
e1bef591ed45c5baf6b5bdc69fb7fa5ff05df2b6Timo Sirainen if (dsync_mailbox_import_deinit(&brain->box_importer,
805d7834412465268486c50711962407ad13fbf6Timo Sirainen /* don't treat this as brain failure or the
805d7834412465268486c50711962407ad13fbf6Timo Sirainen state won't be sent to the other brain.
805d7834412465268486c50711962407ad13fbf6Timo Sirainen this also means we'll continue syncing the
805d7834412465268486c50711962407ad13fbf6Timo Sirainen following mailboxes. */
4f7951e71128c120d8a502d6406cc603fcc8eb0bTimo Sirainen dsync_brain_set_changes_during_sync(brain, changes_during_sync);
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen dsync_ibc_send_mailbox_state(brain->ibc, &state);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic bool dsync_brain_recv_mail(struct dsync_brain *brain)
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen if ((ret = dsync_ibc_recv_mail(brain->ibc, &mail)) == 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->box_recv_state = DSYNC_BOX_STATE_RECV_LAST_COMMON;
66e5a5a1bee411991ad08b6ee938e14d75941943Timo Sirainen brain->box_send_state >= DSYNC_BOX_STATE_RECV_LAST_COMMON) {
5332128f69ad688cc024897c2a92f6b37ef8d05cTimo Sirainen i_debug("brain %c: import mail uid %u guid %s",
5332128f69ad688cc024897c2a92f6b37ef8d05cTimo Sirainen brain->master_brain ? 'M' : 'S', mail->uid, mail->guid);
7ae6552482fe6e6a613f883335fdafdf9afbc7b7Timo Sirainen if (dsync_mailbox_import_mail(brain->box_importer, mail) < 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic bool dsync_brain_send_mail(struct dsync_brain *brain)
2fdcbdc25e34c7d83bb744f25b2d28335822c4a7Timo Sirainen brain->box_recv_state < DSYNC_BOX_STATE_MAILS) {
2fdcbdc25e34c7d83bb744f25b2d28335822c4a7Timo Sirainen /* wait for mail requests to finish. we could already start
2fdcbdc25e34c7d83bb744f25b2d28335822c4a7Timo Sirainen exporting, but then we're going to do quite a lot of
2fdcbdc25e34c7d83bb744f25b2d28335822c4a7Timo Sirainen separate searches. especially with pipe backend we'd do
2fdcbdc25e34c7d83bb744f25b2d28335822c4a7Timo Sirainen a separate search for each mail. */
e1bef591ed45c5baf6b5bdc69fb7fa5ff05df2b6Timo Sirainen while (dsync_mailbox_export_next_mail(brain->box_exporter, &mail) > 0) {
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen if (dsync_ibc_send_mail(brain->ibc, mail) == 0)
189f639bdf2845b1e8587db5dfb2aedc1c573aa7Timo Sirainen dsync_brain_send_end_of_list(brain, DSYNC_IBC_EOL_MAILS);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic bool dsync_brain_recv_last_common(struct dsync_brain *brain)
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen if ((ret = dsync_ibc_recv_mailbox_state(brain->ibc, &state)) == 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_error("Remote sent end-of-list instead of a mailbox state");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_assert(brain->box_send_state == DSYNC_BOX_STATE_DONE);
34421746925a2e1850549fa0fa07ddeeb1a271e2Timo Sirainen i_assert(memcmp(state.mailbox_guid, brain->local_dsync_box.mailbox_guid,
34421746925a2e1850549fa0fa07ddeeb1a271e2Timo Sirainen /* normally the last_common_* values should be the same in local and
34421746925a2e1850549fa0fa07ddeeb1a271e2Timo Sirainen remote, but during unexpected changes they may differ. use the
34421746925a2e1850549fa0fa07ddeeb1a271e2Timo Sirainen values that are lower as the final state. */
34421746925a2e1850549fa0fa07ddeeb1a271e2Timo Sirainen if (brain->mailbox_state.last_common_uid > state.last_common_uid)
34421746925a2e1850549fa0fa07ddeeb1a271e2Timo Sirainen brain->mailbox_state.last_common_uid = state.last_common_uid;
34421746925a2e1850549fa0fa07ddeeb1a271e2Timo Sirainen if (brain->mailbox_state.last_common_modseq > state.last_common_modseq)
34421746925a2e1850549fa0fa07ddeeb1a271e2Timo Sirainen brain->mailbox_state.last_common_modseq = state.last_common_modseq;
34421746925a2e1850549fa0fa07ddeeb1a271e2Timo Sirainen if (brain->mailbox_state.last_common_pvt_modseq > state.last_common_pvt_modseq)
34421746925a2e1850549fa0fa07ddeeb1a271e2Timo Sirainen brain->mailbox_state.last_common_pvt_modseq = state.last_common_pvt_modseq;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenbool dsync_brain_sync_mails(struct dsync_brain *brain)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen changed = dsync_brain_master_sync_recv_mailbox(brain);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen changed = dsync_brain_recv_mailbox_attribute(brain);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen changed = dsync_brain_recv_mail_change(brain);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen changed = dsync_brain_recv_mail_request(brain);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen changed = dsync_brain_recv_last_common(brain);
66088eb6144f98adbbd9799f902c87cbdd0a4eebTimo Sirainen if (!dsync_ibc_is_send_queue_full(brain->ibc) && !brain->failed) {
66088eb6144f98adbbd9799f902c87cbdd0a4eebTimo Sirainen /* wait for mailbox to be received first */