quota-dict.c revision efe78d3ba24fc866af1c79b9223dc0809ba26cad
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek/* Copyright (c) 2005-2016 Dovecot authors, see the included COPYING file */
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek#include "lib.h"
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek#include "ioloop.h"
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek#include "str.h"
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek#include "dict.h"
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek#include "mail-user.h"
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek#include "mail-namespace.h"
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek#include "quota-private.h"
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek#define DICT_QUOTA_CURRENT_PATH DICT_PATH_PRIVATE"quota/"
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek#define DICT_QUOTA_CURRENT_BYTES_PATH DICT_QUOTA_CURRENT_PATH"storage"
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek#define DICT_QUOTA_CURRENT_COUNT_PATH DICT_QUOTA_CURRENT_PATH"messages"
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozekstruct dict_quota_root {
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek struct quota_root root;
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek struct dict *dict;
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek struct timeout *to_update;
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek bool disable_unset;
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek};
2186f88e0449f2303dc84e98c88379ccf8e55714Lukas Slebodnik
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekextern struct quota_backend quota_backend_dict;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozekstatic struct quota_root *dict_quota_alloc(void)
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek{
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek struct dict_quota_root *root;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek root = i_new(struct dict_quota_root, 1);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek return &root->root;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic int dict_quota_init(struct quota_root *_root, const char *args,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek const char **error_r)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct dict_quota_root *root = (struct dict_quota_root *)_root;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct dict_settings set;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek const char *username, *p, *error;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek p = args == NULL ? NULL : strchr(args, ':');
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio if (p == NULL) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek *error_r = "URI missing from parameters";
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return -1;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek username = t_strdup_until(args, p);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek args = p+1;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek for (;;) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek /* FIXME: pretty ugly in here. the parameters should have
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek been designed to be extensible. do it in a future version */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (strncmp(args, "noenforcing:", 12) == 0) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek _root->no_enforcing = TRUE;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek args += 12;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek } else if (strncmp(args, "hidden:", 7) == 0) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek _root->hidden = TRUE;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek args += 7;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek } else if (strncmp(args, "ignoreunlimited:", 16) == 0) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek _root->disable_unlimited_tracking = TRUE;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek args += 16;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek } else if (strncmp(args, "no-unset:", 9) == 0) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek root->disable_unset = TRUE;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek args += 9;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek } else if (strncmp(args, "ns=", 3) == 0) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek p = strchr(args, ':');
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (p == NULL)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek break;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek _root->ns_prefix = p_strdup_until(_root->pool,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek args + 3, p);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek args = p + 1;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek } else {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek break;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (*username == '\0')
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek username = _root->quota->user->username;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (_root->quota->set->debug) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek i_debug("dict quota: user=%s, uri=%s, noenforcing=%d",
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek username, args, _root->no_enforcing ? 1 : 0);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek /* FIXME: we should use 64bit integer as datatype instead but before
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek it can actually be used don't bother */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek i_zero(&set);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek set.username = username;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek set.base_dir = _root->quota->user->set->base_dir;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (mail_user_get_home(_root->quota->user, &set.home_dir) <= 0)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek set.home_dir = NULL;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (dict_init(args, &set, &root->dict, &error) < 0) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek *error_r = t_strdup_printf("dict_init(%s) failed: %s", args, error);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return -1;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return 0;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic void dict_quota_deinit(struct quota_root *_root)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct dict_quota_root *root = (struct dict_quota_root *)_root;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek i_assert(root->to_update == NULL);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (root->dict != NULL) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek dict_wait(root->dict);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek dict_deinit(&root->dict);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek i_free(root);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic const char *const *
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekdict_quota_root_get_resources(struct quota_root *root ATTR_UNUSED)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek static const char *resources[] = {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek QUOTA_NAME_STORAGE_KILOBYTES, QUOTA_NAME_MESSAGES, NULL
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek };
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return resources;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic int
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekdict_quota_count(struct dict_quota_root *root,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek bool want_bytes, uint64_t *value_r)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct dict_transaction_context *dt;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek uint64_t bytes, count;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (quota_count(&root->root, &bytes, &count) < 0)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return -1;
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio T_BEGIN {
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio dt = dict_transaction_begin(root->dict);
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio /* these unsets are mainly necessary for pgsql, because its
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio trigger otherwise increases quota without deleting it.
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio but some people with other databases want to store the
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio quota usage among other data in the same row, which
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio shouldn't be deleted. */
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio if (!root->disable_unset) {
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio dict_unset(dt, DICT_QUOTA_CURRENT_BYTES_PATH);
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio dict_unset(dt, DICT_QUOTA_CURRENT_COUNT_PATH);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek dict_set(dt, DICT_QUOTA_CURRENT_BYTES_PATH, dec2str(bytes));
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek dict_set(dt, DICT_QUOTA_CURRENT_COUNT_PATH, dec2str(count));
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek } T_END;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek dict_transaction_commit_async(&dt, NULL, NULL);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek *value_r = want_bytes ? bytes : count;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return 1;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic int
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekdict_quota_get_resource(struct quota_root *_root,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek const char *name, uint64_t *value_r)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct dict_quota_root *root = (struct dict_quota_root *)_root;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek bool want_bytes;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek int ret;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (strcmp(name, QUOTA_NAME_STORAGE_BYTES) == 0)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek want_bytes = TRUE;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek else if (strcmp(name, QUOTA_NAME_MESSAGES) == 0)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek want_bytes = FALSE;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek else
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return 0;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek T_BEGIN {
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek const char *key, *value, *error;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek key = want_bytes ? DICT_QUOTA_CURRENT_BYTES_PATH :
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek DICT_QUOTA_CURRENT_COUNT_PATH;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek ret = dict_lookup(root->dict, unsafe_data_stack_pool,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek key, &value, &error);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (ret < 0) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek i_error("dict quota: dict_lookup(%s) failed: %s", key, error);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek *value_r = 0;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek } else {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek intmax_t tmp;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek /* recalculate quota if it's negative or if it
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek wasn't found */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (ret == 0 || str_to_intmax(value, &tmp) < 0)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek tmp = -1;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (tmp >= 0)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek *value_r = tmp;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek else {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek ret = dict_quota_count(root, want_bytes,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek value_r);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek } T_END;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return ret;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic void dict_quota_recalc_timeout(struct dict_quota_root *root)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek uint64_t value;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek timeout_remove(&root->to_update);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek (void)dict_quota_count(root, TRUE, &value);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek}
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozekstatic void dict_quota_update_callback(const struct dict_commit_result *result,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek void *context)
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek{
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek struct dict_quota_root *root = context;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (result->ret == 0) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek /* row doesn't exist, need to recalculate it */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (root->to_update == NULL)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek root->to_update = timeout_add_short(0, dict_quota_recalc_timeout, root);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek } else if (result->ret < 0) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek i_error("dict quota: Quota update failed: %s "
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek "- Quota is now desynced", result->error);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic int
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekdict_quota_update(struct quota_root *_root,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct quota_transaction_context *ctx)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct dict_quota_root *root = (struct dict_quota_root *) _root;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct dict_transaction_context *dt;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek uint64_t value;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (ctx->recalculate != QUOTA_RECALCULATE_DONT) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (dict_quota_count(root, TRUE, &value) < 0)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return -1;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek } else {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek dt = dict_transaction_begin(root->dict);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (ctx->bytes_used != 0) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek dict_atomic_inc(dt, DICT_QUOTA_CURRENT_BYTES_PATH,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek ctx->bytes_used);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (ctx->count_used != 0) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek dict_atomic_inc(dt, DICT_QUOTA_CURRENT_COUNT_PATH,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek ctx->count_used);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek dict_transaction_no_slowness_warning(dt);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek dict_transaction_commit_async(&dt, dict_quota_update_callback,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek root);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return 0;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic void dict_quota_flush(struct quota_root *_root)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct dict_quota_root *root = (struct dict_quota_root *)_root;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek dict_wait(root->dict);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (root->to_update != NULL) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek dict_quota_recalc_timeout(root);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek dict_wait(root->dict);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek }
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek}
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozekstruct quota_backend quota_backend_dict = {
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek "dict",
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio {
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio dict_quota_alloc,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek dict_quota_init,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek dict_quota_deinit,
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio NULL,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek NULL,
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio NULL,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek dict_quota_root_get_resources,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek dict_quota_get_resource,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek dict_quota_update,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek NULL,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek dict_quota_flush
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek }
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek};
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek