From: Stephan Bosch Date: Fri, 16 Nov 2018 11:08:47 +0000 (+0100) Subject: quota: Add support for recording quota resource usage reduction from sub-transactions X-Git-Tag: 2.4.1~136 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f93efcb7397d2c6ab0357bab8c2b98c7c75868fe;p=thirdparty%2Fdovecot%2Fcore.git quota: Add support for recording quota resource usage reduction from sub-transactions Such transactions apply their own quota modifications, so modifying the usage fields for the present transaction would cause such modifications to be counted several times. However, their effect must be applied in the quota limit calculations, so the amount of resources expunged in sub-transactions is recorded in separate fields. --- diff --git a/src/plugins/quota/quota-private.h b/src/plugins/quota/quota-private.h index f532e83340..72fdbc6e21 100644 --- a/src/plugins/quota/quota-private.h +++ b/src/plugins/quota/quota-private.h @@ -109,6 +109,14 @@ struct quota_transaction_root_context { only once and not updated by bytes_used/count_used. (Either *_ceil or *_over is always zero.) */ uint64_t bytes_over, count_over; + + /* Quota resource usage reduction performed in separate transactions. + Hence, these changes are already committed and must not be counted + a second time in this transaction. These values are used in the + limit calculations though, since the limits were recorded at the + start of the transaction and these reductions were performed some + time later. */ + uint64_t bytes_expunged, count_expunged; }; struct quota_transaction_context { @@ -121,7 +129,17 @@ struct quota_transaction_context { struct quota_transaction_root_context *roots; + /* Quota resource usage changes relative to the start of the + transaction. */ int64_t bytes_used, count_used; + /* Quota resource usage reduction performed in separate transactions. + Hence, these changes are already committed and must not be counted + a second time in this transaction. These values are used in the + limit calculations though, since the limits were recorded at the + start of the transaction and these reductions were performed some + time later. */ + uint64_t bytes_expunged, count_expunged; + /* how many bytes/mails can be saved until limit is reached. (set once, not updated by bytes_used/count_used). diff --git a/src/plugins/quota/quota-util.c b/src/plugins/quota/quota-util.c index 4435f9417f..feb8ac87de 100644 --- a/src/plugins/quota/quota-util.c +++ b/src/plugins/quota/quota-util.c @@ -145,10 +145,16 @@ void quota_used_apply_expunged(int64_t *used, uint64_t expunged) bool quota_transaction_is_over(struct quota_transaction_context *ctx, uoff_t size) { - if (quota_is_over(1, ctx->count_used, ctx->count_ceil, + int64_t count_used = ctx->count_used; + int64_t bytes_used = ctx->bytes_used; + + quota_used_apply_expunged(&count_used, ctx->count_expunged); + quota_used_apply_expunged(&bytes_used, ctx->bytes_expunged); + + if (quota_is_over(1, count_used, ctx->count_ceil, ctx->count_over, NULL)) return TRUE; - if (quota_is_over(size, ctx->bytes_used, ctx->bytes_ceil, + if (quota_is_over(size, bytes_used, ctx->bytes_ceil, ctx->bytes_over, NULL)) return TRUE; return FALSE; @@ -159,13 +165,19 @@ bool quota_root_is_over(struct quota_transaction_context *ctx, uoff_t count_alloc, uoff_t bytes_alloc, uoff_t *count_overrun_r, uoff_t *bytes_overrun_r) { + int64_t count_used = ctx->count_used; + int64_t bytes_used = ctx->bytes_used; + *count_overrun_r = 0; *bytes_overrun_r = 0; - return (quota_is_over(count_alloc, ctx->count_used, + quota_used_apply_expunged(&count_used, root->count_expunged); + quota_used_apply_expunged(&bytes_used, root->bytes_expunged); + + return (quota_is_over(count_alloc, count_used, root->count_ceil, root->count_over, count_overrun_r) || - quota_is_over(bytes_alloc, ctx->bytes_used, + quota_is_over(bytes_alloc, bytes_used, root->bytes_ceil, root->bytes_over, bytes_overrun_r)); }