dsync-brain-mailbox-tree-sync.c revision e83126866761632b437e532dfdc30be01d14039d
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "lib.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "mail-namespace.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "mail-storage.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "dsync-mailbox-tree.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "dsync-brain-private.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic int
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainensync_create_box(struct mailbox *box, const guid_128_t mailbox_guid,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen uint32_t uid_validity)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mailbox_metadata metadata;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mailbox_update update;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen enum mail_error error;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *errstr;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen memset(&update, 0, sizeof(update));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen memcpy(update.mailbox_guid, mailbox_guid, sizeof(update.mailbox_guid));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen update.uid_validity = uid_validity;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (mailbox_create(box, &update, FALSE) < 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen errstr = mailbox_get_last_error(box, &error);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (error != MAIL_ERROR_EXISTS) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_error("Can't create mailbox %s: %s",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_get_vname(box), errstr);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* sync the mailbox so we can look up its latest status */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_error("Can't sync mailbox %s: %s",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_get_vname(box),
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_get_last_error(box, NULL));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* verify that the GUID is what we wanted. if it's not, it probably
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen means that the mailbox had already been created. then we'll use the
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen GUID that is higher.
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mismatching UIDVALIDITY is handled later, because we choose it by
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen checking which mailbox has more messages */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_error("Can't get mailbox GUID %s: %s",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_get_vname(box),
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_get_last_error(box, NULL));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (memcmp(mailbox_guid, metadata.guid, sizeof(metadata.guid)) > 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen memset(&update, 0, sizeof(update));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen memcpy(update.mailbox_guid, mailbox_guid,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen sizeof(update.mailbox_guid));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (mailbox_update(box, &update) < 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_error("Can't update mailbox GUID %s: %s",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_get_vname(box),
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_get_last_error(box, NULL));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenint dsync_brain_mailbox_tree_sync_change(struct dsync_brain *brain,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const struct dsync_mailbox_tree_sync_change *change)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mailbox *box = NULL, *destbox;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *errstr, *func_name = NULL, *storage_name;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen enum mail_error error;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int ret = -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen i_assert(!brain->backup_send);
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen switch (change->type) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen case DSYNC_MAILBOX_TREE_SYNC_TYPE_DELETE_BOX:
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* make sure we're deleting the correct mailbox */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = dsync_brain_mailbox_alloc(brain, change->mailbox_guid,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen &box);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (ret <= 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->changes_during_sync = TRUE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen break;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen case DSYNC_MAILBOX_TREE_SYNC_TYPE_DELETE_DIR:
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen storage_name = mailbox_list_get_storage_name(change->ns->list,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen change->full_name);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (mailbox_list_delete_dir(change->ns->list, storage_name) == 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen errstr = mailbox_list_get_last_error(change->ns->list, &error);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (error == MAIL_ERROR_NOTFOUND ||
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen error == MAIL_ERROR_EXISTS) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->changes_during_sync = TRUE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_error("Mailbox sync: mailbox_list_delete_dir failed: %s",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen errstr);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen default:
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box = mailbox_alloc(change->ns->list, change->full_name, 0);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen break;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen switch (change->type) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen case DSYNC_MAILBOX_TREE_SYNC_TYPE_CREATE_BOX:
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = sync_create_box(box, change->mailbox_guid,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen change->uid_validity);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_free(&box);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen case DSYNC_MAILBOX_TREE_SYNC_TYPE_CREATE_DIR:
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = mailbox_create(box, NULL, TRUE);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen func_name = "mailbox_create";
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen break;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen case DSYNC_MAILBOX_TREE_SYNC_TYPE_DELETE_BOX:
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = mailbox_delete(box);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen func_name = "mailbox_delete";
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen break;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen case DSYNC_MAILBOX_TREE_SYNC_TYPE_DELETE_DIR:
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_unreached();
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen case DSYNC_MAILBOX_TREE_SYNC_TYPE_RENAME:
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen destbox = mailbox_alloc(change->ns->list,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen change->rename_dest_name, 0);
71e88fae3be360e9a93b3398e743f99a6f05d2edTimo Sirainen ret = mailbox_rename(box, destbox);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen func_name = "mailbox_rename";
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_free(&destbox);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen break;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen case DSYNC_MAILBOX_TREE_SYNC_TYPE_SUBSCRIBE:
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = mailbox_set_subscribed(box, TRUE);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen func_name = "mailbox_set_subscribed";
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen break;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen case DSYNC_MAILBOX_TREE_SYNC_TYPE_UNSUBSCRIBE:
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = mailbox_set_subscribed(box, FALSE);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen func_name = "mailbox_set_subscribed";
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen break;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (ret < 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen errstr = mailbox_get_last_error(box, &error);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (error == MAIL_ERROR_EXISTS ||
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen error == MAIL_ERROR_NOTFOUND) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* mailbox was already created or was already deleted.
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen let the next sync figure out what to do */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->changes_during_sync = TRUE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_error("Mailbox %s sync: %s failed: %s",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_get_vname(box), func_name, errstr);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_free(&box);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}