dovecot: Changed mail_cache_foreach() to be an iterator: mail_ca...
dovecot at dovecot.org
dovecot at dovecot.org
Thu Jun 14 04:40:38 EEST 2007
details: http://hg.dovecot.org/dovecot/rev/b3ed52bbeca7
changeset: 5736:b3ed52bbeca7
user: Timo Sirainen <tss at iki.fi>
date: Thu Jun 14 04:40:34 2007 +0300
description:
Changed mail_cache_foreach() to be an iterator: mail_cache_lookup_iter_*()
diffstat:
4 files changed, 281 insertions(+), 255 deletions(-)
src/lib-index/mail-cache-compress.c | 57 ++--
src/lib-index/mail-cache-lookup.c | 443 +++++++++++++++++------------------
src/lib-index/mail-cache-private.h | 33 ++
src/lib-index/mail-cache.c | 3
diffs (truncated from 774 to 300 lines):
diff -r 5763c2548153 -r b3ed52bbeca7 src/lib-index/mail-cache-compress.c
--- a/src/lib-index/mail-cache-compress.c Thu Jun 14 04:05:13 2007 +0300
+++ b/src/lib-index/mail-cache-compress.c Thu Jun 14 04:40:34 2007 +0300
@@ -14,9 +14,11 @@
#include <sys/stat.h>
struct mail_cache_copy_context {
- bool new_msg;
+ struct mail_cache *cache;
+
buffer_t *buffer, *field_seen;
uint8_t field_seen_value;
+ bool new_msg;
};
static void mail_cache_merge_bitmask(struct mail_cache *cache, buffer_t *buffer,
@@ -56,49 +58,49 @@ static void mail_cache_merge_bitmask(str
}
}
-static int
-mail_cache_compress_callback(struct mail_cache_view *view, uint32_t field,
- const void *data, size_t data_size, void *context)
-{
- struct mail_cache_copy_context *ctx = context;
+static void
+mail_cache_compress_field(struct mail_cache_copy_context *ctx,
+ const struct mail_cache_iterate_field *field)
+{
+ uint32_t field_idx = field->field_idx;
struct mail_cache_field *cache_field;
enum mail_cache_decision_type dec;
uint8_t *field_seen;
uint32_t size32;
- cache_field = &view->cache->fields[field].field;
-
- field_seen = buffer_get_space_unsafe(ctx->field_seen, field, 1);
+ cache_field = &ctx->cache->fields[field_idx].field;
+
+ field_seen = buffer_get_space_unsafe(ctx->field_seen, field_idx, 1);
if (*field_seen == ctx->field_seen_value) {
/* duplicate */
if (cache_field->type == MAIL_CACHE_FIELD_BITMASK) {
- mail_cache_merge_bitmask(view->cache, ctx->buffer,
- field, data, data_size);
- }
- return 1;
+ mail_cache_merge_bitmask(ctx->cache, ctx->buffer,
+ field_idx, field->data,
+ field->size);
+ }
+ return;
}
*field_seen = ctx->field_seen_value;
dec = cache_field->decision & ~MAIL_CACHE_DECISION_FORCED;
if (ctx->new_msg) {
if (dec == MAIL_CACHE_DECISION_NO)
- return 1;
+ return;
} else {
if (dec != MAIL_CACHE_DECISION_YES)
- return 1;
- }
-
- buffer_append(ctx->buffer, &field, sizeof(field));
+ return;
+ }
+
+ buffer_append(ctx->buffer, &field_idx, sizeof(field_idx));
if (cache_field->field_size == (unsigned int)-1) {
- size32 = (uint32_t)data_size;
+ size32 = (uint32_t)field->size;
buffer_append(ctx->buffer, &size32, sizeof(size32));
}
- buffer_append(ctx->buffer, data, data_size);
- if ((data_size & 3) != 0)
- buffer_append_zero(ctx->buffer, 4 - (data_size & 3));
- return 1;
+ buffer_append(ctx->buffer, field->data, field->size);
+ if ((field->size & 3) != 0)
+ buffer_append_zero(ctx->buffer, 4 - (field->size & 3));
}
static uint32_t
@@ -118,6 +120,8 @@ mail_cache_copy(struct mail_cache *cache
ARRAY_TYPE(uint32_t) *ext_offsets)
{
struct mail_cache_copy_context ctx;
+ struct mail_cache_lookup_iterate_ctx iter;
+ struct mail_cache_iterate_field field;
struct mail_index_view *view;
struct mail_cache_view *cache_view;
const struct mail_index_header *idx_hdr;
@@ -155,6 +159,7 @@ mail_cache_copy(struct mail_cache *cache
o_stream_send(output, &hdr, sizeof(hdr));
memset(&ctx, 0, sizeof(ctx));
+ ctx.cache = cache;
ctx.buffer = buffer_create_dynamic(default_pool, 4096);
ctx.field_seen = buffer_create_dynamic(default_pool, 64);
ctx.field_seen_value = 0;
@@ -178,8 +183,9 @@ mail_cache_copy(struct mail_cache *cache
memset(&cache_rec, 0, sizeof(cache_rec));
buffer_append(ctx.buffer, &cache_rec, sizeof(cache_rec));
- (void)mail_cache_foreach(cache_view, seq,
- mail_cache_compress_callback, &ctx);
+ mail_cache_lookup_iter_init(cache_view, seq, &iter);
+ while (mail_cache_lookup_iter_next(&iter, &field) > 0)
+ mail_cache_compress_field(&ctx, &field);
cache_rec.size = buffer_get_used_size(ctx.buffer);
if (cache_rec.size == sizeof(cache_rec)) {
@@ -295,6 +301,7 @@ static int mail_cache_compress_locked(st
unsigned int i, count;
int fd, ret;
+ i_warning("cache compress");
/* get the latest info on fields */
if (mail_cache_header_fields_read(cache) < 0)
return -1;
diff -r 5763c2548153 -r b3ed52bbeca7 src/lib-index/mail-cache-lookup.c
--- a/src/lib-index/mail-cache-lookup.c Thu Jun 14 04:05:13 2007 +0300
+++ b/src/lib-index/mail-cache-lookup.c Thu Jun 14 04:40:34 2007 +0300
@@ -88,81 +88,6 @@ mail_cache_lookup_offset(struct mail_cac
return 1;
}
-static int
-mail_cache_foreach_rec(struct mail_cache_view *view, uint32_t *offset,
- mail_cache_foreach_callback_t *callback, void *context)
-{
- struct mail_cache *cache = view->cache;
- const struct mail_cache_record *rec;
- unsigned int data_size;
- uint32_t pos, rec_size, file_field;
- unsigned int field;
- int ret;
-
- if (mail_cache_get_record(view->cache, *offset, &rec) < 0)
- return -1;
-
- rec_size = rec->size;
- for (pos = sizeof(*rec); pos + sizeof(uint32_t) <= rec_size; ) {
- file_field = *((const uint32_t *)CONST_PTR_OFFSET(rec, pos));
- pos += sizeof(uint32_t);
-
- if (file_field >= cache->file_fields_count) {
- /* new field, have to re-read fields header to figure
- out its size */
- if (mail_cache_header_fields_read(cache) < 0)
- return -1;
- if (file_field >= cache->file_fields_count) {
- mail_cache_set_corrupted(cache,
- "field index too large (%u >= %u)",
- file_field, cache->file_fields_count);
- return -1;
- }
-
- /* field reading might have re-mmaped the file and
- caused rec pointer to break. need to get it again. */
- if (mail_cache_get_record(view->cache, *offset,
- &rec) < 0)
- return -1;
- }
-
- field = cache->file_field_map[file_field];
- data_size = cache->fields[field].field.field_size;
- if (data_size == (unsigned int)-1) {
- /* variable size field. get its size from the file. */
- if (pos + sizeof(uint32_t) > rec_size) {
- /* broken. we'll catch this error below. */
- } else {
- data_size = *((const uint32_t *)
- CONST_PTR_OFFSET(rec, pos));
- pos += sizeof(uint32_t);
- }
- }
-
- if (rec_size - pos < data_size) {
- mail_cache_set_corrupted(cache,
- "record continues outside its allocated size");
- return -1;
- }
-
- ret = callback(view, field, CONST_PTR_OFFSET(rec, pos),
- data_size, context);
- if (ret != 1)
- return ret;
-
- /* each record begins from 32bit aligned position */
- pos += (data_size + sizeof(uint32_t)-1) & ~(sizeof(uint32_t)-1);
- }
-
- if (pos != rec_size) {
- mail_cache_set_corrupted(cache, "record has invalid size");
- return -1;
- }
-
- *offset = rec->prev_offset;
- return 1;
-}
-
bool mail_cache_track_loops(ARRAY_TYPE(uint32_t) *array, uint32_t offset)
{
const uint32_t *offsets;
@@ -177,66 +102,142 @@ bool mail_cache_track_loops(ARRAY_TYPE(u
return FALSE;
}
-int mail_cache_foreach(struct mail_cache_view *view, uint32_t seq,
- mail_cache_foreach_callback_t *callback, void *context)
-{
- uint32_t offset;
- int ret;
+void mail_cache_lookup_iter_init(struct mail_cache_view *view, uint32_t seq,
+ struct mail_cache_lookup_iterate_ctx *ctx_r)
+{
+ struct mail_cache_lookup_iterate_ctx *ctx = ctx_r;
if (!view->cache->opened)
(void)mail_cache_open_and_verify(view->cache);
- if (MAIL_CACHE_IS_UNUSABLE(view->cache))
- return 0;
-
- if ((ret = mail_cache_lookup_offset(view->cache, view->view,
- seq, &offset)) <= 0)
- return ret;
-
- ret = 1;
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->view = view;
+ ctx->seq = seq;
+
+ if (!MAIL_CACHE_IS_UNUSABLE(view->cache)) {
+ /* look up the first offset */
+ if (mail_cache_lookup_offset(view->cache, view->view, seq,
+ &ctx->offset) < 0)
+ ctx->failed = TRUE;
+ }
+ ctx->remap_counter = view->cache->remap_counter;
+
array_clear(&view->looping_offsets);
- while (offset != 0 && ret > 0) {
- if (mail_cache_track_loops(&view->looping_offsets, offset)) {
- mail_cache_set_corrupted(view->cache,
- "record list is circular");
- return -1;
- }
- ret = mail_cache_foreach_rec(view, &offset,
- callback, context);
- }
-
- if (ret > 0 && view->trans_seq1 <= seq && view->trans_seq2 >= seq &&
- mail_cache_lookup_offset(view->cache, view->trans_view,
- seq, &offset) > 0) {
+}
+
+static int
+mail_cache_lookup_iter_next_record(struct mail_cache_lookup_iterate_ctx *ctx)
+{
+ struct mail_cache_view *view = ctx->view;
+
+ 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 ||
+ view->trans_seq2 < ctx->seq ||
+ mail_cache_lookup_offset(view->cache, view->trans_view,
+ ctx->seq, &ctx->offset) <= 0)
+ return 0;
+
+ ctx->appends_checked = TRUE;
+ ctx->remap_counter = view->cache->remap_counter;
array_clear(&view->looping_offsets);
- while (offset != 0 && ret > 0) {
- if (mail_cache_track_loops(&view->looping_offsets,
- offset)) {
- mail_cache_set_corrupted(view->cache,
- "record list is circular");
- return -1;
- }
- ret = mail_cache_foreach_rec(view, &offset,
- callback, context);
- }
- }
-
- return ret;
-}
-
More information about the dovecot-cvs
mailing list