mdbox-save.c revision 9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5
a82212bd36e1074408974b466798b9966bbaf49bvboxsync/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include "lib.h"
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include "array.h"
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include "fdatasync-path.h"
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include "hex-binary.h"
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include "hex-dec.h"
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include "str.h"
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include "istream.h"
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include "istream-crlf.h"
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include "ostream.h"
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include "write-full.h"
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include "index-mail.h"
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include "mail-copy.h"
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include "dbox-save.h"
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include "mdbox-storage.h"
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include "mdbox-map.h"
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include "mdbox-file.h"
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include "mdbox-sync.h"
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync#include <stdlib.h>
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncstruct dbox_save_mail {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct dbox_file_append_context *file_append;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync uint32_t seq;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync uint32_t append_offset;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync};
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncstruct mdbox_save_context {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct dbox_save_context ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_mailbox *mbox;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_sync_context *sync_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct dbox_file_append_context *cur_file_append;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct dbox_map_append_context *append_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ARRAY_TYPE(uint32_t) copy_map_uids;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct dbox_map_transaction_context *map_trans;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ARRAY_DEFINE(mails, struct dbox_save_mail);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync};
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncstruct dbox_file *
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncmdbox_save_file_get_file(struct mailbox_transaction_context *t,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync uint32_t seq, uoff_t *offset_r)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync{
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_save_context *ctx =
a82212bd36e1074408974b466798b9966bbaf49bvboxsync (struct mdbox_save_context *)t->save_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync const struct dbox_save_mail *mails, *mail;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync unsigned int count;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mails = array_get(&ctx->mails, &count);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync i_assert(count > 0);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync i_assert(seq >= mails[0].seq);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mail = &mails[seq - mails[0].seq];
a82212bd36e1074408974b466798b9966bbaf49bvboxsync i_assert(mail->seq == seq);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (dbox_file_append_flush(mail->file_append) < 0)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->ctx.failed = TRUE;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync *offset_r = mail->append_offset;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return mail->file_append->file;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync}
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncstruct mail_save_context *
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncmdbox_save_alloc(struct mailbox_transaction_context *t)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync{
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct index_transaction_context *it =
a82212bd36e1074408974b466798b9966bbaf49bvboxsync (struct index_transaction_context *)t;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)t->box;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_save_context *ctx =
a82212bd36e1074408974b466798b9966bbaf49bvboxsync (struct mdbox_save_context *)t->save_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync i_assert((t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (ctx != NULL) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* use the existing allocated structure */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->ctx.finished = FALSE;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return &ctx->ctx.ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync }
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx = i_new(struct mdbox_save_context, 1);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->ctx.ctx.transaction = t;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->ctx.trans = it->trans;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->mbox = mbox;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->append_ctx = dbox_map_append_begin(mbox->storage->map);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync i_array_init(&ctx->mails, 32);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync t->save_ctx = &ctx->ctx.ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return t->save_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync}
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncint mdbox_save_begin(struct mail_save_context *_ctx, struct istream *input)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync{
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_save_context *ctx = (struct mdbox_save_context *)_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct dbox_save_mail *save_mail;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync uoff_t mail_size, append_offset;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* get the size of the mail to be saved, if possible */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (i_stream_get_size(input, TRUE, &mail_size) <= 0)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mail_size = 0;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (dbox_map_append_next(ctx->append_ctx, mail_size,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync &ctx->cur_file_append,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync &ctx->ctx.cur_output) < 0) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->ctx.failed = TRUE;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return -1;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync }
a82212bd36e1074408974b466798b9966bbaf49bvboxsync i_assert(ctx->ctx.cur_output->offset <= (uint32_t)-1);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync append_offset = ctx->ctx.cur_output->offset;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->ctx.cur_file = ctx->cur_file_append->file;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync dbox_save_begin(&ctx->ctx, input);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync save_mail = array_append_space(&ctx->mails);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync save_mail->file_append = ctx->cur_file_append;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync save_mail->seq = ctx->ctx.seq;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync save_mail->append_offset = append_offset;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return ctx->ctx.failed ? -1 : 0;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync}
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncstatic int mdbox_save_mail_write_metadata(struct mdbox_save_context *ctx,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct dbox_save_mail *mail)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync{
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct dbox_file *file = mail->file_append->file;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct dbox_message_header dbox_msg_hdr;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync uoff_t message_size;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync uint8_t guid_128[MAIL_GUID_128_SIZE];
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync i_assert(file->msg_header_size == sizeof(dbox_msg_hdr));
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync message_size = ctx->ctx.cur_output->offset -
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mail->append_offset - mail->file_append->file->msg_header_size;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync dbox_save_write_metadata(&ctx->ctx.ctx, ctx->ctx.cur_output,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->mbox->ibox.box.name, guid_128);
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 ctx->mbox->guid_ext_id, guid_128, NULL);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync dbox_msg_header_fill(&dbox_msg_hdr, message_size);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (o_stream_pwrite(ctx->ctx.cur_output, &dbox_msg_hdr,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync sizeof(dbox_msg_hdr), mail->append_offset) < 0) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync dbox_file_set_syscall_error(file, "pwrite()");
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return -1;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync }
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return 0;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync}
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncstatic int mdbox_save_finish_write(struct mail_save_context *_ctx)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync{
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_save_context *ctx = (struct mdbox_save_context *)_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct dbox_save_mail *mails;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->ctx.finished = TRUE;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (ctx->ctx.cur_output == NULL)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return -1;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync index_mail_cache_parse_deinit(_ctx->dest_mail,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync _ctx->received_date, !ctx->ctx.failed);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mails = array_idx_modifiable(&ctx->mails, array_count(&ctx->mails) - 1);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (!ctx->ctx.failed) T_BEGIN {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (mdbox_save_mail_write_metadata(ctx, mails) < 0)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->ctx.failed = TRUE;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync else
a82212bd36e1074408974b466798b9966bbaf49bvboxsync dbox_map_append_finish(ctx->append_ctx);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync } T_END;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync i_stream_unref(&ctx->ctx.input);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (ctx->ctx.failed) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync array_delete(&ctx->mails, array_count(&ctx->mails) - 1, 1);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return -1;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync }
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return 0;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync}
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncint mdbox_save_finish(struct mail_save_context *ctx)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync{
a82212bd36e1074408974b466798b9966bbaf49bvboxsync int ret;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ret = mdbox_save_finish_write(ctx);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync index_save_context_free(ctx);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return ret;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync}
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncvoid mdbox_save_cancel(struct mail_save_context *_ctx)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync{
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->failed = TRUE;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync (void)mdbox_save_finish(_ctx);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync}
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncint mdbox_transaction_save_commit_pre(struct mail_save_context *_ctx)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync{
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_save_context *ctx = (struct mdbox_save_context *)_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mailbox_transaction_context *_t = _ctx->transaction;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_mailbox *mbox = ctx->mbox;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync const struct mail_index_header *hdr;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync uint32_t first_map_uid, last_map_uid;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync i_assert(ctx->ctx.finished);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* lock the mailbox before map to avoid deadlocks */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (mdbox_sync_begin(mbox, MDBOX_SYNC_FLAG_NO_PURGE |
a82212bd36e1074408974b466798b9966bbaf49bvboxsync MDBOX_SYNC_FLAG_FORCE |
a82212bd36e1074408974b466798b9966bbaf49bvboxsync MDBOX_SYNC_FLAG_FSYNC, &ctx->sync_ctx) < 0) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mdbox_transaction_save_rollback(_ctx);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return -1;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync }
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
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 &last_map_uid) < 0) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mdbox_transaction_save_rollback(_ctx);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return -1;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync }
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
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 &_t->changes->saved_uids);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* add map_uids for all messages saved to multi-files */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (first_map_uid != 0) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_mail_index_record rec;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync const struct dbox_save_mail *mails;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync unsigned int i, count;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync uint32_t next_map_uid = first_map_uid;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mdbox_update_header(mbox, ctx->ctx.trans, NULL);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync memset(&rec, 0, sizeof(rec));
a82212bd36e1074408974b466798b9966bbaf49bvboxsync rec.save_date = ioloop_time;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mails = array_get(&ctx->mails, &count);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync for (i = 0; i < count; i++) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync rec.map_uid = next_map_uid++;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync i_assert(i == 0 ||
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mails[i-1].append_offset != mails[i].append_offset);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mail_index_update_ext(ctx->ctx.trans, mails[i].seq,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mbox->ext_id, &rec, NULL);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync }
a82212bd36e1074408974b466798b9966bbaf49bvboxsync i_assert(next_map_uid == last_map_uid + 1);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync }
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* increase map's refcount for copied mails */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (array_is_created(&ctx->copy_map_uids)) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->map_trans =
a82212bd36e1074408974b466798b9966bbaf49bvboxsync dbox_map_transaction_begin(mbox->storage->map, FALSE);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (dbox_map_update_refcounts(ctx->map_trans,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync &ctx->copy_map_uids, 1) < 0) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mdbox_transaction_save_rollback(_ctx);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return -1;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync }
a82212bd36e1074408974b466798b9966bbaf49bvboxsync }
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (ctx->ctx.mail != NULL)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mail_free(&ctx->ctx.mail);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync _t->changes->uid_validity = hdr->uid_validity;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return 0;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync}
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncvoid mdbox_transaction_save_commit_post(struct mail_save_context *_ctx,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mail_index_transaction_commit_result *result)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync{
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_save_context *ctx = (struct mdbox_save_context *)_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync _ctx->transaction = NULL; /* transaction is already freed */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mail_index_sync_set_commit_result(ctx->sync_ctx->index_sync_ctx,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync result);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* finish writing the mailbox APPENDs */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (mdbox_sync_finish(&ctx->sync_ctx, TRUE) == 0) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (ctx->map_trans != NULL)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync (void)dbox_map_transaction_commit(ctx->map_trans);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* commit only updates the sync tail offset, everything else
a82212bd36e1074408974b466798b9966bbaf49bvboxsync was already written at this point. */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync (void)dbox_map_append_commit(ctx->append_ctx);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync }
a82212bd36e1074408974b466798b9966bbaf49bvboxsync dbox_map_append_free(&ctx->append_ctx);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (!ctx->mbox->storage->storage.storage.set->fsync_disable) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (fdatasync_path(ctx->mbox->ibox.box.path) < 0) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync i_error("fdatasync_path(%s) failed: %m",
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->mbox->ibox.box.path);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync }
a82212bd36e1074408974b466798b9966bbaf49bvboxsync }
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mdbox_transaction_save_rollback(_ctx);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync}
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncvoid mdbox_transaction_save_rollback(struct mail_save_context *_ctx)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync{
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_save_context *ctx = (struct mdbox_save_context *)_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (!ctx->ctx.finished)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mdbox_save_cancel(&ctx->ctx.ctx);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (ctx->append_ctx != NULL)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync dbox_map_append_free(&ctx->append_ctx);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (ctx->map_trans != NULL)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync dbox_map_transaction_free(&ctx->map_trans);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (array_is_created(&ctx->copy_map_uids))
a82212bd36e1074408974b466798b9966bbaf49bvboxsync array_free(&ctx->copy_map_uids);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (ctx->sync_ctx != NULL)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync (void)mdbox_sync_finish(&ctx->sync_ctx, FALSE);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (ctx->ctx.mail != NULL)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mail_free(&ctx->ctx.mail);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync array_free(&ctx->mails);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync i_free(ctx);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync}
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsyncint mdbox_copy(struct mail_save_context *_ctx, struct mail *mail)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync{
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_save_context *ctx = (struct mdbox_save_context *)_ctx;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_mailbox *src_mbox;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync struct mdbox_mail_index_record rec;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync const void *data;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync bool expunged;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->ctx.finished = TRUE;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (mail->box->storage != _ctx->transaction->box->storage)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return mail_storage_copy(_ctx, mail);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync src_mbox = (struct mdbox_mailbox *)mail->box;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync memset(&rec, 0, sizeof(rec));
a82212bd36e1074408974b466798b9966bbaf49bvboxsync rec.save_date = ioloop_time;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (mdbox_mail_lookup(src_mbox, src_mbox->ibox.view, mail->seq,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync &rec.map_uid) < 0)
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return -1;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* remember the map_uid so we can later increase its refcount */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (!array_is_created(&ctx->copy_map_uids))
a82212bd36e1074408974b466798b9966bbaf49bvboxsync i_array_init(&ctx->copy_map_uids, 32);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync array_append(&ctx->copy_map_uids, &rec.map_uid, 1);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync /* add message to mailbox index */
a82212bd36e1074408974b466798b9966bbaf49bvboxsync dbox_save_add_to_index(&ctx->ctx);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mail_index_update_ext(ctx->ctx.trans, ctx->ctx.seq,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->mbox->ext_id, &rec, NULL);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mail_index_lookup_ext(src_mbox->ibox.view, mail->seq,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync src_mbox->guid_ext_id, &data, &expunged);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync if (data != NULL) {
a82212bd36e1074408974b466798b9966bbaf49bvboxsync mail_index_update_ext(ctx->ctx.trans, ctx->ctx.seq,
a82212bd36e1074408974b466798b9966bbaf49bvboxsync ctx->mbox->guid_ext_id, data, NULL);
a82212bd36e1074408974b466798b9966bbaf49bvboxsync }
a82212bd36e1074408974b466798b9966bbaf49bvboxsync return 0;
a82212bd36e1074408974b466798b9966bbaf49bvboxsync}
a82212bd36e1074408974b466798b9966bbaf49bvboxsync