mbox-sync.c revision e06c0b65c16ccce69bbee009ead14d7d3d17a256
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2004 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/*
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen Modifying mbox can be slow, so we try to do it all at once minimizing the
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen required disk I/O. We may need to:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Update message flags in Status, X-Status and X-Keywords headers
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Write missing X-UID and X-IMAPbase headers
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Write missing or broken Content-Length header if there's space
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Expunge specified messages
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen Here's how we do it:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Start reading the mails mail headers from the beginning
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - X-Keywords and X-UID headers may contain extra spaces at the end of them,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen remember how much extra each message has and offset to beginning of the
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen spaces
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - If message flags are dirty and there's enough space to write them, do it
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - If we didn't have enough space, remember how much was missing and keep
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen the total amount of them
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - When we encounter expunged message, check if the amount of empty space in
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen previous messages plus size of expunged message is enough to cover the
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen missing space. If yes,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - execute the rewrite plan
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - forget all the messages before the expunged message. only remember
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen how much data we still have to move to cover the expunged message
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - If we encounter end of file, grow the file and execute the rewrite plan
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen Rewrite plan goes:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Start from the first message that needs more space
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - If there's expunged messages before us, we have to write over them.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Move all messages after it backwards to fill it
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Each moved message's X-Keywords header should have n bytes extra
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen space, unless there's not enough space to do it.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - If there's no expunged messages, we can move data either forward or
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen backward to get it. Calculate which requires less moving. Forward
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen counting may encounter more messages which require extra space, count
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen that too.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - If we decide to move forwards and we had to go through dirty
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen messages, do the moving from last to first dirty message
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - If we encounter end of file, grow the file enough to get the required
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen amount of space plus enough space to fill X-Keywords headers full of
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen spaces.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen*/
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "ioloop.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "buffer.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "file-set-size.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "write-full.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream-raw-mbox.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mbox-storage.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mbox-file.h"
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen#include "mbox-lock.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mbox-sync-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen#include <stddef.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <sys/stat.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int mbox_sync_grow_file(struct mbox_sync_context *sync_ctx,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen struct mbox_sync_mail_context *mail_ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uoff_t grow_size)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen uoff_t src_offset, file_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(grow_size > 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen /* put the extra space between last message's header and body */
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen file_size = i_stream_get_size(sync_ctx->file_input) + grow_size;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (file_set_size(sync_ctx->fd, file_size) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen src_offset = mail_ctx->body_offset;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mail_ctx->body_offset += grow_size;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (mbox_move(sync_ctx, mail_ctx->body_offset, src_offset,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen file_size - mail_ctx->body_offset) < 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen istream_raw_mbox_flush(sync_ctx->input);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainenstatic void mbox_sync_buffer_delete_old(buffer_t *syncs_buf, uint32_t uid)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen{
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen struct mail_index_sync_rec *sync;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen size_t size, src, dest;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen sync = buffer_get_modifyable_data(syncs_buf, &size);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen size /= sizeof(*sync);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen for (src = dest = 0; src < size; src++) {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen if (sync[src].uid2 >= uid) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (src != dest)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen sync[dest] = sync[src];
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen dest++;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen buffer_set_used_size(syncs_buf, dest * sizeof(*sync));
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen}
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainenstatic void
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainenmbox_sync_next_mail(struct mbox_sync_context *sync_ctx,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen struct mbox_sync_mail_context *mail_ctx, uint32_t seq)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen{
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen uoff_t from_offset;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen memset(mail_ctx, 0, sizeof(*mail_ctx));
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->sync_ctx = sync_ctx;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->seq = seq;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->header = sync_ctx->header;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen from_offset = istream_raw_mbox_get_start_offset(sync_ctx->input);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->mail.offset =
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen istream_raw_mbox_get_header_offset(sync_ctx->input);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen mbox_sync_parse_next_mail(sync_ctx->input, mail_ctx, FALSE);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen i_assert(sync_ctx->input->v_offset != from_offset);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->mail.body_size =
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen istream_raw_mbox_get_body_size(sync_ctx->input,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->content_length);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen /* save the offset permanently with recent flag state */
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen from_offset <<= 1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if ((mail_ctx->mail.flags & MBOX_NONRECENT) == 0) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen /* need to add 'O' flag to Status-header */
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mail_ctx->need_rewrite = TRUE;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen from_offset |= 1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen buffer_append(sync_ctx->ibox->mbox_data_buf, &from_offset,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen sizeof(from_offset));
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen}
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainenstatic void mbox_sync_apply_index_syncs(buffer_t *syncs_buf, uint8_t *flags,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen keywords_mask_t keywords)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen{
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen const struct mail_index_sync_rec *sync;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen size_t size, i;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen sync = buffer_get_data(syncs_buf, &size);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen size /= sizeof(*sync);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen for (i = 0; i < size; i++)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mail_index_sync_flags_apply(&sync[i], flags, keywords);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen}
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainenstatic int mbox_sync_do(struct index_mailbox *ibox,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen struct mail_index_sync_ctx *index_sync_ctx,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen struct mail_index_view *sync_view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mbox_sync_context sync_ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mbox_sync_mail_context mail_ctx;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen struct mail_index_sync_rec sync_rec;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen struct mail_index_transaction *t;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen const struct mail_index_header *hdr;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen const struct mail_index_record *rec;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct istream *input;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen uint32_t seq, need_space_seq, idx_seq, messages_count;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen uint8_t new_flags;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen off_t space_diff;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen uoff_t offset, extra_space;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen buffer_t *mails, *syncs;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen size_t size;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct stat st;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen int ret = 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen t = mail_index_transaction_begin(sync_view, FALSE);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (ibox->mbox_data_buf == NULL) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ibox->mbox_data_buf =
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen buffer_create_dynamic(default_pool, 512, (size_t)-1);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen } else {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen buffer_set_used_size(ibox->mbox_data_buf, 0);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memset(&sync_ctx, 0, sizeof(sync_ctx));
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen sync_ctx.ibox = ibox;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen sync_ctx.file_input = ibox->mbox_file_stream;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen sync_ctx.input = ibox->mbox_stream;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen sync_ctx.fd = ibox->mbox_fd;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen sync_ctx.header = str_new(default_pool, 4096);
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen sync_ctx.next_uid = 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen input = sync_ctx.input;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen istream_raw_mbox_seek(input, 0);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen mails = buffer_create_dynamic(default_pool, 4096, (size_t)-1);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen syncs = buffer_create_dynamic(default_pool, 256, (size_t)-1);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen memset(&sync_rec, 0, sizeof(sync_rec));
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen messages_count = mail_index_view_get_message_count(sync_view);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen space_diff = 0; need_space_seq = 0; idx_seq = 0; rec = NULL;
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen for (seq = 0;;) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen /* set input->eof */
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen (void)istream_raw_mbox_get_header_offset(input);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (input->eof)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen break;
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen seq++;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainen mbox_sync_next_mail(&sync_ctx, &mail_ctx, seq);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen /* get all sync records related to this message */
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = 1;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen mbox_sync_buffer_delete_old(syncs, mail_ctx.mail.uid);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen while (mail_ctx.mail.uid >= sync_rec.uid1 && ret > 0) {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen if (sync_rec.uid1 != 0) {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen i_assert(mail_ctx.mail.uid <= sync_rec.uid2);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen buffer_append(syncs, &sync_rec,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen sizeof(sync_rec));
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen ret = mail_index_sync_next(index_sync_ctx, &sync_rec);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (ret == 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen memset(&sync_rec, 0, sizeof(sync_rec));
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (ret < 0)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen break;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (seq == 1 && sync_ctx.base_uid_validity == 0) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (mail_index_get_header(sync_view, &hdr) < 0) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen break;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen sync_ctx.base_uid_validity = hdr->uid_validity;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if ((mail_ctx.need_rewrite ||
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen buffer_get_used_size(syncs) != 0) && !ibox->readonly) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (ibox->mbox_lock_type == F_RDLCK) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -2;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen break;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mbox_sync_update_header(&mail_ctx, syncs);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if ((ret = mbox_sync_try_rewrite(&mail_ctx)) < 0)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (ret == 0 && need_space_seq == 0) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen /* first mail with no space to write it */
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen need_space_seq = seq;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen space_diff = 0;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen /* update index */
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen do {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (rec != NULL && rec->uid >= mail_ctx.mail.uid)
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen break;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen if (idx_seq >= messages_count) {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen rec = NULL;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen break;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen if (rec != NULL)
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen mail_index_expunge(t, idx_seq);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen ret = mail_index_lookup(sync_view, ++idx_seq, &rec);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen } while (ret == 0);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen if (ret < 0)
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen break;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (rec != NULL && rec->uid != mail_ctx.mail.uid) {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen /* new UID in the middle of the mailbox -
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen shouldn't happen */
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen mail_storage_set_critical(ibox->box.storage,
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen "mbox sync: UID inserted in the middle "
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen "of mailbox (%u > %u)",
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen rec->uid, mail_ctx.mail.uid);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen mail_index_mark_corrupted(ibox->index);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen ret = -1;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen break;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen if (rec != NULL) {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen /* see if flags changed */
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen keywords_mask_t old_keywords;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen uint8_t old_flags;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen old_flags = rec->flags;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen memcpy(old_keywords, rec->keywords,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen INDEX_KEYWORDS_BYTE_COUNT);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mbox_sync_apply_index_syncs(syncs, &old_flags,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen old_keywords);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen new_flags = (rec->flags & ~MAIL_FLAGS_MASK) |
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen (mail_ctx.mail.flags &
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen (MAIL_FLAGS_MASK^MAIL_RECENT));
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (old_flags != new_flags ||
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen memcmp(old_keywords, mail_ctx.mail.keywords,
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen INDEX_KEYWORDS_BYTE_COUNT) != 0) {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen mail_index_update_flags(t, idx_seq,
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen MODIFY_REPLACE,
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen new_flags,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx.mail.keywords);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen /* we used this record */
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen rec = NULL;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen } else {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen /* new message */
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_index_append(t, mail_ctx.mail.uid, &idx_seq);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen new_flags = mail_ctx.mail.flags &
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen (MAIL_FLAGS_MASK^MAIL_RECENT);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen mail_index_update_flags(t, idx_seq, MODIFY_REPLACE,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen new_flags,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mail_ctx.mail.keywords);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen istream_raw_mbox_next(input, mail_ctx.mail.body_size);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen offset = istream_raw_mbox_get_start_offset(input);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (need_space_seq != 0) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen buffer_append(mails, &mail_ctx.mail,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen sizeof(mail_ctx.mail));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen space_diff += mail_ctx.mail.space;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (space_diff >= 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we have enough space now */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mbox_sync_rewrite(&sync_ctx, mails,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen need_space_seq, seq,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen space_diff) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen /* mail_ctx may contain wrong data after
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen rewrite, so make sure we don't try to access
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen it */
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen memset(&mail_ctx, 0, sizeof(mail_ctx));
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen i_stream_seek(input, offset);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen need_space_seq = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (need_space_seq != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(space_diff < 0);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen extra_space = MBOX_HEADER_EXTRA_SPACE *
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen (seq - need_space_seq + 1);
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (mbox_sync_grow_file(&sync_ctx, &mail_ctx,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen -space_diff + extra_space) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen else if (mbox_sync_try_rewrite(&mail_ctx) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = -1;
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen else if (seq != need_space_seq) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen buffer_set_used_size(mails,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen (seq-1) * sizeof(mail_ctx.mail));
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen buffer_append(mails, &mail_ctx.mail,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen sizeof(mail_ctx.mail));
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (mbox_sync_rewrite(&sync_ctx, mails, need_space_seq,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen seq, extra_space) < 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (rec != NULL)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mail_index_expunge(t, idx_seq);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen while (idx_seq < messages_count)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mail_index_expunge(t, ++idx_seq);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (sync_ctx.base_uid_last+1 != sync_ctx.next_uid) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen // FIXME: rewrite X-IMAPbase header
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (ret >= 0) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen /* only syncs left should be just appends which weren't synced
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen yet. we'll just ignore them, as we've overwritten those
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen above. */
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen while ((ret = mail_index_sync_next(index_sync_ctx,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen &sync_rec)) > 0) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen i_assert(sync_rec.type == MAIL_INDEX_SYNC_TYPE_APPEND);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (ret == 0) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (fstat(ibox->mbox_fd, &st) < 0) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mbox_set_syscall_error(ibox, "fstat()");
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (ret < 0) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen st.st_mtime = 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen st.st_size = 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (mail_index_get_header(sync_view, &hdr) < 0)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen ret = -1;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if ((uint32_t)st.st_mtime != hdr->sync_stamp) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen uint32_t sync_stamp = st.st_mtime;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_index_update_header(t,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen offsetof(struct mail_index_header, sync_stamp),
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen &sync_stamp, sizeof(sync_stamp));
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if ((uint64_t)st.st_mtime != hdr->sync_size) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen uint64_t sync_size = st.st_size;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_index_update_header(t,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen offsetof(struct mail_index_header, sync_size),
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen &sync_size, sizeof(sync_size));
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (ret < 0)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_index_transaction_rollback(t);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen else {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (mail_index_transaction_commit(t, &seq, &offset) < 0)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen ret = -1;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen else if (seq != 0) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen ibox->commit_log_file_seq = seq;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen ibox->commit_log_file_offset = offset;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (ret != -2) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (mail_index_sync_end(index_sync_ctx) < 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen if (ret == 0) {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen ibox->commit_log_file_seq = 0;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen ibox->commit_log_file_offset = 0;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen } else {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen mail_storage_set_index_error(ibox);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen ibox->mbox_data = buffer_get_data(ibox->mbox_data_buf, &size);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen ibox->mbox_data_count = size / sizeof(*ibox->mbox_data);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen str_free(sync_ctx.header);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen buffer_free(mails);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen buffer_free(syncs);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen return ret < 0 ? ret : 0;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen}
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainenint mbox_sync(struct index_mailbox *ibox, int last_commit)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen{
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen struct mail_index_sync_ctx *index_sync_ctx;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen struct mail_index_view *sync_view;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen unsigned int lock_id;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen uint32_t seq;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen uoff_t offset;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen int ret, lock_type;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (last_commit) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen seq = ibox->commit_log_file_seq;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen offset = ibox->commit_log_file_offset;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen } else {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen seq = (uint32_t)-1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen offset = (uoff_t)-1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = mail_index_sync_begin(ibox->index, &index_sync_ctx, &sync_view,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen seq, offset);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (ret <= 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen return ret;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen lock_type = mail_index_sync_have_more(index_sync_ctx) ?
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen F_WRLCK : F_RDLCK;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (mbox_lock(ibox, lock_type, &lock_id) > 0 &&
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mbox_file_open_stream(ibox) == 0) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = mbox_sync_do(ibox, index_sync_ctx, sync_view);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (ret == -2) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen /* read lock -> write lock. do it again. */
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen (void)mbox_unlock(ibox, lock_id);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen lock_id = 0;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (mbox_lock(ibox, F_WRLCK, &lock_id) <= 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen else if (mbox_file_open_stream(ibox) < 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen else {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = mbox_sync_do(ibox, index_sync_ctx,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen sync_view);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen } else {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen (void)mail_index_sync_end(index_sync_ctx);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (lock_id != 0) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (mbox_unlock(ibox, lock_id) < 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen return ret;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenint mbox_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct index_mailbox *ibox = (struct index_mailbox *)box;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FAST) == 0 ||
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ibox->sync_last_check + MAILBOX_FULL_SYNC_INTERVAL <= ioloop_time) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ibox->sync_last_check = ioloop_time;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (mbox_sync(ibox, FALSE) < 0)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return index_storage_sync(box, flags);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}