mail-index-sync-update.c revision 3b94ff5951db4d4eddb7a80ed4e3f61207202635
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2004 Timo Sirainen */
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenmail_index_header_update_counts(struct mail_index_header *hdr,
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen if (((old_flags ^ new_flags) & MAIL_RECENT) != 0) {
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen /* different recent-flag */
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen hdr->first_recent_uid_lowwater = hdr->next_uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (((old_flags ^ new_flags) & MAIL_SEEN) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* different seen-flag */
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen else if (++hdr->seen_messages_count == hdr->messages_count)
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen hdr->first_unseen_uid_lowwater = hdr->next_uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (((old_flags ^ new_flags) & MAIL_DELETED) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* different deleted-flag */
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen hdr->first_deleted_uid_lowwater = hdr->next_uid;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenmail_index_header_update_lowwaters(struct mail_index_header *hdr,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenvoid mail_index_sync_expunge(struct mail_index_view *view,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct mail_index_header *hdr = &map->hdr_copy;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen ret = mail_index_lookup_uid_range(view, e->uid1, e->uid2, &seq1, &seq2);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_index_header_update_counts(hdr, rec->flags, 0);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen /* @UNSAFE */
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen memcpy(map->records + (seq1-1), map->records + seq2,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen (map->records_count - seq2) * sizeof(*map->records));
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen buffer_set_used_size(map->buffer, map->records_count);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen map->records = buffer_get_modifyable_data(map->buffer, NULL);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int sync_expunge(const struct mail_transaction_expunge *e, void *context)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int sync_append(const struct mail_index_record *rec, void *context)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_transaction_log_view_set_corrupted(view->log_view,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen "Append with UID %u, but next_uid = %u",
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen buffer_get_modifyable_data(map->buffer, NULL);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen i_assert(map->records_count * sizeof(*rec) <= map->mmap_size);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_index_header_update_counts(&map->hdr_copy, 0, rec->flags);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_index_header_update_lowwaters(&map->hdr_copy, rec);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int sync_flag_update(const struct mail_transaction_flag_update *u,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen ret = mail_index_lookup_uid_range(view, u->uid1, u->uid2, &seq1, &seq2);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if ((u->add_flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen for (i = 0; i < INDEX_KEYWORDS_BYTE_COUNT; i++) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (u->add_keywords[i] != 0 ||
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen rec->flags = (rec->flags & flag_mask) | u->add_flags;
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen for (i = 0; i < INDEX_KEYWORDS_BYTE_COUNT; i++) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_index_header_update_counts(hdr, old_flags, rec->flags);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int sync_cache_update(const struct mail_transaction_cache_update *u,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen ret = mail_index_lookup_uid_range(view, u->uid, u->uid,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen view->map->records[seq-1].cache_offset = u->cache_offset;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int sync_header_update(const struct mail_transaction_header_update *u,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen data = PTR_OFFSET(&view->map->hdr_copy, u->offset);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int mail_index_grow(struct mail_index *index, struct mail_index_map *map,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen unsigned int count)
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen map->records = buffer_get_modifyable_data(map->buffer, NULL);
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen (map->records_count + count) * sizeof(struct mail_index_record);
690af4a90eaf8611c2573d34126bb7a852c50a44Timo Sirainen /* when we grow fast, do it exponentially */
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen (map->records_count + 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()");
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenint mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct mail_index_view *view = sync_ctx->view;
5c1a8aee989af87bddefd71e2aa83aa2bd695155Timo Sirainen if (mail_index_lock_exclusive(index, &lock_id) < 0)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen /* NOTE: locking may change index->map so make sure assignment
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen after locking */
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen had_dirty = (map->hdr_copy.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) != 0;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen map->hdr_copy.flags &= ~MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view, &hdr,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0 &&
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen /* expunges have to be atomic. so we'll have to copy
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen the mapping, do the changes there and then finally
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen replace the whole index file. to avoid extra disk
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen I/O we copy the index into memory rather than to
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen temporary file */
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_APPEND) != 0) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen count = hdr->size / sizeof(struct mail_index_record);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (mail_index_grow(index, view->map, count) < 0)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (mail_transaction_map(hdr, data, &mail_index_map_sync_funcs,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_transaction_log_get_head(index->log, &seq, &offset);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if ((map->hdr_copy.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) == 0 &&
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen /* do we have dirty flags anymore? */
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen map->mmap_used_size = index->hdr->header_size +
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen map->records_count * sizeof(struct mail_index_record);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen memcpy(map->mmap_base, &map->hdr_copy, sizeof(map->hdr_copy));
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen if (msync(map->mmap_base, map->mmap_used_size, MS_SYNC) < 0) {
5c1a8aee989af87bddefd71e2aa83aa2bd695155Timo Sirainen mail_index_set_syscall_error(index, "msync()");