cydir-sync.c revision cc977f55ce66b63e8b37c20fce58d0ef516f0f29
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx/* Copyright (c) 2007-2008 Dovecot authors, see the included COPYING file */
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx#include "lib.h"
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx#include "ioloop.h"
0d2f4bc964616a7fec76406480264fcaa2cfbc14ff#include "str.h"
0d2f4bc964616a7fec76406480264fcaa2cfbc14ff#include "cydir-storage.h"
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx#include "cydir-sync.h"
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhxstatic void cydir_sync_set_uidvalidity(struct cydir_sync_context *ctx)
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx{
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx uint32_t uid_validity = ioloop_time;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx mail_index_update_header(ctx->trans,
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx offsetof(struct mail_index_header, uid_validity),
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx &uid_validity, sizeof(uid_validity), TRUE);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx ctx->uid_validity = uid_validity;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx}
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhxstatic string_t *cydir_get_path_prefix(struct cydir_mailbox *mbox)
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx{
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx string_t *path = str_new(default_pool, 256);
0d2f4bc964616a7fec76406480264fcaa2cfbc14ff const char *dir;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx dir = mailbox_list_get_path(mbox->storage->storage.list,
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx mbox->ibox.box.name,
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx MAILBOX_LIST_PATH_TYPE_MAILBOX);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx str_append(path, dir);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx str_append_c(path, '/');
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx return path;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx}
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhxstatic void
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhxcydir_sync_expunge(struct cydir_sync_context *ctx, uint32_t seq1, uint32_t seq2)
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx{
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx struct mailbox *box = &ctx->mbox->ibox.box;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx uint32_t uid;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx if (ctx->path == NULL) {
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx ctx->path = cydir_get_path_prefix(ctx->mbox);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx ctx->path_dir_prefix_len = str_len(ctx->path);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx }
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx for (; seq1 <= seq2; seq1++) {
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx mail_index_lookup_uid(ctx->sync_view, seq1, &uid);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx str_truncate(ctx->path, ctx->path_dir_prefix_len);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx str_printfa(ctx->path, "%u.", uid);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx if (unlink(str_c(ctx->path)) == 0) {
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx if (box->v.sync_notify != NULL) {
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx box->v.sync_notify(box, uid,
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx MAILBOX_SYNC_TYPE_EXPUNGE);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx }
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx mail_index_expunge(ctx->trans, seq1);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx } else if (errno != ENOENT) {
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx mail_storage_set_critical(&ctx->mbox->storage->storage,
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx "unlink(%s) failed: %m", str_c(ctx->path));
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx /* continue anyway */
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx }
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx }
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx}
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhxstatic void cydir_sync_index(struct cydir_sync_context *ctx)
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx{
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx struct mailbox *box = &ctx->mbox->ibox.box;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx const struct mail_index_header *hdr;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx struct mail_index_sync_rec sync_rec;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx uint32_t seq1, seq2;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx hdr = mail_index_get_header(ctx->sync_view);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx if (hdr->uid_validity != 0)
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx ctx->uid_validity = hdr->uid_validity;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx else
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx cydir_sync_set_uidvalidity(ctx);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx /* mark the newly seen messages as recent */
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx if (mail_index_lookup_seq_range(ctx->sync_view, hdr->first_recent_uid,
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx hdr->next_uid, &seq1, &seq2)) {
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx index_mailbox_set_recent_seq(&ctx->mbox->ibox, ctx->sync_view,
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx seq1, seq2);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx }
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx while (mail_index_sync_next(ctx->index_sync_ctx, &sync_rec)) {
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx if (!mail_index_lookup_seq_range(ctx->sync_view,
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx sync_rec.uid1, sync_rec.uid2,
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx &seq1, &seq2)) {
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx /* already expunged, nothing to do. */
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx continue;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx }
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx switch (sync_rec.type) {
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx case MAIL_INDEX_SYNC_TYPE_APPEND:
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx /* don't care */
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx break;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx cydir_sync_expunge(ctx, seq1, seq2);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx break;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx case MAIL_INDEX_SYNC_TYPE_FLAGS:
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx /* FIXME: should be bother calling sync_notify()? */
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx break;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx }
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx }
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx if (box->v.sync_notify != NULL)
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx box->v.sync_notify(box, 0, 0);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx}
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhxint cydir_sync_begin(struct cydir_mailbox *mbox,
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx struct cydir_sync_context **ctx_r, bool force)
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx{
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx struct cydir_sync_context *ctx;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx enum mail_index_sync_flags sync_flags;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx int ret;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx ctx = i_new(struct cydir_sync_context, 1);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx ctx->mbox = mbox;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx sync_flags = MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx if (!mbox->ibox.keep_recent)
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx sync_flags |= MAIL_INDEX_SYNC_FLAG_DROP_RECENT;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx if (!force)
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx sync_flags |= MAIL_INDEX_SYNC_FLAG_REQUIRE_CHANGES;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx ret = mail_index_sync_begin(mbox->ibox.index, &ctx->index_sync_ctx,
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx &ctx->sync_view, &ctx->trans,
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx sync_flags);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx if (ret <= 0) {
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx if (ret < 0)
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx mail_storage_set_index_error(&mbox->ibox);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx i_free(ctx);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx *ctx_r = NULL;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx return ret;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx }
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx cydir_sync_index(ctx);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx *ctx_r = ctx;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx return 0;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx}
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhxint cydir_sync_finish(struct cydir_sync_context **_ctx, bool success)
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx{
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx struct cydir_sync_context *ctx = *_ctx;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx int ret = success ? 0 : -1;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx *_ctx = NULL;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx if (success) {
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx if (mail_index_sync_commit(&ctx->index_sync_ctx) < 0) {
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx mail_storage_set_index_error(&ctx->mbox->ibox);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx ret = -1;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx }
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx } else {
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx mail_index_sync_rollback(&ctx->index_sync_ctx);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx }
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx if (ctx->path != NULL)
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx str_free(&ctx->path);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx i_free(ctx);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx return 0;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx}
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhxstatic int cydir_sync(struct cydir_mailbox *mbox)
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx{
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx struct cydir_sync_context *sync_ctx;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx if (cydir_sync_begin(mbox, &sync_ctx, FALSE) < 0)
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx return -1;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx return sync_ctx == NULL ? 0 :
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx cydir_sync_finish(&sync_ctx, TRUE);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx}
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhxstruct mailbox_sync_context *
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhxcydir_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx{
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx struct cydir_mailbox *mbox = (struct cydir_mailbox *)box;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx int ret = 0;
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx if (!box->opened)
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx index_storage_mailbox_open(&mbox->ibox);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx if (index_mailbox_want_full_sync(&mbox->ibox, flags))
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx ret = cydir_sync(mbox);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx return index_mailbox_sync_init(box, flags, ret < 0);
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx}
516fc7f3e48e25d0375ea3f93ead33ec38bc597bhx