changeset 21656:538853d82926

lib,lib-storage: Move hook building code to lib This allows it to be reused elsewhere
author Aki Tuomi <aki.tuomi@dovecot.fi>
date Mon, 20 Feb 2017 15:28:36 +0200
parents cb11cca4eaee
children 69f21a7bd37e
files src/lib-storage/mail-storage-hooks.c src/lib/Makefile.am src/lib/hook-build.c src/lib/hook-build.h
diffstat 4 files changed, 148 insertions(+), 114 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/mail-storage-hooks.c	Mon Feb 20 14:34:25 2017 +0200
+++ b/src/lib-storage/mail-storage-hooks.c	Mon Feb 20 15:28:36 2017 +0200
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "array.h"
+#include "hook-build.h"
 #include "llist.h"
 #include "module-dir.h"
 #include "mail-user.h"
@@ -15,28 +16,6 @@
 	bool forced;
 };
 
-struct hook_stack {
-	struct hook_stack *prev, *next;
-
-	/* Pointer to vfuncs struct. This 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.. */
-	void (**vfuncs)();
-	/* nonzero in the areas where vfuncs has been changed */
-	void (**mask)();
-};
-
-struct hook_build_context {
-	pool_t pool;
-	/* size of the vfuncs struct */
-	size_t size;
-	/* number of function pointers in the struct */
-	unsigned int count;
-
-	struct hook_stack *head, *tail;
-};
-
 static ARRAY(struct mail_storage_module_hooks) module_hooks = ARRAY_INIT;
 static ARRAY(const struct mail_storage_hooks *) internal_hooks = ARRAY_INIT;
 
@@ -176,93 +155,6 @@
 	array_append_array(&user->hooks, &internal_hooks);
 }
 
-static void hook_build_append(struct hook_build_context *ctx, void (**vfuncs)())
-{
-	struct hook_stack *stack;
-
-	stack = p_new(ctx->pool, struct hook_stack, 1);
-	stack->vfuncs = vfuncs;
-	stack->mask = p_malloc(ctx->pool, ctx->size);
-	DLLIST2_APPEND(&ctx->head, &ctx->tail, stack);
-}
-
-static struct hook_build_context *
-hook_build_init(void (**vfuncs)(), size_t size)
-{
-	struct hook_build_context *ctx;
-	pool_t pool;
-
-	i_assert((size % sizeof(void (*)())) == 0);
-
-	pool = pool_alloconly_create("hook build context", 2048);
-	ctx = p_new(pool, struct hook_build_context, 1);
-	ctx->pool = pool;
-	ctx->size = size;
-	ctx->count = size / sizeof(void (*)());
-	hook_build_append(ctx, vfuncs);
-	return ctx;
-}
-
-static void
-hook_update_mask(struct hook_build_context *ctx, struct hook_stack *stack,
-		 void (**vlast)())
-{
-	unsigned int i;
-
-	for (i = 0; i < ctx->count; i++) {
-		if (stack->vfuncs[i] != vlast[i]) {
-			i_assert(stack->vfuncs[i] != NULL);
-			stack->mask[i] = stack->vfuncs[i];
-		}
-	}
-}
-
-static void
-hook_copy_stack(struct hook_build_context *ctx, struct hook_stack *stack)
-{
-	unsigned int i;
-
-	i_assert(stack->next != NULL);
-
-	for (i = 0; i < ctx->count; i++) {
-		if (stack->mask[i] == NULL) {
-			stack->vfuncs[i] = stack->next->vfuncs[i];
-			stack->mask[i] = stack->next->mask[i];
-		}
-	}
-}
-
-static void hook_build_update(struct hook_build_context *ctx, void *_vlast)
-{
-	void (**vlast)() = _vlast;
-	struct hook_stack *stack;
-
-	if (ctx->tail->vfuncs == vlast) {
-		/* no vfuncs overridden */
-		return;
-	}
-
-	/* ctx->vfuncs_stack->vfuncs points to the root vfuncs,
-	   ctx->vfuncs_stack->next->vfuncs points to the first super function
-	   that is being called, and so on.
-
-	   the previous plugin added its vfuncs to the stack tail.
-	   vlast contains the previous plugin's super vfuncs, which is where
-	   the next plugin should put its own vfuncs.
-
-	   first we'll need to figure out what vfuncs the previous plugin
-	   changed and update the mask */
-	hook_update_mask(ctx, ctx->tail, vlast);
-
-	/* now go up in the stack as long as the mask isn't set,
-	   and update the vfuncs */
-	for (stack = ctx->tail->prev; stack != NULL; stack = stack->prev)
-		hook_copy_stack(ctx, stack);
-
-	/* add vlast to stack */
-	hook_build_append(ctx, vlast);
-}
-
 void hook_mail_user_created(struct mail_user *user)
 {
 	const struct mail_storage_hooks *const *hooks;
@@ -279,7 +171,7 @@
 		} T_END;
 	}
 	user->vlast = NULL;
-	pool_unref(&ctx->pool);
+	hook_build_deinit(&ctx);
 }
 
 void hook_mail_namespace_storage_added(struct mail_namespace *ns)
@@ -333,7 +225,7 @@
 		} T_END;
 	}
 	storage->vlast = NULL;
-	pool_unref(&ctx->pool);
+	hook_build_deinit(&ctx);
 }
 
 void hook_mailbox_list_created(struct mailbox_list *list)
@@ -350,7 +242,7 @@
 		} T_END;
 	}
 	list->vlast = NULL;
-	pool_unref(&ctx->pool);
+	hook_build_deinit(&ctx);
 }
 
 void hook_mailbox_allocated(struct mailbox *box)
@@ -367,7 +259,7 @@
 		} T_END;
 	}
 	box->vlast = NULL;
-	pool_unref(&ctx->pool);
+	hook_build_deinit(&ctx);
 }
 
 void hook_mailbox_opened(struct mailbox *box)
@@ -396,5 +288,5 @@
 		} T_END;
 	}
 	pmail->vlast = NULL;
-	pool_unref(&ctx->pool);
+	hook_build_deinit(&ctx);
 }
--- a/src/lib/Makefile.am	Mon Feb 20 14:34:25 2017 +0200
+++ b/src/lib/Makefile.am	Mon Feb 20 15:28:36 2017 +0200
@@ -50,6 +50,7 @@
 	hmac.c \
 	hmac-cram-md5.c \
 	home-expand.c \
+	hook-build.c \
 	hostpid.c \
 	imem.c \
 	ipwd.c \
@@ -196,6 +197,7 @@
 	hmac.h \
 	hmac-cram-md5.h \
 	home-expand.h \
+	hook-build.h \
 	hostpid.h \
 	imem.h \
 	ipwd.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/hook-build.c	Mon Feb 20 15:28:36 2017 +0200
@@ -0,0 +1,121 @@
+/* Copyright (c) 2009-2017 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "llist.h"
+#include "hook-build.h"
+
+struct hook_stack {
+	struct hook_stack *prev, *next;
+
+	/* Pointer to vfuncs struct. This 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.. */
+	void (**vfuncs)();
+	/* nonzero in the areas where vfuncs has been changed */
+	void (**mask)();
+};
+
+struct hook_build_context {
+	pool_t pool;
+	/* size of the vfuncs struct */
+	size_t size;
+	/* number of function pointers in the struct */
+	unsigned int count;
+
+	struct hook_stack *head, *tail;
+};
+
+static void hook_build_append(struct hook_build_context *ctx, void (**vfuncs)())
+{
+	struct hook_stack *stack;
+
+	stack = p_new(ctx->pool, struct hook_stack, 1);
+	stack->vfuncs = vfuncs;
+	stack->mask = p_malloc(ctx->pool, ctx->size);
+	DLLIST2_APPEND(&ctx->head, &ctx->tail, stack);
+}
+
+struct hook_build_context *hook_build_init(void (**vfuncs)(), size_t size)
+{
+	struct hook_build_context *ctx;
+	pool_t pool;
+
+	i_assert((size % sizeof(void (*)())) == 0);
+
+	pool = pool_alloconly_create("hook build context", 2048);
+	ctx = p_new(pool, struct hook_build_context, 1);
+	ctx->pool = pool;
+	ctx->size = size;
+	ctx->count = size / sizeof(void (*)());
+	hook_build_append(ctx, vfuncs);
+	return ctx;
+}
+
+static void
+hook_update_mask(struct hook_build_context *ctx, struct hook_stack *stack,
+		 void (**vlast)())
+{
+	unsigned int i;
+
+	for (i = 0; i < ctx->count; i++) {
+		if (stack->vfuncs[i] != vlast[i]) {
+			i_assert(stack->vfuncs[i] != NULL);
+			stack->mask[i] = stack->vfuncs[i];
+		}
+	}
+}
+
+static void
+hook_copy_stack(struct hook_build_context *ctx, struct hook_stack *stack)
+{
+	unsigned int i;
+
+	i_assert(stack->next != NULL);
+
+	for (i = 0; i < ctx->count; i++) {
+		if (stack->mask[i] == NULL) {
+			stack->vfuncs[i] = stack->next->vfuncs[i];
+			stack->mask[i] = stack->next->mask[i];
+		}
+	}
+}
+
+void hook_build_update(struct hook_build_context *ctx, void *_vlast)
+{
+	void (**vlast)() = _vlast;
+	struct hook_stack *stack;
+
+	if (ctx->tail->vfuncs == vlast) {
+		/* no vfuncs overridden */
+		return;
+	}
+
+	/* ctx->vfuncs_stack->vfuncs points to the root vfuncs,
+	   ctx->vfuncs_stack->next->vfuncs points to the first super function
+	   that is being called, and so on.
+
+	   the previous plugin added its vfuncs to the stack tail.
+	   vlast contains the previous plugin's super vfuncs, which is where
+	   the next plugin should put its own vfuncs.
+
+	   first we'll need to figure out what vfuncs the previous plugin
+	   changed and update the mask */
+	hook_update_mask(ctx, ctx->tail, vlast);
+
+	/* now go up in the stack as long as the mask isn't set,
+	   and update the vfuncs */
+	for (stack = ctx->tail->prev; stack != NULL; stack = stack->prev)
+		hook_copy_stack(ctx, stack);
+
+	/* add vlast to stack */
+	hook_build_append(ctx, vlast);
+}
+
+void hook_build_deinit(struct hook_build_context **_ctx)
+{
+	struct hook_build_context *ctx = *_ctx;
+	*_ctx = NULL;
+	pool_unref(&ctx->pool);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/hook-build.h	Mon Feb 20 15:28:36 2017 +0200
@@ -0,0 +1,19 @@
+/* Copyright (c) 2017 Dovecot authors, see the included COPYING file */
+#ifndef HOOK_BUILD_H
+#define HOOK_BUILD_H 1
+
+struct hook_build_context;
+struct hook_stack;
+
+/* Initialize new hook building context, vfuncs should point to
+   the functions table that is being manipulated, and size should be
+   the size of this table. */
+struct hook_build_context *hook_build_init(void (**vfuncs)(), size_t size);
+
+/* This is called after a hook may have updated vfuncs */
+void hook_build_update(struct hook_build_context *ctx, void *_vlast);
+
+/* Free memory used by build context */
+void hook_build_deinit(struct hook_build_context **_ctx);
+
+#endif