mail-index-view.c revision b0be0bead3d6963149f7f2a9504b8ab5aced9af5
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (C) 2003-2004 Timo Sirainen */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenvoid mail_index_view_clone(struct mail_index_view *dest,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_transaction_log_view_open(src->index->log);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen dest->log_file_expunge_seq = src->log_file_expunge_seq;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen dest->log_file_expunge_offset = src->log_file_expunge_offset;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen dest->log_file_head_seq = src->log_file_head_seq;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen dest->log_file_head_offset = src->log_file_head_offset;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainenvoid mail_index_view_ref(struct mail_index_view *view)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainenstatic void _view_close(struct mail_index_view *view)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen mail_transaction_log_view_close(&view->log_view);
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Boschstatic void mail_index_view_check_nextuid(struct mail_index_view *view)
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen rec = MAIL_INDEX_MAP_IDX(view->map, view->hdr.messages_count-1);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenint mail_index_view_lock_head(struct mail_index_view *view)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (MAIL_INDEX_MAP_IS_IN_MEMORY(view->index->map))
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!mail_index_is_locked(view->index, view->lock_id)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (mail_index_lock_shared(view->index, &view->lock_id) < 0) {
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainenint mail_index_view_lock(struct mail_index_view *view)
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen /* not head mapping, no need to lock */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenvoid mail_index_view_unlock(struct mail_index_view *view)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (view->lock_id != 0 && view->transactions == 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_unlock(view->index, view->lock_id);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenbool mail_index_view_is_inconsistent(struct mail_index_view *view)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstruct mail_index *mail_index_view_get_index(struct mail_index_view *view)
c3cb859d93a77d52d6af054d358b55d45b4a5188Timo Sirainenvoid mail_index_view_transaction_ref(struct mail_index_view *view)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenvoid mail_index_view_transaction_unref(struct mail_index_view *view)
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainenstatic void mail_index_view_ref_map(struct mail_index_view *view,
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen unsigned int i, count;
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen /* if map is already referenced, do nothing */
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen for (i = 0; i < count; i++) {
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen /* reference the given mapping. the reference is dropped when the view
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen is synchronized or closed. */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenvoid mail_index_view_unref_maps(struct mail_index_view *view)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen unsigned int i, count;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen maps = array_get_modifiable(&view->map_refs, &count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (i = 0; i < count; i++)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic uint32_t _view_get_messages_count(struct mail_index_view *view)
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainenstatic const struct mail_index_header *
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainenstatic int _view_lookup_full(struct mail_index_view *view, uint32_t seq,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_record *rec, *head_rec;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view));
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* look up the record */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_set_error(view->index, "Corrupted Index file %s: "
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* view's mapping is latest. we can use it directly. */
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen /* look up the record from head mapping. it may contain some changes. */
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen /* start looking up from the same sequence as in the old view.
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen if there are no expunges, it's there. otherwise it's somewhere
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen before (since records can't be inserted).
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen usually there are only a few expunges, so just going downwards from
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen our initial sequence position is probably faster than binary
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (seq > view->index->map->hdr.messages_count)
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen /* everything is expunged from head. use the old record. */
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen } while (seq > 0);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* found it. use it. reference the index mapping so that the
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen returned record doesn't get invalidated after next sync. */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_view_ref_map(view, view->index->map);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* expuned from head. use the old record. */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic int _view_lookup_uid(struct mail_index_view *view, uint32_t seq,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view));
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *uid_r = MAIL_INDEX_MAP_IDX(view->map, seq-1)->uid;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic uint32_t mail_index_bsearch_uid(struct mail_index_view *view,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_record *rec_base, *rec;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(view->hdr.messages_count <= view->map->records_count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* optimization: the message can be only the first one */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* we want uid or larger */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen idx == view->hdr.messages_count-1 ? 0 : idx+2;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* we want uid or smaller */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic int _view_lookup_uid_range(struct mail_index_view *view,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *first_seq_r = mail_index_bsearch_uid(view, first_uid, 0, 1);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen MAIL_INDEX_MAP_IDX(view->map, *first_seq_r-1)->uid > last_uid) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* we want the last message */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* optimization - binary lookup only from right side: */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *last_seq_r = mail_index_bsearch_uid(view, last_uid,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic int _view_lookup_first(struct mail_index_view *view,
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen STMT_START { if ((x) > low_uid) low_uid = x; } STMT_END
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if ((flags_mask & MAIL_RECENT) != 0 && (flags & MAIL_RECENT) != 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen LOW_UPDATE(view->map->hdr.first_recent_uid_lowwater);
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen if ((flags_mask & MAIL_SEEN) != 0 && (flags & MAIL_SEEN) == 0)
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen LOW_UPDATE(view->map->hdr.first_unseen_uid_lowwater);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if ((flags_mask & MAIL_DELETED) != 0 && (flags & MAIL_DELETED) != 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen LOW_UPDATE(view->map->hdr.first_deleted_uid_lowwater);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (mail_index_lookup_uid_range(view, low_uid, low_uid,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(view->hdr.messages_count <= view->map->records_count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (; seq <= view->hdr.messages_count; seq++) {
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen if ((rec->flags & flags_mask) == (uint8_t)flags) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic int _view_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t ext_id, struct mail_index_map **map_r,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const void **data_r)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if ((ret = mail_index_lookup_full(view, seq, map_r, &rec)) < 0)
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen if (rec == NULL || !mail_index_map_get_ext_idx(*map_r, ext_id, &idx)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *data_r = offset == 0 ? NULL : CONST_PTR_OFFSET(rec, offset);
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainenstatic int _view_get_header_ext(struct mail_index_view *view,
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen /* if we have a mapping, the view where it's from is already locked */
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen /* no mapping given, use head mapping */
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen if (!mail_index_map_get_ext_idx(map, ext_id, &idx)) {
de9d79337eca11a7f9c1cd476c74dfe4f09a4bd7Timo Sirainen /* extension doesn't exist in this index file */
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen *data_r = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenvoid mail_index_view_close(struct mail_index_view **_view)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainenuint32_t mail_index_view_get_messages_count(struct mail_index_view *view)
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainenmail_index_get_header(struct mail_index_view *view)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenint mail_index_lookup(struct mail_index_view *view, uint32_t seq,
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen return mail_index_lookup_full(view, seq, &map, rec_r);
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainenint mail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen return view->v.lookup_full(view, seq, map_r, rec_r);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenint mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen const unsigned char *keyword_data;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen const unsigned int *keyword_idx_map;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen /* get the keywords data. */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen ret = mail_index_lookup_ext_full(view, seq, ext_id, &map, &data);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen /* no keywords at all in index */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen (void)mail_index_ext_get_size(view, ext_id, map, NULL,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen /* keyword_idx_map[] contains file => index keyword mapping */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen if (!array_is_created(&map->keyword_idx_map)) {
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen keyword_idx_map = array_get(&map->keyword_idx_map,
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen /* first do the quick check to see if there's keywords at all */
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen /* keyword header was updated, parse it again
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen it so we know what this keyword is called */
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen /* pointer may have changed. update it. */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen /* extra bits set in keyword bytes.
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen shouldn't happen, but just ignore. */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenint mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenint mail_index_lookup_uid_range(struct mail_index_view *view,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return view->v.lookup_uid_range(view, first_uid, last_uid,
af0a12ae492d79e27b29d63ff0f289f9034fecc9Stephan Boschint mail_index_lookup_first(struct mail_index_view *view, enum mail_flags flags,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return view->v.lookup_first(view, flags, flags_mask, seq_r);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenint mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return view->v.lookup_ext_full(view, seq, ext_id, &map, data_r);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenint mail_index_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen uint32_t ext_id, struct mail_index_map **map_r,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen const void **data_r)
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return view->v.lookup_ext_full(view, seq, ext_id, map_r, data_r);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenint mail_index_get_header_ext(struct mail_index_view *view, uint32_t ext_id,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return view->v.get_header_ext(view, NULL, ext_id, data_r, data_size_r);
*hdr_size_r = 0;
*record_size_r = 0;
*record_align_r = 0;
struct mail_index_view *
return view;
const struct mail_index_ext *