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