mdbox-sync.c revision 637455ebee0453f860c9bce0626c485e35fb83de
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2007-2010 Dovecot authors, see the included COPYING file */
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainendbox_sync_verify_expunge_guid(struct mdbox_sync_context *ctx, uint32_t seq,
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen mail_index_lookup_uid(ctx->sync_view, seq, &uid);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memcmp(data, guid_128, MAIL_GUID_128_SIZE) == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_set_critical(&ctx->mbox->storage->storage.storage,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Mailbox %s: Expunged GUID mismatch for UID %u: %s vs %s",
e12648867876aaec17e06ee4caef0bb60363449dTimo Sirainen ctx->mbox->storage->storage.files_corrupted = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int mdbox_sync_expunge(struct mdbox_sync_context *ctx, uint32_t seq,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (seq_range_exists(&ctx->expunged_seqs, seq)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* already marked as expunged in this sync */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (dbox_sync_verify_expunge_guid(ctx, seq, guid_128) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mdbox_mail_lookup(ctx->mbox, ctx->sync_view, seq, &map_uid) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen seq_range_array_add(&ctx->expunged_seqs, 0, seq);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_append(&ctx->expunged_map_uids, &map_uid, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int mdbox_sync_add(struct mdbox_sync_context *ctx,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (sync_rec->type != MAIL_INDEX_SYNC_TYPE_EXPUNGE) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* not interested */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!mail_index_lookup_seq_range(ctx->sync_view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* already expunged everything. nothing to do. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mdbox_sync_expunge(ctx, seq, sync_rec->guid_128) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int dbox_sync_mark_expunges(struct mdbox_sync_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int n;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen /* use a separate transaction here so that we can commit the changes
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen during map transaction */
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen trans = mail_index_transaction_begin(ctx->sync_view, flags);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen seq_range_array_iter_init(&iter, &ctx->expunged_seqs); n = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while (seq_range_array_iter_nth(&iter, n++, &seq)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_lookup_uid(ctx->sync_view, seq, &uid);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (mail_index_transaction_commit(&trans) < 0)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* do notifications after commit finished successfully */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen seq_range_array_iter_init(&iter, &ctx->expunged_seqs); n = 0;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen while (seq_range_array_iter_nth(&iter, n++, &seq)) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen mail_index_lookup_uid(ctx->sync_view, seq, &uid);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen box->v.sync_notify(box, uid, MAILBOX_SYNC_TYPE_EXPUNGE);
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainenstatic int mdbox_sync_index_finish_expunges(struct mdbox_sync_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct dbox_map_transaction_context *map_trans;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen map_trans = dbox_map_transaction_begin(ctx->mbox->storage->map, FALSE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = dbox_map_update_refcounts(map_trans, &ctx->expunged_map_uids, -1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* write refcount changes to map index */
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen /* write changes to mailbox index */
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen /* this finally finishes the map sync and makes it clear that the
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen map transaction was successfully finished. */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstatic int mdbox_sync_index(struct mdbox_sync_context *ctx)
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen /* newly created index file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* mark the newly seen messages as recent */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_index_lookup_seq_range(ctx->sync_view, hdr->first_recent_uid,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mailbox_set_recent_seq(&ctx->mbox->box, ctx->sync_view,
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen /* read all changes and group changes to same file_id together */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while (mail_index_sync_next(ctx->index_sync_ctx, &sync_rec)) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if ((ret = mdbox_sync_add(ctx, &sync_rec)) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret == 0 && array_count(&ctx->expunged_seqs) > 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (ctx->mbox->storage->storage.files_corrupted ? 0 : -1);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainenstatic int mdbox_refresh_header(struct mdbox_mailbox *mbox, bool retry)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = mbox->storage->storage.files_corrupted ? -1 : 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if (retry) {
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainenint mdbox_sync_begin(struct mdbox_mailbox *mbox, enum mdbox_sync_flags flags,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_storage *storage = mbox->box.storage;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rebuild = mdbox_refresh_header(mbox, TRUE) < 0 ||
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sync_flags = index_storage_get_sync_flags(&mbox->box);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!rebuild && (flags & MDBOX_SYNC_FLAG_FORCE) == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sync_flags |= MAIL_INDEX_SYNC_FLAG_REQUIRE_CHANGES;
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen /* don't write unnecessary dirty flag updates */
757726d9acbd04cf0d0d4be8ce14e11525476a0bTimo Sirainen sync_flags |= MAIL_INDEX_SYNC_FLAG_AVOID_FLAG_UPDATES;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0;; i++) {
685393de106e55b61f754d420e378d05bd462ebbTimo Sirainen /* now that we're locked, check again if we want to rebuild */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* failure. keep the index locked while we're doing a
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we'll need to rebuild storage too.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen try again from the beginning. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mbox->storage->storage.files_corrupted = TRUE;
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen mail_index_sync_rollback(&ctx->index_sync_ctx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "dbox %s: Storage keeps breaking",
b5ea11802f2bafbec06282a7b3b6704dc5fae584Timo Sirainen mail_index_sync_rollback(&ctx->index_sync_ctx);
b5ea11802f2bafbec06282a7b3b6704dc5fae584Timo Sirainenint mdbox_sync_finish(struct mdbox_sync_context **_ctx, bool success)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_index_sync_commit(&ctx->index_sync_ctx) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_set_index_error(&ctx->mbox->box);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_sync_rollback(&ctx->index_sync_ctx);
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainenint mdbox_sync(struct mdbox_mailbox *mbox, enum mdbox_sync_flags flags)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mdbox_sync_begin(mbox, flags, &sync_ctx) < 0)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenmdbox_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (ret == 0 && (index_mailbox_want_full_sync(&mbox->box, flags) ||
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FORCE_RESYNC) != 0)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen mdbox_sync_flags |= MDBOX_SYNC_FLAG_FORCE_REBUILD;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen return index_mailbox_sync_init(box, flags, ret < 0);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic int mdbox_sync_altmove_add_files(struct mdbox_storage *dstorage,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen struct mail_storage *storage = &dstorage->storage.storage;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen altmove_mtime = ioloop_time - dstorage->set->mdbox_altmove;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we want to quickly find the latest alt file, but we also want to
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen avoid accessing the alt storage as much as possible. so we'll do
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen this by finding the lowest numbered file (n) from primary storage.
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen hopefully one of n-[1..m] is appendable in alt storage. */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen "opendir(%s) failed: %m", dstorage->storage_dir);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen for (errno = 0; (d = readdir(dir)) != NULL; errno = 0) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (strncmp(d->d_name, MDBOX_MAIL_FILE_PREFIX,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen file_id = strtoul(d->d_name + strlen(MDBOX_MAIL_FILE_PREFIX),
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen "readdir(%s) failed: %m", dstorage->storage_dir);
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen "closedir(%s) failed: %m", dstorage->storage_dir);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenint mdbox_sync_purge(struct mail_storage *_storage)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mdbox_storage *storage = (struct mdbox_storage *)_storage;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen unsigned int i = 0;
} T_END;
return ret;