dovecot-2.2: lib-index: mail_cache_lookup*() can now return fiel...
dovecot at dovecot.org
dovecot at dovecot.org
Sun May 26 19:05:37 EEST 2013
details: http://hg.dovecot.org/dovecot-2.2/rev/b9a312951881
changeset: 16393:b9a312951881
user: Timo Sirainen <tss at iki.fi>
date: Sun May 26 19:04:00 2013 +0300
description:
lib-index: mail_cache_lookup*() can now return fields recently added with mail_cache_add()
Previously it was returning them if they had already been written to
dovecot.index.cache, but not if they were still in the in-memory buffer.
This avoids caching/parsing the same field multiple times when messages
aren't accessed in ascending order (e.g. when sorting messages).
diffstat:
src/lib-index/mail-cache-lookup.c | 39 +++++++++++++++++++++++----
src/lib-index/mail-cache-private.h | 9 +++++-
src/lib-index/mail-cache-transaction.c | 47 +++++++++++++++++++++++++++------
3 files changed, 79 insertions(+), 16 deletions(-)
diffs (215 lines):
diff -r af9947e1e5f7 -r b9a312951881 src/lib-index/mail-cache-lookup.c
--- a/src/lib-index/mail-cache-lookup.c Thu May 23 17:36:54 2013 +0300
+++ b/src/lib-index/mail-cache-lookup.c Sun May 26 19:04:00 2013 +0300
@@ -163,31 +163,58 @@
memset(&view->loop_track, 0, sizeof(view->loop_track));
}
+static bool
+mail_cache_lookup_iter_transaction(struct mail_cache_lookup_iterate_ctx *ctx)
+{
+ ctx->rec = mail_cache_transaction_lookup_rec(ctx->view->transaction,
+ ctx->seq,
+ &ctx->trans_next_idx);
+ if (ctx->rec == NULL)
+ return FALSE;
+
+ ctx->remap_counter = ctx->view->cache->remap_counter;
+ ctx->pos = sizeof(*ctx->rec);
+ ctx->rec_size = ctx->rec->size;
+ return TRUE;
+}
+
static int
mail_cache_lookup_iter_next_record(struct mail_cache_lookup_iterate_ctx *ctx)
{
struct mail_cache_view *view = ctx->view;
- if (ctx->stop)
- return ctx->failed ? -1 : 0;
+ if (ctx->failed)
+ return -1;
if (ctx->rec != NULL)
ctx->offset = ctx->rec->prev_offset;
if (ctx->offset == 0) {
/* end of this record list. check newly appended data. */
- if (ctx->appends_checked ||
- view->trans_seq1 > ctx->seq ||
+ if (view->trans_seq1 > ctx->seq ||
view->trans_seq2 < ctx->seq ||
- MAIL_CACHE_IS_UNUSABLE(view->cache) ||
+ MAIL_CACHE_IS_UNUSABLE(view->cache))
+ return 0;
+ /* check data still in memory */
+ if (!ctx->memory_appends_checked) {
+ if (mail_cache_lookup_iter_transaction(ctx))
+ return 1;
+ ctx->memory_appends_checked = TRUE;
+ }
+
+ /* check data already written to cache file */
+ if (ctx->disk_appends_checked ||
mail_cache_lookup_offset(view->cache, view->trans_view,
ctx->seq, &ctx->offset) <= 0)
return 0;
- ctx->appends_checked = TRUE;
+ ctx->disk_appends_checked = TRUE;
ctx->remap_counter = view->cache->remap_counter;
memset(&view->loop_track, 0, sizeof(view->loop_track));
}
+ if (ctx->stop)
+ return 0;
+
/* look up the next record */
if (mail_cache_get_record(view->cache, ctx->offset, &ctx->rec) < 0)
return -1;
diff -r af9947e1e5f7 -r b9a312951881 src/lib-index/mail-cache-private.h
--- a/src/lib-index/mail-cache-private.h Thu May 23 17:36:54 2013 +0300
+++ b/src/lib-index/mail-cache-private.h Sun May 26 19:04:00 2013 +0300
@@ -202,9 +202,12 @@
unsigned int pos, rec_size;
uint32_t offset;
+ unsigned int trans_next_idx;
+
unsigned int stop:1;
unsigned int failed:1;
- unsigned int appends_checked:1;
+ unsigned int memory_appends_checked:1;
+ unsigned int disk_appends_checked:1;
};
/* Explicitly lock the cache file. Returns -1 if error / timed out,
@@ -243,6 +246,10 @@
/* Returns 1 if field was returned, 0 if end of fields, or -1 if error */
int mail_cache_lookup_iter_next(struct mail_cache_lookup_iterate_ctx *ctx,
struct mail_cache_iterate_field *field_r);
+const struct mail_cache_record *
+mail_cache_transaction_lookup_rec(struct mail_cache_transaction_ctx *ctx,
+ unsigned int seq,
+ unsigned int *trans_next_idx);
int mail_cache_map(struct mail_cache *cache, size_t offset, size_t size,
const void **data_r);
diff -r af9947e1e5f7 -r b9a312951881 src/lib-index/mail-cache-transaction.c
--- a/src/lib-index/mail-cache-transaction.c Thu May 23 17:36:54 2013 +0300
+++ b/src/lib-index/mail-cache-transaction.c Sun May 26 19:04:00 2013 +0300
@@ -21,6 +21,11 @@
#define CACHE_TRANS_CONTEXT(obj) \
MODULE_CONTEXT(obj, cache_mail_index_transaction_module)
+struct mail_cache_transaction_rec {
+ uint32_t seq;
+ uint32_t cache_data_pos;
+};
+
struct mail_cache_transaction_ctx {
union mail_index_transaction_module_context module_ctx;
struct mail_index_transaction_vfuncs super;
@@ -33,7 +38,7 @@
uint32_t first_new_seq;
buffer_t *cache_data;
- ARRAY(uint32_t) cache_data_seq;
+ ARRAY(struct mail_cache_transaction_rec) cache_data_seq;
uint32_t prev_seq, min_seq;
size_t last_rec_pos;
@@ -272,13 +277,33 @@
return 1;
}
+const struct mail_cache_record *
+mail_cache_transaction_lookup_rec(struct mail_cache_transaction_ctx *ctx,
+ unsigned int seq,
+ unsigned int *trans_next_idx)
+{
+ const struct mail_cache_transaction_rec *recs;
+ unsigned int i, count;
+
+ recs = array_get(&ctx->cache_data_seq, &count);
+ for (i = *trans_next_idx; i < count; i++) {
+ if (recs[i].seq == seq) {
+ *trans_next_idx = i + 1;
+ return CONST_PTR_OFFSET(ctx->cache_data->data,
+ recs[i].cache_data_pos);
+ }
+ }
+ *trans_next_idx = i;
+ return NULL;
+}
+
static int
mail_cache_transaction_update_index(struct mail_cache_transaction_ctx *ctx,
uint32_t write_offset)
{
struct mail_cache *cache = ctx->cache;
const struct mail_cache_record *rec = ctx->cache_data->data;
- const uint32_t *seqs;
+ const struct mail_cache_transaction_rec *recs;
uint32_t i, seq_count;
mail_index_ext_using_reset_id(ctx->trans, ctx->cache->ext_id,
@@ -287,9 +312,9 @@
/* write the cache_offsets to index file. records' prev_offset
is updated to point to old cache record when index is being
synced. */
- seqs = array_get(&ctx->cache_data_seq, &seq_count);
+ recs = array_get(&ctx->cache_data_seq, &seq_count);
for (i = 0; i < seq_count; i++) {
- mail_index_update_ext(ctx->trans, seqs[i], cache->ext_id,
+ mail_index_update_ext(ctx->trans, recs[i].seq, cache->ext_id,
&write_offset, NULL);
write_offset += rec->size;
@@ -304,7 +329,8 @@
{
struct mail_index_map *map;
struct mail_cache_record *rec;
- const uint32_t *seqs, *prev_offsetp;
+ const struct mail_cache_transaction_rec *recs;
+ const uint32_t *prev_offsetp;
ARRAY_TYPE(uint32_t) seq_offsets;
uint32_t i, seq_count, reset_id, prev_offset, *offsetp;
const void *data;
@@ -312,15 +338,15 @@
i_assert(ctx->min_seq != 0);
i_array_init(&seq_offsets, 64);
- seqs = array_get(&ctx->cache_data_seq, &seq_count);
+ recs = array_get(&ctx->cache_data_seq, &seq_count);
rec = buffer_get_modifiable_data(ctx->cache_data, NULL);
for (i = 0; i < seq_count; i++) {
offsetp = array_idx_modifiable(&seq_offsets,
- seqs[i] - ctx->min_seq);
+ recs[i].seq - ctx->min_seq);
if (*offsetp != 0)
prev_offset = *offsetp;
else {
- mail_index_lookup_ext_full(ctx->view->trans_view, seqs[i],
+ mail_index_lookup_ext_full(ctx->view->trans_view, recs[i].seq,
ctx->cache->ext_id, &map,
&data, NULL);
prev_offsetp = data;
@@ -423,6 +449,7 @@
static void
mail_cache_transaction_update_last_rec(struct mail_cache_transaction_ctx *ctx)
{
+ struct mail_cache_transaction_rec *trans_rec;
struct mail_cache_record *rec;
void *data;
size_t size;
@@ -439,7 +466,9 @@
if (ctx->min_seq > ctx->prev_seq || ctx->min_seq == 0)
ctx->min_seq = ctx->prev_seq;
- array_append(&ctx->cache_data_seq, &ctx->prev_seq, 1);
+ trans_rec = array_append_space(&ctx->cache_data_seq);
+ trans_rec->seq = ctx->prev_seq;
+ trans_rec->cache_data_pos = ctx->last_rec_pos;
ctx->last_rec_pos = size;
}
More information about the dovecot-cvs
mailing list