dovecot-1.2: QRESYNC: Send HIGHESTMODSEQ automatically in all ta...

dovecot at dovecot.org dovecot at dovecot.org
Wed Jun 11 15:45:04 EEST 2008


details:   http://hg.dovecot.org/dovecot-1.2/rev/ffaf1ea49704
changeset: 7817:ffaf1ea49704
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Jun 11 15:44:35 2008 +0300
description:
QRESYNC: Send HIGHESTMODSEQ automatically in all tagged replies whenever it
seems useful.

diffstat:

7 files changed, 81 insertions(+), 60 deletions(-)
src/imap/client.h      |    1 
src/imap/cmd-close.c   |   17 +--------
src/imap/cmd-expunge.c |   21 +----------
src/imap/cmd-idle.c    |    4 +-
src/imap/imap-fetch.c  |    8 +++-
src/imap/imap-sync.c   |   87 ++++++++++++++++++++++++++++++++++++------------
src/imap/imap-sync.h   |    3 +

diffs (282 lines):

diff -r ea6727a1220e -r ffaf1ea49704 src/imap/client.h
--- a/src/imap/client.h	Wed Jun 11 15:43:12 2008 +0300
+++ b/src/imap/client.h	Wed Jun 11 15:44:35 2008 +0300
@@ -94,6 +94,7 @@ struct client {
 	unsigned int command_queue_size;
 
 	uint64_t sync_last_full_modseq;
+	uint64_t highest_fetch_modseq;
 
 	/* SEARCHRES extension: Last saved SEARCH result */
 	ARRAY_TYPE(seq_range) search_saved_uidset;
diff -r ea6727a1220e -r ffaf1ea49704 src/imap/cmd-close.c
--- a/src/imap/cmd-close.c	Wed Jun 11 15:43:12 2008 +0300
+++ b/src/imap/cmd-close.c	Wed Jun 11 15:44:35 2008 +0300
@@ -12,19 +12,6 @@ static void cmd_close_finish(struct clie
 			mailbox_get_storage(client->mailbox));
 	}
 	client_update_mailbox_flags(client, NULL);
-}
-
-static bool cmd_close_callback(struct client_command_context *cmd)
-{
-	struct mailbox_status status;
-
-	mailbox_get_status(cmd->client->mailbox,
-			   STATUS_HIGHESTMODSEQ, &status);
-	cmd_close_finish(cmd->client);
-	client_send_tagline(cmd, t_strdup_printf(
-		"OK [HIGHESTMODSEQ %llu] Close completed.",
-		(unsigned long long)status.highest_modseq));
-	return TRUE;
 }
 
 bool cmd_close(struct client_command_context *cmd)
@@ -51,8 +38,8 @@ bool cmd_close(struct client_command_con
 		   it by syncing the mailbox one last time. We wouldn't need
 		   to include our own expunge in there, but it's too much
 		   trouble to hide it. */
-		return cmd_sync_callback(cmd, 0, IMAP_SYNC_FLAG_SAFE,
-					 cmd_close_callback);
+		return cmd_sync(cmd, 0, IMAP_SYNC_FLAG_SAFE,
+				"OK Close completed.");
 	} else {
 		if (mailbox_sync(mailbox, 0, 0, NULL) < 0)
 			client_send_untagged_storage_error(client, storage);
diff -r ea6727a1220e -r ffaf1ea49704 src/imap/cmd-expunge.c
--- a/src/imap/cmd-expunge.c	Wed Jun 11 15:43:12 2008 +0300
+++ b/src/imap/cmd-expunge.c	Wed Jun 11 15:44:35 2008 +0300
@@ -19,22 +19,6 @@ static bool cmd_expunge_callback(struct 
 	return TRUE;
 }
 
-static bool cmd_expunge_callback_qresync(struct client_command_context *cmd)
-{
-	struct mailbox_status status;
-
-	if (!cmd->client->sync_seen_expunges)
-		client_send_tagline(cmd, "OK Expunge completed.");
-	else {
-		mailbox_get_status(cmd->client->mailbox,
-				   STATUS_HIGHESTMODSEQ, &status);
-		client_send_tagline(cmd, t_strdup_printf(
-			"OK [HIGHESTMODSEQ %llu] Expunge completed.",
-			(unsigned long long)status.highest_modseq));
-	}
-	return TRUE;
-}
-
 static bool cmd_expunge_finish(struct client_command_context *cmd,
 			       struct mail_search_args *search_args)
 {
@@ -52,9 +36,8 @@ static bool cmd_expunge_finish(struct cl
 	client->sync_seen_deletes = FALSE;
 	client->sync_seen_expunges = FALSE;
 	if ((client->enabled_features & MAILBOX_FEATURE_QRESYNC) != 0) {
-		return cmd_sync_callback(cmd, MAILBOX_SYNC_FLAG_EXPUNGE,
-					 IMAP_SYNC_FLAG_SAFE,
-					 cmd_expunge_callback_qresync);
+		return cmd_sync(cmd, MAILBOX_SYNC_FLAG_EXPUNGE,
+				IMAP_SYNC_FLAG_SAFE, "OK Expunge completed.");
 	} else {
 		return cmd_sync_callback(cmd, MAILBOX_SYNC_FLAG_EXPUNGE,
 					 IMAP_SYNC_FLAG_SAFE,
diff -r ea6727a1220e -r ffaf1ea49704 src/imap/cmd-idle.c
--- a/src/imap/cmd-idle.c	Wed Jun 11 15:43:12 2008 +0300
+++ b/src/imap/cmd-idle.c	Wed Jun 11 15:44:35 2008 +0300
@@ -37,7 +37,7 @@ idle_finish(struct cmd_idle_context *ctx
 
 	if (ctx->sync_ctx != NULL) {
 		/* we're here only in connection failure cases */
-		(void)imap_sync_deinit(ctx->sync_ctx);
+		(void)imap_sync_deinit(ctx->sync_ctx, ctx->cmd);
 	}
 
 	o_stream_cork(client->output);
@@ -157,7 +157,7 @@ static bool cmd_idle_continue(struct cli
 			return FALSE;
 		}
 
-		if (imap_sync_deinit(ctx->sync_ctx) < 0) {
+		if (imap_sync_deinit(ctx->sync_ctx, ctx->cmd) < 0) {
 			client_send_untagged_storage_error(client,
 				mailbox_get_storage(client->mailbox));
 			mailbox_notify_changes_stop(client->mailbox);
diff -r ea6727a1220e -r ffaf1ea49704 src/imap/imap-fetch.c
--- a/src/imap/imap-fetch.c	Wed Jun 11 15:43:12 2008 +0300
+++ b/src/imap/imap-fetch.c	Wed Jun 11 15:44:35 2008 +0300
@@ -740,8 +740,13 @@ static int fetch_modseq(struct imap_fetc
 static int fetch_modseq(struct imap_fetch_context *ctx, struct mail *mail,
 			void *context ATTR_UNUSED)
 {
+	uint64_t modseq;
+
+	modseq = mail_get_modseq(mail);
+	if (ctx->client->highest_fetch_modseq < modseq)
+		ctx->client->highest_fetch_modseq = modseq;
 	str_printfa(ctx->cur_str, "MODSEQ %llu ",
-		    (unsigned long long)mail_get_modseq(mail));
+		    (unsigned long long)modseq);
 	return 1;
 }
 
@@ -752,7 +757,6 @@ 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 ea6727a1220e -r ffaf1ea49704 src/imap/imap-sync.c
--- a/src/imap/imap-sync.c	Wed Jun 11 15:43:12 2008 +0300
+++ b/src/imap/imap-sync.c	Wed Jun 11 15:44:35 2008 +0300
@@ -158,7 +158,54 @@ imap_sync_init(struct client *client, st
 	return ctx;
 }
 
-int imap_sync_deinit(struct imap_sync_context *ctx)
+static void
+imap_sync_send_highestmodseq(struct imap_sync_context *ctx,
+			     const struct mailbox_status *status,
+			     struct client_command_context *sync_cmd)
+{
+	struct client *client = ctx->client;
+	uint64_t send_modseq = 0;
+
+	if (status->sync_delayed_expunges &&
+	    client->highest_fetch_modseq > client->sync_last_full_modseq) {
+		/* if client updates highest-modseq using returned MODSEQs
+		   it loses expunges. try to avoid this by sending it a lower
+		   pre-expunge HIGHESTMODSEQ reply. */
+		send_modseq = client->sync_last_full_modseq;
+	} else if (!status->sync_delayed_expunges &&
+		   status->highest_modseq > client->sync_last_full_modseq &&
+		   status->highest_modseq > client->highest_fetch_modseq) {
+		/* we've probably send some VANISHED or EXISTS replies which
+		   increased the highest-modseq. notify the client about
+		   this. */
+		send_modseq = status->highest_modseq;
+	}
+
+	if (send_modseq == 0) {
+		/* no sending */
+	} else if (strncmp(sync_cmd->sync->tagline, "OK ", 3) == 0 &&
+		   sync_cmd->sync->tagline[3] != '[') {
+		/* modify the tagged reply directly */
+		sync_cmd->sync->tagline = p_strdup_printf(sync_cmd->pool,
+			"OK [HIGHESTMODSEQ %llu] %s",
+			(unsigned long long)send_modseq,
+			sync_cmd->sync->tagline + 3);
+	} else {
+		/* send an untagged OK reply */
+		client_send_line(client, t_strdup_printf(
+			"* OK [HIGHESTMODSEQ %llu]",
+			(unsigned long long)send_modseq));
+	}
+
+	if (!status->sync_delayed_expunges) {
+		/* no delayed expunges, remember this for future */
+		client->sync_last_full_modseq = status->highest_modseq;
+	}
+	client->highest_fetch_modseq = 0;
+}
+
+int imap_sync_deinit(struct imap_sync_context *ctx,
+		     struct client_command_context *sync_cmd)
 {
 	struct client *client = ctx->client;
 	struct mailbox_status status;
@@ -178,19 +225,6 @@ 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 != client->uidvalidity) {
@@ -217,6 +251,9 @@ int imap_sync_deinit(struct imap_sync_co
 	   now it contains added/removed messages. */
 	imap_sync_send_search_updates(ctx);
 
+	if ((client->enabled_features & MAILBOX_FEATURE_QRESYNC) != 0)
+		imap_sync_send_highestmodseq(ctx, &status, sync_cmd);
+
 	if (array_is_created(&ctx->search_removes)) {
 		array_free(&ctx->search_removes);
 		array_free(&ctx->search_adds);
@@ -225,6 +262,16 @@ int imap_sync_deinit(struct imap_sync_co
 	array_free(&ctx->tmp_keywords);
 	i_free(ctx);
 	return ret;
+}
+
+static void imap_sync_add_modseq(struct imap_sync_context *ctx, string_t *str)
+{
+	uint64_t modseq;
+
+	modseq = mail_get_modseq(ctx->mail);
+	if (ctx->client->highest_fetch_modseq < modseq)
+		ctx->client->highest_fetch_modseq = modseq;
+	str_printfa(str, "MODSEQ %llu", (unsigned long long)modseq);
 }
 
 static int imap_sync_send_flags(struct imap_sync_context *ctx, string_t *str)
@@ -246,9 +293,8 @@ 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));
+		imap_sync_add_modseq(ctx, str);
+		str_append_c(str, ' ');
 	}
 	str_append(str, "FLAGS (");
 	imap_write_flags(str, flags, keywords);
@@ -264,9 +310,8 @@ static int imap_sync_send_modseq(struct 
 	str_printfa(str, "* %u FETCH (", ctx->seq);
 	if (ctx->imap_flags & IMAP_SYNC_FLAG_SEND_UID)
 		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;
+	imap_sync_add_modseq(ctx, str);
+	str_append_c(str, ')');
 	return client_send_line(ctx->client, str_c(str));
 }
 
@@ -446,7 +491,7 @@ static bool cmd_sync_continue(struct cli
 		ctx->failed = TRUE;
 
 	client->syncing = FALSE;
-	if (imap_sync_deinit(ctx) < 0) {
+	if (imap_sync_deinit(ctx, sync_cmd) < 0) {
 		client_send_untagged_storage_error(client,
 			mailbox_get_storage(client->mailbox));
 	}
diff -r ea6727a1220e -r ffaf1ea49704 src/imap/imap-sync.h
--- a/src/imap/imap-sync.h	Wed Jun 11 15:43:12 2008 +0300
+++ b/src/imap/imap-sync.h	Wed Jun 11 15:44:35 2008 +0300
@@ -13,7 +13,8 @@ struct imap_sync_context *
 struct imap_sync_context *
 imap_sync_init(struct client *client, struct mailbox *box,
 	       enum imap_sync_flags imap_flags, enum mailbox_sync_flags flags);
-int imap_sync_deinit(struct imap_sync_context *ctx);
+int imap_sync_deinit(struct imap_sync_context *ctx,
+		     struct client_command_context *sync_cmd);
 int imap_sync_more(struct imap_sync_context *ctx);
 
 bool cmd_sync(struct client_command_context *cmd, enum mailbox_sync_flags flags,


More information about the dovecot-cvs mailing list