Mercurial > dovecot > core-2.2
view src/lib-storage/index/index-transaction.c @ 10655:fc0ac73f0b36 HEAD
Added support for marking mailbox index deleted. Don't allow any changes after that.
This is going to help with race conditions when deleting mailboxes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 07 Feb 2010 03:25:32 +0200 |
parents | 615eef3139c2 |
children | e7f066508299 |
line wrap: on
line source
/* Copyright (c) 2003-2010 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "array.h" #include "index-storage.h" #include "index-mail.h" static void index_transaction_free(struct index_transaction_context *t) { mail_cache_view_close(t->cache_view); mail_index_view_close(&t->trans_view); array_free(&t->mailbox_ctx.module_contexts); i_free(t); } static int index_transaction_index_commit(struct mail_index_transaction *index_trans, struct mail_index_transaction_commit_result *result_r) { struct index_transaction_context *it = MAIL_STORAGE_CONTEXT(index_trans); struct mailbox_transaction_context *t = &it->mailbox_ctx; struct index_mailbox *ibox = (struct index_mailbox *)t->box; int ret = 0; if (t->save_ctx != NULL) { if (ibox->save_commit_pre(t->save_ctx) < 0) { t->save_ctx = NULL; ret = -1; } } i_assert(it->mail_ref_count == 0); if (ret < 0) it->super.rollback(it->trans); else { if (it->super.commit(it->trans, result_r) < 0) { mail_storage_set_index_error(ibox); ret = -1; } } if (t->save_ctx != NULL) ibox->save_commit_post(t->save_ctx, result_r); index_transaction_free(it); return ret; } static void index_transaction_index_rollback(struct mail_index_transaction *t) { struct index_transaction_context *it = MAIL_STORAGE_CONTEXT(t); struct index_mailbox *ibox = (struct index_mailbox *)it->mailbox_ctx.box; if (it->mailbox_ctx.save_ctx != NULL) ibox->save_rollback(it->mailbox_ctx.save_ctx); it->super.rollback(it->trans); index_transaction_free(it); } void index_transaction_init(struct index_transaction_context *it, struct mailbox *box, enum mailbox_transaction_flags flags) { struct index_mailbox *ibox = (struct index_mailbox *)box; enum mail_index_transaction_flags trans_flags; i_assert(box->opened); trans_flags = MAIL_INDEX_TRANSACTION_FLAG_AVOID_FLAG_UPDATES; if ((flags & MAILBOX_TRANSACTION_FLAG_HIDE) != 0) trans_flags |= MAIL_INDEX_TRANSACTION_FLAG_HIDE; if ((flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0) trans_flags |= MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL; if ((flags & MAILBOX_TRANSACTION_FLAG_REFRESH) != 0) (void)mail_index_refresh(ibox->index); it->trans = mail_index_transaction_begin(ibox->view, trans_flags); it->mailbox_ctx.box = &ibox->box; array_create(&it->mailbox_ctx.module_contexts, default_pool, sizeof(void *), 5); it->trans_view = mail_index_transaction_open_updated_view(it->trans); it->cache_view = mail_cache_view_open(ibox->cache, it->trans_view); it->cache_trans = mail_cache_get_transaction(it->cache_view, it->trans); /* set up after mail_cache_get_transaction(), so that we'll still have the cache_trans available in _index_commit() */ it->super = it->trans->v; it->trans->v.commit = index_transaction_index_commit; it->trans->v.rollback = index_transaction_index_rollback; MODULE_CONTEXT_SET(it->trans, mail_storage_mail_index_module, it); } struct mailbox_transaction_context * index_transaction_begin(struct mailbox *box, enum mailbox_transaction_flags flags) { struct index_transaction_context *it; it = i_new(struct index_transaction_context, 1); index_transaction_init(it, box, flags); return &it->mailbox_ctx; } int index_transaction_commit(struct mailbox_transaction_context *_t, struct mail_transaction_commit_changes *changes_r) { struct index_transaction_context *t = (struct index_transaction_context *)_t; struct mail_index_transaction *itrans = t->trans; struct index_mailbox *ibox = (struct index_mailbox *)_t->box; struct mail_index_transaction_commit_result result; int ret; memset(changes_r, 0, sizeof(*changes_r)); changes_r->pool = pool_alloconly_create("transaction changes", 1024); p_array_init(&changes_r->saved_uids, changes_r->pool, 32); _t->changes = changes_r; ret = mail_index_transaction_commit_full(&itrans, &result); if (ret < 0 && mail_index_is_deleted(ibox->index)) mailbox_set_deleted(&ibox->box); changes_r->ignored_uid_changes = result.ignored_uid_changes; changes_r->ignored_modseq_changes = result.ignored_modseq_changes; i_assert(ibox->box.transaction_count > 0 || ibox->view->transactions == 0); return ret; } void index_transaction_rollback(struct mailbox_transaction_context *_t) { struct index_transaction_context *t = (struct index_transaction_context *)_t; struct mail_index_transaction *itrans = t->trans; struct index_mailbox *ibox = (struct index_mailbox *)_t->box; mail_index_transaction_rollback(&itrans); i_assert(ibox->box.transaction_count > 0 || ibox->view->transactions == 0); } void index_transaction_set_max_modseq(struct mailbox_transaction_context *_t, uint64_t max_modseq, ARRAY_TYPE(seq_range) *seqs) { struct index_transaction_context *t = (struct index_transaction_context *)_t; mail_index_transaction_set_max_modseq(t->trans, max_modseq, seqs); }