]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
quota-count: Improve error_r strings
authorMartti Rannanjärvi <martti.rannanjarvi@dovecot.fi>
Tue, 17 Oct 2017 08:57:29 +0000 (11:57 +0300)
committerTimo Sirainen <tss@dovecot.fi>
Thu, 19 Oct 2017 13:43:45 +0000 (16:43 +0300)
src/plugins/quota/quota-count.c
src/plugins/quota/quota-dict.c
src/plugins/quota/quota-private.h

index 4005be372d5f30488942444af491ceb8fabbb8cf..a4c73666461b1681e90c8ea3b14eee90eceacaf4 100644 (file)
@@ -18,14 +18,15 @@ struct quota_mailbox_iter {
        unsigned int ns_idx;
        struct mailbox_list_iterate_context *iter;
        struct mailbox_info info;
-       bool failed;
+       const char *error;
 };
 
 extern struct quota_backend quota_backend_count;
 
 static int
 quota_count_mailbox(struct quota_root *root, struct mail_namespace *ns,
-                   const char *vname, uint64_t *bytes, uint64_t *count)
+                   const char *vname, uint64_t *bytes, uint64_t *count,
+                   const char **error_r)
 {
        struct quota_rule *rule;
        struct mailbox *box;
@@ -53,11 +54,17 @@ quota_count_mailbox(struct quota_root *root, struct mail_namespace *ns,
            mailbox_get_status(box, STATUS_MESSAGES, &status) < 0) {
                errstr = mailbox_get_last_internal_error(box, &error);
                if (error == MAIL_ERROR_TEMP) {
-                       i_error("quota: Couldn't get size of mailbox %s: %s",
+                       *error_r = t_strdup_printf(
+                               "Couldn't get size of mailbox %s: %s",
                                vname, errstr);
                        ret = -1;
                } else if (error == MAIL_ERROR_INUSE) {
                        /* started on background. don't log an error. */
+                       /* FIXME: Should not log an error, will be fixed with
+                        *        upcoming enum addition. */
+                       *error_r = t_strdup_printf(
+                               "%s busy with background quota calculation",
+                               vname);
                        ret = -1;
                } else {
                        /* non-temporary error, e.g. ACLs denied access. */
@@ -80,25 +87,35 @@ quota_mailbox_iter_begin(struct quota_root *root)
 
        iter = i_new(struct quota_mailbox_iter, 1);
        iter->root = root;
+       iter->error = "";
        return iter;
 }
 
 static int
-quota_mailbox_iter_deinit(struct quota_mailbox_iter **_iter)
+quota_mailbox_iter_deinit(struct quota_mailbox_iter **_iter,
+                         const char **error_r)
 {
        struct quota_mailbox_iter *iter = *_iter;
-       int ret = iter->failed ? -1 : 0;
+       int ret = *iter->error != '\0' ? -1 : 0;
 
        *_iter = NULL;
 
+       const char *error2 = "";
        if (iter->iter != NULL) {
                if (mailbox_list_iter_deinit(&iter->iter) < 0) {
-                       i_error("quota: Listing namespace '%s' failed: %s",
+                       error2 = t_strdup_printf(
+                               "Listing namespace '%s' failed: %s",
                                iter->ns->prefix,
                                mailbox_list_get_last_internal_error(iter->ns->list, NULL));
                        ret = -1;
                }
        }
+       if (ret < 0) {
+               const char *separator =
+                       *iter->error != '\0' && *error2 != '\0' ? " and " : "";
+               *error_r = t_strdup_printf("%s%s%s",
+                                          iter->error, separator, error2);
+       }
        i_free(iter);
        return ret;
 }
@@ -129,10 +146,10 @@ quota_mailbox_iter_next(struct quota_mailbox_iter *iter)
                        return info;
        }
        if (mailbox_list_iter_deinit(&iter->iter) < 0) {
-               i_error("quota: Listing namespace '%s' failed: %s",
+               iter->error = t_strdup_printf(
+                       "Listing namespace '%s' failed: %s",
                        iter->ns->prefix,
                        mailbox_list_get_last_internal_error(iter->ns->list, NULL));
-               iter->failed = TRUE;
        }
        if (iter->ns->prefix_len > 0 &&
            (iter->ns->prefix_len != 6 ||
@@ -147,10 +164,12 @@ quota_mailbox_iter_next(struct quota_mailbox_iter *iter)
        return quota_mailbox_iter_next(iter);
 }
 
-int quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r)
+int quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r,
+               const char **error_r)
 {
        struct quota_mailbox_iter *iter;
        const struct mailbox_info *info;
+       const char *error1 = "", *error2 = "";
        int ret = 1;
 
        *bytes_r = *count_r = 0;
@@ -161,19 +180,27 @@ int quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r)
        iter = quota_mailbox_iter_begin(root);
        while ((info = quota_mailbox_iter_next(iter)) != NULL) {
                if (quota_count_mailbox(root, info->ns, info->vname,
-                                       bytes_r, count_r) < 0) {
+                                       bytes_r, count_r, &error1) < 0) {
                        ret = -1;
                        break;
                }
        }
-       if (quota_mailbox_iter_deinit(&iter) < 0)
+       if (quota_mailbox_iter_deinit(&iter, &error2) < 0)
                ret = -1;
+       if (ret < 0) {
+               const char *separator =
+                       *error1 != '\0' && *error2 != '\0' ? " and " : "";
+               *error_r = t_strdup_printf(
+                       "quota-count failed: %s%s%s",
+                       error1, separator, error2);
+       }
        root->recounting = FALSE;
        return ret;
 }
 
 static int quota_count_cached(struct count_quota_root *root,
-                             uint64_t *bytes_r, uint64_t *count_r)
+                             uint64_t *bytes_r, uint64_t *count_r,
+                             const char **error_r)
 {
        int ret;
 
@@ -184,7 +211,7 @@ static int quota_count_cached(struct count_quota_root *root,
                *count_r = root->cached_count;
                return 1;
        }
-       ret = quota_count(&root->root, bytes_r, count_r);
+       ret = quota_count(&root->root, bytes_r, count_r, error_r);
        if (ret > 0) {
                root->cache_timeval = ioloop_timeval;
                root->cached_bytes = *bytes_r;
@@ -233,9 +260,11 @@ count_quota_get_resource(struct quota_root *_root,
 {
        struct count_quota_root *root = (struct count_quota_root *)_root;
        uint64_t bytes, count;
+       const char *error;
 
-       if (quota_count_cached(root, &bytes, &count) < 0) {
-               *error_r = "quota-count failed";
+       if (quota_count_cached(root, &bytes, &count, &error) < 0) {
+               *error_r = t_strdup_printf(
+                       "quota-count: Failed to get %s: %s", name, error);
                return -1;
        }
 
@@ -248,7 +277,8 @@ count_quota_get_resource(struct quota_root *_root,
        return 1;
 }
 
-static int quota_count_recalculate_box(struct mailbox *box)
+static int quota_count_recalculate_box(struct mailbox *box,
+                                      const char **error_r)
 {
        struct mail_index_transaction *trans;
        struct mailbox_metadata metadata;
@@ -262,7 +292,8 @@ static int quota_count_recalculate_box(struct mailbox *box)
                        /* non-temporary error, e.g. ACLs denied access. */
                        return 0;
                }
-               i_error("Couldn't open mailbox %s: %s", box->vname, errstr);
+               *error_r = t_strdup_printf(
+                       "Couldn't open mailbox %s: %s", box->vname, errstr);
                return -1;
        }
 
@@ -272,41 +303,57 @@ static int quota_count_recalculate_box(struct mailbox *box)
        i_zero(&vsize_hdr);
        mail_index_update_header_ext(trans, box->vsize_hdr_ext_id,
                                     0, &vsize_hdr, sizeof(vsize_hdr));
-       if (mail_index_transaction_commit(&trans) < 0)
+       if (mail_index_transaction_commit(&trans) < 0) {
+               *error_r = t_strdup_printf(
+                       "Couldn't commit mail index transaction for %s: %s",
+                       box->vname,
+                       mail_index_get_error_message(box->view->index));
                return -1;
+       }
        /* getting the vsize now forces its recalculation */
        if (mailbox_get_metadata(box, MAILBOX_METADATA_VIRTUAL_SIZE,
                                 &metadata) < 0) {
-               i_error("Couldn't get mailbox %s vsize: %s", box->vname,
+               *error_r = t_strdup_printf(
+                       "Couldn't get mailbox %s vsize: %s", box->vname,
                        mailbox_get_last_internal_error(box, NULL));
                return -1;
        }
        /* call sync to write the change to mailbox list index */
        if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FAST) < 0) {
-               i_error("Couldn't sync mailbox %s: %s", box->vname,
+               *error_r = t_strdup_printf(
+                       "Couldn't sync mailbox %s: %s", box->vname,
                        mailbox_get_last_internal_error(box, NULL));
                return -1;
        }
        return 0;
 }
 
-static int quota_count_recalculate(struct quota_root *root)
+static int quota_count_recalculate(struct quota_root *root,
+                                  const char **error_r)
 {
        struct quota_mailbox_iter *iter;
        const struct mailbox_info *info;
        struct mailbox *box;
        int ret = 0;
+       const char *error1 = "", *error2 = "";
 
        iter = quota_mailbox_iter_begin(root);
        while ((info = quota_mailbox_iter_next(iter)) != NULL) {
                box = mailbox_alloc(info->ns->list, info->vname, 0);
                mailbox_set_reason(box, "quota recalculate");
-               if (quota_count_recalculate_box(box) < 0)
+               if (quota_count_recalculate_box(box, &error1) < 0)
                        ret = -1;
                mailbox_free(&box);
        }
-       if (quota_mailbox_iter_deinit(&iter) < 0)
+       if (quota_mailbox_iter_deinit(&iter, &error2) < 0)
                ret = -1;
+       if (ret < 0) {
+               const char *separator =
+                       *error1 != '\0' && *error2 != '\0' ? " and " : "";
+               *error_r = t_strdup_printf(
+                       "quota-count: recalculate failed: %s%s%s",
+                       error1, separator, error2);
+       }
        return ret;
 }
 
@@ -319,10 +366,8 @@ count_quota_update(struct quota_root *root,
 
        croot->cache_timeval.tv_sec = 0;
        if (ctx->recalculate == QUOTA_RECALCULATE_FORCED) {
-               if (quota_count_recalculate(root) < 0) {
-                       *error_r = "Calculating quota failed";
+               if (quota_count_recalculate(root, error_r) < 0)
                        return -1;
-               }
        }
        return 0;
 }
index 5cb7728a946d2abdea416fafbb705e55a0895b3a..cbc830d83a0370bc4638aa9b9080f263e155b0cc 100644 (file)
@@ -111,9 +111,12 @@ dict_quota_count(struct dict_quota_root *root,
 {
        struct dict_transaction_context *dt;
        uint64_t bytes, count;
+       const char *error;
 
-       if (quota_count(&root->root, &bytes, &count) < 0)
+       if (quota_count(&root->root, &bytes, &count, &error) < 0) {
+               i_error("quota-dict failed: %s", error);
                return -1;
+       }
 
        dt = dict_transaction_begin(root->dict);
        /* these unsets are mainly necessary for pgsql, because its
index 41e9ddfb032904b5a71f2d4b6b36bf71e4cfbff6..453114e2b005fb8ae1a7a4282d99ac3b3e0f3595 100644 (file)
@@ -203,7 +203,8 @@ void quota_root_recalculate_relative_rules(struct quota_root_settings *root_set,
                                           int64_t count_limit);
 /* Returns 1 if values were returned successfully, 0 if we're recursing into
    the same function, -1 if error. */
-int quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r);
+int quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r,
+               const char **error_r);
 
 int quota_root_parse_grace(struct quota_root_settings *root_set,
                           const char *value, const char **error_r);