dovecot-1.1: Added wildcard support to expire plugin. Added a ne...

dovecot at dovecot.org dovecot at dovecot.org
Tue Mar 4 06:28:08 EET 2008


details:   http://hg.dovecot.org/dovecot-1.1/rev/969656b58e7f
changeset: 7335:969656b58e7f
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Mar 04 06:26:24 2008 +0200
description:
Added wildcard support to expire plugin. Added a new expire_altmove setting
which moves mails to alt directory with dbox instead of expunging them. Both
settings can be used simultaneously. Added --test parameter to expire-tool.
Fixed several bugs and did some optimizations.

diffstat:

5 files changed, 248 insertions(+), 142 deletions(-)
src/plugins/expire/Makefile.am     |    1 
src/plugins/expire/expire-env.c    |   83 ++++++++++++++---
src/plugins/expire/expire-env.h    |   14 +-
src/plugins/expire/expire-plugin.c |  120 ++++++++++---------------
src/plugins/expire/expire-tool.c   |  172 ++++++++++++++++++++++++++----------

diffs (truncated from 705 to 300 lines):

diff -r ae8180a4febd -r 969656b58e7f src/plugins/expire/Makefile.am
--- a/src/plugins/expire/Makefile.am	Tue Mar 04 06:24:44 2008 +0200
+++ b/src/plugins/expire/Makefile.am	Tue Mar 04 06:26:24 2008 +0200
@@ -4,6 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/lib \
 	-I$(top_srcdir)/src/lib-dict \
 	-I$(top_srcdir)/src/lib-mail \
+	-I$(top_srcdir)/src/lib-imap \
 	-I$(top_srcdir)/src/lib-index \
 	-I$(top_srcdir)/src/lib-storage \
 	-I$(top_srcdir)/src/lib-storage/index \
diff -r ae8180a4febd -r 969656b58e7f src/plugins/expire/expire-env.c
--- a/src/plugins/expire/expire-env.c	Tue Mar 04 06:24:44 2008 +0200
+++ b/src/plugins/expire/expire-env.c	Tue Mar 04 06:26:24 2008 +0200
@@ -2,42 +2,70 @@
 
 #include "lib.h"
 #include "array.h"
+#include "imap-match.h"
 #include "expire-env.h"
 
 #include <stdlib.h>
+
+enum expire_type {
+	EXPIRE_TYPE_EXPUNGE,
+	EXPIRE_TYPE_ALTMOVE
+};
+
+struct expire_box {
+	const char *pattern;
+	struct imap_match_glob *glob;
+
+	enum expire_type type;
+	unsigned int expire_secs;
+};
 
 struct expire_env {
 	pool_t pool;
 	ARRAY_DEFINE(expire_boxes, struct expire_box);
 };
 
-struct expire_env *expire_env_init(const char *str)
+static void expire_env_parse(struct expire_env *env, const char *str,
+			     enum expire_type type)
 {
-	struct expire_env *env;
 	struct expire_box box;
-	pool_t pool;
 	char *const *names;
 	unsigned int len;
 
-	pool = pool_alloconly_create("Expire pool", 512);
-	env = p_new(pool, struct expire_env, 1);
-	env->pool = pool;
+	if (str == NULL)
+		return;
 
-	names = p_strsplit(pool, str, " ");
+	names = p_strsplit(env->pool, str, " ");
 	len = str_array_length((const char *const *)names);
 
-	p_array_init(&env->expire_boxes, pool, len / 2);
+	p_array_init(&env->expire_boxes, env->pool, len / 2);
 	for (; *names != NULL; names += 2) {
 		if (names[1] == NULL) {
 			i_fatal("expire: Missing expire days for mailbox '%s'",
 				*names);
 		}
 
-		box.name = *names;
-		box.expire_secs = strtoul(names[1], NULL, 10) * 3600 * 24;
+		box.pattern = *names;
+		/* FIXME: hardcoded separator isn't very good */
+		box.glob = imap_match_init(env->pool, box.pattern, TRUE, '/');
+		box.type = type;
+		box.expire_secs = strtoul(names[1], NULL, 10)/* * 3600 * 24*/ * 10;//FIXME
+
 		array_append(&env->expire_boxes, &box, 1);
 	}
+}
 
+struct expire_env *expire_env_init(const char *expunges, const char *altmoves)
+{
+	struct expire_env *env;
+	pool_t pool;
+
+	pool = pool_alloconly_create("Expire pool", 512);
+	env = p_new(pool, struct expire_env, 1);
+	env->pool = pool;
+
+	expire_env_parse(env, expunges, EXPIRE_TYPE_EXPUNGE);
+	expire_env_parse(env, altmoves, EXPIRE_TYPE_ALTMOVE);
 	return env;
 }
 
@@ -46,16 +74,41 @@ void expire_env_deinit(struct expire_env
 	pool_unref(&env->pool);
 }
 
-const struct expire_box *expire_box_find(struct expire_env *env,
-					 const char *name)
+bool expire_box_find(struct expire_env *env, const char *name,
+		     unsigned int *expunge_secs_r,
+		     unsigned int *altmove_secs_r)
 {
 	const struct expire_box *expire_boxes;
 	unsigned int i, count;
+	unsigned int secs, expunge_min = 0, altmove_min = 0;
 
 	expire_boxes = array_get(&env->expire_boxes, &count);
 	for (i = 0; i < count; i++) {
-		if (strcmp(name, expire_boxes[i].name) == 0)
-			return &expire_boxes[i];
+		if (imap_match(expire_boxes[i].glob, name) == IMAP_MATCH_YES) {
+			secs = expire_boxes[i].expire_secs;
+			i_assert(secs > 0);
+
+			switch (expire_boxes[i].type) {
+			case EXPIRE_TYPE_EXPUNGE:
+				if (expunge_min == 0 || expunge_min > secs)
+					expunge_min = secs;
+				break;
+			case EXPIRE_TYPE_ALTMOVE:
+				if (altmove_min == 0 || altmove_min > secs)
+					altmove_min = secs;
+				break;
+			}
+		}
 	}
-	return NULL;
+	*expunge_secs_r = expunge_min;
+	*altmove_secs_r = altmove_min;
+	return expunge_min > 0 || altmove_min > 0;
 }
+
+unsigned int expire_box_find_min_secs(struct expire_env *env, const char *name)
+{
+	unsigned int secs1, secs2;
+
+	(void)expire_box_find(env, name, &secs1, &secs2);
+	return secs1 < secs2 && secs1 != 0 ? secs1 : secs2;
+}
diff -r ae8180a4febd -r 969656b58e7f src/plugins/expire/expire-env.h
--- a/src/plugins/expire/expire-env.h	Tue Mar 04 06:24:44 2008 +0200
+++ b/src/plugins/expire/expire-env.h	Tue Mar 04 06:26:24 2008 +0200
@@ -3,15 +3,13 @@
 
 struct expire_env;
 
-struct expire_box {
-	const char *name;
-	time_t expire_secs;
-};
-
-struct expire_env *expire_env_init(const char *str);
+struct expire_env *expire_env_init(const char *expunges, const char *altmoves);
 void expire_env_deinit(struct expire_env *env);
 
-const struct expire_box *expire_box_find(struct expire_env *env,
-					 const char *name);
+bool expire_box_find(struct expire_env *env, const char *name,
+		     unsigned int *expunge_secs_r,
+		     unsigned int *altmove_secs_r);
+
+unsigned int expire_box_find_min_secs(struct expire_env *env, const char *name);
 
 #endif
diff -r ae8180a4febd -r 969656b58e7f src/plugins/expire/expire-plugin.c
--- a/src/plugins/expire/expire-plugin.c	Tue Mar 04 06:24:44 2008 +0200
+++ b/src/plugins/expire/expire-plugin.c	Tue Mar 04 06:26:24 2008 +0200
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "ioloop.h"
 #include "array.h"
+#include "str.h"
 #include "dict.h"
 #include "mail-namespace.h"
 #include "index-mail.h"
@@ -33,9 +34,7 @@ struct expire_transaction_context {
 struct expire_transaction_context {
 	union mailbox_transaction_module_context module_ctx;
 
-	struct mail *mail;
-	time_t first_save_time;
-
+	unsigned int saves:1;
 	unsigned int first_expunged:1;
 };
 
@@ -56,7 +55,6 @@ expire_mailbox_transaction_begin(struct 
 
 	t = xpr_box->module_ctx.super.transaction_begin(box, flags);
 	xt = i_new(struct expire_transaction_context, 1);
-	xt->mail = mail_alloc(t, 0, NULL);
 
 	MODULE_CONTEXT_SET(t, expire_storage_module, xt);
 	return t;
@@ -67,21 +65,26 @@ static void first_nonexpunged_timestamp(
 {
 	struct index_transaction_context *t =
 		(struct index_transaction_context *)_t;
-	struct expire_transaction_context *xt = EXPIRE_CONTEXT(_t);
 	struct mail_index_view *view = t->trans_view;
 	const struct mail_index_header *hdr;
+	struct mail *mail;
 	uint32_t seq;
+
+	mail = mail_alloc(_t, 0, NULL);
 
 	/* find the first non-expunged mail. we're here because the first
 	   mail was expunged, so don't bother checking it. */
 	hdr = mail_index_get_header(view);
 	for (seq = 2; seq <= hdr->messages_count; seq++) {
 		if (!mail_index_is_expunged(view, seq)) {
-			mail_set_seq(xt->mail, seq);
-			if (mail_get_save_date(xt->mail, stamp_r) == 0)
+			mail_set_seq(mail, seq);
+			if (mail_get_save_date(mail, stamp_r) == 0) {
+				mail_free(&mail);
 				return;
+			}
 		}
 	}
+	mail_free(&mail);
 
 	/* everything expunged */
 	*stamp_r = 0;
@@ -106,7 +109,6 @@ expire_mailbox_transaction_commit(struct
 		update_dict = TRUE;
 	}
 
-	mail_free(&xt->mail);
 	if (xpr_box->module_ctx.super.
 	    	transaction_commit(t, uid_validity_r,
 				   first_saved_uid_r, last_saved_uid_r) < 0) {
@@ -114,27 +116,33 @@ expire_mailbox_transaction_commit(struct
 		return -1;
 	}
 
-	T_BEGIN {
+	if (xt->first_expunged || xt->saves) T_BEGIN {
 		const char *key, *value;
 
 		key = t_strconcat(DICT_PATH_SHARED, expire.username, "/",
 				  mailbox_name, NULL);
-		if (!xt->first_expunged) {
+		if (!xt->first_expunged && xt->saves) {
 			/* saved new mails. dict needs to be updated only if
 			   this is the first mail in the database */
 			ret = dict_lookup(expire.db, pool_datastack_create(),
 					  key, &value);
 			update_dict = ret == 0 || strtoul(value, NULL, 10) == 0;
-			new_stamp = xt->first_save_time;
+			/* may not be exactly the first message's save time
+			   but a few second difference doesn't matter */
+			new_stamp = ioloop_time;
 		}
 
 		if (update_dict) {
 			struct dict_transaction_context *dctx;
 
-			new_stamp += xpr_box->expire_secs;
-
 			dctx = dict_transaction_begin(expire.db);
-			dict_set(dctx, key, dec2str(new_stamp));
+			if (new_stamp == 0) {
+				/* everything expunged */
+				dict_unset(dctx, key);
+			} else {
+				new_stamp += xpr_box->expire_secs;
+				dict_set(dctx, key, dec2str(new_stamp));
+			}
 			dict_transaction_commit(dctx);
 		}
 	} T_END;
@@ -148,8 +156,6 @@ expire_mailbox_transaction_rollback(stru
 	struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(t->box);
 	struct expire_transaction_context *xt = EXPIRE_CONTEXT(t);
 
-	mail_free(&xt->mail);
-
 	xpr_box->module_ctx.super.transaction_rollback(t);
 	i_free(xt);
 }
@@ -190,41 +196,14 @@ expire_mail_alloc(struct mailbox_transac
 	return _mail;
 }
 
-static void
-mail_set_save_time(struct mailbox_transaction_context *t, uint32_t seq)
-{
-	struct expire_transaction_context *xt = EXPIRE_CONTEXT(t);
-	struct index_transaction_context *it =
-		(struct index_transaction_context *)t;
-
-	if (xt->first_save_time == 0)
-		xt->first_save_time = ioloop_time;
-
-	mail_cache_add(it->cache_trans, seq, MAIL_CACHE_SAVE_DATE,
-		       &ioloop_time, sizeof(ioloop_time));


More information about the dovecot-cvs mailing list