expire-plugin.c revision 31a574fda352ef4f71dbff9c30e15e4744e132c0
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2006-2012 Dovecot authors, see the included COPYING file */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mailbox_transaction_module_context module_ctx;
4462bd7b4c7ef3de006f060e155a90e5de7cae21Timo Sirainenconst char *expire_plugin_version = DOVECOT_VERSION;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(expire_storage_module,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(expire_mail_module, &mail_module_register);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(expire_mail_user_module,
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenexpire_mailbox_transaction_begin(struct mailbox *box,
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(box);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen t = xpr_box->module_ctx.super.transaction_begin(box, flags);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen xt = i_new(struct expire_transaction_context, 1);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET(t, expire_storage_module, xt);
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainenstatic void first_nonexpunged_timestamp(struct mailbox_transaction_context *t,
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* find the first non-expunged mail. we're here because the first
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen mail was expunged, so don't bother checking it. */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen for (seq = 2; seq <= hdr->messages_count; seq++) {
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen /* everything expunged */
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainenstatic void first_save_timestamp(struct mailbox *box, time_t *stamp_r)
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen /* find the first non-expunged mail. we're here because the first
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen mail was expunged, so don't bother checking it. */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenexpire_mailbox_transaction_commit(struct mailbox_transaction_context *t,
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen struct mail_transaction_commit_changes *changes_r)
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen struct mail_user *user = t->box->storage->user;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen struct expire_mail_user *euser = EXPIRE_USER_CONTEXT(user);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(t->box);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct expire_transaction_context *xt = EXPIRE_CONTEXT(t);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* first mail expunged. dict needs updating. */
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen /* everything was expunged, but also within this
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen transaction a new message was saved */
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen i_debug("expire: Expunging first message in %s, "
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen "updating timestamp to %ld",
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen if (xpr_box->module_ctx.super.transaction_commit(t, changes_r) < 0) {
d66be2bebfa96e7d3d20e2153f60e6e25dcc9a18Timo Sirainen /* transaction is freed now */
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen if (xt->first_expunged || xt->saves) T_BEGIN {
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen /* new_stamp is already set */
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen /* saved new mails. dict needs to be updated only if
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen this is the first mail in the database */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen ret = dict_lookup(euser->db, pool_datastack_create(),
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen /* first time saving here with expire enabled.
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen also handle lookup errors by just assuming
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen it didn't exist */
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen "assuming update is needed");
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen /* we're saving the first mail to this mailbox.
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen ioloop_time may not be exactly the first
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen message's save time, but a few seconds
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen difference doesn't matter */
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen /* already exists */
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen i_debug("expire: Saving first message to %s, "
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen "updating timestamp to %ld",
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenexpire_mailbox_transaction_rollback(struct mailbox_transaction_context *t)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(t->box);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct expire_transaction_context *xt = EXPIRE_CONTEXT(t);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen xpr_box->module_ctx.super.transaction_rollback(t);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic void expire_mail_expunge(struct mail *_mail)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mail_module_context *xpr_mail = EXPIRE_MAIL_CONTEXT(mail);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* first mail expunged, database needs to be updated */
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainenstatic void expire_mail_allocated(struct mail *_mail)
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(_mail->box);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen xpr_mail = p_new(mail->pool, union mail_module_context, 1);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET_SELF(mail, expire_mail_module, xpr_mail);
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainenstatic int expire_save_finish(struct mail_save_context *ctx)
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(ctx->transaction->box);
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen return xpr_box->module_ctx.super.save_finish(ctx);
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainenexpire_copy(struct mail_save_context *ctx, struct mail *mail)
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(ctx->transaction->box);
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen return xpr_box->module_ctx.super.copy(ctx, mail);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainenstatic void expire_mailbox_allocate_init(struct mailbox *box)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen xpr_box = p_new(box->pool, struct expire_mailbox, 1);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->transaction_begin = expire_mailbox_transaction_begin;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->transaction_commit = expire_mailbox_transaction_commit;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->transaction_rollback = expire_mailbox_transaction_rollback;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET(box, expire_storage_module, xpr_box);
56963ffad65b860c827553dfaf09fb766cb7e20eTimo Sirainenstatic void expire_mailbox_allocated(struct mailbox *box)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (euser != NULL && expire_set_lookup(euser->set, box->vname))
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenstatic void expire_mail_user_deinit(struct mail_user *user)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen struct expire_mail_user *euser = EXPIRE_USER_CONTEXT(user);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainenstatic const char *const *expire_get_patterns(struct mail_user *user)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen const char *str;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen unsigned int i;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen str = mail_user_set_plugin_getenv(user->set, "expire");
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen if (i_snprintf(set_name, sizeof(set_name), "expire%u", i) < 0)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen str = mail_user_set_plugin_getenv(user->set, set_name);
9514dbd41faad453406fc3a10aca791417a9ce75Timo Sirainenstatic void expire_mail_namespaces_created(struct mail_namespace *ns)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen dict_uri = mail_user_plugin_getenv(user, "expire_dict");
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (mail_user_plugin_getenv(user, "expire") == NULL) {
b87daa509bf5b306189282a9df795d094a6d7150Timo Sirainen i_debug("expire: No expire setting - plugin disabled");
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen i_error("expire plugin: expire_dict setting missing");
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen euser = p_new(user->pool, struct expire_mail_user, 1);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen euser->set = expire_set_init(expire_get_patterns(user));
783278c012551bc2f25f065a8d3ec1a3cfc0d296Timo Sirainen /* we're using only shared dictionary, the username
783278c012551bc2f25f065a8d3ec1a3cfc0d296Timo Sirainen doesn't matter. */
4073f0dbf3277f981a8fcee3b89ea15aaf380a7fTimo Sirainen euser->db = dict_init(dict_uri, DICT_DATA_TYPE_UINT32, "",
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen i_error("expire plugin: dict_init(%s) failed", dict_uri);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen MODULE_CONTEXT_SET(user, expire_mail_user_module, euser);
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainenstatic struct mail_storage_hooks expire_mail_storage_hooks = {
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen .mail_namespaces_created = expire_mail_namespaces_created,
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen .mailbox_allocated = expire_mailbox_allocated,
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen mail_storage_hooks_add(module, &expire_mail_storage_hooks);