expire-plugin.c revision 71748cca1bacd74451fd228db5536828bdfeb190
/* Copyright (c) 2006-2016 Dovecot authors, see the included COPYING file */
/* There are several race conditions in this plugin, but they should be
happening pretty rarely and usually it's not a big problem if the results
are temporarily wrong. Fixing the races would likely be a lot of work,
so it's not really worth it. */
#include "lib.h"
#include "ioloop.h"
#include "array.h"
#include "str.h"
#include "master-service.h"
#include "dict.h"
#include "mail-namespace.h"
#include "index-mail.h"
#include "index-storage.h"
#include "expire-set.h"
#include "expire-plugin.h"
#define EXPIRE_CONTEXT(obj) \
#define EXPIRE_MAIL_CONTEXT(obj) \
#define EXPIRE_USER_CONTEXT(obj) \
struct expire_mail_index_header {
};
struct expire_mail_user {
struct expire_set *set;
bool expire_cache;
};
struct expire_mailbox {
union mailbox_module_context module_ctx;
};
struct expire_transaction_context {
unsigned int saves:1;
unsigned int first_expunged:1;
};
const char *expire_plugin_version = DOVECOT_ABI_VERSION;
static struct mailbox_transaction_context *
{
struct mailbox_transaction_context *t;
struct expire_transaction_context *xt;
return t;
}
{
struct mailbox_transaction_context *t;
const struct mail_index_header *hdr;
*stamp_r = ioloop_time;
t = mailbox_transaction_begin(box, 0);
/* find the first non-expunged mail. we're here because the first
mail was expunged, so don't bother checking it. */
if (hdr->messages_count > 0) {
}
(void)mailbox_transaction_commit(&t);
}
{
return xpr_box->expire_ext_id;
sizeof(struct expire_mail_index_header), 0, 0);
return xpr_box->expire_ext_id;
}
{
struct expire_mail_user *euser =
const struct expire_mail_index_header *hdr;
const void *data;
const char *value;
int ret;
/* default to ioloop_time for newly saved mails. it may not be exactly
the first message's save time, but a few seconds difference doesn't
matter */
if (euser->expire_cache) {
return 0;
/* preserve the original timestamp */
return 1;
}
/* cache doesn't exist yet */
}
if (ret <= 0) {
if (ret < 0)
return -1;
return 0;
}
}
static void
{
struct expire_mail_user *euser =
struct dict_transaction_context *dctx;
struct mail_index_transaction *trans;
struct expire_mail_index_header hdr;
if (dict_transaction_commit(&dctx) < 0)
i_error("expire: dict commit failed");
else if (euser->expire_cache) {
if (mail_index_transaction_commit(&trans) < 0)
i_error("expire: index transaction commit failed");
}
}
static void first_nonexpunged_timestamp(struct mailbox_transaction_context *t,
{
const struct mail_index_header *hdr;
/* find the first non-expunged mail. we're here because the first
mail was expunged, so don't bother checking it. */
break;
}
}
/* everything expunged */
*stamp_r = 0;
}
}
static int
struct mail_transaction_commit_changes *changes_r)
{
bool update_dict = FALSE;
int ret;
if (xt->first_expunged) {
/* first mail expunged. dict needs updating. */
/* everything was expunged, but also within this
transaction a new message was saved */
}
if (user->mail_debug) {
i_debug("expire: Expunging first message in %s, "
"updating timestamp to %ld",
}
update_dict = TRUE;
}
return -1;
}
/* transaction is freed now */
t = NULL;
const char *key;
if (xt->first_expunged) {
/* new_stamp is already set */
} else {
/* saved new mails. dict needs to be updated only if
this is the first mail in the database */
if (ret <= 0) {
/* first time saving here with expire enabled.
also handle lookup errors by just assuming
it didn't exist */
if (ret < 0) {
i_warning("expire: dict lookup failed, "
"assuming update is needed");
}
update_dict = TRUE;
} else {
/* already exists */
}
i_debug("expire: Saving first message to %s, "
"updating timestamp to %ld",
}
}
if (update_dict)
} T_END;
return 0;
}
static void
{
}
{
struct expire_transaction_context *xt =
/* first mail expunged, database needs to be updated */
}
}
{
union mail_module_context *xpr_mail;
return;
v->expunge = expire_mail_expunge;
}
{
struct expire_transaction_context *xt =
}
static int
{
struct expire_transaction_context *xt =
}
{
struct expire_mailbox *xpr_box;
v->copy = expire_copy;
}
{
struct expire_mail_user *euser =
}
{
}
{
const char *str;
unsigned int i;
i_unreached();
}
}
{
struct expire_mail_user *euser;
if (user->mail_debug)
i_debug("expire: No expire setting - plugin disabled");
return;
}
i_error("expire plugin: expire_dict setting missing");
return;
}
/* we're using only shared dictionary, the username doesn't matter. */
i_error("expire plugin: dict_init(%s) failed: %s",
return;
}
}
static struct mail_storage_hooks expire_mail_storage_hooks = {
};
{
}
void expire_plugin_deinit(void)
{
}