bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "array.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "buffer.h"
ef4d0eafab4d26bba047551db1e23ceff8aa9404Timo Sirainen#include "llist.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-view-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-transaction-log.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainenstruct mail_index_view *
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainenmail_index_view_dup_private(const struct mail_index_view *src)
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen{
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen struct mail_index_view *view;
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen struct mail_index_map *map;
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen view = i_new(struct mail_index_view, 1);
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen mail_index_view_clone(view, src);
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen map = mail_index_map_clone(view->map);
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen mail_index_unmap(&view->map);
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen view->map = map;
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen return view;
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen}
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainenvoid mail_index_view_clone(struct mail_index_view *dest,
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen const struct mail_index_view *src)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(dest);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen dest->refcount = 1;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen dest->v = src->v;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen dest->index = src->index;
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen if (src->log_view != NULL) {
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen dest->log_view =
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen mail_transaction_log_view_open(src->index->log);
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen }
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen dest->indexid = src->indexid;
e627cdc5ef30d87959f9510832427e33a2f1d84aTimo Sirainen dest->inconsistency_id = src->inconsistency_id;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen dest->map = src->map;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen if (dest->map != NULL)
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen dest->map->refcount++;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
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;
ff7257145f317d6ca44a9402427bb74c34b999a9Timo Sirainen
ff7257145f317d6ca44a9402427bb74c34b999a9Timo Sirainen i_array_init(&dest->module_contexts,
ff7257145f317d6ca44a9402427bb74c34b999a9Timo Sirainen I_MIN(5, mail_index_module_register.id));
1727610dbc69920b7f0d0622b4e5d7127c59093dTimo Sirainen
ef4d0eafab4d26bba047551db1e23ceff8aa9404Timo Sirainen DLLIST_PREPEND(&dest->index->views, dest);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainenvoid mail_index_view_ref(struct mail_index_view *view)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen{
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen view->refcount++;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen}
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic void view_close(struct mail_index_view *view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen i_assert(view->refcount == 0);
ef4d0eafab4d26bba047551db1e23ceff8aa9404Timo Sirainen i_assert(view->index->views != NULL);
1727610dbc69920b7f0d0622b4e5d7127c59093dTimo Sirainen
ef4d0eafab4d26bba047551db1e23ceff8aa9404Timo Sirainen DLLIST_REMOVE(&view->index->views, view);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mail_transaction_log_view_close(&view->log_view);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen if (array_is_created(&view->syncs_hidden))
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen array_free(&view->syncs_hidden);
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen mail_index_unmap(&view->map);
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen if (array_is_created(&view->map_refs)) {
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen mail_index_view_unref_maps(view);
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen array_free(&view->map_refs);
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen }
ff7257145f317d6ca44a9402427bb74c34b999a9Timo Sirainen array_free(&view->module_contexts);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(view);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenbool mail_index_view_is_inconsistent(struct mail_index_view *view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen if (view->index->indexid != view->indexid ||
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen view->index->inconsistency_id != view->inconsistency_id)
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen view->inconsistent = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return view->inconsistent;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_index *mail_index_view_get_index(struct mail_index_view *view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return view->index;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainenunsigned int
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainenmail_index_view_get_transaction_count(struct mail_index_view *view)
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen{
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen i_assert(view->transactions >= 0);
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen return view->transactions;
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen}
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_view_transaction_ref(struct mail_index_view *view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->transactions++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_view_transaction_unref(struct mail_index_view *view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(view->transactions > 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->transactions--;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainenstatic void mail_index_view_ref_map(struct mail_index_view *view,
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen struct mail_index_map *map)
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen{
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen struct mail_index_map *const *maps;
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen unsigned int i, count;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen if (array_is_created(&view->map_refs)) {
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen maps = array_get(&view->map_refs, &count);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen /* if map is already referenced, do nothing */
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen for (i = 0; i < count; i++) {
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen if (maps[i] == map)
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen return;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen }
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen } else {
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen i_array_init(&view->map_refs, 4);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen }
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* reference the given mapping. the reference is dropped when the view
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen is synchronized or closed. */
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen map->refcount++;
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen array_append(&view->map_refs, &map, 1);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen}
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainenvoid mail_index_view_unref_maps(struct mail_index_view *view)
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct mail_index_map **maps;
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen unsigned int i, count;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen if (!array_is_created(&view->map_refs))
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen return;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen maps = array_get_modifiable(&view->map_refs, &count);
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen for (i = 0; i < count; i++)
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen mail_index_unmap(&maps[i]);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen array_clear(&view->map_refs);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen}
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic uint32_t view_get_messages_count(struct mail_index_view *view)
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen{
3776ed607821b502468bdfd5a4533af3002125d1Timo Sirainen return view->map->hdr.messages_count;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen}
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainenstatic const struct mail_index_header *
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenview_get_header(struct mail_index_view *view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
3776ed607821b502468bdfd5a4533af3002125d1Timo Sirainen return &view->map->hdr;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
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)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen static struct mail_index_record broken_rec;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_map *map;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen const struct mail_index_record *rec, *head_rec;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* look up the record */
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody rec = MAIL_INDEX_REC_AT_SEQ(view->map, seq);
24ec3e51a1bd7aaf09c92a7ff7498e225796d7e0Timo Sirainen if (unlikely(rec->uid == 0)) {
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen if (!view->inconsistent) {
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen mail_index_set_error(view->index,
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen "Corrupted Index file %s: Record [%u].uid=0",
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen view->index->filepath, seq);
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen (void)mail_index_fsck(view->index);
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen view->inconsistent = TRUE;
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen }
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen /* we'll need to return something so the caller doesn't crash */
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen *map_r = view->map;
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen if (expunged_r != NULL)
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen *expunged_r = TRUE;
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen return &broken_rec;
06fb99af33bd380b382d2d4f2994cf9a5bf0bbaeTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (view->map == view->index->map) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* view's mapping is latest. we can use it directly. */
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen *map_r = view->map;
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen if (expunged_r != NULL)
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen *expunged_r = FALSE;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return rec;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen /* look up the record from head mapping. it may contain some changes.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
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).
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen
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
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen search. */
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen if (seq > view->index->map->hdr.messages_count)
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen seq = view->index->map->hdr.messages_count;
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen if (seq == 0) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* everything is expunged from head. use the old record. */
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen *map_r = view->map;
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen if (expunged_r != NULL)
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen *expunged_r = TRUE;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return rec;
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen }
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen map = view->index->map;
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen do {
c308d70af9d1465b33e95e03052fe10cd40231b1Phil Carmody head_rec = MAIL_INDEX_REC_AT_SEQ(map, seq);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if (head_rec->uid <= rec->uid)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
c308d70af9d1465b33e95e03052fe10cd40231b1Phil Carmody } while (--seq > 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if (head_rec->uid == rec->uid) {
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);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen *map_r = view->index->map;
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen if (expunged_r != NULL)
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen *expunged_r = FALSE;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return head_rec;
b5ea11802f2bafbec06282a7b3b6704dc5fae584Timo Sirainen } else {
19557f192d37cd54a1a090a8a26d9d47265e4413Aki Tuomi /* expunged from head. use the old record. */
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen *map_r = view->map;
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen if (expunged_r != NULL)
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen *expunged_r = TRUE;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return rec;
b5ea11802f2bafbec06282a7b3b6704dc5fae584Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic void view_lookup_uid(struct mail_index_view *view, uint32_t seq,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen uint32_t *uid_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody *uid_r = MAIL_INDEX_REC_AT_SEQ(view->map, seq)->uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainenstatic void view_lookup_seq_range(struct mail_index_view *view,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen uint32_t first_uid, uint32_t last_uid,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen uint32_t *first_seq_r, uint32_t *last_seq_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen mail_index_map_lookup_seq_range(view->map, first_uid, last_uid,
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen first_seq_r, last_seq_r);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic void view_lookup_first(struct mail_index_view *view,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen enum mail_flags flags, uint8_t flags_mask,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen uint32_t *seq_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define LOW_UPDATE(x) \
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen STMT_START { if ((x) > low_uid) low_uid = x; } STMT_END
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen const struct mail_index_header *hdr = &view->map->hdr;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_index_record *rec;
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen uint32_t seq, seq2, low_uid = 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *seq_r = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((flags_mask & MAIL_SEEN) != 0 && (flags & MAIL_SEEN) == 0)
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen LOW_UPDATE(hdr->first_unseen_uid_lowwater);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((flags_mask & MAIL_DELETED) != 0 && (flags & MAIL_DELETED) != 0)
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen LOW_UPDATE(hdr->first_deleted_uid_lowwater);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (low_uid == 1)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen seq = 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else {
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen if (!mail_index_lookup_seq_range(view, low_uid, hdr->next_uid,
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen &seq, &seq2))
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen i_assert(hdr->messages_count <= view->map->rec_map->records_count);
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen for (; seq <= hdr->messages_count; seq++) {
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody rec = MAIL_INDEX_REC_AT_SEQ(view->map, seq);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((rec->flags & flags_mask) == (uint8_t)flags) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *seq_r = seq;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainenstatic void
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainenmail_index_data_lookup_keywords(struct mail_index_map *map,
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen const unsigned char *data,
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen ARRAY_TYPE(keyword_indexes) *keyword_idx)
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen{
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen const unsigned int *keyword_idx_map;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen unsigned int i, j, keyword_count, index_idx;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen uint32_t idx, hdr_size;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen uint16_t record_size, record_align;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen array_clear(keyword_idx);
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen if (data == NULL) {
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen /* no keywords at all in index */
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen return;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen }
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen (void)mail_index_ext_get_size(map, map->index->keywords_ext_id,
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen &hdr_size, &record_size,
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen &record_align);
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen /* keyword_idx_map[] contains file => index keyword mapping */
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen if (!array_is_created(&map->keyword_idx_map))
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen return;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen keyword_idx_map = array_get(&map->keyword_idx_map, &keyword_count);
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen for (i = 0; i < record_size; i++) {
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen /* first do the quick check to see if there's keywords at all */
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen if (data[i] == 0)
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen continue;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen idx = i * CHAR_BIT;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen for (j = 0; j < CHAR_BIT; j++, idx++) {
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen if ((data[i] & (1 << j)) == 0)
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen continue;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen if (idx >= keyword_count) {
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen /* extra bits set in keyword bytes.
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen shouldn't happen, but just ignore. */
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen break;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen }
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen index_idx = keyword_idx_map[idx];
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen array_append(keyword_idx, &index_idx, 1);
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen }
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen }
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen}
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainenstatic void view_lookup_keywords(struct mail_index_view *view, uint32_t seq,
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen ARRAY_TYPE(keyword_indexes) *keyword_idx)
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen{
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen struct mail_index_map *map;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen const void *data;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen mail_index_lookup_ext_full(view, seq, view->index->keywords_ext_id,
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen &map, &data, NULL);
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen mail_index_data_lookup_keywords(map, data, keyword_idx);
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen}
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainenstatic const void *
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainenview_map_lookup_ext_full(struct mail_index_map *map,
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen const struct mail_index_record *rec, uint32_t ext_id)
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen{
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen const struct mail_index_ext *ext;
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen uint32_t idx;
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen if (!mail_index_map_get_ext_idx(map, ext_id, &idx))
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen return NULL;
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen ext = array_idx(&map->extensions, idx);
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen return ext->record_offset == 0 ? NULL :
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen CONST_PTR_OFFSET(rec, ext->record_offset);
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen}
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic void
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,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen const void **data_r, bool *expunged_r)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen const struct mail_index_record *rec;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen rec = view->v.lookup_full(view, seq, map_r, expunged_r);
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen *data_r = view_map_lookup_ext_full(*map_r, rec, ext_id);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic void view_get_header_ext(struct mail_index_view *view,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen struct mail_index_map *map, uint32_t ext_id,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen const void **data_r, size_t *data_size_r)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const struct mail_index_ext *ext;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen uint32_t idx;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen if (map == NULL) {
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen /* no mapping given, use head mapping */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen map = view->index->map;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (!mail_index_map_get_ext_idx(map, ext_id, &idx)) {
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen /* extension doesn't exist in this index file */
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen *data_r = NULL;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen *data_size_r = 0;
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen return;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ext = array_idx(&map->extensions, idx);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen *data_r = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen *data_size_r = ext->hdr_size;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic bool view_ext_get_reset_id(struct mail_index_view *view ATTR_UNUSED,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen struct mail_index_map *map,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen uint32_t ext_id, uint32_t *reset_id_r)
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen{
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen const struct mail_index_ext *ext;
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen uint32_t idx;
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen
44c5e644cb413a6559bf2d4179cbe48f9a82f366Timo Sirainen if (!mail_index_map_get_ext_idx(map, ext_id, &idx))
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen return FALSE;
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen
44c5e644cb413a6559bf2d4179cbe48f9a82f366Timo Sirainen ext = array_idx(&map->extensions, idx);
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen *reset_id_r = ext->reset_id;
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen return TRUE;
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen}
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid mail_index_view_close(struct mail_index_view **_view)
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct mail_index_view *view = *_view;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen *_view = NULL;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (--view->refcount > 0)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen return;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
c3b36993785d9567a63bdad1933031060c9460cfTimo Sirainen i_assert(view->transactions == 0);
c3b36993785d9567a63bdad1933031060c9460cfTimo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen view->v.close(view);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen}
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainenuint32_t mail_index_view_get_messages_count(struct mail_index_view *view)
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen{
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen return view->v.get_messages_count(view);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen}
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainenconst struct mail_index_header *
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainenmail_index_get_header(struct mail_index_view *view)
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen{
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen return view->v.get_header(view);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen}
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenconst struct mail_index_record *
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenmail_index_lookup(struct mail_index_view *view, uint32_t seq)
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen{
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen struct mail_index_map *map;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return mail_index_lookup_full(view, seq, &map);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen}
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenconst struct mail_index_record *
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenmail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen struct mail_index_map **map_r)
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen{
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen return view->v.lookup_full(view, seq, map_r, NULL);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen}
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenbool mail_index_is_expunged(struct mail_index_view *view, uint32_t seq)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen{
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen struct mail_index_map *map;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen bool expunged;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen (void)view->v.lookup_full(view, seq, &map, &expunged);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return expunged;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen}
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainenvoid mail_index_map_lookup_keywords(struct mail_index_map *map, uint32_t seq,
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen ARRAY_TYPE(keyword_indexes) *keyword_idx)
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen{
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen const struct mail_index_ext *ext;
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen const struct mail_index_record *rec;
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen const void *data;
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen uint32_t idx;
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen if (!mail_index_map_get_ext_idx(map, map->index->keywords_ext_id, &idx))
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen data = NULL;
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen else {
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody rec = MAIL_INDEX_REC_AT_SEQ(map, seq);
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen ext = array_idx(&map->extensions, idx);
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen data = ext->record_offset == 0 ? NULL :
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen CONST_PTR_OFFSET(rec, ext->record_offset);
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen }
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen mail_index_data_lookup_keywords(map, data, keyword_idx);
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen}
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainenvoid mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq,
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen ARRAY_TYPE(keyword_indexes) *keyword_idx)
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen{
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen view->v.lookup_keywords(view, seq, keyword_idx);
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen}
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainenvoid mail_index_lookup_view_flags(struct mail_index_view *view, uint32_t seq,
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen enum mail_flags *flags_r,
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen ARRAY_TYPE(keyword_indexes) *keyword_idx)
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen{
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen const struct mail_index_record *rec;
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen const unsigned char *keyword_data;
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view));
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody rec = MAIL_INDEX_REC_AT_SEQ(view->map, seq);
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen *flags_r = rec->flags;
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen keyword_data = view_map_lookup_ext_full(view->map, rec,
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen view->index->keywords_ext_id);
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen mail_index_data_lookup_keywords(view->map, keyword_data, keyword_idx);
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen}
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainenvoid mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen uint32_t *uid_r)
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen{
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen view->v.lookup_uid(view, seq, uid_r);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen}
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainenbool mail_index_lookup_seq_range(struct mail_index_view *view,
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen uint32_t first_uid, uint32_t last_uid,
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen uint32_t *first_seq_r, uint32_t *last_seq_r)
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen{
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen view->v.lookup_seq_range(view, first_uid, last_uid,
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen first_seq_r, last_seq_r);
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen return *first_seq_r != 0;
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen}
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainenbool mail_index_lookup_seq(struct mail_index_view *view,
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen uint32_t uid, uint32_t *seq_r)
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen{
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen view->v.lookup_seq_range(view, uid, uid, seq_r, seq_r);
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen return *seq_r != 0;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen}
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainenvoid mail_index_lookup_first(struct mail_index_view *view,
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen enum mail_flags flags, uint8_t flags_mask,
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen uint32_t *seq_r)
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen{
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen view->v.lookup_first(view, flags, flags_mask, seq_r);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen}
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenvoid mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen uint32_t ext_id, const void **data_r,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen bool *expunged_r)
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct mail_index_map *map;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mail_index_lookup_ext_full(view, seq, ext_id, &map, data_r, expunged_r);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
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 const void **data_r, bool *expunged_r)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen view->v.lookup_ext_full(view, seq, ext_id, map_r, data_r, expunged_r);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainenvoid mail_index_get_header_ext(struct mail_index_view *view, uint32_t ext_id,
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen const void **data_r, size_t *data_size_r)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen view->v.get_header_ext(view, NULL, ext_id, data_r, data_size_r);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainenvoid mail_index_map_get_header_ext(struct mail_index_view *view,
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen struct mail_index_map *map, uint32_t ext_id,
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen const void **data_r, size_t *data_size_r)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen view->v.get_header_ext(view, map, ext_id, data_r, data_size_r);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen}
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainenbool mail_index_ext_get_reset_id(struct mail_index_view *view,
44c5e644cb413a6559bf2d4179cbe48f9a82f366Timo Sirainen struct mail_index_map *map,
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen uint32_t ext_id, uint32_t *reset_id_r)
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen{
44c5e644cb413a6559bf2d4179cbe48f9a82f366Timo Sirainen return view->v.ext_get_reset_id(view, map, ext_id, reset_id_r);
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen}
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenvoid mail_index_ext_get_size(struct mail_index_map *map, uint32_t ext_id,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen uint32_t *hdr_size_r, uint16_t *record_size_r,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen uint16_t *record_align_r)
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen{
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen const struct mail_index_ext *ext;
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen uint32_t idx;
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen i_assert(map != NULL);
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen if (!mail_index_map_get_ext_idx(map, ext_id, &idx)) {
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen /* extension doesn't exist in this index file */
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen *hdr_size_r = 0;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen *record_size_r = 0;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen *record_align_r = 0;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return;
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen }
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen ext = array_idx(&map->extensions, idx);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen *hdr_size_r = ext->hdr_size;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen *record_size_r = ext->record_size;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen *record_align_r = ext->record_align;
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen}
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenstatic struct mail_index_view_vfuncs view_vfuncs = {
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen view_close,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen view_get_messages_count,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen view_get_header,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen view_lookup_full,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen view_lookup_uid,
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen view_lookup_seq_range,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen view_lookup_first,
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen view_lookup_keywords,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen view_lookup_ext_full,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen view_get_header_ext,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen view_ext_get_reset_id
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen};
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstruct mail_index_view *
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainenmail_index_view_open_with_map(struct mail_index *index,
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen struct mail_index_map *map)
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen{
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen struct mail_index_view *view;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen view = i_new(struct mail_index_view, 1);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen view->refcount = 1;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen view->v = view_vfuncs;
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen view->index = index;
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen view->log_view = mail_transaction_log_view_open(index->log);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen view->indexid = index->indexid;
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen view->inconsistency_id = index->inconsistency_id;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen view->map = map;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen view->map->refcount++;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
cc6ed00c61fda24799c905e403b94a2a8c39ae5cTimo Sirainen view->log_file_expunge_seq = view->log_file_head_seq =
cc6ed00c61fda24799c905e403b94a2a8c39ae5cTimo Sirainen view->map->hdr.log_file_seq;
cc6ed00c61fda24799c905e403b94a2a8c39ae5cTimo Sirainen view->log_file_expunge_offset = view->log_file_head_offset =
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen view->map->hdr.log_file_head_offset;
ff7257145f317d6ca44a9402427bb74c34b999a9Timo Sirainen
ff7257145f317d6ca44a9402427bb74c34b999a9Timo Sirainen i_array_init(&view->module_contexts,
ff7257145f317d6ca44a9402427bb74c34b999a9Timo Sirainen I_MIN(5, mail_index_module_register.id));
ef4d0eafab4d26bba047551db1e23ceff8aa9404Timo Sirainen DLLIST_PREPEND(&index->views, view);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen return view;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
5ea06115cb60413b62ffb58ffdd62786fec6a316Timo Sirainen#undef mail_index_view_open
5ea06115cb60413b62ffb58ffdd62786fec6a316Timo Sirainenstruct mail_index_view *
5ea06115cb60413b62ffb58ffdd62786fec6a316Timo Sirainenmail_index_view_open(struct mail_index *index,
5ea06115cb60413b62ffb58ffdd62786fec6a316Timo Sirainen const char *source_filename, unsigned int source_linenum)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
5ea06115cb60413b62ffb58ffdd62786fec6a316Timo Sirainen struct mail_index_view *view;
5ea06115cb60413b62ffb58ffdd62786fec6a316Timo Sirainen
5ea06115cb60413b62ffb58ffdd62786fec6a316Timo Sirainen view = mail_index_view_open_with_map(index, index->map);
5ea06115cb60413b62ffb58ffdd62786fec6a316Timo Sirainen /* these can be used to debug mail_index_view_close() leaks */
5ea06115cb60413b62ffb58ffdd62786fec6a316Timo Sirainen view->source_filename = source_filename;
5ea06115cb60413b62ffb58ffdd62786fec6a316Timo Sirainen view->source_linenum = source_linenum;
5ea06115cb60413b62ffb58ffdd62786fec6a316Timo Sirainen return view;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenconst struct mail_index_ext *
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenmail_index_view_get_ext(struct mail_index_view *view, uint32_t ext_id)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen uint32_t idx;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (!mail_index_map_get_ext_idx(view->map, ext_id, &idx))
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen return NULL;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return array_idx(&view->map->extensions, idx);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}