]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Try to use cached mailbox settings
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 7 Mar 2025 10:27:06 +0000 (12:27 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Wed, 12 Mar 2025 13:01:57 +0000 (13:01 +0000)
src/lib-storage/mail-storage-private.h
src/lib-storage/mail-storage.c
src/lib-storage/mailbox-list-private.h
src/lib-storage/mailbox-list.c

index f93f9204c8c638a89466a33530e70f5a47f7bd24..eaeb2020138ddecf7a46200d6cac4a74ba27d506 100644 (file)
@@ -931,6 +931,12 @@ static inline const char *mailbox_name_sanitize(const char *name)
 struct event *
 mail_storage_mailbox_create_event(struct event *parent,
                                  struct mailbox_list *list, const char *vname);
+/* Try to get mailbox_settings for a mailbox. Returns 1 on success, -1 on
+   error, 0 if settings need to be merged and caller should be calling
+   settings_get() instead with the mailbox event. */
+int mailbox_name_try_get_settings(struct mailbox_list *list, const char *vname,
+                                 const struct mailbox_settings **set_r,
+                                 const char **error_r);
 
 /* for unit testing */
 int mailbox_verify_name(struct mailbox *box);
index b172440fec4e8f0945d81cf60281aca3ed5667cc..ca51ab5d13a44f592c4d961838ca3d4e55539811 100644 (file)
@@ -1048,6 +1048,55 @@ bool mail_storage_set_error_from_errno(struct mail_storage *storage)
        return TRUE;
 }
 
+static int
+mailbox_list_get_default_box_settings(struct mailbox_list *list,
+                                     const struct mailbox_settings **set_r,
+                                     const char **error_r)
+{
+       if (list->default_box_set == NULL) {
+               if (settings_get(list->event,
+                                &mailbox_setting_parser_info, 0,
+                                &list->default_box_set, error_r) < 0)
+                       return -1;
+       }
+       pool_ref(list->default_box_set->pool);
+       *set_r = list->default_box_set;
+       return 1;
+}
+
+int mailbox_name_try_get_settings(struct mailbox_list *list, const char *vname,
+                                 const struct mailbox_settings **set_r,
+                                 const char **error_r)
+{
+       if (array_is_empty(&list->ns->set->mailboxes))
+               return mailbox_list_get_default_box_settings(list, set_r, error_r);
+
+       const char *vname_without_prefix =
+               mailbox_get_name_without_prefix(list->ns, vname);
+       unsigned int i, count;
+       const struct mailbox_settings *set = NULL, *const *mailboxes =
+               array_get(&list->ns->set->parsed_mailboxes, &count);
+
+       for (i = 0; i < count; i++) {
+               if (!wildcard_match(vname_without_prefix, mailboxes[i]->name))
+                       continue;
+
+               if (set == NULL)
+                       set = mailboxes[i];
+               else {
+                       /* multiple mailbox named list filters match - need to
+                          lookup settings to get them merged. */
+                       return 0;
+               }
+       }
+       if (set == NULL)
+               return mailbox_list_get_default_box_settings(list, set_r, error_r);
+
+       pool_ref(set->pool);
+       *set_r = set;
+       return 1;
+}
+
 struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname,
                              enum mailbox_flags flags)
 {
@@ -1082,8 +1131,10 @@ struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname,
        }
 
        T_BEGIN {
-               const char *orig_vname = vname;
+               const char *error, *orig_vname = vname;
                enum mailbox_list_get_storage_flags storage_flags = 0;
+               int ret;
+
                if ((flags & MAILBOX_FLAG_SAVEONLY) != 0)
                        storage_flags |= MAILBOX_LIST_GET_STORAGE_FLAG_SAVEONLY;
                if (mailbox_list_get_storage(&new_list, &vname,
@@ -1095,15 +1146,20 @@ struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname,
                }
 
                box = storage->v.mailbox_alloc(storage, new_list, vname, flags);
-               const char *error;
                if (open_error != 0) {
                        box->open_error = open_error;
                        mail_storage_set_error(storage, open_error, errstr);
-               } else if (settings_get(box->event,
-                                       &mailbox_setting_parser_info, 0,
-                                       &box->set, &error) < 0) {
+               } else if ((ret = mailbox_name_try_get_settings(box->list,
+                                       vname, &box->set, &error)) < 0) {
                        mailbox_set_critical(box, "%s", error);
                        box->open_error = box->storage->error;
+               } else if (ret == 0) {
+                       if (settings_get(box->event,
+                                        &mailbox_setting_parser_info, 0,
+                                        &box->set, &error) < 0) {
+                               mailbox_set_critical(box, "%s", error);
+                               box->open_error = box->storage->error;
+                       }
                }
                if (strcmp(orig_vname, vname) != 0)
                        box->mailbox_not_original = TRUE;
index f39c9830cac3da97e8c3df79cf6d502142d3467b..0e078cfe5025ce50b2b4344e81ac758c24347063 100644 (file)
@@ -114,6 +114,7 @@ struct mailbox_list {
        pool_t pool;
        struct mail_namespace *ns;
        const struct mail_storage_settings *mail_set;
+       const struct mailbox_settings *default_box_set;
        enum mailbox_list_flags flags;
 
        /* may not be set yet, use mailbox_list_get_permissions() to access */
index fb120096b8758be13c5ecdad353872ab478f7188..8e1bca079d397aa8c10bf5fe049dc69466f3e63f 100644 (file)
@@ -555,6 +555,7 @@ void mailbox_list_destroy(struct mailbox_list **_list)
 
        struct event *event = list->event;
        settings_free(list->mail_set);
+       settings_free(list->default_box_set);
        list->v.deinit(list);
        event_unref(&event);
 }