From: Timo Sirainen Date: Thu, 12 Dec 2019 14:25:30 +0000 (+0200) Subject: imap: copy/move: Refactor to use struct cmd_copy_context X-Git-Tag: 2.3.10~42 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f262edf0da9ed83f48bf37df1d29557d85cecc9c;p=thirdparty%2Fdovecot%2Fcore.git imap: copy/move: Refactor to use struct cmd_copy_context --- diff --git a/src/imap/cmd-copy.c b/src/imap/cmd-copy.c index 9e050629c2..2237cc603f 100644 --- a/src/imap/cmd-copy.c +++ b/src/imap/cmd-copy.c @@ -12,6 +12,16 @@ #define COPY_CHECK_INTERVAL 100 +struct cmd_copy_context { + struct client_command_context *cmd; + struct mailbox *destbox; + bool move; + + struct mailbox_transaction_context *src_trans; + struct msgset_generator_context srcset_ctx; + unsigned int copy_count; +}; + static void client_send_sendalive_if_needed(struct client *client) { time_t now, last_io; @@ -30,32 +40,31 @@ static void client_send_sendalive_if_needed(struct client *client) } } -static int fetch_and_copy(struct client_command_context *cmd, bool move, - struct mailbox_transaction_context *t, - struct mailbox_transaction_context **src_trans_r, +static int fetch_and_copy(struct cmd_copy_context *copy_ctx, struct mail_search_args *search_args, - const char **src_uidset_r, - unsigned int *copy_count_r) + struct mail_transaction_commit_changes *changes_r) { - struct client *client = cmd->client; + struct client *client = copy_ctx->cmd->client; + struct mailbox_transaction_context *t; struct mail_search_context *search_ctx; - struct mailbox_transaction_context *src_trans; struct mail_save_context *save_ctx; struct mail *mail; - unsigned int copy_count = 0; - struct msgset_generator_context srcset_ctx; - string_t *src_uidset; + const char *cmd_reason; int ret; i_assert(o_stream_is_corked(client->output) || client->output->stream_errno != 0); - src_uidset = t_str_new(256); - msgset_generator_init(&srcset_ctx, src_uidset); + cmd_reason = imap_client_command_get_reason(copy_ctx->cmd); + t = mailbox_transaction_begin(copy_ctx->destbox, + MAILBOX_TRANSACTION_FLAG_EXTERNAL | + MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS, + cmd_reason); - src_trans = mailbox_transaction_begin(client->mailbox, 0, - imap_client_command_get_reason(cmd)); - search_ctx = mailbox_search_init(src_trans, search_args, NULL, 0, NULL); + copy_ctx->src_trans = + mailbox_transaction_begin(client->mailbox, 0, cmd_reason); + search_ctx = mailbox_search_init(copy_ctx->src_trans, search_args, + NULL, 0, NULL); ret = 1; while (mailbox_search_next(search_ctx, &mail) && ret > 0) { @@ -64,13 +73,13 @@ static int fetch_and_copy(struct client_command_context *cmd, bool move, break; } - if ((++copy_count % COPY_CHECK_INTERVAL) == 0) + if ((++copy_ctx->copy_count % COPY_CHECK_INTERVAL) == 0) client_send_sendalive_if_needed(client); save_ctx = mailbox_save_alloc(t); mailbox_save_copy_flags(save_ctx, mail); - if (move) { + if (copy_ctx->move) { if (mailbox_move(&save_ctx, mail) < 0) ret = -1; } else { @@ -80,16 +89,25 @@ static int fetch_and_copy(struct client_command_context *cmd, bool move, if (ret < 0 && mail->expunged) ret = 0; - msgset_generator_next(&srcset_ctx, mail->uid); + msgset_generator_next(©_ctx->srcset_ctx, mail->uid); } - msgset_generator_finish(&srcset_ctx); + + if (ret <= 0) + mailbox_transaction_rollback(&t); + else if (mailbox_transaction_commit_get_changes(&t, changes_r) < 0) { + if (mailbox_get_last_mail_error(copy_ctx->destbox) == MAIL_ERROR_EXPUNGED) { + /* storage backend didn't notice the expunge until + at commit time. */ + ret = 0; + } else { + ret = -1; + } + } + + msgset_generator_finish(©_ctx->srcset_ctx); if (mailbox_search_deinit(&search_ctx) < 0) ret = -1; - - *src_trans_r = src_trans; - *src_uidset_r = str_c(src_uidset); - *copy_count_r = copy_count; return ret; } @@ -111,14 +129,13 @@ static bool cmd_copy_full(struct client_command_context *cmd, bool move) struct client *client = cmd->client; struct mail_storage *dest_storage; struct mailbox *destbox; - struct mailbox_transaction_context *t, *src_trans; struct mail_search_args *search_args; - const char *messageset, *mailbox, *src_uidset; + const char *messageset, *mailbox; enum mailbox_sync_flags sync_flags = 0; enum imap_sync_flags imap_flags = 0; struct mail_transaction_commit_changes changes; - unsigned int copy_count; - string_t *msg; + struct cmd_copy_context copy_ctx; + string_t *msg, *src_uidset; int ret; /* */ @@ -137,26 +154,19 @@ static bool cmd_copy_full(struct client_command_context *cmd, bool move) return TRUE; } - t = mailbox_transaction_begin(destbox, - MAILBOX_TRANSACTION_FLAG_EXTERNAL | - MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS, - imap_client_command_get_reason(cmd)); - ret = fetch_and_copy(cmd, move, t, &src_trans, search_args, - &src_uidset, ©_count); + i_zero(©_ctx); + copy_ctx.cmd = cmd; + copy_ctx.destbox = destbox; + copy_ctx.move = move; + src_uidset = t_str_new(256); + msgset_generator_init(©_ctx.srcset_ctx, src_uidset); + ret = fetch_and_copy(©_ctx, search_args, &changes); mail_search_args_unref(&search_args); msg = t_str_new(256); if (ret <= 0) - mailbox_transaction_rollback(&t); - else if (mailbox_transaction_commit_get_changes(&t, &changes) < 0) { - if (mailbox_get_last_mail_error(destbox) == MAIL_ERROR_EXPUNGED) { - /* storage backend didn't notice the expunge until - at commit time. */ - ret = 0; - } else { - ret = -1; - } - } else if (copy_count == 0) { + ; + else if (copy_ctx.copy_count == 0) { str_append(msg, "OK No messages found."); pool_unref(&changes.pool); } else if (seq_range_count(&changes.saved_uids) == 0 || @@ -167,11 +177,11 @@ static bool cmd_copy_full(struct client_command_context *cmd, bool move) "OK Copy completed."); pool_unref(&changes.pool); } else if (move) { - i_assert(copy_count == seq_range_count(&changes.saved_uids)); - copy_update_trashed(client, destbox, copy_count); + i_assert(copy_ctx.copy_count == seq_range_count(&changes.saved_uids)); + copy_update_trashed(client, destbox, copy_ctx.copy_count); str_printfa(msg, "* OK [COPYUID %u %s ", - changes.uid_validity, src_uidset); + changes.uid_validity, str_c(src_uidset)); imap_write_seq_range(msg, &changes.saved_uids); str_append(msg, "] Moved UIDs."); client_send_line(client, str_c(msg)); @@ -180,11 +190,11 @@ static bool cmd_copy_full(struct client_command_context *cmd, bool move) str_append(msg, "OK Move completed."); pool_unref(&changes.pool); } else { - i_assert(copy_count == seq_range_count(&changes.saved_uids)); - copy_update_trashed(client, destbox, copy_count); + i_assert(copy_ctx.copy_count == seq_range_count(&changes.saved_uids)); + copy_update_trashed(client, destbox, copy_ctx.copy_count); str_printfa(msg, "OK [COPYUID %u %s ", changes.uid_validity, - src_uidset); + str_c(src_uidset)); imap_write_seq_range(msg, &changes.saved_uids); str_append(msg, "] Copy completed."); pool_unref(&changes.pool); @@ -192,9 +202,9 @@ static bool cmd_copy_full(struct client_command_context *cmd, bool move) if (ret <= 0 && move) { /* move failed, don't expunge anything */ - mailbox_transaction_rollback(&src_trans); + mailbox_transaction_rollback(©_ctx.src_trans); } else { - if (mailbox_transaction_commit(&src_trans) < 0) + if (mailbox_transaction_commit(©_ctx.src_trans) < 0) ret = -1; }