changeset 20106:09dab35fdb78

quota-count: Cache quota usage within the same ioloop run. This mainly means that when both STORAGE and MESSAGES quota is looked up we don't need to calculate them twice.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Fri, 29 Apr 2016 17:21:26 +0300
parents 0787b74eb38b
children e3063593181b
files src/plugins/quota/quota-count.c
diffstat 1 files changed, 29 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/plugins/quota/quota-count.c	Fri Apr 29 17:20:31 2016 +0300
+++ b/src/plugins/quota/quota-count.c	Fri Apr 29 17:21:26 2016 +0300
@@ -1,9 +1,17 @@
 /* Copyright (c) 2006-2016 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
+#include "ioloop.h"
 #include "mailbox-list-iter.h"
 #include "quota-private.h"
 
+struct count_quota_root {
+	struct quota_root root;
+
+	struct timeval cache_timeval;
+	uint64_t cached_bytes, cached_count;
+};
+
 struct quota_mailbox_iter {
 	struct quota_root *root;
 	struct mail_namespace *ns;
@@ -137,10 +145,19 @@
 
 int quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r)
 {
+	struct count_quota_root *croot = (struct count_quota_root *)root;
 	struct quota_mailbox_iter *iter;
 	const struct mailbox_info *info;
 	int ret = 0, ret2;
 
+	if (croot->cache_timeval.tv_usec == ioloop_timeval.tv_usec &&
+	    croot->cache_timeval.tv_sec == ioloop_timeval.tv_sec &&
+	    ioloop_timeval.tv_sec != 0) {
+		*bytes_r = croot->cached_bytes;
+		*count_r = croot->cached_count;
+		return 1;
+	}
+
 	*bytes_r = *count_r = 0;
 	if (root->recounting)
 		return 0;
@@ -159,12 +176,20 @@
 	}
 	quota_mailbox_iter_deinit(&iter);
 	root->recounting = FALSE;
+	if (ret > 0) {
+		croot->cache_timeval = ioloop_timeval;
+		croot->cached_bytes = *bytes_r;
+		croot->cached_count = *count_r;
+	}
 	return ret < 0 ? -1 : 0;
 }
 
 static struct quota_root *count_quota_alloc(void)
 {
-	return i_new(struct quota_root, 1);
+	struct count_quota_root *root;
+
+	root = i_new(struct count_quota_root, 1);
+	return &root->root;
 }
 
 static int count_quota_init(struct quota_root *root, const char *args,
@@ -273,6 +298,9 @@
 count_quota_update(struct quota_root *root,
 		   struct quota_transaction_context *ctx)
 {
+	struct count_quota_root *croot = (struct count_quota_root *)root;
+
+	croot->cache_timeval.tv_sec = 0;
 	if (ctx->recalculate) {
 		if (quota_count_recalculate(root) < 0)
 			return -1;