changeset 21190:263658888a0d

quota-clone: Flush quota-clone 10s after quota update if it's not already done This way a long-running IMAP session can't keep the quota-clone desynced for a long time.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Mon, 21 Nov 2016 14:05:42 +0200
parents 17b19f94a319
children 497740483ab4
files src/plugins/quota-clone/quota-clone-plugin.c
diffstat 1 files changed, 23 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/plugins/quota-clone/quota-clone-plugin.c	Mon Nov 21 14:02:11 2016 +0200
+++ b/src/plugins/quota-clone/quota-clone-plugin.c	Mon Nov 21 14:05:42 2016 +0200
@@ -2,11 +2,16 @@
 
 #include "lib.h"
 #include "module-context.h"
+#include "ioloop.h"
 #include "dict.h"
 #include "mail-storage-private.h"
 #include "quota.h"
 #include "quota-clone-plugin.h"
 
+/* If mailbox is kept open for this many milliseconds after quota update,
+   flush quota-clone. */
+#define QUOTA_CLONE_FLUSH_DELAY_MSECS (10*1000)
+
 #define DICT_QUOTA_CLONE_PATH DICT_PATH_PRIVATE"quota/"
 #define DICT_QUOTA_CLONE_BYTES_PATH DICT_QUOTA_CLONE_PATH"storage"
 #define DICT_QUOTA_CLONE_COUNT_PATH DICT_QUOTA_CLONE_PATH"messages"
@@ -29,6 +34,7 @@
 
 struct quota_clone_mailbox {
 	union mailbox_module_context module_ctx;
+	struct timeout *to_quota_flush;
 	bool quota_changed;
 };
 
@@ -82,6 +88,9 @@
 	struct quota_clone_user *quser =
 		QUOTA_CLONE_USER_CONTEXT(box->storage->user);
 
+	if (qbox->to_quota_flush != NULL)
+		timeout_remove(&qbox->to_quota_flush);
+
 	if (quser->quota_flushing) {
 		/* recursing back from quota recalculation */
 	} else if (qbox->quota_changed) {
@@ -91,12 +100,23 @@
 	}
 }
 
+static void quota_clone_changed(struct mailbox *box)
+{
+	struct quota_clone_mailbox *qbox = QUOTA_CLONE_CONTEXT(box);
+
+	qbox->quota_changed = TRUE;
+	if (qbox->to_quota_flush == NULL) {
+		qbox->to_quota_flush = timeout_add(QUOTA_CLONE_FLUSH_DELAY_MSECS,
+						   quota_clone_flush, box);
+	}
+}
+
 static int quota_clone_save_finish(struct mail_save_context *ctx)
 {
 	struct quota_clone_mailbox *qbox =
 		QUOTA_CLONE_CONTEXT(ctx->transaction->box);
 
-	qbox->quota_changed = TRUE;
+	quota_clone_changed(ctx->transaction->box);
 	return qbox->module_ctx.super.save_finish(ctx);
 }
 
@@ -106,7 +126,7 @@
 	struct quota_clone_mailbox *qbox =
 		QUOTA_CLONE_CONTEXT(ctx->transaction->box);
 
-	qbox->quota_changed = TRUE;
+	quota_clone_changed(ctx->transaction->box);
 	return qbox->module_ctx.super.copy(ctx, mail);
 }
 
@@ -120,7 +140,7 @@
 		qbox->module_ctx.super.sync_notify(box, uid, sync_type);
 
 	if (sync_type == MAILBOX_SYNC_TYPE_EXPUNGE)
-		qbox->quota_changed = TRUE;
+		quota_clone_changed(box);
 }
 
 static void quota_clone_mailbox_close(struct mailbox *box)