dovecot-2.1: expire: Only go through users listed by userdb iter...

dovecot at dovecot.org dovecot at dovecot.org
Sun Feb 12 04:58:28 EET 2012


details:   http://hg.dovecot.org/dovecot-2.1/rev/f889e25711a1
changeset: 14120:f889e25711a1
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Feb 12 04:58:17 2012 +0200
description:
expire: Only go through users listed by userdb iteration.
Delete dict rows for nonexistent users, unless
expire_keep_nonexistent_users=yes.

diffstat:

 src/plugins/expire/doveadm-expire.c |  73 ++++++++++++++++++++++++++----------
 1 files changed, 52 insertions(+), 21 deletions(-)

diffs (164 lines):

diff -r 845c3045f45c -r f889e25711a1 src/plugins/expire/doveadm-expire.c
--- a/src/plugins/expire/doveadm-expire.c	Sun Feb 12 04:18:50 2012 +0200
+++ b/src/plugins/expire/doveadm-expire.c	Sun Feb 12 04:58:17 2012 +0200
@@ -14,6 +14,12 @@
 #define DOVEADM_EXPIRE_MAIL_CMD_CONTEXT(obj) \
 	MODULE_CONTEXT(obj, doveadm_expire_mail_cmd_module)
 
+enum expire_user_state {
+	EXPIRE_USER_STATE_NONEXISTENT = 0,
+	EXPIRE_USER_STATE_EXISTS = 1,
+	EXPIRE_USER_STATE_SEEN = 2
+};
+
 struct expire_query {
 	const char *mailbox;
 	struct imap_match_glob *glob;
@@ -27,9 +33,10 @@
 	struct dict_transaction_context *trans;
 	struct dict_iterate_context *iter;
 
-	struct hash_table *seen_users;
+	struct hash_table *users;
 	ARRAY_DEFINE(queries, struct expire_query);
 	time_t oldest_before_time;
+	bool delete_nonexistent_users;
 };
 
 const char *doveadm_expire_plugin_version = DOVECOT_VERSION;
@@ -62,41 +69,51 @@
 	return FALSE;
 }
 
-static bool
+static int
 doveadm_expire_mail_want(struct doveadm_mail_cmd_context *ctx,
-			 const char *key, time_t oldest_savedate,
+			 const char *dict_key, time_t oldest_savedate,
 			 const char **username_r)
 {
 	struct doveadm_expire_mail_cmd_context *ectx =
 		DOVEADM_EXPIRE_MAIL_CMD_CONTEXT(ctx);
 	const char *username, *mailbox;
-	char *username_dup;
+	enum expire_user_state state;
+	void *key, *value;
 
-	/* key = DICT_EXPIRE_PREFIX<user>/<mailbox> */
-	username = key + strlen(DICT_EXPIRE_PREFIX);
+	/* dict_key = DICT_EXPIRE_PREFIX<user>/<mailbox> */
+	username = dict_key + strlen(DICT_EXPIRE_PREFIX);
 	mailbox = strchr(username, '/');
 	if (mailbox == NULL) {
 		/* invalid record, ignore */
-		i_error("expire: Invalid key: %s", key);
-		return FALSE;
+		i_error("expire: Invalid key: %s", dict_key);
+		return -1;
 	}
 	username = t_strdup_until(username, mailbox++);
 
-	if (hash_table_lookup(ectx->seen_users, username) != NULL) {
+	if (!hash_table_lookup_full(ectx->users, username, &key, &value)) {
+		/* user no longer exists, delete the record */
+		return -1;
+	}
+	state = POINTER_CAST_TO(value, enum expire_user_state);
+	switch (state) {
+	case EXPIRE_USER_STATE_NONEXISTENT:
+		i_unreached();
+	case EXPIRE_USER_STATE_EXISTS:
+		break;
+	case EXPIRE_USER_STATE_SEEN:
 		/* seen this user already, skip the record */
-		return FALSE;
+		return 0;
 	}
 
 	if (!doveadm_expire_mail_match_mailbox(ectx, mailbox,
 					       oldest_savedate)) {
 		/* this mailbox doesn't have any matching messages */
-		return FALSE;
+		return 0;
 	}
-	username_dup = p_strdup(ctx->pool, username);
-	hash_table_insert(ectx->seen_users, username_dup, username_dup);
-
-	*username_r = username_dup;
-	return TRUE;
+	hash_table_update(ectx->users, key,
+			  POINTER_CAST(EXPIRE_USER_STATE_SEEN));
+	*username_r = key;
+	return 1;
 }
 
 static int
@@ -107,7 +124,7 @@
 		DOVEADM_EXPIRE_MAIL_CMD_CONTEXT(ctx);
 	const char *key, *value;
 	unsigned long oldest_savedate;
-	bool ret;
+	int ret;
 
 	while (dict_iterate(ectx->iter, &key, &value)) {
 		if (str_to_ulong(value, &oldest_savedate) < 0) {
@@ -129,8 +146,12 @@
 						       oldest_savedate,
 						       username_r);
 		} T_END;
-		if (ret)
+		if (ret > 0)
 			return TRUE;
+		if (ret < 0 && ectx->delete_nonexistent_users) {
+			/* user has been deleted */
+			dict_unset(ectx->trans, key);
+		}
 	}
 
 	/* finished */
@@ -331,7 +352,7 @@
 	}
 	dict_transaction_commit(&ectx->trans);
 	dict_deinit(&ectx->dict);
-	hash_table_destroy(&ectx->seen_users);
+	hash_table_destroy(&ectx->users);
 
 	ectx->module_ctx.super.deinit(ctx);
 }
@@ -341,7 +362,8 @@
 	struct doveadm_expire_mail_cmd_context *ectx;
 	struct dict *dict;
 	const struct expire_query *query;
-	const char *expire_dict;
+	const char *expire_dict, *username, *value;
+	char *username_dup;
 
 	if (ctx->search_args == NULL)
 		return;
@@ -360,6 +382,9 @@
 
 	ectx = p_new(ctx->pool, struct doveadm_expire_mail_cmd_context, 1);
 	ectx->module_ctx.super = ctx->v;
+	value = doveadm_plugin_getenv("expire_keep_nonexistent_users");
+	ectx->delete_nonexistent_users =
+		value == NULL || strcmp(value, "yes") != 0;
 	MODULE_CONTEXT_SET(ctx, doveadm_expire_mail_cmd_module, ectx);
 
 	/* we can potentially optimize this query. see if the search args
@@ -387,9 +412,15 @@
 	ctx->v.deinit = doveadm_expire_mail_cmd_deinit;
 	ctx->v.get_next_user = doveadm_expire_mail_cmd_get_next_user;
 
-	ectx->seen_users =
+	ectx->users =
 		hash_table_create(default_pool, ctx->pool, 0,
 				  str_hash, (hash_cmp_callback_t *)strcmp);
+	while (mail_storage_service_all_next(ctx->storage_service, &username) > 0) {
+		username_dup = p_strdup(ctx->pool, username);
+		hash_table_insert(ectx->users, username_dup,
+				  POINTER_CAST(EXPIRE_USER_STATE_EXISTS));
+	}
+
 	ectx->dict = dict;
 	ectx->trans = dict_transaction_begin(dict);
 	ectx->iter = dict_iterate_init(dict, DICT_EXPIRE_PREFIX,


More information about the dovecot-cvs mailing list