dovecot-2.2: Added quota-clone plugin.

dovecot at dovecot.org dovecot at dovecot.org
Wed May 13 09:26:11 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/f5749f22276b
changeset: 18668:f5749f22276b
user:      Timo Sirainen <tss at iki.fi>
date:      Wed May 13 12:24:02 2015 +0300
description:
Added quota-clone plugin.

diffstat:

 NEWS                                         |    1 +
 configure.ac                                 |    1 +
 src/plugins/Makefile.am                      |    1 +
 src/plugins/quota-clone/Makefile.am          |   19 ++
 src/plugins/quota-clone/quota-clone-plugin.c |  197 +++++++++++++++++++++++++++
 src/plugins/quota-clone/quota-clone-plugin.h |    7 +
 6 files changed, 226 insertions(+), 0 deletions(-)

diffs (268 lines):

diff -r 69dcc2c8cd9d -r f5749f22276b NEWS
--- a/NEWS	Wed May 13 05:34:16 2015 +0300
+++ b/NEWS	Wed May 13 12:24:02 2015 +0300
@@ -34,6 +34,7 @@
 	  -A parameter reading the list of users from userdb lookup.
 	+ Implemented initial Cassandra CQL support as lib-sql backend. It's
 	  only usable as dict backend currently.
+	+ Added quota-clone plugin to copy current quota usage to a dict.
 	- auth: If auth_master_user_separator was set, auth process could be
 	  crashed by trying to log in with empty master username.
 	- imap-login, pop3-login: Fixed crash on handshake failures with new
diff -r 69dcc2c8cd9d -r f5749f22276b configure.ac
--- a/configure.ac	Wed May 13 05:34:16 2015 +0300
+++ b/configure.ac	Wed May 13 12:24:02 2015 +0300
@@ -2991,6 +2991,7 @@
 src/plugins/notify/Makefile
 src/plugins/pop3-migration/Makefile
 src/plugins/quota/Makefile
+src/plugins/quota-clone/Makefile
 src/plugins/imap-quota/Makefile
 src/plugins/replication/Makefile
 src/plugins/snarf/Makefile
diff -r 69dcc2c8cd9d -r f5749f22276b src/plugins/Makefile.am
--- a/src/plugins/Makefile.am	Wed May 13 05:34:16 2015 +0300
+++ b/src/plugins/Makefile.am	Wed May 13 12:24:02 2015 +0300
@@ -25,6 +25,7 @@
 	mail-log \
 	mailbox-alias \
 	quota \
+	quota-clone \
 	imap-quota \
 	pop3-migration \
 	replication \
diff -r 69dcc2c8cd9d -r f5749f22276b src/plugins/quota-clone/Makefile.am
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/plugins/quota-clone/Makefile.am	Wed May 13 12:24:02 2015 +0300
@@ -0,0 +1,19 @@
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/lib \
+	-I$(top_srcdir)/src/lib-dict \
+	-I$(top_srcdir)/src/lib-mail \
+	-I$(top_srcdir)/src/lib-index \
+	-I$(top_srcdir)/src/lib-storage \
+	-I$(top_srcdir)/src/plugins/quota
+
+NOPLUGIN_LDFLAGS =
+lib20_quota_clone_plugin_la_LDFLAGS = -module -avoid-version
+
+module_LTLIBRARIES = \
+	lib20_quota_clone_plugin.la
+
+lib20_quota_clone_plugin_la_SOURCES = \
+	quota-clone-plugin.c
+
+noinst_HEADERS = \
+	quota-clone-plugin.h
diff -r 69dcc2c8cd9d -r f5749f22276b src/plugins/quota-clone/quota-clone-plugin.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/plugins/quota-clone/quota-clone-plugin.c	Wed May 13 12:24:02 2015 +0300
@@ -0,0 +1,197 @@
+/* Copyright (c) 2015 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "module-context.h"
+#include "dict.h"
+#include "mail-storage-private.h"
+#include "quota.h"
+#include "quota-clone-plugin.h"
+
+#define DICT_QUOTA_CLONE_PATH DICT_PATH_PRIVATE"quota/"
+#define DICT_QUOTA_CLONE_BYTES_PATH DICT_QUOTA_CLONE_PATH"storage"
+#define DICT_QUOTA_CLONE_COUNT_PATH DICT_QUOTA_CLONE_PATH"messages"
+
+#define QUOTA_CLONE_USER_CONTEXT(obj) \
+	MODULE_CONTEXT(obj, quota_clone_user_module)
+#define QUOTA_CLONE_CONTEXT(obj) \
+	MODULE_CONTEXT(obj, quota_clone_storage_module)
+
+static MODULE_CONTEXT_DEFINE_INIT(quota_clone_user_module,
+				  &mail_user_module_register);
+static MODULE_CONTEXT_DEFINE_INIT(quota_clone_storage_module,
+				  &mail_storage_module_register);
+
+struct quota_clone_user {
+	union mail_user_module_context module_ctx;
+	struct dict *dict;
+};
+
+struct quota_clone_mailbox {
+	union mailbox_module_context module_ctx;
+	bool quota_changed;
+};
+
+static void quota_clone_flush(struct mailbox *box)
+{
+	struct quota_clone_mailbox *qbox = QUOTA_CLONE_CONTEXT(box);
+	struct quota_clone_user *quser =
+		QUOTA_CLONE_USER_CONTEXT(box->storage->user);
+	struct dict_transaction_context *trans;
+	struct quota_root_iter *iter;
+	struct quota_root *root;
+	uint64_t value, limit;
+	int ret;
+
+	/* we'll clone the first quota root */
+	iter = quota_root_iter_init(box);
+	root = quota_root_iter_next(iter);
+	if (root == NULL) {
+		/* no quota roots defined for this mailbox - ignore */
+		qbox->quota_changed = FALSE;
+		return;
+	}
+	quota_root_iter_deinit(&iter);
+
+	trans = dict_transaction_begin(quser->dict);
+	/* update bytes */
+	ret = quota_get_resource(root, "", QUOTA_NAME_STORAGE_BYTES,
+				 &value, &limit);
+	if (ret < 0)
+		i_error("quota_clone_plugin: Failed to lookup current quota bytes");
+	else {
+		dict_set(trans, DICT_QUOTA_CLONE_BYTES_PATH,
+			 t_strdup_printf("%llu", (unsigned long long)value));
+	}
+	/* update messages */
+	ret = quota_get_resource(root, "", QUOTA_NAME_MESSAGES,
+				 &value, &limit);
+	if (ret < 0)
+		i_error("quota_clone_plugin: Failed to lookup current quota count");
+	else {
+		dict_set(trans, DICT_QUOTA_CLONE_COUNT_PATH,
+			 t_strdup_printf("%llu", (unsigned long long)value));
+	}
+	if (dict_transaction_commit(&trans) < 0)
+		i_error("quota_clone_plugin: Failed to commit dict update");
+	else
+		qbox->quota_changed = FALSE;
+}
+
+static int quota_clone_save_finish(struct mail_save_context *ctx)
+{
+	struct quota_clone_mailbox *qbox =
+		QUOTA_CLONE_CONTEXT(ctx->transaction->box);
+
+	qbox->quota_changed = TRUE;
+	return qbox->module_ctx.super.save_finish(ctx);
+}
+
+static int
+quota_clone_copy(struct mail_save_context *ctx, struct mail *mail)
+{
+	struct quota_clone_mailbox *qbox =
+		QUOTA_CLONE_CONTEXT(ctx->transaction->box);
+
+	qbox->quota_changed = TRUE;
+	return qbox->module_ctx.super.copy(ctx, mail);
+}
+
+static void
+quota_clone_mailbox_sync_notify(struct mailbox *box, uint32_t uid,
+				enum mailbox_sync_type sync_type)
+{
+	struct quota_clone_mailbox *qbox = QUOTA_CLONE_CONTEXT(box);
+
+	if (qbox->module_ctx.super.sync_notify != NULL)
+		qbox->module_ctx.super.sync_notify(box, uid, sync_type);
+
+	if (sync_type == MAILBOX_SYNC_TYPE_EXPUNGE)
+		qbox->quota_changed = TRUE;
+}
+
+static void quota_clone_mailbox_close(struct mailbox *box)
+{
+	struct quota_clone_mailbox *qbox = QUOTA_CLONE_CONTEXT(box);
+
+	qbox->module_ctx.super.close(box);
+	if (qbox->quota_changed)
+		quota_clone_flush(box);
+}
+
+static void quota_clone_mailbox_allocated(struct mailbox *box)
+{
+	struct quota_clone_user *quser =
+		QUOTA_CLONE_USER_CONTEXT(box->storage->user);
+	struct mailbox_vfuncs *v = box->vlast;
+	struct quota_clone_mailbox *qbox;
+
+	if (quser == NULL)
+		return;
+
+	qbox = p_new(box->pool, struct quota_clone_mailbox, 1);
+	qbox->module_ctx.super = *v;
+	box->vlast = &qbox->module_ctx.super;
+
+	v->save_finish = quota_clone_save_finish;
+	v->copy = quota_clone_copy;
+	v->sync_notify = quota_clone_mailbox_sync_notify;
+	v->close = quota_clone_mailbox_close;
+	MODULE_CONTEXT_SET(box, quota_clone_storage_module, qbox);
+}
+
+static void quota_clone_mail_user_deinit(struct mail_user *user)
+{
+	struct quota_clone_user *quser = QUOTA_CLONE_USER_CONTEXT(user);
+
+	dict_deinit(&quser->dict);
+	quser->module_ctx.super.deinit(user);
+}
+
+static void quota_clone_mail_user_created(struct mail_user *user)
+{
+	struct quota_clone_user *quser;
+	struct mail_user_vfuncs *v = user->vlast;
+	struct dict_settings dict_set;
+	struct dict *dict;
+	const char *uri, *error;
+
+	uri = mail_user_plugin_getenv(user, "quota_clone_dict");
+	if (uri == NULL || uri[0] == '\0') {
+		i_error("The quota_clone_dict setting is missing from configuration");
+		return;
+	}
+
+	memset(&dict_set, 0, sizeof(dict_set));
+	dict_set.username = user->username;
+	dict_set.base_dir = user->set->base_dir;
+	(void)mail_user_get_home(user, &dict_set.home_dir);
+	if (dict_init_full(uri, &dict_set, &dict, &error) < 0) {
+		i_error("quota_clone_dict: Failed to initialize '%s': %s",
+			uri, error);
+		return;
+	}
+
+	quser = p_new(user->pool, struct quota_clone_user, 1);
+	quser->module_ctx.super = *v;
+	user->vlast = &quser->module_ctx.super;
+	v->deinit = quota_clone_mail_user_deinit;
+	quser->dict = dict;
+	MODULE_CONTEXT_SET(user, quota_clone_user_module, quser);
+}
+
+static struct mail_storage_hooks quota_clone_mail_storage_hooks = {
+	.mailbox_allocated = quota_clone_mailbox_allocated,
+	.mail_user_created = quota_clone_mail_user_created
+};
+
+void quota_clone_plugin_init(struct module *module ATTR_UNUSED)
+{
+	mail_storage_hooks_add(module, &quota_clone_mail_storage_hooks);
+}
+
+void quota_clone_plugin_deinit(void)
+{
+	mail_storage_hooks_remove(&quota_clone_mail_storage_hooks);
+}
+
+const char *quota_clone_plugin_dependencies[] = { "quota", NULL };
diff -r 69dcc2c8cd9d -r f5749f22276b src/plugins/quota-clone/quota-clone-plugin.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/plugins/quota-clone/quota-clone-plugin.h	Wed May 13 12:24:02 2015 +0300
@@ -0,0 +1,7 @@
+#ifndef QUOTA_CLONE_PLUGIN_H
+#define QUOTA_CLONE_PLUGIN_H
+
+void quota_clone_plugin_init(struct module *module);
+void quota_clone_plugin_deinit(void);
+
+#endif


More information about the dovecot-cvs mailing list