trash-plugin.c revision 00d58fcfe8191d6ce7efa801d289a5c0fe88d1ae
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (C) 2005 Timo Sirainen */
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen int priority; /* lower number = higher priority */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* temporarily set while cleaning: */
8fa41238067c854435884c459963fde6f8c6436bTimo Sirainenconst char *trash_plugin_version = PACKAGE_VERSION;
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainenstatic int (*trash_next_quota_test_alloc)(struct quota_transaction_context *,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* trash_boxes ordered by priority, highest first */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic ARRAY_DEFINE(trash_boxes, struct trash_mailbox);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ctx = mailbox_sync_init(box, MAILBOX_SYNC_FLAG_FULL_READ);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenstatic int trash_clean_mailbox_open(struct trash_mailbox *trash)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen trash->box = mailbox_open(trash->storage, trash->name, NULL,
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen trash->trans = mailbox_transaction_begin(trash->box, 0);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen trash->search_ctx = mailbox_search_init(trash->trans, NULL,
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen trash->mail = mail_alloc(trash->trans, MAIL_FETCH_PHYSICAL_SIZE |
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return mailbox_search_next(trash->search_ctx, trash->mail);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int trash_clean_mailbox_get_next(struct trash_mailbox *trash,
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen *received_time_r = mail_get_received_date(trash->mail);
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainenstatic void trash_find_storage(struct trash_mailbox *trash)
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen unsigned int i, count;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen storages = array_get("a_set->storages, &count);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen for (i = 0; i < count; i++) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (mail_namespace_update_name(storages[i]->ns, &trash->name)) {
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen i_fatal("trash: Namespace not found for mailbox '%s'", trash->name);
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainenstatic int trash_try_clean_mails(struct quota_transaction_context *ctx,
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen uint64_t size, size_expunged = 0, expunged_count = 0;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen trashes = array_get_modifiable(&trash_boxes, &count);
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen for (i = 0; i < count; ) {
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen /* expunge oldest mails first in all trash boxes with
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen same priority */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen for (j = i; j < count; j++) {
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen if (trashes[j].priority != trashes[i].priority)
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ret = trash_clean_mailbox_get_next(&trashes[j],
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen if (oldest == (time_t)-1 || received < oldest) {
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen size = mail_get_physical_size(trashes[oldest_idx].mail);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* maybe expunged already? */
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen if (mail_expunge(trashes[oldest_idx].mail) < 0)
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen /* find more mails from next priority's mailbox */
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen for (i = 0; i < count; i++) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen (void)mailbox_search_deinit(&trash->search_ctx);
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen (void)mailbox_transaction_commit(&trash->trans,
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen /* couldn't get enough space, don't expunge anything */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen ctx->bytes_used = ctx->bytes_used > (int64_t)size_expunged ?
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen ctx->count_used = ctx->count_used > (int64_t)expunged_count ?
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainentrash_quota_test_alloc(struct quota_transaction_context *ctx,
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen for (i = 0; ; i++) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ret = trash_next_quota_test_alloc(ctx, size, too_large_r);
6825360d446542046757b06064282301c4c6b27cTimo Sirainen /* trash_try_clean_mails() should have returned 0 if
6825360d446542046757b06064282301c4c6b27cTimo Sirainen it couldn't get enough space, but allow retrying
6825360d446542046757b06064282301c4c6b27cTimo Sirainen it a couple of times if there was some extra space
6825360d446542046757b06064282301c4c6b27cTimo Sirainen that was needed.. */
6825360d446542046757b06064282301c4c6b27cTimo Sirainen /* not enough space. try deleting some from mailbox. */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenstatic int trash_mailbox_priority_cmp(const void *p1, const void *p2)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const struct trash_mailbox *t1 = p1, *t2 = p2;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic int read_configuration(const char *path)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen unsigned int count;
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen p_array_init(&trash_boxes, config_pool, INIT_TRASH_MAILBOX_COUNT);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen input = i_stream_create_file(fd, default_pool, (size_t)-1, FALSE);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen while ((line = i_stream_read_next_line(input)) != NULL) {
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen /* <priority> <mailbox name> */
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen trash->priority = atoi(t_strdup_until(line, name));
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen trash = array_get_modifiable(&trash_boxes, &count);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen qsort(trash, count, sizeof(*trash), trash_mailbox_priority_cmp);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen const char *env;
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen i_error("trash plugin: quota plugin not initialized");
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen config_pool = pool_alloconly_create("trash config",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen trash_next_quota_test_alloc = quota_set->test_alloc;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen quota_set->test_alloc = trash_quota_test_alloc;