changeset 7130:26dbad6c08f3 HEAD

If a message was expunged but is still visible in a view, its flags/keywords might have been updated if an uid range included the expunged message.
author Timo Sirainen <tss@iki.fi>
date Sun, 06 Jan 2008 11:59:21 +0200
parents 0c1859ca8ee9
children 0355a4603e80
files src/lib-index/mail-index-sync-keywords.c src/lib-index/mail-index-sync-private.h src/lib-index/mail-index-sync-update.c src/lib-index/mail-index-view-sync.c
diffstat 4 files changed, 100 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-index-sync-keywords.c	Sun Jan 06 11:24:04 2008 +0200
+++ b/src/lib-index/mail-index-sync-keywords.c	Sun Jan 06 11:59:21 2008 +0200
@@ -191,23 +191,19 @@
 	i_assert(*keyword_idx_r / CHAR_BIT < ext->record_size);
 }
 
-static int
+static void
 keywords_update_records(struct mail_index_sync_map_ctx *ctx,
 			const struct mail_index_ext *ext,
 			unsigned int keyword_idx, enum modify_type type,
-			uint32_t uid1, uint32_t uid2)
+			uint32_t seq1, uint32_t seq2)
 {
 	struct mail_index_view *view = ctx->view;
 	struct mail_index_record *rec;
 	unsigned char *data, data_mask;
 	unsigned int data_offset;
-	uint32_t seq1, seq2;
 
 	i_assert(keyword_idx != (unsigned int)-1);
 
-	if (!mail_index_lookup_seq_range(view, uid1, uid2, &seq1, &seq2))
-		return 1;
-
 	mail_index_sync_write_seq_update(ctx, seq1, seq2);
 
 	data_offset = keyword_idx / CHAR_BIT;
@@ -237,7 +233,6 @@
 	default:
 		i_unreached();
 	}
-	return 1;
 }
 
 int mail_index_sync_keywords(struct mail_index_sync_map_ctx *ctx,
@@ -248,9 +243,10 @@
 	const char *keyword_name;
 	const struct mail_index_ext *ext;
 	const uint32_t *uid, *end;
+	struct sync_uid_range_iter iter;
+	uint32_t seq1, seq2;
 	uint32_t seqset_offset, ext_map_idx;
 	unsigned int keyword_idx;
-	int ret;
 
 	seqset_offset = sizeof(*rec) + rec->name_size;
 	if ((seqset_offset % 4) != 0)
@@ -293,12 +289,11 @@
 	}
 
 	while (uid+2 <= end) {
-		ret = keywords_update_records(ctx, ext, keyword_idx,
-					      rec->modify_type,
-					      uid[0], uid[1]);
-		if (ret <= 0)
-			return ret;
-
+		sync_uid_range_iter_init(&iter, ctx, uid[0], uid[1]);
+		while (sync_uid_range_iter_next(&iter, &seq1, &seq2)) {
+			keywords_update_records(ctx, ext, keyword_idx,
+						rec->modify_type, seq1, seq2);
+		}
 		uid += 2;
 	}
 
@@ -314,6 +309,7 @@
 	struct mail_index_record *rec;
 	const struct mail_index_ext *ext;
 	const struct mail_transaction_keyword_reset *end;
+	struct sync_uid_range_iter iter;
 	uint32_t ext_map_idx, seq1, seq2;
 
 	if (!mail_index_map_lookup_ext(map, "keywords", &ext_map_idx)) {
@@ -324,15 +320,14 @@
 	ext = array_idx(&map->extensions, ext_map_idx);
 	end = CONST_PTR_OFFSET(r, hdr->size);
 	for (; r != end; r++) {
-		if (!mail_index_lookup_seq_range(ctx->view, r->uid1, r->uid2,
-						 &seq1, &seq2))
-			continue;
-
-		mail_index_sync_write_seq_update(ctx, seq1, seq2);
-		for (seq1--; seq1 < seq2; seq1++) {
-			rec = MAIL_INDEX_MAP_IDX(map, seq1);
-			memset(PTR_OFFSET(rec, ext->record_offset),
-			       0, ext->record_size);
+		sync_uid_range_iter_init(&iter, ctx, r->uid1, r->uid2);
+		while (sync_uid_range_iter_next(&iter, &seq1, &seq2)) {
+			mail_index_sync_write_seq_update(ctx, seq1, seq2);
+			for (seq1--; seq1 < seq2; seq1++) {
+				rec = MAIL_INDEX_MAP_IDX(map, seq1);
+				memset(PTR_OFFSET(rec, ext->record_offset),
+				       0, ext->record_size);
+			}
 		}
 	}
 	return 1;
--- a/src/lib-index/mail-index-sync-private.h	Sun Jan 06 11:24:04 2008 +0200
+++ b/src/lib-index/mail-index-sync-private.h	Sun Jan 06 11:59:21 2008 +0200
@@ -8,6 +8,11 @@
 };
 ARRAY_DEFINE_TYPE(uid_range, struct uid_range);
 
+struct sync_uid_range_iter {
+	struct mail_index_sync_map_ctx *ctx;
+	uint32_t seq1, seq2;
+};
+
 struct mail_index_sync_list {
 	const ARRAY_TYPE(uid_range) *array;
 	unsigned int idx;
@@ -52,6 +57,12 @@
 int mail_index_sync_map(struct mail_index_map **map,
 			enum mail_index_sync_handler_type type, bool force);
 
+void sync_uid_range_iter_init(struct sync_uid_range_iter *iter,
+			      struct mail_index_sync_map_ctx *ctx,
+			      uint32_t uid1, uint32_t uid2);
+bool sync_uid_range_iter_next(struct sync_uid_range_iter *iter,
+			      uint32_t *seq1_r, uint32_t *seq2_r);
+
 int mail_index_sync_record(struct mail_index_sync_map_ctx *ctx,
 			   const struct mail_transaction_header *hdr,
 			   const void *data);
--- a/src/lib-index/mail-index-sync-update.c	Sun Jan 06 11:24:04 2008 +0200
+++ b/src/lib-index/mail-index-sync-update.c	Sun Jan 06 11:59:21 2008 +0200
@@ -88,6 +88,55 @@
 	return ctx->view->map;
 }
 
+void sync_uid_range_iter_init(struct sync_uid_range_iter *iter,
+			      struct mail_index_sync_map_ctx *ctx,
+			      uint32_t uid1, uint32_t uid2)
+{
+	memset(iter, 0, sizeof(*iter));
+	iter->ctx = ctx;
+	if (!mail_index_lookup_seq_range(ctx->view, uid1, uid2,
+					 &iter->seq1, &iter->seq2))
+		iter->seq1 = 1;
+}
+
+bool sync_uid_range_iter_next(struct sync_uid_range_iter *iter,
+			      uint32_t *seq1_r, uint32_t *seq2_r)
+{
+	struct mail_index_view *view;
+	uint32_t seq;
+
+	if (iter->seq1 > iter->seq2)
+		return FALSE;
+
+	if (iter->ctx->type != MAIL_INDEX_SYNC_HANDLER_VIEW) {
+		*seq1_r = iter->seq1;
+		*seq2_r = iter->seq2;
+		iter->seq1 = iter->seq2 + 1;
+		return TRUE;
+	}
+	view = iter->ctx->view;
+
+	/* with views we have to drop expunged messages from the range.
+	   first skip over any expunged messages from the beginning of the
+	   range. */
+	for (seq = iter->seq1; seq <= iter->seq2; seq++) {
+		if (!mail_index_is_expunged(view, seq))
+			break;
+	}
+	if (seq > iter->seq2)
+		return FALSE;
+	*seq1_r = seq;
+
+	/* go forward until we find the first expunged message */
+	for (seq++; seq <= iter->seq2; seq++) {
+		if (mail_index_is_expunged(view, seq))
+			break;
+	}
+	*seq2_r = seq - 1;
+	iter->seq1 = seq;
+	return TRUE;
+}
+
 static int
 mail_index_header_update_counts(struct mail_index_header *hdr,
 				uint8_t old_flags, uint8_t new_flags,
@@ -338,16 +387,14 @@
 	return 1;
 }
 
-static int sync_flag_update(const struct mail_transaction_flag_update *u,
-			    struct mail_index_sync_map_ctx *ctx)
+static void sync_flag_update_range(struct mail_index_sync_map_ctx *ctx,
+				   const struct mail_transaction_flag_update *u,
+				   uint32_t seq1, uint32_t seq2)
 {
 	struct mail_index_view *view = ctx->view;
 	struct mail_index_record *rec;
 	uint8_t flag_mask, old_flags;
-	uint32_t idx, seq1, seq2;
-
-	if (!mail_index_lookup_seq_range(view, u->uid1, u->uid2, &seq1, &seq2))
-		return 1;
+	uint32_t idx;
 
 	mail_index_sync_write_seq_update(ctx, seq1, seq2);
 
@@ -377,6 +424,17 @@
 							     rec->flags, TRUE);
 		}
 	}
+}
+
+static int sync_flag_update(const struct mail_transaction_flag_update *u,
+			    struct mail_index_sync_map_ctx *ctx)
+{
+	struct sync_uid_range_iter iter;
+	uint32_t seq1, seq2;
+
+	sync_uid_range_iter_init(&iter, ctx, u->uid1, u->uid2);
+	while (sync_uid_range_iter_next(&iter, &seq1, &seq2))
+		sync_flag_update_range(ctx, u, seq1, seq2);
 	return 1;
 }
 
--- a/src/lib-index/mail-index-view-sync.c	Sun Jan 06 11:24:04 2008 +0200
+++ b/src/lib-index/mail-index-view-sync.c	Sun Jan 06 11:59:21 2008 +0200
@@ -309,8 +309,6 @@
 	ctx->expunges = expunges;
 	ctx->finish_min_msg_count = reset || quick_sync ? 0 :
 		view->map->hdr.messages_count - expunge_count;
-	mail_index_sync_map_init(&ctx->sync_map_ctx, view,
-				 MAIL_INDEX_SYNC_HANDLER_VIEW);
 
 	if (reset && view->map->hdr.messages_count > 0 &&
 	    (flags & MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT) == 0) {
@@ -360,6 +358,11 @@
 		}
 	}
 
+	if (ctx->sync_map_update) {
+		mail_index_sync_map_init(&ctx->sync_map_ctx, view,
+					 MAIL_INDEX_SYNC_HANDLER_VIEW);
+	}
+
 #ifdef DEBUG
 	mail_index_map_check(view->map);
 #endif
@@ -686,7 +689,8 @@
 		view->map->hdr.log_file_tail_offset = 0;
 	}
 
-	mail_index_sync_map_deinit(&ctx->sync_map_ctx);
+	if (ctx->sync_map_update)
+		mail_index_sync_map_deinit(&ctx->sync_map_ctx);
 	mail_index_view_sync_clean_log_syncs(ctx->view);
 
 #ifdef DEBUG