dovecot-1.2: QRESYNC: If MODSEQs were returned in FETCH replies ...

dovecot at dovecot.org dovecot at dovecot.org
Wed Jun 11 14:40:26 EEST 2008


details:   http://hg.dovecot.org/dovecot-1.2/rev/2d62129a709b
changeset: 7815:2d62129a709b
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Jun 11 14:39:52 2008 +0300
description:
QRESYNC: If MODSEQs were returned in FETCH replies but there are pending
expunges, send a low enough HIGHESTMODSEQ reply to make sure the client will
later see the expunges.

diffstat:

8 files changed, 44 insertions(+), 12 deletions(-)
src/imap/client.h                    |    3 +++
src/imap/cmd-select.c                |    1 +
src/imap/imap-fetch.c                |    1 +
src/imap/imap-sync.c                 |   33 +++++++++++++++++++++++++--------
src/lib-index/mail-index-view-sync.c |    4 +++-
src/lib-index/mail-index.h           |    3 ++-
src/lib-storage/index/index-sync.c   |    8 ++++++--
src/lib-storage/mail-storage.h       |    3 +++

diffs (205 lines):

diff -r 1ae3d4a5057b -r 2d62129a709b src/imap/client.h
--- a/src/imap/client.h	Wed Jun 11 14:37:49 2008 +0300
+++ b/src/imap/client.h	Wed Jun 11 14:39:52 2008 +0300
@@ -93,6 +93,8 @@ struct client {
 	struct client_command_context *command_queue;
 	unsigned int command_queue_size;
 
+	uint64_t sync_last_full_modseq;
+
 	/* SEARCHRES extension: Last saved SEARCH result */
 	ARRAY_TYPE(seq_range) search_saved_uidset;
 	/* SEARCH=CONTEXT extension: Searches that get updated */
@@ -113,6 +115,7 @@ struct client {
 	unsigned int changing_mailbox:1;
 	unsigned int input_skip_line:1; /* skip all the data until we've
 					   found a new line */
+	unsigned int modseqs_sent_since_sync:1;
 };
 
 /* Create new client with specified input/output handles. socket specifies
diff -r 1ae3d4a5057b -r 2d62129a709b src/imap/cmd-select.c
--- a/src/imap/cmd-select.c	Wed Jun 11 14:37:49 2008 +0300
+++ b/src/imap/cmd-select.c	Wed Jun 11 14:39:52 2008 +0300
@@ -313,6 +313,7 @@ select_open(struct imap_select_context *
 		client_send_line(client,
 			t_strdup_printf("* OK [HIGHESTMODSEQ %llu]",
 				(unsigned long long)status.highest_modseq));
+		client->sync_last_full_modseq = status.highest_modseq;
 	}
 
 	if (ctx->qresync_uid_validity == status.uidvalidity) {
diff -r 1ae3d4a5057b -r 2d62129a709b src/imap/imap-fetch.c
--- a/src/imap/imap-fetch.c	Wed Jun 11 14:37:49 2008 +0300
+++ b/src/imap/imap-fetch.c	Wed Jun 11 14:39:52 2008 +0300
@@ -752,6 +752,7 @@ fetch_modseq_init(struct imap_fetch_cont
 	client_enable(ctx->client, MAILBOX_FEATURE_CONDSTORE);
 	imap_fetch_add_handler(ctx, TRUE, FALSE, name, NULL,
 			       fetch_modseq, NULL);
+	ctx->client->modseqs_sent_since_sync = TRUE;
 	return TRUE;
 }
 
diff -r 1ae3d4a5057b -r 2d62129a709b src/imap/imap-sync.c
--- a/src/imap/imap-sync.c	Wed Jun 11 14:37:49 2008 +0300
+++ b/src/imap/imap-sync.c	Wed Jun 11 14:39:52 2008 +0300
@@ -160,6 +160,7 @@ imap_sync_init(struct client *client, st
 
 int imap_sync_deinit(struct imap_sync_context *ctx)
 {
+	struct client *client = ctx->client;
 	struct mailbox_status status;
 	int ret;
 
@@ -168,7 +169,8 @@ int imap_sync_deinit(struct imap_sync_co
 		array_free(&ctx->expunges);
 
 	if (mailbox_sync_deinit(&ctx->sync_ctx, STATUS_UIDVALIDITY |
-				STATUS_MESSAGES | STATUS_RECENT, &status) < 0 ||
+				STATUS_MESSAGES | STATUS_RECENT |
+				STATUS_HIGHESTMODSEQ, &status) < 0 ||
 	    ctx->failed) {
 		mailbox_transaction_rollback(&ctx->t);
 		array_free(&ctx->tmp_keywords);
@@ -176,25 +178,38 @@ int imap_sync_deinit(struct imap_sync_co
 		return -1;
 	}
 
+	if (!status.sync_delayed_expunges || status.highest_modseq == 0)
+		client->sync_last_full_modseq = status.highest_modseq;
+	else if (client->modseqs_sent_since_sync &&
+		 (client->enabled_features & MAILBOX_FEATURE_QRESYNC) != 0) {
+		/* if client updates highest-modseq using returned MODSEQs
+		   it loses expunges. try to avoid this by sending it a lower
+		   pre-expunge HIGHESTMODSEQ reply. */
+		client_send_line(client, t_strdup_printf(
+			"* OK [HIGHESTMODSEQ %llu]",
+			(unsigned long long)client->sync_last_full_modseq));
+	}
+	client->modseqs_sent_since_sync = FALSE;
+
 	ret = mailbox_transaction_commit(&ctx->t);
 
-	if (status.uidvalidity != ctx->client->uidvalidity) {
+	if (status.uidvalidity != client->uidvalidity) {
 		/* most clients would get confused by this. disconnect them. */
-		client_disconnect_with_error(ctx->client,
+		client_disconnect_with_error(client,
 					     "Mailbox UIDVALIDITY changed");
 	}
 	if (!ctx->no_newmail) {
 		if (status.messages < ctx->messages_count)
 			i_panic("Message count decreased");
-		ctx->client->messages_count = status.messages;
+		client->messages_count = status.messages;
 		if (status.messages != ctx->messages_count) {
-			client_send_line(ctx->client,
+			client_send_line(client,
 				t_strdup_printf("* %u EXISTS", status.messages));
 		}
-		if (status.recent != ctx->client->recent_count &&
+		if (status.recent != client->recent_count &&
 		    !ctx->no_newmail) {
-			ctx->client->recent_count = status.recent;
-			client_send_line(ctx->client,
+			client->recent_count = status.recent;
+			client_send_line(client,
 				t_strdup_printf("* %u RECENT", status.recent));
 		}
 	}
@@ -231,6 +246,7 @@ static int imap_sync_send_flags(struct i
 		str_printfa(str, "UID %u ", ctx->mail->uid);
 	if ((mailbox_get_enabled_features(ctx->box) &
 	     MAILBOX_FEATURE_CONDSTORE) != 0) {
+		ctx->client->modseqs_sent_since_sync = TRUE;
 		str_printfa(str, "MODSEQ %llu ",
 			    (unsigned long long)mail_get_modseq(ctx->mail));
 	}
@@ -250,6 +266,7 @@ static int imap_sync_send_modseq(struct 
 		str_printfa(str, "UID %u ", ctx->mail->uid);
 	str_printfa(str, "MODSEQ %llu)",
 		    (unsigned long long)mail_get_modseq(ctx->mail));
+	ctx->client->modseqs_sent_since_sync = TRUE;
 	return client_send_line(ctx->client, str_c(str));
 }
 
diff -r 1ae3d4a5057b -r 2d62129a709b src/lib-index/mail-index-view-sync.c
--- a/src/lib-index/mail-index-view-sync.c	Wed Jun 11 14:37:49 2008 +0300
+++ b/src/lib-index/mail-index-view-sync.c	Wed Jun 11 14:39:52 2008 +0300
@@ -633,7 +633,8 @@ mail_index_view_sync_clean_log_syncs(str
 		array_delete(&view->syncs_hidden, 0, i);
 }
 
-int mail_index_view_sync_commit(struct mail_index_view_sync_ctx **_ctx)
+int mail_index_view_sync_commit(struct mail_index_view_sync_ctx **_ctx,
+				bool *delayed_expunges_r)
 {
         struct mail_index_view_sync_ctx *ctx = *_ctx;
         struct mail_index_view *view = ctx->view;
@@ -642,6 +643,7 @@ int mail_index_view_sync_commit(struct m
 	i_assert(view->syncing);
 
 	*_ctx = NULL;
+	*delayed_expunges_r = ctx->skipped_expunges;
 
 	if ((!ctx->last_read || view->inconsistent) &&
 	    (ctx->flags & MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT) == 0) {
diff -r 1ae3d4a5057b -r 2d62129a709b src/lib-index/mail-index.h
--- a/src/lib-index/mail-index.h	Wed Jun 11 14:37:49 2008 +0300
+++ b/src/lib-index/mail-index.h	Wed Jun 11 14:39:52 2008 +0300
@@ -314,7 +314,8 @@ void
 void
 mail_index_view_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
 				  const ARRAY_TYPE(seq_range) **expunges_r);
-int mail_index_view_sync_commit(struct mail_index_view_sync_ctx **ctx);
+int mail_index_view_sync_commit(struct mail_index_view_sync_ctx **ctx,
+				bool *delayed_expunges_r);
 
 /* Returns the index header. */
 const struct mail_index_header *
diff -r 1ae3d4a5057b -r 2d62129a709b src/lib-storage/index/index-sync.c
--- a/src/lib-storage/index/index-sync.c	Wed Jun 11 14:37:49 2008 +0300
+++ b/src/lib-storage/index/index-sync.c	Wed Jun 11 14:39:52 2008 +0300
@@ -325,6 +325,7 @@ int index_mailbox_sync_deinit(struct mai
 	struct mailbox_sync_rec sync_rec;
 	const struct mail_index_header *hdr;
 	uint32_t seq1, seq2;
+	bool delayed_expunges = FALSE;
 	int ret = ctx->failed ? -1 : 0;
 
 	/* finish handling expunges, so we don't break when updating
@@ -332,7 +333,8 @@ int index_mailbox_sync_deinit(struct mai
 	while (index_mailbox_sync_next_expunge(ctx, &sync_rec) > 0) ;
 
 	if (ctx->sync_ctx != NULL) {
-		if (mail_index_view_sync_commit(&ctx->sync_ctx) < 0) {
+		if (mail_index_view_sync_commit(&ctx->sync_ctx,
+						&delayed_expunges) < 0) {
 			mail_storage_set_index_error(ibox);
 			ret = -1;
 		}
@@ -354,8 +356,10 @@ int index_mailbox_sync_deinit(struct mai
 		}
 	}
 
-	if (ret == 0 && status_items != 0)
+	if (ret == 0 && status_items != 0) {
 		mailbox_get_status(_ctx->box, status_items, status_r);
+		status_r->sync_delayed_expunges = delayed_expunges;
+	}
 
 	index_sync_search_results_update(ctx);
 
diff -r 1ae3d4a5057b -r 2d62129a709b src/lib-storage/mail-storage.h
--- a/src/lib-storage/mail-storage.h	Wed Jun 11 14:37:49 2008 +0300
+++ b/src/lib-storage/mail-storage.h	Wed Jun 11 14:39:52 2008 +0300
@@ -189,6 +189,9 @@ struct mailbox_status {
 	uint64_t highest_modseq;
 
 	const ARRAY_TYPE(keywords) *keywords;
+
+	/* There are expunges that haven't been synced yet */
+	unsigned int sync_delayed_expunges:1;
 };
 
 struct mailbox_sync_rec {


More information about the dovecot-cvs mailing list