changeset 18975:f78bd5be4e47

lib-storage: Moved most of the \Recent flag handling code to mailbox-recent-flags.c There are also some API changes, because functions were renamed and the recent_* fields were moved to struct mailbox. I'm not aware of any plugins using these though, except for index_mailbox_set_recent_seq() which for now is kept as a backwards compatibility macro. No changes were made to the actual code logic.
author Timo Sirainen <tss@iki.fi>
date Wed, 19 Aug 2015 12:56:55 +0300
parents 0f442376beae
children 3a8af59b379d
files src/lib-storage/Makefile.am src/lib-storage/index/cydir/cydir-sync.c src/lib-storage/index/dbox-multi/mdbox-sync.c src/lib-storage/index/dbox-single/sdbox-sync.c src/lib-storage/index/index-mail.c src/lib-storage/index/index-rebuild.c src/lib-storage/index/index-search.c src/lib-storage/index/index-status.c src/lib-storage/index/index-storage.c src/lib-storage/index/index-storage.h src/lib-storage/index/index-sync.c src/lib-storage/index/maildir/maildir-save.c src/lib-storage/index/maildir/maildir-sync-index.c src/lib-storage/index/maildir/maildir-util.c src/lib-storage/index/mbox/mbox-file.c src/lib-storage/index/mbox/mbox-sync.c src/lib-storage/index/pop3c/pop3c-sync.c src/lib-storage/index/raw/raw-sync.c src/lib-storage/mail-storage-private.h src/lib-storage/mail-storage.c src/lib-storage/mailbox-recent-flags.c src/lib-storage/mailbox-recent-flags.h src/plugins/virtual/virtual-sync.c
diffstat 23 files changed, 161 insertions(+), 148 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/Makefile.am	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/Makefile.am	Wed Aug 19 12:56:55 2015 +0300
@@ -51,6 +51,7 @@
 	mailbox-keywords.c \
 	mailbox-list.c \
 	mailbox-list-notify.c \
+	mailbox-recent-flags.c \
 	mailbox-search-result.c \
 	mailbox-tree.c \
 	mailbox-uidvalidity.c
@@ -79,6 +80,7 @@
 	mailbox-list-iter.h \
 	mailbox-list-private.h \
 	mailbox-list-notify.h \
+	mailbox-recent-flags.h \
 	mailbox-search-result-private.h \
 	mailbox-tree.h \
 	mailbox-uidvalidity.h
--- a/src/lib-storage/index/cydir/cydir-sync.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/index/cydir/cydir-sync.c	Wed Aug 19 12:56:55 2015 +0300
@@ -71,8 +71,8 @@
 	/* mark the newly seen messages as recent */
 	if (mail_index_lookup_seq_range(ctx->sync_view, hdr->first_recent_uid,
 					hdr->next_uid, &seq1, &seq2)) {
-		index_mailbox_set_recent_seq(&ctx->mbox->box, ctx->sync_view,
-					     seq1, seq2);
+		mailbox_recent_flags_set_seqs(&ctx->mbox->box, ctx->sync_view,
+					      seq1, seq2);
 	}
 
 	while (mail_index_sync_next(ctx->index_sync_ctx, &sync_rec)) {
--- a/src/lib-storage/index/dbox-multi/mdbox-sync.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/index/dbox-multi/mdbox-sync.c	Wed Aug 19 12:56:55 2015 +0300
@@ -154,8 +154,8 @@
 	/* mark the newly seen messages as recent */
 	if (mail_index_lookup_seq_range(ctx->sync_view, hdr->first_recent_uid,
 					hdr->next_uid, &seq1, &seq2)) {
-		index_mailbox_set_recent_seq(&ctx->mbox->box, ctx->sync_view,
-					     seq1, seq2);
+		mailbox_recent_flags_set_seqs(&ctx->mbox->box, ctx->sync_view,
+					      seq1, seq2);
 	}
 
 	/* handle syncing records without map being locked. */
@@ -242,7 +242,7 @@
 	if (rebuild && (flags & MDBOX_SYNC_FLAG_NO_REBUILD) == 0) {
 		if (mdbox_storage_rebuild_in_context(mbox->storage, atomic) < 0)
 			return -1;
-		index_mailbox_reset_uidvalidity(&mbox->box);
+		mailbox_recent_flags_reset(&mbox->box);
 		storage_rebuilt = TRUE;
 	}
 
--- a/src/lib-storage/index/dbox-single/sdbox-sync.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/index/dbox-single/sdbox-sync.c	Wed Aug 19 12:56:55 2015 +0300
@@ -125,7 +125,7 @@
 	/* mark the newly seen messages as recent */
 	if (mail_index_lookup_seq_range(ctx->sync_view, hdr->first_recent_uid,
 					hdr->next_uid, &seq1, &seq2))
-		index_mailbox_set_recent_seq(box, ctx->sync_view, seq1, seq2);
+		mailbox_recent_flags_set_seqs(box, ctx->sync_view, seq1, seq2);
 
 	while (mail_index_sync_next(ctx->index_sync_ctx, &sync_rec))
 		sdbox_sync_add(ctx, &sync_rec);
--- a/src/lib-storage/index/index-mail.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/index/index-mail.c	Wed Aug 19 12:56:55 2015 +0300
@@ -195,7 +195,7 @@
 	flags = rec->flags & (MAIL_FLAGS_NONRECENT |
 			      MAIL_INDEX_MAIL_FLAG_BACKEND);
 
-	if (index_mailbox_is_recent(_mail->box, _mail->uid))
+	if (mailbox_recent_flags_have_uid(_mail->box, _mail->uid))
 		flags |= MAIL_RECENT;
 
 	if (index_mail_get_pvt(_mail)) {
@@ -1980,7 +1980,7 @@
 	bool update_modseq = FALSE;
 
 	if ((flags & MAIL_RECENT) == 0 &&
-	    index_mailbox_is_recent(_mail->box, _mail->uid))
+	    mailbox_recent_flags_have_uid(_mail->box, _mail->uid))
 		index_mail_drop_recent_flag(_mail);
 	flags &= MAIL_FLAGS_NONRECENT | MAIL_INDEX_MAIL_FLAG_BACKEND;
 
--- a/src/lib-storage/index/index-rebuild.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/index/index-rebuild.c	Wed Aug 19 12:56:55 2015 +0300
@@ -157,7 +157,7 @@
 	ctx->view = view;
 	ctx->trans = trans;
 	mail_index_reset(ctx->trans);
-	index_mailbox_reset_uidvalidity(box);
+	mailbox_recent_flags_reset(box);
 	(void)mail_index_ext_lookup(box->index, "cache", &ctx->cache_ext_id);
 
 	/* open cache and read the caching decisions. */
--- a/src/lib-storage/index/index-search.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/index/index-search.c	Wed Aug 19 12:56:55 2015 +0300
@@ -178,7 +178,7 @@
 		   may contain it. */
 		flags = rec->flags & ~MAIL_RECENT;
 		if ((arg->value.flags & MAIL_RECENT) != 0 &&
-		    index_mailbox_is_recent(ctx->box, rec->uid))
+		    mailbox_recent_flags_have_uid(ctx->box, rec->uid))
 			flags |= MAIL_RECENT;
 		if (ctx->box->view_pvt == NULL) {
 			/* no private view (set by view syncing) ->
--- a/src/lib-storage/index/index-status.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/index/index-status.c	Wed Aug 19 12:56:55 2015 +0300
@@ -126,7 +126,7 @@
 			   synced yet */
 			index_sync_update_recent_count(box);
 		}
-		status_r->recent = index_mailbox_get_recent_count(box);
+		status_r->recent = mailbox_recent_flags_count(box);
 		i_assert(status_r->recent <= status_r->messages);
 	}
 	if ((items & STATUS_UNSEEN) != 0) {
--- a/src/lib-storage/index/index-storage.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/index/index-storage.c	Wed Aug 19 12:56:55 2015 +0300
@@ -369,11 +369,6 @@
 	ibox->keyword_names = NULL;
 	i_free_and_null(ibox->cache_fields);
 
-	if (array_is_created(&ibox->recent_flags))
-		array_free(&ibox->recent_flags);
-	ibox->recent_flags_prev_uid = 0;
-	ibox->recent_flags_count = 0;
-
 	ibox->sync_last_check = 0;
 }
 
--- a/src/lib-storage/index/index-storage.h	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/index/index-storage.h	Wed Aug 19 12:56:55 2015 +0300
@@ -4,6 +4,7 @@
 #include "file-dotlock.h"
 #include "mail-storage-private.h"
 #include "mail-index-private.h"
+#include "mailbox-recent-flags.h" /* FIXME: remove in v2.3 */
 
 #define MAILBOX_FULL_SYNC_INTERVAL 5
 
@@ -30,9 +31,7 @@
 	const ARRAY_TYPE(keywords) *keyword_names;
 	struct mail_cache_field *cache_fields;
 
-	ARRAY_TYPE(seq_range) recent_flags;
-	uint32_t recent_flags_prev_uid, recent_flags_last_check_nextuid;
-	uint32_t recent_flags_count;
+	uint32_t recent_flags_last_check_nextuid;
 
 	time_t sync_last_check;
 	uint32_t list_index_sync_ext_id;
@@ -76,13 +75,9 @@
 bool index_storage_is_readonly(struct mailbox *box);
 bool index_storage_is_inconsistent(struct mailbox *box);
 
-void index_mailbox_set_recent_uid(struct mailbox *box, uint32_t uid);
-void index_mailbox_set_recent_seq(struct mailbox *box,
-				  struct mail_index_view *view,
-				  uint32_t seq1, uint32_t seq2);
-bool index_mailbox_is_recent(struct mailbox *box, uint32_t uid);
-unsigned int index_mailbox_get_recent_count(struct mailbox *box);
-void index_mailbox_reset_uidvalidity(struct mailbox *box);
+/* FIXME: for backwards compatibility - remove in v2.3 */
+#define index_mailbox_set_recent_seq(box, view, seq1, seq2) \
+	mailbox_recent_flags_set_seqs(box, view, seq1, seq2)
 
 void index_mailbox_check_add(struct mailbox *box, const char *path);
 void index_mailbox_check_remove_all(struct mailbox *box);
--- a/src/lib-storage/index/index-sync.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/index/index-sync.c	Wed Aug 19 12:56:55 2015 +0300
@@ -51,103 +51,6 @@
 	return TRUE;
 }
 
-void index_mailbox_set_recent_uid(struct mailbox *box, uint32_t uid)
-{
-	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
-
-	if (uid <= ibox->recent_flags_prev_uid) {
-		if (seq_range_exists(&ibox->recent_flags, uid))
-			return;
-
-		mail_storage_set_critical(box->storage,
-			"Recent flags state corrupted for mailbox %s",
-			box->vname);
-		array_clear(&ibox->recent_flags);
-		ibox->recent_flags_count = 0;
-	}
-	ibox->recent_flags_prev_uid = uid;
-
-	seq_range_array_add_with_init(&ibox->recent_flags, 64, uid);
-	ibox->recent_flags_count++;
-}
-
-void index_mailbox_set_recent_seq(struct mailbox *box,
-				  struct mail_index_view *view,
-				  uint32_t seq1, uint32_t seq2)
-{
-	uint32_t uid;
-
-	for (; seq1 <= seq2; seq1++) {
-		mail_index_lookup_uid(view, seq1, &uid);
-		index_mailbox_set_recent_uid(box, uid);
-	}
-}
-
-bool index_mailbox_is_recent(struct mailbox *box, uint32_t uid)
-{
-	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
-
-	return array_is_created(&ibox->recent_flags) &&
-		seq_range_exists(&ibox->recent_flags, uid);
-}
-
-void index_mailbox_reset_uidvalidity(struct mailbox *box)
-{
-	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
-
-	/* can't trust the currently cached recent flags anymore */
-	if (array_is_created(&ibox->recent_flags))
-		array_clear(&ibox->recent_flags);
-	ibox->recent_flags_count = 0;
-	ibox->recent_flags_prev_uid = 0;
-}
-
-unsigned int index_mailbox_get_recent_count(struct mailbox *box)
-{
-	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
-	const struct mail_index_header *hdr;
-	const struct seq_range *range;
-	unsigned int i, count, recent_count;
-
-	if (!array_is_created(&ibox->recent_flags))
-		return 0;
-
-	hdr = mail_index_get_header(box->view);
-	recent_count = ibox->recent_flags_count;
-	range = array_get(&ibox->recent_flags, &count);
-	for (i = count; i > 0; ) {
-		i--;
-		if (range[i].seq2 < hdr->next_uid)
-			break;
-
-		if (range[i].seq1 >= hdr->next_uid) {
-			/* completely invisible to this view */
-			recent_count -= range[i].seq2 - range[i].seq1 + 1;
-		} else {
-			/* partially invisible */
-			recent_count -= range[i].seq2 - hdr->next_uid + 1;
-			break;
-		}
-	}
-	return recent_count;
-}
-
-static void
-index_mailbox_expunge_recent(struct mailbox *box, uint32_t seq1, uint32_t seq2)
-{
-	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
-	uint32_t uid;
-
-	if (!array_is_created(&ibox->recent_flags))
-		return;
-
-	for (; seq1 <= seq2; seq1++) {
-		mail_index_lookup_uid(box->view, seq1, &uid);
-		if (seq_range_array_remove(&ibox->recent_flags, uid))
-			ibox->recent_flags_count--;
-	}
-}
-
 static void index_view_sync_recs_get(struct index_mailbox_sync_context *ctx)
 {
 	struct mail_index_view_sync_rec sync_rec;
@@ -264,7 +167,7 @@
 	range = array_idx(ctx->expunges, ctx->expunge_pos);
 	i_assert(range->seq2 <= ctx->messages_count);
 
-	index_mailbox_expunge_recent(ctx->ctx.box, range->seq1, range->seq2);
+	mailbox_recent_flags_expunge_seqs(ctx->ctx.box, range->seq1, range->seq2);
 	ctx->messages_count -= range->seq2 - range->seq1 + 1;
 
 	sync_rec_r->seq1 = range->seq1;
@@ -310,13 +213,12 @@
 static void
 index_mailbox_expunge_unseen_recent(struct index_mailbox_sync_context *ctx)
 {
-	struct index_mailbox_context *ibox =
-		INDEX_STORAGE_CONTEXT(ctx->ctx.box);
+	struct mailbox *box = ctx->ctx.box;
 	struct mail_index_view *view = ctx->ctx.box->view;
 	const struct mail_index_header *hdr;
 	uint32_t seq, start_uid, uid;
 
-	if (!array_is_created(&ibox->recent_flags))
+	if (!array_is_created(&box->recent_flags))
 		return;
 
 	/* expunges array contained expunges for the messages that were already
@@ -339,14 +241,14 @@
 		if (start_uid + 1 > uid - 1)
 			continue;
 
-		ibox->recent_flags_count -=
-			seq_range_array_remove_range(&ibox->recent_flags,
+		box->recent_flags_count -=
+			seq_range_array_remove_range(&box->recent_flags,
 						     start_uid + 1, uid - 1);
 	}
 
 	if (uid + 1 < hdr->next_uid) {
-		ibox->recent_flags_count -=
-			seq_range_array_remove_range(&ibox->recent_flags,
+		box->recent_flags_count -=
+			seq_range_array_remove_range(&box->recent_flags,
 						     uid + 1,
 						     hdr->next_uid - 1);
 	}
@@ -355,7 +257,7 @@
 		const struct seq_range *range;
 		unsigned int i, count;
 
-		range = array_get(&ibox->recent_flags, &count);
+		range = array_get(&box->recent_flags, &count);
 		for (i = 0; i < count; i++) {
 			for (uid = range[i].seq1; uid <= range[i].seq2; uid++) {
 				if (uid >= hdr->next_uid)
@@ -375,15 +277,15 @@
 	uint32_t seq1, seq2;
 
 	hdr = mail_index_get_header(box->view);
-	if (hdr->first_recent_uid > ibox->recent_flags_prev_uid ||
+	if (hdr->first_recent_uid > box->recent_flags_prev_uid ||
 	    hdr->next_uid > ibox->recent_flags_last_check_nextuid) {
 		ibox->recent_flags_last_check_nextuid = hdr->next_uid;
 		if (mail_index_lookup_seq_range(box->view,
 						hdr->first_recent_uid,
 						hdr->next_uid,
 						&seq1, &seq2)) {
-			index_mailbox_set_recent_seq(box, box->view,
-						     seq1, seq2);
+			mailbox_recent_flags_set_seqs(box, box->view,
+						      seq1, seq2);
 		}
 	}
 }
--- a/src/lib-storage/index/maildir/maildir-save.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/index/maildir/maildir-save.c	Wed Aug 19 12:56:55 2015 +0300
@@ -732,7 +732,7 @@
 	uids = array_get(&saved_sorted_uids, &count);
 	for (i = 0; i < count; i++) {
 		for (uid = uids[i].seq1; uid <= uids[i].seq2; uid++)
-			index_mailbox_set_recent_uid(&mbox->box, uid);
+			mailbox_recent_flags_set_uid(&mbox->box, uid);
 	}
 	return uids[count-1].seq2 + 1;
 }
--- a/src/lib-storage/index/maildir/maildir-sync-index.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/index/maildir/maildir-sync-index.c	Wed Aug 19 12:56:55 2015 +0300
@@ -484,7 +484,7 @@
 			  mailbox_get_path(&ctx->mbox->box),
 			  hdr->uid_validity, uid_validity);
 		mail_index_reset(trans);
-		index_mailbox_reset_uidvalidity(&mbox->box);
+		mailbox_recent_flags_reset(&mbox->box);
 
 		first_uid = hdr->messages_count + 1;
 		memset(&empty_hdr, 0, sizeof(empty_hdr));
@@ -637,7 +637,7 @@
 			/* UIDVALIDITY changed, skip over the old messages */
 			seq = first_uid;
 		}
-		index_mailbox_set_recent_seq(&mbox->box, view2, seq, seq2);
+		mailbox_recent_flags_set_seqs(&mbox->box, view2, seq, seq2);
 	}
 	mail_index_view_close(&view2);
 
--- a/src/lib-storage/index/maildir/maildir-util.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/index/maildir/maildir-util.c	Wed Aug 19 12:56:55 2015 +0300
@@ -59,7 +59,7 @@
 		*uidlist_flags &= MAILDIR_UIDLIST_REC_FLAG_NEW_DIR;
 	} else if ((*uidlist_flags & MAILDIR_UIDLIST_REC_FLAG_MOVED) == 0 &&
 		   ((*uidlist_flags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0 ||
-		    index_mailbox_is_recent(&mbox->box, uid))) {
+		    mailbox_recent_flags_have_uid(&mbox->box, uid))) {
 		/* probably in new/ dir, drop ":2," from fname */
 		*uidlist_flags |= MAILDIR_UIDLIST_REC_FLAG_NEW_DIR;
 		p = strrchr(fname, MAILDIR_INFO_SEP);
--- a/src/lib-storage/index/mbox/mbox-file.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/index/mbox/mbox-file.c	Wed Aug 19 12:56:55 2015 +0300
@@ -98,11 +98,10 @@
 
 static void mbox_file_fix_atime(struct mbox_mailbox *mbox)
 {
-	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(&mbox->box);
 	struct utimbuf buf;
 	struct stat st;
 
-	if (ibox->recent_flags_count > 0 &&
+	if (mbox->box.recent_flags_count > 0 &&
 	    (mbox->box.flags & MAILBOX_FLAG_DROP_RECENT) == 0 &&
 	    mbox->mbox_fd != -1 && !mbox_is_backend_readonly(mbox)) {
 		/* we've seen recent messages which we want to keep recent.
--- a/src/lib-storage/index/mbox/mbox-sync.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/index/mbox/mbox-sync.c	Wed Aug 19 12:56:55 2015 +0300
@@ -1544,8 +1544,8 @@
 	view = mail_index_transaction_open_updated_view(sync_ctx->t);
 	if (mail_index_lookup_seq_range(view, sync_ctx->last_nonrecent_uid + 1,
 					(uint32_t)-1, &seq, &seq2)) {
-		index_mailbox_set_recent_seq(&sync_ctx->mbox->box,
-					     view, seq, seq2);
+		mailbox_recent_flags_set_seqs(&sync_ctx->mbox->box,
+					      view, seq, seq2);
 	}
 	mail_index_view_close(&view);
 
@@ -1576,7 +1576,7 @@
 		mail_index_reset(sync_ctx->t);
 		sync_ctx->reset_hdr.next_uid = 1;
 		sync_ctx->hdr = &sync_ctx->reset_hdr;
-		index_mailbox_reset_uidvalidity(&sync_ctx->mbox->box);
+		mailbox_recent_flags_reset(&sync_ctx->mbox->box);
 	}
 
 	sync_ctx->prev_msg_uid = 0;
--- a/src/lib-storage/index/pop3c/pop3c-sync.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/index/pop3c/pop3c-sync.c	Wed Aug 19 12:56:55 2015 +0300
@@ -186,7 +186,7 @@
 	/* mark the newly seen messages as recent */
 	if (mail_index_lookup_seq_range(sync_view, hdr->first_recent_uid,
 					hdr->next_uid, &seq1, &seq2))
-		index_mailbox_set_recent_seq(&mbox->box, sync_view, seq1, seq2);
+		mailbox_recent_flags_set_seqs(&mbox->box, sync_view, seq1, seq2);
 }
 
 static int uint32_cmp(const uint32_t *u1, const uint32_t *u2)
--- a/src/lib-storage/index/raw/raw-sync.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/index/raw/raw-sync.c	Wed Aug 19 12:56:55 2015 +0300
@@ -35,7 +35,7 @@
 
 	/* add our one and only message */
 	mail_index_append(trans, 1, &seq);
-	index_mailbox_set_recent_uid(&mbox->box, 1);
+	mailbox_recent_flags_set_uid(&mbox->box, 1);
 
 	if (mail_index_sync_commit(&index_sync_ctx) < 0) {
 		mailbox_set_index_error(&mbox->box);
--- a/src/lib-storage/mail-storage-private.h	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/mail-storage-private.h	Wed Aug 19 12:56:55 2015 +0300
@@ -319,6 +319,11 @@
 	struct mail_msgpart_partial_cache partial_cache;
 	uint32_t vsize_hdr_ext_id;
 
+	/* MAIL_RECENT flags handling */
+	ARRAY_TYPE(seq_range) recent_flags;
+	uint32_t recent_flags_prev_uid;
+	uint32_t recent_flags_count;
+
 	struct mail_index_view *tmp_sync_view;
 
 	/* Mailbox notification settings: */
--- a/src/lib-storage/mail-storage.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/lib-storage/mail-storage.c	Wed Aug 19 12:56:55 2015 +0300
@@ -1231,6 +1231,11 @@
 	box->opened = FALSE;
 	box->mailbox_deleted = FALSE;
 	array_clear(&box->search_results);
+
+	if (array_is_created(&box->recent_flags))
+		array_free(&box->recent_flags);
+	box->recent_flags_prev_uid = 0;
+	box->recent_flags_count = 0;
 }
 
 void mailbox_free(struct mailbox **_box)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-storage/mailbox-recent-flags.c	Wed Aug 19 12:56:55 2015 +0300
@@ -0,0 +1,93 @@
+/* Copyright (c) 2002-2015 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "mail-storage-private.h"
+#include "mailbox-recent-flags.h"
+
+void mailbox_recent_flags_set_uid(struct mailbox *box, uint32_t uid)
+{
+	if (uid <= box->recent_flags_prev_uid) {
+		if (seq_range_exists(&box->recent_flags, uid))
+			return;
+
+		mail_storage_set_critical(box->storage,
+			"Recent flags state corrupted for mailbox %s",
+			box->vname);
+		array_clear(&box->recent_flags);
+		box->recent_flags_count = 0;
+	}
+	box->recent_flags_prev_uid = uid;
+
+	seq_range_array_add_with_init(&box->recent_flags, 64, uid);
+	box->recent_flags_count++;
+}
+
+void mailbox_recent_flags_set_seqs(struct mailbox *box,
+				   struct mail_index_view *view,
+				   uint32_t seq1, uint32_t seq2)
+{
+	uint32_t uid;
+
+	for (; seq1 <= seq2; seq1++) {
+		mail_index_lookup_uid(view, seq1, &uid);
+		mailbox_recent_flags_set_uid(box, uid);
+	}
+}
+
+bool mailbox_recent_flags_have_uid(struct mailbox *box, uint32_t uid)
+{
+	return array_is_created(&box->recent_flags) &&
+		seq_range_exists(&box->recent_flags, uid);
+}
+
+void mailbox_recent_flags_reset(struct mailbox *box)
+{
+	if (array_is_created(&box->recent_flags))
+		array_clear(&box->recent_flags);
+	box->recent_flags_count = 0;
+	box->recent_flags_prev_uid = 0;
+}
+
+unsigned int mailbox_recent_flags_count(struct mailbox *box)
+{
+	const struct mail_index_header *hdr;
+	const struct seq_range *range;
+	unsigned int i, count, recent_count;
+
+	if (!array_is_created(&box->recent_flags))
+		return 0;
+
+	hdr = mail_index_get_header(box->view);
+	recent_count = box->recent_flags_count;
+	range = array_get(&box->recent_flags, &count);
+	for (i = count; i > 0; ) {
+		i--;
+		if (range[i].seq2 < hdr->next_uid)
+			break;
+
+		if (range[i].seq1 >= hdr->next_uid) {
+			/* completely invisible to this view */
+			recent_count -= range[i].seq2 - range[i].seq1 + 1;
+		} else {
+			/* partially invisible */
+			recent_count -= range[i].seq2 - hdr->next_uid + 1;
+			break;
+		}
+	}
+	return recent_count;
+}
+
+void mailbox_recent_flags_expunge_seqs(struct mailbox *box,
+				       uint32_t seq1, uint32_t seq2)
+{
+	uint32_t uid;
+
+	if (!array_is_created(&box->recent_flags))
+		return;
+
+	for (; seq1 <= seq2; seq1++) {
+		mail_index_lookup_uid(box->view, seq1, &uid);
+		if (seq_range_array_remove(&box->recent_flags, uid))
+			box->recent_flags_count--;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-storage/mailbox-recent-flags.h	Wed Aug 19 12:56:55 2015 +0300
@@ -0,0 +1,17 @@
+#ifndef MAILBOX_RECENT_FLAGS
+#define MAILBOX_RECENT_FLAGS
+
+struct mailbox;
+struct mail_index_view;
+
+void mailbox_recent_flags_set_uid(struct mailbox *box, uint32_t uid);
+void mailbox_recent_flags_set_seqs(struct mailbox *box,
+				   struct mail_index_view *view,
+				   uint32_t seq1, uint32_t seq2);
+bool mailbox_recent_flags_have_uid(struct mailbox *box, uint32_t uid);
+void mailbox_recent_flags_reset(struct mailbox *box);
+unsigned int mailbox_recent_flags_count(struct mailbox *box);
+void mailbox_recent_flags_expunge_seqs(struct mailbox *box,
+				       uint32_t seq1, uint32_t seq2);
+
+#endif
--- a/src/plugins/virtual/virtual-sync.c	Wed Aug 19 11:34:36 2015 +0300
+++ b/src/plugins/virtual/virtual-sync.c	Wed Aug 19 12:56:55 2015 +0300
@@ -444,8 +444,8 @@
 	/* mark the newly seen messages as recent */
 	if (mail_index_lookup_seq_range(ctx->sync_view, hdr->first_recent_uid,
 					hdr->next_uid, &seq1, &seq2)) {
-		index_mailbox_set_recent_seq(&ctx->mbox->box, ctx->sync_view,
-					     seq1, seq2);
+		mailbox_recent_flags_set_seqs(&ctx->mbox->box, ctx->sync_view,
+					      seq1, seq2);
 	}
 	if (ctx->ext_header_rewrite) {
 		/* entire mailbox list needs to be rewritten */