From: Timo Sirainen Date: Fri, 31 Jul 2009 02:10:11 +0000 (-0400) Subject: index-storage: Simplified the way transactions are are created/finished. X-Git-Tag: 2.0.alpha1~344 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=eb0816090cf5a549280ad783b9aa6fec199d36ba;p=thirdparty%2Fdovecot%2Fcore.git index-storage: Simplified the way transactions are are created/finished. Removed also mail_storage.class_init/deinit since they're no longer used for anything. --HG-- branch : HEAD --- diff --git a/src/lib-storage/index/cydir/Makefile.am b/src/lib-storage/index/cydir/Makefile.am index 116230f82b..32a7ca1e11 100644 --- a/src/lib-storage/index/cydir/Makefile.am +++ b/src/lib-storage/index/cydir/Makefile.am @@ -12,8 +12,7 @@ libstorage_cydir_la_SOURCES = \ cydir-mail.c \ cydir-save.c \ cydir-sync.c \ - cydir-storage.c \ - cydir-transaction.c + cydir-storage.c headers = \ cydir-storage.h \ diff --git a/src/lib-storage/index/cydir/cydir-save.c b/src/lib-storage/index/cydir/cydir-save.c index 62f13d53ed..e7d4437318 100644 --- a/src/lib-storage/index/cydir/cydir-save.c +++ b/src/lib-storage/index/cydir/cydir-save.c @@ -57,24 +57,25 @@ cydir_get_save_path(struct cydir_save_context *ctx, unsigned int num) } struct mail_save_context * -cydir_save_alloc(struct mailbox_transaction_context *_t) +cydir_save_alloc(struct mailbox_transaction_context *t) { - struct cydir_transaction_context *t = - (struct cydir_transaction_context *)_t; - struct cydir_mailbox *mbox = (struct cydir_mailbox *)_t->box; - struct cydir_save_context *ctx = t->save_ctx; - - i_assert((_t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0); - - if (t->save_ctx != NULL) - return &t->save_ctx->ctx; - - ctx = t->save_ctx = i_new(struct cydir_save_context, 1); - ctx->ctx.transaction = &t->ictx.mailbox_ctx; - ctx->mbox = mbox; - ctx->trans = t->ictx.trans; - ctx->tmp_basename = cydir_generate_tmp_filename(); - return &ctx->ctx; + struct index_transaction_context *it = + (struct index_transaction_context *)t; + struct cydir_mailbox *mbox = (struct cydir_mailbox *)t->box; + struct cydir_save_context *ctx = + (struct cydir_save_context *)t->save_ctx; + + i_assert((t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0); + + if (t->save_ctx == NULL) { + ctx = i_new(struct cydir_save_context, 1); + ctx->ctx.transaction = t; + ctx->mbox = mbox; + ctx->trans = it->trans; + ctx->tmp_basename = cydir_generate_tmp_filename(); + t->save_ctx = &ctx->ctx; + } + return t->save_ctx; } int cydir_save_begin(struct mail_save_context *_ctx, struct istream *input) @@ -232,9 +233,10 @@ void cydir_save_cancel(struct mail_save_context *_ctx) (void)cydir_save_finish(_ctx); } -int cydir_transaction_save_commit_pre(struct cydir_save_context *ctx) +int cydir_transaction_save_commit_pre(struct mail_save_context *_ctx) { - struct mailbox_transaction_context *_t = ctx->ctx.transaction; + struct cydir_save_context *ctx = (struct cydir_save_context *)_ctx; + struct mailbox_transaction_context *_t = _ctx->transaction; const struct mail_index_header *hdr; struct seq_range_iter iter; uint32_t uid; @@ -246,7 +248,7 @@ int cydir_transaction_save_commit_pre(struct cydir_save_context *ctx) if (cydir_sync_begin(ctx->mbox, &ctx->sync_ctx, TRUE) < 0) { ctx->failed = TRUE; - cydir_transaction_save_rollback(ctx); + cydir_transaction_save_rollback(_ctx); return -1; } @@ -280,7 +282,7 @@ int cydir_transaction_save_commit_pre(struct cydir_save_context *ctx) "rename(%s, %s) failed: %m", str_c(src_path), str_c(dest_path)); ctx->failed = TRUE; - cydir_transaction_save_rollback(ctx); + cydir_transaction_save_rollback(_ctx); return -1; } } @@ -290,16 +292,20 @@ int cydir_transaction_save_commit_pre(struct cydir_save_context *ctx) return 0; } -void cydir_transaction_save_commit_post(struct cydir_save_context *ctx) +void cydir_transaction_save_commit_post(struct mail_save_context *_ctx) { - ctx->ctx.transaction = NULL; /* transaction is already freed */ + struct cydir_save_context *ctx = (struct cydir_save_context *)_ctx; + + _ctx->transaction = NULL; /* transaction is already freed */ (void)cydir_sync_finish(&ctx->sync_ctx, TRUE); - cydir_transaction_save_rollback(ctx); + cydir_transaction_save_rollback(_ctx); } -void cydir_transaction_save_rollback(struct cydir_save_context *ctx) +void cydir_transaction_save_rollback(struct mail_save_context *_ctx) { + struct cydir_save_context *ctx = (struct cydir_save_context *)_ctx; + if (!ctx->finished) cydir_save_cancel(&ctx->ctx); diff --git a/src/lib-storage/index/cydir/cydir-storage.c b/src/lib-storage/index/cydir/cydir-storage.c index 1a1d343d4b..c5e8d0e58c 100644 --- a/src/lib-storage/index/cydir/cydir-storage.c +++ b/src/lib-storage/index/cydir/cydir-storage.c @@ -86,6 +86,10 @@ cydir_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list, mbox->ibox.box.list = list; mbox->ibox.mail_vfuncs = &cydir_mail_vfuncs; + mbox->ibox.save_commit_pre = cydir_transaction_save_commit_pre; + mbox->ibox.save_commit_post = cydir_transaction_save_commit_post; + mbox->ibox.save_rollback = cydir_transaction_save_rollback; + index_storage_mailbox_alloc(&mbox->ibox, name, input, flags, CYDIR_INDEX_PREFIX); mail_index_set_fsync_types(mbox->ibox.index, @@ -332,16 +336,6 @@ static int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx return ret; } -static void cydir_class_init(void) -{ - cydir_transaction_class_init(); -} - -static void cydir_class_deinit(void) -{ - cydir_transaction_class_deinit(); -} - static void cydir_storage_add_list(struct mail_storage *storage ATTR_UNUSED, struct mailbox_list *list) { @@ -362,8 +356,6 @@ struct mail_storage cydir_storage = { { NULL, - cydir_class_init, - cydir_class_deinit, cydir_storage_alloc, NULL, index_storage_destroy, diff --git a/src/lib-storage/index/cydir/cydir-storage.h b/src/lib-storage/index/cydir/cydir-storage.h index c601892fd1..47e649105b 100644 --- a/src/lib-storage/index/cydir/cydir-storage.h +++ b/src/lib-storage/index/cydir/cydir-storage.h @@ -18,19 +18,8 @@ struct cydir_mailbox { struct cydir_storage *storage; }; -struct cydir_transaction_context { - struct index_transaction_context ictx; - union mail_index_transaction_module_context module_ctx; - - uint32_t first_saved_mail_seq; - struct cydir_save_context *save_ctx; -}; - extern struct mail_vfuncs cydir_mail_vfuncs; -void cydir_transaction_class_init(void); -void cydir_transaction_class_deinit(void); - struct mail_save_context * cydir_save_alloc(struct mailbox_transaction_context *_t); int cydir_save_begin(struct mail_save_context *ctx, struct istream *input); @@ -38,8 +27,8 @@ int cydir_save_continue(struct mail_save_context *ctx); int cydir_save_finish(struct mail_save_context *ctx); void cydir_save_cancel(struct mail_save_context *ctx); -int cydir_transaction_save_commit_pre(struct cydir_save_context *ctx); -void cydir_transaction_save_commit_post(struct cydir_save_context *ctx); -void cydir_transaction_save_rollback(struct cydir_save_context *ctx); +int cydir_transaction_save_commit_pre(struct mail_save_context *ctx); +void cydir_transaction_save_commit_post(struct mail_save_context *ctx); +void cydir_transaction_save_rollback(struct mail_save_context *ctx); #endif diff --git a/src/lib-storage/index/cydir/cydir-transaction.c b/src/lib-storage/index/cydir/cydir-transaction.c deleted file mode 100644 index 4966c16c9d..0000000000 --- a/src/lib-storage/index/cydir/cydir-transaction.c +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "array.h" -#include "cydir-storage.h" -#include "cydir-sync.h" - -static void (*next_hook_mail_index_transaction_created) - (struct mail_index_transaction *t) = NULL; - -static int cydir_transaction_commit(struct mail_index_transaction *t, - uint32_t *log_file_seq_r, - uoff_t *log_file_offset_r) -{ - struct cydir_transaction_context *dt = MAIL_STORAGE_CONTEXT(t); - struct cydir_save_context *save_ctx; - int ret = 0; - - if (dt->save_ctx != NULL) { - if (cydir_transaction_save_commit_pre(dt->save_ctx) < 0) { - dt->save_ctx = NULL; - ret = -1; - } - } - - save_ctx = dt->save_ctx; - - if (ret < 0) - index_transaction_finish_rollback(&dt->ictx); - else { - if (index_transaction_finish_commit(&dt->ictx, log_file_seq_r, - log_file_offset_r) < 0) - ret = -1; - } - - /* transaction is destroyed now. */ - dt = NULL; - - if (save_ctx != NULL) { - /* unlock uidlist file after writing to transaction log, - to make sure we don't write uids in wrong order. */ - cydir_transaction_save_commit_post(save_ctx); - } - return ret; -} - -static void cydir_transaction_rollback(struct mail_index_transaction *t) -{ - struct cydir_transaction_context *dt = MAIL_STORAGE_CONTEXT(t); - - if (dt->save_ctx != NULL) - cydir_transaction_save_rollback(dt->save_ctx); - - index_transaction_finish_rollback(&dt->ictx); -} - -static void cydir_transaction_created(struct mail_index_transaction *t) -{ - struct mailbox *box = MAIL_STORAGE_CONTEXT(t->view); - - /* index can be for mailbox list index, in which case box=NULL */ - if (box != NULL && - strcmp(box->storage->name, CYDIR_STORAGE_NAME) == 0) { - struct cydir_mailbox *cydir = (struct cydir_mailbox *)box; - struct cydir_transaction_context *mt; - - mt = i_new(struct cydir_transaction_context, 1); - mt->ictx.trans = t; - index_transaction_init(&mt->ictx, &cydir->ibox); - - t->v.commit = cydir_transaction_commit; - t->v.rollback = cydir_transaction_rollback; - MODULE_CONTEXT_SET(t, mail_storage_mail_index_module, mt); - } - - if (next_hook_mail_index_transaction_created != NULL) - next_hook_mail_index_transaction_created(t); -} - -void cydir_transaction_class_init(void) -{ - next_hook_mail_index_transaction_created = - hook_mail_index_transaction_created; - hook_mail_index_transaction_created = cydir_transaction_created; -} - -void cydir_transaction_class_deinit(void) -{ - i_assert(hook_mail_index_transaction_created == - cydir_transaction_created); - hook_mail_index_transaction_created = - next_hook_mail_index_transaction_created; -} diff --git a/src/lib-storage/index/dbox/Makefile.am b/src/lib-storage/index/dbox/Makefile.am index 83a4ea14c8..2db73f9f28 100644 --- a/src/lib-storage/index/dbox/Makefile.am +++ b/src/lib-storage/index/dbox/Makefile.am @@ -21,8 +21,7 @@ libstorage_dbox_la_SOURCES = \ dbox-sync-file.c \ dbox-sync-rebuild.c \ dbox-storage.c \ - dbox-storage-rebuild.c \ - dbox-transaction.c + dbox-storage-rebuild.c headers = \ dbox-file.h \ diff --git a/src/lib-storage/index/dbox/dbox-save.c b/src/lib-storage/index/dbox/dbox-save.c index c00d5ffe6c..8d06e7163f 100644 --- a/src/lib-storage/index/dbox/dbox-save.c +++ b/src/lib-storage/index/dbox/dbox-save.c @@ -54,28 +54,29 @@ struct dbox_save_context { }; struct mail_save_context * -dbox_save_alloc(struct mailbox_transaction_context *_t) +dbox_save_alloc(struct mailbox_transaction_context *t) { - struct dbox_transaction_context *t = - (struct dbox_transaction_context *)_t; - struct dbox_mailbox *mbox = (struct dbox_mailbox *)_t->box; - struct dbox_save_context *ctx; + struct index_transaction_context *it = + (struct index_transaction_context *)t; + struct dbox_mailbox *mbox = (struct dbox_mailbox *)t->box; + struct dbox_save_context *ctx = (struct dbox_save_context *)t->save_ctx; - i_assert((_t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0); + i_assert((t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0); - if (t->save_ctx != NULL) { + if (ctx != NULL) { /* use the existing allocated structure */ - t->save_ctx->finished = FALSE; - return &t->save_ctx->ctx; + ctx->finished = FALSE; + return &ctx->ctx; } - ctx = t->save_ctx = i_new(struct dbox_save_context, 1); - ctx->ctx.transaction = &t->ictx.mailbox_ctx; + ctx = i_new(struct dbox_save_context, 1); + ctx->ctx.transaction = t; ctx->mbox = mbox; - ctx->trans = t->ictx.trans; + ctx->trans = it->trans; ctx->append_ctx = dbox_map_append_begin(mbox); i_array_init(&ctx->mails, 32); - return &ctx->ctx; + t->save_ctx = &ctx->ctx; + return t->save_ctx; } static void dbox_save_add_to_index(struct dbox_save_context *ctx) @@ -310,9 +311,10 @@ void dbox_save_cancel(struct mail_save_context *_ctx) (void)dbox_save_finish(_ctx); } -int dbox_transaction_save_commit_pre(struct dbox_save_context *ctx) +int dbox_transaction_save_commit_pre(struct mail_save_context *_ctx) { - struct mailbox_transaction_context *_t = ctx->ctx.transaction; + struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx; + struct mailbox_transaction_context *_t = _ctx->transaction; const struct mail_index_header *hdr; uint32_t first_map_uid, last_map_uid; @@ -322,7 +324,7 @@ int dbox_transaction_save_commit_pre(struct dbox_save_context *ctx) if (dbox_sync_begin(ctx->mbox, DBOX_SYNC_FLAG_NO_PURGE | DBOX_SYNC_FLAG_FORCE | DBOX_SYNC_FLAG_FSYNC, &ctx->sync_ctx) < 0) { - dbox_transaction_save_rollback(ctx); + dbox_transaction_save_rollback(_ctx); return -1; } @@ -331,7 +333,7 @@ int dbox_transaction_save_commit_pre(struct dbox_save_context *ctx) is left locked. */ if (dbox_map_append_assign_map_uids(ctx->append_ctx, &first_map_uid, &last_map_uid) < 0) { - dbox_transaction_save_rollback(ctx); + dbox_transaction_save_rollback(_ctx); return -1; } @@ -344,7 +346,7 @@ int dbox_transaction_save_commit_pre(struct dbox_save_context *ctx) if (ctx->single_count > 0) { if (dbox_map_append_assign_uids(ctx->append_ctx, &_t->changes->saved_uids) < 0) { - dbox_transaction_save_rollback(ctx); + dbox_transaction_save_rollback(_ctx); return -1; } } @@ -380,7 +382,7 @@ int dbox_transaction_save_commit_pre(struct dbox_save_context *ctx) FALSE); if (dbox_map_update_refcounts(ctx->map_trans, &ctx->copy_map_uids, 1) < 0) { - dbox_transaction_save_rollback(ctx); + dbox_transaction_save_rollback(_ctx); return -1; } } @@ -392,9 +394,11 @@ int dbox_transaction_save_commit_pre(struct dbox_save_context *ctx) return 0; } -void dbox_transaction_save_commit_post(struct dbox_save_context *ctx) +void dbox_transaction_save_commit_post(struct mail_save_context *_ctx) { - ctx->ctx.transaction = NULL; /* transaction is already freed */ + struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx; + + _ctx->transaction = NULL; /* transaction is already freed */ /* finish writing the mailbox APPENDs */ if (dbox_sync_finish(&ctx->sync_ctx, TRUE) == 0) { @@ -412,11 +416,13 @@ void dbox_transaction_save_commit_post(struct dbox_save_context *ctx) ctx->mbox->ibox.box.path); } } - dbox_transaction_save_rollback(ctx); + dbox_transaction_save_rollback(_ctx); } -void dbox_transaction_save_rollback(struct dbox_save_context *ctx) +void dbox_transaction_save_rollback(struct mail_save_context *_ctx) { + struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx; + if (!ctx->finished) dbox_save_cancel(&ctx->ctx); if (ctx->append_ctx != NULL) diff --git a/src/lib-storage/index/dbox/dbox-storage.c b/src/lib-storage/index/dbox/dbox-storage.c index be21347fc2..b1c8949c15 100644 --- a/src/lib-storage/index/dbox/dbox-storage.c +++ b/src/lib-storage/index/dbox/dbox-storage.c @@ -156,6 +156,10 @@ dbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list, mbox->ibox.box.list = list; mbox->ibox.mail_vfuncs = &dbox_mail_vfuncs; + mbox->ibox.save_commit_pre = dbox_transaction_save_commit_pre; + mbox->ibox.save_commit_post = dbox_transaction_save_commit_post; + mbox->ibox.save_rollback = dbox_transaction_save_rollback; + index_storage_mailbox_alloc(&mbox->ibox, name, input, flags, DBOX_INDEX_PREFIX); mail_index_set_fsync_types(mbox->ibox.index, @@ -823,16 +827,6 @@ static int dbox_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx return ret; } -static void dbox_class_init(void) -{ - dbox_transaction_class_init(); -} - -static void dbox_class_deinit(void) -{ - dbox_transaction_class_deinit(); -} - static void dbox_storage_add_list(struct mail_storage *storage, struct mailbox_list *list) { @@ -856,8 +850,6 @@ struct mail_storage dbox_storage = { { dbox_get_setting_parser_info, - dbox_class_init, - dbox_class_deinit, dbox_storage_alloc, dbox_storage_create, dbox_storage_destroy, diff --git a/src/lib-storage/index/dbox/dbox-storage.h b/src/lib-storage/index/dbox/dbox-storage.h index 2574f51b50..2a85a8f62a 100644 --- a/src/lib-storage/index/dbox/dbox-storage.h +++ b/src/lib-storage/index/dbox/dbox-storage.h @@ -80,19 +80,8 @@ struct dbox_mailbox { unsigned int creating:1; }; -struct dbox_transaction_context { - struct index_transaction_context ictx; - union mail_index_transaction_module_context module_ctx; - - uint32_t first_saved_mail_seq; - struct dbox_save_context *save_ctx; -}; - extern struct mail_vfuncs dbox_mail_vfuncs; -void dbox_transaction_class_init(void); -void dbox_transaction_class_deinit(void); - struct mailbox * dbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list, const char *name, struct istream *input, @@ -120,9 +109,9 @@ int dbox_save_continue(struct mail_save_context *ctx); int dbox_save_finish(struct mail_save_context *ctx); void dbox_save_cancel(struct mail_save_context *ctx); -int dbox_transaction_save_commit_pre(struct dbox_save_context *ctx); -void dbox_transaction_save_commit_post(struct dbox_save_context *ctx); -void dbox_transaction_save_rollback(struct dbox_save_context *ctx); +int dbox_transaction_save_commit_pre(struct mail_save_context *ctx); +void dbox_transaction_save_commit_post(struct mail_save_context *ctx); +void dbox_transaction_save_rollback(struct mail_save_context *ctx); int dbox_copy(struct mail_save_context *ctx, struct mail *mail); diff --git a/src/lib-storage/index/dbox/dbox-transaction.c b/src/lib-storage/index/dbox/dbox-transaction.c deleted file mode 100644 index f662145ae4..0000000000 --- a/src/lib-storage/index/dbox/dbox-transaction.c +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "array.h" -#include "dbox-storage.h" -#include "dbox-sync.h" - -static void (*next_hook_mail_index_transaction_created) - (struct mail_index_transaction *t) = NULL; - -static int dbox_transaction_commit(struct mail_index_transaction *t, - uint32_t *log_file_seq_r, - uoff_t *log_file_offset_r) -{ - struct dbox_transaction_context *dt = MAIL_STORAGE_CONTEXT(t); - struct dbox_save_context *save_ctx; - int ret = 0; - - if (dt->save_ctx != NULL) { - if (dbox_transaction_save_commit_pre(dt->save_ctx) < 0) { - dt->save_ctx = NULL; - ret = -1; - } - } - - save_ctx = dt->save_ctx; - - if (ret < 0) - index_transaction_finish_rollback(&dt->ictx); - else { - if (index_transaction_finish_commit(&dt->ictx, log_file_seq_r, - log_file_offset_r) < 0) - ret = -1; - } - - /* transaction is destroyed now. */ - dt = NULL; - - if (save_ctx != NULL) { - /* unlock uidlist file after writing to transaction log, - to make sure we don't write uids in wrong order. */ - dbox_transaction_save_commit_post(save_ctx); - } - return ret; -} - -static void dbox_transaction_rollback(struct mail_index_transaction *t) -{ - struct dbox_transaction_context *dt = MAIL_STORAGE_CONTEXT(t); - - if (dt->save_ctx != NULL) - dbox_transaction_save_rollback(dt->save_ctx); - - index_transaction_finish_rollback(&dt->ictx); -} - -static void dbox_transaction_created(struct mail_index_transaction *t) -{ - struct mailbox *box = MAIL_STORAGE_CONTEXT(t->view); - - /* index can be for mailbox list index, in which case box=NULL */ - if (box != NULL && - strcmp(box->storage->name, DBOX_STORAGE_NAME) == 0) { - struct dbox_mailbox *dbox = (struct dbox_mailbox *)box; - struct dbox_transaction_context *mt; - - mt = i_new(struct dbox_transaction_context, 1); - mt->ictx.trans = t; - index_transaction_init(&mt->ictx, &dbox->ibox); - - t->v.commit = dbox_transaction_commit; - t->v.rollback = dbox_transaction_rollback; - MODULE_CONTEXT_SET(t, mail_storage_mail_index_module, mt); - } - - if (next_hook_mail_index_transaction_created != NULL) - next_hook_mail_index_transaction_created(t); -} - -void dbox_transaction_class_init(void) -{ - next_hook_mail_index_transaction_created = - hook_mail_index_transaction_created; - hook_mail_index_transaction_created = dbox_transaction_created; -} - -void dbox_transaction_class_deinit(void) -{ - i_assert(hook_mail_index_transaction_created == - dbox_transaction_created); - hook_mail_index_transaction_created = - next_hook_mail_index_transaction_created; -} diff --git a/src/lib-storage/index/index-storage.h b/src/lib-storage/index/index-storage.h index 000f3f6e87..c1c87eb79e 100644 --- a/src/lib-storage/index/index-storage.h +++ b/src/lib-storage/index/index-storage.h @@ -16,11 +16,28 @@ enum mailbox_lock_notify_type { MAILBOX_LOCK_NOTIFY_MAILBOX_OVERRIDE }; +struct index_transaction_context { + struct mailbox_transaction_context mailbox_ctx; + union mail_index_transaction_module_context module_ctx; + + struct mail_index_transaction_vfuncs super; + int mail_ref_count; + + struct mail_index_transaction *trans; + struct mail_index_view *trans_view; + struct mail_cache_view *cache_view; + struct mail_cache_transaction_ctx *cache_trans; +}; + struct index_mailbox { struct mailbox box; union mail_index_view_module_context view_module_ctx; enum mail_index_open_flags index_flags; + int (*save_commit_pre)(struct mail_save_context *save_ctx); + void (*save_commit_post)(struct mail_save_context *save_ctx); + void (*save_rollback)(struct mail_save_context *save_ctx); + struct mail_index *index; struct mail_index_view *view; struct mail_cache *cache; @@ -49,17 +66,6 @@ struct index_mailbox { unsigned int move_to_memory:1; }; -struct index_transaction_context { - struct mailbox_transaction_context mailbox_ctx; - struct mail_index_transaction_vfuncs super; - int mail_ref_count; - - struct mail_index_transaction *trans; - struct mail_index_view *trans_view; - struct mail_cache_view *cache_view; - struct mail_cache_transaction_ctx *cache_trans; -}; - void mail_storage_set_index_error(struct index_mailbox *ibox); void index_storage_lock_notify(struct index_mailbox *ibox, @@ -147,12 +153,6 @@ int index_storage_search_next_nonblock(struct mail_search_context *ctx, struct mail *mail, bool *tryagain_r); bool index_storage_search_next_update_seq(struct mail_search_context *ctx); -void index_transaction_init(struct index_transaction_context *t, - struct index_mailbox *ibox); -int index_transaction_finish_commit(struct index_transaction_context *t, - uint32_t *log_file_seq_r, - uoff_t *log_file_offset_r); -void index_transaction_finish_rollback(struct index_transaction_context *t); void index_transaction_set_max_modseq(struct mailbox_transaction_context *_t, uint64_t max_modseq, ARRAY_TYPE(seq_range) *seqs); @@ -160,6 +160,9 @@ void index_transaction_set_max_modseq(struct mailbox_transaction_context *_t, struct mailbox_transaction_context * index_transaction_begin(struct mailbox *box, enum mailbox_transaction_flags flags); +void index_transaction_init(struct index_transaction_context *it, + struct mailbox *box, + enum mailbox_transaction_flags flags); int index_transaction_commit(struct mailbox_transaction_context *t, struct mail_transaction_commit_changes *changes_r); void index_transaction_rollback(struct mailbox_transaction_context *t); diff --git a/src/lib-storage/index/index-transaction.c b/src/lib-storage/index/index-transaction.c index e3ede01e60..005f049d1a 100644 --- a/src/lib-storage/index/index-transaction.c +++ b/src/lib-storage/index/index-transaction.c @@ -5,22 +5,6 @@ #include "index-storage.h" #include "index-mail.h" -void index_transaction_init(struct index_transaction_context *t, - struct index_mailbox *ibox) -{ - t->mailbox_ctx.box = &ibox->box; - - array_create(&t->mailbox_ctx.module_contexts, default_pool, - sizeof(void *), 5); - - t->trans_view = mail_index_transaction_open_updated_view(t->trans); - t->cache_view = mail_cache_view_open(ibox->cache, t->trans_view); - t->cache_trans = mail_cache_get_transaction(t->cache_view, t->trans); - - /* mail_cache_get_transaction() changes trans->v */ - t->super = t->trans->v; -} - static void index_transaction_free(struct index_transaction_context *t) { mail_cache_view_close(t->cache_view); @@ -29,38 +13,60 @@ static void index_transaction_free(struct index_transaction_context *t) i_free(t); } -int index_transaction_finish_commit(struct index_transaction_context *t, - uint32_t *log_file_seq_r, - uoff_t *log_file_offset_r) +static int +index_transaction_index_commit(struct mail_index_transaction *index_trans, + uint32_t *log_file_seq_r, + uoff_t *log_file_offset_r) { - struct index_mailbox *ibox = (struct index_mailbox *)t->mailbox_ctx.box; - int ret; - - i_assert(t->mail_ref_count == 0); + 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; + } + } - ret = t->super.commit(t->trans, log_file_seq_r, log_file_offset_r); + i_assert(it->mail_ref_count == 0); if (ret < 0) - mail_storage_set_index_error(ibox); + it->super.rollback(it->trans); + else { + if (it->super.commit(it->trans, log_file_seq_r, + log_file_offset_r) < 0) { + mail_storage_set_index_error(ibox); + ret = -1; + } + } - index_transaction_free(t); + if (t->save_ctx != NULL) + ibox->save_commit_post(t->save_ctx); + + index_transaction_free(it); return ret; } -void index_transaction_finish_rollback(struct index_transaction_context *t) +static void index_transaction_index_rollback(struct mail_index_transaction *t) { - i_assert(t->mail_ref_count == 0); + 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); - t->super.rollback(t->trans); - index_transaction_free(t); + it->super.rollback(it->trans); + index_transaction_free(it); } -struct mailbox_transaction_context * -index_transaction_begin(struct mailbox *box, - enum mailbox_transaction_flags flags) +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; - struct mail_index_transaction *t; - struct index_transaction_context *it; enum mail_index_transaction_flags trans_flags; i_assert(box->opened); @@ -72,13 +78,33 @@ index_transaction_begin(struct mailbox *box, trans_flags |= MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL; if ((flags & MAILBOX_TRANSACTION_FLAG_REFRESH) != 0) (void)mail_index_refresh(ibox->index); - t = mail_index_transaction_begin(ibox->view, trans_flags); - it = MAIL_STORAGE_CONTEXT(t); - if (it == NULL) { - i_panic("mail storage transaction context mising for type %s", - box->storage->name); - } + 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; } diff --git a/src/lib-storage/index/maildir/Makefile.am b/src/lib-storage/index/maildir/Makefile.am index b6451cf885..99221d8bbf 100644 --- a/src/lib-storage/index/maildir/Makefile.am +++ b/src/lib-storage/index/maildir/Makefile.am @@ -19,7 +19,6 @@ libstorage_maildir_la_SOURCES = \ maildir-storage.c \ maildir-sync.c \ maildir-sync-index.c \ - maildir-transaction.c \ maildir-uidlist.c \ maildir-util.c diff --git a/src/lib-storage/index/maildir/maildir-copy.c b/src/lib-storage/index/maildir/maildir-copy.c index 6cda964728..1138bd3065 100644 --- a/src/lib-storage/index/maildir/maildir-copy.c +++ b/src/lib-storage/index/maildir/maildir-copy.c @@ -211,10 +211,7 @@ maildir_compatible_file_modes(struct mailbox *box1, struct mailbox *box2) int maildir_copy(struct mail_save_context *ctx, struct mail *mail) { struct mailbox_transaction_context *_t = ctx->transaction; - struct maildir_transaction_context *t = - (struct maildir_transaction_context *)_t; - struct maildir_mailbox *mbox = - (struct maildir_mailbox *)t->ictx.mailbox_ctx.box; + struct maildir_mailbox *mbox = (struct maildir_mailbox *)_t->box; int ret; i_assert((_t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0); diff --git a/src/lib-storage/index/maildir/maildir-save.c b/src/lib-storage/index/maildir/maildir-save.c index 42e190238c..ed5c0271f8 100644 --- a/src/lib-storage/index/maildir/maildir-save.c +++ b/src/lib-storage/index/maildir/maildir-save.c @@ -105,20 +105,19 @@ static int maildir_file_move(struct maildir_save_context *ctx, } } -struct maildir_save_context * -maildir_save_transaction_init(struct maildir_transaction_context *t) +static struct mail_save_context * +maildir_save_transaction_init(struct mailbox_transaction_context *t) { - struct maildir_mailbox *mbox = - (struct maildir_mailbox *)t->ictx.mailbox_ctx.box; + struct maildir_mailbox *mbox = (struct maildir_mailbox *)t->box; struct maildir_save_context *ctx; pool_t pool; pool = pool_alloconly_create("maildir_save_context", 4096); ctx = p_new(pool, struct maildir_save_context, 1); - ctx->ctx.transaction = &t->ictx.mailbox_ctx; + ctx->ctx.transaction = t; ctx->pool = pool; ctx->mbox = mbox; - ctx->trans = t->ictx.trans; + ctx->trans = ((struct index_transaction_context *)t)->trans; ctx->files_tail = &ctx->files; ctx->fd = -1; @@ -130,7 +129,7 @@ maildir_save_transaction_init(struct maildir_transaction_context *t) array_create_from_buffer(&ctx->keywords_array, &ctx->keywords_buffer, sizeof(unsigned int)); ctx->last_save_finished = TRUE; - return ctx; + return &ctx->ctx; } struct maildir_filename * @@ -267,25 +266,24 @@ static const char *maildir_mf_get_path(struct maildir_save_context *ctx, return t_strdup_printf("%s/%s", ctx->curdir, fname); } -const char *maildir_save_file_get_path(struct mailbox_transaction_context *_t, +const char *maildir_save_file_get_path(struct mailbox_transaction_context *t, uint32_t seq) { - struct maildir_transaction_context *t = - (struct maildir_transaction_context *)_t; - struct maildir_save_context *ctx = t->save_ctx; + struct maildir_save_context *save_ctx = + (struct maildir_save_context *)t->save_ctx; struct maildir_filename *mf; - i_assert(seq >= ctx->first_seq); + i_assert(seq >= save_ctx->first_seq); - seq -= ctx->first_seq; - mf = ctx->files; + seq -= save_ctx->first_seq; + mf = save_ctx->files; while (seq > 0) { mf = mf->next; i_assert(mf != NULL); seq--; } - return maildir_mf_get_path(ctx, mf); + return maildir_mf_get_path(save_ctx, mf); } static int maildir_create_tmp(struct maildir_mailbox *mbox, const char *dir, @@ -361,16 +359,13 @@ static int maildir_create_tmp(struct maildir_mailbox *mbox, const char *dir, } struct mail_save_context * -maildir_save_alloc(struct mailbox_transaction_context *_t) +maildir_save_alloc(struct mailbox_transaction_context *t) { - struct maildir_transaction_context *t = - (struct maildir_transaction_context *)_t; - - i_assert((_t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0); + i_assert((t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0); if (t->save_ctx == NULL) t->save_ctx = maildir_save_transaction_init(t); - return &t->save_ctx->ctx; + return t->save_ctx; } int maildir_save_begin(struct mail_save_context *_ctx, struct istream *input) @@ -694,14 +689,14 @@ maildir_save_sync_index(struct maildir_save_context *ctx) static void maildir_save_rollback_index_changes(struct maildir_save_context *ctx) { - struct maildir_transaction_context *t = - (struct maildir_transaction_context *)ctx->ctx.transaction; + struct index_transaction_context *t = + (struct index_transaction_context *)ctx->ctx.transaction; uint32_t seq; for (seq = ctx->seq; seq >= ctx->first_seq; seq--) mail_index_expunge(ctx->trans, seq); - mail_cache_transaction_reset(t->ictx.cache_trans); + mail_cache_transaction_reset(t->cache_trans); } static int @@ -764,14 +759,15 @@ static void maildir_save_sync_uidlist(struct maildir_save_context *ctx) i_assert(!seq_range_array_iter_nth(&iter, n, &uid)); } -int maildir_transaction_save_commit_pre(struct maildir_save_context *ctx) +int maildir_transaction_save_commit_pre(struct mail_save_context *_ctx) { - struct mailbox_transaction_context *_t = ctx->ctx.transaction; + struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx; + struct mailbox_transaction_context *_t = _ctx->transaction; struct maildir_filename *last_mf; enum maildir_uidlist_sync_flags sync_flags; int ret; - i_assert(ctx->ctx.output == NULL); + i_assert(_ctx->output == NULL); i_assert(ctx->last_save_finished); sync_flags = MAILDIR_UIDLIST_SYNC_PARTIAL | @@ -791,7 +787,7 @@ int maildir_transaction_save_commit_pre(struct maildir_save_context *ctx) if (ret > 0) { ctx->locked = TRUE; if (maildir_save_sync_index(ctx) < 0) { - maildir_transaction_save_rollback(ctx); + maildir_transaction_save_rollback(_ctx); return -1; } } else if (ret == 0 && @@ -802,7 +798,7 @@ int maildir_transaction_save_commit_pre(struct maildir_save_context *ctx) appends to index. */ maildir_save_rollback_index_changes(ctx); } else { - maildir_transaction_save_rollback(ctx); + maildir_transaction_save_rollback(_ctx); return -1; } @@ -852,25 +848,28 @@ int maildir_transaction_save_commit_pre(struct maildir_save_context *ctx) if (ctx->keywords_sync_ctx != NULL) maildir_keywords_sync_deinit(&ctx->keywords_sync_ctx); /* returning failure finishes the save_context */ - maildir_transaction_save_rollback(ctx); + maildir_transaction_save_rollback(_ctx); return -1; } return 0; } -void maildir_transaction_save_commit_post(struct maildir_save_context *ctx) +void maildir_transaction_save_commit_post(struct mail_save_context *_ctx) { - ctx->ctx.transaction = NULL; /* transaction is already freed */ + struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx; + + _ctx->transaction = NULL; /* transaction is already freed */ if (ctx->locked) maildir_uidlist_unlock(ctx->mbox->uidlist); pool_unref(&ctx->pool); } -static void -maildir_transaction_save_rollback_real(struct maildir_save_context *ctx) +void maildir_transaction_save_rollback(struct mail_save_context *_ctx) { - i_assert(ctx->ctx.output == NULL); + struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx; + + i_assert(_ctx->output == NULL); if (!ctx->last_save_finished) maildir_save_cancel(&ctx->ctx); @@ -889,10 +888,3 @@ maildir_transaction_save_rollback_real(struct maildir_save_context *ctx) mail_free(&ctx->mail); pool_unref(&ctx->pool); } - -void maildir_transaction_save_rollback(struct maildir_save_context *ctx) -{ - T_BEGIN { - maildir_transaction_save_rollback_real(ctx); - } T_END; -} diff --git a/src/lib-storage/index/maildir/maildir-storage.c b/src/lib-storage/index/maildir/maildir-storage.c index f1f3fbb2d6..c9ea435612 100644 --- a/src/lib-storage/index/maildir/maildir-storage.c +++ b/src/lib-storage/index/maildir/maildir-storage.c @@ -350,6 +350,10 @@ maildir_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list, mbox->ibox.box.list = list; mbox->ibox.mail_vfuncs = &maildir_mail_vfuncs; + mbox->ibox.save_commit_pre = maildir_transaction_save_commit_pre; + mbox->ibox.save_commit_post = maildir_transaction_save_commit_post; + mbox->ibox.save_rollback = maildir_transaction_save_rollback; + index_storage_mailbox_alloc(&mbox->ibox, name, input, flags, MAILDIR_INDEX_PREFIX); @@ -1037,16 +1041,6 @@ uint32_t maildir_get_uidvalidity_next(struct mailbox_list *list) return mailbox_uidvalidity_next(path); } -static void maildir_class_init(void) -{ - maildir_transaction_class_init(); -} - -static void maildir_class_deinit(void) -{ - maildir_transaction_class_deinit(); -} - static void maildir_storage_add_list(struct mail_storage *storage, struct mailbox_list *list) { @@ -1076,8 +1070,6 @@ struct mail_storage maildir_storage = { { maildir_get_setting_parser_info, - maildir_class_init, - maildir_class_deinit, maildir_storage_alloc, maildir_storage_create, index_storage_destroy, diff --git a/src/lib-storage/index/maildir/maildir-storage.h b/src/lib-storage/index/maildir/maildir-storage.h index 599812953a..90852feda3 100644 --- a/src/lib-storage/index/maildir/maildir-storage.h +++ b/src/lib-storage/index/maildir/maildir-storage.h @@ -92,13 +92,6 @@ struct maildir_mailbox { unsigned int syncing_commit:1; }; -struct maildir_transaction_context { - struct index_transaction_context ictx; - union mail_index_transaction_module_context module_ctx; - - struct maildir_save_context *save_ctx; -}; - extern struct mail_vfuncs maildir_mail_vfuncs; /* Return -1 = error, 0 = file not found, 1 = ok */ @@ -121,9 +114,6 @@ int maildir_file_do(struct maildir_mailbox *mbox, uint32_t uid, bool maildir_set_deleted(struct mailbox *box); uint32_t maildir_get_uidvalidity_next(struct mailbox_list *list); -void maildir_transaction_class_init(void); -void maildir_transaction_class_deinit(void); - struct mail_save_context * maildir_save_alloc(struct mailbox_transaction_context *_t); int maildir_save_begin(struct mail_save_context *ctx, struct istream *input); @@ -131,16 +121,14 @@ int maildir_save_continue(struct mail_save_context *ctx); int maildir_save_finish(struct mail_save_context *ctx); void maildir_save_cancel(struct mail_save_context *ctx); -struct maildir_save_context * -maildir_save_transaction_init(struct maildir_transaction_context *t); struct maildir_filename * maildir_save_add(struct mail_save_context *_ctx, const char *base_fname); const char *maildir_save_file_get_path(struct mailbox_transaction_context *t, uint32_t seq); -int maildir_transaction_save_commit_pre(struct maildir_save_context *ctx); -void maildir_transaction_save_commit_post(struct maildir_save_context *ctx); -void maildir_transaction_save_rollback(struct maildir_save_context *ctx); +int maildir_transaction_save_commit_pre(struct mail_save_context *ctx); +void maildir_transaction_save_commit_post(struct mail_save_context *ctx); +void maildir_transaction_save_rollback(struct mail_save_context *ctx); int maildir_copy(struct mail_save_context *ctx, struct mail *mail); int maildir_transaction_copy_commit(struct maildir_copy_context *ctx); diff --git a/src/lib-storage/index/maildir/maildir-transaction.c b/src/lib-storage/index/maildir/maildir-transaction.c deleted file mode 100644 index ab13b94dc5..0000000000 --- a/src/lib-storage/index/maildir/maildir-transaction.c +++ /dev/null @@ -1,88 +0,0 @@ -/* Copyright (c) 2004-2009 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "array.h" -#include "maildir-storage.h" -#include "maildir-sync.h" - -static void (*next_hook_mail_index_transaction_created) - (struct mail_index_transaction *t) = NULL; - -static int maildir_transaction_commit(struct mail_index_transaction *t, - uint32_t *log_file_seq_r, - uoff_t *log_file_offset_r) -{ - struct maildir_transaction_context *mt = MAIL_STORAGE_CONTEXT(t); - struct maildir_save_context *save_ctx; - int ret = 0; - - if (mt->save_ctx != NULL) { - if (maildir_transaction_save_commit_pre(mt->save_ctx) < 0) { - mt->save_ctx = NULL; - ret = -1; - } - } - - save_ctx = mt->save_ctx; - - if (ret == 0) { - if (index_transaction_finish_commit(&mt->ictx, log_file_seq_r, - log_file_offset_r) < 0) - ret = -1; - } else { - index_transaction_finish_rollback(&mt->ictx); - } - - /* transaction is destroyed now. */ - mt = NULL; - - if (save_ctx != NULL) - maildir_transaction_save_commit_post(save_ctx); - return ret; -} - -static void maildir_transaction_rollback(struct mail_index_transaction *t) -{ - struct maildir_transaction_context *mt = MAIL_STORAGE_CONTEXT(t); - - if (mt->save_ctx != NULL) - maildir_transaction_save_rollback(mt->save_ctx); - index_transaction_finish_rollback(&mt->ictx); -} - -static void maildir_transaction_created(struct mail_index_transaction *t) -{ - struct mailbox *box = MAIL_STORAGE_CONTEXT(t->view); - - /* index can be for mailbox list index, in which case box=NULL */ - if (box != NULL && - strcmp(box->storage->name, MAILDIR_STORAGE_NAME) == 0) { - struct maildir_mailbox *mbox = (struct maildir_mailbox *)box; - struct maildir_transaction_context *mt; - - mt = i_new(struct maildir_transaction_context, 1); - mt->ictx.trans = t; - index_transaction_init(&mt->ictx, &mbox->ibox); - - t->v.commit = maildir_transaction_commit; - t->v.rollback = maildir_transaction_rollback; - MODULE_CONTEXT_SET(t, mail_storage_mail_index_module, mt); - } - if (next_hook_mail_index_transaction_created != NULL) - next_hook_mail_index_transaction_created(t); -} - -void maildir_transaction_class_init(void) -{ - next_hook_mail_index_transaction_created = - hook_mail_index_transaction_created; - hook_mail_index_transaction_created = maildir_transaction_created; -} - -void maildir_transaction_class_deinit(void) -{ - i_assert(hook_mail_index_transaction_created == - maildir_transaction_created); - hook_mail_index_transaction_created = - next_hook_mail_index_transaction_created; -} diff --git a/src/lib-storage/index/mbox/Makefile.am b/src/lib-storage/index/mbox/Makefile.am index f9e9a6e42a..a69b2722ae 100644 --- a/src/lib-storage/index/mbox/Makefile.am +++ b/src/lib-storage/index/mbox/Makefile.am @@ -21,8 +21,7 @@ libstorage_mbox_la_SOURCES = \ mbox-sync-rewrite.c \ mbox-sync-update.c \ mbox-sync.c \ - mbox-storage.c \ - mbox-transaction.c + mbox-storage.c headers = \ istream-raw-mbox.h \ diff --git a/src/lib-storage/index/mbox/mbox-save.c b/src/lib-storage/index/mbox/mbox-save.c index 5739b36bb8..2ef26610ad 100644 --- a/src/lib-storage/index/mbox/mbox-save.c +++ b/src/lib-storage/index/mbox/mbox-save.c @@ -170,11 +170,10 @@ static int mbox_write_content_length(struct mbox_save_context *ctx) return 0; } -static void mbox_save_init_sync(struct mbox_transaction_context *t) +static void mbox_save_init_sync(struct mailbox_transaction_context *t) { - struct mbox_mailbox *mbox = - (struct mbox_mailbox *)t->ictx.mailbox_ctx.box; - struct mbox_save_context *ctx = t->save_ctx; + struct mbox_mailbox *mbox = (struct mbox_mailbox *)t->box; + struct mbox_save_context *ctx = (struct mbox_save_context *)t->save_ctx; const struct mail_index_header *hdr; struct mail_index_view *view; @@ -188,7 +187,6 @@ static void mbox_save_init_sync(struct mbox_transaction_context *t) ctx->first_saved_uid = ctx->next_uid; ctx->uid_validity = hdr->uid_validity; ctx->synced = TRUE; - t->mails_saved = TRUE; mail_index_view_close(&view); } @@ -296,7 +294,7 @@ mbox_save_init_file(struct mbox_save_context *ctx, /* we're not required to assign UIDs for the appended mails immediately. do it only if it doesn't require syncing. */ - mbox_save_init_sync(t); + mbox_save_init_sync(_t); } } @@ -304,7 +302,7 @@ mbox_save_init_file(struct mbox_save_context *ctx, /* we'll need to assign UID for the mail immediately. */ if (mbox_sync(mbox, 0) < 0) return -1; - mbox_save_init_sync(t); + mbox_save_init_sync(_t); } /* the syncing above could have changed the append offset */ @@ -411,26 +409,26 @@ mbox_save_get_input_stream(struct mbox_save_context *ctx, struct istream *input) } struct mail_save_context * -mbox_save_alloc(struct mailbox_transaction_context *_t) +mbox_save_alloc(struct mailbox_transaction_context *t) { - struct mbox_transaction_context *t = - (struct mbox_transaction_context *)_t; - struct mbox_mailbox *mbox = (struct mbox_mailbox *)_t->box; + struct mbox_transaction_context *mt = + (struct mbox_transaction_context *)t; + struct mbox_mailbox *mbox = (struct mbox_mailbox *)t->box; struct mbox_save_context *ctx; - i_assert((_t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0); - - if (t->save_ctx != NULL) - return &t->save_ctx->ctx; + i_assert((t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0); - ctx = t->save_ctx = i_new(struct mbox_save_context, 1); - ctx->ctx.transaction = &t->ictx.mailbox_ctx; - ctx->mbox = mbox; - ctx->trans = t->ictx.trans; - ctx->append_offset = (uoff_t)-1; - ctx->headers = str_new(default_pool, 512); - ctx->mail_offset = (uoff_t)-1; - return &ctx->ctx; + if (t->save_ctx == NULL) { + ctx = i_new(struct mbox_save_context, 1); + ctx->ctx.transaction = t; + ctx->mbox = mbox; + ctx->trans = mt->ictx.trans; + ctx->append_offset = (uoff_t)-1; + ctx->headers = str_new(default_pool, 512); + ctx->mail_offset = (uoff_t)-1; + t->save_ctx = &ctx->ctx; + } + return t->save_ctx; } int mbox_save_begin(struct mail_save_context *_ctx, struct istream *input) @@ -713,12 +711,12 @@ static void mbox_transaction_save_deinit(struct mbox_save_context *ctx) if (ctx->mail != NULL) mail_free(&ctx->mail); str_free(&ctx->headers); - i_free(ctx); } -int mbox_transaction_save_commit(struct mbox_save_context *ctx) +int mbox_transaction_save_commit_pre(struct mail_save_context *_ctx) { - struct mailbox_transaction_context *_t = ctx->ctx.transaction; + struct mbox_save_context *ctx = (struct mbox_save_context *)_ctx; + struct mailbox_transaction_context *_t = _ctx->transaction; struct mbox_mailbox *mbox = ctx->mbox; struct seq_range *range; struct stat st; @@ -771,11 +769,29 @@ int mbox_transaction_save_commit(struct mbox_save_context *ctx) } mbox_transaction_save_deinit(ctx); + if (ret < 0) + i_free(ctx); return ret; } -void mbox_transaction_save_rollback(struct mbox_save_context *ctx) +void mbox_transaction_save_commit_post(struct mail_save_context *_ctx) +{ + struct mbox_save_context *ctx = (struct mbox_save_context *)_ctx; + + i_assert(ctx->mbox->mbox_lock_type == F_WRLCK); + + if (ctx->synced) { + /* after saving mails with UIDs we need to update + the last-uid */ + (void)mbox_sync(ctx->mbox, MBOX_SYNC_HEADER | + MBOX_SYNC_REWRITE); + } + i_free(ctx); +} + +void mbox_transaction_save_rollback(struct mail_save_context *_ctx) { + struct mbox_save_context *ctx = (struct mbox_save_context *)_ctx; struct mbox_mailbox *mbox = ctx->mbox; if (!ctx->finished) @@ -795,4 +811,5 @@ void mbox_transaction_save_rollback(struct mbox_save_context *ctx) } mbox_transaction_save_deinit(ctx); + i_free(ctx); } diff --git a/src/lib-storage/index/mbox/mbox-storage.c b/src/lib-storage/index/mbox/mbox-storage.c index 8e836eb26d..a739f8545b 100644 --- a/src/lib-storage/index/mbox/mbox-storage.c +++ b/src/lib-storage/index/mbox/mbox-storage.c @@ -348,6 +348,10 @@ mbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list, mbox->ibox.box.list = list; mbox->ibox.mail_vfuncs = &mbox_mail_vfuncs; + mbox->ibox.save_commit_pre = mbox_transaction_save_commit_pre; + mbox->ibox.save_commit_post = mbox_transaction_save_commit_post; + mbox->ibox.save_rollback = mbox_transaction_save_rollback; + index_storage_mailbox_alloc(&mbox->ibox, name, input, flags, MBOX_INDEX_PREFIX); @@ -818,16 +822,6 @@ static int mbox_list_delete_mailbox(struct mailbox_list *list, return 0; } -static void mbox_class_init(void) -{ - mbox_transaction_class_init(); -} - -static void mbox_class_deinit(void) -{ - mbox_transaction_class_deinit(); -} - static void mbox_storage_add_list(struct mail_storage *storage, struct mailbox_list *list) { @@ -850,14 +844,65 @@ static void mbox_storage_add_list(struct mail_storage *storage, MODULE_CONTEXT_SET(list, mbox_mailbox_list_module, mlist); } +static struct mailbox_transaction_context * +mbox_transaction_begin(struct mailbox *box, + enum mailbox_transaction_flags flags) +{ + struct mbox_transaction_context *mt; + + mt = i_new(struct mbox_transaction_context, 1); + index_transaction_init(&mt->ictx, box, flags); + return &mt->ictx.mailbox_ctx; +} + +static void mbox_transaction_unlock(struct mailbox *box, unsigned int lock_id) +{ + struct mbox_mailbox *mbox = (struct mbox_mailbox *)box; + + if (lock_id != 0) + (void)mbox_unlock(mbox, lock_id); + if (mbox->mbox_global_lock_id == 0) { + i_assert(mbox->ibox.box.transaction_count > 0 || + mbox->mbox_lock_type == F_UNLCK); + } else { + /* mailbox opened with MAILBOX_FLAG_KEEP_LOCKED */ + i_assert(mbox->mbox_lock_type == F_WRLCK); + } +} + +static int +mbox_transaction_commit(struct mailbox_transaction_context *t, + struct mail_transaction_commit_changes *changes_r) +{ + struct mbox_transaction_context *mt = + (struct mbox_transaction_context *)t; + struct mailbox *box = t->box; + unsigned int lock_id = mt->mbox_lock_id; + int ret; + + ret = index_transaction_commit(t, changes_r); + mbox_transaction_unlock(box, lock_id); + return ret; +} + +static void +mbox_transaction_rollback(struct mailbox_transaction_context *t) +{ + struct mbox_transaction_context *mt = + (struct mbox_transaction_context *)t; + struct mailbox *box = t->box; + unsigned int lock_id = mt->mbox_lock_id; + + index_transaction_rollback(t); + mbox_transaction_unlock(box, lock_id); +} + struct mail_storage mbox_storage = { MEMBER(name) MBOX_STORAGE_NAME, MEMBER(class_flags) MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE, { mbox_get_setting_parser_info, - mbox_class_init, - mbox_class_deinit, mbox_storage_alloc, mbox_storage_create, index_storage_destroy, @@ -890,9 +935,9 @@ struct mailbox mbox_mailbox = { index_mailbox_sync_deinit, NULL, mbox_notify_changes, - index_transaction_begin, - index_transaction_commit, - index_transaction_rollback, + mbox_transaction_begin, + mbox_transaction_commit, + mbox_transaction_rollback, index_transaction_set_max_modseq, index_keywords_create, index_keywords_create_from_indexes, diff --git a/src/lib-storage/index/mbox/mbox-storage.h b/src/lib-storage/index/mbox/mbox-storage.h index d0bdf3bc82..1a210cdfba 100644 --- a/src/lib-storage/index/mbox/mbox-storage.h +++ b/src/lib-storage/index/mbox/mbox-storage.h @@ -62,11 +62,7 @@ struct mbox_mailbox { struct mbox_transaction_context { struct index_transaction_context ictx; - union mail_index_transaction_module_context module_ctx; - - struct mbox_save_context *save_ctx; unsigned int mbox_lock_id; - unsigned int mails_saved:1; }; extern struct mail_vfuncs mbox_mail_vfuncs; @@ -75,9 +71,6 @@ extern unsigned int mbox_hide_headers_count, mbox_save_drop_headers_count; int mbox_set_syscall_error(struct mbox_mailbox *mbox, const char *function); -void mbox_transaction_class_init(void); -void mbox_transaction_class_deinit(void); - struct mailbox_sync_context * mbox_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags); @@ -88,7 +81,8 @@ int mbox_save_continue(struct mail_save_context *ctx); int mbox_save_finish(struct mail_save_context *ctx); void mbox_save_cancel(struct mail_save_context *ctx); -int mbox_transaction_save_commit(struct mbox_save_context *ctx); -void mbox_transaction_save_rollback(struct mbox_save_context *ctx); +int mbox_transaction_save_commit_pre(struct mail_save_context *ctx); +void mbox_transaction_save_commit_post(struct mail_save_context *ctx); +void mbox_transaction_save_rollback(struct mail_save_context *ctx); #endif diff --git a/src/lib-storage/index/mbox/mbox-transaction.c b/src/lib-storage/index/mbox/mbox-transaction.c deleted file mode 100644 index 27b1e48b1c..0000000000 --- a/src/lib-storage/index/mbox/mbox-transaction.c +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright (c) 2004-2009 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "array.h" -#include "mbox-storage.h" -#include "mbox-lock.h" -#include "mbox-sync-private.h" - -static void (*next_hook_mail_index_transaction_created) - (struct mail_index_transaction *t) = NULL; - -static int mbox_transaction_commit(struct mail_index_transaction *t, - uint32_t *log_file_seq_r, - uoff_t *log_file_offset_r) -{ - struct mbox_transaction_context *mt = MAIL_STORAGE_CONTEXT(t); - struct mbox_mailbox *mbox = - (struct mbox_mailbox *)mt->ictx.mailbox_ctx.box; - unsigned int lock_id = mt->mbox_lock_id; - bool mails_saved; - int ret = 0; - - if (mt->save_ctx != NULL) - ret = mbox_transaction_save_commit(mt->save_ctx); - mails_saved = mt->mails_saved; - - if (ret < 0) - index_transaction_finish_rollback(&mt->ictx); - else { - if (index_transaction_finish_commit(&mt->ictx, log_file_seq_r, - log_file_offset_r) < 0) - ret = -1; - } - - /* transaction is destroyed now. */ - mt = NULL; - - if (lock_id != 0 && mbox->mbox_lock_type != F_WRLCK) { - /* unlock before writing any changes */ - (void)mbox_unlock(mbox, lock_id); - lock_id = 0; - } - - if (ret == 0 && mails_saved) { - /* after saving mails we want to update the last-uid */ - if (mbox_sync(mbox, MBOX_SYNC_HEADER | MBOX_SYNC_REWRITE) < 0) - ret = -1; - } - - if (lock_id != 0) { - if (mbox_unlock(mbox, lock_id) < 0) - ret = -1; - } - if (mbox->mbox_global_lock_id == 0) { - i_assert(mbox->ibox.box.transaction_count > 0 || - mbox->mbox_lock_type == F_UNLCK); - } else { - i_assert(mbox->mbox_lock_type == F_WRLCK); - } - return ret; -} - -static void mbox_transaction_rollback(struct mail_index_transaction *t) -{ - struct mbox_transaction_context *mt = MAIL_STORAGE_CONTEXT(t); - struct mbox_mailbox *mbox = - (struct mbox_mailbox *)mt->ictx.mailbox_ctx.box; - - if (mt->save_ctx != NULL) - mbox_transaction_save_rollback(mt->save_ctx); - - if (mt->mbox_lock_id != 0) - (void)mbox_unlock(mbox, mt->mbox_lock_id); - index_transaction_finish_rollback(&mt->ictx); - - i_assert(mbox->ibox.box.transaction_count > 0 || - mbox->mbox_lock_type == F_UNLCK); -} - -static void mbox_transaction_created(struct mail_index_transaction *t) -{ - struct mailbox *box = MAIL_STORAGE_CONTEXT(t->view); - - /* index can be for mailbox list index, in which case box=NULL */ - if (box != NULL && strcmp(box->storage->name, MBOX_STORAGE_NAME) == 0) { - struct mbox_mailbox *mbox = (struct mbox_mailbox *)box; - struct mbox_transaction_context *mt; - - mt = i_new(struct mbox_transaction_context, 1); - mt->ictx.trans = t; - index_transaction_init(&mt->ictx, &mbox->ibox); - - t->v.commit = mbox_transaction_commit; - t->v.rollback = mbox_transaction_rollback; - MODULE_CONTEXT_SET(t, mail_storage_mail_index_module, mt); - } - - if (next_hook_mail_index_transaction_created != NULL) - next_hook_mail_index_transaction_created(t); -} - -void mbox_transaction_class_init(void) -{ - next_hook_mail_index_transaction_created = - hook_mail_index_transaction_created; - hook_mail_index_transaction_created = mbox_transaction_created; -} - -void mbox_transaction_class_deinit(void) -{ - i_assert(hook_mail_index_transaction_created == - mbox_transaction_created); - hook_mail_index_transaction_created = - next_hook_mail_index_transaction_created; -} diff --git a/src/lib-storage/index/raw/Makefile.am b/src/lib-storage/index/raw/Makefile.am index 38ff536f8c..ad747d28c5 100644 --- a/src/lib-storage/index/raw/Makefile.am +++ b/src/lib-storage/index/raw/Makefile.am @@ -11,8 +11,7 @@ AM_CPPFLAGS = \ libstorage_raw_la_SOURCES = \ raw-mail.c \ raw-sync.c \ - raw-storage.c \ - raw-transaction.c + raw-storage.c headers = \ raw-storage.h \ diff --git a/src/lib-storage/index/raw/raw-storage.c b/src/lib-storage/index/raw/raw-storage.c index 6d8a3c5947..36c600dd50 100644 --- a/src/lib-storage/index/raw/raw-storage.c +++ b/src/lib-storage/index/raw/raw-storage.c @@ -162,16 +162,6 @@ static int raw_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx, } } -static void raw_class_init(void) -{ - raw_transaction_class_init(); -} - -static void raw_class_deinit(void) -{ - raw_transaction_class_deinit(); -} - static void raw_storage_add_list(struct mail_storage *storage ATTR_UNUSED, struct mailbox_list *list) { @@ -185,8 +175,6 @@ struct mail_storage raw_storage = { { NULL, - raw_class_init, - raw_class_deinit, raw_storage_alloc, NULL, index_storage_destroy, diff --git a/src/lib-storage/index/raw/raw-storage.h b/src/lib-storage/index/raw/raw-storage.h index 9bc3443645..2dfa14ab2c 100644 --- a/src/lib-storage/index/raw/raw-storage.h +++ b/src/lib-storage/index/raw/raw-storage.h @@ -26,7 +26,4 @@ struct raw_mailbox { extern struct mail_vfuncs raw_mail_vfuncs; -void raw_transaction_class_init(void); -void raw_transaction_class_deinit(void); - #endif diff --git a/src/lib-storage/index/raw/raw-transaction.c b/src/lib-storage/index/raw/raw-transaction.c deleted file mode 100644 index 12bc065d3a..0000000000 --- a/src/lib-storage/index/raw/raw-transaction.c +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "array.h" -#include "raw-storage.h" - -struct raw_transaction_context { - struct index_transaction_context ictx; - union mail_index_transaction_module_context module_ctx; -}; - -static void (*next_hook_mail_index_transaction_created) - (struct mail_index_transaction *t) = NULL; - -static int -raw_transaction_commit(struct mail_index_transaction *t, - uint32_t *log_file_seq_r, uoff_t *log_file_offset_r) -{ - struct raw_transaction_context *mt = MAIL_STORAGE_CONTEXT(t); - - return index_transaction_finish_commit(&mt->ictx, log_file_seq_r, - log_file_offset_r); -} - -static void raw_transaction_rollback(struct mail_index_transaction *t) -{ - struct raw_transaction_context *mt = MAIL_STORAGE_CONTEXT(t); - - index_transaction_finish_rollback(&mt->ictx); -} - -static void raw_transaction_created(struct mail_index_transaction *t) -{ - struct mailbox *box = MAIL_STORAGE_CONTEXT(t->view); - - /* index can be for mailbox list index, in which case box=NULL */ - if (box != NULL && - strcmp(box->storage->name, RAW_STORAGE_NAME) == 0) { - struct raw_mailbox *raw = (struct raw_mailbox *)box; - struct raw_transaction_context *mt; - - mt = i_new(struct raw_transaction_context, 1); - mt->ictx.trans = t; - index_transaction_init(&mt->ictx, &raw->ibox); - - t->v.commit = raw_transaction_commit; - t->v.rollback = raw_transaction_rollback; - MODULE_CONTEXT_SET(t, mail_storage_mail_index_module, mt); - } - - if (next_hook_mail_index_transaction_created != NULL) - next_hook_mail_index_transaction_created(t); -} - -void raw_transaction_class_init(void) -{ - next_hook_mail_index_transaction_created = - hook_mail_index_transaction_created; - hook_mail_index_transaction_created = raw_transaction_created; -} - -void raw_transaction_class_deinit(void) -{ - i_assert(hook_mail_index_transaction_created == - raw_transaction_created); - hook_mail_index_transaction_created = - next_hook_mail_index_transaction_created; -} diff --git a/src/lib-storage/index/shared/shared-storage.c b/src/lib-storage/index/shared/shared-storage.c index cea4e2cbb4..641258f916 100644 --- a/src/lib-storage/index/shared/shared-storage.c +++ b/src/lib-storage/index/shared/shared-storage.c @@ -292,8 +292,6 @@ struct mail_storage shared_storage = { MEMBER(class_flags) 0, /* unknown at this point */ { - NULL, - NULL, NULL, shared_storage_alloc, shared_storage_create, diff --git a/src/lib-storage/mail-storage-private.h b/src/lib-storage/mail-storage-private.h index 9558123901..80a1827aef 100644 --- a/src/lib-storage/mail-storage-private.h +++ b/src/lib-storage/mail-storage-private.h @@ -28,9 +28,6 @@ struct mail_module_register { struct mail_storage_vfuncs { const struct setting_parser_info *(*get_setting_parser_info)(void); - void (*class_init)(void); - void (*class_deinit)(void); - struct mail_storage *(*alloc)(void); int (*create)(struct mail_storage *storage, struct mail_namespace *ns, const char **error_r); @@ -352,6 +349,8 @@ struct mailbox_transaction_context { struct mail_transaction_commit_changes *changes; ARRAY_DEFINE(module_contexts, union mailbox_transaction_module_context *); + + struct mail_save_context *save_ctx; }; union mail_search_module_context { diff --git a/src/lib-storage/mail-storage.c b/src/lib-storage/mail-storage.c index 20ab12ee5e..1f4a09a416 100644 --- a/src/lib-storage/mail-storage.c +++ b/src/lib-storage/mail-storage.c @@ -46,9 +46,6 @@ void mail_storage_class_register(struct mail_storage *storage_class) { i_assert(mail_storage_find_class(storage_class->name) == NULL); - if (storage_class->v.class_init != NULL) - storage_class->v.class_init(); - /* append it after the list, so the autodetection order is correct */ array_append(&mail_storage_classes, &storage_class, 1); } @@ -65,9 +62,6 @@ void mail_storage_class_unregister(struct mail_storage *storage_class) break; } } - - if (storage_class->v.class_deinit != NULL) - storage_class->v.class_deinit(); } struct mail_storage *mail_storage_find_class(const char *name) diff --git a/src/lib-storage/test-mail-storage.c b/src/lib-storage/test-mail-storage.c index afd4d1bbd0..92a5a3b24d 100644 --- a/src/lib-storage/test-mail-storage.c +++ b/src/lib-storage/test-mail-storage.c @@ -35,8 +35,6 @@ struct mail_storage test_storage = { MEMBER(class_flags) 0, { - NULL, - NULL, NULL, test_storage_alloc, NULL, diff --git a/src/plugins/virtual/virtual-save.c b/src/plugins/virtual/virtual-save.c index 72519b41bf..8d9512ddcf 100644 --- a/src/plugins/virtual/virtual-save.c +++ b/src/plugins/virtual/virtual-save.c @@ -21,10 +21,10 @@ virtual_save_alloc(struct mailbox_transaction_context *_t) struct mailbox_transaction_context *backend_trans; struct virtual_save_context *ctx; - if (t->save_ctx != NULL) - return &t->save_ctx->ctx; + if (_t->save_ctx != NULL) + return _t->save_ctx; - ctx = t->save_ctx = i_new(struct virtual_save_context, 1); + ctx = i_new(struct virtual_save_context, 1); ctx->ctx.transaction = &t->ictx.mailbox_ctx; if (mbox->save_bbox != NULL) { @@ -32,7 +32,8 @@ virtual_save_alloc(struct mailbox_transaction_context *_t) virtual_transaction_get(_t, mbox->save_bbox->box); ctx->backend_save_ctx = mailbox_save_alloc(backend_trans); } - return &ctx->ctx; + _t->save_ctx = &ctx->ctx; + return _t->save_ctx; } static struct mail_keywords * @@ -119,8 +120,10 @@ void virtual_save_cancel(struct mail_save_context *_ctx) mailbox_save_cancel(&ctx->backend_save_ctx); } -void virtual_save_free(struct virtual_save_context *ctx) +void virtual_save_free(struct mail_save_context *_ctx) { + struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx; + if (ctx->backend_keywords != NULL) mailbox_keywords_unref(ctx->backend_box, &ctx->backend_keywords); if (ctx->backend_save_ctx != NULL) diff --git a/src/plugins/virtual/virtual-storage.c b/src/plugins/virtual/virtual-storage.c index 501bb233ca..9a88631a05 100644 --- a/src/plugins/virtual/virtual-storage.c +++ b/src/plugins/virtual/virtual-storage.c @@ -544,16 +544,6 @@ static bool virtual_is_inconsistent(struct mailbox *box) return index_storage_is_inconsistent(box); } -static void virtual_class_init(void) -{ - virtual_transaction_class_init(); -} - -static void virtual_class_deinit(void) -{ - virtual_transaction_class_deinit(); -} - static void virtual_storage_add_list(struct mail_storage *storage ATTR_UNUSED, struct mailbox_list *list) { @@ -576,8 +566,6 @@ struct mail_storage virtual_storage = { { NULL, - virtual_class_init, - virtual_class_deinit, virtual_storage_alloc, NULL, index_storage_destroy, @@ -610,9 +598,9 @@ struct mailbox virtual_mailbox = { index_mailbox_sync_deinit, NULL, virtual_notify_changes, - index_transaction_begin, - index_transaction_commit, - index_transaction_rollback, + virtual_transaction_begin, + virtual_transaction_commit, + virtual_transaction_rollback, index_transaction_set_max_modseq, index_keywords_create, index_keywords_create_from_indexes, diff --git a/src/plugins/virtual/virtual-storage.h b/src/plugins/virtual/virtual-storage.h index 616ca26f3f..7d24884e95 100644 --- a/src/plugins/virtual/virtual-storage.h +++ b/src/plugins/virtual/virtual-storage.h @@ -166,11 +166,8 @@ int virtual_save_begin(struct mail_save_context *ctx, struct istream *input); int virtual_save_continue(struct mail_save_context *ctx); int virtual_save_finish(struct mail_save_context *ctx); void virtual_save_cancel(struct mail_save_context *ctx); -void virtual_save_free(struct virtual_save_context *ctx); +void virtual_save_free(struct mail_save_context *ctx); void virtual_box_copy_error(struct mailbox *dest, struct mailbox *src); -void virtual_transaction_class_init(void); -void virtual_transaction_class_deinit(void); - #endif diff --git a/src/plugins/virtual/virtual-transaction.c b/src/plugins/virtual/virtual-transaction.c index 68519e2ba5..228eb7f253 100644 --- a/src/plugins/virtual/virtual-transaction.c +++ b/src/plugins/virtual/virtual-transaction.c @@ -5,109 +5,82 @@ #include "virtual-storage.h" #include "virtual-transaction.h" -static void (*next_hook_mail_index_transaction_created) - (struct mail_index_transaction *t) = NULL; - struct mailbox_transaction_context * virtual_transaction_get(struct mailbox_transaction_context *trans, struct mailbox *backend_box) { - struct virtual_transaction_context *dt = + struct virtual_transaction_context *vt = (struct virtual_transaction_context *)trans; struct mailbox_transaction_context *const *bt, *new_bt; unsigned int i, count; - bt = array_get(&dt->backend_transactions, &count); + bt = array_get(&vt->backend_transactions, &count); for (i = 0; i < count; i++) { if (bt[i]->box == backend_box) return bt[i]; } new_bt = mailbox_transaction_begin(backend_box, trans->flags); - array_append(&dt->backend_transactions, &new_bt, 1); + array_append(&vt->backend_transactions, &new_bt, 1); return new_bt; } -static int virtual_transaction_commit(struct mail_index_transaction *t, - uint32_t *log_file_seq_r, - uoff_t *log_file_offset_r) +struct mailbox_transaction_context * +virtual_transaction_begin(struct mailbox *box, + enum mailbox_transaction_flags flags) +{ + struct virtual_mailbox *mbox = (struct virtual_mailbox *)box; + struct virtual_transaction_context *vt; + + vt = i_new(struct virtual_transaction_context, 1); + i_array_init(&vt->backend_transactions, + array_count(&mbox->backend_boxes)); + index_transaction_init(&vt->ictx, box, flags); + return &vt->ictx.mailbox_ctx; +} + +int virtual_transaction_commit(struct mailbox_transaction_context *t, + struct mail_transaction_commit_changes *changes_r) { - struct virtual_transaction_context *dt = MAIL_STORAGE_CONTEXT(t); + struct virtual_transaction_context *vt = + (struct virtual_transaction_context *)t; struct mailbox_transaction_context **bt; unsigned int i, count; int ret = 0; - if (dt->save_ctx != NULL) - virtual_save_free(dt->save_ctx); + if (t->save_ctx != NULL) { + virtual_save_free(t->save_ctx); + t->save_ctx = NULL; + } - bt = array_get_modifiable(&dt->backend_transactions, &count); + bt = array_get_modifiable(&vt->backend_transactions, &count); for (i = 0; i < count; i++) { if (mailbox_transaction_commit(&bt[i]) < 0) ret = -1; } - array_free(&dt->backend_transactions); + array_free(&vt->backend_transactions); - if (index_transaction_finish_commit(&dt->ictx, log_file_seq_r, - log_file_offset_r) < 0) + if (index_transaction_commit(t, changes_r) < 0) ret = -1; return ret; } -static void virtual_transaction_rollback(struct mail_index_transaction *t) +void virtual_transaction_rollback(struct mailbox_transaction_context *t) { - struct virtual_transaction_context *dt = MAIL_STORAGE_CONTEXT(t); + struct virtual_transaction_context *vt = + (struct virtual_transaction_context *)t; struct mailbox_transaction_context **bt; unsigned int i, count; - if (dt->save_ctx != NULL) - virtual_save_free(dt->save_ctx); + if (t->save_ctx != NULL) { + virtual_save_free(t->save_ctx); + t->save_ctx = NULL; + } - bt = array_get_modifiable(&dt->backend_transactions, &count); + bt = array_get_modifiable(&vt->backend_transactions, &count); for (i = 0; i < count; i++) mailbox_transaction_rollback(&bt[i]); - array_free(&dt->backend_transactions); - - index_transaction_finish_rollback(&dt->ictx); -} - -static void virtual_transaction_created(struct mail_index_transaction *t) -{ - struct mailbox *box = MAIL_STORAGE_CONTEXT(t->view); + array_free(&vt->backend_transactions); - /* index can be for mailbox list index, in which case box=NULL */ - if (box != NULL && - strcmp(box->storage->name, VIRTUAL_STORAGE_NAME) == 0) { - struct virtual_mailbox *mbox = (struct virtual_mailbox *)box; - struct virtual_transaction_context *mt; - - mt = i_new(struct virtual_transaction_context, 1); - mt->ictx.trans = t; - mt->ictx.super = t->v; - - t->v.commit = virtual_transaction_commit; - t->v.rollback = virtual_transaction_rollback; - MODULE_CONTEXT_SET(t, mail_storage_mail_index_module, mt); - - i_array_init(&mt->backend_transactions, - array_count(&mbox->backend_boxes)); - index_transaction_init(&mt->ictx, &mbox->ibox); - } - - if (next_hook_mail_index_transaction_created != NULL) - next_hook_mail_index_transaction_created(t); -} - -void virtual_transaction_class_init(void) -{ - next_hook_mail_index_transaction_created = - hook_mail_index_transaction_created; - hook_mail_index_transaction_created = virtual_transaction_created; -} - -void virtual_transaction_class_deinit(void) -{ - i_assert(hook_mail_index_transaction_created == - virtual_transaction_created); - hook_mail_index_transaction_created = - next_hook_mail_index_transaction_created; + index_transaction_rollback(t); } diff --git a/src/plugins/virtual/virtual-transaction.h b/src/plugins/virtual/virtual-transaction.h index d2ca72c293..e10525f08c 100644 --- a/src/plugins/virtual/virtual-transaction.h +++ b/src/plugins/virtual/virtual-transaction.h @@ -5,9 +5,6 @@ struct virtual_transaction_context { struct index_transaction_context ictx; - union mail_index_transaction_module_context module_ctx; - - struct virtual_save_context *save_ctx; ARRAY_DEFINE(backend_transactions, struct mailbox_transaction_context *); @@ -17,7 +14,11 @@ struct mailbox_transaction_context * virtual_transaction_get(struct mailbox_transaction_context *trans, struct mailbox *backend_box); -void virtual_transaction_class_init(void); -void virtual_transaction_class_deinit(void); +struct mailbox_transaction_context * +virtual_transaction_begin(struct mailbox *box, + enum mailbox_transaction_flags flags); +int virtual_transaction_commit(struct mailbox_transaction_context *t, + struct mail_transaction_commit_changes *changes_r); +void virtual_transaction_rollback(struct mailbox_transaction_context *t); #endif