]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
virtual plugin: Auto-close mailboxes by hooking into backend's mailbox_open()
authorTimo Sirainen <tss@iki.fi>
Thu, 24 Sep 2015 16:27:10 +0000 (19:27 +0300)
committerTimo Sirainen <tss@iki.fi>
Thu, 24 Sep 2015 16:27:10 +0000 (19:27 +0300)
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
src/plugins/virtual/virtual-plugin.c
src/plugins/virtual/virtual-storage.c
src/plugins/virtual/virtual-storage.h
src/plugins/virtual/virtual-sync.c

index bf4a5045bb32b777779c7b4e360e0dd15a3c77ae..d73646e3556fa58cc18d6045f8d9a281db5725a4 100644 (file)
@@ -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);
index ae27a7dbaabd9ea29b7b8bf2e2ff1feb9c5fee29..946328ab45e36fcbc498f632a3dbc370e30a7c80 100644 (file)
@@ -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);
 }
index 37d520d48027ae189a8e62050d32f947ccaa1b80..5c385d7615b5c168fa0f7343b6fc9685b63908b7 100644 (file)
@@ -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);
 }
 
index 10d0dd3884d13e033dac6a5f5df570438274e7a1..dfa16fc85926c1ec20398fccb775c1f01f35a5fd 100644 (file)
@@ -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
index 3f9baebe2a555ce7b61e7f0648f484d2d576bf5f..87b97acec57a423ddc63fb42936233a392e4ce01 100644 (file)
@@ -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 */