quota-dict.c revision efe78d3ba24fc866af1c79b9223dc0809ba26cad
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek/* Copyright (c) 2005-2016 Dovecot authors, see the included COPYING file */
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 Hrozekstatic struct quota_root *dict_quota_alloc(void)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic int dict_quota_init(struct quota_root *_root, const char *args,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek const char **error_r)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct dict_quota_root *root = (struct dict_quota_root *)_root;
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 } else if (strncmp(args, "ignoreunlimited:", 16) == 0) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek } else if (strncmp(args, "no-unset:", 9) == 0) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek i_debug("dict quota: user=%s, uri=%s, noenforcing=%d",
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 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 if (dict_init(args, &set, &root->dict, &error) < 0) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek *error_r = t_strdup_printf("dict_init(%s) failed: %s", args, error);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic void dict_quota_deinit(struct quota_root *_root)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct dict_quota_root *root = (struct dict_quota_root *)_root;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic const char *const *
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekdict_quota_root_get_resources(struct quota_root *root ATTR_UNUSED)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek static const char *resources[] = {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek QUOTA_NAME_STORAGE_KILOBYTES, QUOTA_NAME_MESSAGES, NULL
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (quota_count(&root->root, &bytes, &count) < 0)
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 dict_unset(dt, DICT_QUOTA_CURRENT_BYTES_PATH);
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio dict_unset(dt, DICT_QUOTA_CURRENT_COUNT_PATH);
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 dict_transaction_commit_async(&dt, NULL, NULL);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekdict_quota_get_resource(struct quota_root *_root,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct dict_quota_root *root = (struct dict_quota_root *)_root;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (strcmp(name, QUOTA_NAME_STORAGE_BYTES) == 0)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek else if (strcmp(name, QUOTA_NAME_MESSAGES) == 0)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek key = want_bytes ? DICT_QUOTA_CURRENT_BYTES_PATH :
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek ret = dict_lookup(root->dict, unsafe_data_stack_pool,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek i_error("dict quota: dict_lookup(%s) failed: %s", key, error);
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 Hrozekstatic void dict_quota_recalc_timeout(struct dict_quota_root *root)
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozekstatic void dict_quota_update_callback(const struct dict_commit_result *result,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek /* row doesn't exist, need to recalculate it */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek root->to_update = timeout_add_short(0, dict_quota_recalc_timeout, root);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct dict_quota_root *root = (struct dict_quota_root *) _root;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (ctx->recalculate != QUOTA_RECALCULATE_DONT) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek dict_atomic_inc(dt, DICT_QUOTA_CURRENT_BYTES_PATH,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek dict_atomic_inc(dt, DICT_QUOTA_CURRENT_COUNT_PATH,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek dict_transaction_commit_async(&dt, dict_quota_update_callback,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic void dict_quota_flush(struct quota_root *_root)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct dict_quota_root *root = (struct dict_quota_root *)_root;