mail-index-view.c revision 3fe9483b2b412a14493e3120751b0e99ecfe9388
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2003-2008 Dovecot authors, see the included COPYING file */
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainenvoid mail_index_view_clone(struct mail_index_view *dest,
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen mail_transaction_log_view_open(src->index->log);
e627cdc5ef30d87959f9510832427e33a2f1d84aTimo Sirainen dest->inconsistency_id = src->inconsistency_id;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen dest->log_file_expunge_seq = src->log_file_expunge_seq;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen dest->log_file_expunge_offset = src->log_file_expunge_offset;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen dest->log_file_head_seq = src->log_file_head_seq;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen dest->log_file_head_offset = src->log_file_head_offset;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainenvoid mail_index_view_ref(struct mail_index_view *view)
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic void view_close(struct mail_index_view *view)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mail_transaction_log_view_close(&view->log_view);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenbool mail_index_view_is_inconsistent(struct mail_index_view *view)
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen view->index->inconsistency_id != view->inconsistency_id)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_index *mail_index_view_get_index(struct mail_index_view *view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_view_transaction_ref(struct mail_index_view *view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_view_transaction_unref(struct mail_index_view *view)
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainenstatic void mail_index_view_ref_map(struct mail_index_view *view,
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen unsigned int i, count;
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen /* if map is already referenced, do nothing */
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen for (i = 0; i < count; i++) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* reference the given mapping. the reference is dropped when the view
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen is synchronized or closed. */
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainenvoid mail_index_view_unref_maps(struct mail_index_view *view)
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen unsigned int i, count;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen maps = array_get_modifiable(&view->map_refs, &count);
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen for (i = 0; i < count; i++)
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic uint32_t view_get_messages_count(struct mail_index_view *view)
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainenstatic const struct mail_index_header *
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic const struct mail_index_record *
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenview_lookup_full(struct mail_index_view *view, uint32_t seq,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen struct mail_index_map **map_r, bool *expunged_r)
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen const struct mail_index_record *rec, *head_rec;
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view));
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* look up the record */
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen "Corrupted Index file %s: Record [%u].uid=0",
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen /* we'll need to return something so the caller doesn't crash */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* view's mapping is latest. we can use it directly. */
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen /* look up the record from head mapping. it may contain some changes.
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen start looking up from the same sequence as in the old view.
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if there are no expunges, it's there. otherwise it's somewhere
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen before (since records can't be inserted).
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen usually there are only a few expunges, so just going downwards from
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen our initial sequence position is probably faster than binary
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen if (seq > view->index->map->hdr.messages_count)
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* everything is expunged from head. use the old record. */
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen } while (seq > 0);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* found it. use it. reference the index mapping so that the
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen returned record doesn't get invalidated after next sync. */
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen mail_index_view_ref_map(view, view->index->map);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* expuned from head. use the old record. */
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic void view_lookup_uid(struct mail_index_view *view, uint32_t seq,
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view));
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen *uid_r = MAIL_INDEX_MAP_IDX(view->map, seq-1)->uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic uint32_t mail_index_bsearch_uid(struct mail_index_view *view,
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen const struct mail_index_record *rec_base, *rec;
5ba25fa97ceebd32d8c58a2d38b0b3f7fc5e67ccTimo Sirainen right_idx = I_MIN(view->map->hdr.messages_count, uid);
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
3776ed607821b502468bdfd5a4533af3002125d1Timo Sirainen i_assert(idx < view->map->hdr.messages_count);
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we want uid or larger */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we want uid or smaller */
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainenstatic void view_lookup_seq_range(struct mail_index_view *view,
6d25922a089626f5535d51358e33d3337783a410Timo Sirainen *first_seq_r = mail_index_bsearch_uid(view, first_uid, 0, 1);
06a5ffa611efd86ffb9acc8beb0fe66e7bd844e4Timo Sirainen MAIL_INDEX_MAP_IDX(view->map, *first_seq_r-1)->uid > last_uid) {
06a5ffa611efd86ffb9acc8beb0fe66e7bd844e4Timo Sirainen /* we want the last message */
24815ed8224a0647926b49b9a1f716efb2a57148Timo Sirainen /* optimization - binary lookup only from right side: */
24815ed8224a0647926b49b9a1f716efb2a57148Timo Sirainen *last_seq_r = mail_index_bsearch_uid(view, last_uid,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic void view_lookup_first(struct mail_index_view *view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen STMT_START { if ((x) > low_uid) low_uid = x; } STMT_END
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((flags_mask & MAIL_SEEN) != 0 && (flags & MAIL_SEEN) == 0)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen LOW_UPDATE(view->map->hdr.first_unseen_uid_lowwater);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((flags_mask & MAIL_DELETED) != 0 && (flags & MAIL_DELETED) != 0)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen LOW_UPDATE(view->map->hdr.first_deleted_uid_lowwater);
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen if (!mail_index_lookup_seq(view, low_uid, &seq))
3776ed607821b502468bdfd5a4533af3002125d1Timo Sirainen for (; seq <= view->map->hdr.messages_count; seq++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((rec->flags & flags_mask) == (uint8_t)flags) {
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainenmail_index_data_lookup_keywords(struct mail_index_map *map,
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen const unsigned char *data,
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen const unsigned int *keyword_idx_map;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen /* no keywords at all in index */
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen (void)mail_index_ext_get_size(NULL, map->index->keywords_ext_id,
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen /* keyword_idx_map[] contains file => index keyword mapping */
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen keyword_idx_map = array_get(&map->keyword_idx_map, &keyword_count);
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen /* first do the quick check to see if there's keywords at all */
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen /* extra bits set in keyword bytes.
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen shouldn't happen, but just ignore. */
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainenstatic void view_lookup_keywords(struct mail_index_view *view, uint32_t seq,
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen mail_index_lookup_ext_full(view, seq, view->index->keywords_ext_id,
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen mail_index_data_lookup_keywords(map, data, keyword_idx);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenview_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen uint32_t ext_id, struct mail_index_map **map_r,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen rec = view->v.lookup_full(view, seq, map_r, expunged_r);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (!mail_index_map_get_ext_idx(*map_r, ext_id, &idx)) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen *data_r = offset == 0 ? NULL : CONST_PTR_OFFSET(rec, offset);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic void view_get_header_ext(struct mail_index_view *view,
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen /* no mapping given, use head mapping */
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (!mail_index_map_get_ext_idx(map, ext_id, &idx)) {
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen /* extension doesn't exist in this index file */
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen *data_r = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic bool view_ext_get_reset_id(struct mail_index_view *view ATTR_UNUSED,
44c5e644cb413a6559bf2d4179cbe48f9a82f366Timo Sirainen if (!mail_index_map_get_ext_idx(map, ext_id, &idx))
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid mail_index_view_close(struct mail_index_view **_view)
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainenuint32_t mail_index_view_get_messages_count(struct mail_index_view *view)
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainenmail_index_get_header(struct mail_index_view *view)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenmail_index_lookup(struct mail_index_view *view, uint32_t seq)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return mail_index_lookup_full(view, seq, &map);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenmail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return view->v.lookup_full(view, seq, map_r, &expunged);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenbool mail_index_is_expunged(struct mail_index_view *view, uint32_t seq)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen (void)view->v.lookup_full(view, seq, &map, &expunged);
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainenvoid mail_index_map_lookup_keywords(struct mail_index_map *map, uint32_t seq,
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen if (!mail_index_map_get_ext_idx(map, map->index->keywords_ext_id, &idx))
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen mail_index_data_lookup_keywords(map, data, keyword_idx);
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainenvoid mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq,
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen view->v.lookup_keywords(view, seq, keyword_idx);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainenvoid mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainenbool mail_index_lookup_seq_range(struct mail_index_view *view,
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen view->v.lookup_seq_range(view, first_uid, last_uid,
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainenbool mail_index_lookup_seq(struct mail_index_view *view,
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen view->v.lookup_seq_range(view, uid, uid, seq_r, seq_r);
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen return *seq_r != 0;
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainenvoid mail_index_lookup_first(struct mail_index_view *view,
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen view->v.lookup_first(view, flags, flags_mask, seq_r);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenvoid mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mail_index_lookup_ext_full(view, seq, ext_id, &map, data_r, expunged_r);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenvoid mail_index_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen uint32_t ext_id, struct mail_index_map **map_r,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen view->v.lookup_ext_full(view, seq, ext_id, map_r, data_r, expunged_r);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainenvoid mail_index_get_header_ext(struct mail_index_view *view, uint32_t ext_id,
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen view->v.get_header_ext(view, NULL, ext_id, data_r, data_size_r);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainenvoid mail_index_map_get_header_ext(struct mail_index_view *view,
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen view->v.get_header_ext(view, map, ext_id, data_r, data_size_r);
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainenbool mail_index_ext_get_reset_id(struct mail_index_view *view,
44c5e644cb413a6559bf2d4179cbe48f9a82f366Timo Sirainen return view->v.ext_get_reset_id(view, map, ext_id, reset_id_r);
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainenvoid mail_index_ext_get_size(struct mail_index_view *view ATTR_UNUSED,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen uint32_t *hdr_size_r, uint16_t *record_size_r,
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen if (!mail_index_map_get_ext_idx(map, ext_id, &idx)) {
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen /* extension doesn't exist in this index file */
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenstatic struct mail_index_view_vfuncs view_vfuncs = {
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainenmail_index_view_open_with_map(struct mail_index *index,
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen view->log_view = mail_transaction_log_view_open(index->log);
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen view->inconsistency_id = index->inconsistency_id;
cc6ed00c61fda24799c905e403b94a2a8c39ae5cTimo Sirainen view->log_file_expunge_seq = view->log_file_head_seq =
cc6ed00c61fda24799c905e403b94a2a8c39ae5cTimo Sirainen view->log_file_expunge_offset = view->log_file_head_offset =
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstruct mail_index_view *mail_index_view_open(struct mail_index *index)
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen return mail_index_view_open_with_map(index, index->map);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenmail_index_view_get_ext(struct mail_index_view *view, uint32_t ext_id)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (!mail_index_map_get_ext_idx(view->map, ext_id, &idx))