[dovecot-cvs] dovecot/src/plugins/quota Makefile.am, 1.6.2.2, 1.6.2.3 quota-count.c, NONE, 1.1.2.1 quota-dict.c, 1.9.2.6, 1.9.2.7 quota-private.h, 1.7.2.3, 1.7.2.4

tss at dovecot.org tss at dovecot.org
Sun Dec 3 18:55:37 UTC 2006


Update of /var/lib/cvs/dovecot/src/plugins/quota
In directory talvi:/tmp/cvs-serv13868

Modified Files:
      Tag: branch_1_0
	Makefile.am quota-dict.c quota-private.h 
Added Files:
      Tag: branch_1_0
	quota-count.c 
Log Message:
dict quota: If dictionary doesn't yet contain the quota, calculate it by
going through all mails in all mailboxes.



Index: Makefile.am
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/quota/Makefile.am,v
retrieving revision 1.6.2.2
retrieving revision 1.6.2.3
diff -u -d -r1.6.2.2 -r1.6.2.3
--- Makefile.am	17 Jun 2006 18:03:40 -0000	1.6.2.2
+++ Makefile.am	3 Dec 2006 18:55:34 -0000	1.6.2.3
@@ -14,6 +14,7 @@
 
 lib01_quota_plugin_la_SOURCES = \
 	quota.c \
+        quota-count.c \
 	quota-fs.c \
 	quota-dict.c \
 	quota-dirsize.c \

--- NEW FILE: quota-count.c ---
/* Copyright (C) 2006 Timo Sirainen */

#include "lib.h"
#include "mail-search.h"
#include "mail-storage.h"
#include "quota-private.h"

static int quota_count_mailbox(struct mail_storage *storage, const char *name,
			       uint64_t *bytes_r, uint64_t *count_r)
{
	struct mailbox *box;
	struct mailbox_transaction_context *trans;
	struct mail_search_context *ctx;
	struct mail *mail;
	struct mail_search_arg search_arg;
	uoff_t size;
	int ret = 0;

	box = mailbox_open(storage, name, NULL,
			   MAILBOX_OPEN_READONLY | MAILBOX_OPEN_KEEP_RECENT);
	if (box == NULL)
		return -1;

	memset(&search_arg, 0, sizeof(search_arg));
	search_arg.type = SEARCH_ALL;

	trans = mailbox_transaction_begin(box, 0);
	ctx = mailbox_search_init(trans, NULL, &search_arg, NULL);
	mail = mail_alloc(trans, MAIL_FETCH_PHYSICAL_SIZE, NULL);
	while (mailbox_search_next(ctx, mail) > 0) {
		size = mail_get_physical_size(mail);
		if (size != (uoff_t)-1)
			*bytes_r += size;
		*count_r += 1;
	}
	mail_free(&mail);
	if (mailbox_search_deinit(&ctx) < 0)
		ret = -1;

	if (ret < 0)
		mailbox_transaction_rollback(&trans);
	else
		(void)mailbox_transaction_commit(&trans, 0);

	mailbox_close(&box);
	return ret;
}

int quota_count_storage(struct mail_storage *storage,
			uint64_t *bytes_r, uint64_t *count_r)
{
	struct mailbox_list_context *ctx;
	struct mailbox_list *list;
	int ret = 0;

	*bytes_r = *count_r = 0;

	ctx = mail_storage_mailbox_list_init(storage, "", "*",
					     MAILBOX_LIST_FAST_FLAGS |
					     MAILBOX_LIST_INBOX);
	while ((list = mail_storage_mailbox_list_next(ctx)) != NULL) {
		if ((list->flags & (MAILBOX_NONEXISTENT |
				    MAILBOX_PLACEHOLDER |
				    MAILBOX_NOSELECT)) == 0) {
			ret = quota_count_mailbox(storage, list->name,
						  bytes_r, count_r);
			if (ret < 0)
				break;
		}
	}
	if (mail_storage_mailbox_list_deinit(&ctx) < 0)
		ret = -1;

	return ret;
}

Index: quota-dict.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/quota/quota-dict.c,v
retrieving revision 1.9.2.6
retrieving revision 1.9.2.7
diff -u -d -r1.9.2.6 -r1.9.2.7
--- quota-dict.c	3 Dec 2006 16:15:10 -0000	1.9.2.6
+++ quota-dict.c	3 Dec 2006 18:55:34 -0000	1.9.2.7
@@ -1,6 +1,7 @@
 /* Copyright (C) 2005-2006 Timo Sirainen */
 
 #include "lib.h"
+#include "array.h"
 #include "str.h"
 #include "dict.h"
 #include "quota-private.h"
@@ -17,6 +18,8 @@
 
 	uint64_t message_bytes_limit;
 	uint64_t message_count_limit;
+
+	unsigned int counting:1;
 };
 
 extern struct quota_backend quota_backend_dict;
@@ -97,34 +100,93 @@
 	return resources;
 }
 
+static struct mail_storage *
+dict_quota_root_get_storage(struct quota_root *root)
+{
+	/* FIXME: figure out how to support multiple storages */
+	struct mail_storage *const *storages;
+	unsigned int count;
+
+	storages = array_get(&root->storages, &count);
+	i_assert(count > 0);
+
+	return storages[0];
+}
+
+static int dict_quota_lookup(struct dict_quota_root *root, const char *path,
+			     uint64_t *value_r)
+{
+	struct dict_transaction_context *dt;
+	const char *value;
+	uint64_t bytes, count;
+	int ret;
+
+	i_assert(!root->counting);
+
+	t_push();
+	ret = dict_lookup(root->dict, unsafe_data_stack_pool, path, &value);
+	if (ret > 0) {
+		*value_r = strtoull(value, NULL, 10);
+		t_pop();
+		return 0;
+	}
+	t_pop();
+
+	if (ret < 0)
+		return -1;
+
+	/* not found, recalculate the quota */
+	root->counting = TRUE;
+	ret = quota_count_storage(dict_quota_root_get_storage(&root->root),
+				  &bytes, &count);
+	root->counting = FALSE;
+
+	if (ret < 0)
+		return -1;
+
+	t_push();
+	dt = dict_transaction_begin(root->dict);
+	if (root->message_bytes_limit != (uint64_t)-1)
+		dict_set(dt, DICT_QUOTA_CURRENT_BYTES_PATH, dec2str(bytes));
+	if (root->message_count_limit != (uint64_t)-1)
+		dict_set(dt, DICT_QUOTA_CURRENT_COUNT_PATH, dec2str(count));
+	t_pop();
+
+	if (dict_transaction_commit(dt) < 0)
+		i_error("dict_quota: Couldn't update quota");
+
+	if (strcmp(path, DICT_QUOTA_CURRENT_BYTES_PATH) == 0)
+		*value_r = bytes;
+	else {
+		i_assert(strcmp(path, DICT_QUOTA_CURRENT_COUNT_PATH) == 0);
+		*value_r = count;
+	}
+	return 0;
+}
+
 static int
 dict_quota_get_resource(struct quota_root *_root, const char *name,
 			uint64_t *value_r, uint64_t *limit_r)
 {
 	struct dict_quota_root *root = (struct dict_quota_root *)_root;
-	const char *value;
-	int ret;
 
 	if (strcmp(name, QUOTA_NAME_STORAGE) == 0) {
 		if (root->message_bytes_limit == (uint64_t)-1)
 			return 0;
 
 		*limit_r = root->message_bytes_limit / 1024;
-		t_push();
-		ret = dict_lookup(root->dict, unsafe_data_stack_pool,
-				  DICT_QUOTA_CURRENT_BYTES_PATH, &value);
-		*value_r = ret <= 0 ? 0 : strtoull(value, NULL, 10) / 1024;
-		t_pop();
+		if (dict_quota_lookup(root, DICT_QUOTA_CURRENT_BYTES_PATH,
+				      value_r) < 0)
+			return -1;
+		*value_r /= 1024;
 	} else if (strcmp(name, QUOTA_NAME_MESSAGES) == 0) {
 		if (root->message_count_limit == (uint64_t)-1)
 			return 0;
 
 		*limit_r = root->message_count_limit;
-		t_push();
-		ret = dict_lookup(root->dict, unsafe_data_stack_pool,
-				  DICT_QUOTA_CURRENT_COUNT_PATH, &value);
-		*value_r = ret <= 0 ? 0 : strtoull(value, NULL, 10);
-		t_pop();
+		if (dict_quota_lookup(root, DICT_QUOTA_CURRENT_COUNT_PATH,
+				      value_r) < 0)
+			return -1;
 	} else {
 		return 0;
 	}
@@ -148,7 +210,6 @@
 {
 	struct dict_quota_root *root = (struct dict_quota_root *)_root;
 	struct quota_root_transaction_context *ctx;
-	const char *value;
 
 	ctx = i_new(struct quota_root_transaction_context, 1);
 	ctx->root = _root;
@@ -157,18 +218,24 @@
 	ctx->bytes_limit = root->message_bytes_limit;
 	ctx->count_limit = root->message_count_limit;
 
+	if (root->counting) {
+		/* created by quota_count_storage(), we don't care about
+		   the quota there */
+		ctx->bytes_limit = (uint64_t)-1;
+		ctx->count_limit = (uint64_t)-1;
+		return ctx;
+	}
+
 	t_push();
 	if (ctx->bytes_limit != (uint64_t)-1) {
-		(void)dict_lookup(root->dict, unsafe_data_stack_pool,
-				  DICT_QUOTA_CURRENT_BYTES_PATH, &value);
-		ctx->bytes_current = value == NULL ? 0 :
-			strtoull(value, NULL, 10);
+		if (dict_quota_lookup(root, DICT_QUOTA_CURRENT_BYTES_PATH,
+				      &ctx->bytes_current) < 0)
+			ctx->bytes_current = 0;
 	}
 	if (ctx->count_limit != (uint64_t)-1) {
-		(void)dict_lookup(root->dict, unsafe_data_stack_pool,
-				  DICT_QUOTA_CURRENT_COUNT_PATH, &value);
-		ctx->count_current = value == NULL ? 0 :
-			strtoull(value, NULL, 10);
+		if (dict_quota_lookup(root, DICT_QUOTA_CURRENT_COUNT_PATH,
+				      &ctx->count_current) < 0)
+			ctx->bytes_current = 0;
 	}
 	t_pop();
 	return ctx;

Index: quota-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/quota/quota-private.h,v
retrieving revision 1.7.2.3
retrieving revision 1.7.2.4
diff -u -d -r1.7.2.3 -r1.7.2.4
--- quota-private.h	3 Dec 2006 16:15:10 -0000	1.7.2.3
+++ quota-private.h	3 Dec 2006 18:55:34 -0000	1.7.2.4
@@ -130,4 +130,7 @@
 void quota_default_free(struct quota_root_transaction_context *ctx,
 			struct mail *mail);
 
+int quota_count_storage(struct mail_storage *storage,
+			uint64_t *bytes_r, uint64_t *count_r);
+
 #endif



More information about the dovecot-cvs mailing list