mail-index-view.c revision e627cdc5ef30d87959f9510832427e33a2f1d84a
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#include "lib.h"
6157a322f2ac1ea1332d9003ecb0b11466aa8fe7Timo Sirainen#include "array.h"
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#include "buffer.h"
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#include "mail-index-view-private.h"
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen#include "mail-transaction-log.h"
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenvoid mail_index_view_clone(struct mail_index_view *dest,
c4cfee078c4a185b5ba8f0c55f51275b7e885b2cTimo Sirainen const struct mail_index_view *src)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen memset(dest, 0, sizeof(dest));
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen dest->refcount = 1;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen dest->v = src->v;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen dest->index = src->index;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen if (src->log_view != NULL) {
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen dest->log_view =
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen mail_transaction_log_view_open(src->index->log);
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen }
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen dest->indexid = src->indexid;
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen dest->inconsistency_id = src->inconsistency_id;
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen dest->map = src->map;
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen if (dest->map != NULL)
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen dest->map->refcount++;
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen
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;
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen i_array_init(&dest->module_contexts,
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen I_MIN(5, mail_index_module_register.id));
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen}
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainenvoid mail_index_view_ref(struct mail_index_view *view)
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen{
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen view->refcount++;
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen}
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainenstatic void _view_close(struct mail_index_view *view)
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen{
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen i_assert(view->refcount == 0);
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen mail_transaction_log_view_close(&view->log_view);
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen if (array_is_created(&view->syncs_hidden))
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen array_free(&view->syncs_hidden);
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen mail_index_unmap(&view->map);
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen if (array_is_created(&view->map_refs)) {
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen mail_index_view_unref_maps(view);
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen array_free(&view->map_refs);
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen }
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen array_free(&view->module_contexts);
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen i_free(view);
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen}
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainenbool mail_index_view_is_inconsistent(struct mail_index_view *view)
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen{
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen if (view->index->indexid != view->indexid ||
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen view->index->inconsistency_id != view->inconsistency_id)
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen view->inconsistent = TRUE;
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen return view->inconsistent;
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen}
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainenstruct mail_index *mail_index_view_get_index(struct mail_index_view *view)
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return view->index;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mail_index_view_transaction_ref(struct mail_index_view *view)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
8d6cb44a0161d88743756733f83c4fb278485987Timo Sirainen view->transactions++;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mail_index_view_transaction_unref(struct mail_index_view *view)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_assert(view->transactions > 0);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen view->transactions--;
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen}
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void mail_index_view_ref_map(struct mail_index_view *view,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mail_index_map *map)
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen{
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen struct mail_index_map *const *maps;
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen unsigned int i, count;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (array_is_created(&view->map_refs)) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen maps = array_get(&view->map_refs, &count);
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen /* if map is already referenced, do nothing */
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen for (i = 0; i < count; i++) {
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen if (maps[i] == map)
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen return;
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen }
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen } else {
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen i_array_init(&view->map_refs, 4);
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen }
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen /* reference the given mapping. the reference is dropped when the view
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen is synchronized or closed. */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen map->refcount++;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen array_append(&view->map_refs, &map, 1);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mail_index_view_unref_maps(struct mail_index_view *view)
0cea9b1f4fa0495a48f5f097e40492517d67e1baTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mail_index_map **maps;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen unsigned int i, count;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
0cea9b1f4fa0495a48f5f097e40492517d67e1baTimo Sirainen if (!array_is_created(&view->map_refs))
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen maps = array_get_modifiable(&view->map_refs, &count);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen for (i = 0; i < count; i++)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail_index_unmap(&maps[i]);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen array_clear(&view->map_refs);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic uint32_t _view_get_messages_count(struct mail_index_view *view)
8d6cb44a0161d88743756733f83c4fb278485987Timo Sirainen{
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen return view->map->hdr.messages_count;
8d6cb44a0161d88743756733f83c4fb278485987Timo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic const struct mail_index_header *
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen_view_get_header(struct mail_index_view *view)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return &view->map->hdr;
8d6cb44a0161d88743756733f83c4fb278485987Timo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
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{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen static struct mail_index_record broken_rec;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mail_index_map *map;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const struct mail_index_record *rec, *head_rec;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view));
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* look up the record */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen rec = MAIL_INDEX_MAP_IDX(view->map, seq-1);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (rec->uid == 0) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (!view->inconsistent) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail_index_set_error(view->index,
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen "Corrupted Index file %s: Record [%u].uid=0",
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen view->index->filepath, seq);
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen (void)mail_index_fsck(view->index);
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen view->inconsistent = TRUE;
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen }
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen /* we'll need to return something so the caller doesn't crash */
bc793bfcee945ce8871edfa298fe7235744425b6Timo Sirainen *map_r = view->map;
bc793bfcee945ce8871edfa298fe7235744425b6Timo Sirainen *expunged_r = TRUE;
bc793bfcee945ce8871edfa298fe7235744425b6Timo Sirainen return &broken_rec;
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen }
ea4ca37ec14913354f3a0deebc0df96097eb9468Timo Sirainen if (view->map == view->index->map) {
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen /* view's mapping is latest. we can use it directly. */
ea4ca37ec14913354f3a0deebc0df96097eb9468Timo Sirainen *map_r = view->map;
ea4ca37ec14913354f3a0deebc0df96097eb9468Timo Sirainen *expunged_r = FALSE;
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen return rec;
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen }
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen /* look up the record from head mapping. it may contain some changes.
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen
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).
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
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
abb83d133dd082527d500916fca66a72fbbbaa8dTimo Sirainen search. */
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen if (seq > view->index->map->hdr.messages_count)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen seq = view->index->map->hdr.messages_count;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (seq == 0) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* everything is expunged from head. use the old record. */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *map_r = view->map;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *expunged_r = TRUE;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return rec;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen map = view->index->map;
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen do {
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen seq--;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen head_rec = MAIL_INDEX_MAP_IDX(map, seq);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen if (head_rec->uid <= rec->uid)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen break;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen } while (seq > 0);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen if (head_rec->uid == rec->uid) {
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 *map_r = view->index->map;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen *expunged_r = FALSE;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen return head_rec;
c4cfee078c4a185b5ba8f0c55f51275b7e885b2cTimo Sirainen } else {
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen /* expuned from head. use the old record. */
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen *map_r = view->map;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen *expunged_r = TRUE;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen return rec;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen }
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen}
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainenstatic void _view_lookup_uid(struct mail_index_view *view, uint32_t seq,
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen uint32_t *uid_r)
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen{
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view));
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen *uid_r = MAIL_INDEX_MAP_IDX(view->map, seq-1)->uid;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen}
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainenstatic uint32_t mail_index_bsearch_uid(struct mail_index_view *view,
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen uint32_t uid, uint32_t left_idx,
114a0f74e0f825c6bd8aeadfafb248a030762a1fTimo Sirainen int nearest_side)
c4cfee078c4a185b5ba8f0c55f51275b7e885b2cTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const struct mail_index_record *rec_base, *rec;
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen uint32_t idx, right_idx, record_size;
abb83d133dd082527d500916fca66a72fbbbaa8dTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_assert(view->map->hdr.messages_count <=
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen view->map->rec_map->records_count);
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen if (uid == 1) {
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen /* optimization: the message can be only the first one */
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen return 1;
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen }
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen rec_base = view->map->rec_map->records;
abb83d133dd082527d500916fca66a72fbbbaa8dTimo Sirainen record_size = view->map->hdr.record_size;
abb83d133dd082527d500916fca66a72fbbbaa8dTimo Sirainen
abb83d133dd082527d500916fca66a72fbbbaa8dTimo Sirainen idx = left_idx;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen right_idx = view->map->hdr.messages_count;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen while (left_idx < right_idx) {
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen idx = (left_idx + right_idx) / 2;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen if (rec->uid < uid)
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen left_idx = idx+1;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen else if (rec->uid > uid)
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen right_idx = idx;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen else
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen break;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_assert(idx < view->map->hdr.messages_count);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (rec->uid != uid) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (nearest_side > 0) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* we want uid or larger */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return rec->uid > uid ? idx+1 :
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen (idx == view->map->hdr.messages_count-1 ?
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen 0 : idx+2);
11768c622a8e5aaf0e5d9b3c9a872867b62b4830Timo Sirainen } else {
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen /* we want uid or smaller */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return rec->uid < uid ? idx + 1 : idx;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return idx+1;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void _view_lookup_uid_range(struct mail_index_view *view,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen uint32_t first_uid, uint32_t last_uid,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen uint32_t *first_seq_r, uint32_t *last_seq_r)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_assert(first_uid > 0);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_assert(first_uid <= last_uid);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (view->map->hdr.messages_count == 0) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *first_seq_r = *last_seq_r = 0;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *first_seq_r = mail_index_bsearch_uid(view, first_uid, 0, 1);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (*first_seq_r == 0 ||
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen MAIL_INDEX_MAP_IDX(view->map, *first_seq_r-1)->uid > last_uid) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *first_seq_r = *last_seq_r = 0;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
11768c622a8e5aaf0e5d9b3c9a872867b62b4830Timo Sirainen if (last_uid >= view->map->hdr.next_uid-1) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* we want the last message */
11768c622a8e5aaf0e5d9b3c9a872867b62b4830Timo Sirainen last_uid = view->map->hdr.next_uid-1;
265e9d8457aa5ce01b7aad954632aed8c36deeb8Timo Sirainen if (first_uid > last_uid) {
265e9d8457aa5ce01b7aad954632aed8c36deeb8Timo Sirainen *first_seq_r = *last_seq_r = 0;
265e9d8457aa5ce01b7aad954632aed8c36deeb8Timo Sirainen return;
265e9d8457aa5ce01b7aad954632aed8c36deeb8Timo Sirainen }
11768c622a8e5aaf0e5d9b3c9a872867b62b4830Timo Sirainen
265e9d8457aa5ce01b7aad954632aed8c36deeb8Timo Sirainen *last_seq_r = view->map->hdr.messages_count;
265e9d8457aa5ce01b7aad954632aed8c36deeb8Timo Sirainen return;
265e9d8457aa5ce01b7aad954632aed8c36deeb8Timo Sirainen }
11768c622a8e5aaf0e5d9b3c9a872867b62b4830Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (first_uid == last_uid)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen *last_seq_r = *first_seq_r;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen else {
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen /* optimization - binary lookup only from right side: */
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen *last_seq_r = mail_index_bsearch_uid(view, last_uid,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen *first_seq_r - 1, -1);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen }
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen i_assert(*last_seq_r >= *first_seq_r);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen}
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void _view_lookup_first(struct mail_index_view *view,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen enum mail_flags flags, uint8_t flags_mask,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen uint32_t *seq_r)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#define LOW_UPDATE(x) \
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen STMT_START { if ((x) > low_uid) low_uid = x; } STMT_END
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen const struct mail_index_record *rec;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen uint32_t seq, low_uid = 1;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *seq_r = 0;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
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);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (low_uid == 1)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen seq = 1;
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen else {
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen mail_index_lookup_uid_range(view, low_uid, low_uid,
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen &seq, &seq);
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen if (seq == 0)
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen return;
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen }
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen i_assert(view->map->hdr.messages_count <=
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen view->map->rec_map->records_count);
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen for (; seq <= view->map->hdr.messages_count; seq++) {
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen rec = MAIL_INDEX_MAP_IDX(view->map, seq-1);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen if ((rec->flags & flags_mask) == (uint8_t)flags) {
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen *seq_r = seq;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen break;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen }
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen }
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen}
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainenstatic void
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 const void **data_r, bool *expunged_r)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen{
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen const struct mail_index_ext *ext;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen const struct mail_index_record *rec;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen uint32_t idx, offset;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
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)) {
8e574a603c2c02105b073906a7ca91904271b80eTimo Sirainen *data_r = NULL;
8e574a603c2c02105b073906a7ca91904271b80eTimo Sirainen return;
8e574a603c2c02105b073906a7ca91904271b80eTimo Sirainen }
8e574a603c2c02105b073906a7ca91904271b80eTimo Sirainen
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen ext = array_idx(&(*map_r)->extensions, idx);
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen offset = ext->record_offset;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *data_r = offset == 0 ? NULL : CONST_PTR_OFFSET(rec, offset);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainenstatic void _view_get_header_ext(struct mail_index_view *view,
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen struct mail_index_map *map, uint32_t ext_id,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen const void **data_r, size_t *data_size_r)
9c4c535b86e9473ad97c6e9242ed84f3d9d69d0dTimo Sirainen{
9c4c535b86e9473ad97c6e9242ed84f3d9d69d0dTimo Sirainen const struct mail_index_ext *ext;
9c4c535b86e9473ad97c6e9242ed84f3d9d69d0dTimo Sirainen uint32_t idx;
9c4c535b86e9473ad97c6e9242ed84f3d9d69d0dTimo Sirainen
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen if (map == NULL) {
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen /* no mapping given, use head mapping */
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen map = view->index->map;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (!mail_index_map_get_ext_idx(map, ext_id, &idx)) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* extension doesn't exist in this index file */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *data_r = NULL;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen *data_size_r = 0;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen return;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen }
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen ext = array_idx(&map->extensions, idx);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen *data_r = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen *data_size_r = ext->hdr_size;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen}
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenstatic bool _view_ext_get_reset_id(struct mail_index_view *view __attr_unused__,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen struct mail_index_map *map,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen uint32_t ext_id, uint32_t *reset_id_r)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen{
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen const struct mail_index_ext *ext;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen uint32_t idx;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen if (!mail_index_map_get_ext_idx(map, ext_id, &idx))
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen return FALSE;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen ext = array_idx(&map->extensions, idx);
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen *reset_id_r = ext->reset_id;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen return TRUE;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen}
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainenvoid mail_index_view_close(struct mail_index_view **_view)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen{
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen struct mail_index_view *view = *_view;
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen *_view = NULL;
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen if (--view->refcount > 0)
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen return;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen i_assert(view->transactions == 0);
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen view->v.close(view);
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen}
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainenuint32_t mail_index_view_get_messages_count(struct mail_index_view *view)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen{
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen return view->v.get_messages_count(view);
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen}
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainenconst struct mail_index_header *
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainenmail_index_get_header(struct mail_index_view *view)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen{
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen return view->v.get_header(view);
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen}
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainenconst struct mail_index_record *
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainenmail_index_lookup(struct mail_index_view *view, uint32_t seq)
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen{
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen struct mail_index_map *map;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen return mail_index_lookup_full(view, seq, &map);
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen}
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenconst struct mail_index_record *
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenmail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen struct mail_index_map **map_r)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen{
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen bool expunged;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen return view->v.lookup_full(view, seq, map_r, &expunged);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen}
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenbool mail_index_is_expunged(struct mail_index_view *view, uint32_t seq)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen{
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen struct mail_index_map *map;
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen bool expunged;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen (void)view->v.lookup_full(view, seq, &map, &expunged);
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen return expunged;
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen}
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainenvoid mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq,
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen ARRAY_TYPE(keyword_indexes) *keyword_idx)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen{
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen struct mail_index_map *map;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen const void *data;
2c20ffcb5bb1ccdfdcd0b0ff0c7296f65b990362Timo Sirainen const unsigned char *keyword_data;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen const unsigned int *keyword_idx_map;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen unsigned int i, j, keyword_count, index_idx;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen uint32_t ext_id, idx;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen uint16_t record_size;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
114a0f74e0f825c6bd8aeadfafb248a030762a1fTimo Sirainen array_clear(keyword_idx);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* get the keywords data. */
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen ext_id = view->index->keywords_ext_id;
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen mail_index_lookup_ext_full(view, seq, ext_id, &map, &data, NULL);
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen if (data == NULL) {
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen /* no keywords at all in index */
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen return;
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen }
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen keyword_data = data;
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen (void)mail_index_ext_get_size(view, ext_id, map, NULL,
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen &record_size, NULL);
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen /* keyword_idx_map[] contains file => index keyword mapping */
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen if (!array_is_created(&map->keyword_idx_map))
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen return;
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen keyword_idx_map = array_get(&map->keyword_idx_map, &keyword_count);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen for (i = 0, idx = 0; i < record_size; i++) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* first do the quick check to see if there's keywords at all */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (keyword_data[i] == 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen continue;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen idx = i * CHAR_BIT;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen for (j = 0; j < CHAR_BIT; j++, idx++) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if ((keyword_data[i] & (1 << j)) == 0)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen continue;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (idx >= keyword_count) {
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen /* extra bits set in keyword bytes.
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen shouldn't happen, but just ignore. */
6157a322f2ac1ea1332d9003ecb0b11466aa8fe7Timo Sirainen break;
6157a322f2ac1ea1332d9003ecb0b11466aa8fe7Timo Sirainen }
6157a322f2ac1ea1332d9003ecb0b11466aa8fe7Timo Sirainen
6157a322f2ac1ea1332d9003ecb0b11466aa8fe7Timo Sirainen index_idx = keyword_idx_map[idx];
6157a322f2ac1ea1332d9003ecb0b11466aa8fe7Timo Sirainen array_append(keyword_idx, &index_idx, 1);
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen }
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen }
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen uint32_t *uid_r)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen{
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen view->v.lookup_uid(view, seq, uid_r);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen}
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainenvoid mail_index_lookup_uid_range(struct mail_index_view *view,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen uint32_t first_uid, uint32_t last_uid,
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen uint32_t *first_seq_r, uint32_t *last_seq_r)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen{
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen view->v.lookup_uid_range(view, first_uid, last_uid,
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen first_seq_r, last_seq_r);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen}
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenvoid mail_index_lookup_first(struct mail_index_view *view,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen enum mail_flags flags, uint8_t flags_mask,
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen uint32_t *seq_r)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen view->v.lookup_first(view, flags, flags_mask, seq_r);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen uint32_t ext_id, const void **data_r,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen bool *expunged_r)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen{
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen struct mail_index_map *map;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen mail_index_lookup_ext_full(view, seq, ext_id, &map, data_r, expunged_r);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
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 const void **data_r, bool *expunged_r)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
d5ac54ef50db16b50689b5c8b7bb64d344190832Timo Sirainen bool expunged;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (expunged_r == NULL)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen expunged_r = &expunged;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen view->v.lookup_ext_full(view, seq, ext_id, map_r, data_r, expunged_r);
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mail_index_get_header_ext(struct mail_index_view *view, uint32_t ext_id,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const void **data_r, size_t *data_size_r)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen view->v.get_header_ext(view, NULL, ext_id, data_r, data_size_r);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mail_index_map_get_header_ext(struct mail_index_view *view,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mail_index_map *map, uint32_t ext_id,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const void **data_r, size_t *data_size_r)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
view->v.get_header_ext(view, map, ext_id, data_r, data_size_r);
}
bool mail_index_ext_get_reset_id(struct mail_index_view *view,
struct mail_index_map *map,
uint32_t ext_id, uint32_t *reset_id_r)
{
return view->v.ext_get_reset_id(view, map, ext_id, reset_id_r);
}
void mail_index_ext_get_size(struct mail_index_view *view __attr_unused__,
uint32_t ext_id, struct mail_index_map *map,
uint32_t *hdr_size_r, uint16_t *record_size_r,
uint16_t *record_align_r)
{
const struct mail_index_ext *ext;
uint32_t idx;
i_assert(map != NULL);
if (!mail_index_map_get_ext_idx(map, ext_id, &idx)) {
/* extension doesn't exist in this index file */
if (hdr_size_r != NULL)
*hdr_size_r = 0;
if (record_size_r != NULL)
*record_size_r = 0;
if (record_align_r != NULL)
*record_align_r = 0;
return;
}
ext = array_idx(&map->extensions, idx);
if (hdr_size_r != NULL)
*hdr_size_r = ext->hdr_size;
if (record_size_r != NULL)
*record_size_r = ext->record_size;
if (record_align_r != NULL)
*record_align_r = ext->record_align;
}
static struct mail_index_view_vfuncs view_vfuncs = {
_view_close,
_view_get_messages_count,
_view_get_header,
_view_lookup_full,
_view_lookup_uid,
_view_lookup_uid_range,
_view_lookup_first,
_view_lookup_ext_full,
_view_get_header_ext,
_view_ext_get_reset_id
};
struct mail_index_view *
mail_index_view_open_with_map(struct mail_index *index,
struct mail_index_map *map)
{
struct mail_index_view *view;
view = i_new(struct mail_index_view, 1);
view->refcount = 1;
view->v = view_vfuncs;
view->index = index;
view->log_view = mail_transaction_log_view_open(index->log);
view->indexid = index->indexid;
view->inconsistency_id = index->inconsistency_id;
view->map = map;
view->map->refcount++;
view->log_file_expunge_seq = view->log_file_head_seq =
view->map->hdr.log_file_seq;
view->log_file_expunge_offset = view->log_file_head_offset =
view->map->hdr.log_file_head_offset;
i_array_init(&view->module_contexts,
I_MIN(5, mail_index_module_register.id));
return view;
}
struct mail_index_view *mail_index_view_open(struct mail_index *index)
{
return mail_index_view_open_with_map(index, index->map);
}
const struct mail_index_ext *
mail_index_view_get_ext(struct mail_index_view *view, uint32_t ext_id)
{
uint32_t idx;
if (!mail_index_map_get_ext_idx(view->map, ext_id, &idx))
return NULL;
return array_idx(&view->map->extensions, idx);
}