dovecot-2.1: imapc: Delay handling new messages and setting uidv...

dovecot at dovecot.org dovecot at dovecot.org
Sun Sep 4 16:34:42 EEST 2011


details:   http://hg.dovecot.org/dovecot-2.1/rev/1da4bc23d4dc
changeset: 13386:1da4bc23d4dc
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Sep 04 16:34:23 2011 +0300
description:
imapc: Delay handling new messages and setting uidvalidity/uidnext until sync.

diffstat:

 src/lib-storage/index/imapc/imapc-mailbox.c |  94 +++-------------------------
 src/lib-storage/index/imapc/imapc-storage.c |   5 +-
 src/lib-storage/index/imapc/imapc-storage.h |   8 +-
 src/lib-storage/index/imapc/imapc-sync.c    |  65 +++++++++++++++++++-
 4 files changed, 83 insertions(+), 89 deletions(-)

diffs (truncated from 367 to 300 lines):

diff -r 5dac75d12c59 -r 1da4bc23d4dc src/lib-storage/index/imapc/imapc-mailbox.c
--- a/src/lib-storage/index/imapc/imapc-mailbox.c	Sun Sep 04 13:20:27 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-mailbox.c	Sun Sep 04 16:34:23 2011 +0300
@@ -44,6 +44,8 @@
 					MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL);
 	mbox->delayed_sync_view =
 		mail_index_transaction_open_updated_view(mbox->delayed_sync_trans);
+	mbox->min_append_uid =
+		mail_index_get_header(mbox->delayed_sync_view)->next_uid;
 }
 
 int imapc_mailbox_commit_delayed_trans(struct imapc_mailbox *mbox,
@@ -67,53 +69,6 @@
 	return ret;
 }
 
-static void imapc_mailbox_open_finish(struct imapc_mailbox *mbox)
-{
-	const struct mail_index_record *rec;
-	struct imapc_seqmap *seqmap;
-	uint32_t lseq, rseq, cur_count;
-
-	/* if we haven't seen FETCH reply for some messages at the end of
-	   mailbox they've been externally expunged. */
-	imapc_mailbox_init_delayed_trans(mbox);
-	seqmap = imapc_client_mailbox_get_seqmap(mbox->client_box);
-
-	cur_count = mail_index_view_get_messages_count(mbox->delayed_sync_view);
-	for (lseq = cur_count; lseq > 0; lseq--) {
-		rec = mail_index_lookup(mbox->delayed_sync_view, lseq);
-		if (rec->uid <= mbox->highest_seen_uid)
-			break;
-
-		rseq = imapc_seqmap_lseq_to_rseq(seqmap, lseq);
-		imapc_seqmap_expunge(seqmap, rseq);
-		mail_index_expunge(mbox->delayed_sync_trans, lseq);
-	}
-}
-
-static void
-imapc_newmsgs_callback(const struct imapc_command_reply *reply,
-		       void *context)
-{
-	struct imapc_mailbox *mbox = context;
-
-	if (reply->state == IMAPC_COMMAND_STATE_OK)
-		mbox->open_success = TRUE;
-	else if (reply->state == IMAPC_COMMAND_STATE_NO) {
-		imapc_copy_error_from_reply(mbox->storage, MAIL_ERROR_PARAMS,
-					    reply);
-	} else if (mbox->opening ||
-		   reply->state != IMAPC_COMMAND_STATE_DISCONNECTED) {
-		mail_storage_set_critical(&mbox->storage->storage,
-			"imapc: Mailbox newmsgs fetch failed: %s",
-			reply->text_full);
-	}
-	if (mbox->opening) {
-		if (reply->state == IMAPC_COMMAND_STATE_OK)
-			imapc_mailbox_open_finish(mbox);
-		imapc_client_stop(mbox->storage->client);
-	}
-}
-
 static void imapc_untagged_exists(const struct imapc_untagged_reply *reply,
 				  struct imapc_mailbox *mbox)
 {
@@ -121,7 +76,7 @@
 	uint32_t rcount = reply->num;
 	const struct mail_index_header *hdr;
 	struct imapc_seqmap *seqmap;
-	uint32_t first_uid, next_lseq, next_rseq;
+	uint32_t next_lseq, next_rseq;
 
 	if (mbox == NULL)
 		return;
@@ -135,7 +90,7 @@
 	}
 	if (mbox->opening) {
 		/* We don't know the latest flags, refresh them. */
-		first_uid = 1;
+		mbox->sync_fetch_first_uid = 1;
 	} else {
 		seqmap = imapc_client_mailbox_get_seqmap(mbox->client_box);
 		next_lseq = mail_index_view_get_messages_count(view) + 1;
@@ -150,12 +105,8 @@
 			return;
 		}
 		hdr = mail_index_get_header(view);
-		first_uid = hdr->next_uid;
+		mbox->sync_fetch_first_uid = hdr->next_uid;
 	}
-
-	mbox->new_msgs = TRUE;
-	imapc_client_mailbox_cmdf(mbox->client_box, imapc_newmsgs_callback,
-				  mbox, "UID FETCH %u:* FLAGS", first_uid);
 }
 
 static void imapc_mailbox_idle_timeout(struct imapc_mailbox *mbox)
@@ -205,7 +156,6 @@
 	struct imapc_mail *const *mailp;
 	const struct imap_arg *list, *flags_list;
 	const char *atom;
-	const struct mail_index_header *old_hdr;
 	const struct mail_index_record *rec = NULL;
 	enum mail_flags flags;
 	uint32_t uid, cur_count;
@@ -260,8 +210,6 @@
 	}
 
 	imapc_mailbox_init_delayed_trans(mbox);
-	old_hdr = mail_index_get_header(mbox->sync_view);
-
 	cur_count = mail_index_view_get_messages_count(mbox->delayed_sync_view);
 	while (lseq <= cur_count) {
 		rec = mail_index_lookup(mbox->delayed_sync_view, lseq);
@@ -282,17 +230,20 @@
 		lseq++;
 	}
 	if (lseq > cur_count) {
+		if (!mbox->syncing)
+			return;
 		if (uid == 0 || lseq != cur_count + 1)
 			return;
-		if (uid < old_hdr->next_uid) {
+		if (uid < mbox->min_append_uid) {
 			imapc_mailbox_set_corrupted(mbox,
 				"Expunged message reappeared "
 				"(uid=%u < next_uid=%u)",
-				uid, old_hdr->next_uid);
+				uid, mbox->min_append_uid);
 			return;
 		}
 		i_assert(lseq == cur_count + 1);
 		mail_index_append(mbox->delayed_sync_trans, uid, &lseq);
+		mbox->min_append_uid = uid + 1;
 		rec = NULL;
 	}
 	if (seen_flags && (rec == NULL || rec->flags != flags)) {
@@ -355,47 +306,26 @@
 imapc_resp_text_uidvalidity(const struct imapc_untagged_reply *reply,
 			    struct imapc_mailbox *mbox)
 {
-	const struct mail_index_header *hdr;
 	uint32_t uid_validity;
-	bool changes;
 
 	if (mbox == NULL || reply->resp_text_value == NULL ||
 	    str_to_uint32(reply->resp_text_value, &uid_validity) < 0)
 		return;
 
-	hdr = mail_index_get_header(imapc_mailbox_get_sync_view(mbox));
-	if (hdr->uid_validity != uid_validity) {
-		imapc_mailbox_init_delayed_trans(mbox);
-		if (hdr->uid_validity != 0) {
-			/* uidvalidity changed, reset the entire mailbox */
-			mail_index_reset(mbox->delayed_sync_trans);
-			(void)imapc_mailbox_commit_delayed_trans(mbox, &changes);
-			imapc_mailbox_init_delayed_trans(mbox);
-		}
-		mail_index_update_header(mbox->delayed_sync_trans,
-			offsetof(struct mail_index_header, uid_validity),
-			&uid_validity, sizeof(uid_validity), TRUE);
-	}
+	mbox->sync_uid_validity = uid_validity;
 }
 
 static void
 imapc_resp_text_uidnext(const struct imapc_untagged_reply *reply,
 			struct imapc_mailbox *mbox)
 {
-	const struct mail_index_header *hdr;
 	uint32_t uid_next;
 
 	if (mbox == NULL || reply->resp_text_value == NULL ||
 	    str_to_uint32(reply->resp_text_value, &uid_next) < 0)
 		return;
 
-	hdr = mail_index_get_header(imapc_mailbox_get_sync_view(mbox));
-	if (hdr->next_uid != uid_next) {
-		imapc_mailbox_init_delayed_trans(mbox);
-		mail_index_update_header(mbox->delayed_sync_trans,
-			offsetof(struct mail_index_header, next_uid),
-			&uid_next, sizeof(uid_next), FALSE);
-	}
+	mbox->sync_uid_next = uid_next;
 }
 
 void imapc_mailbox_register_untagged(struct imapc_mailbox *mbox,
diff -r 5dac75d12c59 -r 1da4bc23d4dc src/lib-storage/index/imapc/imapc-storage.c
--- a/src/lib-storage/index/imapc/imapc-storage.c	Sun Sep 04 13:20:27 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-storage.c	Sun Sep 04 16:34:23 2011 +0300
@@ -326,8 +326,7 @@
 			ctx->mbox->box.name, reply->text_full);
 		ctx->ret = -1;
 	}
-	if (!ctx->mbox->new_msgs)
-		imapc_client_stop(ctx->mbox->storage->client);
+	imapc_client_stop(ctx->mbox->storage->client);
 }
 
 static int imapc_mailbox_open(struct mailbox *box)
@@ -357,7 +356,7 @@
 	while (ctx.ret == -2)
 		imapc_storage_run(mbox->storage);
 	mbox->opening = FALSE;
-	if (!mbox->open_success) {
+	if (ctx.ret < 0) {
 		mailbox_close(box);
 		return -1;
 	}
diff -r 5dac75d12c59 -r 1da4bc23d4dc src/lib-storage/index/imapc/imapc-storage.h
--- a/src/lib-storage/index/imapc/imapc-storage.h	Sun Sep 04 13:20:27 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-storage.h	Sun Sep 04 16:34:23 2011 +0300
@@ -54,11 +54,15 @@
 	ARRAY_DEFINE(untagged_callbacks, struct imapc_mailbox_event_callback);
 	ARRAY_DEFINE(resp_text_callbacks, struct imapc_mailbox_event_callback);
 
+	uint32_t min_append_uid;
 	uint32_t highest_seen_uid;
 
+	uint32_t sync_uid_validity;
+	uint32_t sync_uid_next;
+	uint32_t sync_fetch_first_uid;
+
 	unsigned int opening:1;
-	unsigned int open_success:1;
-	unsigned int new_msgs:1;
+	unsigned int syncing:1;
 };
 
 struct imapc_simple_context {
diff -r 5dac75d12c59 -r 1da4bc23d4dc src/lib-storage/index/imapc/imapc-sync.c
--- a/src/lib-storage/index/imapc/imapc-sync.c	Sun Sep 04 13:20:27 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-sync.c	Sun Sep 04 16:34:23 2011 +0300
@@ -166,6 +166,49 @@
 	imapc_sync_cmd(ctx, str_c(str));
 }
 
+static void imapc_sync_expunge_eom(struct imapc_sync_context *ctx)
+{
+	const struct mail_index_record *rec;
+	uint32_t lseq, cur_count;
+
+	/* if we haven't seen FETCH reply for some messages at the end of
+	   mailbox they've been externally expunged. */
+	cur_count = mail_index_view_get_messages_count(ctx->sync_view);
+	for (lseq = cur_count; lseq > 0; lseq--) {
+		rec = mail_index_lookup(ctx->sync_view, lseq);
+		if (rec->uid <= ctx->mbox->highest_seen_uid)
+			break;
+
+		mail_index_expunge(ctx->trans, lseq);
+	}
+}
+
+static void imapc_sync_index_header(struct imapc_sync_context *ctx)
+{
+	struct imapc_mailbox *mbox = ctx->mbox;
+	const struct mail_index_header *hdr;
+
+	hdr = mail_index_get_header(ctx->sync_view);
+	if (hdr->uid_validity != mbox->sync_uid_validity &&
+	    mbox->sync_uid_validity != 0) {
+		if (hdr->uid_validity != 0) {
+			/* uidvalidity changed, reset the entire mailbox */
+			mail_index_reset(ctx->trans);
+			mbox->sync_fetch_first_uid = 1;
+		}
+		mail_index_update_header(ctx->trans,
+			offsetof(struct mail_index_header, uid_validity),
+			&mbox->sync_uid_validity,
+			sizeof(mbox->sync_uid_validity), TRUE);
+	}
+	if (hdr->next_uid < mbox->sync_uid_next) {
+		mail_index_update_header(ctx->trans,
+			offsetof(struct mail_index_header, next_uid),
+			&mbox->sync_uid_next, sizeof(mbox->sync_uid_next),
+			FALSE);
+	}
+}
+
 static void imapc_sync_index(struct imapc_sync_context *ctx)
 {
 	struct mailbox *box = &ctx->mbox->box;
@@ -175,6 +218,7 @@
 	i_array_init(&ctx->expunged_uids, 64);
 	ctx->keywords = mail_index_get_keywords(box->index);
 
+	imapc_sync_index_header(ctx);
 	while (mail_index_sync_next(ctx->index_sync_ctx, &sync_rec)) T_BEGIN {
 		if (!mail_index_lookup_seq_range(ctx->sync_view,
 						 sync_rec.uid1, sync_rec.uid2,
@@ -202,11 +246,22 @@
 		}
 	} T_END;
 
+	if (ctx->mbox->sync_fetch_first_uid != 0) {
+		/* we'll resync existing messages' flags and add new messages.
+		   adding new messages requires sync locking to avoid
+		   duplicates. */


More information about the dovecot-cvs mailing list