changeset 4688:764bd841e0ae HEAD

Try to avoid sending duplicate/useless flag updates.
author Timo Sirainen <tss@iki.fi>
date Sun, 15 Oct 2006 20:56:09 +0300
parents c8b565e87966
children 80023f898ddd
files src/lib-index/mail-index-view-sync.c src/lib-index/mail-index.h src/lib-storage/index/index-sync.c
diffstat 3 files changed, 100 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-index-view-sync.c	Sun Oct 15 20:44:32 2006 +0300
+++ b/src/lib-index/mail-index-view-sync.c	Sun Oct 15 20:56:09 2006 +0300
@@ -12,7 +12,7 @@
 	struct mail_index_view *view;
 	enum mail_transaction_type visible_sync_mask;
 	struct mail_index_sync_map_ctx sync_map_ctx;
-	ARRAY_TYPE(uid_range) expunges;
+	ARRAY_TYPE(seq_range) expunges;
 
 	const struct mail_transaction_header *hdr;
 	const void *data;
@@ -24,11 +24,12 @@
 };
 
 static void
-mail_transaction_log_sort_expunges(ARRAY_TYPE(uid_range) *expunges,
-				   const struct uid_range *src, size_t src_size)
+mail_transaction_log_sort_expunges(ARRAY_TYPE(seq_range) *expunges,
+				   const struct seq_range *src, size_t src_size)
 {
-	const struct uid_range *src_end;
-	struct uid_range *dest, new_exp;
+	/* Note that all the sequences are actually still UIDs at this point */
+	const struct seq_range *src_end;
+	struct seq_range *dest, new_exp;
 	unsigned int first, i, dest_count;
 
 	i_assert(src_size % sizeof(*src) == 0);
@@ -43,28 +44,28 @@
 	src_end = CONST_PTR_OFFSET(src, src_size);
 	for (i = 0; src != src_end; src++) {
 		/* src[] must be sorted. */
-		i_assert(src+1 == src_end || src->uid2 < src[1].uid1);
-		i_assert(src->uid1 <= src->uid2);
+		i_assert(src+1 == src_end || src->seq2 < src[1].seq1);
+		i_assert(src->seq1 <= src->seq2);
 
 		for (; i < dest_count; i++) {
-			if (src->uid1 < dest[i].uid1)
+			if (src->seq1 < dest[i].seq1)
 				break;
 		}
 
 		new_exp = *src;
 
 		first = i;
-		while (i < dest_count && src->uid2 >= dest[i].uid1-1) {
+		while (i < dest_count && src->seq2 >= dest[i].seq1-1) {
 			/* we can/must merge with next record */
-			if (new_exp.uid2 < dest[i].uid2)
-				new_exp.uid2 = dest[i].uid2;
+			if (new_exp.seq2 < dest[i].seq2)
+				new_exp.seq2 = dest[i].seq2;
 			i++;
 		}
 
-		if (first > 0 && new_exp.uid1 <= dest[first-1].uid2+1) {
+		if (first > 0 && new_exp.seq1 <= dest[first-1].seq2+1) {
 			/* continue previous record */
-			if (dest[first-1].uid2 < new_exp.uid2)
-				dest[first-1].uid2 = new_exp.uid2;
+			if (dest[first-1].seq2 < new_exp.seq2)
+				dest[first-1].seq2 = new_exp.seq2;
 		} else if (i == first) {
 			array_insert(expunges, i, &new_exp, 1);
 			i++; first++;
@@ -112,10 +113,10 @@
 
 static int
 view_sync_get_expunges(struct mail_index_view *view,
-		       ARRAY_TYPE(uid_range) *expunges_r)
+		       ARRAY_TYPE(seq_range) *expunges_r)
 {
 	const struct mail_transaction_header *hdr;
-	struct uid_range *src, *src_end, *dest;
+	struct seq_range *src, *src_end, *dest;
 	const void *data;
 	unsigned int count;
 	int ret;
@@ -135,17 +136,17 @@
 		return -1;
 	}
 
-	/* convert to sequences */
+	/* convert UIDs to sequences */
 	src = dest = array_get_modifiable(expunges_r, &count);
 	src_end = src + count;
 	for (; src != src_end; src++) {
-		ret = mail_index_lookup_uid_range(view, src->uid1,
-						  src->uid2,
-						  &dest->uid1,
-						  &dest->uid2);
+		ret = mail_index_lookup_uid_range(view, src->seq1,
+						  src->seq2,
+						  &dest->seq1,
+						  &dest->seq2);
 		i_assert(ret == 0);
 
-		if (dest->uid1 == 0)
+		if (dest->seq1 == 0)
 			count--;
 		else
 			dest++;
@@ -195,7 +196,7 @@
 	struct mail_index_view_sync_ctx *ctx;
 	struct mail_index_map *map;
 	enum mail_transaction_type log_get_mask, visible_mask;
-	ARRAY_TYPE(uid_range) expunges = ARRAY_INIT;
+	ARRAY_TYPE(seq_range) expunges = ARRAY_INIT;
 
 	/* We must sync flags as long as view is mmap()ed, as the flags may
 	   have already changed under us. */
@@ -511,14 +512,10 @@
 	return 1;
 }
 
-const uint32_t *
-mail_index_view_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
-				  unsigned int *count_r)
+void mail_index_view_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
+				       const ARRAY_TYPE(seq_range) **expunges_r)
 {
-	const struct uid_range *data;
-
-	data = array_get(&ctx->expunges, count_r);
-	return (const uint32_t *)data;
+	*expunges_r = &ctx->expunges;
 }
 
 static void
--- a/src/lib-index/mail-index.h	Sun Oct 15 20:44:32 2006 +0300
+++ b/src/lib-index/mail-index.h	Sun Oct 15 20:56:09 2006 +0300
@@ -2,6 +2,7 @@
 #define __MAIL_INDEX_H
 
 #include "mail-types.h"
+#include "seq-range-array.h"
 
 #define MAIL_INDEX_MAJOR_VERSION 7
 #define MAIL_INDEX_MINOR_VERSION 0
@@ -266,9 +267,9 @@
 /* Returns -1 if error, 0 if sync is finished, 1 if record was filled. */
 int mail_index_view_sync_next(struct mail_index_view_sync_ctx *ctx,
 			      struct mail_index_view_sync_rec *sync_rec);
-const uint32_t *
+void
 mail_index_view_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
-				 unsigned int *count_r);
+				  const ARRAY_TYPE(seq_range) **expunges_r);
 void mail_index_view_sync_end(struct mail_index_view_sync_ctx **ctx);
 
 /* Returns the index header. */
--- a/src/lib-storage/index/index-sync.c	Sun Oct 15 20:44:32 2006 +0300
+++ b/src/lib-storage/index/index-sync.c	Sun Oct 15 20:56:09 2006 +0300
@@ -1,6 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
+#include "seq-range-array.h"
 #include "array.h"
 #include "buffer.h"
 #include "index-storage.h"
@@ -11,9 +12,11 @@
 	struct mail_index_view_sync_ctx *sync_ctx;
 	uint32_t messages_count;
 
-	const uint32_t *expunges;
-	unsigned int expunges_count;
-	int failed;
+	const ARRAY_TYPE(seq_range) *expunges;
+	unsigned int expunge_pos;
+	uint32_t last_seq1, last_seq2;
+
+	bool failed;
 };
 
 void index_mailbox_set_recent(struct index_mailbox *ibox, uint32_t seq)
@@ -163,13 +166,62 @@
 	}
 
 	if ((flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) == 0) {
-		ctx->expunges =
-			mail_index_view_sync_get_expunges(ctx->sync_ctx,
-							  &ctx->expunges_count);
+		mail_index_view_sync_get_expunges(ctx->sync_ctx,
+						  &ctx->expunges);
+		ctx->expunge_pos = array_count(ctx->expunges);
 	}
 	return &ctx->ctx;
 }
 
+static bool sync_rec_check_skips(struct index_mailbox_sync_context *ctx,
+				 struct mailbox_sync_rec *sync_rec)
+{
+	uint32_t seq, new_seq1, new_seq2;
+
+	if (sync_rec->seq1 >= ctx->last_seq1 &&
+	    sync_rec->seq1 <= ctx->last_seq2)
+		new_seq1 = ctx->last_seq2 + 1;
+	else
+		new_seq1 = sync_rec->seq1;
+	if (sync_rec->seq2 >= ctx->last_seq1 &&
+	    sync_rec->seq2 <= ctx->last_seq2)
+		new_seq2 = ctx->last_seq1 - 1;
+	else
+		new_seq2 = sync_rec->seq2;
+
+	if (new_seq1 > new_seq2)
+		return FALSE;
+
+	ctx->last_seq1 = sync_rec->seq1;
+	ctx->last_seq2 = sync_rec->seq2;
+
+	sync_rec->seq1 = new_seq1;
+	sync_rec->seq2 = new_seq2;
+
+	/* FIXME: we're only skipping messages from the beginning and from
+	   the end. we should skip also the middle ones. This takes care of
+	   the most common repeats though. */
+	if (ctx->expunges != NULL) {
+		/* skip expunged messages from the beginning and the end */
+		for (seq = sync_rec->seq1; seq <= sync_rec->seq2; seq++) {
+			if (!seq_range_exists(ctx->expunges, seq))
+				break;
+		}
+		if (seq > sync_rec->seq2) {
+			/* everything skipped */
+			return FALSE;
+		}
+		sync_rec->seq1 = seq;
+
+		for (seq = sync_rec->seq2; seq >= sync_rec->seq1; seq--) {
+			if (!seq_range_exists(ctx->expunges, seq))
+				break;
+		}
+		sync_rec->seq2 = seq;
+	}
+	return TRUE;
+}
+
 int index_mailbox_sync_next(struct mailbox_sync_context *_ctx,
 			    struct mailbox_sync_rec *sync_rec_r)
 {
@@ -205,6 +257,9 @@
 			if (sync_rec_r->seq1 == 0)
 				break;
 
+			if (!sync_rec_check_skips(ctx, sync_rec_r))
+				break;
+
 			sync_rec_r->type =
 				sync.type == MAIL_INDEX_SYNC_TYPE_FLAGS ?
 				MAILBOX_SYNC_TYPE_FLAGS :
@@ -213,19 +268,22 @@
 		}
 	}
 
-	if (ret == 0 && ctx->expunges_count > 0) {
-		/* expunges[] is a sorted array of sequences. it's easiest for
+	if (ret == 0 && ctx->expunge_pos > 0) {
+		/* expunges is a sorted array of sequences. it's easiest for
 		   us to print them from end to beginning. */
-		sync_rec_r->seq1 = ctx->expunges[ctx->expunges_count*2-2];
-		sync_rec_r->seq2 = ctx->expunges[ctx->expunges_count*2-1];
+		const struct seq_range *range;
+
+		ctx->expunge_pos--;
+		range = array_idx(ctx->expunges, ctx->expunge_pos);
+
+		sync_rec_r->seq1 = range->seq1;
+		sync_rec_r->seq2 = range->seq2;
 		index_mailbox_expunge_recent(ctx->ibox, sync_rec_r->seq1,
 					     sync_rec_r->seq2);
 
 		if (sync_rec_r->seq2 > ctx->messages_count)
 			sync_rec_r->seq2 = ctx->messages_count;
-
 		ctx->messages_count -= sync_rec_r->seq2 - sync_rec_r->seq1 + 1;
-		ctx->expunges_count--;
 
 		sync_rec_r->type = MAILBOX_SYNC_TYPE_EXPUNGE;
 		return 1;