mdbox-save.c revision 767ff4367960efd5fa868f3b56f850fd4c205c8b
5e0ce63bb65db34d7f48b34bbb5545fa791781c4Timo Sirainen/* Copyright (c) 2007-2010 Dovecot authors, see the included COPYING file */
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct dbox_file_append_context *cur_file_append;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct dbox_map_transaction_context *map_trans;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic struct dbox_file *
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenmdbox_copy_file_get_file(struct mailbox_transaction_context *t,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_index_lookup_ext(t->view, seq, ctx->mbox->ext_id,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (dbox_map_lookup(ctx->mbox->storage->map, rec->map_uid,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return mdbox_file_init(ctx->mbox->storage, file_id);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenmdbox_save_file_get_file(struct mailbox_transaction_context *t,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen unsigned int count;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* copied mail */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return mdbox_copy_file_get_file(t, seq, offset_r);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* saved mail */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (dbox_file_append_flush(mail->file_append) < 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenmdbox_save_alloc(struct mailbox_transaction_context *t)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)t->box;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_assert((t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* use the existing allocated structure */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ctx->append_ctx = dbox_map_append_begin(mbox->storage->map, 0);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenint mdbox_save_begin(struct mail_save_context *_ctx, struct istream *input)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mdbox_save_context *ctx = (struct mdbox_save_context *)_ctx;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* get the size of the mail to be saved, if possible */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (i_stream_get_size(input, TRUE, &mail_size) <= 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* we couldn't find out the exact size. fallback to non-exact,
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen maybe it'll give something useful. the mail size is used
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen only to figure out if it's causing mdbox file to grow
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen too large. */
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen mail_size = st->st_size > 0 ? st->st_size : 0;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen if (dbox_map_append_next(ctx->append_ctx, mail_size,
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen i_assert(ctx->ctx.dbox_output->offset <= (uint32_t)-1);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen ctx->ctx.cur_file = ctx->cur_file_append->file;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen save_mail->file_append = ctx->cur_file_append;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic int mdbox_save_mail_write_metadata(struct mdbox_save_context *ctx,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct dbox_file *file = mail->file_append->file;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_assert(file->msg_header_size == sizeof(dbox_msg_hdr));
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail->append_offset - mail->file_append->file->msg_header_size;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen dbox_save_write_metadata(&ctx->ctx.ctx, ctx->ctx.dbox_output,
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen /* save the 128bit GUID to index so if the map index gets corrupted
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen we can still find the message */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_index_update_ext(ctx->ctx.trans, ctx->ctx.seq,
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen dbox_msg_header_fill(&dbox_msg_hdr, message_size);
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen if (o_stream_pwrite(ctx->ctx.dbox_output, &dbox_msg_hdr,
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen sizeof(dbox_msg_hdr), mail->append_offset) < 0) {
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen dbox_file_set_syscall_error(file, "pwrite()");
e743c8779135b67056f8211cad867f79d3d4065eTimo Sirainenstatic int mdbox_save_finish_write(struct mail_save_context *_ctx)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mdbox_save_context *ctx = (struct mdbox_save_context *)_ctx;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen index_mail_cache_parse_deinit(_ctx->dest_mail,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mails = array_idx_modifiable(&ctx->mails, array_count(&ctx->mails) - 1);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (mdbox_save_mail_write_metadata(ctx, mails) < 0)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen array_delete(&ctx->mails, array_count(&ctx->mails) - 1, 1);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenint mdbox_save_finish(struct mail_save_context *ctx)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenvoid mdbox_save_cancel(struct mail_save_context *_ctx)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenint mdbox_transaction_save_commit_pre(struct mail_save_context *_ctx)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct mdbox_save_context *ctx = (struct mdbox_save_context *)_ctx;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct mailbox_transaction_context *_t = _ctx->transaction;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* lock the mailbox before map to avoid deadlocks */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (mdbox_sync_begin(mbox, MDBOX_SYNC_FLAG_NO_PURGE |
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* get map UIDs for messages saved to multi-files. they're written
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen to transaction log immediately within this function, but the map
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen is left locked. */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (dbox_map_append_assign_map_uids(ctx->append_ctx, &first_map_uid,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* assign UIDs for new messages */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen hdr = mail_index_get_header(ctx->sync_ctx->sync_view);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen mail_index_append_finish_uids(ctx->ctx.trans, hdr->next_uid,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* add map_uids for all messages saved to multi-files */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen unsigned int i, count;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen mdbox_update_header(mbox, ctx->ctx.trans, NULL);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen for (i = 0; i < count; i++) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen mail_index_update_ext(ctx->ctx.trans, mails[i].seq,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* increase map's refcount for copied mails */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen dbox_map_transaction_begin(mbox->storage->map, FALSE);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen _t->changes->uid_validity = hdr->uid_validity;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenvoid mdbox_transaction_save_commit_post(struct mail_save_context *_ctx,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct mail_index_transaction_commit_result *result)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct mdbox_save_context *ctx = (struct mdbox_save_context *)_ctx;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen _ctx->transaction = NULL; /* transaction is already freed */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen mail_index_sync_set_commit_result(ctx->sync_ctx->index_sync_ctx,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* finish writing the mailbox APPENDs */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (mdbox_sync_finish(&ctx->sync_ctx, TRUE) == 0) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen (void)dbox_map_transaction_commit(ctx->map_trans);
const void *data;
bool expunged;