[dovecot-cvs] dovecot/src/imap cmd-append.c,1.41,1.42
cras at dovecot.org
cras at dovecot.org
Sun Aug 22 12:17:10 EEST 2004
- Previous message: [dovecot-cvs]
dovecot/src/imap cmd-idle.c, 1.13, 1.14 client.c, 1.40, 1.41
- Next message: [dovecot-cvs] dovecot/src/lib-storage Makefile.am, 1.10,
1.11 mail-copy.c, NONE, 1.1 mail-copy.h, NONE, 1.1 mail-save.c,
1.12, NONE mail-save.h, 1.3, NONE mail-storage-private.h, 1.7,
1.8 mail-storage.c, 1.28, 1.29 mail-storage.h, 1.76,
1.77 proxy-mailbox.c, 1.9, 1.10
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /home/cvs/dovecot/src/imap
In directory talvi:/tmp/cvs-serv2400/imap
Modified Files:
cmd-append.c
Log Message:
Changed mail saving API to be nonblocking.
Index: cmd-append.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-append.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -d -r1.41 -r1.42
--- cmd-append.c 18 Aug 2004 23:53:39 -0000 1.41
+++ cmd-append.c 22 Aug 2004 09:17:08 -0000 1.42
@@ -12,6 +12,56 @@
#include <sys/time.h>
+struct cmd_append_context {
+ struct client *client;
+ struct mail_storage *storage;
+ struct mailbox *box;
+ struct mailbox_transaction_context *t;
+
+ struct istream *input;
+ uoff_t msg_size;
+
+ struct imap_parser *save_parser;
+ struct mail_save_context *save_ctx;
+};
+
+static int cmd_append_continue_message(struct client *client);
+
+static void client_input(void *context)
+{
+ struct client *client = context;
+
+ client->last_input = ioloop_time;
+
+ switch (i_stream_read(client->input)) {
+ case -1:
+ /* disconnected */
+ client_destroy(client);
+ return;
+ case -2:
+ if (client->command_pending) {
+ /* message data, this is handled internally by
+ mailbox_save_continue() */
+ break;
+ }
+
+ /* parameter word is longer than max. input buffer size.
+ this is most likely an error, so skip the new data
+ until newline is found. */
+ client->input_skip_line = TRUE;
+
+ client_send_command_error(client, "Too long argument.");
+ _client_reset_command(client);
+ break;
+ }
+
+ if (client->cmd_func(client)) {
+ /* command execution was finished */
+ client->bad_counter = 0;
+ _client_reset_command(client);
+ }
+}
+
/* Returns -1 = error, 0 = need more data, 1 = successful. flags and
internal_date may be NULL as a result, but mailbox and msg_size are always
set when successful. */
@@ -44,175 +94,244 @@
return TRUE;
}
-int cmd_append(struct client *client)
+static void cmd_append_finish(struct cmd_append_context *ctx)
{
- struct mail_storage *storage;
- struct mailbox *box;
- struct mailbox_status status;
- struct mailbox_transaction_context *t;
- struct imap_parser *save_parser;
+ size_t size;
+
+ io_remove(ctx->client->io);
+ ctx->client->io = NULL;
+
+ imap_parser_destroy(ctx->save_parser);
+
+ 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->client->mailbox)
+ mailbox_close(ctx->box);
+
+ (void)i_stream_get_data(ctx->client->input, &size);
+ ctx->client->input_pending = size != 0;
+}
+
+static int cmd_append_continue_parsing(struct client *client)
+{
+ struct cmd_append_context *ctx = client->cmd_context;
struct imap_arg *args;
struct imap_arg_list *flags_list;
- struct mailbox_keywords old_flags;
struct mail_full_flags flags;
- struct istream *input;
+ const char *internal_date_str;
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;
+ int ret, timezone_offset, nonsync;
- /* <mailbox> */
- if (!client_read_string_args(client, 1, &mailbox))
- return FALSE;
+ /* if error occurs, the CRLF is already read. */
+ client->input_skip_line = FALSE;
- if (!client_verify_mailbox_name(client, mailbox, TRUE, FALSE))
+ /* [<flags>] [<internal date>] <message literal> */
+ ret = imap_parser_read_args(ctx->save_parser, 0,
+ IMAP_PARSE_FLAG_LITERAL_SIZE, &args);
+ if (ret == -1) {
+ client_send_command_error(client, NULL);
+ cmd_append_finish(ctx);
return TRUE;
+ }
+ if (ret < 0) {
+ /* need more data */
+ return FALSE;
+ }
- storage = client_find_storage(client, &mailbox);
- if (storage == NULL)
+ if (args->type == IMAP_ARG_EOL) {
+ /* last message */
+ enum mailbox_sync_flags sync_flags;
+
+ ret = mailbox_transaction_commit(ctx->t);
+ ctx->t = NULL;
+ if (ret < 0) {
+ client_send_storage_error(client, ctx->storage);
+ cmd_append_finish(ctx);
+ return TRUE;
+ }
+
+ sync_flags = ctx->box == client->mailbox ?
+ 0 : MAILBOX_SYNC_FLAG_FAST;
+
+ client->input_skip_line = TRUE;
+ cmd_append_finish(ctx);
+ return cmd_sync(client, sync_flags, "OK Append completed.");
+ }
+
+ if (!validate_args(args, &flags_list, &internal_date_str,
+ &ctx->msg_size, &nonsync)) {
+ client_send_command_error(client, "Invalid arguments.");
+ cmd_append_finish(ctx);
return TRUE;
+ }
- if (client->mailbox != NULL &&
- mailbox_name_equals(mailbox_get_name(client->mailbox), mailbox))
- box = client->mailbox;
- else {
- box = mailbox_open(storage, mailbox, MAILBOX_OPEN_FAST |
- MAILBOX_OPEN_KEEP_RECENT);
- if (box == NULL) {
- client_send_storage_error(client, storage);
+ if (flags_list != NULL) {
+ if (!client_parse_mail_flags(client, flags_list->args,
+ &client->keywords, &flags)) {
+ cmd_append_finish(ctx);
return TRUE;
}
+ } else {
+ memset(&flags, 0, sizeof(flags));
}
- if (mailbox_get_status(box, STATUS_KEYWORDS, &status) < 0) {
- client_send_storage_error(client, storage);
- mailbox_close(box);
+ if (internal_date_str == NULL) {
+ /* no time given, default to now. */
+ internal_date = (time_t)-1;
+ timezone_offset = 0;
+ } else if (!imap_parse_datetime(internal_date_str,
+ &internal_date, &timezone_offset)) {
+ client_send_tagline(client, "BAD Invalid internal date.");
+ cmd_append_finish(ctx);
return TRUE;
}
- memset(&old_flags, 0, sizeof(old_flags));
- old_flags.pool = pool_datastack_create();
- client_save_keywords(&old_flags, status.keywords,
- status.keywords_count);
- t = mailbox_transaction_begin(box, FALSE);
+ if (ctx->msg_size == 0) {
+ /* no message data, abort */
+ client_send_tagline(client, "NO Append aborted.");
+ cmd_append_finish(ctx);
+ return TRUE;
+ }
- /* if error occurs, the CRLF is already read. */
- client->input_skip_line = FALSE;
+ if (!nonsync) {
+ o_stream_send(client->output, "+ OK\r\n", 6);
+ o_stream_flush(client->output);
+ }
- count = 0;
- failed = TRUE;
- save_parser = imap_parser_create(client->input, client->output,
- imap_max_line_length);
+ /* after literal comes CRLF, if we fail make sure we eat it away */
+ client->input_skip_line = TRUE;
- for (;;) {
- /* [<flags>] [<internal date>] <message literal> */
- imap_parser_reset(save_parser);
- for (;;) {
- ret = imap_parser_read_args(save_parser, 0,
- IMAP_PARSE_FLAG_LITERAL_SIZE,
- &args);
- if (ret >= 0)
- break;
- if (ret == -1) {
- client_send_command_error(client, NULL);
- break;
- }
+ /* save the mail */
+ ctx->input = i_stream_create_limit(default_pool, client->input,
+ client->input->v_offset,
+ ctx->msg_size);
+ ctx->save_ctx = mailbox_save_init(ctx->t, &flags, internal_date,
+ timezone_offset, NULL,
+ ctx->input, TRUE);
- /* need more data */
- ret = i_stream_read(client->input);
- if (ret < 0) {
- if (ret == -2) {
- client_send_command_error(client,
- "Too long argument.");
- }
- break;
- }
- }
+ client->command_pending = TRUE;
+ client->cmd_func = cmd_append_continue_message;
+ return cmd_append_continue_message(client);
+}
- if (ret < 0)
- break;
+static int cmd_append_continue_message(struct client *client)
+{
+ struct cmd_append_context *ctx = client->cmd_context;
+ size_t size;
+ int failed;
- if (args->type == IMAP_ARG_EOL) {
- /* last one */
- if (count > 0)
- failed = FALSE;
- client->input_skip_line = TRUE;
- break;
+ if (ctx->save_ctx != NULL) {
+ if (mailbox_save_continue(ctx->save_ctx) < 0) {
+ /* we still have to finish reading the message
+ from client */
+ mailbox_save_cancel(ctx->save_ctx);
+ ctx->save_ctx = NULL;
}
+ }
- if (!validate_args(args, &flags_list, &internal_date_str,
- &msg_size, &nonsync)) {
- /* error */
- client_send_command_error(client, "Invalid arguments.");
- break;
- }
+ if (ctx->save_ctx == NULL) {
+ (void)i_stream_read(ctx->input);
+ (void)i_stream_get_data(ctx->input, &size);
+ i_stream_skip(ctx->input, size);
+ }
- if (flags_list != NULL) {
- if (!client_parse_mail_flags(client, flags_list->args,
- &old_flags, &flags))
- break;
+ if (ctx->input->v_offset == ctx->msg_size) {
+ /* finished */
+ i_stream_unref(ctx->input);
+ ctx->input = NULL;
+
+ if (ctx->save_ctx == NULL) {
+ /* failed above */
+ client_send_storage_error(client, ctx->storage);
+ failed = TRUE;
+ } else if (client->input->eof) {
+ /* client disconnected */
+ failed = TRUE;
+ mailbox_save_cancel(ctx->save_ctx);
+ } else if (mailbox_save_finish(ctx->save_ctx, NULL) < 0) {
+ failed = TRUE;
+ client_send_storage_error(client, ctx->storage);
} else {
- memset(&flags, 0, sizeof(flags));
+ failed = FALSE;
}
+ ctx->save_ctx = NULL;
- if (internal_date_str == NULL) {
- /* no time given, default to now. */
- internal_date = (time_t)-1;
- timezone_offset = 0;
- } else if (!imap_parse_datetime(internal_date_str,
- &internal_date,
- &timezone_offset)) {
- client_send_tagline(client,
- "BAD Invalid internal date.");
- break;
+ if (failed) {
+ cmd_append_finish(ctx);
+ return TRUE;
}
- if (msg_size == 0) {
- /* no message data, abort */
- client_send_tagline(client, "NO Append aborted.");
- break;
- }
+ /* prepare for next message */
+ client->command_pending = FALSE;
+ imap_parser_reset(ctx->save_parser);
+ client->cmd_func = cmd_append_continue_parsing;
+ return cmd_append_continue_parsing(client);
+ }
- if (!nonsync) {
- o_stream_send(client->output, "+ OK\r\n", 6);
- o_stream_flush(client->output);
- }
+ return FALSE;
+}
- /* save the mail */
- input = i_stream_create_limit(default_pool, client->input,
- client->input->v_offset,
- msg_size);
- if (mailbox_save(t, &flags, internal_date, timezone_offset,
- NULL, input, NULL) < 0) {
- i_stream_unref(input);
- client_send_storage_error(client, storage);
- break;
- }
- i_stream_unref(input);
+int cmd_append(struct client *client)
+{
+ struct cmd_append_context *ctx;
+ struct mail_storage *storage;
+ struct mailbox *box;
+ struct mailbox_status status;
+ const char *mailbox;
- if (client->input->closed)
- break;
+ /* <mailbox> */
+ if (!client_read_string_args(client, 1, &mailbox))
+ return FALSE;
- count++;
- }
- imap_parser_destroy(save_parser);
+ if (!client_verify_mailbox_name(client, mailbox, TRUE, FALSE))
+ return TRUE;
- if (failed)
- mailbox_transaction_rollback(t);
+ storage = client_find_storage(client, &mailbox);
+ if (storage == NULL)
+ return TRUE;
+
+ if (client->mailbox != NULL &&
+ mailbox_name_equals(mailbox_get_name(client->mailbox), mailbox))
+ box = client->mailbox;
else {
- if (mailbox_transaction_commit(t) < 0) {
- failed = TRUE;
+ box = mailbox_open(storage, mailbox, MAILBOX_OPEN_FAST |
+ MAILBOX_OPEN_KEEP_RECENT);
+ if (box == NULL) {
client_send_storage_error(client, storage);
+ return TRUE;
}
}
- if (box != client->mailbox) {
- sync_flags |= MAILBOX_SYNC_FLAG_FAST;
+ if (mailbox_get_status(box, STATUS_KEYWORDS, &status) < 0) {
+ client_send_storage_error(client, storage);
mailbox_close(box);
+ return TRUE;
}
- return failed ? TRUE :
- cmd_sync(client, sync_flags, "OK Append completed.");
+ ctx = p_new(client->cmd_pool, struct cmd_append_context, 1);
+ ctx->client = client;
+ ctx->storage = storage;
+ ctx->box = box;
+ ctx->t = mailbox_transaction_begin(box, FALSE);
+
+ client_save_keywords(&client->keywords, status.keywords,
+ status.keywords_count);
+
+ io_remove(client->io);
+ client->io = io_add(i_stream_get_fd(client->input), IO_READ,
+ client_input, client);
+
+ ctx->save_parser = imap_parser_create(client->input, client->output,
+ imap_max_line_length);
+
+ client->cmd_func = cmd_append_continue_parsing;
+ client->cmd_context = ctx;
+ return cmd_append_continue_parsing(client);
}
- Previous message: [dovecot-cvs]
dovecot/src/imap cmd-idle.c, 1.13, 1.14 client.c, 1.40, 1.41
- Next message: [dovecot-cvs] dovecot/src/lib-storage Makefile.am, 1.10,
1.11 mail-copy.c, NONE, 1.1 mail-copy.h, NONE, 1.1 mail-save.c,
1.12, NONE mail-save.h, 1.3, NONE mail-storage-private.h, 1.7,
1.8 mail-storage.c, 1.28, 1.29 mail-storage.h, 1.76,
1.77 proxy-mailbox.c, 1.9, 1.10
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the dovecot-cvs
mailing list