mdbox-save.c revision d4002fe1f64d25a792f76fb102ef7dc519cd4e24
/* Copyright (c) 2007-2017 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "fdatasync-path.h"
#include "hex-binary.h"
#include "hex-dec.h"
#include "str.h"
#include "istream.h"
#include "istream-crlf.h"
#include "ostream.h"
#include "write-full.h"
#include "index-mail.h"
#include "index-pop3-uidl.h"
#include "mail-copy.h"
#include "dbox-save.h"
#include "mdbox-storage.h"
#include "mdbox-map.h"
#include "mdbox-file.h"
#include "mdbox-sync.h"
struct dbox_save_mail {
struct dbox_file_append_context *file_append;
bool written_to_disk;
};
struct mdbox_save_context {
struct dbox_save_context ctx;
struct mdbox_mailbox *mbox;
struct mdbox_sync_context *sync_ctx;
struct dbox_file_append_context *cur_file_append;
struct mdbox_map_append_context *append_ctx;
struct mdbox_map_atomic_context *atomic;
struct mdbox_map_transaction_context *map_trans;
};
static struct dbox_file *
{
const struct mdbox_mail_index_record *rec;
const void *data;
i_unreached();
}
struct dbox_file *
{
unsigned int count;
/* copied mail */
}
/* saved mail */
}
struct mail_save_context *
mdbox_save_alloc(struct mailbox_transaction_context *t)
{
/* use the existing allocated structure */
}
return t->save_ctx;
}
{
struct dbox_save_mail *save_mail;
/* get the size of the mail to be saved, if possible */
/* we couldn't find out the exact size. fallback to non-exact,
maybe it'll give something useful. the mail size is used
only to figure out if it's causing mdbox file to grow
too large. */
mail_size = 0;
}
return -1;
}
}
struct dbox_save_mail *mail)
{
struct dbox_message_header dbox_msg_hdr;
/* save the 128bit GUID to index so if the map index gets corrupted
we can still find the message */
return -1;
}
return 0;
}
{
struct dbox_save_mail *mail;
return -1;
else
} T_END;
/* if we try to read the saved mail before unlocking file,
make sure the input stream doesn't have stale data */
}
return -1;
}
return 0;
}
{
int ret;
return ret;
}
{
(void)mdbox_save_finish(_ctx);
}
static void
{
const struct mdbox_mail_index_record *old_rec;
struct mdbox_mail_index_record rec;
const struct dbox_save_mail *mails;
unsigned int i, count;
const void *data;
for (i = 0; i < count; i++) {
/* message was copied. keep the existing map uid */
continue;
}
}
}
{
const struct mail_index_header *hdr;
return -1;
}
/* make sure the map gets locked */
return -1;
}
/* lock the mailbox after map to avoid deadlocks. if we've noticed
any corruption, deal with it later, otherwise we won't have
up-to-date atomic->sync_view */
return -1;
}
/* assign map UIDs for newly saved messages after we've successfully
acquired all the locks. the transaction is now very unlikely to
fail. the UIDs are written to the transaction log immediately within
this function, but the map is left locked. */
&last_map_uid) < 0) {
return -1;
}
/* update dbox header flags */
/* assign UIDs for new messages */
const struct dbox_save_mail *mails;
struct seq_range_iter iter;
unsigned int highest_pop3_uidl_idx;
i_unreached();
}
/* save map UIDs to mailbox index */
if (first_map_uid != 0)
/* increase map's refcount for copied mails */
return -1;
}
} else {
}
return 0;
}
{
result);
/* finish writing the mailbox APPENDs */
/* commit refcount increases for copied mails */
}
/* flush file append writes */
}
/* update the sync tail offset, everything else
was already written at this point. */
if (fdatasync_path(box_path) < 0) {
"fdatasync_path(%s) failed: %m", box_path);
}
}
}
{
}
{
struct dbox_save_mail *save_mail;
struct mdbox_mailbox *src_mbox;
struct mdbox_mail_index_record rec;
const void *guid_data;
return -1;
}
/* missing GUID, something's broken. don't copy using
refcounting. */
/* GUID change requested. we can't do it with refcount
copying */
}
/* remember the map_uid so we can later increase its refcount */
/* add message to mailbox index */
return 0;
}