quota-dict.c revision 20e04227229970d148801c507946666e2a9bd838
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2005-2016 Dovecot authors, see the included COPYING file */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "lib.h"
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainen#include "ioloop.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "str.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "dict.h"
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen#include "mail-user.h"
2d8b23805db6f06b8b38174fb6e135386694f429Timo Sirainen#include "mail-namespace.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "quota-private.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen#define DICT_QUOTA_CURRENT_PATH DICT_PATH_PRIVATE"quota/"
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen#define DICT_QUOTA_CURRENT_BYTES_PATH DICT_QUOTA_CURRENT_PATH"storage"
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen#define DICT_QUOTA_CURRENT_COUNT_PATH DICT_QUOTA_CURRENT_PATH"messages"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainenstruct dict_quota_root {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct quota_root root;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct dict *dict;
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainen struct timeout *to_update;
6b0e35b29f65a95fe8ae22ed8b5f0f36720c9f45Timo Sirainen bool disable_unset;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen};
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainenextern struct quota_backend quota_backend_dict;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenstatic struct quota_root *dict_quota_alloc(void)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen struct dict_quota_root *root;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen root = i_new(struct dict_quota_root, 1);
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen return &root->root;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
9b61a6db87c026656f8d2ae214e4486b98a069c0Timo Sirainenstatic int dict_quota_init(struct quota_root *_root, const char *args,
9b61a6db87c026656f8d2ae214e4486b98a069c0Timo Sirainen const char **error_r)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen struct dict_quota_root *root = (struct dict_quota_root *)_root;
9346506a9f4dd9a6285fe8595588e73161849235Timo Sirainen struct dict_settings set;
eca38954bcf972618f6b85932a3690acbd2b673aTimo Sirainen const char *username, *p, *error;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen p = args == NULL ? NULL : strchr(args, ':');
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen if (p == NULL) {
9b61a6db87c026656f8d2ae214e4486b98a069c0Timo Sirainen *error_r = "URI missing from parameters";
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen return -1;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen username = t_strdup_until(args, p);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen args = p+1;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen
9c0cd052c03799d764938ffe500cf510bf9eb464Timo Sirainen for (;;) {
65e14cef911d5d3fac8993c8a76911a587f05cd7Timo Sirainen /* FIXME: pretty ugly in here. the parameters should have
65e14cef911d5d3fac8993c8a76911a587f05cd7Timo Sirainen been designed to be extensible. do it in a future version */
2d8b23805db6f06b8b38174fb6e135386694f429Timo Sirainen if (strncmp(args, "noenforcing:", 12) == 0) {
2d8b23805db6f06b8b38174fb6e135386694f429Timo Sirainen _root->no_enforcing = TRUE;
2d8b23805db6f06b8b38174fb6e135386694f429Timo Sirainen args += 12;
9c0cd052c03799d764938ffe500cf510bf9eb464Timo Sirainen } else if (strncmp(args, "hidden:", 7) == 0) {
3f7583189249a28892cd5bd69e15681c7a8a619bTimo Sirainen _root->hidden = TRUE;
3f7583189249a28892cd5bd69e15681c7a8a619bTimo Sirainen args += 7;
9c0cd052c03799d764938ffe500cf510bf9eb464Timo Sirainen } else if (strncmp(args, "ignoreunlimited:", 16) == 0) {
d19d3aa4eafa34b48b7d7d311c9db31e1898576aTimo Sirainen _root->disable_unlimited_tracking = TRUE;
d19d3aa4eafa34b48b7d7d311c9db31e1898576aTimo Sirainen args += 16;
6b0e35b29f65a95fe8ae22ed8b5f0f36720c9f45Timo Sirainen } else if (strncmp(args, "no-unset:", 9) == 0) {
6b0e35b29f65a95fe8ae22ed8b5f0f36720c9f45Timo Sirainen root->disable_unset = TRUE;
6b0e35b29f65a95fe8ae22ed8b5f0f36720c9f45Timo Sirainen args += 9;
9c0cd052c03799d764938ffe500cf510bf9eb464Timo Sirainen } else if (strncmp(args, "ns=", 3) == 0) {
2d8b23805db6f06b8b38174fb6e135386694f429Timo Sirainen p = strchr(args, ':');
2d8b23805db6f06b8b38174fb6e135386694f429Timo Sirainen if (p == NULL)
2d8b23805db6f06b8b38174fb6e135386694f429Timo Sirainen break;
2d8b23805db6f06b8b38174fb6e135386694f429Timo Sirainen
2d8b23805db6f06b8b38174fb6e135386694f429Timo Sirainen _root->ns_prefix = p_strdup_until(_root->pool,
2d8b23805db6f06b8b38174fb6e135386694f429Timo Sirainen args + 3, p);
2d8b23805db6f06b8b38174fb6e135386694f429Timo Sirainen args = p + 1;
9c0cd052c03799d764938ffe500cf510bf9eb464Timo Sirainen } else {
9c0cd052c03799d764938ffe500cf510bf9eb464Timo Sirainen break;
2d8b23805db6f06b8b38174fb6e135386694f429Timo Sirainen }
9c0cd052c03799d764938ffe500cf510bf9eb464Timo Sirainen }
65e14cef911d5d3fac8993c8a76911a587f05cd7Timo Sirainen
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen if (*username == '\0')
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen username = _root->quota->user->username;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen if (_root->quota->set->debug) {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk i_debug("dict quota: user=%s, uri=%s, noenforcing=%d",
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk username, args, _root->no_enforcing);
65e14cef911d5d3fac8993c8a76911a587f05cd7Timo Sirainen }
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen
92d1458b00f4f236c4cec96a696253d3bbf8b05aTimo Sirainen /* FIXME: we should use 64bit integer as datatype instead but before
92d1458b00f4f236c4cec96a696253d3bbf8b05aTimo Sirainen it can actually be used don't bother */
9346506a9f4dd9a6285fe8595588e73161849235Timo Sirainen memset(&set, 0, sizeof(set));
9346506a9f4dd9a6285fe8595588e73161849235Timo Sirainen set.username = username;
9346506a9f4dd9a6285fe8595588e73161849235Timo Sirainen set.base_dir = _root->quota->user->set->base_dir;
9346506a9f4dd9a6285fe8595588e73161849235Timo Sirainen if (mail_user_get_home(_root->quota->user, &set.home_dir) <= 0)
9346506a9f4dd9a6285fe8595588e73161849235Timo Sirainen set.home_dir = NULL;
20e04227229970d148801c507946666e2a9bd838Timo Sirainen if (dict_init(args, &set, &root->dict, &error) < 0) {
9b61a6db87c026656f8d2ae214e4486b98a069c0Timo Sirainen *error_r = t_strdup_printf("dict_init(%s) failed: %s", args, error);
10399559650f552a23949772be79eb6a80198c5aTimo Sirainen return -1;
eca38954bcf972618f6b85932a3690acbd2b673aTimo Sirainen }
10399559650f552a23949772be79eb6a80198c5aTimo Sirainen return 0;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenstatic void dict_quota_deinit(struct quota_root *_root)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen struct dict_quota_root *root = (struct dict_quota_root *)_root;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainen i_assert(root->to_update == NULL);
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainen
048e40f9364fa68482bc276dd4a5d595a3d742e9Timo Sirainen if (root->dict != NULL)
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen dict_deinit(&root->dict);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen i_free(root);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstatic const char *const *
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainendict_quota_root_get_resources(struct quota_root *root ATTR_UNUSED)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen static const char *resources[] = {
e392fcb39a06609af20a9e79017683f194de3ddeTimo Sirainen QUOTA_NAME_STORAGE_KILOBYTES, QUOTA_NAME_MESSAGES, NULL
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen };
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return resources;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainenstatic int
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainendict_quota_count(struct dict_quota_root *root,
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen bool want_bytes, uint64_t *value_r)
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen{
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen struct dict_transaction_context *dt;
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen uint64_t bytes, count;
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen
2b682d8d3661800f16aceaa45fa4de9b6b140a59Timo Sirainen if (quota_count(&root->root, &bytes, &count) < 0)
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen return -1;
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen dt = dict_transaction_begin(root->dict);
8595bafebf582a04fdff49af3cc69919c5332a0dTimo Sirainen /* these unsets are mainly necessary for pgsql, because its
6b0e35b29f65a95fe8ae22ed8b5f0f36720c9f45Timo Sirainen trigger otherwise increases quota without deleting it.
6b0e35b29f65a95fe8ae22ed8b5f0f36720c9f45Timo Sirainen but some people with other databases want to store the
6b0e35b29f65a95fe8ae22ed8b5f0f36720c9f45Timo Sirainen quota usage among other data in the same row, which
6b0e35b29f65a95fe8ae22ed8b5f0f36720c9f45Timo Sirainen shouldn't be deleted. */
6b0e35b29f65a95fe8ae22ed8b5f0f36720c9f45Timo Sirainen if (!root->disable_unset) {
6b0e35b29f65a95fe8ae22ed8b5f0f36720c9f45Timo Sirainen dict_unset(dt, DICT_QUOTA_CURRENT_BYTES_PATH);
6b0e35b29f65a95fe8ae22ed8b5f0f36720c9f45Timo Sirainen dict_unset(dt, DICT_QUOTA_CURRENT_COUNT_PATH);
6b0e35b29f65a95fe8ae22ed8b5f0f36720c9f45Timo Sirainen }
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen dict_set(dt, DICT_QUOTA_CURRENT_BYTES_PATH, dec2str(bytes));
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen dict_set(dt, DICT_QUOTA_CURRENT_COUNT_PATH, dec2str(count));
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen
02d91785bcf42ced46080db91c29bb534fbe2d1cTimo Sirainen dict_transaction_commit_async(&dt, NULL, NULL);
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen *value_r = want_bytes ? bytes : count;
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen return 1;
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen}
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstatic int
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainendict_quota_get_resource(struct quota_root *_root,
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen const char *name, uint64_t *value_r)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen struct dict_quota_root *root = (struct dict_quota_root *)_root;
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen bool want_bytes;
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen int ret;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen if (strcmp(name, QUOTA_NAME_STORAGE_BYTES) == 0)
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen want_bytes = TRUE;
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen else if (strcmp(name, QUOTA_NAME_MESSAGES) == 0)
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen want_bytes = FALSE;
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen else
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen return 0;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen const char *value;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ret = dict_lookup(root->dict, unsafe_data_stack_pool,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen want_bytes ? DICT_QUOTA_CURRENT_BYTES_PATH :
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen DICT_QUOTA_CURRENT_COUNT_PATH, &value);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (ret < 0)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen *value_r = 0;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen else {
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch intmax_t tmp;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen /* recalculate quota if it's negative or if it
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen wasn't found */
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch if (ret == 0 || str_to_intmax(value, &tmp) < 0)
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch tmp = -1;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (tmp >= 0)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen *value_r = tmp;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen else {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ret = dict_quota_count(root, want_bytes,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen value_r);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen return ret;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainenstatic void dict_quota_recalc_timeout(struct dict_quota_root *root)
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainen{
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainen uint64_t value;
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainen
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainen timeout_remove(&root->to_update);
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainen (void)dict_quota_count(root, TRUE, &value);
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainen}
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainen
02d91785bcf42ced46080db91c29bb534fbe2d1cTimo Sirainenstatic void dict_quota_update_callback(int ret, void *context)
02d91785bcf42ced46080db91c29bb534fbe2d1cTimo Sirainen{
02d91785bcf42ced46080db91c29bb534fbe2d1cTimo Sirainen struct dict_quota_root *root = context;
02d91785bcf42ced46080db91c29bb534fbe2d1cTimo Sirainen
02d91785bcf42ced46080db91c29bb534fbe2d1cTimo Sirainen if (ret == 0) {
02d91785bcf42ced46080db91c29bb534fbe2d1cTimo Sirainen /* row doesn't exist, need to recalculate it */
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainen if (root->to_update == NULL)
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainen root->to_update = timeout_add_short(0, dict_quota_recalc_timeout, root);
560d08aadc24eeb6c13ed20316bad51e4f090dc1Timo Sirainen } else if (ret < 0) {
560d08aadc24eeb6c13ed20316bad51e4f090dc1Timo Sirainen i_error("dict quota: Quota update failed, it's now desynced");
02d91785bcf42ced46080db91c29bb534fbe2d1cTimo Sirainen }
02d91785bcf42ced46080db91c29bb534fbe2d1cTimo Sirainen}
02d91785bcf42ced46080db91c29bb534fbe2d1cTimo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstatic int
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainendict_quota_update(struct quota_root *_root,
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen struct quota_transaction_context *ctx)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen struct dict_quota_root *root = (struct dict_quota_root *) _root;
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen struct dict_transaction_context *dt;
02d91785bcf42ced46080db91c29bb534fbe2d1cTimo Sirainen uint64_t value;
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen if (ctx->recalculate) {
02d91785bcf42ced46080db91c29bb534fbe2d1cTimo Sirainen if (dict_quota_count(root, TRUE, &value) < 0)
02d91785bcf42ced46080db91c29bb534fbe2d1cTimo Sirainen return -1;
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen } else {
02d91785bcf42ced46080db91c29bb534fbe2d1cTimo Sirainen dt = dict_transaction_begin(root->dict);
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen if (ctx->bytes_used != 0) {
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen dict_atomic_inc(dt, DICT_QUOTA_CURRENT_BYTES_PATH,
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen ctx->bytes_used);
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen }
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen if (ctx->count_used != 0) {
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen dict_atomic_inc(dt, DICT_QUOTA_CURRENT_COUNT_PATH,
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen ctx->count_used);
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen }
02d91785bcf42ced46080db91c29bb534fbe2d1cTimo Sirainen dict_transaction_commit_async(&dt, dict_quota_update_callback,
02d91785bcf42ced46080db91c29bb534fbe2d1cTimo Sirainen root);
62300a38f91227b9de043a9a8ec1d4f1978e1138Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return 0;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
048e40f9364fa68482bc276dd4a5d595a3d742e9Timo Sirainenstatic void dict_quota_flush(struct quota_root *_root)
048e40f9364fa68482bc276dd4a5d595a3d742e9Timo Sirainen{
048e40f9364fa68482bc276dd4a5d595a3d742e9Timo Sirainen struct dict_quota_root *root = (struct dict_quota_root *)_root;
048e40f9364fa68482bc276dd4a5d595a3d742e9Timo Sirainen
048e40f9364fa68482bc276dd4a5d595a3d742e9Timo Sirainen (void)dict_wait(root->dict);
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainen if (root->to_update != NULL) {
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainen dict_quota_recalc_timeout(root);
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainen (void)dict_wait(root->dict);
54a8bb6e9b852d9a96a8cdda1bb55a85ce0e10daTimo Sirainen }
048e40f9364fa68482bc276dd4a5d595a3d742e9Timo Sirainen}
048e40f9364fa68482bc276dd4a5d595a3d742e9Timo Sirainen
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainenstruct quota_backend quota_backend_dict = {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen "dict",
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen {
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen dict_quota_alloc,
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen dict_quota_init,
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen dict_quota_deinit,
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen NULL,
12dc81583d1958cb301a617e19fbd40e8d376397Timo Sirainen NULL,
cb931f84e3ec8e3deda253a1c0ae0409023de096Timo Sirainen NULL,
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen dict_quota_root_get_resources,
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen dict_quota_get_resource,
6d6bbe8787354bbb69d0c03187adfe0f497d70b8Timo Sirainen dict_quota_update,
048e40f9364fa68482bc276dd4a5d595a3d742e9Timo Sirainen NULL,
048e40f9364fa68482bc276dd4a5d595a3d742e9Timo Sirainen dict_quota_flush
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen};