From: Timo Sirainen Date: Sat, 8 Jun 2013 21:46:06 +0000 (+0300) Subject: lib-storage: Added support for multiple storages per namespace. X-Git-Tag: 2.2.3~43 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=47ede56f4e6eebfe631a1f0febf74d7adcdbcd00;p=thirdparty%2Fdovecot%2Fcore.git lib-storage: Added support for multiple storages per namespace. --- diff --git a/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c b/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c index 96542f4d9c..bc1c1ffc9a 100644 --- a/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c +++ b/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c @@ -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", diff --git a/src/lib-storage/mail-namespace.c b/src/lib-storage/mail-namespace.c index 2383a93b51..a6ede7a6dd 100644 --- a/src/lib-storage/mail-namespace.c +++ b/src/lib-storage/mail-namespace.c @@ -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; } diff --git a/src/lib-storage/mail-namespace.h b/src/lib-storage/mail-namespace.h index 081bce960e..8580015793 100644 --- a/src/lib-storage/mail-namespace.h +++ b/src/lib-storage/mail-namespace.h @@ -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; diff --git a/src/lib-storage/mail-storage.c b/src/lib-storage/mail-storage.c index f52b353041..78857027af 100644 --- a/src/lib-storage/mail-storage.c +++ b/src/lib-storage/mail-storage.c @@ -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; diff --git a/src/lib-storage/mail-storage.h b/src/lib-storage/mail-storage.h index 0a5d5b40d5..0a91572cc7 100644 --- a/src/lib-storage/mail-storage.h +++ b/src/lib-storage/mail-storage.h @@ -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. */