]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
quota: Code cleanup - abstract out iteration of mailboxes related to a quota root.
authorTimo Sirainen <tss@iki.fi>
Mon, 28 Sep 2015 13:06:43 +0000 (16:06 +0300)
committerTimo Sirainen <tss@iki.fi>
Mon, 28 Sep 2015 13:06:43 +0000 (16:06 +0300)
src/plugins/quota/quota-count.c

index 132b328ba0a0995cfadda338c8f95d1a1d6a3478..17d897d2f44314ab1ddec97c3b5392e7376fe86b 100644 (file)
@@ -4,6 +4,15 @@
 #include "mailbox-list-iter.h"
 #include "quota-private.h"
 
+struct quota_mailbox_iter {
+       struct quota_root *root;
+       struct mail_namespace *ns;
+       unsigned int ns_idx;
+       struct mailbox_list_iterate_context *iter;
+       struct mailbox_info info;
+       bool failed;
+};
+
 extern struct quota_backend quota_backend_count;
 
 static int
@@ -49,44 +58,81 @@ quota_count_mailbox(struct quota_root *root, struct mail_namespace *ns,
        return ret;
 }
 
+static struct quota_mailbox_iter *
+quota_mailbox_iter_begin(struct quota_root *root)
+{
+       struct quota_mailbox_iter *iter;
+
+       iter = i_new(struct quota_mailbox_iter, 1);
+       iter->root = root;
+       return iter;
+}
+
 static int
-quota_count_namespace(struct quota_root *root, struct mail_namespace *ns,
-                     uint64_t *bytes, uint64_t *count)
+quota_mailbox_iter_deinit(struct quota_mailbox_iter **_iter)
+{
+       struct quota_mailbox_iter *iter = *_iter;
+       int ret = iter->failed ? -1 : 0;
+
+       *_iter = NULL;
+
+       if (iter->iter != NULL) {
+               if (mailbox_list_iter_deinit(&iter->iter) < 0) {
+                       i_error("quota: Listing namespace '%s' failed: %s",
+                               iter->ns->prefix,
+                               mailbox_list_get_last_error(iter->ns->list, NULL));
+                       ret = -1;
+               }
+       }
+       i_free(iter);
+       return ret;
+}
+
+static const struct mailbox_info *
+quota_mailbox_iter_next(struct quota_mailbox_iter *iter)
 {
-       struct mailbox_list_iterate_context *ctx;
+       struct mail_namespace *const *namespaces;
        const struct mailbox_info *info;
-       int ret = 0;
+       unsigned int count;
+
+       if (iter->iter == NULL) {
+               namespaces = array_get(&iter->root->quota->namespaces, &count);
+               if (iter->ns_idx >= count)
+                       return NULL;
 
-       ctx = mailbox_list_iter_init(ns->list, "*",
-                                    MAILBOX_LIST_ITER_SKIP_ALIASES |
-                                    MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
-       while ((info = mailbox_list_iter_next(ctx)) != NULL) {
+               iter->ns = namespaces[iter->ns_idx++];
+               iter->iter = mailbox_list_iter_init(iter->ns->list, "*",
+                       MAILBOX_LIST_ITER_SKIP_ALIASES |
+                       MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
+       }
+       while ((info = mailbox_list_iter_next(iter->iter)) != NULL) {
                if ((info->flags & (MAILBOX_NONEXISTENT |
-                                   MAILBOX_NOSELECT)) == 0) {
-                       ret = quota_count_mailbox(root, ns, info->vname,
-                                                 bytes, count);
-                       if (ret < 0)
-                               break;
-               }
+                                   MAILBOX_NOSELECT)) == 0)
+                       return info;
        }
-       if (mailbox_list_iter_deinit(&ctx) < 0) {
+       if (mailbox_list_iter_deinit(&iter->iter) < 0) {
                i_error("quota: Listing namespace '%s' failed: %s",
-                       ns->prefix, mailbox_list_get_last_error(ns->list, NULL));
-               ret = -1;
+                       iter->ns->prefix,
+                       mailbox_list_get_last_error(iter->ns->list, NULL));
+               iter->failed = TRUE;
        }
-       if (ns->prefix_len > 0 && ret == 0 &&
-           (ns->prefix_len != 6 || strncasecmp(ns->prefix, "INBOX", 5) != 0)) {
+       if (iter->ns->prefix_len > 0 &&
+           (iter->ns->prefix_len != 6 ||
+            strncasecmp(iter->ns->prefix, "INBOX", 5) != 0)) {
                /* if the namespace prefix itself exists, count it also */
-               const char *name = t_strndup(ns->prefix, ns->prefix_len-1);
-               ret = quota_count_mailbox(root, ns, name, bytes, count);
+               iter->info.ns = iter->ns;
+               iter->info.vname = t_strndup(iter->ns->prefix,
+                                            iter->ns->prefix_len-1);
+               return &iter->info;
        }
-       return ret;
+       /* try the next namespace */
+       return quota_mailbox_iter_next(iter);
 }
 
 int quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r)
 {
-       struct mail_namespace *const *namespaces;
-       unsigned int i, count;
+       struct quota_mailbox_iter *iter;
+       const struct mailbox_info *info;
        int ret = 0;
 
        *bytes_r = *count_r = 0;
@@ -94,16 +140,12 @@ int quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r)
                return 0;
        root->recounting = TRUE;
 
-       namespaces = array_get(&root->quota->namespaces, &count);
-       for (i = 0; i < count; i++) {
-               if (!quota_root_is_namespace_visible(root, namespaces[i]))
-                       continue;
-
-               ret = quota_count_namespace(root, namespaces[i],
-                                           bytes_r, count_r);
-               if (ret < 0)
-                       break;
+       iter = quota_mailbox_iter_begin(root);
+       while (ret >= 0 && (info = quota_mailbox_iter_next(iter)) != NULL) {
+               ret = quota_count_mailbox(root, info->ns, info->vname,
+                                         bytes_r, count_r);
        }
+       quota_mailbox_iter_deinit(&iter);
        root->recounting = FALSE;
        return ret;
 }