dovecot-2.0: lib-storage: Fixes to recent plugin API change.
dovecot at dovecot.org
dovecot at dovecot.org
Wed Jun 9 20:02:58 EEST 2010
details: http://hg.dovecot.org/dovecot-2.0/rev/6d32cf98b5f3
changeset: 11508:6d32cf98b5f3
user: Timo Sirainen <tss at iki.fi>
date: Wed Jun 09 18:02:46 2010 +0100
description:
lib-storage: Fixes to recent plugin API change.
diffstat:
src/lib-storage/mail-storage-hooks.c | 87 +++++++++++++++++++++++++++-
1 files changed, 82 insertions(+), 5 deletions(-)
diffs (147 lines):
diff -r e85e6b1df82f -r 6d32cf98b5f3 src/lib-storage/mail-storage-hooks.c
--- a/src/lib-storage/mail-storage-hooks.c Wed Jun 09 17:03:20 2010 +0100
+++ b/src/lib-storage/mail-storage-hooks.c Wed Jun 09 18:02:46 2010 +0100
@@ -119,16 +119,70 @@
array_append_array(&user->hooks, &internal_hooks);
}
+static void hook_vfuncs_update(void *_v, const void *_vlast,
+ const void *_prev_vlast,
+ void *_mask, size_t size)
+{
+ /* This function assumes that a struct containing function pointers
+ equals to an array of function pointers. Not ANSI-C, but should work
+ in all OSes supported by Dovecot. Much easier anyway than doing this
+ work manually..
+
+ The problem this function solves is:
+
+ 1. First hook overrides methods A and B by updating vlast->A+B.
+ vlast points to v, so v->A+B gets updated.
+ 2. Second hook overrides method B and C by updating vlast->B+C.
+ vlast points first hook's super struct. now, the call paths go:
+ B: v->B = hook1_B, which calls its super.B = hook2_B,
+ which calls super.B = original -> all OK
+ C: v->C = still the original, so hook2_C won't be called!
+
+ The idea is to detect the C situation, and update v->C = hook2_C
+ so that the call path goes:
+ C: v->C = hook2_C, which calls super.C = original
+ */
+ void (**v)() = _v;
+ void (*const *prev_vlast)() = _prev_vlast;
+ void (*const *vlast)() = _vlast;
+ void (**mask)() = _mask;
+ unsigned int i, count;
+
+ i_assert((size % sizeof(void (*)())) == 0);
+ count = size / sizeof(void (*)());
+
+ for (i = 0; i < count; i++) {
+ if (mask[i] != NULL)
+ continue;
+
+ if (v[i] != vlast[i]) {
+ /* first hook overriding any method in this object */
+ mask[i] = v[i];
+ } else if (prev_vlast != NULL && v[i] != prev_vlast[i]) {
+ /* first hook overriding this method object
+ (but earlier hooks already overrode other methods) */
+ v[i] = prev_vlast[i];
+ mask[i] = prev_vlast[i];
+ }
+ }
+}
+
void hook_mail_user_created(struct mail_user *user)
{
const struct mail_storage_hooks *const *hooks;
+ struct mail_user_vfuncs mask, *prev_vlast = NULL;
mail_user_add_plugin_hooks(user);
+ memset(&mask, 0, sizeof(mask));
user->vlast = &user->v;
array_foreach(&user->hooks, hooks) {
- if ((*hooks)->mail_user_created != NULL)
+ if ((*hooks)->mail_user_created != NULL) {
(*hooks)->mail_user_created(user);
+ hook_vfuncs_update(&user->v, user->vlast, prev_vlast,
+ &mask, sizeof(mask));
+ prev_vlast = user->vlast;
+ }
}
}
@@ -155,33 +209,51 @@
void hook_mail_storage_created(struct mail_storage *storage)
{
const struct mail_storage_hooks *const *hooks;
+ struct mail_storage_vfuncs mask, *prev_vlast = NULL;
+ memset(&mask, 0, sizeof(mask));
storage->vlast = &storage->v;
array_foreach(&storage->user->hooks, hooks) {
- if ((*hooks)->mail_storage_created != NULL)
+ if ((*hooks)->mail_storage_created != NULL) {
(*hooks)->mail_storage_created(storage);
+ hook_vfuncs_update(&storage->v, storage->vlast,
+ prev_vlast, &mask, sizeof(mask));
+ prev_vlast = storage->vlast;
+ }
}
}
void hook_mailbox_list_created(struct mailbox_list *list)
{
const struct mail_storage_hooks *const *hooks;
+ struct mailbox_list_vfuncs mask, *prev_vlast = NULL;
+ memset(&mask, 0, sizeof(mask));
list->vlast = &list->v;
array_foreach(&list->ns->user->hooks, hooks) {
- if ((*hooks)->mailbox_list_created != NULL)
+ if ((*hooks)->mailbox_list_created != NULL) {
(*hooks)->mailbox_list_created(list);
+ hook_vfuncs_update(&list->v, list->vlast, prev_vlast,
+ &mask, sizeof(mask));
+ prev_vlast = list->vlast;
+ }
}
}
void hook_mailbox_allocated(struct mailbox *box)
{
const struct mail_storage_hooks *const *hooks;
+ struct mailbox_vfuncs mask, *prev_vlast = NULL;
+ memset(&mask, 0, sizeof(mask));
box->vlast = &box->v;
array_foreach(&box->storage->user->hooks, hooks) {
- if ((*hooks)->mailbox_allocated != NULL)
+ if ((*hooks)->mailbox_allocated != NULL) {
(*hooks)->mailbox_allocated(box);
+ hook_vfuncs_update(&box->v, box->vlast, prev_vlast,
+ &mask, sizeof(mask));
+ prev_vlast = box->vlast;
+ }
}
}
@@ -199,10 +271,15 @@
{
const struct mail_storage_hooks *const *hooks;
struct mail_private *pmail = (struct mail_private *)mail;
+ struct mail_vfuncs mask, *prev_vlast = NULL;
pmail->vlast = &pmail->v;
array_foreach(&mail->box->storage->user->hooks, hooks) {
- if ((*hooks)->mail_allocated != NULL)
+ if ((*hooks)->mail_allocated != NULL) {
(*hooks)->mail_allocated(mail);
+ hook_vfuncs_update(&pmail->v, pmail->vlast, prev_vlast,
+ &mask, sizeof(mask));
+ prev_vlast = pmail->vlast;
+ }
}
}
More information about the dovecot-cvs
mailing list