mail-index-view.c revision 6ef7e31619edfaa17ed044b45861d106a86191ef
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid mail_index_view_clone(struct mail_index_view *dest,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen dest->log_view = mail_transaction_log_view_open(src->index->log);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid mail_index_view_ref(struct mail_index_view *view)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void _view_close(struct mail_index_view *view)
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen mail_transaction_log_view_close(view->log_view);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenint mail_index_view_lock_head(struct mail_index_view *view, bool update_index)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int lock_id;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (MAIL_INDEX_MAP_IS_IN_MEMORY(view->index->map))
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (!mail_index_is_locked(view->index, view->lock_id)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mail_index_lock_shared(view->index, update_index,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mail_index_map(view->index, FALSE) <= 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* index was rebuilt */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mail_index_lock_shared(view->index, TRUE, &lock_id) < 0)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen mail_index_unlock(view->index, view->lock_id);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainenint mail_index_view_lock(struct mail_index_view *view)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* not head mapping, no need to lock */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return mail_index_view_lock_head(view, FALSE);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid mail_index_view_unlock(struct mail_index_view *view)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_index_unlock(view->index, view->lock_id);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenbool mail_index_view_is_inconsistent(struct mail_index_view *view)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstruct mail_index *mail_index_view_get_index(struct mail_index_view *view)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainenvoid mail_index_view_transaction_ref(struct mail_index_view *view)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid mail_index_view_transaction_unref(struct mail_index_view *view)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void mail_index_view_ref_map(struct mail_index_view *view,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int i, count;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* if map is already referenced, do nothing */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (i = 0; i < count; i++) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* reference the given mapping. the reference is dropped when the view
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen is synchronized or closed. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid mail_index_view_unref_maps(struct mail_index_view *view)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int i, count;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (i = 0; i < count; i++)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic uint32_t _view_get_messages_count(struct mail_index_view *view)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic const struct mail_index_header *
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic int _view_lookup_full(struct mail_index_view *view, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const struct mail_index_record *rec, *head_rec;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* look up the record */
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen /* view's mapping is latest. we can use it directly. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* look up the record from head mapping. it may contain some changes. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (mail_index_view_lock_head(view, FALSE) < 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* start looking up from the same sequence as in the old view.
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if there are no expunges, it's there. otherwise it's somewhere
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen before (since records can't be inserted).
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen usually there are only a few expunges, so just going downwards from
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen our initial sequence position is probably faster than binary
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* everything is expunged from head. use the old record. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } while (seq > 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* found it. use it. reference the index mapping so that the
7f13786e6a18a846376e46d77349528d99935871Timo Sirainen returned record doesn't get invalidated after next sync. */
7f13786e6a18a846376e46d77349528d99935871Timo Sirainen mail_index_view_ref_map(view, view->index->map);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* expuned from head. use the old record. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int _view_lookup_uid(struct mail_index_view *view, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *uid_r = MAIL_INDEX_MAP_IDX(view->map, seq-1)->uid;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic uint32_t mail_index_bsearch_uid(struct mail_index_view *view,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const struct mail_index_record *rec_base, *rec;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint32_t idx, left_idx, right_idx, record_size;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(view->hdr.messages_count <= view->map->records_count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* no messages available */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen /* we want uid or larger */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen idx == view->hdr.messages_count-1 ? 0 : idx+2;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* we want uid or smaller */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic int _view_lookup_uid_range(struct mail_index_view *view,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *first_seq_r = mail_index_bsearch_uid(view, first_uid, &left_idx, 1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen MAIL_INDEX_MAP_IDX(view->map, *first_seq_r-1)->uid > last_uid) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* optimization - binary lookup only from right side: */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *last_seq_r = mail_index_bsearch_uid(view, last_uid, &left_idx, -1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int _view_lookup_first(struct mail_index_view *view,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen STMT_START { if ((x) > low_uid) low_uid = x; } STMT_END
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if ((flags_mask & MAIL_RECENT) != 0 && (flags & MAIL_RECENT) != 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen LOW_UPDATE(view->map->hdr.first_recent_uid_lowwater);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if ((flags_mask & MAIL_SEEN) != 0 && (flags & MAIL_SEEN) == 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen LOW_UPDATE(view->map->hdr.first_unseen_uid_lowwater);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if ((flags_mask & MAIL_DELETED) != 0 && (flags & MAIL_DELETED) != 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen LOW_UPDATE(view->map->hdr.first_deleted_uid_lowwater);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mail_index_lookup_uid_range(view, low_uid, low_uid,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(view->hdr.messages_count <= view->map->records_count);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (; seq <= view->hdr.messages_count; seq++) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if ((rec->flags & flags_mask) == (uint8_t)flags) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenstatic int _view_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen uint32_t ext_id, struct mail_index_map **map_r,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen const void **data_r)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if ((ret = mail_index_lookup_full(view, seq, map_r, &rec)) < 0)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (rec == NULL || !mail_index_map_get_ext_idx(*map_r, ext_id, &idx)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *data_r = offset == 0 ? NULL : CONST_PTR_OFFSET(rec, offset);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int _view_get_header_ext(struct mail_index_view *view,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* if we have a mapping, the view where it's from is already locked */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* no mapping given, use head mapping */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (mail_index_view_lock_head(view, FALSE) < 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (!mail_index_map_get_ext_idx(map, ext_id, &idx)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* extension doesn't exist in this index file */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen *data_r = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_index_view_close(struct mail_index_view *view)
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainenuint32_t mail_index_view_get_messages_count(struct mail_index_view *view)
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen return view->methods.get_messages_count(view);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenmail_index_get_header(struct mail_index_view *view)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenint mail_index_lookup(struct mail_index_view *view, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return mail_index_lookup_full(view, seq, &map, rec_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return view->methods.lookup_full(view, seq, map_r, rec_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const unsigned char *keyword_data;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const unsigned int *keyword_idx_map;
e3540e734a79fd4f971652925079c2e26a4b5524Timo Sirainen /* get the keywords data. */
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen ret = mail_index_lookup_ext_full(view, seq, ext_id, &map, &data);
e4eb49e29197c6783ec93b868100394e189f4e0cTimo Sirainen /* no keywords at all in index */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen (void)mail_index_ext_get_size(view, ext_id, map, NULL,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* keyword_idx_map[] contains file => index keyword mapping */
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen if (!array_is_created(&map->keyword_idx_map)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen keyword_idx_map = array_get(&map->keyword_idx_map,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* first do the quick check to see if there's keywords at all */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* keyword header is updated, re-read
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen it so we know what this one is
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen /* pointer may have changed. update it. */
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen /* extra bits set in keyword bytes.
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen shouldn't happen, but just ignore. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return view->methods.lookup_uid(view, seq, uid_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_uid_range(struct mail_index_view *view,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return view->methods.lookup_uid_range(view, first_uid, last_uid,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_first(struct mail_index_view *view, enum mail_flags flags,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return view->methods.lookup_first(view, flags, flags_mask, seq_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return view->methods.lookup_ext_full(view, seq, ext_id, &map, data_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint32_t ext_id, struct mail_index_map **map_r,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const void **data_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return view->methods.lookup_ext_full(view, seq, ext_id, map_r, data_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_get_header_ext(struct mail_index_view *view, uint32_t ext_id,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return view->methods.get_header_ext(view, NULL, ext_id,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_map_get_header_ext(struct mail_index_view *view,
*hdr_size_r = 0;
*record_size_r = 0;
*record_align_r = 0;
return view;
const struct mail_index_ext *