mail-index-view.c revision e627cdc5ef30d87959f9510832427e33a2f1d84a
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenvoid mail_index_view_clone(struct mail_index_view *dest,
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen mail_transaction_log_view_open(src->index->log);
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen dest->inconsistency_id = src->inconsistency_id;
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen dest->log_file_expunge_seq = src->log_file_expunge_seq;
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen dest->log_file_expunge_offset = src->log_file_expunge_offset;
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen dest->log_file_head_seq = src->log_file_head_seq;
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen dest->log_file_head_offset = src->log_file_head_offset;
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainenvoid mail_index_view_ref(struct mail_index_view *view)
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainenstatic void _view_close(struct mail_index_view *view)
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen mail_transaction_log_view_close(&view->log_view);
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainenbool mail_index_view_is_inconsistent(struct mail_index_view *view)
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen view->index->inconsistency_id != view->inconsistency_id)
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainenstruct mail_index *mail_index_view_get_index(struct mail_index_view *view)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mail_index_view_transaction_ref(struct mail_index_view *view)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mail_index_view_transaction_unref(struct mail_index_view *view)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void mail_index_view_ref_map(struct mail_index_view *view,
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen unsigned int i, count;
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen /* if map is already referenced, do nothing */
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen for (i = 0; i < count; i++) {
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen /* reference the given mapping. the reference is dropped when the view
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen is synchronized or closed. */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mail_index_view_unref_maps(struct mail_index_view *view)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen unsigned int i, count;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen maps = array_get_modifiable(&view->map_refs, &count);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen for (i = 0; i < count; i++)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic uint32_t _view_get_messages_count(struct mail_index_view *view)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic const struct mail_index_header *
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic const struct mail_index_record *
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen_view_lookup_full(struct mail_index_view *view, uint32_t seq,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mail_index_map **map_r, bool *expunged_r)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const struct mail_index_record *rec, *head_rec;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view));
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* look up the record */
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen "Corrupted Index file %s: Record [%u].uid=0",
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen /* we'll need to return something so the caller doesn't crash */
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen /* view's mapping is latest. we can use it directly. */
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen /* look up the record from head mapping. it may contain some changes.
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen start looking up from the same sequence as in the old view.
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen if there are no expunges, it's there. otherwise it's somewhere
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen before (since records can't be inserted).
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen usually there are only a few expunges, so just going downwards from
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen our initial sequence position is probably faster than binary
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen if (seq > view->index->map->hdr.messages_count)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* everything is expunged from head. use the old record. */
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen } while (seq > 0);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* found it. use it. reference the index mapping so that the
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen returned record doesn't get invalidated after next sync. */
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen mail_index_view_ref_map(view, view->index->map);
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen /* expuned from head. use the old record. */
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainenstatic void _view_lookup_uid(struct mail_index_view *view, uint32_t seq,
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view));
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen *uid_r = MAIL_INDEX_MAP_IDX(view->map, seq-1)->uid;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainenstatic uint32_t mail_index_bsearch_uid(struct mail_index_view *view,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const struct mail_index_record *rec_base, *rec;
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen /* optimization: the message can be only the first one */
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_assert(idx < view->map->hdr.messages_count);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* we want uid or larger */
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen /* we want uid or smaller */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void _view_lookup_uid_range(struct mail_index_view *view,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *first_seq_r = mail_index_bsearch_uid(view, first_uid, 0, 1);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen MAIL_INDEX_MAP_IDX(view->map, *first_seq_r-1)->uid > last_uid) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* we want the last message */
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen /* optimization - binary lookup only from right side: */
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen *last_seq_r = mail_index_bsearch_uid(view, last_uid,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void _view_lookup_first(struct mail_index_view *view,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen STMT_START { if ((x) > low_uid) low_uid = x; } STMT_END
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if ((flags_mask & MAIL_SEEN) != 0 && (flags & MAIL_SEEN) == 0)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen LOW_UPDATE(view->map->hdr.first_unseen_uid_lowwater);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if ((flags_mask & MAIL_DELETED) != 0 && (flags & MAIL_DELETED) != 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen LOW_UPDATE(view->map->hdr.first_deleted_uid_lowwater);
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen mail_index_lookup_uid_range(view, low_uid, low_uid,
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen for (; seq <= view->map->hdr.messages_count; seq++) {
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen if ((rec->flags & flags_mask) == (uint8_t)flags) {
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen_view_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
7bb939ef70752f2731d27b18c944ea94e5b23eb5Timo Sirainen uint32_t ext_id, struct mail_index_map **map_r,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen rec = view->v.lookup_full(view, seq, map_r, expunged_r);
8e574a603c2c02105b073906a7ca91904271b80eTimo Sirainen if (!mail_index_map_get_ext_idx(*map_r, ext_id, &idx)) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *data_r = offset == 0 ? NULL : CONST_PTR_OFFSET(rec, offset);
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainenstatic void _view_get_header_ext(struct mail_index_view *view,
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen /* no mapping given, use head mapping */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (!mail_index_map_get_ext_idx(map, ext_id, &idx)) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* extension doesn't exist in this index file */
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen *data_r = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenstatic bool _view_ext_get_reset_id(struct mail_index_view *view __attr_unused__,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen if (!mail_index_map_get_ext_idx(map, ext_id, &idx))
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainenvoid mail_index_view_close(struct mail_index_view **_view)
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainenuint32_t mail_index_view_get_messages_count(struct mail_index_view *view)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainenmail_index_get_header(struct mail_index_view *view)
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainenmail_index_lookup(struct mail_index_view *view, uint32_t seq)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen return mail_index_lookup_full(view, seq, &map);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenmail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen return view->v.lookup_full(view, seq, map_r, &expunged);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenbool mail_index_is_expunged(struct mail_index_view *view, uint32_t seq)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen (void)view->v.lookup_full(view, seq, &map, &expunged);
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainenvoid mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq,
2c20ffcb5bb1ccdfdcd0b0ff0c7296f65b990362Timo Sirainen const unsigned char *keyword_data;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen const unsigned int *keyword_idx_map;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* get the keywords data. */
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen mail_index_lookup_ext_full(view, seq, ext_id, &map, &data, NULL);
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen /* no keywords at all in index */
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen (void)mail_index_ext_get_size(view, ext_id, map, NULL,
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen /* keyword_idx_map[] contains file => index keyword mapping */
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen keyword_idx_map = array_get(&map->keyword_idx_map, &keyword_count);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* first do the quick check to see if there's keywords at all */
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen /* extra bits set in keyword bytes.
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen shouldn't happen, but just ignore. */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainenvoid mail_index_lookup_uid_range(struct mail_index_view *view,
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen view->v.lookup_uid_range(view, first_uid, last_uid,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenvoid mail_index_lookup_first(struct mail_index_view *view,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen view->v.lookup_first(view, flags, flags_mask, seq_r);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen mail_index_lookup_ext_full(view, seq, ext_id, &map, data_r, expunged_r);
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainenvoid mail_index_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen uint32_t ext_id, struct mail_index_map **map_r,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen view->v.lookup_ext_full(view, seq, ext_id, map_r, data_r, expunged_r);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mail_index_get_header_ext(struct mail_index_view *view, uint32_t ext_id,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen view->v.get_header_ext(view, NULL, ext_id, data_r, data_size_r);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mail_index_map_get_header_ext(struct mail_index_view *view,
*hdr_size_r = 0;
*record_size_r = 0;
*record_align_r = 0;
struct mail_index_view *
return view;
const struct mail_index_ext *
return NULL;