mail-index-sync-update.c revision e4fb5bfcdff32d337d054cce36e00e1cdfaae9f8
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (C) 2004 Timo Sirainen */
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen#include "lib.h"
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen#include "buffer.h"
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen#include "file-set-size.h"
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen#include "mmap-util.h"
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen#include "mail-index-view-private.h"
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen#include "mail-index-sync-private.h"
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen#include "mail-transaction-log.h"
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainenstruct mail_index_update_ctx {
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen struct mail_index *index;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen struct mail_index_header hdr;
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen struct mail_transaction_log_view *log_view;
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen};
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainenvoid mail_index_header_update_counts(struct mail_index_header *hdr,
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen uint8_t old_flags, uint8_t new_flags)
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen{
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (((old_flags ^ new_flags) & MAIL_SEEN) != 0) {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen /* different seen-flag */
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if ((old_flags & MAIL_SEEN) == 0)
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen hdr->seen_messages_count++;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen else
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen hdr->seen_messages_count--;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen }
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (((old_flags ^ new_flags) & MAIL_DELETED) != 0) {
221351ed85c839e0b03d82c47654c3d17202e3dbTimo Sirainen /* different deleted-flag */
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if ((old_flags & MAIL_DELETED) == 0)
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen hdr->deleted_messages_count++;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen else
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen hdr->deleted_messages_count--;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen }
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen}
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainenvoid mail_index_header_update_lowwaters(struct mail_index_header *hdr,
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen const struct mail_index_record *rec)
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen{
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if ((rec->flags & MAIL_RECENT) != 0 &&
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen rec->uid < hdr->first_recent_uid_lowwater)
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen hdr->first_recent_uid_lowwater = rec->uid;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if ((rec->flags & MAIL_SEEN) == 0 &&
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen rec->uid < hdr->first_unseen_uid_lowwater)
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen hdr->first_unseen_uid_lowwater = rec->uid;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if ((rec->flags & MAIL_DELETED) != 0 &&
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen rec->uid < hdr->first_deleted_uid_lowwater)
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen hdr->first_deleted_uid_lowwater = rec->uid;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen}
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainenstatic void mail_index_sync_update_expunges(struct mail_index_update_ctx *ctx,
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen uint32_t seq1, uint32_t seq2)
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen{
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen struct mail_index_record *rec;
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen rec = &ctx->index->map->records[seq1-1];
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen for (; seq1 <= seq2; seq1++, rec++)
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen mail_index_header_update_counts(&ctx->hdr, rec->flags, 0);
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen}
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainenstatic void mail_index_sync_update_flags(struct mail_index_update_ctx *ctx,
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen struct mail_index_sync_rec *syncrec)
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen{
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen struct mail_index_record *rec, *end;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen uint8_t flag_mask, old_flags;
8ababf3e7b15f793370d1dedf85825d38b42633fTimo Sirainen keywords_mask_t keyword_mask;
cfa9359fbd6a967ccdcd553c5e483a093885ab6fTimo Sirainen int i, update_keywords;
cfa9359fbd6a967ccdcd553c5e483a093885ab6fTimo Sirainen
cfa9359fbd6a967ccdcd553c5e483a093885ab6fTimo Sirainen update_keywords = FALSE;
cfa9359fbd6a967ccdcd553c5e483a093885ab6fTimo Sirainen for (i = 0; i < INDEX_KEYWORDS_BYTE_COUNT; i++) {
cfa9359fbd6a967ccdcd553c5e483a093885ab6fTimo Sirainen if (syncrec->add_keywords[i] != 0)
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen update_keywords = TRUE;
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen if (syncrec->remove_keywords[i] != 0)
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen update_keywords = TRUE;
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen keyword_mask[i] = ~syncrec->remove_keywords[i];
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen }
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen flag_mask = ~syncrec->remove_flags;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen rec = &ctx->index->map->records[syncrec->seq1-1];
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen end = rec + (syncrec->seq2 - syncrec->seq1) + 1;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen for (; rec != end; rec++) {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen old_flags = rec->flags;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen rec->flags = (rec->flags & flag_mask) | syncrec->add_flags;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (update_keywords) {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen for (i = 0; i < INDEX_KEYWORDS_BYTE_COUNT; i++) {
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen rec->keywords[i] =
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen (rec->keywords[i] & keyword_mask[i]) |
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen syncrec->add_keywords[i];
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen }
cfa9359fbd6a967ccdcd553c5e483a093885ab6fTimo Sirainen }
8ababf3e7b15f793370d1dedf85825d38b42633fTimo Sirainen
8ababf3e7b15f793370d1dedf85825d38b42633fTimo Sirainen mail_index_header_update_counts(&ctx->hdr,
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen old_flags, rec->flags);
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen mail_index_header_update_lowwaters(&ctx->hdr, rec);
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen }
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen}
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainenstatic int mail_index_grow(struct mail_index *index, unsigned int count)
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen{
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen struct mail_index_map *map = index->map;
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen unsigned int records_count;
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen size_t size;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (MAIL_INDEX_MAP_IS_IN_MEMORY(map)) {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen (void)buffer_append_space_unsafe(map->buffer,
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen count * sizeof(struct mail_index_record));
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen map->records = buffer_get_modifyable_data(map->buffer, NULL);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen return 0;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen }
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen size = map->hdr->header_size +
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen (map->records_count + count) * sizeof(struct mail_index_record);
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen if (size <= map->mmap_size)
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen return 0;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen /* when we grow fast, do it exponentially */
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen if (count < index->last_grow_count)
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen count = index->last_grow_count;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen if (count < MAIL_INDEX_MAX_POWER_GROW)
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen count = nearest_power(count);
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen index->last_grow_count = count;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen size = map->hdr->header_size +
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen (map->records_count + count) * sizeof(struct mail_index_record);
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen if (file_set_size(index->fd, (off_t)size) < 0)
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen return mail_index_set_syscall_error(index, "file_set_size()");
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen records_count = map->records_count;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen if (mail_index_map(index, TRUE) <= 0)
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen return -1;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen i_assert(map->mmap_size >= size);
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen map->records_count = records_count;
8ababf3e7b15f793370d1dedf85825d38b42633fTimo Sirainen return 0;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen}
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainenstatic int mail_index_sync_appends(struct mail_index_update_ctx *ctx,
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen const struct mail_index_record *appends,
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen unsigned int count)
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen{
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen struct mail_index_map *map = ctx->index->map;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen unsigned int i;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen uint32_t next_uid;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen if (mail_index_grow(ctx->index, count) < 0)
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen return -1;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen next_uid = ctx->hdr.next_uid;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen for (i = 0; i < count; i++) {
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen mail_index_header_update_counts(&ctx->hdr, 0, appends[i].flags);
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen mail_index_header_update_lowwaters(&ctx->hdr, &appends[i]);
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen if (appends[i].uid < next_uid) {
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen mail_transaction_log_view_set_corrupted(ctx->log_view,
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen "Append with UID %u, but next_uid = %u",
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen appends[i].uid, next_uid);
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen return -1;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen }
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen next_uid = appends[i].uid+1;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen }
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen ctx->hdr.next_uid = next_uid;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen memcpy(map->records + map->records_count, appends,
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen count * sizeof(*appends));
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen map->records_count += count;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen return 0;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen}
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainenint mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx,
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen uint32_t sync_stamp, uint64_t sync_size)
f46068919d4b3e1f36028c4182108c169f914019Timo Sirainen{
f46068919d4b3e1f36028c4182108c169f914019Timo Sirainen struct mail_index *index = sync_ctx->index;
f46068919d4b3e1f36028c4182108c169f914019Timo Sirainen struct mail_index_map *map = index->map;
f46068919d4b3e1f36028c4182108c169f914019Timo Sirainen struct mail_index_update_ctx ctx;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen struct mail_index_sync_rec rec;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen const struct mail_index_record *appends;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen unsigned int append_count;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen uint32_t count, file_seq, src_idx, dest_idx, dirty_flag;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen uoff_t file_offset;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen unsigned int lock_id;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen int ret, changed;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen /* rewind */
6c9699d37fbe4d8af3682ee7f341ede8d54faa87Timo Sirainen sync_ctx->update_idx = sync_ctx->expunge_idx = 0;
9573f4283f9118315b0865998d43223fedee0246Timo Sirainen sync_ctx->sync_appends =
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen buffer_get_used_size(sync_ctx->appends_buf) != 0;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen changed = mail_index_sync_have_more(sync_ctx);
6c9699d37fbe4d8af3682ee7f341ede8d54faa87Timo Sirainen
6c9699d37fbe4d8af3682ee7f341ede8d54faa87Timo Sirainen memset(&ctx, 0, sizeof(ctx));
6c9699d37fbe4d8af3682ee7f341ede8d54faa87Timo Sirainen ctx.index = index;
6c9699d37fbe4d8af3682ee7f341ede8d54faa87Timo Sirainen ctx.hdr = *index->hdr;
6c9699d37fbe4d8af3682ee7f341ede8d54faa87Timo Sirainen ctx.log_view = sync_ctx->view->log_view;
6c9699d37fbe4d8af3682ee7f341ede8d54faa87Timo Sirainen
6c9699d37fbe4d8af3682ee7f341ede8d54faa87Timo Sirainen dirty_flag = sync_ctx->have_dirty ? MAIL_INDEX_HDR_FLAG_HAVE_DIRTY : 0;
ed50658501d9ae8c85f6264831056b1debed11c3Timo Sirainen if ((ctx.hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) != dirty_flag) {
ed50658501d9ae8c85f6264831056b1debed11c3Timo Sirainen ctx.hdr.flags ^= MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
ed50658501d9ae8c85f6264831056b1debed11c3Timo Sirainen changed = TRUE;
ed50658501d9ae8c85f6264831056b1debed11c3Timo Sirainen }
ed50658501d9ae8c85f6264831056b1debed11c3Timo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen /* see if we need to update sync headers */
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen if (ctx.hdr.sync_stamp != sync_stamp && sync_stamp != 0) {
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen ctx.hdr.sync_stamp = sync_stamp;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen changed = TRUE;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen }
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (ctx.hdr.sync_size != sync_size && sync_size != 0) {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen ctx.hdr.sync_size = sync_size;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen changed = TRUE;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen }
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (!changed) {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen /* nothing to sync */
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen return 0;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen }
91add6e26ed2b91e15276c96ffe02d9f71476d71Timo Sirainen
91add6e26ed2b91e15276c96ffe02d9f71476d71Timo Sirainen if (mail_index_lock_exclusive(index, &lock_id) < 0)
91add6e26ed2b91e15276c96ffe02d9f71476d71Timo Sirainen return -1;
91add6e26ed2b91e15276c96ffe02d9f71476d71Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (MAIL_INDEX_MAP_IS_IN_MEMORY(map))
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen map->write_to_disk = TRUE;
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen src_idx = dest_idx = 0;
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen append_count = 0; appends = NULL;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen while (mail_index_sync_next(sync_ctx, &rec) > 0) {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen switch (rec.type) {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen case MAIL_INDEX_SYNC_TYPE_APPEND:
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen i_assert(appends == NULL);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen append_count = rec.seq2 - rec.seq1 + 1;
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen appends = rec.appends;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen break;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (src_idx == 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* expunges have to be atomic. so we'll have
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen to copy the mapping, do the changes there
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen and then finally replace the whole index
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen file. to avoid extra disk I/O we copy the
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen index into memory rather than to temporary
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen file */
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen map = mail_index_map_to_memory(map);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_unmap(index, index->map);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen index->map = map;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen index->hdr = map->hdr;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen map->write_to_disk = TRUE;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen dest_idx = rec.seq1-1;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen } else {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen count = (rec.seq1-1) - src_idx;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen memmove(map->records + dest_idx,
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen map->records + src_idx,
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen count * sizeof(*map->records));
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen dest_idx += count;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen }
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_sync_update_expunges(&ctx, rec.seq1,
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen rec.seq2);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen src_idx = rec.seq2;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen break;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen case MAIL_INDEX_SYNC_TYPE_FLAGS:
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen mail_index_sync_update_flags(&ctx, &rec);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen break;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen }
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (src_idx != 0) {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen count = map->records_count - src_idx;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen memmove(map->records + dest_idx,
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen map->records + src_idx,
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen count * sizeof(*map->records));
2aa3ac8bfb8fea49fd0ab6d56afcb3af3375d22cTimo Sirainen dest_idx += count;
2aa3ac8bfb8fea49fd0ab6d56afcb3af3375d22cTimo Sirainen
2aa3ac8bfb8fea49fd0ab6d56afcb3af3375d22cTimo Sirainen map->records_count = dest_idx;
2aa3ac8bfb8fea49fd0ab6d56afcb3af3375d22cTimo Sirainen }
2aa3ac8bfb8fea49fd0ab6d56afcb3af3375d22cTimo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen ret = 0;
2aa3ac8bfb8fea49fd0ab6d56afcb3af3375d22cTimo Sirainen if (append_count > 0)
2aa3ac8bfb8fea49fd0ab6d56afcb3af3375d22cTimo Sirainen ret = mail_index_sync_appends(&ctx, appends, append_count);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen mail_transaction_log_get_head(index->log, &file_seq, &file_offset);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2aa3ac8bfb8fea49fd0ab6d56afcb3af3375d22cTimo Sirainen ctx.hdr.messages_count = map->records_count;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen ctx.hdr.log_file_seq = file_seq;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen ctx.hdr.log_file_offset = file_offset;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (!MAIL_INDEX_MAP_IS_IN_MEMORY(map)) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen map->mmap_used_size = index->hdr->header_size +
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen map->records_count * sizeof(struct mail_index_record);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen memcpy(map->mmap_base, &ctx.hdr, sizeof(ctx.hdr));
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (msync(map->mmap_base, map->mmap_used_size, MS_SYNC) < 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_index_set_syscall_error(index, "msync()");
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ret = -1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen } else {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen map->hdr_copy = ctx.hdr;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen map->hdr = &map->hdr_copy;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_index_unlock(index, lock_id);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return ret;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen