dovecot: Don't set quota limits to transactions until they're ne...

dovecot at dovecot.org dovecot at dovecot.org
Mon Jul 16 01:23:21 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/001d25a650df
changeset: 6025:001d25a650df
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Jul 16 00:28:24 2007 +0300
description:
Don't set quota limits to transactions until they're needed.

diffstat:

3 files changed, 62 insertions(+), 59 deletions(-)
src/plugins/quota/quota-count.c   |    6 -
src/plugins/quota/quota-private.h |    2 
src/plugins/quota/quota.c         |  113 +++++++++++++++++++------------------

diffs (206 lines):

diff -r 6074e9e6059d -r 001d25a650df src/plugins/quota/quota-count.c
--- a/src/plugins/quota/quota-count.c	Sun Jul 15 22:30:14 2007 +0300
+++ b/src/plugins/quota/quota-count.c	Mon Jul 16 00:28:24 2007 +0300
@@ -77,11 +77,7 @@ int quota_count(struct quota *quota, uin
 	unsigned int i, count;
 	int ret = 0;
 
-	i_assert(!quota->counting);
-
 	*bytes_r = *count_r = 0;
-
-	quota->counting = TRUE;
 
 	storages = array_get(&quota->storages, &count);
 	for (i = 0; i < count; i++) {
@@ -89,7 +85,5 @@ int quota_count(struct quota *quota, uin
 		if (ret < 0)
 			break;
 	}
-	quota->counting = FALSE;
-
 	return ret;
 }
diff -r 6074e9e6059d -r 001d25a650df src/plugins/quota/quota-private.h
--- a/src/plugins/quota/quota-private.h	Sun Jul 15 22:30:14 2007 +0300
+++ b/src/plugins/quota/quota-private.h	Mon Jul 16 00:28:24 2007 +0300
@@ -16,7 +16,6 @@ struct quota {
 			  uoff_t size, bool *too_large_r);
 
 	unsigned int debug:1;
-	unsigned int counting:1;
 };
 
 struct quota_rule {
@@ -81,6 +80,7 @@ struct quota_transaction_context {
 
 	struct mail *tmp_mail;
 
+	unsigned int limits_set:1;
 	unsigned int failed:1;
 	unsigned int recalculate:1;
 };
diff -r 6074e9e6059d -r 001d25a650df src/plugins/quota/quota.c
--- a/src/plugins/quota/quota.c	Sun Jul 15 22:30:14 2007 +0300
+++ b/src/plugins/quota/quota.c	Mon Jul 16 00:28:24 2007 +0300
@@ -438,83 +438,87 @@ struct quota_transaction_context *quota_
 							  struct mailbox *box)
 {
 	struct quota_transaction_context *ctx;
-	struct quota_root *const *roots;
-	const char *mailbox_name;
-	unsigned int i, count;
-	uint64_t current, limit, left;
-	int ret;
-
-	mailbox_name = mailbox_get_name(box);
-	
+
 	ctx = i_new(struct quota_transaction_context, 1);
 	ctx->quota = quota;
 	ctx->box = box;
 	ctx->bytes_left = (uint64_t)-1;
 	ctx->count_left = (uint64_t)-1;
-
-	if (quota->counting) {
-		/* we got here through quota_count_storage() */
-		return ctx;
-	}
+	return ctx;
+}
+
+int quota_transaction_commit(struct quota_transaction_context **_ctx)
+{
+	struct quota_transaction_context *ctx = *_ctx;
+	struct quota_root *const *roots;
+	unsigned int i, count;
+	int ret = 0;
+
+	*_ctx = NULL;
+
+	if (ctx->failed)
+		ret = -1;
+	else if (ctx->bytes_used != 0 || ctx->count_used != 0 ||
+		 ctx->recalculate) {
+		roots = array_get(&ctx->quota->roots, &count);
+		for (i = 0; i < count; i++) {
+			if (roots[i]->backend.v.update(roots[i], ctx) < 0)
+				ret = -1;
+		}
+	}
+
+	i_free(ctx);
+	return ret;
+}
+
+void quota_transaction_rollback(struct quota_transaction_context **_ctx)
+{
+	struct quota_transaction_context *ctx = *_ctx;
+
+	*_ctx = NULL;
+	i_free(ctx);
+}
+
+static int quota_transaction_set_limits(struct quota_transaction_context *ctx)
+{
+	struct quota_root *const *roots;
+	const char *mailbox_name;
+	unsigned int i, count;
+	uint64_t current, limit, left;
+	int ret;
+
+	ctx->limits_set = TRUE;
+	mailbox_name = mailbox_get_name(ctx->box);
 
 	/* find the lowest quota limits from all roots and use them */
-	roots = array_get(&quota->roots, &count);
+	roots = array_get(&ctx->quota->roots, &count);
 	for (i = 0; i < count; i++) {
 		ret = quota_get_resource(roots[i], mailbox_name,
 					 QUOTA_NAME_STORAGE_BYTES,
 					 &current, &limit);
 		if (ret > 0) {
+			current += ctx->bytes_used;
 			left = limit < current ? 0 : limit - current;
 			if (ctx->bytes_left > left)
 				ctx->bytes_left = left;
 		} else if (ret < 0) {
 			ctx->failed = TRUE;
-			break;
+			return -1;
 		}
 		
 		ret = quota_get_resource(roots[i], mailbox_name,
 					 QUOTA_NAME_MESSAGES, &current, &limit);
 		if (ret > 0) {
+			current += ctx->count_used;
 			left = limit < current ? 0 : limit - current;
 			if (ctx->count_left > left)
 				ctx->count_left = left;
 		} else if (ret < 0) {
 			ctx->failed = TRUE;
-			break;
-		}
-	}
-	return ctx;
-}
-
-int quota_transaction_commit(struct quota_transaction_context **_ctx)
-{
-	struct quota_transaction_context *ctx = *_ctx;
-	struct quota_root *const *roots;
-	unsigned int i, count;
-	int ret = 0;
-
-	*_ctx = NULL;
-
-	if (ctx->failed)
-		ret = -1;
-	else {
-		roots = array_get(&ctx->quota->roots, &count);
-		for (i = 0; i < count; i++) {
-			if (roots[i]->backend.v.update(roots[i], ctx) < 0)
-				ret = -1;
-		}
-	}
-
-	i_free(ctx);
-	return ret;
-}
-
-void quota_transaction_rollback(struct quota_transaction_context **_ctx)
-{
-	struct quota_transaction_context *ctx = *_ctx;
-
-	*_ctx = NULL;
-	i_free(ctx);
+			return -1;
+		}
+	}
+	return 0;
 }
 
 int quota_try_alloc(struct quota_transaction_context *ctx,
@@ -533,6 +537,13 @@ int quota_test_alloc(struct quota_transa
 int quota_test_alloc(struct quota_transaction_context *ctx,
 		     uoff_t size, bool *too_large_r)
 {
+	if (ctx->failed)
+		return -1;
+
+	if (!ctx->limits_set) {
+		if (quota_transaction_set_limits(ctx) < 0)
+			return -1;
+	}
 	return ctx->quota->test_alloc(ctx, size, too_large_r);
 }
 
@@ -544,8 +555,6 @@ static int quota_default_test_alloc(stru
 
 	*too_large_r = FALSE;
 
-	if (ctx->failed)
-		return -1;
 	if (ctx->count_left != 0 && ctx->bytes_left >= ctx->bytes_used + size)
 		return 1;
 


More information about the dovecot-cvs mailing list