quota-dict.c revision 92d1458b00f4f236c4cec96a696253d3bbf8b05a
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen/* Copyright (C) 2005-2006 Timo Sirainen */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "lib.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "str.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "dict.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "quota-private.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include <stdlib.h>
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;
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
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenstatic int dict_quota_init(struct quota_root *_root, const char *args)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen struct dict_quota_root *root = (struct dict_quota_root *)_root;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen const char *username, *p;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen p = args == NULL ? NULL : strchr(args, ':');
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen if (p == NULL) {
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen i_error("dict quota: 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
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen if (*username == '\0')
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen username = getenv("USER");
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen if (getenv("DEBUG") != NULL)
19e8858fad5128326481e6cd85c9070b1345bad8Timo Sirainen i_info("dict quota: user = %s, uri = %s", username, args);
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 */
92d1458b00f4f236c4cec96a696253d3bbf8b05aTimo Sirainen root->dict = dict_init(args, DICT_DATA_TYPE_STRING, username);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen return root->dict != NULL ? 0 : -1;
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
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo 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 *
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainendict_quota_root_get_resources(struct quota_root *root __attr_unused__)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen static const char *resources[] = {
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen QUOTA_NAME_STORAGE, QUOTA_NAME_MESSAGES, NULL
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen };
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return resources;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstatic int
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainendict_quota_get_resource(struct quota_root *_root, const char *name,
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen uint64_t *value_r, uint64_t *limit __attr_unused__)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen struct dict_quota_root *root = (struct dict_quota_root *)_root;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen const char *value;
f8ead0942a9b7c8fcf91414ed1b534d5807ca555Timo Sirainen int ret;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen if (strcmp(name, QUOTA_NAME_STORAGE) == 0) {
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen t_push();
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen ret = dict_lookup(root->dict, unsafe_data_stack_pool,
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen DICT_QUOTA_CURRENT_BYTES_PATH, &value);
882897aa8345370a82487bd5c706cf26767b9f83Timo Sirainen *value_r = ret <= 0 ? 0 : strtoull(value, NULL, 10) / 1024;
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen t_pop();
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen } else if (strcmp(name, QUOTA_NAME_MESSAGES) == 0) {
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen t_push();
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen ret = dict_lookup(root->dict, unsafe_data_stack_pool,
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen DICT_QUOTA_CURRENT_COUNT_PATH, &value);
882897aa8345370a82487bd5c706cf26767b9f83Timo Sirainen *value_r = ret <= 0 ? 0 : strtoull(value, NULL, 10);
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen t_pop();
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen } else {
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen return 0;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen return ret;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo 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;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen dt = dict_transaction_begin(root->dict);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen dict_atomic_inc(dt, DICT_QUOTA_CURRENT_BYTES_PATH,
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen ctx->bytes_used);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen dict_atomic_inc(dt, DICT_QUOTA_CURRENT_COUNT_PATH,
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen ctx->count_used);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen
51dbc2d559815da774f8ee5faf0e28df3c8d40c0Timo Sirainen if (dict_transaction_commit(dt) < 0)
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen return -1;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return 0;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo 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,
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen dict_quota_root_get_resources,
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen dict_quota_get_resource,
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen dict_quota_update
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen};