dovecot-2.2: quota: Moved some functions to quota-util.c

dovecot at dovecot.org dovecot at dovecot.org
Wed Jul 2 17:38:35 UTC 2014


details:   http://hg.dovecot.org/dovecot-2.2/rev/0d4de84a54f0
changeset: 17565:0d4de84a54f0
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Jul 02 20:34:43 2014 +0300
description:
quota: Moved some functions to quota-util.c

diffstat:

 src/plugins/quota/Makefile.am     |    4 +-
 src/plugins/quota/quota-private.h |   12 +-
 src/plugins/quota/quota-util.c    |  401 ++++++++++++++++++++++++++++++++++++
 src/plugins/quota/quota.c         |  421 +------------------------------------
 4 files changed, 426 insertions(+), 412 deletions(-)

diffs (truncated from 959 to 300 lines):

diff -r d77d880c1385 -r 0d4de84a54f0 src/plugins/quota/Makefile.am
--- a/src/plugins/quota/Makefile.am	Wed Jul 02 20:13:35 2014 +0300
+++ b/src/plugins/quota/Makefile.am	Wed Jul 02 20:34:43 2014 +0300
@@ -29,7 +29,8 @@
 	quota-dirsize.c \
 	quota-maildir.c \
         quota-plugin.c \
-	quota-storage.c
+	quota-storage.c \
+	quota-util.c
 
 quota_common_objects = \
 	quota.lo \
@@ -40,6 +41,7 @@
 	quota-maildir.lo \
         quota-plugin.lo \
 	quota-storage.lo \
+	quota-util.lo \
 	$(RQUOTA_XDR_LO)
 
 lib10_quota_plugin_la_SOURCES = $(quota_dist_sources)
diff -r d77d880c1385 -r 0d4de84a54f0 src/plugins/quota/quota-private.h
--- a/src/plugins/quota/quota-private.h	Wed Jul 02 20:13:35 2014 +0300
+++ b/src/plugins/quota/quota-private.h	Wed Jul 02 20:34:43 2014 +0300
@@ -150,8 +150,9 @@
 	   after the first allocation is done, bytes_ceil is set to
 	   bytes_ceil2. */
 	uint64_t bytes_ceil, bytes_ceil2, count_ceil;
-	/* how many bytes/mails we are over quota (either *_ceil or *_over
-	   is always zero) */
+	/* How many bytes/mails we are over quota. Like *_ceil, these are set
+	   only once and not updated by bytes_used/count_used. (Either *_ceil
+	   or *_over is always zero.) */
 	uint64_t bytes_over, count_over;
 
 	struct mail *tmp_mail;
@@ -178,4 +179,11 @@
 					   int64_t count_limit);
 int quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r);
 
+int quota_root_parse_grace(struct quota_root_settings *root_set,
+			   const char *value, const char **error_r);
+bool quota_warning_match(const struct quota_warning_rule *w,
+			 uint64_t bytes_before, uint64_t bytes_current,
+			 uint64_t count_before, uint64_t count_current);
+bool quota_transaction_is_over(struct quota_transaction_context *ctx, uoff_t size);
+
 #endif
diff -r d77d880c1385 -r 0d4de84a54f0 src/plugins/quota/quota-util.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/plugins/quota/quota-util.c	Wed Jul 02 20:34:43 2014 +0300
@@ -0,0 +1,401 @@
+/* Copyright (c) 2005-2014 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "wildcard-match.h"
+#include "quota-private.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#define QUOTA_DEFAULT_GRACE "10%"
+
+#define RULE_NAME_DEFAULT_FORCE "*"
+#define RULE_NAME_DEFAULT_NONFORCE "?"
+
+struct quota_rule *
+quota_root_rule_find(struct quota_root_settings *root_set, const char *name)
+{
+	struct quota_rule *rule;
+
+	array_foreach_modifiable(&root_set->rules, rule) {
+		if (wildcard_match(name, rule->mailbox_mask))
+			return rule;
+	}
+	return NULL;
+}
+
+static struct quota_rule *
+quota_root_rule_find_exact(struct quota_root_settings *root_set,
+			   const char *name)
+{
+	struct quota_rule *rule;
+
+	array_foreach_modifiable(&root_set->rules, rule) {
+		if (strcmp(rule->mailbox_mask, name) == 0)
+			return rule;
+	}
+	return NULL;
+}
+
+static int
+quota_rule_parse_percentage(struct quota_root_settings *root_set,
+			    struct quota_rule *rule,
+			    int64_t *limit, const char **error_r)
+{
+	int64_t percentage = *limit;
+
+	if (percentage <= -100 || percentage >= UINT_MAX) {
+		*error_r = "Invalid percentage";
+		return -1;
+	}
+
+	if (rule == &root_set->default_rule) {
+		*error_r = "Default rule can't be a percentage";
+		return -1;
+	}
+
+	if (limit == &rule->bytes_limit)
+		rule->bytes_percent = percentage;
+	else if (limit == &rule->count_limit)
+		rule->count_percent = percentage;
+	else
+		i_unreached();
+	return 0;
+}
+
+static int quota_limit_parse(struct quota_root_settings *root_set,
+			     struct quota_rule *rule, const char *unit,
+			     uint64_t multiply, int64_t *limit,
+			     const char **error_r)
+{
+	switch (i_toupper(*unit)) {
+	case '\0':
+		/* default */
+		break;
+	case 'B':
+		multiply = 1;
+		break;
+	case 'K':
+		multiply = 1024;
+		break;
+	case 'M':
+		multiply = 1024*1024;
+		break;
+	case 'G':
+		multiply = 1024*1024*1024;
+		break;
+	case 'T':
+		multiply = 1024ULL*1024*1024*1024;
+		break;
+	case '%':
+		multiply = 0;
+		if (quota_rule_parse_percentage(root_set, rule, limit,
+						error_r) < 0)
+			return -1;
+		break;
+	default:
+		*error_r = t_strdup_printf("Unknown unit: %s", unit);
+		return -1;
+	}
+	*limit *= multiply;
+	return 0;
+}
+
+static void
+quota_rule_recalculate_relative_rules(struct quota_rule *rule,
+				      int64_t bytes_limit, int64_t count_limit)
+{
+	if (rule->bytes_percent != 0)
+		rule->bytes_limit = bytes_limit * rule->bytes_percent / 100;
+	if (rule->count_percent != 0)
+		rule->count_limit = count_limit * rule->count_percent / 100;
+}
+
+void quota_root_recalculate_relative_rules(struct quota_root_settings *root_set,
+					   int64_t bytes_limit,
+					   int64_t count_limit)
+{
+	struct quota_rule *rule;
+	struct quota_warning_rule *warning_rule;
+
+	array_foreach_modifiable(&root_set->rules, rule) {
+		quota_rule_recalculate_relative_rules(rule, bytes_limit,
+						      count_limit);
+	}
+
+	array_foreach_modifiable(&root_set->warning_rules, warning_rule) {
+		quota_rule_recalculate_relative_rules(&warning_rule->rule,
+						      bytes_limit, count_limit);
+	}
+	quota_rule_recalculate_relative_rules(&root_set->grace_rule,
+					      bytes_limit, 0);
+	root_set->last_mail_max_extra_bytes = root_set->grace_rule.bytes_limit;
+
+	if (root_set->set->debug && root_set->set->initialized) {
+		i_debug("Quota root %s: Recalculated relative rules with "
+			"bytes=%lld count=%lld. Now grace=%llu", root_set->name,
+			(long long)bytes_limit, (long long)count_limit,
+			(unsigned long long)root_set->last_mail_max_extra_bytes);
+	}
+}
+
+static int
+quota_rule_parse_limits(struct quota_root_settings *root_set,
+			struct quota_rule *rule, const char *limits,
+			const char *full_rule_def,
+			bool relative_rule, const char **error_r)
+{
+	const char **args, *key, *value, *error;
+	char *p;
+	uint64_t multiply;
+	int64_t *limit;
+
+	args = t_strsplit(limits, ":");
+	for (; *args != NULL; args++) {
+		multiply = 1;
+		limit = NULL;
+
+		key = *args;
+		value = strchr(key, '=');
+		if (value == NULL)
+			value = "";
+		else
+			key = t_strdup_until(key, value++);
+
+		if (*value == '+') {
+			if (!relative_rule) {
+				*error_r = "Rule limit cannot have '+'";
+				return -1;
+			}
+			value++;
+		} else if (*value != '-' && relative_rule) {
+			i_warning("quota root %s rule %s: "
+				  "obsolete configuration for rule '%s' "
+				  "should be changed to '%s=+%s'",
+				  root_set->name, full_rule_def,
+				  *args, key, value);
+		}
+
+		if (strcmp(key, "storage") == 0) {
+			multiply = 1024;
+			limit = &rule->bytes_limit;
+			*limit = strtoll(value, &p, 10);
+		} else if (strcmp(key, "bytes") == 0) {
+			limit = &rule->bytes_limit;
+			*limit = strtoll(value, &p, 10);
+		} else if (strcmp(key, "messages") == 0) {
+			limit = &rule->count_limit;
+			*limit = strtoll(value, &p, 10);
+		} else {
+			*error_r = p_strdup_printf(root_set->set->pool,
+					"Unknown rule limit name: %s", key);
+			return -1;
+		}
+
+		if (quota_limit_parse(root_set, rule, p, multiply,
+				      limit, &error) < 0) {
+			*error_r = p_strdup_printf(root_set->set->pool,
+				"Invalid rule limit value '%s': %s",
+				*args, error);
+			return -1;
+		}
+	}
+	if (!relative_rule) {
+		if (rule->bytes_limit < 0) {
+			*error_r = "Bytes limit can't be negative";
+			return -1;
+		}
+		if (rule->count_limit < 0) {
+			*error_r = "Count limit can't be negative";
+			return -1;
+		}
+	}
+	return 0;
+}
+
+int quota_root_add_rule(struct quota_root_settings *root_set,
+			const char *rule_def, const char **error_r)
+{
+	struct quota_rule *rule;
+	const char *p, *mailbox_mask;
+	int ret = 0;
+
+	p = strchr(rule_def, ':');
+	if (p == NULL) {
+		*error_r = "Invalid rule";
+		return -1;
+	}
+
+	/* <mailbox mask>:<quota limits> */
+	mailbox_mask = t_strdup_until(rule_def, p++);
+
+	rule = quota_root_rule_find_exact(root_set, mailbox_mask);
+	if (rule == NULL) {
+		if (strcmp(mailbox_mask, RULE_NAME_DEFAULT_NONFORCE) == 0)
+			rule = &root_set->default_rule;
+		else if (strcmp(mailbox_mask, RULE_NAME_DEFAULT_FORCE) == 0) {
+			rule = &root_set->default_rule;
+			root_set->force_default_rule = TRUE;
+		} else {
+			rule = array_append_space(&root_set->rules);
+			rule->mailbox_mask = strcasecmp(mailbox_mask, "INBOX") == 0 ? "INBOX" :
+				p_strdup(root_set->set->pool, mailbox_mask);
+		}
+	}
+
+	if (strcmp(p, "ignore") == 0) {
+		rule->ignore = TRUE;
+		if (root_set->set->debug) {


More information about the dovecot-cvs mailing list