dovecot-1.2: Implemented support for per-namespace quotas. Can b...

dovecot at dovecot.org dovecot at dovecot.org
Fri Apr 17 04:31:37 EEST 2009


details:   http://hg.dovecot.org/dovecot-1.2/rev/16c286aee307
changeset: 8958:16c286aee307
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Apr 16 21:31:30 2009 -0400
description:
Implemented support for per-namespace quotas. Can be used with public namespaces.

diffstat:

9 files changed, 151 insertions(+), 16 deletions(-)
src/plugins/quota/quota-count.c   |    3 +
src/plugins/quota/quota-dict.c    |   22 ++++++++++---
src/plugins/quota/quota-dirsize.c |    3 +
src/plugins/quota/quota-maildir.c |   32 +++++++++++++++++--
src/plugins/quota/quota-plugin.c  |    6 +++
src/plugins/quota/quota-plugin.h  |    1 
src/plugins/quota/quota-private.h |    8 ++++
src/plugins/quota/quota-storage.c |   62 ++++++++++++++++++++++++++++++++++---
src/plugins/quota/quota.c         |   30 ++++++++++++++---

diffs (truncated from 358 to 300 lines):

diff -r d7847f03ae65 -r 16c286aee307 src/plugins/quota/quota-count.c
--- a/src/plugins/quota/quota-count.c	Thu Apr 16 20:09:12 2009 -0400
+++ b/src/plugins/quota/quota-count.c	Thu Apr 16 21:31:30 2009 -0400
@@ -102,6 +102,9 @@ int quota_count(struct quota_root *root,
 
 	storages = array_get(&root->quota->storages, &count);
 	for (i = 0; i < count; i++) {
+		if (!quota_root_is_storage_visible(root, storages[i]))
+			continue;
+
 		ret = quota_count_storage(root, storages[i], bytes_r, count_r);
 		if (ret < 0)
 			break;
diff -r d7847f03ae65 -r 16c286aee307 src/plugins/quota/quota-dict.c
--- a/src/plugins/quota/quota-dict.c	Thu Apr 16 20:09:12 2009 -0400
+++ b/src/plugins/quota/quota-dict.c	Thu Apr 16 21:31:30 2009 -0400
@@ -4,6 +4,7 @@
 #include "str.h"
 #include "dict.h"
 #include "mail-user.h"
+#include "mail-namespace.h"
 #include "quota-private.h"
 
 #include <stdlib.h>
@@ -41,12 +42,25 @@ static int dict_quota_init(struct quota_
 	username = t_strdup_until(args, p);
 	args = p+1;
 
-	if (strncmp(args, "noenforcing:", 12) == 0) {
+	do {
 		/* FIXME: pretty ugly in here. the parameters should have
 		   been designed to be extensible. do it in a future version */
-		_root->no_enforcing = TRUE;
-		args += 12;
-	}
+		if (strncmp(args, "noenforcing:", 12) == 0) {
+			_root->no_enforcing = TRUE;
+			args += 12;
+			continue;
+		}
+		if (strncmp(args, "ns=", 3) == 0) {
+			p = strchr(args, ':');
+			if (p == NULL)
+				break;
+
+			_root->ns_prefix = p_strdup_until(_root->pool,
+							  args + 3, p);
+			args = p + 1;
+			continue;
+		}
+	} while (0);
 
 	if (*username == '\0')
 		username = _root->quota->user->username;
diff -r d7847f03ae65 -r 16c286aee307 src/plugins/quota/quota-dirsize.c
--- a/src/plugins/quota/quota-dirsize.c	Thu Apr 16 20:09:12 2009 -0400
+++ b/src/plugins/quota/quota-dirsize.c	Thu Apr 16 21:31:30 2009 -0400
@@ -158,6 +158,9 @@ get_quota_root_usage(struct quota_root *
 	t_array_init(&paths, 8);
 	storages = array_get(&root->quota->storages, &count);
 	for (i = 0; i < count; i++) {
+		if (!quota_root_is_storage_visible(root, storages[i]))
+			continue;
+
 		path = mail_storage_get_mailbox_path(storages[i], "", &is_file);
 		quota_count_path_add(&paths, path, FALSE);
 
diff -r d7847f03ae65 -r 16c286aee307 src/plugins/quota/quota-maildir.c
--- a/src/plugins/quota/quota-maildir.c	Thu Apr 16 20:09:12 2009 -0400
+++ b/src/plugins/quota/quota-maildir.c	Thu Apr 16 21:31:30 2009 -0400
@@ -377,6 +377,9 @@ static int maildirsize_recalculate(struc
 	/* count mails from all storages */
 	storages = array_get(&root->root.quota->storages, &count);
 	for (i = 0; i < count; i++) {
+		if (!quota_root_is_storage_visible(root, storages[i]))
+			continue;
+
 		if (maildirsize_recalculate_storage(root, storages[i]) < 0) {
 			ret = -1;
 			break;
@@ -386,6 +389,9 @@ static int maildirsize_recalculate(struc
 	if (ret == 0) {
 		/* check if any of the directories have changed */
 		for (i = 0; i < count; i++) {
+			if (!quota_root_is_storage_visible(root, storages[i]))
+				continue;
+
 			ret = maildirs_check_have_changed(root, storages[i],
 						root->recalc_last_stamp);
 			if (ret != 0)
@@ -685,6 +691,26 @@ static struct quota_root *maildir_quota_
 	return &root->root;
 }
 
+static int maildir_quota_init(struct quota_root *_root, const char *args)
+{
+	const char *const *tmp;
+
+	if (args == NULL)
+		return 0;
+
+	for (tmp = t_strsplit(args, ":"); *tmp != NULL; tmp++) {
+		if (strcmp(*tmp, "noenforcing") == 0)
+			_root->no_enforcing = TRUE;
+		else if (strncmp(*tmp, "ns=", 3) == 0)
+			_root->ns_prefix = p_strdup(_root->pool, *tmp + 3);
+		else {
+			i_error("maildir quota: Invalid parameter: %s", *tmp);
+			return -1;
+		}
+	}
+	return 0;
+}
+
 static void maildir_quota_deinit(struct quota_root *_root)
 {
 	struct maildir_quota_root *root = (struct maildir_quota_root *)_root;
@@ -738,7 +764,9 @@ maildir_quota_storage_added(struct quota
 
 	roots = array_get_modifiable(&quota->roots, &count);
 	for (i = 0; i < count; i++) {
-		if (roots[i]->backend.name == quota_backend_maildir.name)
+		if (roots[i]->backend.name == quota_backend_maildir.name &&
+		    (roots[i]->ns_prefix == NULL ||
+		     roots[i]->ns == storage->ns))
 			maildir_quota_root_storage_added(roots[i], storage);
 	}
 }
@@ -804,7 +832,7 @@ struct quota_backend quota_backend_maild
 
 	{
 		maildir_quota_alloc,
-		NULL,
+		maildir_quota_init,
 		maildir_quota_deinit,
 		maildir_quota_parse_rule,
 		maildir_quota_storage_added,
diff -r d7847f03ae65 -r 16c286aee307 src/plugins/quota/quota-plugin.c
--- a/src/plugins/quota/quota-plugin.c	Thu Apr 16 20:09:12 2009 -0400
+++ b/src/plugins/quota/quota-plugin.c	Thu Apr 16 21:31:30 2009 -0400
@@ -14,6 +14,7 @@ void (*quota_next_hook_mail_user_created
 void (*quota_next_hook_mail_user_created)(struct mail_user *user);
 void (*quota_next_hook_mail_storage_created)(struct mail_storage *storage);
 void (*quota_next_hook_mailbox_list_created)(struct mailbox_list *list);
+void (*quota_next_hook_mail_namespaces_created)(struct mail_namespace *namespaces);
 
 const char *quota_plugin_version = PACKAGE_VERSION;
 struct quota_settings *quota_set;
@@ -105,6 +106,9 @@ void quota_plugin_init(void)
 
 	quota_next_hook_mailbox_list_created = hook_mailbox_list_created;
 	hook_mailbox_list_created = quota_mailbox_list_created;
+
+	quota_next_hook_mail_namespaces_created = hook_mail_namespaces_created;
+	hook_mail_namespaces_created = quota_mail_namespaces_created;
 }
 
 void quota_plugin_deinit(void)
@@ -115,6 +119,8 @@ void quota_plugin_deinit(void)
 			quota_next_hook_mail_storage_created;
 		hook_mailbox_list_created =
 			quota_next_hook_mailbox_list_created;
+		hook_mail_namespaces_created =
+			quota_next_hook_mail_namespaces_created;
 		quota_settings_deinit(&quota_set);
 	}
 }
diff -r d7847f03ae65 -r 16c286aee307 src/plugins/quota/quota-plugin.h
--- a/src/plugins/quota/quota-plugin.h	Thu Apr 16 20:09:12 2009 -0400
+++ b/src/plugins/quota/quota-plugin.h	Thu Apr 16 21:31:30 2009 -0400
@@ -13,6 +13,7 @@ void quota_mail_user_created(struct mail
 void quota_mail_user_created(struct mail_user *user);
 void quota_mail_storage_created(struct mail_storage *storage);
 void quota_mailbox_list_created(struct mailbox_list *list);
+void quota_mail_namespaces_created(struct mail_namespace *namespaces);
 
 void quota_plugin_init(void);
 void quota_plugin_deinit(void);
diff -r d7847f03ae65 -r 16c286aee307 src/plugins/quota/quota-private.h
--- a/src/plugins/quota/quota-private.h	Thu Apr 16 20:09:12 2009 -0400
+++ b/src/plugins/quota/quota-private.h	Thu Apr 16 21:31:30 2009 -0400
@@ -96,6 +96,12 @@ struct quota_root {
 	struct quota *quota;
 	struct quota_backend backend;
 
+	/* this quota root applies only to this namespace. it may also be
+	   a public namespace without an owner. */
+	struct mail_namespace *ns;
+	/* this is set in quota init(), because namespaces aren't known yet */
+	const char *ns_prefix;
+
 	/* initially the same as set->default_rule.*_limit, but some backends
 	   may change these by reading the limits elsewhere (e.g. Maildir++,
 	   FS quota) */
@@ -133,6 +139,8 @@ void quota_remove_user_storage(struct ma
 
 struct quota *quota_get_mail_user_quota(struct mail_user *user);
 
+bool quota_root_is_storage_visible(struct quota_root *root,
+				   struct mail_storage *storage);
 struct quota_rule *
 quota_root_rule_find(struct quota_root_settings *root_set, const char *name);
 
diff -r d7847f03ae65 -r 16c286aee307 src/plugins/quota/quota-storage.c
--- a/src/plugins/quota/quota-storage.c	Thu Apr 16 20:09:12 2009 -0400
+++ b/src/plugins/quota/quota-storage.c	Thu Apr 16 21:31:30 2009 -0400
@@ -525,7 +525,9 @@ void quota_mail_storage_created(struct m
 					qstorage);
 
 		/* register to owner's quota roots */
-		quota = quota_get_mail_user_quota(storage->ns->owner);
+		quota = storage->ns->owner != NULL ?
+			quota_get_mail_user_quota(storage->ns->owner) :
+			quota_get_mail_user_quota(storage->ns->user);
 		quota_add_user_storage(quota, storage);
 	}
 
@@ -533,12 +535,43 @@ void quota_mail_storage_created(struct m
 		quota_next_hook_mail_storage_created(storage);
 }
 
+static struct quota_root *
+quota_find_root_for_ns(struct quota *quota, struct mail_namespace *ns)
+{
+	struct quota_root *const *roots;
+	unsigned int i, count;
+
+	roots = array_get(&quota->roots, &count);
+	for (i = 0; i < count; i++) {
+		if (roots[i]->ns_prefix != NULL &&
+		    strcmp(roots[i]->ns_prefix, ns->prefix) == 0)
+			return roots[i];
+	}
+	return NULL;
+}
+
 void quota_mailbox_list_created(struct mailbox_list *list)
 {
 	struct quota_mailbox_list *qlist;
-
-	if (list->ns->owner != NULL &&
-	    (list->ns->flags & NAMESPACE_FLAG_INTERNAL) == 0) {
+	struct quota *quota;
+	struct quota_root *root;
+	bool add;
+
+	if ((list->ns->flags & NAMESPACE_FLAG_INTERNAL) != 0)
+		add = FALSE;
+	else if (list->ns->owner == NULL) {
+		/* see if we have a quota explicitly defined for
+		   this namespace */
+		quota = quota_get_mail_user_quota(list->ns->user);
+		root = quota_find_root_for_ns(quota, list->ns);
+		add = root != NULL;
+		if (root != NULL)
+			root->ns = list->ns;
+	} else {
+		add = TRUE;
+	}
+
+	if (add) {
 		qlist = p_new(list->pool, struct quota_mailbox_list, 1);
 		qlist->module_ctx.super = list->v;
 		list->v.delete_mailbox = quota_mailbox_list_delete;
@@ -548,3 +581,24 @@ void quota_mailbox_list_created(struct m
 	if (quota_next_hook_mailbox_list_created != NULL)
 		quota_next_hook_mailbox_list_created(list);
 }
+
+void quota_mail_namespaces_created(struct mail_namespace *namespaces)
+{
+	struct quota *quota;
+	struct quota_root *const *roots;
+	unsigned int i, count;
+
+	quota = quota_get_mail_user_quota(namespaces->user);
+	roots = array_get(&quota->roots, &count);
+	for (i = 0; i < count; i++) {
+		if (roots[i]->ns_prefix == NULL || roots[i]->ns != NULL)
+			continue;
+
+		roots[i]->ns = mail_namespace_find_prefix(namespaces,
+							  roots[i]->ns_prefix);
+		if (roots[i]->ns == NULL) {
+			i_error("maildir quota: Unknown namespace: %s",
+				roots[i]->ns_prefix);
+		}
+	}
+}
diff -r d7847f03ae65 -r 16c286aee307 src/plugins/quota/quota.c
--- a/src/plugins/quota/quota.c	Thu Apr 16 20:09:12 2009 -0400
+++ b/src/plugins/quota/quota.c	Thu Apr 16 21:31:30 2009 -0400
@@ -531,8 +531,9 @@ void quota_remove_user_storage(struct ma
 	struct mail_storage *const *storages;
 	unsigned int i, count;
 
-	quota = storage->ns->owner == NULL ? NULL :
-		quota_get_mail_user_quota(storage->ns->owner);
+	quota = storage->ns->owner != NULL ?
+		quota_get_mail_user_quota(storage->ns->owner) :


More information about the dovecot-cvs mailing list