Mercurial > dovecot > original-hg > dovecot-1.2
changeset 2427:e1616067df5c HEAD
Syncing works now too without buffering everything. Also fixed handling
input while command was being processed.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 19 Aug 2004 02:53:39 +0300 |
parents | d47a550fc23b |
children | abef2ac8843a |
files | src/imap/client.c src/imap/client.h src/imap/cmd-append.c src/imap/cmd-check.c src/imap/cmd-copy.c src/imap/cmd-expunge.c src/imap/cmd-fetch.c src/imap/cmd-idle.c src/imap/cmd-noop.c src/imap/cmd-search.c src/imap/cmd-select.c src/imap/cmd-sort.c src/imap/cmd-status.c src/imap/cmd-store.c src/imap/cmd-thread.c src/imap/commands-util.c src/imap/commands-util.h src/imap/commands.h src/imap/imap-sync.c src/imap/imap-sync.h |
diffstat | 20 files changed, 321 insertions(+), 205 deletions(-) [+] |
line wrap: on
line diff
--- a/src/imap/client.c Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/client.c Thu Aug 19 02:53:39 2004 +0300 @@ -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); }
--- a/src/imap/client.h Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/client.h Thu Aug 19 02:53:39 2004 +0300 @@ -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
--- a/src/imap/cmd-append.c Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/cmd-append.c Thu Aug 19 02:53:39 2004 +0300 @@ -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."); }
--- a/src/imap/cmd-check.c Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/cmd-check.c Thu Aug 19 02:53:39 2004 +0300 @@ -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."); }
--- a/src/imap/cmd-copy.c Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/cmd-copy.c Thu Aug 19 02:53:39 2004 +0300 @@ -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; }
--- a/src/imap/cmd-expunge.c Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/cmd-expunge.c Thu Aug 19 02:53:39 2004 +0300 @@ -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; }
--- a/src/imap/cmd-fetch.c Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/cmd-fetch.c Thu Aug 19 02:53:39 2004 +0300 @@ -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); }
--- a/src/imap/cmd-idle.c Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/cmd-idle.c Thu Aug 19 02:53:39 2004 +0300 @@ -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 (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); + } +} - if (imap_sync(client, box, 0) < 0) { +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; }
--- a/src/imap/cmd-noop.c Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/cmd-noop.c Thu Aug 19 02:53:39 2004 +0300 @@ -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."); }
--- a/src/imap/cmd-search.c Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/cmd-search.c Thu Aug 19 02:53:39 2004 +0300 @@ -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));
--- a/src/imap/cmd-select.c Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/cmd-select.c Thu Aug 19 02:53:39 2004 +0300 @@ -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;
--- a/src/imap/cmd-sort.c Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/cmd-sort.c Thu Aug 19 02:53:39 2004 +0300 @@ -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));
--- a/src/imap/cmd-status.c Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/cmd-status.c Thu Aug 19 02:53:39 2004 +0300 @@ -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;
--- a/src/imap/cmd-store.c Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/cmd-store.c Thu Aug 19 02:53:39 2004 +0300 @@ -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; }
--- a/src/imap/cmd-thread.c Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/cmd-thread.c Thu Aug 19 02:53:39 2004 +0300 @@ -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));
--- a/src/imap/commands-util.c Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/commands-util.c Thu Aug 19 02:53:39 2004 +0300 @@ -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) {
--- a/src/imap/commands-util.h Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/commands-util.h Thu Aug 19 02:53:39 2004 +0300 @@ -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);
--- a/src/imap/commands.h Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/commands.h Thu Aug 19 02:53:39 2004 +0300 @@ -3,6 +3,7 @@ #include "mail-storage.h" #include "imap-parser.h" +#include "imap-sync.h" #include "commands-util.h" struct command {
--- a/src/imap/imap-sync.c Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/imap-sync.c Thu Aug 19 02:53:39 2004 +0300 @@ -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 mailbox_transaction_context *t; - struct mailbox_sync_context *ctx; - struct mailbox_sync_rec sync_rec; + 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_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; + + for (;;) { + if (ctx->seq == 0) { + /* get next one */ + if (mailbox_sync_next(ctx->sync_ctx, + &ctx->sync_rec) <= 0) + break; + } - t = mailbox_transaction_begin(box, FALSE); - ctx = mailbox_sync_init(box, flags); - while (mailbox_sync_next(ctx, &sync_rec) > 0) { - switch (sync_rec.type) { + 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; +} + +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; - if (mailbox_sync_deinit(ctx, &status) < 0) { - mailbox_transaction_rollback(t); - t_pop(); - return -1; + ctx = mailbox_sync_init(box, flags); + while (mailbox_sync_next(ctx, &sync_rec) > 0) + ; + return mailbox_sync_deinit(ctx, &status); +} + +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)); } - mailbox_transaction_commit(t); + client_send_tagline(client, ctx->tagline); + return TRUE; +} - 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)); - } - 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)); +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); }
--- a/src/imap/imap-sync.h Thu Aug 19 02:42:31 2004 +0300 +++ b/src/imap/imap-sync.h Thu Aug 19 02:53:39 2004 +0300 @@ -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