mail-index-sync-update.c revision 690af4a90eaf8611c2573d34126bb7a852c50a44
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2004 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_header_update_counts(struct mail_index_header *hdr,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (((old_flags ^ new_flags) & MAIL_SEEN) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* different seen-flag */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (((old_flags ^ new_flags) & MAIL_DELETED) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* different deleted-flag */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_header_update_lowwaters(struct mail_index_header *hdr,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void mail_index_sync_update_expunges(struct mail_index_update_ctx *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_header_update_counts(&ctx->hdr, rec->flags, 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void mail_index_sync_update_flags(struct mail_index_update_ctx *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < INDEX_CUSTOM_FLAGS_BYTE_COUNT; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen custom_mask[i] = ~syncrec->remove_custom_flags[i];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rec = &ctx->index->map->records[syncrec->seq1-1];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen end = rec + (syncrec->seq2 - syncrec->seq1) + 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rec->flags = (rec->flags & flag_mask) | syncrec->add_flags;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < INDEX_CUSTOM_FLAGS_BYTE_COUNT; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_header_update_lowwaters(&ctx->hdr, rec);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int mail_index_grow(struct mail_index *index, unsigned int count)
690af4a90eaf8611c2573d34126bb7a852c50a44Timo Sirainen /* when we grow fast, do it exponentially */
690af4a90eaf8611c2573d34126bb7a852c50a44Timo Sirainen size = map->file_used_size + count * sizeof(struct mail_index_record);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (file_set_size(index->fd, (off_t)size) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return mail_index_set_syscall_error(index, "file_set_size()");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int mail_index_sync_appends(struct mail_index_update_ctx *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int count)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen space = (map->file_size - map->file_used_size) / sizeof(*appends);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < count; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_header_update_counts(&ctx->hdr, 0, appends[i].flags);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_header_update_lowwaters(&ctx->hdr, &appends[i]);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* FIXME: should we rather just update the record?
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen this can actually happen if append was written to
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen transaction log but index wasn't updated, then
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen another sync wrote it again.. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_transaction_log_view_set_corrupted(ctx->log_view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Append with UID %u, but next_uid = %u",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memcpy(map->records + map->records_count, appends,
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen map->file_used_size += count * sizeof(struct mail_index_record);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx)
5c1a8aee989af87bddefd71e2aa83aa2bd695155Timo Sirainen unsigned int lock_id;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sync_ctx->update_idx = sync_ctx->expunge_idx = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buffer_get_used_size(sync_ctx->appends_buf) != 0;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen /* nothing to sync */
5c1a8aee989af87bddefd71e2aa83aa2bd695155Timo Sirainen if (mail_index_lock_exclusive(index, &lock_id) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while (mail_index_sync_next(sync_ctx, &rec) > 0) {
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen /* expunges have to be atomic. so we'll have
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen to copy the mapping, do the changes there
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen and then finally replace the whole index
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen file. to avoid extra disk I/O we copy the
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen index into memory rather than to temporary
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_sync_update_expunges(&ctx, rec.seq1,
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen map->file_used_size = index->hdr->header_size +
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen map->records_count * sizeof(struct mail_index_record);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = mail_index_sync_appends(&ctx, appends, append_count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_transaction_log_get_head(index->log, &file_seq, &file_offset);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memcpy(map->mmap_base, &ctx.hdr, sizeof(ctx.hdr));
5c1a8aee989af87bddefd71e2aa83aa2bd695155Timo Sirainen if (msync(map->mmap_base, map->file_used_size, MS_SYNC) < 0) {