changeset 5450:7a6db5ec047d HEAD

Better type safety to module_contexts arrays. Already fixed some bugs.
author Timo Sirainen <tss@iki.fi>
date Thu, 29 Mar 2007 14:51:09 +0300
parents bca896b09c7a
children 3f1eb49a8555
files src/imap/imap-thread.c src/lib-storage/index/dbox/dbox-storage.c src/lib-storage/index/dbox/dbox-storage.h src/lib-storage/index/dbox/dbox-transaction.c src/lib-storage/index/index-storage.c src/lib-storage/index/index-storage.h src/lib-storage/index/index-transaction.c src/lib-storage/index/maildir/maildir-storage.c src/lib-storage/index/maildir/maildir-storage.h src/lib-storage/index/maildir/maildir-transaction.c src/lib-storage/index/mbox/mbox-storage.c src/lib-storage/index/mbox/mbox-storage.h src/lib-storage/index/mbox/mbox-transaction.c src/lib-storage/list/index-mailbox-list-sync.c src/lib-storage/list/index-mailbox-list.c src/lib-storage/list/index-mailbox-list.h src/lib-storage/mail-storage-private.h src/lib-storage/mail-storage.c src/lib-storage/mailbox-list-private.h src/lib-storage/mailbox-list.c src/lib/Makefile.am src/lib/module-context.h src/plugins/acl/Makefile.am src/plugins/acl/acl-mailbox-list.c src/plugins/acl/acl-mailbox.c src/plugins/acl/acl-plugin.h src/plugins/acl/acl-storage.c src/plugins/expire/expire-plugin.c src/plugins/fts-lucene/Makefile.am src/plugins/fts-lucene/fts-backend-lucene.c src/plugins/fts-lucene/fts-lucene-plugin.c src/plugins/fts-lucene/fts-lucene-plugin.h src/plugins/fts-squat/Makefile.am src/plugins/fts/Makefile.am src/plugins/fts/fts-storage.c src/plugins/lazy-expunge/lazy-expunge-plugin.c src/plugins/mail-log/mail-log-plugin.c src/plugins/quota/quota-private.h src/plugins/quota/quota-storage.c src/plugins/trash/Makefile.am src/plugins/zlib/zlib-plugin.c
diffstat 41 files changed, 496 insertions(+), 465 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap/imap-thread.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/imap/imap-thread.c	Thu Mar 29 14:51:09 2007 +0300
@@ -77,8 +77,7 @@
 #include <stdlib.h>
 
 #define IMAP_THREAD_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					imap_thread_storage_module_id))
+	MODULE_CONTEXT(obj, imap_thread_storage_module)
 
 /* how much memory to allocate initially. these are very rough
    approximations. */
@@ -169,7 +168,7 @@
 };
 
 struct imap_thread_mailbox {
-	struct mailbox_vfuncs super;
+	union mailbox_module_context module_ctx;
 	struct mail_hash *msgid_hash;
 
 	/* set only temporarily while needed */
@@ -177,7 +176,9 @@
 };
 
 static void (*next_hook_mailbox_opened)(struct mailbox *box);
-static unsigned int imap_thread_storage_module_id;
+
+static MODULE_CONTEXT_DEFINE_INIT(imap_thread_storage_module,
+				  &mail_storage_module_register);
 
 static void imap_thread_hash_init(struct mailbox *box, bool create);
 
@@ -2082,7 +2083,7 @@
 			return 0;
 
 		t = mail_index_transaction_begin(sync_ctx->view, FALSE, FALSE);
-		mt = MAIL_STORAGE_TRANSACTION(t);
+		mt = MAIL_STORAGE_CONTEXT(t);
 
 		ctx->msgid_hash = tbox->msgid_hash;
 		ctx->msgid_pool =
@@ -2143,7 +2144,7 @@
 	if (tbox->msgid_hash != NULL)
 		mail_hash_free(&tbox->msgid_hash);
 
-	ret = tbox->super.close(box);
+	ret = tbox->module_ctx.super.close(box);
 	i_free(tbox);
 	return ret;
 }
@@ -2178,11 +2179,11 @@
 	struct imap_thread_mailbox *tbox = IMAP_THREAD_CONTEXT(box);
 	struct mailbox_sync_context *ctx;
 
-	ctx = tbox->super.sync_init(box, flags);
+	ctx = tbox->module_ctx.super.sync_init(box, flags);
 	if (box->opened) {
 		imap_thread_hash_init(box, FALSE);
 		/* we don't want to get back here */
-		box->v.sync_init = tbox->super.sync_init;
+		box->v.sync_init = tbox->module_ctx.super.sync_init;
 	}
 	return ctx;
 }
@@ -2195,11 +2196,10 @@
 		next_hook_mailbox_opened(box);
 
 	tbox = i_new(struct imap_thread_mailbox, 1);
-	tbox->super = box->v;
+	tbox->module_ctx.super = box->v;
 	box->v.close = imap_thread_mailbox_close;
 
-	array_idx_set(&box->module_contexts,
-		      imap_thread_storage_module_id, &tbox);
+	MODULE_CONTEXT_SET(box, imap_thread_storage_module, tbox);
 
 	if (box->opened)
 		imap_thread_hash_init(box, FALSE);
@@ -2215,8 +2215,6 @@
 {
 	next_hook_mailbox_opened = hook_mailbox_opened;
 	hook_mailbox_opened = imap_thread_mailbox_opened;
-
-	imap_thread_storage_module_id = mail_storage_module_id++;
 }
 
 void imap_thread_deinit(void)
--- a/src/lib-storage/index/dbox/dbox-storage.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/index/dbox/dbox-storage.c	Thu Mar 29 14:51:09 2007 +0300
@@ -23,8 +23,7 @@
 #define DBOX_LOCK_TOUCH_MSECS (10*1000)
 
 #define DBOX_LIST_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					dbox_mailbox_list_module_id))
+	MODULE_CONTEXT(obj, dbox_mailbox_list_module)
 
 const struct dotlock_settings default_uidlist_dotlock_set = {
 	MEMBER(temp_prefix) NULL,
@@ -68,7 +67,8 @@
 extern struct mail_storage dbox_storage;
 extern struct mailbox dbox_mailbox;
 
-static unsigned int dbox_mailbox_list_module_id = 0;
+static MODULE_CONTEXT_DEFINE_INIT(dbox_mailbox_list_module,
+				  &mailbox_list_module_register);
 
 static int
 dbox_list_delete_mailbox(struct mailbox_list *list, const char *name);
@@ -83,7 +83,7 @@
 	struct dbox_storage *storage = DBOX_LIST_CONTEXT(list);
 	const char *p;
 
-	if (!storage->list_super.is_valid_existing_name(list, name))
+	if (!storage->list_module_ctx.super.is_valid_existing_name(list, name))
 		return FALSE;
 
 	/* Don't allow the mailbox name to end in dbox-Mails */
@@ -100,7 +100,7 @@
 	const char *const *tmp;
 	bool ret = TRUE;
 
-	if (!storage->list_super.is_valid_create_name(list, name))
+	if (!storage->list_module_ctx.super.is_valid_create_name(list, name))
 		return FALSE;
 
 	/* Don't allow creating mailboxes under dbox-Mails */
@@ -206,14 +206,14 @@
 		pool_unref(pool);
 		return NULL;
 	}
-	storage->list_super = list->v;
+	storage->list_module_ctx.super = list->v;
 	list->v.is_valid_existing_name = dbox_storage_is_valid_existing_name;
 	list->v.is_valid_create_name = dbox_storage_is_valid_create_name;
 	list->v.iter_is_mailbox = dbox_list_iter_is_mailbox;
 	list->v.delete_mailbox = dbox_list_delete_mailbox;
 
-	array_idx_set(&list->module_contexts,
-		      dbox_mailbox_list_module_id, &storage);
+	MODULE_CONTEXT_SET_FULL(list, dbox_mailbox_list_module,
+				storage, &storage->list_module_ctx);
 
 	storage->uidlist_dotlock_set = default_uidlist_dotlock_set;
 	storage->file_dotlock_set = default_file_dotlock_set;
@@ -462,7 +462,7 @@
 	index_storage_destroy_unrefed();
 
 	/* delete the index and control directories */
-	if (storage->list_super.delete_mailbox(list, name) < 0)
+	if (storage->list_module_ctx.super.delete_mailbox(list, name) < 0)
 		return -1;
 
 	path = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR);
@@ -600,7 +600,6 @@
 
 static void dbox_class_init(void)
 {
-	dbox_mailbox_list_module_id = mailbox_list_module_id++;
 	dbox_transaction_class_init();
 }
 
--- a/src/lib-storage/index/dbox/dbox-storage.h	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/index/dbox/dbox-storage.h	Thu Mar 29 14:51:09 2007 +0300
@@ -15,7 +15,7 @@
 
 struct dbox_storage {
 	struct index_storage storage;
-	struct mailbox_list_vfuncs list_super;
+	union mailbox_list_module_context list_module_ctx;
 
 	struct dotlock_settings uidlist_dotlock_set;
 	struct dotlock_settings file_dotlock_set;
@@ -77,6 +77,7 @@
 
 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;
--- a/src/lib-storage/index/dbox/dbox-transaction.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/index/dbox/dbox-transaction.c	Thu Mar 29 14:51:09 2007 +0300
@@ -12,7 +12,7 @@
 				   uint32_t *log_file_seq_r,
 				   uoff_t *log_file_offset_r)
 {
-	struct dbox_transaction_context *dt = MAIL_STORAGE_TRANSACTION(t);
+	struct dbox_transaction_context *dt = MAIL_STORAGE_CONTEXT(t);
 	struct dbox_mailbox *dbox = (struct dbox_mailbox *)dt->ictx.ibox;
 	struct dbox_save_context *save_ctx;
 	bool syncing = t->sync_transaction;
@@ -54,7 +54,7 @@
 
 static void dbox_transaction_rollback(struct mail_index_transaction *t)
 {
-	struct dbox_transaction_context *dt = MAIL_STORAGE_TRANSACTION(t);
+	struct dbox_transaction_context *dt = MAIL_STORAGE_CONTEXT(t);
 
 	if (dt->save_ctx != NULL)
 		dbox_transaction_save_rollback(dt->save_ctx);
@@ -64,7 +64,7 @@
 
 void dbox_transaction_created(struct mail_index_transaction *t)
 {
-	struct mailbox *box = MAIL_STORAGE_INDEX(t->view->index);
+	struct mailbox *box = MAIL_STORAGE_CONTEXT(t->view->index);
 
 	/* index can be for mailbox list index, in which case box=NULL */
 	if (box != NULL && strcmp(box->storage->name, DBOX_STORAGE_NAME) == 0) {
@@ -77,9 +77,7 @@
 
 		t->v.commit = dbox_transaction_commit;
 		t->v.rollback = dbox_transaction_rollback;
-
-		array_idx_set(&t->mail_index_transaction_module_contexts,
-			      mail_storage_mail_index_module_id, &mt);
+		MODULE_CONTEXT_SET(t, mail_storage_mail_index_module, mt);
 
 		index_transaction_init(&mt->ictx, &dbox->ibox);
 	}
--- a/src/lib-storage/index/index-storage.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/index/index-storage.c	Thu Mar 29 14:51:09 2007 +0300
@@ -390,8 +390,8 @@
 	ibox->md5hdr_ext_idx =
 		mail_index_ext_register(ibox->index, "header-md5", 0, 16, 1);
 
-	array_idx_set(&ibox->index->mail_index_module_contexts,
-		      mail_storage_mail_index_module_id, &ibox);
+	MODULE_CONTEXT_SET_FULL(ibox->index, mail_storage_mail_index_module,
+				ibox, &ibox->index_module_ctx);
 
 	if ((flags & MAILBOX_OPEN_FAST) == 0)
 		index_storage_mailbox_open(ibox);
@@ -411,8 +411,7 @@
 		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);
+	MODULE_CONTEXT_UNSET(ibox->index, mail_storage_mail_index_module);
 	pool_unref(box->pool);
 }
 
--- a/src/lib-storage/index/index-storage.h	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/index/index-storage.h	Thu Mar 29 14:51:09 2007 +0300
@@ -29,6 +29,8 @@
 
 struct index_mailbox {
 	struct mailbox box;
+	union mail_index_module_context index_module_ctx;
+
 	struct index_storage *storage;
 	enum mailbox_open_flags open_flags;
 
--- a/src/lib-storage/index/index-transaction.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/index/index-transaction.c	Thu Mar 29 14:51:09 2007 +0300
@@ -69,7 +69,7 @@
 		(flags & MAILBOX_TRANSACTION_FLAG_HIDE) != 0,
 		(flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
 
-	it = MAIL_STORAGE_TRANSACTION(t);
+	it = MAIL_STORAGE_CONTEXT(t);
 	if (it == NULL) {
 		i_panic("mail storage transaction context mising for type %s",
 			box->storage->name);
--- a/src/lib-storage/index/maildir/maildir-storage.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Thu Mar 29 14:51:09 2007 +0300
@@ -26,8 +26,7 @@
 #define MAILDIR_SUBFOLDER_FILENAME "maildirfolder"
 
 #define MAILDIR_LIST_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					maildir_mailbox_list_module_id))
+	MODULE_CONTEXT(obj, maildir_mailbox_list_module)
 
 struct rename_context {
 	bool found;
@@ -38,7 +37,8 @@
 extern struct mail_storage maildir_storage;
 extern struct mailbox maildir_mailbox;
 
-static unsigned int maildir_mailbox_list_module_id = 0;
+static MODULE_CONTEXT_DEFINE_INIT(maildir_mailbox_list_module,
+				  &mailbox_list_module_register);
 
 static int verify_inbox(struct mail_storage *storage,
 			enum mailbox_open_flags *flags);
@@ -178,7 +178,7 @@
 	struct maildir_storage *storage = MAILDIR_LIST_CONTEXT(list);
 	const char *p;
 
-	if (!storage->list_super.is_valid_existing_name(list, name))
+	if (!storage->list_module_ctx.super.is_valid_existing_name(list, name))
 		return FALSE;
 
 	/* Don't allow the mailbox name to end in cur/new/tmp */
@@ -195,7 +195,7 @@
 	const char *const *tmp;
 	bool ret = TRUE;
 
-	if (!storage->list_super.is_valid_create_name(list, name))
+	if (!storage->list_module_ctx.super.is_valid_create_name(list, name))
 		return FALSE;
 
 	/* Don't allow creating mailboxes under cur/new/tmp */
@@ -250,7 +250,7 @@
 		pool_unref(pool);
 		return NULL;
 	}
-	storage->list_super = list->v;
+	storage->list_module_ctx.super = list->v;
 	if (strcmp(layout, MAILDIR_PLUSPLUS_DRIVER_NAME) == 0) {
 		list->v.iter_is_mailbox = maildirplusplus_iter_is_mailbox;
 	} else {
@@ -263,8 +263,8 @@
 	list->v.delete_mailbox = maildir_list_delete_mailbox;
 	list->v.rename_mailbox = maildir_list_rename_mailbox;
 
-	array_idx_set(&list->module_contexts,
-		      maildir_mailbox_list_module_id, &storage);
+	MODULE_CONTEXT_SET_FULL(list, maildir_mailbox_list_module,
+				storage, &storage->list_module_ctx);
 
 	storage->copy_with_hardlinks =
 		getenv("MAILDIR_COPY_WITH_HARDLINKS") != NULL;
@@ -797,7 +797,7 @@
 	index_storage_destroy_unrefed();
 
 	/* delete the index and control directories */
-	if (storage->list_super.delete_mailbox(list, name) < 0)
+	if (storage->list_module_ctx.super.delete_mailbox(list, name) < 0)
 		return -1;
 
 	/* check if the mailbox actually exists */
@@ -873,7 +873,8 @@
 		}
 	}
 
-	return storage->list_super.rename_mailbox(list, oldname, newname);
+	return storage->list_module_ctx.super.
+		rename_mailbox(list, oldname, newname);
 }
 
 static int maildir_storage_close(struct mailbox *box)
@@ -1054,7 +1055,6 @@
 
 static void maildir_class_init(void)
 {
-	maildir_mailbox_list_module_id = mailbox_list_module_id++;
 	maildir_transaction_class_init();
 }
 
--- a/src/lib-storage/index/maildir/maildir-storage.h	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-storage.h	Thu Mar 29 14:51:09 2007 +0300
@@ -57,7 +57,7 @@
 struct maildir_storage {
 	struct index_storage storage;
 
-	struct mailbox_list_vfuncs list_super;
+	union mailbox_list_module_context list_module_ctx;
 	const char *temp_prefix;
 
 	unsigned int copy_with_hardlinks:1;
@@ -94,6 +94,8 @@
 
 struct maildir_transaction_context {
 	struct index_transaction_context ictx;
+	union mail_index_transaction_module_context module_ctx;
+
 	struct maildir_save_context *save_ctx;
 };
 
--- a/src/lib-storage/index/maildir/maildir-transaction.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-transaction.c	Thu Mar 29 14:51:09 2007 +0300
@@ -12,7 +12,7 @@
 				      uint32_t *log_file_seq_r,
 				      uoff_t *log_file_offset_r)
 {
-	struct maildir_transaction_context *mt = MAIL_STORAGE_TRANSACTION(t);
+	struct maildir_transaction_context *mt = MAIL_STORAGE_CONTEXT(t);
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)mt->ictx.ibox;
 	struct maildir_save_context *save_ctx;
 	bool syncing = t->sync_transaction;
@@ -48,7 +48,7 @@
 
 static void maildir_transaction_rollback(struct mail_index_transaction *t)
 {
-	struct maildir_transaction_context *mt = MAIL_STORAGE_TRANSACTION(t);
+	struct maildir_transaction_context *mt = MAIL_STORAGE_CONTEXT(t);
 
 	if (mt->save_ctx != NULL)
 		maildir_transaction_save_rollback(mt->save_ctx);
@@ -57,7 +57,7 @@
 
 void maildir_transaction_created(struct mail_index_transaction *t)
 {
-	struct mailbox *box = MAIL_STORAGE_INDEX(t->view->index);
+	struct mailbox *box = MAIL_STORAGE_CONTEXT(t->view->index);
 
 	/* index can be for mailbox list index, in which case box=NULL */
 	if (box != NULL &&
@@ -71,9 +71,7 @@
 
 		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);
+		MODULE_CONTEXT_SET(t, mail_storage_mail_index_module, mt);
 
 		index_transaction_init(&mt->ictx, &mbox->ibox);
 	}
--- a/src/lib-storage/index/mbox/mbox-storage.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Thu Mar 29 14:51:09 2007 +0300
@@ -32,8 +32,7 @@
 	 (st).st_atime < (st).st_mtime ? MAILBOX_MARKED : MAILBOX_UNMARKED)
 
 #define MBOX_LIST_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					mbox_mailbox_list_module_id))
+	MODULE_CONTEXT(obj, mbox_mailbox_list_module)
 
 /* NOTE: must be sorted for istream-header-filter. Note that it's not such
    a good idea to change this list, as the messages will then change from
@@ -69,7 +68,8 @@
 extern struct mail_storage mbox_storage;
 extern struct mailbox mbox_mailbox;
 
-static unsigned int mbox_mailbox_list_module_id = 0;
+static MODULE_CONTEXT_DEFINE_INIT(mbox_mailbox_list_module,
+				  &mailbox_list_module_register);
 
 static int mbox_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
 				     const char *dir, const char *fname,
@@ -387,7 +387,7 @@
 	struct mbox_storage *storage = MBOX_LIST_CONTEXT(list);
 	const char *path, *p;
 
-	path = storage->list_super.get_path(list, name, type);
+	path = storage->list_module_ctx.super.get_path(list, name, type);
 	if (type == MAILBOX_LIST_PATH_TYPE_CONTROL ||
 	    type == MAILBOX_LIST_PATH_TYPE_INDEX) {
 		p = strrchr(path, '/');
@@ -426,7 +426,7 @@
 		pool_unref(pool);
 		return NULL;
 	}
-	storage->list_super = list->v;
+	storage->list_module_ctx.super = list->v;
 	if (strcmp(layout, "fs") == 0 && *list_set.maildir_name == '\0') {
 		/* have to use .imap/ directories */
 		list->v.get_path = mbox_list_get_path;
@@ -434,8 +434,8 @@
 	list->v.iter_is_mailbox = mbox_list_iter_is_mailbox;
 	list->v.delete_mailbox = mbox_list_delete_mailbox;
 
-	array_idx_set(&list->module_contexts,
-		      mbox_mailbox_list_module_id, &storage);
+	MODULE_CONTEXT_SET_FULL(list, mbox_mailbox_list_module,
+				storage, &storage->list_module_ctx);
 
 	istorage = INDEX_STORAGE(storage);
 	istorage->storage = mbox_storage;
@@ -977,7 +977,7 @@
 
 	/* delete index / control files first */
 	index_storage_destroy_unrefed();
-	if (storage->list_super.delete_mailbox(list, name) < 0)
+	if (storage->list_module_ctx.super.delete_mailbox(list, name) < 0)
 		return -1;
 
 	if (unlink(path) < 0) {
@@ -998,7 +998,6 @@
 
 static void mbox_class_init(void)
 {
-	mbox_mailbox_list_module_id = mailbox_list_module_id++;
 	mbox_transaction_class_init();
 }
 
--- a/src/lib-storage/index/mbox/mbox-storage.h	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-storage.h	Thu Mar 29 14:51:09 2007 +0300
@@ -22,7 +22,7 @@
 struct mbox_storage {
 	struct index_storage storage;
 
-	struct mailbox_list_vfuncs list_super;
+	union mailbox_list_module_context list_module_ctx;
 };
 
 struct mbox_mailbox {
@@ -56,6 +56,7 @@
 
 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;
--- a/src/lib-storage/index/mbox/mbox-transaction.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-transaction.c	Thu Mar 29 14:51:09 2007 +0300
@@ -13,7 +13,7 @@
 				   uint32_t *log_file_seq_r,
 				   uoff_t *log_file_offset_r)
 {
-	struct mbox_transaction_context *mt = MAIL_STORAGE_TRANSACTION(t);
+	struct mbox_transaction_context *mt = MAIL_STORAGE_CONTEXT(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;
@@ -66,7 +66,7 @@
 
 static void mbox_transaction_rollback(struct mail_index_transaction *t)
 {
-	struct mbox_transaction_context *mt = MAIL_STORAGE_TRANSACTION(t);
+	struct mbox_transaction_context *mt = MAIL_STORAGE_CONTEXT(t);
 	struct mbox_mailbox *mbox = (struct mbox_mailbox *)mt->ictx.ibox;
 
 	if (mt->save_ctx != NULL)
@@ -79,7 +79,7 @@
 
 void mbox_transaction_created(struct mail_index_transaction *t)
 {
-	struct mailbox *box = MAIL_STORAGE_INDEX(t->view->index);
+	struct mailbox *box = MAIL_STORAGE_CONTEXT(t->view->index);
 
 	/* index can be for mailbox list index, in which case box=NULL */
 	if (box != NULL && strcmp(box->storage->name, MBOX_STORAGE_NAME) == 0) {
@@ -92,9 +92,7 @@
 
 		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);
+		MODULE_CONTEXT_SET(t, mail_storage_mail_index_module, mt);
 
 		index_transaction_init(&mt->ictx, &mbox->ibox);
 	}
--- a/src/lib-storage/list/index-mailbox-list-sync.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/list/index-mailbox-list-sync.c	Thu Mar 29 14:51:09 2007 +0300
@@ -11,15 +11,14 @@
 #include <sys/stat.h>
 
 #define INDEX_LIST_STORAGE_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					index_list_storage_module_id))
+	MODULE_CONTEXT(obj, index_list_storage_module)
 
 #define CACHED_STATUS_ITEMS \
 	(STATUS_MESSAGES | STATUS_UNSEEN | STATUS_RECENT | \
 	 STATUS_UIDNEXT | STATUS_UIDVALIDITY)
 
 struct index_list_mailbox {
-	struct mailbox_vfuncs super;
+	union mailbox_module_context module_ctx;
 
 	uint32_t log_seq;
 	uoff_t log_offset;
@@ -45,14 +44,14 @@
 
 static void (*index_list_next_hook_mailbox_created)(struct mailbox *box);
 
-static unsigned int index_list_storage_module_id = 0;
-static bool index_list_storage_module_id_set = FALSE;
+static MODULE_CONTEXT_DEFINE_INIT(index_list_storage_module,
+				  &mail_storage_module_register);
 
 static int index_list_box_close(struct mailbox *box)
 {
 	struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
 
-	return ibox->super.close(box);
+	return ibox->module_ctx.super.close(box);
 }
 
 static int index_list_update_mail_index(struct index_mailbox_list *ilist,
@@ -251,7 +250,7 @@
 		/* nonsynced / error, fallback to doing it the slow way */
 	}
 
-	return ibox->super.get_status(box, items, status);
+	return ibox->module_ctx.super.get_status(box, items, status);
 }
 
 static int index_list_lookup_or_create(struct index_mailbox_list *ilist,
@@ -397,7 +396,7 @@
 		}
 	}
 
-	return ibox->super.sync_init(box, flags);
+	return ibox->module_ctx.super.sync_init(box, flags);
 }
 
 static int index_list_sync_next(struct mailbox_sync_context *ctx,
@@ -408,7 +407,7 @@
 	if (!ctx->box->opened)
 		return 0;
 
-	return ibox->super.sync_next(ctx, sync_rec_r);
+	return ibox->module_ctx.super.sync_next(ctx, sync_rec_r);
 }
 
 static int index_list_sync_deinit(struct mailbox_sync_context *ctx,
@@ -436,7 +435,8 @@
 
 	if (ilist == NULL) {
 		/* indexing disabled */
-		return ibox->super.sync_deinit(ctx, status_items, status_r);
+		return ibox->module_ctx.super.
+			sync_deinit(ctx, status_items, status_r);
 	}
 
 	/* if status_items == 0, the status_r may be NULL. we really want to
@@ -444,7 +444,7 @@
 	status = status_items == 0 ? &tmp_status : status_r;
 	status_items |= CACHED_STATUS_ITEMS;
 
-	if (ibox->super.sync_deinit(ctx, status_items, status) < 0)
+	if (ibox->module_ctx.super.sync_deinit(ctx, status_items, status) < 0)
 		return -1;
 	ctx = NULL;
 
@@ -474,20 +474,14 @@
 		return;
 
 	ibox = p_new(box->pool, struct index_list_mailbox, 1);
-	ibox->super = box->v;
+	ibox->module_ctx.super = box->v;
 	box->v.close = index_list_box_close;
 	box->v.get_status = index_list_get_status;
 	box->v.sync_init = index_list_sync_init;
 	box->v.sync_next = index_list_sync_next;
 	box->v.sync_deinit = index_list_sync_deinit;
 
-	if (!index_list_storage_module_id_set) {
-		index_list_storage_module_id = mail_storage_module_id++;
-		index_list_storage_module_id_set = TRUE;
-	}
-
-	array_idx_set(&box->module_contexts,
-		      index_list_storage_module_id, &ibox);
+	MODULE_CONTEXT_SET(box, index_list_storage_module, ibox);
 }
 
 void index_mailbox_list_sync_init_list(struct mailbox_list *list)
--- a/src/lib-storage/list/index-mailbox-list.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/list/index-mailbox-list.c	Thu Mar 29 14:51:09 2007 +0300
@@ -16,9 +16,8 @@
 /* min 2 seconds */
 #define MAILBOX_LIST_SYNC_SECS 2
 
-unsigned int index_mailbox_list_module_id = 0;
-
-static bool index_mailbox_list_module_id_set = FALSE;
+struct index_mailbox_list_module index_mailbox_list_module =
+	MODULE_CONTEXT_INIT(&mailbox_list_module_register);
 static void (*index_next_hook_mailbox_list_created)(struct mailbox_list *list);
 
 static int
@@ -151,7 +150,8 @@
 								ctx->sync_ctx);
 		}
 
-		ctx->backend_ctx = ilist->super.iter_init(list, mask, flags);
+		ctx->backend_ctx = ilist->module_ctx.super.
+			iter_init(list, mask, flags);
 	}
 	return &ctx->ctx;
 }
@@ -271,7 +271,7 @@
 	}
 
 	do {
-		info = ilist->super.iter_next(ctx->backend_ctx);
+		info = ilist->module_ctx.super.iter_next(ctx->backend_ctx);
 		if (info == NULL || ctx->sync_ctx == NULL)
 			return info;
 
@@ -314,7 +314,8 @@
 			offsetof(struct mail_index_header, sync_stamp),
 			&ctx->sync_stamp, sizeof(ctx->sync_stamp), TRUE);
 
-		if ((ret = ilist->super.iter_deinit(ctx->backend_ctx)) < 0)
+		ret = ilist->module_ctx.super.iter_deinit(ctx->backend_ctx);
+		if (ret < 0)
 			mailbox_list_index_sync_rollback(&ctx->sync_ctx);
 		else {
 			/* index updates aren't that important. if the commit
@@ -322,7 +323,7 @@
 			(void)mailbox_list_index_sync_commit(&ctx->sync_ctx);
 		}
 	} else if (ctx->backend_ctx != NULL) {
-		ret = ilist->super.iter_deinit(ctx->backend_ctx);
+		ret = ilist->module_ctx.super.iter_deinit(ctx->backend_ctx);
 	}
 
 	imap_match_deinit(&ctx->glob);
@@ -339,7 +340,7 @@
 	mailbox_list_index_view_deinit(&ilist->list_sync_view);
 	mail_index_free(&ilist->mail_index);
 
-	ilist->super.deinit(list);
+	ilist->module_ctx.super.deinit(list);
 }
 
 static int index_mailbox_list_open_indexes(struct mailbox_list *list,
@@ -400,20 +401,13 @@
 		return;
 
 	ilist = p_new(list->pool, struct index_mailbox_list, 1);
-	ilist->super = list->v;
+	ilist->module_ctx.super = list->v;
 
 	list->v.deinit = index_mailbox_list_deinit;
 	list->v.iter_init = index_mailbox_list_iter_init;
 	list->v.iter_deinit = index_mailbox_list_iter_deinit;
 	list->v.iter_next = index_mailbox_list_iter_next;
-
-	if (!index_mailbox_list_module_id_set) {
-		index_mailbox_list_module_id = mailbox_list_module_id++;
-		index_mailbox_list_module_id_set = TRUE;
-	}
-
-	array_idx_set(&list->module_contexts,
-		      index_mailbox_list_module_id, &ilist);
+	MODULE_CONTEXT_SET(list, index_mailbox_list_module, ilist);
 
 	dir = mailbox_list_get_path(list, NULL, MAILBOX_LIST_PATH_TYPE_INDEX);
 	ilist->mail_index = mail_index_alloc(dir, MAIL_INDEX_PREFIX);
@@ -424,10 +418,9 @@
 	index_mailbox_list_sync_init_list(list);
 
 	if (index_mailbox_list_open_indexes(list, dir) < 0) {
-		list->v = ilist->super;
+		list->v = ilist->module_ctx.super;
 		mail_index_free(&ilist->mail_index);
-		array_idx_clear(&list->module_contexts,
-				index_mailbox_list_module_id);
+		MODULE_CONTEXT_UNSET(list, index_mailbox_list_module);
 	}
 }
 
--- a/src/lib-storage/list/index-mailbox-list.h	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/list/index-mailbox-list.h	Thu Mar 29 14:51:09 2007 +0300
@@ -1,17 +1,17 @@
 #ifndef __INDEX_MAILBOX_LIST_H
 #define __INDEX_MAILBOX_LIST_H
 
+#include "module-context.h"
 #include "mailbox-list-private.h"
 
 #define MAIL_INDEX_PREFIX "dovecot.list.index"
 #define MAILBOX_LIST_INDEX_NAME MAIL_INDEX_PREFIX".uidmap"
 
 #define INDEX_LIST_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					index_mailbox_list_module_id))
+	MODULE_CONTEXT(obj, index_mailbox_list_module)
 
 struct index_mailbox_list {
-	struct mailbox_list_vfuncs super;
+	union mailbox_list_module_context module_ctx;
 
 	struct mail_index *mail_index;
 	struct mailbox_list_index *list_index;
@@ -45,7 +45,8 @@
 	unsigned int failed:1;
 };
 
-extern unsigned int index_mailbox_list_module_id;
+extern MODULE_CONTEXT_DEFINE(index_mailbox_list_module,
+			     &mailbox_list_module_register);
 
 void index_mailbox_list_sync_init(void);
 void index_mailbox_list_sync_init_list(struct mailbox_list *list);
--- a/src/lib-storage/mail-storage-private.h	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/mail-storage-private.h	Thu Mar 29 14:51:09 2007 +0300
@@ -1,14 +1,24 @@
 #ifndef __MAIL_STORAGE_PRIVATE_H
 #define __MAIL_STORAGE_PRIVATE_H
 
+#include "module-context.h"
 #include "file-lock.h"
 #include "mail-storage.h"
+#include "mail-index-private.h"
 
 /* Called after mail storage has been created */
 extern void (*hook_mail_storage_created)(struct mail_storage *storage);
 /* Called after mailbox has been opened */
 extern void (*hook_mailbox_opened)(struct mailbox *box);
 
+struct mail_storage_module_register {
+	unsigned int id;
+};
+
+struct mail_module_register {
+	unsigned int id;
+};
+
 struct mail_storage_vfuncs {
 	void (*class_init)(void);
 	void (*class_deinit)(void);
@@ -38,6 +48,11 @@
 				      bool *temporary_error_r);
 };
 
+union mail_storage_module_context {
+	struct mail_storage_vfuncs super;
+	struct mail_storage_module_register *reg;
+};
+
 struct mail_storage {
 	const char *name;
 	bool mailbox_is_file;
@@ -56,7 +71,7 @@
 	void *callback_context;
 
 	/* Module-specific contexts. See mail_storage_module_id. */
-	ARRAY_DEFINE(module_contexts, void);
+	ARRAY_DEFINE(module_contexts, union mail_storage_module_context *);
 
 	/* IMAP: Give a BAD reply instead of NO */
 	unsigned int syntax_error:1;
@@ -141,6 +156,11 @@
 	bool (*is_inconsistent)(struct mailbox *box);
 };
 
+union mailbox_module_context {
+        struct mailbox_vfuncs super;
+	struct mail_storage_module_register *reg;
+};
+
 struct mailbox {
 	char *name;
 	struct mail_storage *storage;
@@ -152,7 +172,7 @@
 	unsigned int transaction_count;
 
 	/* Module-specific contexts. See mail_storage_module_id. */
-	ARRAY_DEFINE(module_contexts, void);
+	ARRAY_DEFINE(module_contexts, union mailbox_module_context *);
 
 	/* When FAST open flag is used, the mailbox isn't actually opened until
 	   it's synced for the first time. */
@@ -194,12 +214,17 @@
 	int (*expunge)(struct mail *mail);
 };
 
+union mail_module_context {
+	struct mail_vfuncs super;
+	struct mail_module_register *reg;
+};
+
 struct mail_private {
 	struct mail mail;
 	struct mail_vfuncs v;
 
 	pool_t pool;
-	ARRAY_DEFINE(module_contexts, void);
+	ARRAY_DEFINE(module_contexts, union mail_module_context *);
 };
 
 struct mailbox_list_context {
@@ -208,9 +233,18 @@
 	bool failed;
 };
 
+union mailbox_transaction_module_context {
+	struct mail_storage_module_register *reg;
+};
+
 struct mailbox_transaction_context {
 	struct mailbox *box;
-	ARRAY_DEFINE(module_contexts, void);
+	ARRAY_DEFINE(module_contexts,
+		     union mailbox_transaction_module_context *);
+};
+
+union mail_search_module_context {
+	struct mail_storage_module_register *reg;
 };
 
 struct mail_search_context {
@@ -221,7 +255,7 @@
 	struct mail_search_sort_program *sort_program;
 
 	uint32_t seq;
-	ARRAY_DEFINE(module_contexts, void);
+	ARRAY_DEFINE(module_contexts, union mail_search_module_context *);
 };
 
 struct mail_save_context {
@@ -239,25 +273,15 @@
 
 /* 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;
+extern struct mail_storage_module_register mail_storage_module_register;
 
 /* 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))
+extern struct mail_module_register mail_module_register;
 
-#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))
+#define MAIL_STORAGE_CONTEXT(obj) \
+	MODULE_CONTEXT(obj, mail_storage_mail_index_module)
+extern MODULE_CONTEXT_DEFINE(mail_storage_mail_index_module,
+			     &mail_index_module_register);
 
 /* Set error message in storage. Critical errors are logged with i_error(),
    but user sees only "internal error" message. */
--- a/src/lib-storage/mail-storage.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/mail-storage.c	Thu Mar 29 14:51:09 2007 +0300
@@ -17,8 +17,11 @@
 	"Internal error occurred. Refer to server log for more information."
 #define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]"
 
-unsigned int mail_storage_module_id = 0;
-unsigned int mail_storage_mail_index_module_id = 0;
+struct mail_storage_module_register mail_storage_module_register = { 0 };
+struct mail_module_register mail_module_register = { 0 };
+
+struct mail_storage_mail_index_module mail_storage_mail_index_module =
+	MODULE_CONTEXT_INIT(&mail_index_module_register);
 
 void (*hook_mail_storage_created)(struct mail_storage *storage);
 void (*hook_mailbox_opened)(struct mailbox *box) = NULL;
@@ -28,8 +31,6 @@
 void mail_storage_init(void)
 {
 	i_array_init(&storages, 8);
-
-	mail_storage_mail_index_module_id = mail_index_module_id++;
 }
 
 void mail_storage_deinit(void)
--- a/src/lib-storage/mailbox-list-private.h	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/mailbox-list-private.h	Thu Mar 29 14:51:09 2007 +0300
@@ -51,6 +51,15 @@
 			      const char *newname);
 };
 
+struct mailbox_list_module_register {
+	unsigned int id;
+};
+
+union mailbox_list_module_context {
+	struct mailbox_list_vfuncs super;
+	struct mailbox_list_module_register *reg;
+};
+
 struct mailbox_list {
 	const char *name;
 	char hierarchy_sep;
@@ -66,7 +75,7 @@
 	char *error;
 	bool temporary_error;
 
-	ARRAY_DEFINE(module_contexts, void);
+	ARRAY_DEFINE(module_contexts, union mailbox_list_module_context *);
 };
 
 struct mailbox_list_iterate_context {
@@ -77,7 +86,7 @@
 
 /* Modules should use do "my_id = mailbox_list_module_id++" and
    use objects' module_contexts[id] for their own purposes. */
-extern unsigned int mailbox_list_module_id;
+extern struct mailbox_list_module_register mailbox_list_module_register;
 
 extern void (*hook_mailbox_list_created)(struct mailbox_list *list);
 
--- a/src/lib-storage/mailbox-list.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib-storage/mailbox-list.c	Thu Mar 29 14:51:09 2007 +0300
@@ -23,7 +23,7 @@
 	"Internal error occurred. Refer to server log for more information."
 #define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]"
 
-unsigned int mailbox_list_module_id = 0;
+struct mailbox_list_module_register mailbox_list_module_register = { 0 };
 
 void (*hook_mailbox_list_created)(struct mailbox_list *list);
 
--- a/src/lib/Makefile.am	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/lib/Makefile.am	Thu Mar 29 14:51:09 2007 +0300
@@ -135,6 +135,7 @@
 	mempool.h \
 	mkdir-parents.h \
 	mmap-util.h \
+	module-context.h \
 	module-dir.h \
 	mountpoint.h \
 	network.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/module-context.h	Thu Mar 29 14:51:09 2007 +0300
@@ -0,0 +1,104 @@
+#ifndef __MODULE_CONTEXT_H
+#define __MODULE_CONTEXT_H
+
+/*
+   This is a bit complex to use, but it prevents using wrong module IDs
+   in module_contexts arrays.
+
+   ---------
+   The main structure is implemented like this:
+
+   struct STRUCT_NAME_module_register {
+	   unsigned int id;
+   };
+   union STRUCT_NAME_module_context {
+	   struct STRUCT_NAME_module_register *reg;
+	   // it's allowed to have some structure here so it won't waste space.
+	   // for example: struct STRUCT_NAME_vfuncs super;
+   };
+   struct STRUCT_NAME {
+	ARRAY_DEFINE(module_contexts, union STRUCT_NAME_module_context *);
+   };
+   extern struct STRUCT_NAME_module_register STRUCT_NAME_module_register;
+
+   ---------
+   The usage in modules goes like:
+
+   static MODULE_CONTEXT_DEFINE(mymodule_STRUCT_NAME_module,
+				&STRUCT_NAME_module_register);
+   struct mymodule_STRUCT_NAME {
+	union STRUCT_NAME_module_context module_ctx;
+	// module-specific data
+   };
+
+   struct mymodule_STRUCT_NAME *ctx = i_new(...);
+   MODULE_CONTEXT_SET(obj, mymodule_STRUCT_NAME_module, ctx);
+
+   struct mymodule_STRUCT_NAME *ctx =
+	MODULE_CONTEXT(obj, mymodule_STRUCT_NAME_module);
+*/
+
+#define OBJ_REGISTER(obj) \
+	((**(obj)->module_contexts.v)->reg)
+#define OBJ_REGISTER_COMPATIBLE(obj, id_ctx) \
+	COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE(OBJ_REGISTER(obj), (id_ctx).reg)
+
+#define MODULE_CONTEXT(obj, id_ctx) \
+	(*((void **)array_idx_modifiable(&(obj)->module_contexts, \
+					(id_ctx).id.module_id) + \
+	 OBJ_REGISTER_COMPATIBLE(obj, id_ctx)))
+
+#ifdef HAVE_TYPEOF
+#  define MODULE_CONTEXT_DEFINE(_name, _reg) \
+	struct _name { \
+		struct module_context_id id; \
+		typeof(_reg) reg; \
+	} _name
+#  define MODULE_CONTEXT_INIT(_reg) \
+	{ { &(_reg)->id, 0, FALSE }, NULL }
+#else
+#  define MODULE_CONTEXT_DEFINE(_name, _reg) \
+	struct _name { \
+		struct module_context_id id; \
+	} _name
+#  define MODULE_CONTEXT_INIT(_reg) \
+	{ { &(_reg)->id, 0, FALSE } }
+#endif
+
+#define MODULE_CONTEXT_DEFINE_INIT(_name, _reg) \
+	MODULE_CONTEXT_DEFINE(_name, _reg) = MODULE_CONTEXT_INIT(_reg)
+
+struct module_context_id {
+	unsigned int *module_id_register;
+	unsigned int module_id;
+	bool module_id_set;
+};
+
+static inline unsigned int module_get_context_id(struct module_context_id *id)
+{
+	if (!id->module_id_set) {
+		id->module_id = *id->module_id_register;
+		id->module_id_set = TRUE;
+		*id->module_id_register += 1;
+	}
+	return id->module_id;
+}
+
+#define MODULE_CONTEXT_SET_FULL(obj, id_ctx, ctx, module_ctx) STMT_START { \
+	void *_module_tmp = ctx + \
+		COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE(module_ctx, \
+			(**(obj)->module_contexts.v)) + \
+		OBJ_REGISTER_COMPATIBLE(obj, id_ctx); \
+	array_idx_set(&(obj)->module_contexts, \
+		module_get_context_id(&(id_ctx).id), (void *)&_module_tmp); \
+	} STMT_END
+
+#define MODULE_CONTEXT_SET(obj, id_ctx, context) \
+	MODULE_CONTEXT_SET_FULL(obj, id_ctx, context, &(context)->module_ctx)
+#define MODULE_CONTEXT_SET_SELF(obj, id_ctx, context) \
+	MODULE_CONTEXT_SET_FULL(obj, id_ctx, context, context)
+
+#define MODULE_CONTEXT_UNSET(obj, id_ctx) \
+	array_idx_clear(&(obj)->module_contexts, (id_ctx).id.module_id)
+
+#endif
--- a/src/plugins/acl/Makefile.am	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/acl/Makefile.am	Thu Mar 29 14:51:09 2007 +0300
@@ -1,6 +1,7 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/lib \
 	-I$(top_srcdir)/src/lib-mail \
+	-I$(top_srcdir)/src/lib-index \
 	-I$(top_srcdir)/src/lib-storage
 
 lib01_acl_plugin_la_LDFLAGS = -module -avoid-version
--- a/src/plugins/acl/acl-mailbox-list.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/acl/acl-mailbox-list.c	Thu Mar 29 14:51:09 2007 +0300
@@ -7,11 +7,10 @@
 #include "acl-plugin.h"
 
 #define ACL_LIST_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					acl_mailbox_list_module_id))
+	MODULE_CONTEXT(obj, acl_mailbox_list_module)
 
 struct acl_mailbox_list {
-	struct mailbox_list_vfuncs super;
+	union mailbox_list_module_context module_ctx;
 
 	/* FIXME: this is wrong. multiple storages can use the same
 	   mailbox_list, so the whole ACL plugin probably needs redesigning.
@@ -19,9 +18,9 @@
 	struct mail_storage *storage;
 };
 
-unsigned int acl_mailbox_list_module_id = 0;
+static MODULE_CONTEXT_DEFINE_INIT(acl_mailbox_list_module,
+				  &mailbox_list_module_register);
 
-static bool acl_mailbox_list_module_id_set = FALSE;
 
 static struct mailbox_info *
 acl_mailbox_list_iter_next(struct mailbox_list_iterate_context *ctx)
@@ -31,7 +30,7 @@
 	int ret;
 
 	for (;;) {
-		info = alist->super.iter_next(ctx);
+		info = alist->module_ctx.super.iter_next(ctx);
 		if (info == NULL)
 			return NULL;
 
@@ -69,7 +68,8 @@
 	if (ret < 0)
 		return -1;
 
-	if (alist->super.get_mailbox_name_status(list, name, status) < 0)
+	if (alist->module_ctx.super.get_mailbox_name_status(list, name,
+							    status) < 0)
 		return -1;
 	if (ret > 0)
 		return 0;
@@ -124,7 +124,7 @@
 		return -1;
 	}
 
-	return alist->super.delete_mailbox(list, name);
+	return alist->module_ctx.super.delete_mailbox(list, name);
 }
 
 static int
@@ -169,7 +169,7 @@
 		return -1;
 	}
 
-	return alist->super.rename_mailbox(list, oldname, newname);
+	return alist->module_ctx.super.rename_mailbox(list, oldname, newname);
 }
 
 void acl_mailbox_list_created(struct mailbox_list *list)
@@ -180,19 +180,13 @@
 		acl_next_hook_mailbox_list_created(list);
 
 	alist = p_new(list->pool, struct acl_mailbox_list, 1);
-	alist->super = list->v;
+	alist->module_ctx.super = list->v;
 	list->v.iter_next = acl_mailbox_list_iter_next;
 	list->v.get_mailbox_name_status = acl_get_mailbox_name_status;
 	list->v.delete_mailbox = acl_mailbox_list_delete;
 	list->v.rename_mailbox = acl_mailbox_list_rename;
 
-	if (!acl_mailbox_list_module_id_set) {
-		acl_mailbox_list_module_id = mailbox_list_module_id++;
-		acl_mailbox_list_module_id_set = TRUE;
-	}
-
-	array_idx_set(&list->module_contexts,
-		      acl_mailbox_list_module_id, &alist);
+	MODULE_CONTEXT_SET(list, acl_mailbox_list_module, alist);
 }
 
 void acl_mailbox_list_set_storage(struct mail_storage *storage)
--- a/src/plugins/acl/acl-mailbox.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/acl/acl-mailbox.c	Thu Mar 29 14:51:09 2007 +0300
@@ -13,29 +13,26 @@
 
 #include <sys/stat.h>
 
-#define ACL_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					acl_storage_module_id))
+#define ACL_MAIL_CONTEXT(obj) \
+	MODULE_CONTEXT(obj, acl_mail_module)
 
 struct acl_mailbox {
-	struct mailbox_vfuncs super;
+	union mailbox_module_context module_ctx;
 	struct acl_object *aclobj;
 
 	unsigned int save_hack:1;
 };
 
-struct acl_mail {
-	struct mail_vfuncs super;
-};
-
 static int acl_mailbox_close(struct mailbox *box)
 {
 	struct acl_mailbox *abox = ACL_CONTEXT(box);
 
 	acl_object_deinit(&abox->aclobj);
-	return abox->super.close(box);
+	return abox->module_ctx.super.close(box);
 }
 
+static MODULE_CONTEXT_DEFINE_INIT(acl_mail_module, &mail_module_register);
+
 static int mailbox_acl_right_lookup(struct mailbox *box, unsigned int right_idx)
 {
 	struct acl_mailbox *abox = ACL_CONTEXT(box);
@@ -81,7 +78,7 @@
 		      enum mail_flags flags)
 {
 	struct mail_private *mail = (struct mail_private *)_mail;
-	struct acl_mail *amail = ACL_CONTEXT(mail);
+	union mail_module_context *amail = ACL_MAIL_CONTEXT(mail);
 	bool acl_flags, acl_flag_seen, acl_flag_del;
 	int ret;
 
@@ -122,7 +119,7 @@
 			 struct mail_keywords *keywords)
 {
 	struct mail_private *mail = (struct mail_private *)_mail;
-	struct acl_mail *amail = ACL_CONTEXT(mail);
+	union mail_module_context *amail = ACL_MAIL_CONTEXT(mail);
 	int ret;
 
 	ret = mailbox_acl_right_lookup(_mail->box, ACL_STORAGE_RIGHT_WRITE);
@@ -137,7 +134,7 @@
 static int acl_mail_expunge(struct mail *_mail)
 {
 	struct mail_private *mail = (struct mail_private *)_mail;
-	struct acl_mail *amail = ACL_CONTEXT(mail);
+	union mail_module_context *amail = ACL_MAIL_CONTEXT(mail);
 	int ret;
 
 	ret = mailbox_acl_right_lookup(_mail->box, ACL_STORAGE_RIGHT_EXPUNGE);
@@ -157,20 +154,21 @@
 	       struct mailbox_header_lookup_ctx *wanted_headers)
 {
 	struct acl_mailbox *abox = ACL_CONTEXT(t->box);
-	struct acl_mail *amail;
+	union mail_module_context *amail;
 	struct mail *_mail;
 	struct mail_private *mail;
 
-	_mail = abox->super.mail_alloc(t, wanted_fields, wanted_headers);
+	_mail = abox->module_ctx.super.
+		mail_alloc(t, wanted_fields, wanted_headers);
 	mail = (struct mail_private *)_mail;
 
-	amail = p_new(mail->pool, struct acl_mail, 1);
+	amail = p_new(mail->pool, union mail_module_context, 1);
 	amail->super = mail->v;
 
 	mail->v.update_flags = acl_mail_update_flags;
 	mail->v.update_keywords = acl_mail_update_keywords;
 	mail->v.expunge = acl_mail_expunge;
-	array_idx_set(&mail->module_contexts, acl_storage_module_id, &amail);
+	MODULE_CONTEXT_SET_SELF(mail, acl_mail_module, amail);
 	return _mail;
 }
 
@@ -186,9 +184,10 @@
 	if (mailbox_acl_right_lookup(t->box, ACL_STORAGE_RIGHT_INSERT) <= 0)
 		return -1;
 
-	return abox->super.save_init(t, flags, keywords, received_date,
-				     timezone_offset, from_envelope,
-				     input, dest_mail, ctx_r);
+	return abox->module_ctx.super.
+		save_init(t, flags, keywords, received_date,
+			  timezone_offset, from_envelope,
+			  input, dest_mail, ctx_r);
 }
 
 static int
@@ -201,7 +200,7 @@
 	if (mailbox_acl_right_lookup(t->box, ACL_STORAGE_RIGHT_INSERT) <= 0)
 		return -1;
 
-	return abox->super.copy(t, mail, flags, keywords, dest_mail);
+	return abox->module_ctx.super.copy(t, mail, flags, keywords, dest_mail);
 }
 
 struct mailbox *acl_mailbox_open_box(struct mailbox *box)
@@ -210,7 +209,7 @@
 	struct acl_mailbox *abox;
 
 	abox = p_new(box->pool, struct acl_mailbox, 1);
-	abox->super = box->v;
+	abox->module_ctx.super = box->v;
 	abox->aclobj = acl_object_init_from_name(astorage->backend,
 						 mailbox_get_name(box));
 	
@@ -218,6 +217,6 @@
 	box->v.mail_alloc = acl_mail_alloc;
 	box->v.save_init = acl_save_init;
 	box->v.copy = acl_copy;
-	array_idx_set(&box->module_contexts, acl_storage_module_id, &abox);
+	MODULE_CONTEXT_SET(box, acl_storage_module, abox);
 	return box;
 }
--- a/src/plugins/acl/acl-plugin.h	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/acl/acl-plugin.h	Thu Mar 29 14:51:09 2007 +0300
@@ -4,8 +4,7 @@
 #include "mail-storage-private.h"
 
 #define ACL_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					acl_storage_module_id))
+	MODULE_CONTEXT(obj, acl_storage_module)
 
 enum acl_storage_rights {
 	ACL_STORAGE_RIGHT_LOOKUP,
@@ -23,7 +22,8 @@
 };
 
 struct acl_mail_storage {
-	struct mail_storage_vfuncs super;
+	union mail_storage_module_context module_ctx;
+
 	struct acl_backend *backend;
 	unsigned int acl_storage_right_idx[ACL_STORAGE_RIGHT_COUNT];
 };
@@ -31,7 +31,7 @@
 extern void (*acl_next_hook_mail_storage_created)
 	(struct mail_storage *storage);
 extern void (*acl_next_hook_mailbox_list_created)(struct mailbox_list *list);
-extern unsigned int acl_storage_module_id;
+extern MODULE_CONTEXT_DEFINE(acl_storage_module, &mail_storage_module_register);
 
 void acl_mail_storage_created(struct mail_storage *storage);
 void acl_mailbox_list_created(struct mailbox_list *list);
--- a/src/plugins/acl/acl-storage.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/acl/acl-storage.c	Thu Mar 29 14:51:09 2007 +0300
@@ -9,9 +9,8 @@
 
 #include <stdlib.h>
 
-unsigned int acl_storage_module_id = 0;
-
-static bool acl_storage_module_id_set = FALSE;
+struct acl_storage_module acl_storage_module =
+	MODULE_CONTEXT_INIT(&mail_storage_module_register);
 
 static const char *acl_storage_right_names[ACL_STORAGE_RIGHT_COUNT] = {
 	MAIL_ACL_LOOKUP,
@@ -66,7 +65,7 @@
 	struct acl_mail_storage *astorage = ACL_CONTEXT(storage);
 
 	acl_backend_deinit(&astorage->backend);
-	astorage->super.destroy(storage);
+	astorage->module_ctx.super.destroy(storage);
 }
 
 static struct mailbox *
@@ -101,7 +100,8 @@
 		return NULL;
 	}
 
-	box = astorage->super.mailbox_open(storage, name, input, flags);
+	box = astorage->module_ctx.super.
+		mailbox_open(storage, name, input, flags);
 	if (box == NULL)
 		return NULL;
 
@@ -131,7 +131,8 @@
 		return -1;
 	}
 
-	return astorage->super.mailbox_create(storage, name, directory);
+	return astorage->module_ctx.super.
+		mailbox_create(storage, name, directory);
 }
 
 void acl_mail_storage_created(struct mail_storage *storage)
@@ -168,7 +169,7 @@
 	}
 
 	astorage = p_new(storage->pool, struct acl_mail_storage, 1);
-	astorage->super = storage->v;
+	astorage->module_ctx.super = storage->v;
 	astorage->backend = backend;
 	storage->v.destroy = acl_storage_destroy;
 	storage->v.mailbox_open = acl_mailbox_open;
@@ -183,12 +184,6 @@
 						 acl_storage_right_names[i]);
 	}
 
-	if (!acl_storage_module_id_set) {
-		acl_storage_module_id = mail_storage_module_id++;
-		acl_storage_module_id_set = TRUE;
-	}
-
-	array_idx_set(&storage->module_contexts,
-		      acl_storage_module_id, &astorage);
+	MODULE_CONTEXT_SET(storage, acl_storage_module, astorage);
 }
 
--- a/src/plugins/expire/expire-plugin.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/expire/expire-plugin.c	Thu Mar 29 14:51:09 2007 +0300
@@ -12,34 +12,26 @@
 #include <stdlib.h>
 
 #define EXPIRE_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					expire.storage_module_id))
+	MODULE_CONTEXT(obj, expire_storage_module)
+#define EXPIRE_MAIL_CONTEXT(obj) \
+	MODULE_CONTEXT(obj, expire_mail_module)
 
 struct expire {
 	struct dict *db;
 	struct expire_env *env;
 	const char *username;
 
-	unsigned int storage_module_id;
-	bool storage_module_id_set;
-
 	void (*next_hook_mail_storage_created)(struct mail_storage *storage);
 };
 
-struct expire_mail_storage {
-	struct mail_storage_vfuncs super;
-};
-
 struct expire_mailbox {
-	struct mailbox_vfuncs super;
+	union mailbox_module_context module_ctx;
 	time_t expire_secs;
 };
 
-struct expire_mail {
-	struct mail_vfuncs super;
-};
+struct expire_transaction_context {
+	union mailbox_transaction_module_context module_ctx;
 
-struct expire_transaction_context {
 	struct mail *mail;
 	time_t first_save_time;
 
@@ -49,6 +41,9 @@
 const char *expire_plugin_version = PACKAGE_VERSION;
 
 static struct expire expire;
+static MODULE_CONTEXT_DEFINE_INIT(expire_storage_module,
+				  &mail_storage_module_register);
+static MODULE_CONTEXT_DEFINE_INIT(expire_mail_module, &mail_module_register);
 
 static struct mailbox_transaction_context *
 expire_mailbox_transaction_begin(struct mailbox *box,
@@ -58,11 +53,11 @@
 	struct mailbox_transaction_context *t;
 	struct expire_transaction_context *xt;
 
-	t = xpr_box->super.transaction_begin(box, flags);
+	t = xpr_box->module_ctx.super.transaction_begin(box, flags);
 	xt = i_new(struct expire_transaction_context, 1);
 	xt->mail = mail_alloc(t, 0, NULL);
 
-	array_idx_set(&t->module_contexts, expire.storage_module_id, &xt);
+	MODULE_CONTEXT_SET(t, expire_storage_module, xt);
 	return t;
 }
 
@@ -133,7 +128,7 @@
 	mail_free(&xt->mail);
 	i_free(xt);
 
-	if (xpr_box->super.transaction_commit(t, flags) < 0) {
+	if (xpr_box->module_ctx.super.transaction_commit(t, flags) < 0) {
 		t_pop();
 		return -1;
 	}
@@ -159,14 +154,14 @@
 
 	mail_free(&xt->mail);
 
-	xpr_box->super.transaction_rollback(t);
+	xpr_box->module_ctx.super.transaction_rollback(t);
 	i_free(xt);
 }
 
 static int expire_mail_expunge(struct mail *_mail)
 {
 	struct mail_private *mail = (struct mail_private *)_mail;
-	struct expire_mail *xpr_mail = EXPIRE_CONTEXT(mail);
+	union mail_module_context *xpr_mail = EXPIRE_MAIL_CONTEXT(mail);
 	struct expire_transaction_context *xt =
 		EXPIRE_CONTEXT(_mail->transaction);
 
@@ -186,19 +181,19 @@
 		  struct mailbox_header_lookup_ctx *wanted_headers)
 {
 	struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(t->box);
-	struct expire_mail *xpr_mail;
+	union mail_module_context *xpr_mail;
 	struct mail *_mail;
 	struct mail_private *mail;
 
-	_mail = xpr_box->super.mail_alloc(t, wanted_fields, wanted_headers);
+	_mail = xpr_box->module_ctx.super.
+		mail_alloc(t, wanted_fields, wanted_headers);
 	mail = (struct mail_private *)_mail;
 
-	xpr_mail = p_new(mail->pool, struct expire_mail, 1);
+	xpr_mail = p_new(mail->pool, union mail_module_context, 1);
 	xpr_mail->super = mail->v;
 
 	mail->v.expunge = expire_mail_expunge;
-	array_idx_set(&mail->module_contexts, expire.storage_module_id,
-		      &xpr_mail);
+	MODULE_CONTEXT_SET_SELF(mail, expire_mail_module, xpr_mail);
 	return _mail;
 }
 
@@ -230,9 +225,10 @@
 	if (dest_mail == NULL)
 		dest_mail = xt->mail;
 
-	ret = xpr_box->super.save_init(t, flags, keywords, received_date,
-				       timezone_offset, from_envelope, input,
-				       dest_mail, ctx_r);
+	ret = xpr_box->module_ctx.super.
+		save_init(t, flags, keywords, received_date,
+			  timezone_offset, from_envelope, input,
+			  dest_mail, ctx_r);
 	if (ret >= 0)
 		mail_set_save_time(t, dest_mail->seq);
 	return ret;
@@ -250,7 +246,8 @@
 	if (dest_mail == NULL)
 		dest_mail = xt->mail;
 
-	ret = xpr_box->super.copy(t, mail, flags, keywords, dest_mail);
+	ret = xpr_box->module_ctx.super.
+		copy(t, mail, flags, keywords, dest_mail);
 	if (ret >= 0)
 		mail_set_save_time(t, dest_mail->seq);
 	return ret;
@@ -261,7 +258,7 @@
 	struct expire_mailbox *xpr_box;
 
 	xpr_box = p_new(box->pool, struct expire_mailbox, 1);
-	xpr_box->super = box->v;
+	xpr_box->module_ctx.super = box->v;
 
 	box->v.transaction_begin = expire_mailbox_transaction_begin;
 	box->v.transaction_commit = expire_mailbox_transaction_commit;
@@ -272,15 +269,15 @@
 
 	xpr_box->expire_secs = expire_secs;
 
-	array_idx_set(&box->module_contexts,
-		      expire.storage_module_id, &xpr_box);
+	MODULE_CONTEXT_SET(box, expire_storage_module, xpr_box);
 }
 
 static struct mailbox *
 expire_mailbox_open(struct mail_storage *storage, const char *name,
 		    struct istream *input, enum mailbox_open_flags flags)
 {
-	struct expire_mail_storage *xpr_storage = EXPIRE_CONTEXT(storage);
+	union mail_storage_module_context *xpr_storage =
+		EXPIRE_CONTEXT(storage);
 	struct mailbox *box;
 	const struct expire_box *expire_box;
 
@@ -295,22 +292,17 @@
 
 static void expire_mail_storage_created(struct mail_storage *storage)
 {
-	struct expire_mail_storage *xpr_storage;
+	union mail_storage_module_context *xpr_storage;
 
 	if (expire.next_hook_mail_storage_created != NULL)
 		expire.next_hook_mail_storage_created(storage);
 
-	xpr_storage = p_new(storage->pool, struct expire_mail_storage, 1);
+	xpr_storage =
+		p_new(storage->pool, union mail_storage_module_context, 1);
 	xpr_storage->super = storage->v;
 	storage->v.mailbox_open = expire_mailbox_open;
 
-	if (!expire.storage_module_id_set) {
-		expire.storage_module_id = mail_storage_module_id++;
-		expire.storage_module_id_set = TRUE;
-	}
-
-	array_idx_set(&storage->module_contexts,
-		      expire.storage_module_id, &xpr_storage);
+	MODULE_CONTEXT_SET_SELF(storage, expire_storage_module, xpr_storage);
 }
 
 void expire_plugin_init(void)
--- a/src/plugins/fts-lucene/Makefile.am	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/fts-lucene/Makefile.am	Thu Mar 29 14:51:09 2007 +0300
@@ -1,6 +1,7 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/lib \
 	-I$(top_srcdir)/src/lib-mail \
+	-I$(top_srcdir)/src/lib-index \
 	-I$(top_srcdir)/src/lib-storage \
 	-I$(top_srcdir)/src/plugins/fts \
 	-I/usr/lib
--- a/src/plugins/fts-lucene/fts-backend-lucene.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/fts-lucene/fts-backend-lucene.c	Thu Mar 29 14:51:09 2007 +0300
@@ -11,6 +11,7 @@
 #define LUCENE_LOCK_SUBDIR_NAME "locks"
 
 struct lucene_mail_storage {
+	union mail_storage_module_context module_ctx;
 	struct lucene_index *index;
 	struct mailbox *selected_box;
 	int refcount;
@@ -57,8 +58,8 @@
 
 		lstorage = i_new(struct lucene_mail_storage, 1);
 		lstorage->index = lucene_index_init(path, lock_path);
-		array_idx_set(&box->storage->module_contexts,
-			      fts_lucene_storage_module_id, &lstorage);
+		MODULE_CONTEXT_SET(box->storage, fts_lucene_storage_module,
+				   lstorage);
 	}
 	lstorage->refcount++;
 
@@ -75,8 +76,8 @@
 		(struct lucene_fts_backend *)_backend;
 
 	if (--backend->lstorage->refcount == 0) {
-		array_idx_clear(&backend->box->storage->module_contexts,
-				fts_lucene_storage_module_id);
+		MODULE_CONTEXT_UNSET(backend->box->storage,
+				     fts_lucene_storage_module);
 		lucene_index_deinit(backend->lstorage->index);
 		i_free(backend->lstorage);
 	}
--- a/src/plugins/fts-lucene/fts-lucene-plugin.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/fts-lucene/fts-lucene-plugin.c	Thu Mar 29 14:51:09 2007 +0300
@@ -10,7 +10,6 @@
 
 void fts_lucene_plugin_init(void)
 {
-	fts_lucene_storage_module_id = mail_storage_module_id++;
 	fts_backend_register(&fts_backend_lucene);
 }
 
--- a/src/plugins/fts-lucene/fts-lucene-plugin.h	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/fts-lucene/fts-lucene-plugin.h	Thu Mar 29 14:51:09 2007 +0300
@@ -4,11 +4,11 @@
 #include "fts-api-private.h"
 
 #define LUCENE_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					fts_lucene_storage_module_id))
+	MODULE_CONTEXT(obj, fts_lucene_storage_module)
 
 extern struct fts_backend fts_backend_lucene;
-extern unsigned int fts_lucene_storage_module_id;
+extern MODULE_CONTEXT_DEFINE(fts_lucene_storage_module,
+			     &mail_storage_module_register);
 
 void fts_lucene_plugin_init(void);
 void fts_lucene_plugin_deinit(void);
--- a/src/plugins/fts-squat/Makefile.am	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/fts-squat/Makefile.am	Thu Mar 29 14:51:09 2007 +0300
@@ -1,6 +1,7 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/lib \
 	-I$(top_srcdir)/src/lib-mail \
+	-I$(top_srcdir)/src/lib-index \
 	-I$(top_srcdir)/src/lib-storage \
 	-I$(top_srcdir)/src/plugins/fts
 
--- a/src/plugins/fts/Makefile.am	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/fts/Makefile.am	Thu Mar 29 14:51:09 2007 +0300
@@ -1,6 +1,7 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/lib \
 	-I$(top_srcdir)/src/lib-mail \
+	-I$(top_srcdir)/src/lib-index \
 	-I$(top_srcdir)/src/lib-storage
 
 lib20_fts_plugin_la_LDFLAGS = -module -avoid-version
--- a/src/plugins/fts/fts-storage.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/fts/fts-storage.c	Thu Mar 29 14:51:09 2007 +0300
@@ -15,14 +15,15 @@
 #include <stdlib.h>
 
 #define FTS_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					fts_storage_module_id))
+	MODULE_CONTEXT(obj, fts_storage_module)
+#define FTS_MAIL_CONTEXT(obj) \
+	MODULE_CONTEXT(obj, fts_mail_module)
 
 #define FTS_SEARCH_NONBLOCK_COUNT 10
 #define FTS_BUILD_NOTIFY_INTERVAL_SECS 10
 
 struct fts_mailbox {
-	struct mailbox_vfuncs super;
+	union mailbox_module_context module_ctx;
 	struct fts_backend *backend_exact;
 	struct fts_backend *backend_fast;
 
@@ -31,6 +32,8 @@
 };
 
 struct fts_search_context {
+	union mail_search_module_context module_ctx;
+
 	ARRAY_TYPE(seq_range) result;
 	unsigned int result_pos;
 
@@ -58,15 +61,13 @@
 };
 
 struct fts_transaction_context {
+	union mailbox_transaction_module_context module_ctx;
 	bool expunges;
 };
 
-struct fts_mail {
-	struct mail_vfuncs super;
-};
-
-static unsigned int fts_storage_module_id = 0;
-static bool fts_storage_module_id_set = FALSE;
+static MODULE_CONTEXT_DEFINE_INIT(fts_storage_module,
+				  &mail_storage_module_register);
+static MODULE_CONTEXT_DEFINE_INIT(fts_mail_module, &mail_module_register);
 
 static int fts_mailbox_close(struct mailbox *box)
 {
@@ -78,7 +79,7 @@
 	if (fbox->backend_fast != NULL)
 		fts_backend_deinit(fbox->backend_fast);
 
-	ret = fbox->super.close(box);
+	ret = fbox->module_ctx.super.close(box);
 	i_free(fbox);
 	return ret;
 }
@@ -563,12 +564,13 @@
 	struct mail_search_arg *best_fast_arg, *best_exact_arg;
 	bool have_fast, have_exact;
 
-	ctx = fbox->super.search_init(t, charset, args, sort_program);
+	ctx = fbox->module_ctx.super.
+		search_init(t, charset, args, sort_program);
 
 	fctx = i_new(struct fts_search_context, 1);
 	fctx->t = t;
 	fctx->args = args;
-	array_idx_set(&ctx->module_contexts, fts_storage_module_id, &fctx);
+	MODULE_CONTEXT_SET(ctx, fts_storage_module, fctx);
 
 	if (fbox->backend_exact == NULL && fbox->backend_fast == NULL)
 		return ctx;
@@ -620,7 +622,8 @@
 		if (ret > 0)
 			fts_search_init(ctx->transaction->box, fctx);
 	}
-	return fbox->super.search_next_nonblock(ctx, mail, tryagain_r);
+	return fbox->module_ctx.super.
+		search_next_nonblock(ctx, mail, tryagain_r);
 
 }
 
@@ -634,7 +637,7 @@
 	int ret;
 
 	if (!array_is_created(&fctx->result))
-		return fbox->super.search_next_update_seq(ctx);
+		return fbox->module_ctx.super.search_next_update_seq(ctx);
 
 	do {
 		range = array_get_modifiable(&fctx->result, &count);
@@ -658,7 +661,7 @@
 		}
 
 		wanted_seq = ctx->seq + 1;
-		ret = fbox->super.search_next_update_seq(ctx);
+		ret = fbox->module_ctx.super.search_next_update_seq(ctx);
 	} while (ret > 0 && wanted_seq != ctx->seq);
 
 	return ret;
@@ -680,13 +683,13 @@
 	if (array_is_created(&fctx->result))
 		array_free(&fctx->result);
 	i_free(fctx);
-	return fbox->super.search_deinit(ctx);
+	return fbox->module_ctx.super.search_deinit(ctx);
 }
 
 static int fts_mail_expunge(struct mail *_mail)
 {
 	struct mail_private *mail = (struct mail_private *)_mail;
-	struct fts_mail *fmail = FTS_CONTEXT(mail);
+	union mail_module_context *fmail = FTS_MAIL_CONTEXT(mail);
 	struct fts_mailbox *fbox = FTS_CONTEXT(_mail->box);
 	struct fts_transaction_context *ft = FTS_CONTEXT(_mail->transaction);
 
@@ -707,20 +710,20 @@
 	       struct mailbox_header_lookup_ctx *wanted_headers)
 {
 	struct fts_mailbox *fbox = FTS_CONTEXT(t->box);
-	struct fts_mail *fmail;
+	union mail_module_context *fmail;
 	struct mail *_mail;
 	struct mail_private *mail;
 
-	_mail = fbox->super.mail_alloc(t, wanted_fields, wanted_headers);
+	_mail = fbox->module_ctx.super.
+		mail_alloc(t, wanted_fields, wanted_headers);
 	if (fbox->backend_exact != NULL || fbox->backend_fast != NULL) {
 		mail = (struct mail_private *)_mail;
 
-		fmail = p_new(mail->pool, struct fts_mail, 1);
+		fmail = p_new(mail->pool, union mail_module_context, 1);
 		fmail->super = mail->v;
 
 		mail->v.expunge = fts_mail_expunge;
-		array_idx_set(&mail->module_contexts,
-			      fts_storage_module_id, &fmail);
+		MODULE_CONTEXT_SET_SELF(mail, fts_mail_module, fmail);
 	}
 	return _mail;
 }
@@ -770,8 +773,8 @@
 		fbox->backend_set = TRUE;
 	}
 
-	t = fbox->super.transaction_begin(box, flags);
-	array_idx_set(&t->module_contexts, fts_storage_module_id, &ft);
+	t = fbox->module_ctx.super.transaction_begin(box, flags);
+	MODULE_CONTEXT_SET(t, fts_storage_module, ft);
 	return t;
 }
 
@@ -796,7 +799,7 @@
 	struct fts_mailbox *fbox = FTS_CONTEXT(box);
 	struct fts_transaction_context *ft = FTS_CONTEXT(t);
 
-	fbox->super.transaction_rollback(t);
+	fbox->module_ctx.super.transaction_rollback(t);
 	fts_transaction_finish(box, ft, FALSE);
 }
 
@@ -808,7 +811,7 @@
 	struct fts_transaction_context *ft = FTS_CONTEXT(t);
 	int ret;
 
-	ret = fbox->super.transaction_commit(t, flags);
+	ret = fbox->module_ctx.super.transaction_commit(t, flags);
 	fts_transaction_finish(box, ft, ret == 0);
 	return ret;
 }
@@ -827,7 +830,7 @@
 
 	fbox = i_new(struct fts_mailbox, 1);
 	fbox->env = env;
-	fbox->super = box->v;
+	fbox->module_ctx.super = box->v;
 	box->v.close = fts_mailbox_close;
 	box->v.search_init = fts_mailbox_search_init;
 	box->v.search_next_nonblock = fts_mailbox_search_next_nonblock;
@@ -838,10 +841,5 @@
 	box->v.transaction_rollback = fts_transaction_rollback;
 	box->v.transaction_commit = fts_transaction_commit;
 
-	if (!fts_storage_module_id_set) {
-		fts_storage_module_id = mail_storage_module_id++;
-		fts_storage_module_id_set = TRUE;
-	}
-
-	array_idx_set(&box->module_contexts, fts_storage_module_id, &fbox);
+	MODULE_CONTEXT_SET(box, fts_storage_module, fbox);
 }
--- a/src/plugins/lazy-expunge/lazy-expunge-plugin.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/lazy-expunge/lazy-expunge-plugin.c	Thu Mar 29 14:51:09 2007 +0300
@@ -17,11 +17,9 @@
 #include <time.h>
 
 #define LAZY_EXPUNGE_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					lazy_expunge_storage_module_id))
+	MODULE_CONTEXT(obj, lazy_expunge_mail_storage_module)
 #define LAZY_EXPUNGE_LIST_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					lazy_expunge_mailbox_list_module_id))
+	MODULE_CONTEXT(obj, lazy_expunge_mailbox_list_module)
 
 enum lazy_namespace {
 	LAZY_NAMESPACE_EXPUNGE,
@@ -32,29 +30,24 @@
 };
 
 struct lazy_expunge_mailbox_list {
-	struct mailbox_list_vfuncs super;
+	union mailbox_list_module_context module_ctx;
 
 	struct mail_storage *storage;
 };
 
 struct lazy_expunge_mail_storage {
-	struct mail_storage_vfuncs super;
+	union mail_storage_module_context module_ctx;
+
 	bool internal_namespace;
 };
 
-struct lazy_expunge_mailbox {
-	struct mailbox_vfuncs super;
-};
+struct lazy_expunge_transaction {
+	union mailbox_transaction_module_context module_ctx;
 
-struct lazy_expunge_transaction {
 	ARRAY_TYPE(seq_range) expunge_seqs;
 	struct mailbox *expunge_box;
 };
 
-struct lazy_expunge_mail {
-	struct mail_vfuncs super;
-};
-
 const char *lazy_expunge_plugin_version = PACKAGE_VERSION;
 
 static void (*lazy_expunge_next_hook_client_created)(struct client **client);
@@ -63,11 +56,12 @@
 static void (*lazy_expunge_next_hook_mailbox_list_created)
 	(struct mailbox_list *list);
 
-static unsigned int lazy_expunge_storage_module_id = 0;
-static bool lazy_expunge_storage_module_id_set = FALSE;
-
-static unsigned int lazy_expunge_mailbox_list_module_id = 0;
-static bool lazy_expunge_mailbox_list_module_id_set = FALSE;
+static MODULE_CONTEXT_DEFINE_INIT(lazy_expunge_mail_storage_module,
+				  &mail_storage_module_register);
+static MODULE_CONTEXT_DEFINE_INIT(lazy_expunge_mail_module,
+				  &mail_module_register);
+static MODULE_CONTEXT_DEFINE_INIT(lazy_expunge_mailbox_list_module,
+				  &mailbox_list_module_register);
 
 static struct namespace *lazy_namespaces[LAZY_NAMESPACE_COUNT];
 
@@ -122,14 +116,14 @@
 lazy_expunge_transaction_begin(struct mailbox *box,
 			       enum mailbox_transaction_flags flags)
 {
-	struct lazy_expunge_mailbox *qbox = LAZY_EXPUNGE_CONTEXT(box);
+	union mailbox_module_context *mbox = LAZY_EXPUNGE_CONTEXT(box);
 	struct mailbox_transaction_context *t;
 	struct lazy_expunge_transaction *lt;
 
-	t = qbox->super.transaction_begin(box, flags);
+	t = mbox->super.transaction_begin(box, flags);
 	lt = i_new(struct lazy_expunge_transaction, 1);
 
-	array_idx_set(&t->module_contexts, lazy_expunge_storage_module_id, &lt);
+	MODULE_CONTEXT_SET(t, lazy_expunge_mail_storage_module, lt);
 	return t;
 }
 
@@ -218,12 +212,12 @@
 lazy_expunge_transaction_commit(struct mailbox_transaction_context *ctx,
 				enum mailbox_sync_flags flags)
 {
-	struct lazy_expunge_mailbox *qbox = LAZY_EXPUNGE_CONTEXT(ctx->box);
+	union mailbox_module_context *mbox = LAZY_EXPUNGE_CONTEXT(ctx->box);
 	struct lazy_expunge_transaction *lt = LAZY_EXPUNGE_CONTEXT(ctx);
 	struct mailbox *srcbox = ctx->box;
 	int ret;
 
-	ret = qbox->super.transaction_commit(ctx, flags);
+	ret = mbox->super.transaction_commit(ctx, flags);
 
 	if (ret == 0 && array_is_created(&lt->expunge_seqs))
 		ret = lazy_expunge_move_expunges(srcbox, lt);
@@ -235,10 +229,10 @@
 static void
 lazy_expunge_transaction_rollback(struct mailbox_transaction_context *ctx)
 {
-	struct lazy_expunge_mailbox *qbox = LAZY_EXPUNGE_CONTEXT(ctx->box);
+	union mailbox_module_context *mbox = LAZY_EXPUNGE_CONTEXT(ctx->box);
 	struct lazy_expunge_transaction *lt = LAZY_EXPUNGE_CONTEXT(ctx);
 
-	qbox->super.transaction_rollback(ctx);
+	mbox->super.transaction_rollback(ctx);
 	lazy_expunge_transaction_free(lt);
 }
 
@@ -247,20 +241,19 @@
 			enum mail_fetch_field wanted_fields,
 			struct mailbox_header_lookup_ctx *wanted_headers)
 {
-	struct lazy_expunge_mailbox *qbox = LAZY_EXPUNGE_CONTEXT(t->box);
-	struct lazy_expunge_mail *lmail;
+	union mailbox_module_context *mbox = LAZY_EXPUNGE_CONTEXT(t->box);
+	union mail_module_context *mmail;
 	struct mail *_mail;
 	struct mail_private *mail;
 
-	_mail = qbox->super.mail_alloc(t, wanted_fields, wanted_headers);
+	_mail = mbox->super.mail_alloc(t, wanted_fields, wanted_headers);
 	mail = (struct mail_private *)_mail;
 
-	lmail = p_new(mail->pool, struct lazy_expunge_mail, 1);
-	lmail->super = mail->v;
+	mmail = p_new(mail->pool, union mail_module_context, 1);
+	mmail->super = mail->v;
 
 	mail->v.expunge = lazy_expunge_mail_expunge;
-	array_idx_set(&mail->module_contexts,
-		      lazy_expunge_storage_module_id, &lmail);
+	MODULE_CONTEXT_SET_SELF(mail, lazy_expunge_mail_module, mmail);
 	return _mail;
 }
 
@@ -271,21 +264,21 @@
 	struct lazy_expunge_mail_storage *lstorage =
 		LAZY_EXPUNGE_CONTEXT(storage);
 	struct mailbox *box;
-	struct lazy_expunge_mailbox *qbox;
+	union mailbox_module_context *mbox;
 
-	box = lstorage->super.mailbox_open(storage, name, input, flags);
+	box = lstorage->module_ctx.super.
+		mailbox_open(storage, name, input, flags);
 	if (box == NULL || lstorage->internal_namespace)
 		return box;
 
-	qbox = p_new(box->pool, struct lazy_expunge_mailbox, 1);
-	qbox->super = box->v;
+	mbox = p_new(box->pool, union mailbox_module_context, 1);
+	mbox->super = box->v;
 
 	box->v.transaction_begin = lazy_expunge_transaction_begin;
 	box->v.transaction_commit = lazy_expunge_transaction_commit;
 	box->v.transaction_rollback = lazy_expunge_transaction_rollback;
 	box->v.mail_alloc = lazy_expunge_mail_alloc;
-	array_idx_set(&box->module_contexts,
-		      lazy_expunge_storage_module_id, &qbox);
+	MODULE_CONTEXT_SET_SELF(box, lazy_expunge_mail_storage_module, mbox);
 	return box;
 }
 
@@ -423,12 +416,12 @@
 
 	if (llist->storage == NULL) {
 		/* not a maildir storage */
-		return llist->super.delete_mailbox(list, name);
+		return llist->module_ctx.super.delete_mailbox(list, name);
 	}
 
 	lstorage = LAZY_EXPUNGE_CONTEXT(llist->storage);
 	if (lstorage->internal_namespace)
-		return llist->super.delete_mailbox(list, name);
+		return llist->module_ctx.super.delete_mailbox(list, name);
 
 	/* first do the normal sanity checks */
 	if (strcmp(name, "INBOX") == 0) {
@@ -483,16 +476,10 @@
 	llist->storage = storage;
 
 	lstorage = p_new(storage->pool, struct lazy_expunge_mail_storage, 1);
-	lstorage->super = storage->v;
+	lstorage->module_ctx.super = storage->v;
 	storage->v.mailbox_open = lazy_expunge_mailbox_open;
 
-	if (!lazy_expunge_storage_module_id_set) {
-		lazy_expunge_storage_module_id = mail_storage_module_id++;
-		lazy_expunge_storage_module_id_set = TRUE;
-	}
-
-	array_idx_set(&storage->module_contexts,
-		      lazy_expunge_storage_module_id, &lstorage);
+	MODULE_CONTEXT_SET(storage, lazy_expunge_mail_storage_module, lstorage);
 }
 
 static void lazy_expunge_mailbox_list_created(struct mailbox_list *list)
@@ -503,16 +490,10 @@
 		lazy_expunge_next_hook_mailbox_list_created(list);
 
 	llist = p_new(list->pool, struct lazy_expunge_mailbox_list, 1);
-	llist->super = list->v;
+	llist->module_ctx.super = list->v;
 	list->v.delete_mailbox = lazy_expunge_mailbox_list_delete;
 
-	if (!lazy_expunge_mailbox_list_module_id_set) {
-		lazy_expunge_mailbox_list_module_id = mailbox_list_module_id++;
-		lazy_expunge_mailbox_list_module_id_set = TRUE;
-	}
-
-	array_idx_set(&list->module_contexts,
-		      lazy_expunge_mailbox_list_module_id, &llist);
+	MODULE_CONTEXT_SET(list, lazy_expunge_mailbox_list_module, llist);
 }
 
 static void lazy_expunge_hook_client_created(struct client **client)
--- a/src/plugins/mail-log/mail-log-plugin.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/mail-log/mail-log-plugin.c	Thu Mar 29 14:51:09 2007 +0300
@@ -11,27 +11,11 @@
 #define MSGID_LOG_LEN 80
 
 #define MAIL_LOG_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					mail_log_storage_module_id))
+	MODULE_CONTEXT(obj, mail_log_storage_module)
+#define MAIL_LOG_MAIL_CONTEXT(obj) \
+	MODULE_CONTEXT(obj, mail_log_mail_module)
 #define MAIL_LOG_LIST_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					mail_log_mailbox_list_module_id))
-
-struct mail_log_mailbox_list {
-	struct mailbox_list_vfuncs super;
-};
-
-struct mail_log_mail_storage {
-	struct mail_storage_vfuncs super;
-};
-
-struct mail_log_mailbox {
-	struct mailbox_vfuncs super;
-};
-
-struct mail_log_mail {
-	struct mail_vfuncs super;
-};
+	MODULE_CONTEXT(obj, mail_log_mailbox_list_module)
 
 const char *mail_log_plugin_version = PACKAGE_VERSION;
 
@@ -40,11 +24,11 @@
 static void (*mail_log_next_hook_mailbox_list_created)
 	(struct mailbox_list *list);
 
-static unsigned int mail_log_storage_module_id = 0;
-static bool mail_log_storage_module_id_set = FALSE;
-
-static unsigned int mail_log_mailbox_list_module_id = 0;
-static bool mail_log_mailbox_list_module_id_set = FALSE;
+static MODULE_CONTEXT_DEFINE_INIT(mail_log_storage_module,
+				  &mail_storage_module_register);
+static MODULE_CONTEXT_DEFINE_INIT(mail_log_mail_module, &mail_module_register);
+static MODULE_CONTEXT_DEFINE_INIT(mail_log_mailbox_list_module,
+				  &mailbox_list_module_register);
 
 static void mail_log_action(struct mail *mail, const char *action)
 {
@@ -69,7 +53,7 @@
 static int mail_log_mail_expunge(struct mail *_mail)
 {
 	struct mail_private *mail = (struct mail_private *)_mail;
-	struct mail_log_mail *lmail = MAIL_LOG_CONTEXT(mail);
+	union mail_module_context *lmail = MAIL_LOG_MAIL_CONTEXT(mail);
 
 	if (lmail->super.expunge(_mail) < 0)
 		return -1;
@@ -83,7 +67,7 @@
 			   enum mail_flags flags)
 {
 	struct mail_private *mail = (struct mail_private *)_mail;
-	struct mail_log_mail *lmail = MAIL_LOG_CONTEXT(mail);
+	union mail_module_context *lmail = MAIL_LOG_MAIL_CONTEXT(mail);
 	enum mail_flags old_flags, new_flags;
 
 	old_flags = mail_get_flags(_mail);
@@ -115,21 +99,20 @@
 		    enum mail_fetch_field wanted_fields,
 		    struct mailbox_header_lookup_ctx *wanted_headers)
 {
-	struct mail_log_mailbox *lbox = MAIL_LOG_CONTEXT(t->box);
-	struct mail_log_mail *lmail;
+	union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(t->box);
+	union mail_module_context *lmail;
 	struct mail *_mail;
 	struct mail_private *mail;
 
 	_mail = lbox->super.mail_alloc(t, wanted_fields, wanted_headers);
 	mail = (struct mail_private *)_mail;
 
-	lmail = p_new(mail->pool, struct mail_log_mail, 1);
+	lmail = p_new(mail->pool, union mail_module_context, 1);
 	lmail->super = mail->v;
 
 	mail->v.update_flags = mail_log_mail_update_flags;
 	mail->v.expunge = mail_log_mail_expunge;
-	array_idx_set(&mail->module_contexts,
-		      mail_log_storage_module_id, &lmail);
+	MODULE_CONTEXT_SET_SELF(mail, mail_log_mail_module, lmail);
 	return _mail;
 }
 
@@ -138,7 +121,7 @@
 	      enum mail_flags flags, struct mail_keywords *keywords,
 	      struct mail *dest_mail)
 {
-	struct mail_log_mailbox *lbox = MAIL_LOG_CONTEXT(t->box);
+	union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(t->box);
 	const char *name;
 
 	if (lbox->super.copy(t, mail, flags, keywords, dest_mail) < 0)
@@ -155,27 +138,27 @@
 mail_log_mailbox_open(struct mail_storage *storage, const char *name,
 		      struct istream *input, enum mailbox_open_flags flags)
 {
-	struct mail_log_mail_storage *lstorage = MAIL_LOG_CONTEXT(storage);
+	union mail_storage_module_context *lstorage = MAIL_LOG_CONTEXT(storage);
 	struct mailbox *box;
-	struct mail_log_mailbox *lbox;
+	union mailbox_module_context *lbox;
 
 	box = lstorage->super.mailbox_open(storage, name, input, flags);
 	if (box == NULL)
 		return NULL;
 
-	lbox = p_new(box->pool, struct mail_log_mailbox, 1);
+	lbox = p_new(box->pool, union mailbox_module_context, 1);
 	lbox->super = box->v;
 
 	box->v.mail_alloc = mail_log_mail_alloc;
 	box->v.copy = mail_log_copy;
-	array_idx_set(&box->module_contexts, mail_log_storage_module_id, &lbox);
+	MODULE_CONTEXT_SET_SELF(box, mail_log_storage_module, lbox);
 	return box;
 }
 
 static int
 mail_log_mailbox_list_delete(struct mailbox_list *list, const char *name)
 {
-	struct mail_log_mailbox_list *llist = MAIL_LOG_LIST_CONTEXT(list);
+	union mailbox_list_module_context *llist = MAIL_LOG_LIST_CONTEXT(list);
 
 	if (llist->super.delete_mailbox(list, name) < 0)
 		return -1;
@@ -186,42 +169,30 @@
 
 static void mail_log_mail_storage_created(struct mail_storage *storage)
 {
-	struct mail_log_mail_storage *lstorage;
+	union mail_storage_module_context *lstorage;
 
 	if (mail_log_next_hook_mail_storage_created != NULL)
 		mail_log_next_hook_mail_storage_created(storage);
 
-	lstorage = p_new(storage->pool, struct mail_log_mail_storage, 1);
+	lstorage = p_new(storage->pool, union mail_storage_module_context, 1);
 	lstorage->super = storage->v;
 	storage->v.mailbox_open = mail_log_mailbox_open;
 
-	if (!mail_log_storage_module_id_set) {
-		mail_log_storage_module_id = mail_storage_module_id++;
-		mail_log_storage_module_id_set = TRUE;
-	}
-
-	array_idx_set(&storage->module_contexts,
-		      mail_log_storage_module_id, &lstorage);
+	MODULE_CONTEXT_SET_SELF(storage, mail_log_storage_module, lstorage);
 }
 
 static void mail_log_mailbox_list_created(struct mailbox_list *list)
 {
-	struct mail_log_mailbox_list *llist;
+	union mailbox_list_module_context *llist;
 
 	if (mail_log_next_hook_mailbox_list_created != NULL)
 		mail_log_next_hook_mailbox_list_created(list);
 
-	llist = p_new(list->pool, struct mail_log_mailbox_list, 1);
+	llist = p_new(list->pool, union mailbox_list_module_context, 1);
 	llist->super = list->v;
 	list->v.delete_mailbox = mail_log_mailbox_list_delete;
 
-	if (!mail_log_mailbox_list_module_id_set) {
-		mail_log_mailbox_list_module_id = mailbox_list_module_id++;
-		mail_log_mailbox_list_module_id_set = TRUE;
-	}
-
-	array_idx_set(&list->module_contexts,
-		      mail_log_mailbox_list_module_id, &llist);
+	MODULE_CONTEXT_SET_SELF(list, mail_log_mailbox_list_module, llist);
 }
 
 void mail_log_plugin_init(void)
--- a/src/plugins/quota/quota-private.h	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/quota/quota-private.h	Thu Mar 29 14:51:09 2007 +0300
@@ -68,6 +68,8 @@
 };
 
 struct quota_transaction_context {
+	union mailbox_transaction_module_context module_ctx;
+
 	struct quota *quota;
 	struct mailbox *box;
 
--- a/src/plugins/quota/quota-storage.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/quota/quota-storage.c	Thu Mar 29 14:51:09 2007 +0300
@@ -12,42 +12,34 @@
 #include <sys/stat.h>
 
 #define QUOTA_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					quota_storage_module_id))
+	MODULE_CONTEXT(obj, quota_storage_module)
+#define QUOTA_MAIL_CONTEXT(obj) \
+	MODULE_CONTEXT(obj, quota_mail_module)
 #define QUOTA_LIST_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					quota_mailbox_list_module_id))
+	MODULE_CONTEXT(obj, quota_mailbox_list_module)
 
 struct quota_mailbox_list {
-	struct mailbox_list_vfuncs super;
+	union mailbox_list_module_context module_ctx;
 
 	struct mail_storage *storage;
 };
 
-struct quota_mail_storage {
-	struct mail_storage_vfuncs super;
-};
-
 struct quota_mailbox {
-	struct mailbox_vfuncs super;
+	union mailbox_module_context module_ctx;
 
 	unsigned int save_hack:1;
 };
 
-struct quota_mail {
-	struct mail_vfuncs super;
-};
-
-static unsigned int quota_storage_module_id = 0;
-static bool quota_storage_module_id_set = FALSE;
-
-static unsigned int quota_mailbox_list_module_id = 0;
-static bool quota_mailbox_list_module_id_set = FALSE;
+static MODULE_CONTEXT_DEFINE_INIT(quota_storage_module,
+				  &mail_storage_module_register);
+static MODULE_CONTEXT_DEFINE_INIT(quota_mail_module, &mail_module_register);
+static MODULE_CONTEXT_DEFINE_INIT(quota_mailbox_list_module,
+				  &mailbox_list_module_register);
 
 static int quota_mail_expunge(struct mail *_mail)
 {
 	struct mail_private *mail = (struct mail_private *)_mail;
-	struct quota_mail *qmail = QUOTA_CONTEXT(mail);
+	union mail_module_context *qmail = QUOTA_MAIL_CONTEXT(mail);
 	struct quota_transaction_context *qt =
 		QUOTA_CONTEXT(_mail->transaction);
 
@@ -66,10 +58,10 @@
 	struct mailbox_transaction_context *t;
 	struct quota_transaction_context *qt;
 
-	t = qbox->super.transaction_begin(box, flags);
+	t = qbox->module_ctx.super.transaction_begin(box, flags);
 	qt = quota_transaction_begin(quota_set, box);
 
-	array_idx_set(&t->module_contexts, quota_storage_module_id, &qt);
+	MODULE_CONTEXT_SET(t, quota_storage_module, qt);
 	return t;
 }
 
@@ -80,7 +72,7 @@
 	struct quota_mailbox *qbox = QUOTA_CONTEXT(ctx->box);
 	struct quota_transaction_context *qt = QUOTA_CONTEXT(ctx);
 
-	if (qbox->super.transaction_commit(ctx, flags) < 0) {
+	if (qbox->module_ctx.super.transaction_commit(ctx, flags) < 0) {
 		quota_transaction_rollback(qt);
 		return -1;
 	} else {
@@ -97,7 +89,7 @@
 	struct quota_mailbox *qbox = QUOTA_CONTEXT(ctx->box);
 	struct quota_transaction_context *qt = QUOTA_CONTEXT(ctx);
 
-	qbox->super.transaction_rollback(ctx);
+	qbox->module_ctx.super.transaction_rollback(ctx);
 
 	if (qt->tmp_mail != NULL)
 		mail_free(&qt->tmp_mail);
@@ -110,18 +102,19 @@
 		 struct mailbox_header_lookup_ctx *wanted_headers)
 {
 	struct quota_mailbox *qbox = QUOTA_CONTEXT(t->box);
-	struct quota_mail *qmail;
+	union mail_module_context *qmail;
 	struct mail *_mail;
 	struct mail_private *mail;
 
-	_mail = qbox->super.mail_alloc(t, wanted_fields, wanted_headers);
+	_mail = qbox->module_ctx.super.
+		mail_alloc(t, wanted_fields, wanted_headers);
 	mail = (struct mail_private *)_mail;
 
-	qmail = p_new(mail->pool, struct quota_mail, 1);
+	qmail = p_new(mail->pool, union mail_module_context, 1);
 	qmail->super = mail->v;
 
 	mail->v.expunge = quota_mail_expunge;
-	array_idx_set(&mail->module_contexts, quota_storage_module_id, &qmail);
+	MODULE_CONTEXT_SET_SELF(mail, quota_mail_module, qmail);
 	return _mail;
 }
 
@@ -162,7 +155,8 @@
 	}
 
 	qbox->save_hack = FALSE;
-	if (qbox->super.copy(t, mail, flags, keywords, dest_mail) < 0)
+	if (qbox->module_ctx.super.copy(t, mail, flags, keywords,
+					dest_mail) < 0)
 		return -1;
 
 	/* if copying used saving internally, we already checked the quota
@@ -216,9 +210,10 @@
 		dest_mail = qt->tmp_mail;
 	}
 
-	return qbox->super.save_init(t, flags, keywords, received_date,
-				     timezone_offset, from_envelope,
-				     input, dest_mail, ctx_r);
+	return qbox->module_ctx.super.
+		save_init(t, flags, keywords, received_date,
+			  timezone_offset, from_envelope,
+			  input, dest_mail, ctx_r);
 }
 
 static int quota_save_finish(struct mail_save_context *ctx)
@@ -226,7 +221,7 @@
 	struct quota_transaction_context *qt = QUOTA_CONTEXT(ctx->transaction);
 	struct quota_mailbox *qbox = QUOTA_CONTEXT(ctx->transaction->box);
 
-	if (qbox->super.save_finish(ctx) < 0)
+	if (qbox->module_ctx.super.save_finish(ctx) < 0)
 		return -1;
 
 	qbox->save_hack = TRUE;
@@ -238,7 +233,7 @@
 quota_mailbox_open(struct mail_storage *storage, const char *name,
 		   struct istream *input, enum mailbox_open_flags flags)
 {
-	struct quota_mail_storage *qstorage = QUOTA_CONTEXT(storage);
+	union mail_storage_module_context *qstorage = QUOTA_CONTEXT(storage);
 	struct mailbox *box;
 	struct quota_mailbox *qbox;
 
@@ -247,7 +242,7 @@
 		return NULL;
 
 	qbox = p_new(box->pool, struct quota_mailbox, 1);
-	qbox->super = box->v;
+	qbox->module_ctx.super = box->v;
 
 	box->v.transaction_begin = quota_mailbox_transaction_begin;
 	box->v.transaction_commit = quota_mailbox_transaction_commit;
@@ -256,7 +251,7 @@
 	box->v.save_init = quota_save_init;
 	box->v.save_finish = quota_save_finish;
 	box->v.copy = quota_copy;
-	array_idx_set(&box->module_contexts, quota_storage_module_id, &qbox);
+	MODULE_CONTEXT_SET(box, quota_storage_module, qbox);
 	return box;
 }
 
@@ -301,12 +296,12 @@
 	mailbox_close(&box);
 	/* FIXME: here's an unfortunate race condition */
 	return ret < 0 ? -1 :
-		qlist->super.delete_mailbox(list, name);
+		qlist->module_ctx.super.delete_mailbox(list, name);
 }
 
 static void quota_storage_destroy(struct mail_storage *storage)
 {
-	struct quota_mail_storage *qstorage = QUOTA_CONTEXT(storage);
+	union mail_storage_module_context *qstorage = QUOTA_CONTEXT(storage);
 
 	quota_remove_user_storage(quota_set, storage);
 
@@ -316,25 +311,19 @@
 void quota_mail_storage_created(struct mail_storage *storage)
 {
 	struct quota_mailbox_list *qlist = QUOTA_LIST_CONTEXT(storage->list);
-	struct quota_mail_storage *qstorage;
+	union mail_storage_module_context *qstorage;
 
 	if (quota_next_hook_mail_storage_created != NULL)
 		quota_next_hook_mail_storage_created(storage);
 
 	qlist->storage = storage;
 
-	qstorage = p_new(storage->pool, struct quota_mail_storage, 1);
+	qstorage = p_new(storage->pool, union mail_storage_module_context, 1);
 	qstorage->super = storage->v;
 	storage->v.destroy = quota_storage_destroy;
 	storage->v.mailbox_open = quota_mailbox_open;
 
-	if (!quota_storage_module_id_set) {
-		quota_storage_module_id = mail_storage_module_id++;
-		quota_storage_module_id_set = TRUE;
-	}
-
-	array_idx_set(&storage->module_contexts,
-		      quota_storage_module_id, &qstorage);
+	MODULE_CONTEXT_SET_SELF(storage, quota_storage_module, qstorage);
 
 	if ((storage->flags & MAIL_STORAGE_FLAG_SHARED_NAMESPACE) == 0) {
 		/* register to user's quota roots */
@@ -350,14 +339,8 @@
 		quota_next_hook_mailbox_list_created(list);
 
 	qlist = p_new(list->pool, struct quota_mailbox_list, 1);
-	qlist->super = list->v;
+	qlist->module_ctx.super = list->v;
 	list->v.delete_mailbox = quota_mailbox_list_delete;
 
-	if (!quota_mailbox_list_module_id_set) {
-		quota_mailbox_list_module_id = mailbox_list_module_id++;
-		quota_mailbox_list_module_id_set = TRUE;
-	}
-
-	array_idx_set(&list->module_contexts,
-		      quota_mailbox_list_module_id, &qlist);
+	MODULE_CONTEXT_SET(list, quota_mailbox_list_module, qlist);
 }
--- a/src/plugins/trash/Makefile.am	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/trash/Makefile.am	Thu Mar 29 14:51:09 2007 +0300
@@ -1,6 +1,7 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/lib \
 	-I$(top_srcdir)/src/lib-mail \
+	-I$(top_srcdir)/src/lib-index \
 	-I$(top_srcdir)/src/lib-storage \
 	-I$(top_srcdir)/src/plugins/quota
 
--- a/src/plugins/zlib/zlib-plugin.c	Thu Mar 29 14:48:18 2007 +0300
+++ b/src/plugins/zlib/zlib-plugin.c	Thu Mar 29 14:51:09 2007 +0300
@@ -10,27 +10,22 @@
 
 #include <fcntl.h>
 
-struct zlib_mail_storage {
-	struct mail_storage_vfuncs super;
-};
-
 #define ZLIB_CONTEXT(obj) \
-	*((void **)array_idx_modifiable(&(obj)->module_contexts, \
-					zlib_storage_module_id))
+	MODULE_CONTEXT(obj, zlib_storage_module)
 
 const char *zlib_plugin_version = PACKAGE_VERSION;
 
 static void (*zlib_next_hook_mail_storage_created)
 	(struct mail_storage *storage);
 
-static unsigned int zlib_storage_module_id = 0;
-static bool zlib_storage_module_id_set = FALSE;
+static MODULE_CONTEXT_DEFINE_INIT(zlib_storage_module,
+				  &mail_storage_module_register);
 
 static struct mailbox *
 zlib_mailbox_open(struct mail_storage *storage, const char *name,
 		  struct istream *input, enum mailbox_open_flags flags)
 {
-	struct zlib_mail_storage *qstorage = ZLIB_CONTEXT(storage);
+	union mail_storage_module_context *qstorage = ZLIB_CONTEXT(storage);
 	struct mailbox *box;
 	struct istream *zlib_input = NULL;
 	size_t len = strlen(name);
@@ -63,22 +58,16 @@
 
 static void zlib_mail_storage_created(struct mail_storage *storage)
 {
-	struct zlib_mail_storage *qstorage;
+	union mail_storage_module_context *qstorage;
 
 	if (zlib_next_hook_mail_storage_created != NULL)
 		zlib_next_hook_mail_storage_created(storage);
 
-	qstorage = p_new(storage->pool, struct zlib_mail_storage, 1);
+	qstorage = p_new(storage->pool, union mail_storage_module_context, 1);
 	qstorage->super = storage->v;
 	storage->v.mailbox_open = zlib_mailbox_open;
 
-	if (!zlib_storage_module_id_set) {
-		zlib_storage_module_id = mail_storage_module_id++;
-		zlib_storage_module_id_set = TRUE;
-	}
-
-	array_idx_set(&storage->module_contexts,
-		      zlib_storage_module_id, &qstorage);
+	MODULE_CONTEXT_SET_SELF(storage, zlib_storage_module, qstorage);
 }
 
 void zlib_plugin_init(void)