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