dovecot: Removed syncs_done array. Instead track appends and exp...

dovecot at dovecot.org dovecot at dovecot.org
Fri Jun 15 23:52:50 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/c71f611bbffc
changeset: 5747:c71f611bbffc
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Jun 15 23:13:56 2007 +0300
description:
Removed syncs_done array. Instead track appends and expunges separately.
Also fixed handling no-appends in some situations.

diffstat:

4 files changed, 189 insertions(+), 156 deletions(-)
src/lib-index/mail-index-view-private.h |    9 
src/lib-index/mail-index-view-sync.c    |  315 ++++++++++++++++---------------
src/lib-index/mail-index-view.c         |   18 +
src/lib-index/mail-transaction-log.h    |    3 

diffs (truncated from 552 to 300 lines):

diff -r 5378991bed09 -r c71f611bbffc src/lib-index/mail-index-view-private.h
--- a/src/lib-index/mail-index-view-private.h	Fri Jun 15 20:53:18 2007 +0300
+++ b/src/lib-index/mail-index-view-private.h	Fri Jun 15 23:13:56 2007 +0300
@@ -54,10 +54,11 @@ struct mail_index_view {
 
 	struct mail_index_header hdr;
 
-	uint32_t log_file_seq;
-	uoff_t log_file_offset;
-	/* Transaction log offsets which we have already synced */
-	ARRAY_TYPE(view_log_sync_area) syncs_done;
+	/* (append, expunge) <= head */
+	uint32_t log_file_append_seq, log_file_expunge_seq, log_file_head_seq;
+	uoff_t log_file_append_offset, log_file_expunge_offset;
+	uoff_t log_file_head_offset;
+
 	/* Transaction log offsets which we don't want to return in view sync */
 	ARRAY_TYPE(view_log_sync_area) syncs_hidden;
 
diff -r 5378991bed09 -r c71f611bbffc src/lib-index/mail-index-view-sync.c
--- a/src/lib-index/mail-index-view-sync.c	Fri Jun 15 20:53:18 2007 +0300
+++ b/src/lib-index/mail-index-view-sync.c	Fri Jun 15 23:13:56 2007 +0300
@@ -17,9 +17,10 @@ struct mail_index_view_sync_ctx {
 	const void *data;
 
 	size_t data_offset;
-	unsigned int skipped_some:1;
+	unsigned int sync_map_update:1;
+	unsigned int skipped_appends:1;
+	unsigned int skipped_expunges:1;
 	unsigned int last_read:1;
-	unsigned int sync_map_update:1;
 };
 
 static int
@@ -87,15 +88,36 @@ mail_transaction_log_sort_expunges(ARRAY
 	return 0;
 }
 
+static void view_sync_get_tail(struct mail_index_view *view,
+			       uint32_t *seq_r, uoff_t *offset_r)
+{
+	if (LOG_IS_BEFORE(view->log_file_append_seq,
+			  view->log_file_append_offset,
+			  view->log_file_expunge_seq,
+			  view->log_file_expunge_offset)) {
+		*seq_r = view->log_file_append_seq;
+		*offset_r = view->log_file_append_offset;
+	} else {
+		*seq_r = view->log_file_expunge_seq;
+		*offset_r = view->log_file_expunge_offset;
+	}
+	i_assert(!LOG_IS_BEFORE(view->log_file_head_seq,
+				view->log_file_head_offset,
+				*seq_r, *offset_r));
+}
+
 static int view_sync_set_log_view_range(struct mail_index_view *view)
 {
 	const struct mail_index_header *hdr = view->index->hdr;
+	uint32_t tail_seq;
+	uoff_t tail_offset;
 	int ret;
+
+	view_sync_get_tail(view, &tail_seq, &tail_offset);
 
 	/* the view begins from the first non-synced transaction */
 	ret = mail_transaction_log_view_set(view->log_view,
-					    view->log_file_seq,
-					    view->log_file_offset,
+					    tail_seq, tail_offset,
 					    hdr->log_file_seq,
 					    hdr->log_file_index_int_offset);
 	if (ret <= 0) {
@@ -170,8 +192,8 @@ view_sync_get_expunges(struct mail_index
 	return 0;
 }
 
-static void mail_index_view_hdr_update(struct mail_index_view *view,
-				       struct mail_index_map *map)
+static void mail_index_view_hdr_drop_appends(struct mail_index_view *view,
+					     struct mail_index_map *map)
 {
 	/* Keep message count the same. */
 	map->hdr.next_uid = view->hdr.next_uid;
@@ -183,16 +205,6 @@ static void mail_index_view_hdr_update(s
 	map->hdr.recent_messages_count = view->hdr.recent_messages_count;
 	map->hdr.seen_messages_count = view->hdr.seen_messages_count;
 	map->hdr.deleted_messages_count = view->hdr.deleted_messages_count;
-
-	/* Keep log position so we know where to continue syncing */
-	map->hdr.log_file_seq = view->hdr.log_file_seq;
-	map->hdr.log_file_index_int_offset =
-		view->hdr.log_file_index_int_offset;
-	map->hdr.log_file_index_ext_offset =
-		view->hdr.log_file_index_ext_offset;
-
-	view->hdr = map->hdr;
-	buffer_write(map->hdr_copy_buf, 0, &map->hdr, sizeof(map->hdr));
 }
 
 #ifdef DEBUG
@@ -200,6 +212,7 @@ static void mail_index_view_check(struct
 {
 	unsigned int i, del = 0, recent = 0, seen = 0;
 
+	i_assert(view->hdr.messages_count == view->map->records_count);
 	i_assert(view->hdr.deleted_messages_count ==
 		 view->map->hdr.deleted_messages_count);
 	i_assert(view->hdr.recent_messages_count ==
@@ -241,12 +254,10 @@ static void mail_index_view_check(struct
 	 MAIL_TRANSACTION_FLAG_UPDATE | MAIL_TRANSACTION_KEYWORD_UPDATE | \
 	 MAIL_TRANSACTION_KEYWORD_RESET)
 
-#define VIEW_IS_SYNCED_TO_SAME(view, hdr) \
-	((hdr)->log_file_seq == (view)->log_file_seq && \
-	 (hdr)->log_file_index_int_offset == (view)->log_file_offset && \
-	 (hdr)->log_file_index_ext_offset == (view)->log_file_offset && \
-	 (!array_is_created(&view->syncs_done) || \
-	  array_count(&view->syncs_done) == 0))
+#define VIEW_IS_SYNCED_TO_SAME(hdr, tail_seq, tail_offset) \
+	((hdr)->log_file_seq == (tail_seq) && \
+	 (hdr)->log_file_index_int_offset == (tail_offset) && \
+	 (hdr)->log_file_index_ext_offset == (tail_offset))
 
 int mail_index_view_sync_begin(struct mail_index_view *view,
                                enum mail_index_view_sync_type sync_type,
@@ -254,8 +265,11 @@ int mail_index_view_sync_begin(struct ma
 {
 	struct mail_index_view_sync_ctx *ctx;
 	struct mail_index_map *map;
+	uint32_t tail_seq;
+	uoff_t tail_offset;
 	enum mail_transaction_type visible_mask = 0;
 	ARRAY_TYPE(seq_range) expunges = ARRAY_INIT;
+	bool drop_appends;
 
 	i_assert(!view->syncing);
 	i_assert(view->transactions == 0);
@@ -320,50 +334,58 @@ int mail_index_view_sync_begin(struct ma
 			/* Using non-head mapping. We have to apply
 			   transactions to it to get latest changes into it. */
 			ctx->sync_map_update = TRUE;
-
-			/* Unless map was synced at the exact same position as
-			   view, the message flags can't be reliably used to
-			   update flag counters. note that map->hdr may contain
-			   old information if another process updated the
-			   index file since. */
-			if (view->map->mmap_base != NULL) {
-				const struct mail_index_header *hdr;
-
-				hdr = view->map->mmap_base;
-				view->map->hdr = *hdr;
-			}
-			ctx->sync_map_ctx.unreliable_flags =
-				!VIEW_IS_SYNCED_TO_SAME(view, &view->map->hdr);
-
+		}
+
+		/* Unless map was synced at the exact same position as
+		   view, the message flags can't be reliably used to
+		   update flag counters. note that map->hdr may contain
+		   old information if another process updated the
+		   index file since. */
+		if (view->map->mmap_base != NULL) {
+			const struct mail_index_header *hdr;
+
+			hdr = view->map->mmap_base;
+			view->map->hdr = *hdr;
+		}
+
+		view_sync_get_tail(view, &tail_seq, &tail_offset);
+		ctx->sync_map_ctx.unreliable_flags =
+			!VIEW_IS_SYNCED_TO_SAME(&view->map->hdr,
+						tail_seq, tail_offset);
+
+		drop_appends = ctx->sync_map_update || sync_type ==
+			MAIL_INDEX_VIEW_SYNC_TYPE_NOAPPENDS_NOEXPUNGES;
+		if (drop_appends) {
 			/* Copy only the mails that we see currently, since
 			   we're going to append the new ones when we see
 			   their transactions. */
 			i_assert(view->map->records_count >=
 				 view->hdr.messages_count);
 			view->map->records_count = view->hdr.messages_count;
+		}
 
 #ifdef DEBUG
-			if (!ctx->sync_map_ctx.unreliable_flags) {
-				i_assert(view->map->hdr.messages_count ==
-					 view->hdr.messages_count);
-				mail_index_view_check(view);
-			}
+		if (!ctx->sync_map_ctx.unreliable_flags) {
+			i_assert(view->map->hdr.messages_count ==
+				 view->hdr.messages_count);
+			mail_index_view_check(view);
+		}
 #endif
-		}
 
 		map = mail_index_map_clone(view->map);
 		view->map->records_count = old_records_count;
 		mail_index_unmap(view->index, &view->map);
 		view->map = map;
 
-		if (ctx->sync_map_update) {
+		if (drop_appends) {
 			/* Start the sync using our old view's header.
 			   The old view->hdr may differ from map->hdr if
 			   another view sharing the map with us had synced
 			   itself. */
 			i_assert(map->hdr_base == map->hdr_copy_buf->data);
-			mail_index_view_hdr_update(view, map);
-		}
+			mail_index_view_hdr_drop_appends(view, map);
+		}
+		view->hdr = map->hdr;
 
 		i_assert(map->records_count == map->hdr.messages_count);
 	}
@@ -375,21 +397,6 @@ int mail_index_view_sync_begin(struct ma
 
 	*ctx_r = ctx;
 	return 0;
-}
-
-static void
-view_add_synced_transaction(struct mail_index_view *view,
-			    uint32_t log_file_seq, uoff_t log_file_offset)
-{
-	struct mail_index_view_log_sync_area *pos;
-
-	if (!array_is_created(&view->syncs_done))
-		i_array_init(&view->syncs_done, 32);
-
-	pos = array_append_space(&view->syncs_done);
-	pos->log_file_seq = log_file_seq;
-	pos->log_file_offset = log_file_offset;
-	pos->length = 1;
 }
 
 static bool view_sync_area_find(ARRAY_TYPE(view_log_sync_area) *sync_arr,
@@ -413,22 +420,75 @@ static bool view_sync_area_find(ARRAY_TY
 }
 
 static bool
-mail_index_view_sync_skip(struct mail_index_view_sync_ctx *ctx,
+mail_index_view_sync_want(struct mail_index_view_sync_ctx *ctx,
 			  const struct mail_transaction_header *hdr)
 {
-	if ((hdr->type & ctx->visible_sync_mask) != 0)
+        struct mail_index_view *view = ctx->view;
+	uint32_t seq;
+	uoff_t offset, next_offset;
+
+	mail_transaction_log_view_get_prev_pos(view->log_view, &seq, &offset);
+	next_offset = offset + sizeof(*hdr) + hdr->size;
+
+	switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
+	case MAIL_TRANSACTION_APPEND:
+		if ((ctx->visible_sync_mask & MAIL_TRANSACTION_APPEND) == 0) {
+			i_assert(!LOG_IS_BEFORE(seq, offset,
+						view->log_file_append_seq,
+						view->log_file_append_offset));
+			if (!ctx->skipped_appends) {
+				view->log_file_append_seq = seq;
+				view->log_file_append_offset = offset;
+				ctx->skipped_appends = TRUE;
+			}
+			return FALSE;
+		}
+		if (LOG_IS_BEFORE(seq, offset, view->log_file_append_seq,
+				  view->log_file_append_offset)) {
+			/* already synced */
+			return FALSE;
+		}
+		break;
+	case MAIL_TRANSACTION_EXPUNGE:
+		if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
+			/* expunge request. this will be ignored */
+			break;
+		}
+		if ((ctx->visible_sync_mask & MAIL_TRANSACTION_EXPUNGE) == 0) {
+			i_assert(!LOG_IS_BEFORE(seq, offset,
+						view->log_file_expunge_seq,
+						view->log_file_expunge_offset));
+			if (!ctx->skipped_expunges) {
+				view->log_file_expunge_seq = seq;
+				view->log_file_expunge_offset = offset;
+				ctx->skipped_expunges = TRUE;
+			}
+			return FALSE;
+		}
+		if (LOG_IS_BEFORE(seq, offset, view->log_file_expunge_seq,
+				  view->log_file_expunge_offset)) {
+			/* already synced */
+			return FALSE;
+		}


More information about the dovecot-cvs mailing list