Mercurial > dovecot > original-hg > dovecot-1.2
changeset 4453:85fcdb478608 HEAD
Beginnings of joining mail-storage API more closely to mail-index, so that
mail-index could be directly used if needed. Currently only transactions
are joined.
line wrap: on
line diff
--- a/src/lib-index/mail-index-dummy-view.c Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-index/mail-index-dummy-view.c Wed Jun 28 19:31:05 2006 +0300 @@ -17,7 +17,7 @@ return (uint32_t)-3; } -static struct mail_index_view_methods dummy_view_methods = { +static struct mail_index_view_vfuncs dummy_view_vfuncs = { _dummy_view_close, _dummy_view_get_message_count, NULL, @@ -35,7 +35,7 @@ view = i_new(struct mail_index_view, 1); view->refcount = 1; - view->methods = dummy_view_methods; + view->v = dummy_view_vfuncs; view->index = index; return view; }
--- a/src/lib-index/mail-index-private.h Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-index/mail-index-private.h Wed Jun 28 19:31:05 2006 +0300 @@ -6,6 +6,8 @@ #include <fcntl.h> #include "mail-index.h" +#include "mail-index-view-private.h" +#include "mail-index-transaction-private.h" struct mail_transaction_header; struct mail_transaction_log_view; @@ -168,7 +170,7 @@ unsigned int last_grow_count; /* Module-specific contexts. See mail_index_module_id. */ - ARRAY_DEFINE(module_contexts, void); + ARRAY_DEFINE(mail_index_module_contexts, void); char *error; unsigned int nodiskspace:1;
--- a/src/lib-index/mail-index-transaction-private.h Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-index/mail-index-transaction-private.h Wed Jun 28 19:31:05 2006 +0300 @@ -9,8 +9,16 @@ ARRAY_TYPE(seq_range) remove_seq; }; +struct mail_index_transaction_vfuncs { + int (*commit)(struct mail_index_transaction *t, + uint32_t *log_file_seq_r, uoff_t *log_file_offset_r); + void (*rollback)(struct mail_index_transaction *t); +}; + struct mail_index_transaction { int refcount; + + struct mail_index_transaction_vfuncs v; struct mail_index_view *view; ARRAY_DEFINE(appends, struct mail_index_record); @@ -35,6 +43,9 @@ struct mail_cache_transaction_ctx *cache_trans_ctx; + /* Module-specific contexts. See mail_index_module_id. */ + ARRAY_DEFINE(mail_index_transaction_module_contexts, void); + unsigned int hide_transaction:1; unsigned int no_appends:1; unsigned int appends_nonsorted:1; @@ -44,6 +55,9 @@ unsigned int log_updates:1; }; +extern void (*hook_mail_index_transaction_created) + (struct mail_index_transaction *t); + struct mail_index_record * mail_index_transaction_lookup(struct mail_index_transaction *t, uint32_t seq);
--- a/src/lib-index/mail-index-transaction-view.c Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-index/mail-index-transaction-view.c Wed Jun 28 19:31:05 2006 +0300 @@ -10,7 +10,7 @@ struct mail_index_view_transaction { struct mail_index_view view; - struct mail_index_view_methods *parent; + struct mail_index_view_vfuncs *super; struct mail_index_transaction *t; }; @@ -18,9 +18,10 @@ { struct mail_index_view_transaction *tview = (struct mail_index_view_transaction *)view; + struct mail_index_transaction *t = tview->t; - mail_index_transaction_unref(&tview->t); - tview->parent->close(view); + tview->super->close(view); + mail_index_transaction_unref(&t); } static uint32_t _tview_get_message_count(struct mail_index_view *view) @@ -40,7 +41,7 @@ (struct mail_index_view_transaction *)view; /* FIXME: header counters may not be correct */ - return tview->parent->get_header(view); + return tview->super->get_header(view); } static int _tview_lookup_full(struct mail_index_view *view, uint32_t seq, @@ -59,7 +60,7 @@ return 1; } - ret = tview->parent->lookup_full(view, seq, map_r, rec_r); + ret = tview->super->lookup_full(view, seq, map_r, rec_r); if (ret <= 0) return ret; @@ -79,7 +80,7 @@ *uid_r = mail_index_transaction_lookup(tview->t, seq)->uid; return 0; } else { - return tview->parent->lookup_uid(view, seq, uid_r); + return tview->super->lookup_uid(view, seq, uid_r); } } @@ -90,8 +91,8 @@ struct mail_index_view_transaction *tview = (struct mail_index_view_transaction *)view; - if (tview->parent->lookup_uid_range(view, first_uid, last_uid, - first_seq_r, last_seq_r) < 0) + if (tview->super->lookup_uid_range(view, first_uid, last_uid, + first_seq_r, last_seq_r) < 0) return -1; /* FIXME: we don't need this function yet.. new UIDs might be 0 as @@ -117,7 +118,7 @@ unsigned int append_count; uint32_t seq, message_count; - if (tview->parent->lookup_first(view, flags, flags_mask, seq_r) < 0) + if (tview->super->lookup_first(view, flags, flags_mask, seq_r) < 0) return -1; if (*seq_r != 0) @@ -168,8 +169,8 @@ /* not updated, return the existing value */ if (seq < tview->t->first_new_seq) { - return tview->parent->lookup_ext_full(view, seq, ext_id, - map_r, data_r); + return tview->super->lookup_ext_full(view, seq, ext_id, + map_r, data_r); } *data_r = NULL; @@ -184,11 +185,11 @@ (struct mail_index_view_transaction *)view; /* FIXME: check updates */ - return tview->parent->get_header_ext(view, map, ext_id, - data_r, data_size_r); + return tview->super->get_header_ext(view, map, ext_id, + data_r, data_size_r); } -static struct mail_index_view_methods view_methods = { +static struct mail_index_view_vfuncs trans_view_vfuncs = { _tview_close, _tview_get_message_count, _tview_get_header, @@ -215,8 +216,8 @@ tview = i_new(struct mail_index_view_transaction, 1); mail_index_view_clone(&tview->view, t->view); - tview->view.methods = view_methods; - tview->parent = &t->view->methods; + tview->view.v = trans_view_vfuncs; + tview->super = &t->view->v; tview->t = t; mail_index_transaction_ref(t);
--- a/src/lib-index/mail-index-transaction.c Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-index/mail-index-transaction.c Wed Jun 28 19:31:05 2006 +0300 @@ -15,31 +15,8 @@ #include <stddef.h> #include <stdlib.h> -struct mail_index_transaction * -mail_index_transaction_begin(struct mail_index_view *view, - bool hide, bool external) -{ - struct mail_index_transaction *t; - - /* don't allow syncing view while there's ongoing transactions */ - mail_index_view_transaction_ref(view); - mail_index_view_ref(view); - - t = i_new(struct mail_index_transaction, 1); - t->refcount = 1; - t->view = view; - t->hide_transaction = hide; - t->external = external; - t->first_new_seq = mail_index_view_get_messages_count(t->view)+1; - - if (view->syncing) { - /* transaction view cannot work if new records are being added - in two places. make sure it doesn't happen. */ - t->no_appends = TRUE; - } - - return t; -} +void (*hook_mail_index_transaction_created) + (struct mail_index_transaction *t) = NULL; static void mail_index_transaction_free(struct mail_index_transaction *t) { @@ -340,18 +317,12 @@ i_free(old_to_new_map); } -int mail_index_transaction_commit(struct mail_index_transaction **_t, - uint32_t *log_file_seq_r, - uoff_t *log_file_offset_r) +static int _mail_index_transaction_commit(struct mail_index_transaction *t, + uint32_t *log_file_seq_r, + uoff_t *log_file_offset_r) { - struct mail_index_transaction *t = *_t; int ret; - if (mail_index_view_is_inconsistent(t->view)) { - mail_index_transaction_rollback(_t); - return -1; - } - if (t->cache_trans_ctx != NULL) { mail_cache_transaction_commit(t->cache_trans_ctx); t->cache_trans_ctx = NULL; @@ -367,19 +338,40 @@ log_file_offset_r); } - mail_index_transaction_unref(_t); + mail_index_transaction_unref(&t); return ret; } +static void _mail_index_transaction_rollback(struct mail_index_transaction *t) +{ + if (t->cache_trans_ctx != NULL) { + mail_cache_transaction_rollback(t->cache_trans_ctx); + t->cache_trans_ctx = NULL; + } + mail_index_transaction_unref(&t); +} + +int mail_index_transaction_commit(struct mail_index_transaction **_t, + uint32_t *log_file_seq_r, + uoff_t *log_file_offset_r) +{ + struct mail_index_transaction *t = *_t; + + if (mail_index_view_is_inconsistent(t->view)) { + mail_index_transaction_rollback(_t); + return -1; + } + + *_t = NULL; + return t->v.commit(t, log_file_seq_r, log_file_offset_r); +} + void mail_index_transaction_rollback(struct mail_index_transaction **_t) { struct mail_index_transaction *t = *_t; - if (t->cache_trans_ctx != NULL) { - mail_cache_transaction_rollback(t->cache_trans_ctx); - t->cache_trans_ctx = NULL; - } - mail_index_transaction_unref(_t); + *_t = NULL; + t->v.rollback(t); } struct mail_index_record * @@ -951,3 +943,40 @@ t->log_updates = TRUE; } + +struct mail_index_transaction_vfuncs trans_vfuncs = { + _mail_index_transaction_commit, + _mail_index_transaction_rollback +}; + +struct mail_index_transaction * +mail_index_transaction_begin(struct mail_index_view *view, + bool hide, bool external) +{ + struct mail_index_transaction *t; + + /* don't allow syncing view while there's ongoing transactions */ + mail_index_view_transaction_ref(view); + mail_index_view_ref(view); + + t = i_new(struct mail_index_transaction, 1); + t->refcount = 1; + t->v = trans_vfuncs; + t->view = view; + t->hide_transaction = hide; + t->external = external; + t->first_new_seq = mail_index_view_get_messages_count(t->view)+1; + + if (view->syncing) { + /* transaction view cannot work if new records are being added + in two places. make sure it doesn't happen. */ + t->no_appends = TRUE; + } + + ARRAY_CREATE(&t->mail_index_transaction_module_contexts, default_pool, + void *, I_MIN(5, mail_index_module_id)); + + if (hook_mail_index_transaction_created != NULL) + hook_mail_index_transaction_created(t); + return t; +}
--- a/src/lib-index/mail-index-view-private.h Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-index/mail-index-view-private.h Wed Jun 28 19:31:05 2006 +0300 @@ -9,7 +9,7 @@ }; ARRAY_DEFINE_TYPE(view_log_sync_pos, struct mail_index_view_log_sync_pos); -struct mail_index_view_methods { +struct mail_index_view_vfuncs { void (*close)(struct mail_index_view *view); uint32_t (*get_messages_count)(struct mail_index_view *view); const struct mail_index_header * @@ -35,7 +35,7 @@ struct mail_index_view { int refcount; - struct mail_index_view_methods methods; + struct mail_index_view_vfuncs v; struct mail_index *index; struct mail_transaction_log_view *log_view; @@ -56,6 +56,9 @@ /* Transaction log offsets which we don't want to return in view sync */ ARRAY_TYPE(view_log_sync_pos) syncs_hidden; + /* Module-specific contexts. See mail_index_module_id. */ + ARRAY_DEFINE(mail_index_view_module_contexts, void); + int transactions; unsigned int lock_id;
--- a/src/lib-index/mail-index-view.c Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-index/mail-index-view.c Wed Jun 28 19:31:05 2006 +0300 @@ -11,13 +11,14 @@ { memset(dest, 0, sizeof(dest)); dest->refcount = 1; - dest->methods = src->methods; + dest->v = src->v; dest->index = src->index; dest->log_view = mail_transaction_log_view_open(src->index->log); dest->indexid = src->indexid; dest->map = src->map; - dest->map->refcount++; + if (dest->map != NULL) + dest->map->refcount++; dest->hdr = src->hdr; dest->broken_counters = src->broken_counters; @@ -452,18 +453,18 @@ if (--view->refcount > 0) return; - view->methods.close(view); + view->v.close(view); } uint32_t mail_index_view_get_messages_count(struct mail_index_view *view) { - return view->methods.get_messages_count(view); + return view->v.get_messages_count(view); } const struct mail_index_header * mail_index_get_header(struct mail_index_view *view) { - return view->methods.get_header(view); + return view->v.get_header(view); } int mail_index_lookup(struct mail_index_view *view, uint32_t seq, @@ -478,7 +479,7 @@ struct mail_index_map **map_r, const struct mail_index_record **rec_r) { - return view->methods.lookup_full(view, seq, map_r, rec_r); + return view->v.lookup_full(view, seq, map_r, rec_r); } int mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq, @@ -561,21 +562,21 @@ int mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq, uint32_t *uid_r) { - return view->methods.lookup_uid(view, seq, uid_r); + return view->v.lookup_uid(view, seq, uid_r); } int mail_index_lookup_uid_range(struct mail_index_view *view, uint32_t first_uid, uint32_t last_uid, uint32_t *first_seq_r, uint32_t *last_seq_r) { - return view->methods.lookup_uid_range(view, first_uid, last_uid, - first_seq_r, last_seq_r); + return view->v.lookup_uid_range(view, first_uid, last_uid, + first_seq_r, last_seq_r); } int mail_index_lookup_first(struct mail_index_view *view, enum mail_flags flags, uint8_t flags_mask, uint32_t *seq_r) { - return view->methods.lookup_first(view, flags, flags_mask, seq_r); + return view->v.lookup_first(view, flags, flags_mask, seq_r); } int mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq, @@ -583,29 +584,27 @@ { struct mail_index_map *map; - return view->methods.lookup_ext_full(view, seq, ext_id, &map, data_r); + return view->v.lookup_ext_full(view, seq, ext_id, &map, data_r); } int mail_index_lookup_ext_full(struct mail_index_view *view, uint32_t seq, uint32_t ext_id, struct mail_index_map **map_r, const void **data_r) { - return view->methods.lookup_ext_full(view, seq, ext_id, map_r, data_r); + return view->v.lookup_ext_full(view, seq, ext_id, map_r, data_r); } int mail_index_get_header_ext(struct mail_index_view *view, uint32_t ext_id, const void **data_r, size_t *data_size_r) { - return view->methods.get_header_ext(view, NULL, ext_id, - data_r, data_size_r); + return view->v.get_header_ext(view, NULL, ext_id, data_r, data_size_r); } int mail_index_map_get_header_ext(struct mail_index_view *view, struct mail_index_map *map, uint32_t ext_id, const void **data_r, size_t *data_size_r) { - return view->methods.get_header_ext(view, map, ext_id, - data_r, data_size_r); + return view->v.get_header_ext(view, map, ext_id, data_r, data_size_r); } int mail_index_ext_get_size(struct mail_index_view *view __attr_unused__, @@ -639,7 +638,7 @@ return 0; } -static struct mail_index_view_methods view_methods = { +static struct mail_index_view_vfuncs view_vfuncs = { _view_close, _view_get_messages_count, _view_get_header, @@ -659,7 +658,7 @@ view = i_new(struct mail_index_view, 1); view->refcount = 1; - view->methods = view_methods; + view->v = view_vfuncs; view->index = index; view->log_view = mail_transaction_log_view_open(index->log);
--- a/src/lib-index/mail-index.c Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-index/mail-index.c Wed Jun 28 19:31:05 2006 +0300 @@ -18,6 +18,8 @@ #include <time.h> #include <sys/stat.h> +unsigned int mail_index_module_id = 0; + static int mail_index_try_open_only(struct mail_index *index); static void mail_index_create_in_memory(struct mail_index *index, const struct mail_index_header *hdr); @@ -38,6 +40,9 @@ ARRAY_CREATE(&index->sync_lost_handlers, default_pool, mail_index_sync_lost_handler_t *, 4); + ARRAY_CREATE(&index->mail_index_module_contexts, default_pool, + void *, I_MIN(5, mail_index_module_id)); + index->mode = 0600; index->gid = (gid_t)-1;
--- a/src/lib-index/mail-index.h Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-index/mail-index.h Wed Jun 28 19:31:05 2006 +0300 @@ -142,6 +142,8 @@ enum mail_index_sync_type type; }; +extern unsigned int mail_index_module_id; + ARRAY_DEFINE_TYPE(keyword_indexes, unsigned int); struct mail_index;
--- a/src/lib-storage/Makefile.am Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-storage/Makefile.am Wed Jun 28 19:31:05 2006 +0300 @@ -5,7 +5,8 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ -I$(top_srcdir)/src/lib-mail \ - -I$(top_srcdir)/src/lib-imap + -I$(top_srcdir)/src/lib-imap \ + -I$(top_srcdir)/src/lib-index libstorage_a_SOURCES = \ mail.c \
--- a/src/lib-storage/index/dbox/dbox-storage.c Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-storage/index/dbox/dbox-storage.c Wed Jun 28 19:31:05 2006 +0300 @@ -667,11 +667,23 @@ t_strconcat(mbox->path, "/"DBOX_MAILDIR_NAME, NULL)); } +static void dbox_class_init(void) +{ + dbox_transaction_class_init(); +} + +static void dbox_class_deinit(void) +{ + dbox_transaction_class_deinit(); +} + struct mail_storage dbox_storage = { - MEMBER(name) "dbox", + MEMBER(name) DBOX_STORAGE_NAME, MEMBER(hierarchy_sep) '/', { + dbox_class_init, + dbox_class_deinit, dbox_create, dbox_free, dbox_autodetect, @@ -704,9 +716,9 @@ index_mailbox_sync_next, index_mailbox_sync_deinit, dbox_notify_changes, - dbox_transaction_begin, - dbox_transaction_commit, - dbox_transaction_rollback, + index_transaction_begin, + index_transaction_commit, + index_transaction_rollback, index_keywords_create, index_keywords_free, index_storage_get_uids,
--- a/src/lib-storage/index/dbox/dbox-storage.h Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-storage/index/dbox/dbox-storage.h Wed Jun 28 19:31:05 2006 +0300 @@ -4,6 +4,7 @@ #include "index-storage.h" #include "dbox-format.h" +#define DBOX_STORAGE_NAME "dbox" #define STORAGE(mbox_storage) \ (&(mbox_storage)->storage.storage) #define INDEX_STORAGE(mbox_storage) \ @@ -83,12 +84,9 @@ int dbox_mailbox_list_deinit(struct mailbox_list_context *ctx); struct mailbox_list *dbox_mailbox_list_next(struct mailbox_list_context *ctx); -struct mailbox_transaction_context * -dbox_transaction_begin(struct mailbox *box, - enum mailbox_transaction_flags flags); -int dbox_transaction_commit(struct mailbox_transaction_context *t, - enum mailbox_sync_flags flags); -void dbox_transaction_rollback(struct mailbox_transaction_context *t); +void dbox_transaction_created(struct mail_index_transaction *t); +void dbox_transaction_class_init(void); +void dbox_transaction_class_deinit(void); int dbox_save_init(struct mailbox_transaction_context *_t, enum mail_flags flags, struct mail_keywords *keywords,
--- a/src/lib-storage/index/dbox/dbox-transaction.c Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-storage/index/dbox/dbox-transaction.c Wed Jun 28 19:31:05 2006 +0300 @@ -1,47 +1,42 @@ /* Copyright (C) 2005 Timo Sirainen */ #include "lib.h" +#include "array.h" #include "dbox-sync.h" #include "dbox-storage.h" -struct mailbox_transaction_context * -dbox_transaction_begin(struct mailbox *box, - enum mailbox_transaction_flags flags) -{ - struct dbox_mailbox *dbox = (struct dbox_mailbox *)box; - struct dbox_transaction_context *t; +static void (*next_hook_mail_index_transaction_created) + (struct mail_index_transaction *t) = NULL; - t = i_new(struct dbox_transaction_context, 1); - index_transaction_init(&t->ictx, &dbox->ibox, flags); - return &t->ictx.mailbox_ctx; -} - -int dbox_transaction_commit(struct mailbox_transaction_context *_t, - enum mailbox_sync_flags flags __attr_unused__) +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 *t = - (struct dbox_transaction_context *)_t; - struct dbox_mailbox *dbox = (struct dbox_mailbox *)t->ictx.ibox; + struct dbox_transaction_context *dt = MAIL_STORAGE_TRANSACTION(t); + struct dbox_mailbox *dbox = (struct dbox_mailbox *)dt->ictx.ibox; struct dbox_save_context *save_ctx; + bool external = t->external; int ret = 0; - if (t->save_ctx != NULL) { - if (dbox_transaction_save_commit_pre(t->save_ctx) < 0) { - t->save_ctx = NULL; + if (dt->save_ctx != NULL) { + if (dbox_transaction_save_commit_pre(dt->save_ctx) < 0) { + dt->save_ctx = NULL; ret = -1; } } - save_ctx = t->save_ctx; + save_ctx = dt->save_ctx; - if (ret == 0) { - if (index_transaction_commit(_t) < 0) + 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; - } else { - index_transaction_rollback(_t); } - /* transaction is destroyed. */ - t = NULL; _t = NULL; + + /* transaction is destroyed now. */ + dt = NULL; if (save_ctx != NULL) { /* unlock uidlist file after writing to transaction log, @@ -49,7 +44,7 @@ dbox_transaction_save_commit_post(save_ctx); } - if (ret == 0) { + if (ret == 0 && !external) { if (dbox_sync(dbox, FALSE) < 0) ret = -1; } @@ -57,13 +52,52 @@ return ret; } -void dbox_transaction_rollback(struct mailbox_transaction_context *_t) +static void dbox_transaction_rollback(struct mail_index_transaction *t) +{ + struct dbox_transaction_context *dt = MAIL_STORAGE_TRANSACTION(t); + + if (dt->save_ctx != NULL) + dbox_transaction_save_rollback(dt->save_ctx); + + index_transaction_finish_rollback(&dt->ictx); +} + +void dbox_transaction_created(struct mail_index_transaction *t) { - struct dbox_transaction_context *t = - (struct dbox_transaction_context *)_t; + struct mailbox *box = MAIL_STORAGE_INDEX(t->view->index); + + if (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; + mt->ictx.super = t->v; + + t->v.commit = dbox_transaction_commit; + t->v.rollback = dbox_transaction_rollback; - if (t->save_ctx != NULL) - dbox_transaction_save_rollback(t->save_ctx); + array_idx_set(&t->mail_index_transaction_module_contexts, + mail_storage_mail_index_module_id, &mt); + + index_transaction_init(&mt->ictx, &dbox->ibox); + } + + if (next_hook_mail_index_transaction_created != NULL) + next_hook_mail_index_transaction_created(t); +} - index_transaction_rollback(_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; +}
--- a/src/lib-storage/index/index-storage.c Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-storage/index/index-storage.c Wed Jun 28 19:31:05 2006 +0300 @@ -379,6 +379,9 @@ index_cache_register_defaults(ibox); ibox->view = mail_index_view_open(index); ibox->keyword_names = mail_index_get_keywords(index); + + array_idx_set(&index->mail_index_module_contexts, + mail_storage_mail_index_module_id, &ibox); return 0; } @@ -395,6 +398,9 @@ if (ibox->recent_flags != NULL) buffer_free(ibox->recent_flags); i_free(ibox->cache_fields); + + array_idx_clear(&ibox->index->mail_index_module_contexts, + mail_storage_mail_index_module_id); pool_unref(box->pool); }
--- a/src/lib-storage/index/index-storage.h Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-storage/index/index-storage.h Wed Jun 28 19:31:05 2006 +0300 @@ -3,7 +3,7 @@ #include "file-dotlock.h" #include "mail-storage-private.h" -#include "mail-index.h" +#include "mail-index-private.h" /* Max. mmap()ed size for a message */ #define MAIL_MMAP_BLOCK_SIZE (1024*256) @@ -84,8 +84,11 @@ struct index_transaction_context { struct mailbox_transaction_context mailbox_ctx; + struct mail_index_transaction_vfuncs super; + struct index_mailbox *ibox; - enum mailbox_transaction_flags flags; + enum mailbox_transaction_flags flags; + enum mailbox_sync_flags commit_flags; struct mail_index_transaction *trans; struct mail_index_view *trans_view; @@ -178,9 +181,17 @@ int index_storage_search_next_update_seq(struct mail_search_context *ctx); void index_transaction_init(struct index_transaction_context *t, - struct index_mailbox *ibox, - enum mailbox_transaction_flags flags); -int index_transaction_commit(struct mailbox_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); + +struct mailbox_transaction_context * +index_transaction_begin(struct mailbox *box, + enum mailbox_transaction_flags flags); +int index_transaction_commit(struct mailbox_transaction_context *t, + enum mailbox_sync_flags flags); void index_transaction_rollback(struct mailbox_transaction_context *t); bool index_keyword_array_cmp(const ARRAY_TYPE(keyword_indexes) *k1,
--- a/src/lib-storage/index/index-transaction.c Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-storage/index/index-transaction.c Wed Jun 28 19:31:05 2006 +0300 @@ -6,19 +6,14 @@ #include "index-mail.h" void index_transaction_init(struct index_transaction_context *t, - struct index_mailbox *ibox, - enum mailbox_transaction_flags flags) + struct index_mailbox *ibox) { t->mailbox_ctx.box = &ibox->box; t->ibox = ibox; - t->flags = flags; array_create(&t->mailbox_ctx.module_contexts, default_pool, sizeof(void *), 5); - t->trans = mail_index_transaction_begin(ibox->view, - (flags & MAILBOX_TRANSACTION_FLAG_HIDE) != 0, - (flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0); 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); @@ -33,21 +28,19 @@ i_free(t); } -int index_transaction_commit(struct mailbox_transaction_context *_t) +int index_transaction_finish_commit(struct index_transaction_context *t, + uint32_t *log_file_seq_r, + uoff_t *log_file_offset_r) { - struct index_transaction_context *t = - (struct index_transaction_context *)_t; - uint32_t seq; - uoff_t offset; int ret; - ret = mail_index_transaction_commit(&t->trans, &seq, &offset); + ret = t->super.commit(t->trans, log_file_seq_r, log_file_offset_r); if (ret < 0) mail_storage_set_index_error(t->ibox); else { - if (seq != 0) { - t->ibox->commit_log_file_seq = seq; - t->ibox->commit_log_file_offset = offset; + if (*log_file_seq_r != 0) { + t->ibox->commit_log_file_seq = *log_file_seq_r; + t->ibox->commit_log_file_offset = *log_file_offset_r; } } @@ -55,11 +48,46 @@ return ret; } +void index_transaction_finish_rollback(struct index_transaction_context *t) +{ + t->super.rollback(t->trans); + index_transaction_free(t); +} + +struct mailbox_transaction_context * +index_transaction_begin(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; + + t = mail_index_transaction_begin(ibox->view, + (flags & MAILBOX_TRANSACTION_FLAG_HIDE) != 0, + (flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0); + + it = MAIL_STORAGE_TRANSACTION(t); + it->flags = flags; + return &it->mailbox_ctx; +} +int index_transaction_commit(struct mailbox_transaction_context *_t, + enum mailbox_sync_flags flags) +{ + struct index_transaction_context *t = + (struct index_transaction_context *)_t; + struct mail_index_transaction *itrans = t->trans; + uint32_t seq; + uoff_t offset; + + t->commit_flags = flags; + return mail_index_transaction_commit(&itrans, &seq, &offset); +} + 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; - mail_index_transaction_rollback(&t->trans); - index_transaction_free(t); + mail_index_transaction_rollback(&itrans); }
--- a/src/lib-storage/index/maildir/maildir-storage.c Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-storage/index/maildir/maildir-storage.c Wed Jun 28 19:31:05 2006 +0300 @@ -979,11 +979,23 @@ t_strconcat(mbox->path, "/cur", NULL)); } +static void maildir_class_init(void) +{ + maildir_transaction_class_init(); +} + +static void maildir_class_deinit(void) +{ + maildir_transaction_class_deinit(); +} + struct mail_storage maildir_storage = { - MEMBER(name) "maildir", + MEMBER(name) MAILDIR_STORAGE_NAME, MEMBER(hierarchy_sep) MAILDIR_FS_SEP, { + maildir_class_init, + maildir_class_deinit, maildir_create, maildir_free, maildir_autodetect, @@ -1016,9 +1028,9 @@ index_mailbox_sync_next, index_mailbox_sync_deinit, maildir_notify_changes, - maildir_transaction_begin, - maildir_transaction_commit, - maildir_transaction_rollback, + index_transaction_begin, + index_transaction_commit, + index_transaction_rollback, index_keywords_create, index_keywords_free, index_storage_get_uids,
--- a/src/lib-storage/index/maildir/maildir-storage.h Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-storage/index/maildir/maildir-storage.h Wed Jun 28 19:31:05 2006 +0300 @@ -5,6 +5,7 @@ #define MAILDIR_FS_SEP '.' #define MAILDIR_FS_SEP_S "." +#define MAILDIR_STORAGE_NAME "maildir" #define SUBSCRIPTION_FILE_NAME "subscriptions" #define MAILDIR_INDEX_PREFIX "dovecot.index" #define MAILDIR_UNLINK_DIRNAME MAILDIR_FS_SEP_S"DOVECOT-TRASHED" @@ -113,12 +114,9 @@ int maildir_sync_index_finish(struct maildir_index_sync_context **sync_ctx, bool failed); -struct mailbox_transaction_context * -maildir_transaction_begin(struct mailbox *box, - enum mailbox_transaction_flags flags); -int maildir_transaction_commit(struct mailbox_transaction_context *t, - enum mailbox_sync_flags flags); -void maildir_transaction_rollback(struct mailbox_transaction_context *t); +void maildir_transaction_created(struct mail_index_transaction *t); +void maildir_transaction_class_init(void); +void maildir_transaction_class_deinit(void); int maildir_save_init(struct mailbox_transaction_context *_t, enum mail_flags flags, struct mail_keywords *keywords,
--- a/src/lib-storage/index/maildir/maildir-transaction.c Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-storage/index/maildir/maildir-transaction.c Wed Jun 28 19:31:05 2006 +0300 @@ -1,56 +1,90 @@ /* Copyright (C) 2004 Timo Sirainen */ #include "lib.h" +#include "array.h" #include "maildir-storage.h" -struct mailbox_transaction_context * -maildir_transaction_begin(struct mailbox *box, - enum mailbox_transaction_flags flags) -{ - struct maildir_mailbox *mbox = (struct maildir_mailbox *)box; - struct maildir_transaction_context *t; +static void (*next_hook_mail_index_transaction_created) + (struct mail_index_transaction *t) = NULL; - t = i_new(struct maildir_transaction_context, 1); - index_transaction_init(&t->ictx, &mbox->ibox, flags); - return &t->ictx.mailbox_ctx; -} - -int maildir_transaction_commit(struct mailbox_transaction_context *_t, - enum mailbox_sync_flags flags __attr_unused__) +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 *t = - (struct maildir_transaction_context *)_t; - struct maildir_mailbox *mbox = (struct maildir_mailbox *)t->ictx.ibox; + struct maildir_transaction_context *mt = MAIL_STORAGE_TRANSACTION(t); + struct maildir_mailbox *mbox = (struct maildir_mailbox *)mt->ictx.ibox; struct maildir_save_context *save_ctx; + bool external = t->external; int ret = 0; - if (t->save_ctx != NULL) { - if (maildir_transaction_save_commit_pre(t->save_ctx) < 0) { - t->save_ctx = NULL; + if (mt->save_ctx != NULL) { + if (maildir_transaction_save_commit_pre(mt->save_ctx) < 0) { + mt->save_ctx = NULL; ret = -1; } } - save_ctx = t->save_ctx; + save_ctx = mt->save_ctx; - if (index_transaction_commit(_t) < 0) + if (index_transaction_finish_commit(&mt->ictx, log_file_seq_r, + log_file_offset_r) < 0) ret = -1; - /* transaction is destroyed. */ - t = NULL; _t = NULL; + /* transaction is destroyed now. */ + mt = NULL; if (save_ctx != NULL) maildir_transaction_save_commit_post(save_ctx); - return ret < 0 ? -1 : maildir_sync_last_commit(mbox); + if (ret == 0 && !external) + ret = maildir_sync_last_commit(mbox); + return ret; +} + +static void maildir_transaction_rollback(struct mail_index_transaction *t) +{ + struct maildir_transaction_context *mt = MAIL_STORAGE_TRANSACTION(t); + + if (mt->save_ctx != NULL) + maildir_transaction_save_rollback(mt->save_ctx); + index_transaction_finish_rollback(&mt->ictx); } -void maildir_transaction_rollback(struct mailbox_transaction_context *_t) +void maildir_transaction_created(struct mail_index_transaction *t) { - struct maildir_transaction_context *t = - (struct maildir_transaction_context *)_t; + struct mailbox *box = MAIL_STORAGE_INDEX(t->view->index); + + if (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; + mt->ictx.super = t->v; + + t->v.commit = maildir_transaction_commit; + t->v.rollback = maildir_transaction_rollback; + + array_idx_set(&t->mail_index_transaction_module_contexts, + mail_storage_mail_index_module_id, &mt); - if (t->save_ctx != NULL) - maildir_transaction_save_rollback(t->save_ctx); - index_transaction_rollback(_t); + index_transaction_init(&mt->ictx, &mbox->ibox); + } + 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; +}
--- a/src/lib-storage/index/mbox/mbox-storage.c Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-storage/index/mbox/mbox-storage.c Wed Jun 28 19:31:05 2006 +0300 @@ -1085,11 +1085,23 @@ index_mailbox_check_add(&mbox->ibox, mbox->path); } +static void mbox_class_init(void) +{ + mbox_transaction_class_init(); +} + +static void mbox_class_deinit(void) +{ + mbox_transaction_class_deinit(); +} + struct mail_storage mbox_storage = { - MEMBER(name) "mbox", + MEMBER(name) MBOX_STORAGE_NAME, MEMBER(hierarchy_sep) '/', { + mbox_class_init, + mbox_class_deinit, mbox_create, mbox_free, mbox_autodetect, @@ -1122,9 +1134,9 @@ index_mailbox_sync_next, index_mailbox_sync_deinit, mbox_notify_changes, - mbox_transaction_begin, - mbox_transaction_commit, - mbox_transaction_rollback, + index_transaction_begin, + index_transaction_commit, + index_transaction_rollback, index_keywords_create, index_keywords_free, index_storage_get_uids,
--- a/src/lib-storage/index/mbox/mbox-storage.h Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-storage/index/mbox/mbox-storage.h Wed Jun 28 19:31:05 2006 +0300 @@ -6,6 +6,7 @@ /* Don't write Content-Length header unless it's value is larger than this. */ #define MBOX_MIN_CONTENT_LENGTH_SIZE 1024 +#define MBOX_STORAGE_NAME "mbox" #define SUBSCRIPTION_FILE_NAME ".subscriptions" #define MBOX_INDEX_PREFIX "dovecot.index" #define MBOX_INDEX_DIR_NAME ".imap" @@ -70,12 +71,9 @@ int mbox_mailbox_list_deinit(struct mailbox_list_context *ctx); struct mailbox_list *mbox_mailbox_list_next(struct mailbox_list_context *ctx); -struct mailbox_transaction_context * -mbox_transaction_begin(struct mailbox *box, - enum mailbox_transaction_flags flags); -int mbox_transaction_commit(struct mailbox_transaction_context *t, - enum mailbox_sync_flags flags); -void mbox_transaction_rollback(struct mailbox_transaction_context *t); +void mbox_transaction_created(struct mail_index_transaction *t); +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);
--- a/src/lib-storage/index/mbox/mbox-transaction.c Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-storage/index/mbox/mbox-transaction.c Wed Jun 28 19:31:05 2006 +0300 @@ -1,43 +1,40 @@ /* Copyright (C) 2004 Timo Sirainen */ #include "lib.h" +#include "array.h" #include "mbox-storage.h" #include "mbox-lock.h" #include "mbox-sync-private.h" -struct mailbox_transaction_context * -mbox_transaction_begin(struct mailbox *box, - enum mailbox_transaction_flags flags) -{ - struct mbox_mailbox *mbox = (struct mbox_mailbox *)box; - struct mbox_transaction_context *t; +static void (*next_hook_mail_index_transaction_created) + (struct mail_index_transaction *t) = NULL; - t = i_new(struct mbox_transaction_context, 1); - index_transaction_init(&t->ictx, &mbox->ibox, flags); - return &t->ictx.mailbox_ctx; -} - -int mbox_transaction_commit(struct mailbox_transaction_context *_t, - enum mailbox_sync_flags flags) +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 *t = - (struct mbox_transaction_context *)_t; - struct mbox_mailbox *mbox = (struct mbox_mailbox *)t->ictx.ibox; - unsigned int lock_id = t->mbox_lock_id; + struct mbox_transaction_context *mt = MAIL_STORAGE_TRANSACTION(t); + struct mbox_mailbox *mbox = (struct mbox_mailbox *)mt->ictx.ibox; + unsigned int lock_id = mt->mbox_lock_id; + enum mailbox_sync_flags flags = mt->ictx.commit_flags; bool mbox_modified; + bool external = t->external; int ret = 0; - if (t->save_ctx != NULL) - ret = mbox_transaction_save_commit(t->save_ctx); - mbox_modified = t->mbox_modified; + if (mt->save_ctx != NULL) + ret = mbox_transaction_save_commit(mt->save_ctx); + mbox_modified = mt->mbox_modified; - if (ret == 0) { - if (index_transaction_commit(_t) < 0) + 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; - } else { - index_transaction_rollback(_t); } - t = NULL; + + /* transaction is destroyed now. */ + mt = NULL; if (lock_id != 0 && mbox->mbox_lock_type != F_WRLCK) { /* unlock before writing any changes */ @@ -45,7 +42,7 @@ lock_id = 0; } - if (ret == 0) { + if (ret == 0 && !external) { enum mbox_sync_flags mbox_sync_flags = MBOX_SYNC_LAST_COMMIT; if ((flags & MAILBOX_SYNC_FLAG_FULL_READ) != 0 && !mbox->mbox_very_dirty_syncs) @@ -65,16 +62,55 @@ return ret; } -void mbox_transaction_rollback(struct mailbox_transaction_context *_t) +static void mbox_transaction_rollback(struct mail_index_transaction *t) { - struct mbox_transaction_context *t = - (struct mbox_transaction_context *)_t; - struct mbox_mailbox *mbox = (struct mbox_mailbox *)t->ictx.ibox; + struct mbox_transaction_context *mt = MAIL_STORAGE_TRANSACTION(t); + struct mbox_mailbox *mbox = (struct mbox_mailbox *)mt->ictx.ibox; + + 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); +} + +void mbox_transaction_created(struct mail_index_transaction *t) +{ + struct mailbox *box = MAIL_STORAGE_INDEX(t->view->index); + + if (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; + mt->ictx.super = t->v; - if (t->save_ctx != NULL) - mbox_transaction_save_rollback(t->save_ctx); + t->v.commit = mbox_transaction_commit; + t->v.rollback = mbox_transaction_rollback; + + array_idx_set(&t->mail_index_transaction_module_contexts, + mail_storage_mail_index_module_id, &mt); + + index_transaction_init(&mt->ictx, &mbox->ibox); + } + + if (next_hook_mail_index_transaction_created != NULL) + next_hook_mail_index_transaction_created(t); +} - if (t->mbox_lock_id != 0) - (void)mbox_unlock(mbox, t->mbox_lock_id); - index_transaction_rollback(_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; +}
--- a/src/lib-storage/mail-storage-private.h Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-storage/mail-storage-private.h Wed Jun 28 19:31:05 2006 +0300 @@ -8,11 +8,10 @@ #define MAIL_STORAGE_ERR_MAILBOX_NOT_FOUND "Mailbox doesn't exist: %s" #define MAIL_STORAGE_ERR_NO_PERMISSION "Permission denied" -/* Modules should use do "my_id = mail_storage_module_id++" and - use objects' module_contexts[id] for their own purposes. */ -extern unsigned int mail_storage_module_id; +struct mail_storage_vfuncs { + void (*class_init)(void); + void (*class_deinit)(void); -struct mail_storage_vfuncs { struct mail_storage * (*create)(const char *data, const char *user, enum mail_storage_flags flags, @@ -241,6 +240,28 @@ struct mailbox *box; }; +/* Modules should use do "my_id = mail_storage_module_id++" and + use objects' module_contexts[id] for their own purposes. */ +extern unsigned int mail_storage_module_id; + +/* Storage's module_id for mail_index. */ +extern unsigned int mail_storage_mail_index_module_id; + +#define MAIL_STORAGE_INDEX(index) \ + *((void **)array_idx_modifiable( \ + &(index)->mail_index_module_contexts, \ + mail_storage_mail_index_module_id)) + +#define MAIL_STORAGE_VIEW(view) \ + *((void **)array_idx_modifiable( \ + &(view)->mail_index_view_module_contexts, \ + mail_storage_mail_index_module_id)) + +#define MAIL_STORAGE_TRANSACTION(trans) \ + *((void **)array_idx_modifiable( \ + &(trans)->mail_index_transaction_module_contexts, \ + mail_storage_mail_index_module_id)) + /* Set error message in storage. Critical errors are logged with i_error(), but user sees only "internal error" message. */ void mail_storage_clear_error(struct mail_storage *storage);
--- a/src/lib-storage/mail-storage.c Wed Jun 28 18:36:42 2006 +0300 +++ b/src/lib-storage/mail-storage.c Wed Jun 28 19:31:05 2006 +0300 @@ -1,9 +1,10 @@ -/* Copyright (C) 2002-2003 Timo Sirainen */ +/* Copyright (C) 2002-2006 Timo Sirainen */ #include "lib.h" #include "ioloop.h" #include "array.h" #include "var-expand.h" +#include "mail-index-private.h" #include "mail-storage-private.h" #include <stdlib.h> @@ -24,12 +25,15 @@ #define MAILBOX_MAX_HIERARCHY_NAME_LENGTH 200 unsigned int mail_storage_module_id = 0; +unsigned int mail_storage_mail_index_module_id = 0; static ARRAY_DEFINE(storages, struct mail_storage *); void mail_storage_init(void) { ARRAY_CREATE(&storages, default_pool, struct mail_storage *, 8); + + mail_storage_mail_index_module_id = mail_index_module_id++; } void mail_storage_deinit(void) @@ -40,6 +44,9 @@ void mail_storage_class_register(struct mail_storage *storage_class) { + 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(&storages, &storage_class, 1); } @@ -56,6 +63,8 @@ break; } } + + storage_class->v.class_deinit(); } void mail_storage_parse_env(enum mail_storage_flags *flags_r,