Mercurial > dovecot > core-2.2
changeset 21408:a0c9a72975fc
lib-storage: Add vsize extension to index
Keep virtual size in index, instead of cache
when it's less than 2^32-1. This helps when
cache becomes corrupted, and goes away, we
still have virtual sizes for quota calculations.
author | Aki Tuomi <aki.tuomi@dovecot.fi> |
---|---|
date | Tue, 03 Jan 2017 17:21:33 +0200 |
parents | 659c06acb979 |
children | 1d5160a7b0fd |
files | src/lib-storage/index/index-mail.c src/lib-storage/index/index-mail.h |
diffstat | 2 files changed, 51 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/index-mail.c Sun Jan 15 19:56:32 2017 +0200 +++ b/src/lib-storage/index/index-mail.c Tue Jan 03 17:21:33 2017 +0200 @@ -447,7 +447,20 @@ bool index_mail_get_cached_virtual_size(struct index_mail *mail, uoff_t *size_r) { struct index_mail_data *data = &mail->data; + struct mail *_mail = &mail->mail.mail; uoff_t size; + const void *idata; + bool expunged ATTR_UNUSED; + unsigned int idx ATTR_UNUSED; + + /* see if we can get it from index */ + mail_index_lookup_ext(_mail->transaction->view, _mail->seq, + mail->vsize_ext_id, &idata, &expunged); + const uint32_t *vsize = idata; + + if (vsize != NULL && *vsize > 0) { + data->virtual_size = (*vsize)-1; + } data->cache_fetch_fields |= MAIL_FETCH_VIRTUAL_SIZE; if (data->virtual_size == (uoff_t)-1) { @@ -468,6 +481,16 @@ data->body_size_set = TRUE; } *size_r = data->virtual_size; + + /* if vsize is present and wanted for index, but missing from index + add it to index. */ + if (vsize != NULL && *vsize == 0 && + data->body_size.virtual_size < (uint32_t)-1) { + uint32_t vsize = data->body_size.virtual_size+1; + mail_index_update_ext(_mail->transaction->itrans, _mail->seq, + mail->vsize_ext_id, &vsize, NULL); + } + return TRUE; } @@ -832,16 +855,40 @@ static void index_mail_cache_sizes(struct index_mail *mail) { + struct mail *_mail = &mail->mail.mail; + struct mail_index_view *view = _mail->transaction->view; + static enum index_cache_field size_fields[] = { MAIL_CACHE_VIRTUAL_FULL_SIZE, MAIL_CACHE_PHYSICAL_FULL_SIZE }; uoff_t sizes[N_ELEMENTS(size_fields)]; unsigned int i; + uint32_t vsize; + uint32_t idx ATTR_UNUSED; sizes[0] = mail->data.virtual_size; sizes[1] = mail->data.physical_size; + /* store the virtual size in index if + extension for it exists or + extension for box virtual size exists + */ + + if ((mail_index_map_get_ext_idx(view->map, mail->vsize_ext_id, &idx) || + mail_index_map_get_ext_idx(view->map, _mail->box->vsize_hdr_ext_id, &idx)) && + (sizes[0] != (uoff_t)-1 && + sizes[0] < (uint32_t)-1)) { + /* vsize = 0 means it's not present in index, consult cache. + we store vsize for every +4GB-1 mail to cache because + index can only hold 2^32-1 size. Cache will not be used + when vsize is stored in index. */ + vsize = sizes[0] + 1; + sizes[0] = (uoff_t)-1; + mail_index_update_ext(_mail->transaction->itrans, _mail->seq, + mail->vsize_ext_id, &vsize, NULL); + } + for (i = 0; i < N_ELEMENTS(size_fields); i++) { if (sizes[i] != (uoff_t)-1 && index_mail_want_cache(mail, size_fields[i])) { @@ -1490,7 +1537,9 @@ mail->mail.v = *t->box->mail_vfuncs; mail->mail.mail.box = t->box; mail->mail.mail.transaction = t; - + mail->vsize_ext_id = mail_index_ext_register(t->box->index, "vsize", 0, + sizeof(uint32_t), + sizeof(uint32_t)); t->mail_ref_count++; mail->mail.data_pool = pool_alloconly_create("index_mail", 16384); mail->ibox = INDEX_STORAGE_CONTEXT(t->box);
--- a/src/lib-storage/index/index-mail.h Sun Jan 15 19:56:32 2017 +0200 +++ b/src/lib-storage/index/index-mail.h Tue Jan 03 17:21:33 2017 +0200 @@ -137,6 +137,7 @@ struct index_mailbox_context *ibox; int pop3_state; + uint32_t vsize_ext_id; /* per-mail variables, here for performance reasons: */ uint32_t header_seq;