changeset 7421:ac984d42917f HEAD

If sync queue has commands that don't allow EXPUNGEs and also commands that do allow them, sync first the ones that don't allow EXPUNGEs, otherwise we could send untagged EXPUNGEs before e.g. tagged FETCH reply.
author Timo Sirainen <tss@iki.fi>
date Sun, 16 Mar 2008 12:01:09 +0200
parents a4a552321bd3
children ae746a73e51e
files src/imap/imap-sync.c
diffstat 1 files changed, 25 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap/imap-sync.c	Sat Mar 15 07:31:44 2008 +0200
+++ b/src/imap/imap-sync.c	Sun Mar 16 12:01:09 2008 +0200
@@ -263,10 +263,9 @@
 			count++;
 		}
 	}
+	i_assert(noexpunges_count == 0 || noexpunges_count == count);
 	if (fast_count != count)
 		*flags_r &= ~MAILBOX_SYNC_FLAG_FAST;
-	if (noexpunges_count != count)
-		*flags_r &= ~MAILBOX_SYNC_FLAG_NO_EXPUNGES;
 
 	i_assert((*flags_r & (MAILBOX_SYNC_AUTO_STOP |
 			      MAILBOX_SYNC_FLAG_FIX_INCONSISTENT)) == 0);
@@ -383,7 +382,7 @@
 
 bool cmd_sync_delayed(struct client *client)
 {
-	struct client_command_context *cmd;
+	struct client_command_context *cmd, *first_expunge, *first_nonexpunge;
 
 	if (client->output_lock != NULL) {
 		/* wait until we can send output to client */
@@ -397,13 +396,32 @@
 		return cmd_sync_drop_fast(client);
 	}
 
-	/* find a command that we can sync */
+	/* separate syncs that can send expunges from those that can't */
+	first_expunge = first_nonexpunge = NULL;
 	for (cmd = client->command_queue; cmd != NULL; cmd = cmd->next) {
-		if (cmd->state == CLIENT_COMMAND_STATE_WAIT_SYNC) {
-			if (cmd->sync->counter == client->sync_counter)
-				break;
+		if (cmd->sync != NULL &&
+		    cmd->sync->counter == client->sync_counter) {
+			if (cmd->sync->flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) {
+				if (first_nonexpunge == NULL)
+					first_nonexpunge = cmd;
+			} else {
+				if (first_expunge == NULL)
+					first_expunge = cmd;
+			}
 		}
 	}
+	if (first_expunge != NULL && first_nonexpunge != NULL) {
+		/* sync expunges after nonexpunges */
+		for (cmd = first_expunge; cmd != NULL; cmd = cmd->next) {
+			if (cmd->sync != NULL &&
+			    cmd->sync->counter == client->sync_counter &&
+			    (cmd->sync->flags &
+			     MAILBOX_SYNC_FLAG_NO_EXPUNGES) == 0)
+				cmd->sync->counter++;
+		}
+		first_expunge = NULL;
+	}
+	cmd = first_nonexpunge != NULL ? first_nonexpunge : first_expunge;
 
 	if (cmd == NULL)
 		return cmd_sync_drop_fast(client);