Mercurial > dovecot > core-2.2
changeset 9563:1cf278c2fd63 HEAD
expire: Support per-user expire configuration.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 07 Jul 2009 14:19:05 -0400 |
parents | 90f8e2d091b5 |
children | 279af9682cd6 |
files | src/plugins/expire/expire-env.c src/plugins/expire/expire-env.h src/plugins/expire/expire-plugin.c src/plugins/expire/expire-tool.c |
diffstat | 4 files changed, 106 insertions(+), 74 deletions(-) [+] |
line wrap: on
line diff
--- a/src/plugins/expire/expire-env.c Tue Jul 07 13:25:01 2009 -0400 +++ b/src/plugins/expire/expire-env.c Tue Jul 07 14:19:05 2009 -0400 @@ -3,6 +3,7 @@ #include "lib.h" #include "array.h" #include "imap-match.h" +#include "mail-namespace.h" #include "expire-env.h" #include <stdlib.h> @@ -25,11 +26,14 @@ ARRAY_DEFINE(expire_boxes, struct expire_box); }; -static void expire_env_parse(struct expire_env *env, const char *str, - enum expire_type type) +static void +expire_env_parse(struct expire_env *env, struct mail_namespace *namespaces, + const char *str, enum expire_type type) { struct expire_box box; + struct mail_namespace *ns; char *const *names; + const char *ns_name; unsigned int len; if (str == NULL) @@ -46,8 +50,15 @@ } box.pattern = *names; - /* FIXME: hardcoded separator isn't very good */ - box.glob = imap_match_init(env->pool, box.pattern, TRUE, '/'); + ns_name = *names; + ns = mail_namespace_find(namespaces, &ns_name); + if (ns == NULL && *box.pattern != '*') { + i_warning("expire: No namespace found for mailbox: %s", + box.pattern); + } + + box.glob = imap_match_init(env->pool, box.pattern, TRUE, + ns == NULL ? '/' : ns->sep); box.type = type; box.expire_secs = strtoul(names[1], NULL, 10) * 3600 * 24; @@ -55,7 +66,8 @@ } } -struct expire_env *expire_env_init(const char *expunges, const char *altmoves) +struct expire_env *expire_env_init(struct mail_namespace *namespaces, + const char *expunges, const char *altmoves) { struct expire_env *env; pool_t pool; @@ -64,13 +76,16 @@ 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); + expire_env_parse(env, namespaces, expunges, EXPIRE_TYPE_EXPUNGE); + expire_env_parse(env, namespaces, altmoves, EXPIRE_TYPE_ALTMOVE); return env; } -void expire_env_deinit(struct expire_env *env) +void expire_env_deinit(struct expire_env **_env) { + struct expire_env *env = *_env; + + *_env = NULL; pool_unref(&env->pool); }
--- a/src/plugins/expire/expire-env.h Tue Jul 07 13:25:01 2009 -0400 +++ b/src/plugins/expire/expire-env.h Tue Jul 07 14:19:05 2009 -0400 @@ -4,9 +4,11 @@ #define DICT_EXPIRE_PREFIX DICT_PATH_SHARED"expire/" struct expire_env; +struct mail_namespace; -struct expire_env *expire_env_init(const char *expunges, const char *altmoves); -void expire_env_deinit(struct expire_env *env); +struct expire_env *expire_env_init(struct mail_namespace *namespaces, + const char *expunges, const char *altmoves); +void expire_env_deinit(struct expire_env **env); bool expire_box_find(struct expire_env *env, const char *name, unsigned int *expunge_secs_r,
--- a/src/plugins/expire/expire-plugin.c Tue Jul 07 13:25:01 2009 -0400 +++ b/src/plugins/expire/expire-plugin.c Tue Jul 07 14:19:05 2009 -0400 @@ -44,7 +44,7 @@ const char *expire_plugin_version = PACKAGE_VERSION; static void (*next_hook_mailbox_allocated)(struct mailbox *box); -static void (*next_hook_mail_user_created)(struct mail_user *user); +static void (*next_hook_mail_namespaces_created)(struct mail_namespace *ns); static MODULE_CONTEXT_DEFINE_INIT(expire_storage_module, &mail_storage_module_register); @@ -282,13 +282,14 @@ struct expire_mail_user *euser = EXPIRE_USER_CONTEXT(user); dict_deinit(&euser->db); - expire_env_deinit(euser->env); + expire_env_deinit(&euser->env); euser->module_ctx.super.deinit(user); } -static void expire_mail_user_created(struct mail_user *user) +static void expire_mail_namespaces_created(struct mail_namespace *ns) { + struct mail_user *user = ns->user; struct expire_mail_user *euser; const char *expunge_env, *altmove_env, *dict_uri, *service_name; @@ -310,7 +311,7 @@ euser->module_ctx.super = user->v; user->v.deinit = expire_mail_user_deinit; - euser->env = expire_env_init(expunge_env, altmove_env); + euser->env = expire_env_init(ns, expunge_env, altmove_env); /* we're using only shared dictionary, the username doesn't matter. */ euser->db = dict_init(dict_uri, DICT_DATA_TYPE_UINT32, "", @@ -321,8 +322,8 @@ MODULE_CONTEXT_SET(user, expire_mail_user_module, euser); } - if (next_hook_mail_user_created != NULL) - next_hook_mail_user_created(user); + if (next_hook_mail_namespaces_created != NULL) + next_hook_mail_namespaces_created(ns); } void expire_plugin_init(void) @@ -330,12 +331,12 @@ next_hook_mailbox_allocated = hook_mailbox_allocated; hook_mailbox_allocated = expire_mailbox_allocated; - next_hook_mail_user_created = hook_mail_user_created; - hook_mail_user_created = expire_mail_user_created; + next_hook_mail_namespaces_created = hook_mail_namespaces_created; + hook_mail_namespaces_created = expire_mail_namespaces_created; } void expire_plugin_deinit(void) { hook_mailbox_allocated = next_hook_mailbox_allocated; - hook_mail_user_created = next_hook_mail_user_created; + hook_mail_namespaces_created = next_hook_mail_namespaces_created; }
--- a/src/plugins/expire/expire-tool.c Tue Jul 07 13:25:01 2009 -0400 +++ b/src/plugins/expire/expire-tool.c Tue Jul 07 14:19:05 2009 -0400 @@ -20,17 +20,59 @@ pool_t multi_user_pool; struct mail_storage_service_multi_ctx *multi; struct mail_user *mail_user; + struct expire_env *env; bool testrun; }; +static int expire_init_user(struct expire_context *ctx, const char *user) +{ + struct mail_storage_service_input input; + struct mail_storage_service_multi_user *multi_user; + const char *expire, *expire_altmove, *errstr; + int ret; + + i_set_failure_prefix(t_strdup_printf("expire-tool(%s): ", user)); + + memset(&input, 0, sizeof(input)); + input.username = user; + + p_clear(ctx->multi_user_pool); + ret = mail_storage_service_multi_lookup(ctx->multi, &input, + ctx->multi_user_pool, + &multi_user, &errstr); + if (ret <= 0) { + if (ret < 0 || ctx->testrun) + i_error("User lookup failed: %s", errstr); + return ret; + } + ret = mail_storage_service_multi_next(ctx->multi, multi_user, + &ctx->mail_user, &errstr); + if (ret < 0) { + i_error("User init failed: %s", errstr); + return ret; + } + + expire = mail_user_set_plugin_getenv(ctx->mail_user->set, "expire"); + expire_altmove = mail_user_set_plugin_getenv(ctx->mail_user->set, + "expire_altmove"); + if (expire == NULL && expire_altmove == NULL) + i_fatal("expire and expire_altmove settings not set"); + + ctx->env = expire_env_init(ctx->mail_user->namespaces, + expire, expire_altmove); + return 1; +} + +static void expire_deinit_user(struct expire_context *ctx) +{ + mail_user_unref(&ctx->mail_user); + expire_env_deinit(&ctx->env); +} + static int mailbox_delete_old_mails(struct expire_context *ctx, const char *user, - const char *mailbox, - unsigned int expunge_secs, unsigned int altmove_secs, - time_t *oldest_r) + const char *mailbox, time_t *next_expire_r) { - struct mail_storage_service_input input; - struct mail_storage_service_multi_user *multi_user; struct mail_namespace *ns; struct mailbox *box; struct mail_search_context *search_ctx; @@ -38,37 +80,29 @@ struct mail_search_args *search_args; struct mail *mail; const char *ns_mailbox, *errstr; + unsigned int expunge_secs, altmove_secs; time_t now, save_time; enum mail_error error; enum mail_flags flags; int ret; - memset(&input, 0, sizeof(input)); - input.username = user; - - *oldest_r = 0; + *next_expire_r = 0; if (ctx->mail_user != NULL && strcmp(user, ctx->mail_user->username) != 0) - mail_user_unref(&ctx->mail_user); + expire_deinit_user(ctx); if (ctx->mail_user == NULL) { - i_set_failure_prefix(t_strdup_printf("expire-tool(%s): ", - user)); - p_clear(ctx->multi_user_pool); - ret = mail_storage_service_multi_lookup(ctx->multi, &input, - ctx->multi_user_pool, - &multi_user, &errstr); - if (ret <= 0) { - if (ret < 0 || ctx->testrun) - i_error("User lookup failed: %s", errstr); + if ((ret = expire_init_user(ctx, user)) <= 0) return ret; + } + + if (!expire_box_find(ctx->env, mailbox, &expunge_secs, &altmove_secs)) { + /* we're no longer expunging old messages from here */ + if (ctx->testrun) { + i_info("%s: mailbox '%s' removed from config", + user, mailbox); } - ret = mail_storage_service_multi_next(ctx->multi, multi_user, - &ctx->mail_user, &errstr); - if (ret < 0) { - i_error("User init failed: %s", errstr); - return ret; - } + return 0; } ns_mailbox = mailbox; @@ -140,7 +174,9 @@ } } else { /* first non-expired one. */ - *oldest_r = save_time; + *next_expire_r = save_time + + (altmove_secs != 0 ? + altmove_secs : expunge_secs); break; } } @@ -170,10 +206,8 @@ void **sets; struct dict_transaction_context *trans; struct dict_iterate_context *iter; - struct expire_env *env; - time_t oldest, expire_time; - unsigned int expunge_secs, altmove_secs; - const char *p, *key, *value, *expire, *expire_altmove, *expire_dict; + time_t next_expire, expire_time; + const char *p, *key, *value, *expire_dict; const char *userp = NULL, *mailbox; int ret; @@ -185,17 +219,11 @@ sets = master_service_settings_get_others(service); user_set = sets[0]; - expire = mail_user_set_plugin_getenv(user_set, "expire"); - expire_altmove = mail_user_set_plugin_getenv(user_set, "expire_altmove"); expire_dict = mail_user_set_plugin_getenv(user_set, "expire_dict"); - - if (expire == NULL && expire_altmove == NULL) - i_fatal("expire and expire_altmove settings not set"); if (expire_dict == NULL) i_fatal("expire_dict setting not set"); ctx.testrun = testrun; - env = expire_env_init(expire, expire_altmove); dict = dict_init(expire_dict, DICT_DATA_TYPE_UINT32, "", user_set->base_dir); if (dict == NULL) @@ -219,17 +247,6 @@ } mailbox = p + 1; - if (!expire_box_find(env, mailbox, - &expunge_secs, &altmove_secs)) { - /* we're no longer expunging old messages from here */ - if (!testrun) - dict_unset(trans, key); - else { - i_info("%s: mailbox '%s' removed from config", - userp, mailbox); - } - continue; - } expire_time = strtoul(value, NULL, 10); if (time(NULL) < expire_time) { /* this and the rest of the timestamps are in future, @@ -246,13 +263,12 @@ username = t_strdup_until(userp, p); ret = mailbox_delete_old_mails(&ctx, username, - mailbox, expunge_secs, - altmove_secs, &oldest); + mailbox, &next_expire); } T_END; if (ret < 0) { /* failed to update */ - } else if (oldest == 0) { + } else if (next_expire == 0) { /* no more messages or mailbox deleted */ if (!testrun) dict_unset(trans, key); @@ -261,10 +277,8 @@ } else { char new_value[MAX_INT_STRLEN]; - oldest += altmove_secs != 0 ? - altmove_secs : expunge_secs; i_snprintf(new_value, sizeof(new_value), "%lu", - (unsigned long)oldest); + (unsigned long)next_expire); if (strcmp(value, new_value) == 0) { /* no change */ } else if (!testrun) @@ -274,7 +288,7 @@ userp, value, t_strcut(ctime(&expire_time), '\n'), new_value, - t_strcut(ctime(&oldest), '\n')); + t_strcut(ctime(&next_expire), '\n')); } T_END; } } @@ -289,7 +303,7 @@ dict_deinit(&dict); if (ctx.mail_user != NULL) - mail_user_unref(&ctx.mail_user); + expire_deinit_user(&ctx); mail_storage_service_multi_deinit(&ctx.multi); pool_unref(&ctx.multi_user_pool); }