cydir-sync.c revision e9fbe5e18b798728041b7e2ffc6c4fa964fc35a3
2435290e44809a9e6036dbb2701933c44cb0b0e7Stephan Bosch/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen#include "lib.h"
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen#include "ioloop.h"
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen#include "str.h"
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen#include "cydir-storage.h"
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen#include "cydir-sync.h"
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen#include "mailbox-recent-flags.h"
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainenstatic void cydir_sync_set_uidvalidity(struct cydir_sync_context *ctx)
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen{
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen uint32_t uid_validity = ioloop_time;
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen mail_index_update_header(ctx->trans,
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen offsetof(struct mail_index_header, uid_validity),
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen &uid_validity, sizeof(uid_validity), TRUE);
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen ctx->uid_validity = uid_validity;
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen}
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainenstatic string_t *cydir_get_path_prefix(struct cydir_mailbox *mbox)
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen{
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen string_t *path = str_new(default_pool, 256);
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen str_append(path, mailbox_get_path(&mbox->box));
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen str_append_c(path, '/');
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen return path;
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen}
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainenstatic void
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainencydir_sync_expunge(struct cydir_sync_context *ctx, uint32_t seq1, uint32_t seq2)
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen{
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen struct mailbox *box = &ctx->mbox->box;
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen uint32_t uid;
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen if (ctx->path == NULL) {
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen ctx->path = cydir_get_path_prefix(ctx->mbox);
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen ctx->path_dir_prefix_len = str_len(ctx->path);
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen }
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen for (; seq1 <= seq2; seq1++) {
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen mail_index_lookup_uid(ctx->sync_view, seq1, &uid);
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen str_truncate(ctx->path, ctx->path_dir_prefix_len);
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen str_printfa(ctx->path, "%u.", uid);
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen if (i_unlink_if_exists(str_c(ctx->path)) < 0) {
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen /* continue anyway */
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen } else {
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen if (box->v.sync_notify != NULL) {
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen box->v.sync_notify(box, uid,
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen MAILBOX_SYNC_TYPE_EXPUNGE);
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen }
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen mail_index_expunge(ctx->trans, seq1);
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen }
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen }
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen}
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainenstatic void cydir_sync_index(struct cydir_sync_context *ctx)
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen{
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen struct mailbox *box = &ctx->mbox->box;
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen const struct mail_index_header *hdr;
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen struct mail_index_sync_rec sync_rec;
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen uint32_t seq1, seq2;
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen hdr = mail_index_get_header(ctx->sync_view);
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen if (hdr->uid_validity != 0)
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen ctx->uid_validity = hdr->uid_validity;
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen else
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen cydir_sync_set_uidvalidity(ctx);
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen /* mark the newly seen messages as recent */
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen if (mail_index_lookup_seq_range(ctx->sync_view, hdr->first_recent_uid,
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen hdr->next_uid, &seq1, &seq2)) {
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen mailbox_recent_flags_set_seqs(&ctx->mbox->box, ctx->sync_view,
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen seq1, seq2);
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen }
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen while (mail_index_sync_next(ctx->index_sync_ctx, &sync_rec)) {
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen if (!mail_index_lookup_seq_range(ctx->sync_view,
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen sync_rec.uid1, sync_rec.uid2,
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen &seq1, &seq2)) {
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen /* already expunged, nothing to do. */
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen continue;
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen }
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen switch (sync_rec.type) {
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen cydir_sync_expunge(ctx, seq1, seq2);
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen break;
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen case MAIL_INDEX_SYNC_TYPE_FLAGS:
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen /* FIXME: should be bother calling sync_notify()? */
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen break;
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen }
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen }
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen if (box->v.sync_notify != NULL)
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen box->v.sync_notify(box, 0, 0);
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen}
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen
5329bb264c32fa887e53063ff53272160cb8d7e8Timo Sirainenint cydir_sync_begin(struct cydir_mailbox *mbox,
5329bb264c32fa887e53063ff53272160cb8d7e8Timo Sirainen struct cydir_sync_context **ctx_r, bool force)
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen{
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen struct cydir_sync_context *ctx;
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen enum mail_index_sync_flags sync_flags;
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen int ret;
6f213bf43fe6c0f2f2192330d591b4e62d72b4bcTimo Sirainen
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen ctx = i_new(struct cydir_sync_context, 1);
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen ctx->mbox = mbox;
5329bb264c32fa887e53063ff53272160cb8d7e8Timo Sirainen
5329bb264c32fa887e53063ff53272160cb8d7e8Timo Sirainen sync_flags = index_storage_get_sync_flags(&mbox->box) |
5329bb264c32fa887e53063ff53272160cb8d7e8Timo Sirainen MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY;
5329bb264c32fa887e53063ff53272160cb8d7e8Timo Sirainen if (!force)
5329bb264c32fa887e53063ff53272160cb8d7e8Timo Sirainen sync_flags |= MAIL_INDEX_SYNC_FLAG_REQUIRE_CHANGES;
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen ret = index_storage_expunged_sync_begin(&mbox->box, &ctx->index_sync_ctx,
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen &ctx->sync_view, &ctx->trans,
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen sync_flags);
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen if (ret <= 0) {
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen i_free(ctx);
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen *ctx_r = NULL;
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen return ret;
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen }
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen cydir_sync_index(ctx);
5329bb264c32fa887e53063ff53272160cb8d7e8Timo Sirainen index_storage_expunging_deinit(&mbox->box);
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen *ctx_r = ctx;
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen return 0;
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen}
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainenint cydir_sync_finish(struct cydir_sync_context **_ctx, bool success)
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen{
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen struct cydir_sync_context *ctx = *_ctx;
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen int ret = success ? 0 : -1;
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen *_ctx = NULL;
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen if (success) {
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen if (mail_index_sync_commit(&ctx->index_sync_ctx) < 0) {
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen mailbox_set_index_error(&ctx->mbox->box);
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen ret = -1;
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen }
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen } else {
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen mail_index_sync_rollback(&ctx->index_sync_ctx);
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen }
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen str_free(&ctx->path);
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen i_free(ctx);
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen return ret;
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen}
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainenstatic int cydir_sync(struct cydir_mailbox *mbox)
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen{
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen struct cydir_sync_context *sync_ctx;
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen if (cydir_sync_begin(mbox, &sync_ctx, FALSE) < 0)
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen return -1;
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen return sync_ctx == NULL ? 0 :
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen cydir_sync_finish(&sync_ctx, TRUE);
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen}
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainenstruct mailbox_sync_context *
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainencydir_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen{
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen struct cydir_mailbox *mbox = CYDIR_MAILBOX(box);
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen int ret = 0;
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen if (index_mailbox_want_full_sync(&mbox->box, flags))
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen ret = cydir_sync(mbox);
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen return index_mailbox_sync_init(box, flags, ret < 0);
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen}
5233c86a95d3865500c291f00d08b1f4c678a424Timo Sirainen