mail-index-sync-update.c revision e4fb5bfcdff32d337d054cce36e00e1cdfaae9f8
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (C) 2004 Timo Sirainen */
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainenvoid mail_index_header_update_counts(struct mail_index_header *hdr,
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (((old_flags ^ new_flags) & MAIL_SEEN) != 0) {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen /* different seen-flag */
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (((old_flags ^ new_flags) & MAIL_DELETED) != 0) {
221351ed85c839e0b03d82c47654c3d17202e3dbTimo Sirainen /* different deleted-flag */
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainenvoid mail_index_header_update_lowwaters(struct mail_index_header *hdr,
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainenstatic void mail_index_sync_update_expunges(struct mail_index_update_ctx *ctx,
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen mail_index_header_update_counts(&ctx->hdr, rec->flags, 0);
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainenstatic void mail_index_sync_update_flags(struct mail_index_update_ctx *ctx,
cfa9359fbd6a967ccdcd553c5e483a093885ab6fTimo Sirainen for (i = 0; i < INDEX_KEYWORDS_BYTE_COUNT; i++) {
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen keyword_mask[i] = ~syncrec->remove_keywords[i];
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen rec = &ctx->index->map->records[syncrec->seq1-1];
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen end = rec + (syncrec->seq2 - syncrec->seq1) + 1;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen rec->flags = (rec->flags & flag_mask) | syncrec->add_flags;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen for (i = 0; i < INDEX_KEYWORDS_BYTE_COUNT; i++) {
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen mail_index_header_update_lowwaters(&ctx->hdr, rec);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainenstatic int mail_index_grow(struct mail_index *index, unsigned int count)
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen map->records = buffer_get_modifyable_data(map->buffer, NULL);
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen (map->records_count + count) * sizeof(struct mail_index_record);
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen /* when we grow fast, do it exponentially */
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 Sirainenstatic int mail_index_sync_appends(struct mail_index_update_ctx *ctx,
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen unsigned int count)
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen unsigned int i;
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 mail_transaction_log_view_set_corrupted(ctx->log_view,
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen "Append with UID %u, but next_uid = %u",
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen memcpy(map->records + map->records_count, appends,
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainenint mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx,
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen uint32_t count, file_seq, src_idx, dest_idx, dirty_flag;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen unsigned int lock_id;
6c9699d37fbe4d8af3682ee7f341ede8d54faa87Timo Sirainen sync_ctx->update_idx = sync_ctx->expunge_idx = 0;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen buffer_get_used_size(sync_ctx->appends_buf) != 0;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen changed = mail_index_sync_have_more(sync_ctx);
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;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen /* see if we need to update sync headers */
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen if (ctx.hdr.sync_stamp != sync_stamp && sync_stamp != 0) {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (ctx.hdr.sync_size != sync_size && sync_size != 0) {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen /* nothing to sync */
91add6e26ed2b91e15276c96ffe02d9f71476d71Timo Sirainen if (mail_index_lock_exclusive(index, &lock_id) < 0)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen while (mail_index_sync_next(sync_ctx, &rec) > 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 mail_index_sync_update_expunges(&ctx, rec.seq1,
2aa3ac8bfb8fea49fd0ab6d56afcb3af3375d22cTimo Sirainen ret = mail_index_sync_appends(&ctx, appends, append_count);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen mail_transaction_log_get_head(index->log, &file_seq, &file_offset);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen map->mmap_used_size = index->hdr->header_size +
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen map->records_count * sizeof(struct mail_index_record);
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) {