[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