From: Martti Rannanjärvi Date: Tue, 17 Oct 2017 08:57:29 +0000 (+0300) Subject: quota-count: Improve error_r strings X-Git-Tag: 2.3.0.rc1~799 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d2cbbecf76de3f4eb945895fab5760ed0a28281c;p=thirdparty%2Fdovecot%2Fcore.git quota-count: Improve error_r strings --- diff --git a/src/plugins/quota/quota-count.c b/src/plugins/quota/quota-count.c index 4005be372d..a4c7366646 100644 --- a/src/plugins/quota/quota-count.c +++ b/src/plugins/quota/quota-count.c @@ -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; } diff --git a/src/plugins/quota/quota-dict.c b/src/plugins/quota/quota-dict.c index 5cb7728a94..cbc830d83a 100644 --- a/src/plugins/quota/quota-dict.c +++ b/src/plugins/quota/quota-dict.c @@ -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 diff --git a/src/plugins/quota/quota-private.h b/src/plugins/quota/quota-private.h index 41e9ddfb03..453114e2b0 100644 --- a/src/plugins/quota/quota-private.h +++ b/src/plugins/quota/quota-private.h @@ -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);