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