Esempio n. 1
0
static int mdbox_sync_try_begin(struct mdbox_sync_context *ctx,
				enum mail_index_sync_flags sync_flags)
{
	struct mdbox_mailbox *mbox = ctx->mbox;
	int ret;

	ret = mail_index_sync_begin(mbox->box.index, &ctx->index_sync_ctx,
				    &ctx->sync_view, &ctx->trans, sync_flags);
	if (mail_index_reset_fscked(mbox->box.index))
		mdbox_storage_set_corrupted(mbox->storage);
	if (ret < 0) {
		mailbox_set_index_error(&mbox->box);
		return -1;
	}
	if (ret == 0) {
		/* nothing to do */
		return 0;
	}

	if (!mdbox_map_atomic_is_locked(ctx->atomic) &&
	    mail_index_sync_has_expunges(ctx->index_sync_ctx)) {
		/* we have expunges, so we need to write to map.
		   it needs to be locked before mailbox index. */
		mail_index_sync_rollback(&ctx->index_sync_ctx);
		if (mdbox_map_atomic_lock(ctx->atomic) < 0)
			return -1;
		return mdbox_sync_try_begin(ctx, sync_flags);
	}
	return 1;
}
Esempio n. 2
0
int mdbox_sync_finish(struct mdbox_sync_context **_ctx, bool success)
{
	struct mdbox_sync_context *ctx = *_ctx;
	int ret = success ? 0 : -1;

	*_ctx = NULL;

	if (success) {
		if (mail_index_sync_commit(&ctx->index_sync_ctx) < 0) {
			mailbox_set_index_error(&ctx->mbox->box);
			ret = -1;
		}
	} else {
		mail_index_sync_rollback(&ctx->index_sync_ctx);
	}

	i_free(ctx);
	return ret;
}
Esempio n. 3
0
static int maildir_sync_index_finish(struct maildir_index_sync_context *ctx,
				     bool success)
{
	struct maildir_mailbox *mbox = ctx->mbox;
	unsigned int time_diff;
	int ret = success ? 0 : -1;

	time_diff = time(NULL) - ctx->start_time;
	if (time_diff >= MAILDIR_SYNC_TIME_WARN_SECS) {
		i_warning("Maildir %s: Synchronization took %u seconds "
			  "(%u new msgs, %u flag change attempts, "
			  "%u expunge attempts)",
			  mailbox_get_path(&ctx->mbox->box), time_diff,
			  ctx->new_msgs_count, ctx->flag_change_count,
			  ctx->expunge_count);
		mail_index_sync_no_warning(ctx->sync_ctx);
	}

	if (ret < 0)
		mail_index_sync_rollback(&ctx->sync_ctx);
	else {
		maildir_sync_index_update_ext_header(ctx);

		/* Set syncing_commit=TRUE so that if any sync callbacks try
		   to access mails which got lost (eg. expunge callback trying
		   to open the file which was just unlinked) we don't try to
		   start a second index sync and crash. */
		mbox->syncing_commit = TRUE;
		if (mail_index_sync_commit(&ctx->sync_ctx) < 0) {
			mailbox_set_index_error(&mbox->box);
			ret = -1;
		}
		mbox->syncing_commit = FALSE;
	}

	index_storage_expunging_deinit(&mbox->box);
	maildir_keywords_sync_deinit(&ctx->keywords_sync_ctx);
	index_sync_changes_deinit(&ctx->sync_changes);
	i_free(ctx);
	return ret;
}
Esempio n. 4
0
int mdbox_sync_begin(struct mdbox_mailbox *mbox, enum mdbox_sync_flags flags,
		     struct mdbox_map_atomic_context *atomic,
		     struct mdbox_sync_context **ctx_r)
{
	struct mail_storage *storage = mbox->box.storage;
	struct mdbox_sync_context *ctx;
	enum mail_index_sync_flags sync_flags;
	int ret;
	bool rebuild, storage_rebuilt = FALSE;

	*ctx_r = NULL;

	/* avoid race conditions with mailbox creation, don't check for dbox
	   headers until syncing has locked the mailbox */
	rebuild = mbox->storage->corrupted ||
		(flags & MDBOX_SYNC_FLAG_FORCE_REBUILD) != 0;
	if (rebuild && (flags & MDBOX_SYNC_FLAG_NO_REBUILD) == 0) {
		if (mdbox_storage_rebuild_in_context(mbox->storage, atomic) < 0)
			return -1;
		index_mailbox_reset_uidvalidity(&mbox->box);
		storage_rebuilt = TRUE;
	}

	ctx = i_new(struct mdbox_sync_context, 1);
	ctx->mbox = mbox;
	ctx->flags = flags;
	ctx->atomic = atomic;

	sync_flags = index_storage_get_sync_flags(&mbox->box);
	if (!rebuild && (flags & MDBOX_SYNC_FLAG_FORCE) == 0)
		sync_flags |= MAIL_INDEX_SYNC_FLAG_REQUIRE_CHANGES;
	if ((flags & MDBOX_SYNC_FLAG_FSYNC) != 0)
		sync_flags |= MAIL_INDEX_SYNC_FLAG_FSYNC;
	/* don't write unnecessary dirty flag updates */
	sync_flags |= MAIL_INDEX_SYNC_FLAG_AVOID_FLAG_UPDATES;

	ret = mdbox_sync_try_begin(ctx, sync_flags);
	if (ret <= 0) {
		/* failed / nothing to do */
		i_free(ctx);
		return ret;
	}

	if ((ret = mdbox_sync_index(ctx)) <= 0) {
		mail_index_sync_rollback(&ctx->index_sync_ctx);
		i_free_and_null(ctx);

		if (ret < 0)
			return -1;

		/* corrupted */
		if (storage_rebuilt) {
			mail_storage_set_critical(storage,
				"mdbox %s: Storage keeps breaking",
				mailbox_get_path(&mbox->box));
			return -1;
		}

		/* we'll need to rebuild storage.
		   try again from the beginning. */
		mdbox_storage_set_corrupted(mbox->storage);
		if ((flags & MDBOX_SYNC_FLAG_NO_REBUILD) != 0) {
			mail_storage_set_critical(storage,
				"mdbox %s: Can't rebuild storage",
				mailbox_get_path(&mbox->box));
			return -1;
		}
		return mdbox_sync_begin(mbox, flags, atomic, ctx_r);
	}

	*ctx_r = ctx;
	return 0;
}