mdbox-save.c revision 9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5
a82212bd36e1074408974b466798b9966bbaf49bvboxsync/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncmdbox_save_file_get_file(struct mailbox_transaction_context *t,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync unsigned int count;
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncmdbox_save_alloc(struct mailbox_transaction_context *t)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)t->box;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync i_assert((t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* use the existing allocated structure */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->append_ctx = dbox_map_append_begin(mbox->storage->map);
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncint mdbox_save_begin(struct mail_save_context *_ctx, struct istream *input)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_save_context *ctx = (struct mdbox_save_context *)_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* get the size of the mail to be saved, if possible */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (i_stream_get_size(input, TRUE, &mail_size) <= 0)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (dbox_map_append_next(ctx->append_ctx, mail_size,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync i_assert(ctx->ctx.cur_output->offset <= (uint32_t)-1);
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncstatic int mdbox_save_mail_write_metadata(struct mdbox_save_context *ctx,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync i_assert(file->msg_header_size == sizeof(dbox_msg_hdr));
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mail->append_offset - mail->file_append->file->msg_header_size;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync dbox_save_write_metadata(&ctx->ctx.ctx, ctx->ctx.cur_output,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* save the 128bit GUID to index so if the map index gets corrupted
a82212bd36e1074408974b466798b9966bbaf49bvboxsync we can still find the message */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mail_index_update_ext(ctx->ctx.trans, ctx->ctx.seq,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (o_stream_pwrite(ctx->ctx.cur_output, &dbox_msg_hdr,
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncstatic int mdbox_save_finish_write(struct mail_save_context *_ctx)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_save_context *ctx = (struct mdbox_save_context *)_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mails = array_idx_modifiable(&ctx->mails, array_count(&ctx->mails) - 1);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (mdbox_save_mail_write_metadata(ctx, mails) < 0)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync array_delete(&ctx->mails, array_count(&ctx->mails) - 1, 1);
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncint mdbox_save_finish(struct mail_save_context *ctx)
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncvoid mdbox_save_cancel(struct mail_save_context *_ctx)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncint mdbox_transaction_save_commit_pre(struct mail_save_context *_ctx)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_save_context *ctx = (struct mdbox_save_context *)_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mailbox_transaction_context *_t = _ctx->transaction;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* lock the mailbox before map to avoid deadlocks */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (mdbox_sync_begin(mbox, MDBOX_SYNC_FLAG_NO_PURGE |
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* get map UIDs for messages saved to multi-files. they're written
a82212bd36e1074408974b466798b9966bbaf49bvboxsync to transaction log immediately within this function, but the map
a82212bd36e1074408974b466798b9966bbaf49bvboxsync is left locked. */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (dbox_map_append_assign_map_uids(ctx->append_ctx, &first_map_uid,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* assign UIDs for new messages */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync hdr = mail_index_get_header(ctx->sync_ctx->sync_view);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mail_index_append_finish_uids(ctx->ctx.trans, hdr->next_uid,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* add map_uids for all messages saved to multi-files */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync unsigned int i, count;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync for (i = 0; i < count; i++) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mails[i-1].append_offset != mails[i].append_offset);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mail_index_update_ext(ctx->ctx.trans, mails[i].seq,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* increase map's refcount for copied mails */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync dbox_map_transaction_begin(mbox->storage->map, FALSE);
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncvoid mdbox_transaction_save_commit_post(struct mail_save_context *_ctx,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mail_index_transaction_commit_result *result)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_save_context *ctx = (struct mdbox_save_context *)_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync _ctx->transaction = NULL; /* transaction is already freed */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mail_index_sync_set_commit_result(ctx->sync_ctx->index_sync_ctx,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* finish writing the mailbox APPENDs */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (mdbox_sync_finish(&ctx->sync_ctx, TRUE) == 0) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* commit only updates the sync tail offset, everything else
a82212bd36e1074408974b466798b9966bbaf49bvboxsync was already written at this point. */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (!ctx->mbox->storage->storage.storage.set->fsync_disable) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (fdatasync_path(ctx->mbox->ibox.box.path) < 0) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncvoid mdbox_transaction_save_rollback(struct mail_save_context *_ctx)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_save_context *ctx = (struct mdbox_save_context *)_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncint mdbox_copy(struct mail_save_context *_ctx, struct mail *mail)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_save_context *ctx = (struct mdbox_save_context *)_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync const void *data;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (mail->box->storage != _ctx->transaction->box->storage)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (mdbox_mail_lookup(src_mbox, src_mbox->ibox.view, mail->seq,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* remember the map_uid so we can later increase its refcount */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync array_append(&ctx->copy_map_uids, &rec.map_uid, 1);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* add message to mailbox index */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mail_index_update_ext(ctx->ctx.trans, ctx->ctx.seq,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mail_index_lookup_ext(src_mbox->ibox.view, mail->seq,