From dd37e2ff291fbebac1b94e8aad50f3bdf7531049 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Thu, 24 Sep 2015 19:27:10 +0300 Subject: [PATCH] virtual plugin: Auto-close mailboxes by hooking into backend's mailbox_open() This is a more reliable way of doing it. The earlier version had problems that all the backend mailboxes could be opened when doing a search on the virtual mailbox (for getting the GUID of the mailboxes). --- src/plugins/virtual/virtual-config.c | 1 + src/plugins/virtual/virtual-plugin.c | 6 ++++ src/plugins/virtual/virtual-storage.c | 40 +++++++++++++-------------- src/plugins/virtual/virtual-storage.h | 7 +++-- src/plugins/virtual/virtual-sync.c | 9 ++---- 5 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/plugins/virtual/virtual-config.c b/src/plugins/virtual/virtual-config.c index bf4a5045bb..d73646e355 100644 --- a/src/plugins/virtual/virtual-config.c +++ b/src/plugins/virtual/virtual-config.c @@ -138,6 +138,7 @@ virtual_config_parse_line(struct virtual_parse_context *ctx, const char *line, /* new mailbox. the search args are added to it later. */ bbox = p_new(ctx->pool, struct virtual_backend_box, 1); + bbox->virtual_mbox = ctx->mbox; if (strcasecmp(line, "INBOX") == 0) line = "INBOX"; bbox->name = p_strdup(ctx->pool, line); diff --git a/src/plugins/virtual/virtual-plugin.c b/src/plugins/virtual/virtual-plugin.c index ae27a7dbaa..946328ab45 100644 --- a/src/plugins/virtual/virtual-plugin.c +++ b/src/plugins/virtual/virtual-plugin.c @@ -7,12 +7,18 @@ const char *virtual_plugin_version = DOVECOT_ABI_VERSION; +static struct mail_storage_hooks acl_mail_storage_hooks = { + .mailbox_opened = virtual_mailbox_opened_hook +}; + void virtual_plugin_init(struct module *module ATTR_UNUSED) { mail_storage_class_register(&virtual_storage); + mail_storage_hooks_add(module, &acl_mail_storage_hooks); } void virtual_plugin_deinit(void) { mail_storage_class_unregister(&virtual_storage); + mail_storage_hooks_remove(&acl_mail_storage_hooks); } diff --git a/src/plugins/virtual/virtual-storage.c b/src/plugins/virtual/virtual-storage.c index 37d520d480..5c385d7615 100644 --- a/src/plugins/virtual/virtual-storage.c +++ b/src/plugins/virtual/virtual-storage.c @@ -182,6 +182,7 @@ static int virtual_backend_box_alloc(struct virtual_mailbox *mbox, mailbox = bbox->name; ns = mail_namespace_find(user->namespaces, mailbox); bbox->box = mailbox_alloc(ns->list, mailbox, flags); + MODULE_CONTEXT_SET(bbox->box, virtual_storage_module, bbox); if (mailbox_exists(bbox->box, TRUE, &existence) < 0) return virtual_backend_box_open_failed(mbox, bbox); @@ -322,10 +323,17 @@ virtual_backend_box_close_any_except(struct virtual_mailbox *mbox, return FALSE; } -void virtual_backend_box_opened(struct virtual_mailbox *mbox, - struct virtual_backend_box *bbox) +void virtual_mailbox_opened_hook(struct mailbox *box) { + struct virtual_backend_box *bbox = VIRTUAL_CONTEXT(box); + struct virtual_mailbox *mbox; + + if (bbox == NULL) { + /* not a backend for a virtual mailbox */ + return; + } i_assert(!bbox->open_tracked); + mbox = bbox->virtual_mbox; /* the backend mailbox was already opened. if we didn't get here from virtual_backend_box_open() we may need to close a mailbox */ @@ -351,16 +359,14 @@ int virtual_backend_box_open(struct virtual_mailbox *mbox, virtual_backend_box_close_any_except(mbox, bbox)) ; - if (mailbox_open(bbox->box) < 0) - return -1; - virtual_backend_box_opened(mbox, bbox); - return 0; + return mailbox_open(bbox->box); } void virtual_backend_box_close(struct virtual_mailbox *mbox, struct virtual_backend_box *bbox) { i_assert(bbox->box->opened); + i_assert(bbox->open_tracked); if (bbox->search_result != NULL) mailbox_search_result_free(&bbox->search_result); @@ -370,21 +376,13 @@ void virtual_backend_box_close(struct virtual_mailbox *mbox, mail_search_args_deinit(bbox->search_args); bbox->search_args_initialized = FALSE; } - if (bbox->open_tracked) { - i_assert(mbox->backends_open_count > 0); - mbox->backends_open_count--; - bbox->open_tracked = FALSE; - - DLLIST2_REMOVE_FULL(&mbox->open_backend_boxes_head, - &mbox->open_backend_boxes_tail, bbox, - prev_open, next_open); - } else { - /* mailbox can be leaked outside our code via - virtual_get_virtual_backend_boxes() and it could have - been opened there. FIXME: maybe we could hook into the - backend open/close functions to do the tracking and - auto-closing. */ - } + i_assert(mbox->backends_open_count > 0); + mbox->backends_open_count--; + bbox->open_tracked = FALSE; + + DLLIST2_REMOVE_FULL(&mbox->open_backend_boxes_head, + &mbox->open_backend_boxes_tail, bbox, + prev_open, next_open); mailbox_close(bbox->box); } diff --git a/src/plugins/virtual/virtual-storage.h b/src/plugins/virtual/virtual-storage.h index 10d0dd3884..dfa16fc859 100644 --- a/src/plugins/virtual/virtual-storage.h +++ b/src/plugins/virtual/virtual-storage.h @@ -62,6 +62,9 @@ struct virtual_backend_uidmap { }; struct virtual_backend_box { + union mailbox_module_context module_ctx; + struct virtual_mailbox *virtual_mbox; + /* linked list for virtual_mailbox->open_backend_boxes_{head,tail} */ struct virtual_backend_box *prev_open, *next_open; @@ -188,8 +191,6 @@ void virtual_backend_box_close(struct virtual_mailbox *mbox, struct virtual_backend_box *bbox); void virtual_backend_box_accessed(struct virtual_mailbox *mbox, struct virtual_backend_box *bbox); -void virtual_backend_box_opened(struct virtual_mailbox *mbox, - struct virtual_backend_box *bbox); void virtual_backend_box_sync_mail_unset(struct virtual_backend_box *bbox); struct mail_search_context * @@ -224,4 +225,6 @@ void virtual_save_free(struct mail_save_context *ctx); void virtual_box_copy_error(struct mailbox *dest, struct mailbox *src); +void virtual_mailbox_opened_hook(struct mailbox *box); + #endif diff --git a/src/plugins/virtual/virtual-sync.c b/src/plugins/virtual/virtual-sync.c index 3f9baebe2a..87b97acec5 100644 --- a/src/plugins/virtual/virtual-sync.c +++ b/src/plugins/virtual/virtual-sync.c @@ -1131,12 +1131,9 @@ static int virtual_sync_backend_box(struct virtual_sync_context *ctx, bbox->open_failed = FALSE; } - ret = mailbox_get_status(bbox->box, STATUS_UIDVALIDITY | - STATUS_UIDNEXT | STATUS_HIGHESTMODSEQ, - &status); - if (!bbox_index_opened && bbox->box->opened) - virtual_backend_box_opened(ctx->mbox, bbox); - if (ret < 0) { + if (mailbox_get_status(bbox->box, STATUS_UIDVALIDITY | + STATUS_UIDNEXT | STATUS_HIGHESTMODSEQ, + &status) < 0) { if (mailbox_get_last_mail_error(bbox->box) != MAIL_ERROR_NOTFOUND) return -1; /* mailbox was deleted */ -- 2.47.3