mail-index-sync-update.c revision 024815ea2ffdda9ea79919f18e865663977f73ea
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,
8603622835ec0566e49056ee839ef5992b48c46dTimo Sirainenstatic void 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 */
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen (map->records_count - seq2) * view->index->record_size);
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo 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",
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen i_assert(map->records_count * index->record_size ==
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen buffer_append(map->buffer, rec, index->record_size);
ace3c14e47a5a865df8aeea2fabc993b609dd163Timo Sirainen map->records = buffer_get_modifyable_data(map->buffer, NULL);
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen i_assert((map->records_count+1) * index->record_size <=
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen memcpy(MAIL_INDEX_MAP_IDX(index, map, map->records_count),
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 ||
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen rec = MAIL_INDEX_MAP_IDX(view->index, view->map, i);
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,
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen MAIL_INDEX_MAP_IDX(view->index, view->map, seq-1)->
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int sync_header_update(const struct mail_transaction_header_update *u,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen data = PTR_OFFSET(&view->map->hdr_copy, u->offset);
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainensync_extra_rec_update(const struct mail_transaction_extra_rec_header *hdr,
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen const struct mail_transaction_extra_rec_update *u,
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen /* FIXME: do data_id mapping conversion */
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen ret = mail_index_lookup_uid_range(view, u->uid, u->uid,
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen offset = view->index->extra_records[hdr->idx].offset;
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen size = view->index->extra_records[hdr->idx].size;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen rec = MAIL_INDEX_MAP_IDX(view->index, view->map, seq-1);
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen memcpy(PTR_OFFSET(rec, offset), u->data, size);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int mail_index_grow(struct mail_index *index, struct mail_index_map *map,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen unsigned int count)
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen (map->records_count + count) * index->record_size;
690af4a90eaf8611c2573d34126bb7a852c50a44Timo Sirainen /* when we grow fast, do it exponentially */
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen (map->records_count + count) * index->record_size;
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 if (mail_index_grow(index, view->map, count) < 0)
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? */
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) {
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen map->mmap_used_size = index->hdr->header_size +
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()");
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstruct mail_transaction_map_functions mail_index_map_sync_funcs = {