]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Added support for multiple storages per namespace.
authorTimo Sirainen <tss@iki.fi>
Sat, 8 Jun 2013 21:46:06 +0000 (00:46 +0300)
committerTimo Sirainen <tss@iki.fi>
Sat, 8 Jun 2013 21:46:06 +0000 (00:46 +0300)
src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c
src/lib-storage/mail-namespace.c
src/lib-storage/mail-namespace.h
src/lib-storage/mail-storage.c
src/lib-storage/mail-storage.h

index 96542f4d9ce4f229029423a3905b5cc21841b606..bc1c1ffc9a0bb45bfa13fa32ae2fd39fb78d04f1 100644 (file)
@@ -541,7 +541,11 @@ rebuild_mailbox(struct mdbox_storage_rebuild_context *ctx,
 
        box = mailbox_alloc(ns->list, vname, MAILBOX_FLAG_READONLY |
                            MAILBOX_FLAG_IGNORE_ACLS);
-       i_assert(box->storage == &ctx->storage->storage.storage);
+       if (box->storage != &ctx->storage->storage.storage) {
+               /* the namespace has multiple storages. */
+               mailbox_free(&box);
+               return 0;
+       }
        if (mailbox_open(box) < 0) {
                error = mailbox_get_last_mail_error(box);
                i_error("Couldn't open mailbox '%s': %s",
index 2383a93b51a562efb175687681526effbeb0dcc2..a6ede7a6ddc2813efc1afdf0760af5bdb4603a15 100644 (file)
@@ -34,9 +34,9 @@ static struct mail_namespace_settings prefixless_ns_set;
 void mail_namespace_add_storage(struct mail_namespace *ns,
                                struct mail_storage *storage)
 {
-       /* currently we support only a single storage */
-       i_assert(ns->storage == NULL);
-       ns->storage = storage;
+       if (ns->storage == NULL)
+               ns->storage = storage;
+       array_append(&ns->all_storages, &storage, 1);
 
        if (storage->v.add_list != NULL)
                storage->v.add_list(storage, ns->list);
@@ -52,8 +52,11 @@ void mail_namespace_finish_list_init(struct mail_namespace *ns,
 
 static void mail_namespace_free(struct mail_namespace *ns)
 {
-       if (ns->storage != NULL)
-               mail_storage_unref(&ns->storage);
+       struct mail_storage **storagep;
+
+       array_foreach_modifiable(&ns->all_storages, storagep)
+               mail_storage_unref(storagep);
+       array_free(&ns->all_storages);
        if (ns->list != NULL)
                mailbox_list_destroy(&ns->list);
 
@@ -150,6 +153,7 @@ namespace_add(struct mail_user *user,
        ns->mail_set = mail_set;
        ns->prefix = i_strdup(ns_set->prefix);
        ns->special_use_mailboxes = namespace_has_special_use_mailboxes(ns_set);
+       i_array_init(&ns->all_storages, 2);
 
        if (ns->type == MAIL_NAMESPACE_TYPE_SHARED &&
            (strchr(ns->prefix, '%') != NULL ||
@@ -510,9 +514,12 @@ void mail_namespaces_set_storage_callbacks(struct mail_namespace *namespaces,
                                           void *context)
 {
        struct mail_namespace *ns;
+       struct mail_storage *const *storagep;
 
-       for (ns = namespaces; ns != NULL; ns = ns->next)
-               mail_storage_set_callbacks(ns->storage, callbacks, context);
+       for (ns = namespaces; ns != NULL; ns = ns->next) {
+               array_foreach(&ns->all_storages, storagep)
+                       mail_storage_set_callbacks(*storagep, callbacks, context);
+       }
 }
 
 void mail_namespace_ref(struct mail_namespace *ns)
@@ -558,7 +565,6 @@ void mail_namespace_destroy(struct mail_namespace *ns)
 struct mail_storage *
 mail_namespace_get_default_storage(struct mail_namespace *ns)
 {
-       /* currently we don't support more than one storage per namespace */
        return ns->storage;
 }
 
index 081bce960ea90763f11d5b42dcba830a7d5d821e..8580015793f0a07088efce23c735991e4322c44b 100644 (file)
@@ -67,8 +67,8 @@ struct mail_namespace {
 
        struct mail_user *user, *owner;
        struct mailbox_list *list;
-       /* FIXME: we should support multiple storages in one namespace */
-       struct mail_storage *storage;
+       struct mail_storage *storage; /* default storage */
+       ARRAY(struct mail_storage *) all_storages;
 
        const struct mail_namespace_settings *set, *unexpanded_set;
        const struct mail_storage_settings *mail_set;
index f52b3530419a4f5818233c20c78ad88dd7735918..78857027af77e3ace47ba05378e81a2d5317f395 100644 (file)
@@ -298,14 +298,15 @@ mail_storage_find(struct mail_user *user,
        return NULL;
 }
 
-int mail_storage_create(struct mail_namespace *ns, const char *driver,
-                       enum mail_storage_flags flags, const char **error_r)
+int mail_storage_create_full(struct mail_namespace *ns, const char *driver,
+                            const char *data, enum mail_storage_flags flags,
+                            struct mail_storage **storage_r,
+                            const char **error_r)
 {
        struct mail_storage *storage_class, *storage = NULL;
        struct mailbox_list *list;
        struct mailbox_list_settings list_set;
        enum mailbox_list_flags list_flags = 0;
-       const char *data = ns->set->location;
        const char *p;
 
        if ((flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) == 0 &&
@@ -369,6 +370,7 @@ int mail_storage_create(struct mail_namespace *ns, const char *driver,
                /* using an existing storage */
                storage->refcount++;
                mail_namespace_add_storage(ns, storage);
+               *storage_r = storage;
                return 0;
        }
 
@@ -392,10 +394,20 @@ int mail_storage_create(struct mail_namespace *ns, const char *driver,
        } T_END;
 
        DLLIST_PREPEND(&ns->user->storages, storage);
-        mail_namespace_add_storage(ns, storage);
+       mail_namespace_add_storage(ns, storage);
+       *storage_r = storage;
        return 0;
 }
 
+int mail_storage_create(struct mail_namespace *ns, const char *driver,
+                       enum mail_storage_flags flags, const char **error_r)
+{
+       struct mail_storage *storage;
+
+       return mail_storage_create_full(ns, driver, ns->set->location,
+                                       flags, &storage, error_r);
+}
+
 void mail_storage_unref(struct mail_storage **_storage)
 {
        struct mail_storage *storage = *_storage;
@@ -639,6 +651,8 @@ struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname,
        struct mailbox_list *new_list = list;
        struct mail_storage *storage;
        struct mailbox *box;
+       enum mail_error open_error = 0;
+       const char *errstr = NULL;
 
        i_assert(uni_utf8_str_is_valid(vname));
 
@@ -654,14 +668,19 @@ struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname,
                        vname = t_strconcat("INBOX", vname + 5, NULL);
        }
 
-       if (mailbox_list_get_storage(&new_list, vname, &storage) < 0) {
-               /* just use the default storage. FIXME: does this break? */
-               storage = mail_namespace_get_default_storage(list->ns);
-       }
-
        T_BEGIN {
+               if (mailbox_list_get_storage(&new_list, vname, &storage) < 0) {
+                       /* do a delayed failure at mailbox_open() */
+                       storage = mail_namespace_get_default_storage(list->ns);
+                       errstr = mailbox_list_get_last_error(new_list, &open_error);
+                       errstr = t_strdup(errstr);
+               }
+
                box = storage->v.mailbox_alloc(storage, new_list, vname, flags);
                box->set = mailbox_settings_find(storage->user, vname);
+               box->open_error = open_error;
+               if (open_error != 0)
+                       mail_storage_set_error(storage, open_error, errstr);
                hook_mailbox_allocated(box);
        } T_END;
 
index 0a5d5b40d5735c9d05578f5de58f592779b4bb9a..0a91572cc7f9a6051151e298e32dd495f3b2f8b2 100644 (file)
@@ -419,6 +419,10 @@ struct mail_storage *mail_storage_find_class(const char *name);
 int mail_storage_create(struct mail_namespace *ns, const char *driver,
                        enum mail_storage_flags flags, const char **error_r)
        ATTR_NULL(2);
+int mail_storage_create_full(struct mail_namespace *ns, const char *driver,
+                            const char *data, enum mail_storage_flags flags,
+                            struct mail_storage **storage_r,
+                            const char **error_r) ATTR_NULL(2);
 void mail_storage_unref(struct mail_storage **storage);
 
 /* Returns the mail storage settings. */