Mercurial > dovecot > original-hg > dovecot-1.2
diff src/imap/cmd-append.c @ 4939:ff2272c228cc HEAD
Dovecot is now able to execute multiple commands at the same time.
Practically this means commands: FETCH, LIST, SEARCH and syncing output for
all commands. For example it's possible that doing two FETCH commands at the
same time makes their output mixed together.
Non-blocking SEARCH is done by doing search for 20 mails at a time, and then
checking if another command is pending.
Also added X-CANCEL <tag> command to cancel running commands.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 20 Dec 2006 21:23:43 +0200 |
parents | 5b4c9b20eba0 |
children | 8fd9913adad8 |
line wrap: on
line diff
--- a/src/imap/cmd-append.c Wed Dec 20 17:40:22 2006 +0200 +++ b/src/imap/cmd-append.c Wed Dec 20 21:23:43 2006 +0200 @@ -24,14 +24,17 @@ struct imap_parser *save_parser; struct mail_save_context *save_ctx; + + unsigned int message_input:1; }; static void cmd_append_finish(struct cmd_append_context *ctx); static bool cmd_append_continue_message(struct client_command_context *cmd); -static void client_input(struct client *client) +static void client_input(struct client_command_context *cmd) { - struct client_command_context *cmd = &client->cmd; + struct cmd_append_context *ctx = cmd->context; + struct client *client = cmd->client; client->last_input = ioloop_time; @@ -41,12 +44,12 @@ cmd_append_finish(cmd->context); /* Reset command so that client_destroy() doesn't try to call cmd_append_continue_message() anymore. */ - _client_reset_command(client); + client_command_free(cmd); client_destroy(client, "Disconnected in APPEND"); return; case -2: cmd_append_finish(cmd->context); - if (client->command_pending) { + if (ctx->message_input) { /* message data, this is handled internally by mailbox_save_continue() */ break; @@ -58,22 +61,13 @@ client->input_skip_line = TRUE; client_send_command_error(cmd, "Too long argument."); - _client_reset_command(client); + cmd->param_error = TRUE; + client_command_free(cmd); return; } - if (cmd->func(cmd)) { - /* command execution was finished. Note that if cmd_sync() - didn't finish, we didn't get here but the input handler - has already been moved. So don't do anything important - here.. - - reset command once again to reset cmd_sync()'s changes. */ - _client_reset_command(client); - - if (client->input_pending) - _client_input(client); - } + if (cmd->func(cmd)) + client_command_free(cmd); } /* Returns -1 = error, 0 = need more data, 1 = successful. flags and @@ -112,25 +106,18 @@ static void cmd_append_finish(struct cmd_append_context *ctx) { - io_remove(&ctx->client->io); + imap_parser_destroy(&ctx->save_parser); - imap_parser_destroy(&ctx->save_parser); + i_assert(ctx->client->input_lock == ctx->cmd); if (ctx->input != NULL) i_stream_unref(&ctx->input); - if (ctx->save_ctx != NULL) mailbox_save_cancel(&ctx->save_ctx); - if (ctx->t != NULL) mailbox_transaction_rollback(&ctx->t); - if (ctx->box != ctx->cmd->client->mailbox && ctx->box != NULL) mailbox_close(&ctx->box); - - ctx->client->bad_counter = 0; - o_stream_set_flush_callback(ctx->client->output, - _client_output, ctx->client); } static bool cmd_append_continue_cancel(struct client_command_context *cmd) @@ -138,6 +125,11 @@ struct cmd_append_context *ctx = cmd->context; size_t size; + if (cmd->cancel) { + cmd_append_finish(ctx); + return TRUE; + } + (void)i_stream_read(ctx->input); (void)i_stream_get_data(ctx->input, &size); i_stream_skip(ctx->input, size); @@ -163,7 +155,7 @@ ctx->client->input->v_offset, ctx->msg_size); - ctx->client->command_pending = TRUE; + ctx->message_input = TRUE; ctx->cmd->func = cmd_append_continue_cancel; ctx->cmd->context = ctx; return cmd_append_continue_cancel(ctx->cmd); @@ -183,6 +175,11 @@ int ret, timezone_offset; bool nonsync; + if (cmd->cancel) { + cmd_append_finish(ctx); + return TRUE; + } + /* if error occurs, the CRLF is already read. */ client->input_skip_line = FALSE; @@ -293,7 +290,7 @@ o_stream_uncork(client->output); } - client->command_pending = TRUE; + ctx->message_input = TRUE; cmd->func = cmd_append_continue_message; return cmd_append_continue_message(cmd); } @@ -305,6 +302,11 @@ size_t size; bool failed; + if (cmd->cancel) { + cmd_append_finish(ctx); + return TRUE; + } + if (ctx->save_ctx != NULL) { if (mailbox_save_continue(ctx->save_ctx) < 0) { /* we still have to finish reading the message @@ -349,7 +351,7 @@ } /* prepare for next message */ - client->command_pending = FALSE; + ctx->message_input = FALSE; imap_parser_reset(ctx->save_parser); cmd->func = cmd_append_continue_parsing; return cmd_append_continue_parsing(cmd); @@ -395,6 +397,9 @@ if (!client_read_string_args(cmd, 1, &mailbox)) return FALSE; + /* we keep the input locked all the time */ + client->input_lock = cmd; + ctx = p_new(cmd->pool, struct cmd_append_context, 1); ctx->cmd = cmd; ctx->client = client; @@ -417,7 +422,7 @@ io_remove(&client->io); client->io = io_add(i_stream_get_fd(client->input), IO_READ, - client_input, client); + client_input, cmd); /* append is special because we're only waiting on client input, not client output, so disable the standard output handler until we're finished */