[dovecot-cvs] dovecot/src/imap client.c, 1.39, 1.40 client.h, 1.21, 1.22 cmd-append.c, 1.40, 1.41 cmd-check.c, 1.3, 1.4 cmd-copy.c, 1.22, 1.23 cmd-expunge.c, 1.7, 1.8 cmd-fetch.c, 1.21, 1.22 cmd-idle.c, 1.12, 1.13 cmd-noop.c, 1.3, 1.4 cmd-search.c, 1.20, 1.21 cmd-select.c, 1.29, 1.30 cmd-sort.c, 1.15, 1.16 cmd-status.c, 1.19, 1.20 cmd-store.c, 1.25, 1.26 cmd-thread.c, 1.7, 1.8 commands-util.c, 1.35, 1.36 commands-util.h, 1.16, 1.17 commands.h, 1.14, 1.15 imap-sync.c, 1.2, 1.3 imap-sync.h, 1.1, 1.2

cras at dovecot.org cras at dovecot.org
Thu Aug 19 02:53:42 EEST 2004


Update of /home/cvs/dovecot/src/imap
In directory talvi:/tmp/cvs-serv10555

Modified Files:
	client.c client.h cmd-append.c cmd-check.c cmd-copy.c 
	cmd-expunge.c cmd-fetch.c cmd-idle.c cmd-noop.c cmd-search.c 
	cmd-select.c cmd-sort.c cmd-status.c cmd-store.c cmd-thread.c 
	commands-util.c commands-util.h commands.h imap-sync.c 
	imap-sync.h 
Log Message:
Syncing works now too without buffering everything. Also fixed handling
input while command was being processed.



Index: client.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/client.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- client.c	18 Aug 2004 05:13:47 -0000	1.39
+++ client.c	18 Aug 2004 23:53:39 -0000	1.40
@@ -67,9 +67,6 @@
 	if (client->io != NULL)
 		io_remove(client->io);
 
-	if (client->idle_to != NULL)
-		timeout_remove(client->idle_to);
-
 	i_stream_unref(client->input);
 	o_stream_unref(client->output);
 
@@ -235,7 +232,10 @@
 	client->cmd_uid = FALSE;
 
 	p_clear(client->cmd_pool);
-        imap_parser_reset(client->parser);
+	imap_parser_reset(client->parser);
+
+	if (client->input_pending)
+                client_input(client);
 }
 
 /* Skip incoming data until newline is found,
@@ -334,6 +334,7 @@
 		client->io = NULL;
 	}
 
+	client->input_pending = FALSE;
 	client->last_input = ioloop_time;
 
 	switch (i_stream_read(client->input)) {
@@ -357,6 +358,9 @@
 		;
 	o_stream_uncork(client->output);
 
+	if (client->command_pending)
+		client->input_pending = TRUE;
+
 	if (client->output->closed)
 		client_destroy(client);
 }

Index: client.h
===================================================================
RCS file: /home/cvs/dovecot/src/imap/client.h,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- client.h	18 Aug 2004 05:13:47 -0000	1.21
+++ client.h	18 Aug 2004 23:53:39 -0000	1.22
@@ -37,10 +37,8 @@
 	command_func_t *cmd_func;
 	void *cmd_context;
 
-	struct timeout *idle_to;
-	unsigned int idle_expunge;
-
 	unsigned int command_pending:1;
+	unsigned int input_pending:1;
 	unsigned int cmd_uid:1; /* used UID command */
 	unsigned int rawlog:1;
 	unsigned int input_skip_line:1; /* skip all the data until we've

Index: cmd-append.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-append.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- cmd-append.c	15 Aug 2004 03:40:30 -0000	1.40
+++ cmd-append.c	18 Aug 2004 23:53:39 -0000	1.41
@@ -58,6 +58,7 @@
 	struct istream *input;
 	time_t internal_date;
 	const char *mailbox, *internal_date_str;
+        enum mailbox_sync_flags sync_flags = 0;
 	uoff_t msg_size;
 	unsigned int count;
 	int ret, failed, timezone_offset, nonsync;
@@ -207,13 +208,11 @@
 		}
 	}
 
-	if (box != client->mailbox)
+	if (box != client->mailbox) {
+		sync_flags |= MAILBOX_SYNC_FLAG_FAST;
 		mailbox_close(box);
-
-	if (!failed) {
-		client_sync_full(client);
-		client_send_tagline(client, "OK Append completed.");
 	}
 
-	return TRUE;
+	return failed ? TRUE :
+		cmd_sync(client, sync_flags, "OK Append completed.");
 }

Index: cmd-check.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-check.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- cmd-check.c	5 Jan 2003 13:09:51 -0000	1.3
+++ cmd-check.c	18 Aug 2004 23:53:39 -0000	1.4
@@ -8,8 +8,5 @@
 	if (!client_verify_open_mailbox(client))
 		return TRUE;
 
-	/* we don't need this command, but sync the mailbox anyway. */
-	client_sync_full(client);
-	client_send_tagline(client, "OK Check completed.");
-	return TRUE;
+	return cmd_sync(client, 0, "OK Check completed.");
 }

Index: cmd-copy.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-copy.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- cmd-copy.c	22 Jul 2004 21:20:00 -0000	1.22
+++ cmd-copy.c	18 Aug 2004 23:53:39 -0000	1.23
@@ -55,6 +55,7 @@
 	struct mailbox_transaction_context *t;
         struct mail_search_arg *search_arg;
 	const char *messageset, *mailbox;
+        enum mailbox_sync_flags sync_flags = 0;
 	int ret;
 
 	/* <message set> <mailbox> */
@@ -100,22 +101,19 @@
 			ret = -1;
 	}
 
-	if (ret < 0)
-		client_send_storage_error(client, storage);
+	if (destbox != client->mailbox) {
+		sync_flags |= MAILBOX_SYNC_FLAG_FAST;
+		mailbox_close(destbox);
+	}
+
+	if (ret > 0)
+		return cmd_sync(client, sync_flags, "OK Copy completed.");
 	else if (ret == 0) {
 		/* some messages were expunged, sync them */
-		client_sync_full(client);
-		client_send_tagline(client,
+		return cmd_sync(client, 0,
 			"NO Some of the requested messages no longer exist.");
 	} else {
-		if (destbox == client->mailbox)
-			client_sync_full(client);
-		else
-			client_sync_full_fast(client);
-		client_send_tagline(client, "OK Copy completed.");
+		client_send_storage_error(client, storage);
+		return TRUE;
 	}
-
-	if (destbox != client->mailbox)
-		mailbox_close(destbox);
-	return TRUE;
 }

Index: cmd-expunge.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-expunge.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- cmd-expunge.c	20 Jun 2004 03:25:33 -0000	1.7
+++ cmd-expunge.c	18 Aug 2004 23:53:39 -0000	1.8
@@ -27,15 +27,13 @@
 	if (search_arg == NULL)
 		return TRUE;
 
-	if (imap_expunge(client->mailbox, search_arg)) {
-		client_sync_full(client);
-		client_send_tagline(client, "OK Expunge completed.");
-	} else {
+	if (imap_expunge(client->mailbox, search_arg))
+		return cmd_sync(client, 0, "OK Expunge completed.");
+	else {
 		client_send_storage_error(client,
 					  mailbox_get_storage(client->mailbox));
+		return TRUE;
 	}
-
-	return TRUE;
 }
 
 int cmd_expunge(struct client *client)
@@ -43,13 +41,11 @@
 	if (!client_verify_open_mailbox(client))
 		return TRUE;
 
-	if (imap_expunge(client->mailbox, NULL)) {
-		client_sync_full(client);
-		client_send_tagline(client, "OK Expunge completed.");
-	} else {
+	if (imap_expunge(client->mailbox, NULL))
+		return cmd_sync(client, 0, "OK Expunge completed.");
+	else {
 		client_send_storage_error(client,
 					  mailbox_get_storage(client->mailbox));
+		return TRUE;
 	}
-
-	return TRUE;
 }

Index: cmd-fetch.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-fetch.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- cmd-fetch.c	15 Aug 2004 03:40:30 -0000	1.21
+++ cmd-fetch.c	18 Aug 2004 23:53:39 -0000	1.22
@@ -61,19 +61,11 @@
 	return TRUE;
 }
 
-static void cmd_fetch_finish(struct client *client, int failed)
+static int cmd_fetch_finish(struct client *client, int failed)
 {
-	if (!failed) {
-		if ((client_workarounds &
-		     WORKAROUND_OE6_FETCH_NO_NEWMAIL) == 0) {
-			if (client->cmd_uid)
-				client_sync_full_fast(client);
-			else
-				client_sync_without_expunges(client);
-		}
+	static const char *ok_message = "OK Fetch completed.";
 
-		client_send_tagline(client, "OK Fetch completed.");
-	} else {
+	if (failed) {
 		struct mail_storage *storage;
 		const char *error;
 		int syntax;
@@ -92,6 +84,14 @@
 			/* user error, we'll reply with BAD */
 			client_send_storage_error(client, storage);
 		}
+		return TRUE;
+	} if ((client_workarounds & WORKAROUND_OE6_FETCH_NO_NEWMAIL) != 0) {
+		client_send_tagline(client, ok_message);
+		return TRUE;
+	} else {
+		return cmd_sync(client, MAILBOX_SYNC_FLAG_FAST |
+				(client->cmd_uid ? 0 :
+				 MAILBOX_SYNC_FLAG_NO_EXPUNGES), ok_message);
 	}
 }
 
@@ -106,8 +106,7 @@
 	}
 	if (imap_fetch_deinit(ctx) < 0)
 		ret = -1;
-	cmd_fetch_finish(client, ret < 0);
-	return TRUE;
+	return cmd_fetch_finish(client, ret < 0);
 }
 
 int cmd_fetch(struct client *client)
@@ -154,6 +153,5 @@
 	}
 	if (imap_fetch_deinit(ctx) < 0)
 		ret = -1;
-	cmd_fetch_finish(client, ret < 0);
-	return TRUE;
+	return cmd_fetch_finish(client, ret < 0);
 }

Index: cmd-idle.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-idle.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- cmd-idle.c	15 Aug 2004 03:40:30 -0000	1.12
+++ cmd-idle.c	18 Aug 2004 23:53:39 -0000	1.13
@@ -11,18 +11,34 @@
 
 #define DEFAULT_IDLE_CHECK_INTERVAL 30
 
-static void idle_finish(struct client *client, int done_ok)
+struct cmd_idle_context {
+	struct client *client;
+
+	struct imap_sync_context *sync_ctx;
+	struct timeout *to;
+	uint32_t dummy_seq;
+
+	unsigned int idle_timeout:1;
+	unsigned int sync_pending:1;
+};
+
+static int cmd_idle_continue(struct client *client);
+
+static void idle_finish(struct cmd_idle_context *ctx, int done_ok)
 {
-	if (client->idle_to != NULL) {
-		timeout_remove(client->idle_to);
-		client->idle_to = NULL;
+	struct client *client = ctx->client;
+
+	if (ctx->to != NULL) {
+		timeout_remove(ctx->to);
+		ctx->to = NULL;
 	}
 
 	o_stream_cork(client->output);
 
-	if (client->idle_expunge != 0) {
+	if (ctx->dummy_seq != 0) {
+		/* outlook idle workaround */
 		client_send_line(client,
-			t_strdup_printf("* %u EXPUNGE", client->idle_expunge));
+			t_strdup_printf("* %u EXPUNGE", ctx->dummy_seq));
 	}
 
 	io_remove(client->io);
@@ -31,7 +47,6 @@
 	if (client->mailbox != NULL)
 		mailbox_notify_changes(client->mailbox, 0, NULL, NULL);
 
-	client_sync_full(client);
 	if (done_ok)
 		client_send_tagline(client, "OK Idle completed.");
 	else
@@ -45,7 +60,8 @@
 
 static void idle_client_input(void *context)
 {
-	struct client *client = context;
+        struct cmd_idle_context *ctx = context;
+	struct client *client = ctx->client;
 	char *line;
 
 	client->last_input = ioloop_time;
@@ -57,7 +73,7 @@
 		return;
 	case -2:
 		client->input_skip_line = TRUE;
-		idle_finish(client, FALSE);
+		idle_finish(ctx, FALSE);
 		return;
 	}
 
@@ -65,50 +81,95 @@
 		if (client->input_skip_line)
 			client->input_skip_line = FALSE;
 		else {
-			idle_finish(client, strcmp(line, "DONE") == 0);
+			idle_finish(ctx, strcmp(line, "DONE") == 0);
 			break;
 		}
 	}
 }
 
+static void idle_send_expunge(struct cmd_idle_context *ctx)
+{
+	struct client *client = ctx->client;
+
+	ctx->dummy_seq = client->messages_count+1;
+	client_send_line(client,
+			 t_strdup_printf("* %u EXISTS", ctx->dummy_seq));
+	mailbox_notify_changes(client->mailbox, 0, NULL, NULL);
+}
+
 static void idle_timeout(void *context)
 {
-	struct client *client = context;
+	struct cmd_idle_context *ctx = context;
 
 	/* outlook workaround - it hasn't sent anything for a long time and
 	   we're about to disconnect unless it does something. send a fake
 	   EXISTS to see if it responds. it's expunged later. */
 
-	timeout_remove(client->idle_to);
-	client->idle_to = NULL;
+	timeout_remove(ctx->to);
+	ctx->to = NULL;
 
-	client->idle_expunge = client->messages_count+1;
-	client_send_line(client,
-			 t_strdup_printf("* %u EXISTS", client->idle_expunge));
-	mailbox_notify_changes(client->mailbox, 0, NULL, NULL);
+	if (ctx->sync_ctx != NULL) {
+		/* we're already syncing.. do this after it's finished */
+		ctx->idle_timeout = TRUE;
+		return;
+	}
+
+	idle_send_expunge(ctx);
 }
 
 static void idle_callback(struct mailbox *box, void *context)
 {
-	struct client *client = context;
+        struct cmd_idle_context *ctx = context;
 
-	if (imap_sync(client, box, 0) < 0) {
+	if (ctx->sync_ctx != NULL)
+		ctx->sync_pending = TRUE;
+	else {
+		ctx->sync_pending = FALSE;
+		ctx->sync_ctx = imap_sync_init(ctx->client, box, 0);
+		cmd_idle_continue(ctx->client);
+	}
+}
+
+static int cmd_idle_continue(struct client *client)
+{
+	struct cmd_idle_context *ctx = client->cmd_context;
+
+	if (imap_sync_more(ctx->sync_ctx) == 0) {
+		/* unfinished */
+		return FALSE;
+	}
+
+	if (imap_sync_deinit(ctx->sync_ctx) < 0) {
 		client_send_untagged_storage_error(client,
 			mailbox_get_storage(client->mailbox));
 		mailbox_notify_changes(client->mailbox, 0, NULL, NULL);
 	}
+	ctx->sync_ctx = NULL;
+
+	if (ctx->idle_timeout) {
+		/* outlook workaround */
+		idle_send_expunge(ctx);
+	} else if (ctx->sync_pending) {
+		/* more changes occured while we were sending changes to
+		   client */
+                idle_callback(client->mailbox, client);
+	}
+	return FALSE;
 }
 
 int cmd_idle(struct client *client)
 {
+	struct cmd_idle_context *ctx;
 	const char *str;
 	unsigned int interval;
 
-        client->idle_expunge = 0;
+	ctx = p_new(client->cmd_pool, struct cmd_idle_context, 1);
+	ctx->client = client;
+
 	if ((client_workarounds & WORKAROUND_OUTLOOK_IDLE) != 0 &&
 	    client->mailbox != NULL) {
-		client->idle_to = timeout_add((CLIENT_IDLE_TIMEOUT - 60) * 1000,
-					      idle_timeout, client);
+		ctx->to = timeout_add((CLIENT_IDLE_TIMEOUT - 60) * 1000,
+				      idle_timeout, ctx);
 	}
 
 	str = getenv("MAILBOX_IDLE_CHECK_INTERVAL");
@@ -118,12 +179,16 @@
 
 	if (client->mailbox != NULL) {
 		mailbox_notify_changes(client->mailbox, interval,
-				       idle_callback, client);
+				       idle_callback, ctx);
 	}
 	client_send_line(client, "+ idling");
 
 	io_remove(client->io);
 	client->io = io_add(i_stream_get_fd(client->input),
-			    IO_READ, idle_client_input, client);
+			    IO_READ, idle_client_input, ctx);
+
+	client->command_pending = TRUE;
+	client->cmd_func = cmd_idle_continue;
+	client->cmd_context = ctx;
 	return FALSE;
 }

Index: cmd-noop.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-noop.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- cmd-noop.c	5 Jan 2003 13:09:51 -0000	1.3
+++ cmd-noop.c	18 Aug 2004 23:53:39 -0000	1.4
@@ -5,7 +5,5 @@
 
 int cmd_noop(struct client *client)
 {
-	client_sync_full(client);
-	client_send_tagline(client, "OK NOOP completed.");
-	return TRUE;
+	return cmd_sync(client, 0, "OK NOOP completed.");
 }

Index: cmd-search.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-search.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- cmd-search.c	15 Aug 2004 03:40:30 -0000	1.20
+++ cmd-search.c	18 Aug 2004 23:53:39 -0000	1.21
@@ -95,11 +95,10 @@
 		/* error in search arguments */
 		client_send_tagline(client, t_strconcat("NO ", error, NULL));
 	} else if (imap_search(client, charset, sargs)) {
-		if (client->cmd_uid)
-			client_sync_full_fast(client);
-		else
-			client_sync_without_expunges(client);
-		client_send_tagline(client, "OK Search completed.");
+		return cmd_sync(client, MAILBOX_SYNC_FLAG_FAST |
+				(client->cmd_uid ?
+				 0 : MAILBOX_SYNC_FLAG_NO_EXPUNGES),
+				"OK Search completed.");
 	} else {
 		client_send_storage_error(client,
 					  mailbox_get_storage(client->mailbox));

Index: cmd-select.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-select.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- cmd-select.c	22 Jul 2004 21:20:00 -0000	1.29
+++ cmd-select.c	18 Aug 2004 23:53:39 -0000	1.30
@@ -35,7 +35,7 @@
 		return TRUE;
 	}
 
-	if (imap_sync(client, box, 0) < 0) {
+	if (imap_sync_nonselected(box, 0) < 0) {
 		client_send_storage_error(client, storage);
 		mailbox_close(box);
 		return TRUE;

Index: cmd-sort.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-sort.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- cmd-sort.c	16 May 2004 23:11:17 -0000	1.15
+++ cmd-sort.c	18 Aug 2004 23:53:39 -0000	1.16
@@ -121,12 +121,11 @@
 		/* error in search arguments */
 		client_send_tagline(client, t_strconcat("NO ", error, NULL));
 	} else if (imap_sort(client, charset, sargs, sorting) == 0) {
-		/* NOTE: syncing is allowed when returning UIDs */
-		if (client->cmd_uid)
-			client_sync_full_fast(client);
-		else
-			client_sync_without_expunges(client);
-		client_send_tagline(client, "OK Sort completed.");
+		pool_unref(pool);
+		return cmd_sync(client, MAILBOX_SYNC_FLAG_FAST |
+				(client->cmd_uid ?
+				 0 : MAILBOX_SYNC_FLAG_NO_EXPUNGES),
+				"OK Sort completed.");
 	} else {
 		client_send_storage_error(client,
 					  mailbox_get_storage(client->mailbox));

Index: cmd-status.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-status.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- cmd-status.c	22 Jul 2004 21:20:00 -0000	1.19
+++ cmd-status.c	18 Aug 2004 23:53:39 -0000	1.20
@@ -65,7 +65,7 @@
 			return FALSE;
 	}
 
-	if (imap_sync(client, box, 0) < 0)
+	if (imap_sync_nonselected(box, 0) < 0)
 		failed = TRUE;
 	else
 		failed = mailbox_get_status(box, items, status) < 0;

Index: cmd-store.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-store.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- cmd-store.c	18 Aug 2004 05:10:45 -0000	1.25
+++ cmd-store.c	18 Aug 2004 23:53:39 -0000	1.26
@@ -105,14 +105,12 @@
 	}
 
 	if (!failed) {
-		if (client->cmd_uid)
-			client_sync_full_fast(client);
-		else
-			client_sync_without_expunges(client);
-		client_send_tagline(client, "OK Store completed.");
+		return cmd_sync(client, MAILBOX_SYNC_FLAG_FAST |
+				(client->cmd_uid ?
+				 0 : MAILBOX_SYNC_FLAG_NO_EXPUNGES),
+				"OK Store completed.");
 	} else {
 		client_send_storage_error(client, mailbox_get_storage(box));
+		return TRUE;
 	}
-
-	return TRUE;
 }

Index: cmd-thread.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-thread.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- cmd-thread.c	16 May 2004 23:11:17 -0000	1.7
+++ cmd-thread.c	18 Aug 2004 23:53:39 -0000	1.8
@@ -63,12 +63,11 @@
 		/* error in search arguments */
 		client_send_tagline(client, t_strconcat("NO ", error, NULL));
 	} else if (imap_thread(client, charset, sargs, threading) == 0) {
-		/* NOTE: syncing is allowed when returning UIDs */
-		if (client->cmd_uid)
-			client_sync_full_fast(client);
-		else
-			client_sync_without_expunges(client);
-		client_send_tagline(client, "OK Search completed.");
+		pool_unref(pool);
+		return cmd_sync(client, MAILBOX_SYNC_FLAG_FAST |
+				(client->cmd_uid ?
+				 0 : MAILBOX_SYNC_FLAG_NO_EXPUNGES),
+				"OK Thread completed.");
 	} else {
 		client_send_storage_error(client,
 					  mailbox_get_storage(client->mailbox));

Index: commands-util.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/commands-util.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -d -r1.35 -r1.36
--- commands-util.c	18 Aug 2004 05:13:47 -0000	1.35
+++ commands-util.c	18 Aug 2004 23:53:39 -0000	1.36
@@ -112,40 +112,6 @@
 	}
 }
 
-void client_sync_full(struct client *client)
-{
-	if (client->mailbox == NULL)
-		return;
-
-	if (imap_sync(client, client->mailbox, 0) < 0) {
-		client_send_untagged_storage_error(client,
-			mailbox_get_storage(client->mailbox));
-	}
-}
-
-void client_sync_full_fast(struct client *client)
-{
-	if (client->mailbox == NULL)
-		return;
-
-	if (imap_sync(client, client->mailbox, MAILBOX_SYNC_FLAG_FAST) < 0) {
-		client_send_untagged_storage_error(client,
-			mailbox_get_storage(client->mailbox));
-	}
-}
-
-void client_sync_without_expunges(struct client *client)
-{
-	if (client->mailbox == NULL)
-		return;
-
-	if (imap_sync(client, client->mailbox, MAILBOX_SYNC_FLAG_FAST |
-		      MAILBOX_SYNC_FLAG_NO_EXPUNGES) < 0) {
-		client_send_untagged_storage_error(client,
-			mailbox_get_storage(client->mailbox));
-	}
-}
-
 void client_send_storage_error(struct client *client,
 			       struct mail_storage *storage)
 {

Index: commands-util.h
===================================================================
RCS file: /home/cvs/dovecot/src/imap/commands-util.h,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- commands-util.h	22 Jul 2004 21:20:00 -0000	1.16
+++ commands-util.h	18 Aug 2004 23:53:39 -0000	1.17
@@ -26,16 +26,6 @@
    error message to client. */
 int client_verify_open_mailbox(struct client *client);
 
-/* Synchronize selected mailbox with client by sending EXPUNGE,
-   FETCH FLAGS, EXISTS and RECENT responses. */
-void client_sync_full(struct client *client);
-
-/* Synchronize fast. */
-void client_sync_full_fast(struct client *client);
-
-/* Synchronize all but expunges with client. */
-void client_sync_without_expunges(struct client *client);
-
 /* Send last mail storage error message to client. */
 void client_send_storage_error(struct client *client,
 			       struct mail_storage *storage);

Index: commands.h
===================================================================
RCS file: /home/cvs/dovecot/src/imap/commands.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- commands.h	20 Jun 2004 03:25:33 -0000	1.14
+++ commands.h	18 Aug 2004 23:53:39 -0000	1.15
@@ -3,6 +3,7 @@
 
 #include "mail-storage.h"
 #include "imap-parser.h"
+#include "imap-sync.h"
 #include "commands-util.h"
 
 struct command {

Index: imap-sync.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/imap-sync.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- imap-sync.c	18 Jul 2004 12:36:59 -0000	1.2
+++ imap-sync.c	18 Aug 2004 23:53:39 -0000	1.3
@@ -1,90 +1,193 @@
-/* Copyright (C) 2002 Timo Sirainen */
+/* Copyright (C) 2002-2004 Timo Sirainen */
 
 #include "common.h"
 #include "str.h"
 #include "imap-util.h"
 #include "mail-storage.h"
 #include "imap-sync.h"
+#include "commands.h"
 
-int imap_sync(struct client *client, struct mailbox *box,
-	      enum mailbox_sync_flags flags)
+struct cmd_sync_context {
+	const char *tagline;
+	struct imap_sync_context *sync_ctx;
+};
+
+struct imap_sync_context {
+	struct client *client;
+	struct mailbox *box;
+
+	struct mailbox_transaction_context *t;
+	struct mailbox_sync_context *sync_ctx;
+
+	struct mailbox_sync_rec sync_rec;
+	uint32_t seq;
+
+	unsigned int messages_count;
+
+	int failed;
+};
+
+struct imap_sync_context *
+imap_sync_init(struct client *client, struct mailbox *box,
+	       enum mailbox_sync_flags flags)
+{
+	struct imap_sync_context *ctx;
+
+	i_assert(client->mailbox == box);
+
+	ctx = i_new(struct imap_sync_context, 1);
+	ctx->client = client;
+	ctx->box = box;
+
+	ctx->t = mailbox_transaction_begin(box, FALSE);
+	ctx->sync_ctx = mailbox_sync_init(box, flags);
+	ctx->messages_count = client->messages_count;
+	return ctx;
+}
+
+int imap_sync_deinit(struct imap_sync_context *ctx)
 {
-        struct mailbox_transaction_context *t;
-	struct mailbox_sync_context *ctx;
-        struct mailbox_sync_rec sync_rec;
 	struct mailbox_status status;
+
+	if (mailbox_sync_deinit(ctx->sync_ctx, &status) < 0 || ctx->failed) {
+		mailbox_transaction_rollback(ctx->t);
+		i_free(ctx);
+		return -1;
+	}
+
+	mailbox_transaction_commit(ctx->t);
+
+	t_push();
+
+	ctx->client->messages_count = status.messages;
+	if (status.messages != ctx->messages_count) {
+		client_send_line(ctx->client,
+			t_strdup_printf("* %u EXISTS", status.messages));
+	}
+	if (status.recent != ctx->client->recent_count) {
+                ctx->client->recent_count = status.recent;
+		client_send_line(ctx->client,
+			t_strdup_printf("* %u RECENT", status.recent));
+	}
+
+	/*FIXME:client_save_keywords(&client->keywords, keywords, keywords_count);
+	client_send_mailbox_flags(client, mailbox, keywords, keywords_count);*/
+
+	t_pop();
+	i_free(ctx);
+	return 0;
+}
+
+int imap_sync_more(struct imap_sync_context *ctx)
+{
 	struct mail *mail;
         const struct mail_full_flags *mail_flags;
 	string_t *str;
-	uint32_t seq, messages_count;
-
-	if (client->mailbox != box) {
-		/* mailbox isn't selected - we only wish to sync the mailbox
-		   without sending anything to client */
-		ctx = mailbox_sync_init(box, flags);
-		while (mailbox_sync_next(ctx, &sync_rec) > 0)
-			;
-		return mailbox_sync_deinit(ctx, &status);
-	}
 
 	t_push();
 	str = t_str_new(256);
-	messages_count = client->messages_count;
 
-	t = mailbox_transaction_begin(box, FALSE);
-	ctx = mailbox_sync_init(box, flags);
-	while (mailbox_sync_next(ctx, &sync_rec) > 0) {
-		switch (sync_rec.type) {
+	for (;;) {
+		if (ctx->seq == 0) {
+			/* get next one */
+			if (mailbox_sync_next(ctx->sync_ctx,
+					      &ctx->sync_rec) <= 0)
+				break;
+		}
+
+		switch (ctx->sync_rec.type) {
 		case MAILBOX_SYNC_TYPE_FLAGS:
-			for (seq = sync_rec.seq1; seq <= sync_rec.seq2; seq++) {
-				mail = mailbox_fetch(t, seq, MAIL_FETCH_FLAGS);
+			if (ctx->seq == 0)
+				ctx->seq = ctx->sync_rec.seq1;
+
+			for (; ctx->seq <= ctx->sync_rec.seq2; ctx->seq++) {
+				mail = mailbox_fetch(ctx->t, ctx->seq,
+						     MAIL_FETCH_FLAGS);
 
 				mail_flags = mail->get_flags(mail);
 				if (mail_flags == NULL)
 					continue;
 
 				str_truncate(str, 0);
-				str_printfa(str, "* %u FETCH (FLAGS (", seq);
+				str_printfa(str, "* %u FETCH (FLAGS (",
+					    ctx->seq);
 				imap_write_flags(str, mail_flags);
 				str_append(str, "))");
-				client_send_line(client, str_c(str));
+				if (!client_send_line(ctx->client,
+						      str_c(str))) {
+					t_pop();
+					return 0;
+				}
 			}
 			break;
 		case MAILBOX_SYNC_TYPE_EXPUNGE:
-			messages_count -= sync_rec.seq2 - sync_rec.seq1 + 1;
-			for (seq = sync_rec.seq2; seq >= sync_rec.seq1; seq--) {
+			if (ctx->seq == 0) {
+				ctx->seq = ctx->sync_rec.seq2;
+				ctx->messages_count -=
+					ctx->sync_rec.seq2 -
+					ctx->sync_rec.seq1 + 1;
+			}
+			for (; ctx->seq >= ctx->sync_rec.seq1; ctx->seq--) {
 				str_truncate(str, 0);
-				str_printfa(str, "* %u EXPUNGE", seq);
-				client_send_line(client, str_c(str));
+				str_printfa(str, "* %u EXPUNGE", ctx->seq);
+				if (!client_send_line(ctx->client,
+						      str_c(str))) {
+					t_pop();
+					return 0;
+				}
 			}
 			break;
 		}
+		ctx->seq = 0;
 	}
+	t_pop();
+	return 1;
+}
 
-	if (mailbox_sync_deinit(ctx, &status) < 0) {
-		mailbox_transaction_rollback(t);
-		t_pop();
-		return -1;
-	}
+int imap_sync_nonselected(struct mailbox *box, enum mailbox_sync_flags flags)
+{
+	struct mailbox_sync_context *ctx;
+        struct mailbox_sync_rec sync_rec;
+	struct mailbox_status status;
 
-	mailbox_transaction_commit(t);
+	ctx = mailbox_sync_init(box, flags);
+	while (mailbox_sync_next(ctx, &sync_rec) > 0)
+		;
+	return mailbox_sync_deinit(ctx, &status);
+}
 
-	client->messages_count = status.messages;
-	if (status.messages != messages_count) {
-		str_truncate(str, 0);
-		str_printfa(str, "* %u EXISTS", status.messages);
-		client_send_line(client, str_c(str));
+static int cmd_sync_continue(struct client *client)
+{
+	struct cmd_sync_context *ctx = client->cmd_context;
+
+	if (imap_sync_more(ctx->sync_ctx) == 0)
+		return FALSE;
+
+	if (imap_sync_deinit(ctx->sync_ctx) < 0) {
+		client_send_untagged_storage_error(client,
+			mailbox_get_storage(client->mailbox));
 	}
-	if (status.recent != client->recent_count) {
-                client->recent_count = status.recent;
-		str_truncate(str, 0);
-		str_printfa(str, "* %u RECENT", status.recent);
-		client_send_line(client, str_c(str));
+
+	client_send_tagline(client, ctx->tagline);
+	return TRUE;
+}
+
+int cmd_sync(struct client *client, enum mailbox_sync_flags flags,
+	     const char *tagline)
+{
+        struct cmd_sync_context *ctx;
+
+	if (client->mailbox == NULL) {
+		client_send_tagline(client, tagline);
+		return TRUE;
 	}
 
-	/*FIXME:client_save_keywords(&client->keywords, keywords, keywords_count);
-	client_send_mailbox_flags(client, mailbox, keywords, keywords_count);*/
+	ctx = p_new(client->cmd_pool, struct cmd_sync_context, 1);
+	ctx->tagline = p_strdup(client->cmd_pool, tagline);
+	ctx->sync_ctx = imap_sync_init(client, client->mailbox, flags);
 
-	t_pop();
-	return 0;
+	client->cmd_func = cmd_sync_continue;
+	client->cmd_context = ctx;
+	client->command_pending = TRUE;
+	return cmd_sync_continue(client);
 }

Index: imap-sync.h
===================================================================
RCS file: /home/cvs/dovecot/src/imap/imap-sync.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- imap-sync.h	12 Jul 2004 11:35:50 -0000	1.1
+++ imap-sync.h	18 Aug 2004 23:53:39 -0000	1.2
@@ -1,7 +1,15 @@
 #ifndef __IMAP_SYNC_H
 #define __IMAP_SYNC_H
 
-int imap_sync(struct client *client, struct mailbox *box,
-	      enum mailbox_sync_flags flags);
+struct imap_sync_context *
+imap_sync_init(struct client *client, struct mailbox *box,
+	       enum mailbox_sync_flags flags);
+int imap_sync_deinit(struct imap_sync_context *ctx);
+int imap_sync_more(struct imap_sync_context *ctx);
+
+int imap_sync_nonselected(struct mailbox *box, enum mailbox_sync_flags flags);
+
+int cmd_sync(struct client *client, enum mailbox_sync_flags flags,
+	     const char *tagline);
 
 #endif



More information about the dovecot-cvs mailing list