static int dsync_brain_try_next_mailbox(struct dsync_brain *brain, struct mailbox **box_r, struct dsync_mailbox *dsync_box_r) { enum mailbox_flags flags = 0; struct dsync_mailbox dsync_box; struct mailbox *box; struct dsync_mailbox_node *node; const char *vname = NULL; bool synced = FALSE; int ret; *box_r = NULL; while (dsync_mailbox_tree_iter_next(brain->local_tree_iter, &vname, &node)) { if (node->existence == DSYNC_MAILBOX_NODE_EXISTS && !guid_128_is_empty(node->mailbox_guid)) break; vname = NULL; } if (vname == NULL) { /* no more mailboxes */ dsync_mailbox_tree_iter_deinit(&brain->local_tree_iter); return -1; } if (brain->backup_send) { /* make sure mailbox isn't modified */ flags |= MAILBOX_FLAG_READONLY; } box = mailbox_alloc(node->ns->list, vname, flags); for (;;) { if ((ret = dsync_box_get(box, &dsync_box)) <= 0) { if (ret < 0) brain->failed = TRUE; mailbox_free(&box); return ret; } /* if mailbox's last_common_* state equals the current state, we can skip the mailbox */ if (!dsync_brain_has_mailbox_state_changed(brain, &dsync_box)) { mailbox_free(&box); return 0; } if (synced) { /* ok, the mailbox really changed */ break; } /* mailbox appears to have changed. do a full sync here and get the state again */ if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) { i_error("Can't sync mailbox %s: %s", mailbox_get_vname(box), mailbox_get_last_error(box, NULL)); brain->failed = TRUE; mailbox_free(&box); return -1; } synced = TRUE; } *box_r = box; *dsync_box_r = dsync_box; return 1; }
bool dsync_brain_slave_recv_mailbox(struct dsync_brain *brain) { const struct dsync_mailbox *dsync_box; struct dsync_mailbox local_dsync_box; struct mailbox *box; int ret; i_assert(!brain->master_brain); i_assert(brain->box == NULL); if ((ret = dsync_ibc_recv_mailbox(brain->ibc, &dsync_box)) == 0) return FALSE; if (ret < 0) { brain->state = DSYNC_STATE_DONE; return TRUE; } if (dsync_brain_mailbox_alloc(brain, dsync_box->mailbox_guid, &box) < 0) { i_assert(brain->failed); return TRUE; } if (box == NULL) { /* mailbox was probably deleted/renamed during sync */ //FIXME: verify this from log, and if not log an error. brain->changes_during_sync = TRUE; dsync_brain_slave_send_mailbox_lost(brain, dsync_box); return TRUE; } if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) { i_error("Can't sync mailbox %s: %s", mailbox_get_vname(box), mailbox_get_last_error(box, NULL)); mailbox_free(&box); brain->failed = TRUE; return TRUE; } if ((ret = dsync_box_get(box, &local_dsync_box)) <= 0) { mailbox_free(&box); if (ret < 0) { brain->failed = TRUE; return TRUE; } /* another process just deleted this mailbox? */ dsync_brain_slave_send_mailbox_lost(brain, dsync_box); return TRUE; } i_assert(local_dsync_box.uid_validity != 0); i_assert(memcmp(dsync_box->mailbox_guid, local_dsync_box.mailbox_guid, sizeof(dsync_box->mailbox_guid)) == 0); dsync_ibc_send_mailbox(brain->ibc, &local_dsync_box); dsync_brain_mailbox_update_pre(brain, box, &local_dsync_box, dsync_box); if (brain->sync_type == DSYNC_BRAIN_SYNC_TYPE_CHANGED && !dsync_boxes_need_sync(&local_dsync_box, dsync_box)) { /* no fields appear to have changed, skip this mailbox */ mailbox_free(&box); return TRUE; } /* start export/import */ dsync_brain_sync_mailbox_init(brain, box, &local_dsync_box, FALSE); if (dsync_brain_sync_mailbox_open(brain, dsync_box) < 0) return TRUE; brain->state = DSYNC_STATE_SYNC_MAILS; return TRUE; }
bool dsync_brain_slave_recv_mailbox(struct dsync_brain *brain) { const struct dsync_mailbox *dsync_box; struct dsync_mailbox local_dsync_box; struct mailbox *box; const char *error; int ret; i_assert(!brain->master_brain); i_assert(brain->box == NULL); if ((ret = dsync_ibc_recv_mailbox(brain->ibc, &dsync_box)) == 0) return FALSE; if (ret < 0) { brain->state = DSYNC_STATE_DONE; return TRUE; } if (dsync_brain_mailbox_alloc(brain, dsync_box->mailbox_guid, &box, &error) < 0) { i_error("Couldn't allocate mailbox GUID %s: %s", guid_128_to_string(dsync_box->mailbox_guid), error); i_assert(brain->failed); return TRUE; } if (box == NULL) { /* mailbox was probably deleted/renamed during sync */ if (brain->backup_send && brain->no_backup_overwrite) { if (brain->debug) { i_debug("brain %c: Ignore nonexistent " "mailbox GUID %s with -1 sync", brain->master_brain ? 'M' : 'S', guid_128_to_string(dsync_box->mailbox_guid)); } dsync_brain_slave_send_mailbox_lost(brain, dsync_box); return TRUE; } //FIXME: verify this from log, and if not log an error. if (brain->debug) { i_debug("brain %c: Change during sync: " "Mailbox GUID %s was lost", brain->master_brain ? 'M' : 'S', guid_128_to_string(dsync_box->mailbox_guid)); } brain->changes_during_sync = TRUE; dsync_brain_slave_send_mailbox_lost(brain, dsync_box); return TRUE; } if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) { i_error("Can't sync mailbox %s: %s", mailbox_get_vname(box), mailbox_get_last_error(box, NULL)); mailbox_free(&box); brain->failed = TRUE; return TRUE; } if ((ret = dsync_box_get(box, &local_dsync_box)) <= 0) { mailbox_free(&box); if (ret < 0) { brain->failed = TRUE; return TRUE; } /* another process just deleted this mailbox? */ dsync_brain_slave_send_mailbox_lost(brain, dsync_box); return TRUE; } i_assert(local_dsync_box.uid_validity != 0); i_assert(memcmp(dsync_box->mailbox_guid, local_dsync_box.mailbox_guid, sizeof(dsync_box->mailbox_guid)) == 0); dsync_ibc_send_mailbox(brain->ibc, &local_dsync_box); dsync_brain_mailbox_update_pre(brain, box, &local_dsync_box, dsync_box); if (!dsync_boxes_need_sync(brain, &local_dsync_box, dsync_box)) { /* no fields appear to have changed, skip this mailbox */ mailbox_free(&box); return TRUE; } /* start export/import */ dsync_brain_sync_mailbox_init(brain, box, &local_dsync_box, FALSE); if (dsync_brain_sync_mailbox_open(brain, dsync_box) < 0) return TRUE; brain->state = DSYNC_STATE_SYNC_MAILS; return TRUE; }