From: Timo Sirainen Date: Mon, 21 Sep 2015 13:36:05 +0000 (+0300) Subject: quota: Added "count" backend, which simply sums up mailboxes' vsizes. X-Git-Tag: 2.2.19.rc1~25 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c4db1218645ed8ec8b5ae67c05bc5d7a80c1b8ae;p=thirdparty%2Fdovecot%2Fcore.git quota: Added "count" backend, which simply sums up mailboxes' vsizes. In a way this is similar to the simple "dirsize" backend, but much more efficient. As long as mailbox_list_index=yes, the quota can typically be looked up only by reading the dovecot.list.index* files. This backend enforces using quota_vsizes=yes setting to keep the performance good, because physical sizes don't have a similar optimized vsize header. There's also no especially good reason why this backend should support physical sizes - they were originally mainly used to allow quickly stat()ing Maildir files. --- diff --git a/src/plugins/quota/quota-count.c b/src/plugins/quota/quota-count.c index 5946df4b1c..132b328ba0 100644 --- a/src/plugins/quota/quota-count.c +++ b/src/plugins/quota/quota-count.c @@ -107,3 +107,78 @@ int quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r) root->recounting = FALSE; return ret; } + +static struct quota_root *count_quota_alloc(void) +{ + return i_new(struct quota_root, 1); +} + +static int count_quota_init(struct quota_root *root, const char *args, + const char **error_r) +{ + if (!root->quota->set->vsizes) { + *error_r = "quota count backend requires quota_vsizes=yes"; + return -1; + } + return quota_root_default_init(root, args, error_r); +} + +static void count_quota_deinit(struct quota_root *_root) +{ + i_free(_root); +} + +static const char *const * +count_quota_root_get_resources(struct quota_root *root ATTR_UNUSED) +{ + static const char *resources[] = { + QUOTA_NAME_STORAGE_KILOBYTES, QUOTA_NAME_MESSAGES, NULL + }; + return resources; +} + +static int +count_quota_get_resource(struct quota_root *root, + const char *name, uint64_t *value_r) +{ + uint64_t bytes, count; + + if (quota_count(root, &bytes, &count) < 0) + return -1; + + if (strcmp(name, QUOTA_NAME_STORAGE_BYTES) == 0) + *value_r = bytes; + else if (strcmp(name, QUOTA_NAME_MESSAGES) == 0) + *value_r = count; + else + return 0; + return 1; +} + +static int +count_quota_update(struct quota_root *root ATTR_UNUSED, + struct quota_transaction_context *ctx ATTR_UNUSED) +{ + if (ctx->recalculate) { + //FIXME: remove cached values from index + } + return 0; +} + +struct quota_backend quota_backend_count = { + "count", + + { + count_quota_alloc, + count_quota_init, + count_quota_deinit, + NULL, + NULL, + NULL, + count_quota_root_get_resources, + count_quota_get_resource, + count_quota_update, + NULL, + NULL + } +}; diff --git a/src/plugins/quota/quota.c b/src/plugins/quota/quota.c index f4da6bb474..ca9ac2f899 100644 --- a/src/plugins/quota/quota.c +++ b/src/plugins/quota/quota.c @@ -29,6 +29,7 @@ struct quota_root_iter { unsigned int quota_module_id = 0; +extern struct quota_backend quota_backend_count; extern struct quota_backend quota_backend_dict; extern struct quota_backend quota_backend_dirsize; extern struct quota_backend quota_backend_fs; @@ -38,6 +39,7 @@ static const struct quota_backend *quota_backends[] = { #ifdef HAVE_FS_QUOTA "a_backend_fs, #endif + "a_backend_count, "a_backend_dict, "a_backend_dirsize, "a_backend_maildir