doveadm-expire.c revision 20e04227229970d148801c507946666e2a9bd838
/* Copyright (c) 2005-2016 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "module-dir.h"
#include "str.h"
#include "hash.h"
#include "dict.h"
#include "imap-match.h"
#include "expire-set.h"
#include "mail-search.h"
#include "doveadm-settings.h"
#include "doveadm-mail.h"
#define DOVEADM_EXPIRE_MAIL_CMD_CONTEXT(obj) \
enum expire_user_state {
};
struct expire_query {
const char *mailbox;
struct imap_match_glob *glob;
};
struct doveadm_expire_mail_cmd_context {
struct dict_transaction_context *trans;
struct dict_iterate_context *iter;
/* username => enum expire_user_state */
HASH_TABLE(char *, void *) user_states;
bool delete_nonexistent_users;
};
const char *doveadm_expire_plugin_version = DOVECOT_ABI_VERSION;
void doveadm_expire_plugin_deinit(void);
static bool
{
const struct expire_query *query;
continue;
return TRUE;
} else {
return TRUE;
}
}
return FALSE;
}
static int
const char **username_r)
{
struct doveadm_expire_mail_cmd_context *ectx =
enum expire_user_state state;
char *orig_username;
void *value;
/* dict_key = DICT_EXPIRE_PREFIX<user>/<mailbox> */
/* invalid record, ignore */
return -1;
}
&orig_username, &value)) {
/* user no longer exists, delete the record */
return -1;
}
switch (state) {
i_unreached();
case EXPIRE_USER_STATE_EXISTS:
break;
case EXPIRE_USER_STATE_SEEN:
/* seen this user already, skip the record */
return 0;
}
oldest_savedate)) {
/* this mailbox doesn't have any matching messages */
return 0;
}
return 1;
}
static int
const char **username_r)
{
struct doveadm_expire_mail_cmd_context *ectx =
unsigned long oldest_savedate;
int ret;
/* invalid record */
continue;
}
if (doveadm_debug) {
i_debug("expire: Stopping iteration on key %s "
(long)ectx->oldest_before_time);
}
break;
}
T_BEGIN {
} T_END;
if (ret > 0)
return TRUE;
/* user has been deleted */
}
}
/* finished */
i_error("Dictionary iteration failed");
return -1;
}
return 0;
}
static const char *const *doveadm_expire_get_patterns(void)
{
const char *str;
unsigned int i;
i_unreached();
}
}
static bool
const struct mail_search_arg *args,
struct expire_query query)
{
struct doveadm_expire_mail_cmd_context *ectx =
const struct mail_search_arg *arg;
unsigned int query_count;
case SEARCH_MAILBOX_GLOB:
TRUE, '/');
/* fall through */
case SEARCH_MAILBOX:
/* require mailbox to be in expire patterns */
break;
default:
/* there are something else besides mailboxes,
can't optimize this. */
return FALSE;
}
}
}
static bool
const struct mail_search_arg *args)
{
struct doveadm_expire_mail_cmd_context *ectx =
const struct mail_search_arg *arg;
struct expire_query query;
case SEARCH_OR:
break;
case SEARCH_MAILBOX_GLOB:
TRUE, '/');
/* fall through */
case SEARCH_MAILBOX:
/* require mailbox to be in expire patterns */
break;
case SEARCH_BEFORE:
break;
MAIL_SEARCH_ARG_FLAG_USE_TZ) == 0)
break;
break;
default:
break;
}
}
/* no SAVEDBEFORE, can't optimize */
return FALSE;
}
/* one mailbox */
return TRUE;
}
/* no MAILBOX, but check if one of the ORs lists mailboxes */
if (!have_or)
return FALSE;
query))
return TRUE;
}
return FALSE;
}
static time_t
const struct mail_search_arg *args)
{
const struct mail_search_arg *arg;
/* all of the subqueries must have mailbox and savedbefore */
return FALSE;
return FALSE;
}
return TRUE;
}
{
struct doveadm_expire_mail_cmd_context *ectx =
struct expire_set *set;
const struct expire_query *queries;
unsigned int i, count;
/* we support two kinds of queries:
1) mailbox-pattern savedbefore <stamp> ...
2) or 2*(mailbox-pattern savedbefore <stamp> ...)
mailbox-pattern can be:
a) mailbox <name>
b) or 2*(mailbox <name>)
*/
if (doveadm_debug)
i_debug("expire: Couldn't optimize search query");
return FALSE;
}
/* make sure all mailboxes match expire patterns */
for (i = 0; i < count; i++) {
if (doveadm_debug) {
i_debug("expire: Couldn't optimize search query: "
"mailbox %s not in expire database",
}
break;
}
}
return i == count;
}
{
struct doveadm_expire_mail_cmd_context *ectx =
i_error("expire: Dictionary iteration failed");
}
i_error("expire: Dictionary commit failed");
}
{
struct doveadm_expire_mail_cmd_context *ectx;
struct dict_settings dict_set;
const struct expire_query *query;
char *username_dup;
enum expire_user_state state;
return;
if (expire_dict == NULL)
return;
/* doveadm proxying uses expire database only locally. the remote
doveadm handles each user one at a time (even though
iterate_single_user=FALSE) */
if (doveadm_debug) {
i_debug("expire: Iterating only a single user, "
"ignoring expire database");
}
return;
}
/* we can potentially optimize this query. see if the search args
are valid for optimization. */
if (!doveadm_expire_analyze_query(ctx))
return;
if (doveadm_debug)
i_debug("expire: Searching only users listed in expire database");
i_error("dict_init(%s) failed, not using it: %s",
expire_dict, error);
return;
}
}
}
}
{
}
void doveadm_expire_plugin_deinit(void)
{
}