mail-index-view.c revision 6ef7e31619edfaa17ed044b45861d106a86191ef
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "lib.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "array.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "buffer.h"
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen#include "mail-index-view-private.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mail-transaction-log.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid mail_index_view_clone(struct mail_index_view *dest,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct mail_index_view *src)
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen memset(dest, 0, sizeof(dest));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen dest->refcount = 1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen dest->methods = src->methods;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen dest->index = src->index;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen dest->log_view = mail_transaction_log_view_open(src->index->log);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen dest->indexid = src->indexid;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen dest->map = src->map;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen dest->map->refcount++;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen dest->hdr = src->hdr;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen dest->log_file_seq = src->log_file_seq;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen dest->log_file_offset = src->log_file_offset;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid mail_index_view_ref(struct mail_index_view *view)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen view->refcount++;
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void _view_close(struct mail_index_view *view)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(view->refcount == 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_index_view_unlock(view);
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen mail_transaction_log_view_close(view->log_view);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (array_is_created(&view->log_syncs))
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen array_free(&view->log_syncs);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_index_unmap(view->index, view->map);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (array_is_created(&view->map_refs)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_index_view_unref_maps(view);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen array_free(&view->map_refs);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_free(view);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenint mail_index_view_lock_head(struct mail_index_view *view, bool update_index)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int lock_id;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (MAIL_INDEX_MAP_IS_IN_MEMORY(view->index->map))
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return 0;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (!mail_index_is_locked(view->index, view->lock_id)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mail_index_lock_shared(view->index, update_index,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen &view->lock_id) < 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mail_index_map(view->index, FALSE) <= 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen view->inconsistent = TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (view->index->indexid != view->indexid) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* index was rebuilt */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen view->inconsistent = TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen } else if (update_index) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mail_index_lock_shared(view->index, TRUE, &lock_id) < 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen mail_index_unlock(view->index, view->lock_id);
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen view->lock_id = lock_id;
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen }
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen i_assert(view->index->lock_type != F_UNLCK);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen return 0;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen}
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainenint mail_index_view_lock(struct mail_index_view *view)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mail_index_view_is_inconsistent(view))
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (view->map != view->index->map) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* not head mapping, no need to lock */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return 0;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return mail_index_view_lock_head(view, FALSE);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid mail_index_view_unlock(struct mail_index_view *view)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (view->lock_id != 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_index_unlock(view->index, view->lock_id);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen view->lock_id = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenbool mail_index_view_is_inconsistent(struct mail_index_view *view)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (view->index->indexid != view->indexid)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen view->inconsistent = TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return view->inconsistent;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstruct mail_index *mail_index_view_get_index(struct mail_index_view *view)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return view->index;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen}
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainenvoid mail_index_view_transaction_ref(struct mail_index_view *view)
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen{
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen view->transactions++;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid mail_index_view_transaction_unref(struct mail_index_view *view)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(view->transactions > 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen view->transactions--;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void mail_index_view_ref_map(struct mail_index_view *view,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_index_map *map)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_index_map *const *maps;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int i, count;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (array_is_created(&view->map_refs)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen maps = array_get(&view->map_refs, &count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* if map is already referenced, do nothing */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (i = 0; i < count; i++) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (maps[i] == map)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return;
c6335901c67a4c9365319190a111a2168f3b06f5Timo Sirainen }
c6335901c67a4c9365319190a111a2168f3b06f5Timo Sirainen } else {
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen ARRAY_CREATE(&view->map_refs, default_pool,
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen struct mail_index_map *, 4);
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen }
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* reference the given mapping. the reference is dropped when the view
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen is synchronized or closed. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen map->refcount++;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen array_append(&view->map_refs, &map, 1);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid mail_index_view_unref_maps(struct mail_index_view *view)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mail_index_map *const *maps;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int i, count;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (!array_is_created(&view->map_refs))
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen maps = array_get(&view->map_refs, &count);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (i = 0; i < count; i++)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_index_unmap(view->index, maps[i]);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen array_clear(&view->map_refs);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic uint32_t _view_get_messages_count(struct mail_index_view *view)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return view->hdr.messages_count;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic const struct mail_index_header *
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen_view_get_header(struct mail_index_view *view)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return &view->hdr;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic int _view_lookup_full(struct mail_index_view *view, uint32_t seq,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_index_map **map_r,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct mail_index_record **rec_r)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mail_index_map *map;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const struct mail_index_record *rec, *head_rec;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mail_index_view_lock(view) < 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* look up the record */
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen rec = MAIL_INDEX_MAP_IDX(view->map, seq-1);
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen if (view->map == view->index->map) {
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen /* view's mapping is latest. we can use it directly. */
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen *map_r = view->map;
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen *rec_r = rec;
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen return 1;
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen }
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* look up the record from head mapping. it may contain some changes. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (mail_index_view_lock_head(view, FALSE) < 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* start looking up from the same sequence as in the old view.
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if there are no expunges, it's there. otherwise it's somewhere
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen before (since records can't be inserted).
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen usually there are only a few expunges, so just going downwards from
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen our initial sequence position is probably faster than binary
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen search. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (seq > view->index->hdr->messages_count)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen seq = view->index->hdr->messages_count;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (seq == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* everything is expunged from head. use the old record. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *map_r = view->map;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *rec_r = rec;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen map = view->index->map;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen do {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen seq--;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen head_rec = MAIL_INDEX_MAP_IDX(map, seq);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (head_rec->uid <= rec->uid)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } while (seq > 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (head_rec->uid == rec->uid) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* found it. use it. reference the index mapping so that the
7f13786e6a18a846376e46d77349528d99935871Timo Sirainen returned record doesn't get invalidated after next sync. */
7f13786e6a18a846376e46d77349528d99935871Timo Sirainen mail_index_view_ref_map(view, view->index->map);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *map_r = view->index->map;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *rec_r = head_rec;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* expuned from head. use the old record. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *map_r = view->map;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *rec_r = rec;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int _view_lookup_uid(struct mail_index_view *view, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint32_t *uid_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (mail_index_view_lock(view) < 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *uid_r = MAIL_INDEX_MAP_IDX(view->map, seq-1)->uid;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic uint32_t mail_index_bsearch_uid(struct mail_index_view *view,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint32_t uid, uint32_t *left_idx_p,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int nearest_side)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const struct mail_index_record *rec_base, *rec;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint32_t idx, left_idx, right_idx, record_size;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(view->hdr.messages_count <= view->map->records_count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen rec_base = view->map->records;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen record_size = view->map->hdr.record_size;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen idx = left_idx = *left_idx_p;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen right_idx = view->hdr.messages_count;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen while (left_idx < right_idx) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen idx = (left_idx + right_idx) / 2;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (rec->uid < uid)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen left_idx = idx+1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen else if (rec->uid > uid)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen right_idx = idx;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen else
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (idx == view->hdr.messages_count) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* no messages available */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen *left_idx_p = left_idx;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (rec->uid != uid) {
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen if (nearest_side > 0) {
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen /* we want uid or larger */
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen return rec->uid > uid ? idx+1 :
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen idx == view->hdr.messages_count-1 ? 0 : idx+2;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* we want uid or smaller */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return rec->uid < uid ? idx + 1 : idx;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return idx+1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic int _view_lookup_uid_range(struct mail_index_view *view,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen uint32_t first_uid, uint32_t last_uid,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen uint32_t *first_seq_r, uint32_t *last_seq_r)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen uint32_t left_idx;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(first_uid > 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(first_uid <= last_uid);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen if (mail_index_view_lock(view) < 0)
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen return -1;
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (last_uid >= view->map->hdr.next_uid) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen last_uid = view->map->hdr.next_uid-1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (first_uid > last_uid) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *first_seq_r = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *last_seq_r = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen left_idx = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *first_seq_r = mail_index_bsearch_uid(view, first_uid, &left_idx, 1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (*first_seq_r == 0 ||
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen MAIL_INDEX_MAP_IDX(view->map, *first_seq_r-1)->uid > last_uid) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *first_seq_r = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *last_seq_r = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (first_uid == last_uid) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *last_seq_r = *first_seq_r;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* optimization - binary lookup only from right side: */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *last_seq_r = mail_index_bsearch_uid(view, last_uid, &left_idx, -1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(*last_seq_r >= *first_seq_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int _view_lookup_first(struct mail_index_view *view,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen enum mail_flags flags, uint8_t flags_mask,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint32_t *seq_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#define LOW_UPDATE(x) \
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen STMT_START { if ((x) > low_uid) low_uid = x; } STMT_END
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const struct mail_index_record *rec;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint32_t seq, low_uid = 1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *seq_r = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (mail_index_view_lock(view) < 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if ((flags_mask & MAIL_RECENT) != 0 && (flags & MAIL_RECENT) != 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen LOW_UPDATE(view->map->hdr.first_recent_uid_lowwater);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if ((flags_mask & MAIL_SEEN) != 0 && (flags & MAIL_SEEN) == 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen LOW_UPDATE(view->map->hdr.first_unseen_uid_lowwater);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if ((flags_mask & MAIL_DELETED) != 0 && (flags & MAIL_DELETED) != 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen LOW_UPDATE(view->map->hdr.first_deleted_uid_lowwater);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (low_uid == 1)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen seq = 1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen else {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mail_index_lookup_uid_range(view, low_uid, low_uid,
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen &seq, &seq) < 0)
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen return -1;
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen if (seq == 0)
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(view->hdr.messages_count <= view->map->records_count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (; seq <= view->hdr.messages_count; seq++) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen rec = MAIL_INDEX_MAP_IDX(view->map, seq-1);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if ((rec->flags & flags_mask) == (uint8_t)flags) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen *seq_r = seq;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return 0;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen}
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenstatic int _view_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen uint32_t ext_id, struct mail_index_map **map_r,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen const void **data_r)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen{
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen const struct mail_index_ext *ext;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen const struct mail_index_record *rec;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen uint32_t idx, offset;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen int ret;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if ((ret = mail_index_lookup_full(view, seq, map_r, &rec)) < 0)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return -1;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (rec == NULL || !mail_index_map_get_ext_idx(*map_r, ext_id, &idx)) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen *data_r = NULL;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen ext = array_idx(&(*map_r)->extensions, idx);
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen offset = ext->record_offset;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *data_r = offset == 0 ? NULL : CONST_PTR_OFFSET(rec, offset);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int _view_get_header_ext(struct mail_index_view *view,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mail_index_map *map, uint32_t ext_id,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const void **data_r, size_t *data_size_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const struct mail_index_ext *ext;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint32_t idx;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* if we have a mapping, the view where it's from is already locked */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (map == NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* no mapping given, use head mapping */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (mail_index_view_lock_head(view, FALSE) < 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen map = view->index->map;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (!mail_index_map_get_ext_idx(map, ext_id, &idx)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* extension doesn't exist in this index file */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *data_r = NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *data_size_r = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ext = array_idx(&map->extensions, idx);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen *data_r = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen *data_size_r = ext->hdr_size;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return 0;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_index_view_close(struct mail_index_view *view)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (--view->refcount > 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen view->methods.close(view);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainenuint32_t mail_index_view_get_messages_count(struct mail_index_view *view)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen return view->methods.get_messages_count(view);
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen}
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainenconst struct mail_index_header *
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenmail_index_get_header(struct mail_index_view *view)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return view->methods.get_header(view);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenint mail_index_lookup(struct mail_index_view *view, uint32_t seq,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct mail_index_record **rec_r)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mail_index_map *map;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return mail_index_lookup_full(view, seq, &map, rec_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mail_index_map **map_r,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const struct mail_index_record **rec_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return view->methods.lookup_full(view, seq, map_r, rec_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen array_t *keyword_idx)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ARRAY_SET_TYPE(keyword_idx, unsigned int);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mail_index_map *map;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const void *data;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const unsigned char *keyword_data;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const unsigned int *keyword_idx_map;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int i, j, keyword_count, index_idx;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint32_t ext_id, idx;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint16_t record_size;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int ret;
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen array_clear(keyword_idx);
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen
e3540e734a79fd4f971652925079c2e26a4b5524Timo Sirainen /* get the keywords data. */
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen ext_id = view->index->keywords_ext_id;
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen ret = mail_index_lookup_ext_full(view, seq, ext_id, &map, &data);
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen if (ret < 0)
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen if (data == NULL) {
e4eb49e29197c6783ec93b868100394e189f4e0cTimo Sirainen /* no keywords at all in index */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen (void)mail_index_ext_get_size(view, ext_id, map, NULL,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen &record_size, NULL);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* keyword_idx_map[] contains file => index keyword mapping */
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen if (!array_is_created(&map->keyword_idx_map)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen keyword_idx_map = NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen keyword_count = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen keyword_idx_map = array_get(&map->keyword_idx_map,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen &keyword_count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen keyword_data = data;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen for (i = 0, idx = 0; i < record_size; i++) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* first do the quick check to see if there's keywords at all */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (keyword_data[i] == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen continue;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen idx = i * CHAR_BIT;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen for (j = 0; j < CHAR_BIT; j++, idx++) {
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen if ((keyword_data[i] & (1 << j)) == 0)
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen continue;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (idx >= keyword_count) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* keyword header is updated, re-read
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen it so we know what this one is
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen called */
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen if (mail_index_map_read_keywords(view->index,
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen map) < 0)
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen return -1;
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen if (!array_is_created(&map->keyword_idx_map))
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen return ret;
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen /* pointer may have changed. update it. */
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen keyword_idx_map =
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen array_get(&map->keyword_idx_map,
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen &keyword_count);
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen if (idx >= keyword_count) {
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen /* extra bits set in keyword bytes.
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen shouldn't happen, but just ignore. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen index_idx = keyword_idx_map[idx];
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen array_append(keyword_idx, &index_idx, 1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint32_t *uid_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return view->methods.lookup_uid(view, seq, uid_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_uid_range(struct mail_index_view *view,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint32_t first_uid, uint32_t last_uid,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint32_t *first_seq_r, uint32_t *last_seq_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return view->methods.lookup_uid_range(view, first_uid, last_uid,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen first_seq_r, last_seq_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_first(struct mail_index_view *view, enum mail_flags flags,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint8_t flags_mask, uint32_t *seq_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return view->methods.lookup_first(view, flags, flags_mask, seq_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint32_t ext_id, const void **data_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mail_index_map *map;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return view->methods.lookup_ext_full(view, seq, ext_id, &map, data_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint32_t ext_id, struct mail_index_map **map_r,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const void **data_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return view->methods.lookup_ext_full(view, seq, ext_id, map_r, data_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_get_header_ext(struct mail_index_view *view, uint32_t ext_id,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const void **data_r, size_t *data_size_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return view->methods.get_header_ext(view, NULL, ext_id,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen data_r, data_size_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_map_get_header_ext(struct mail_index_view *view,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mail_index_map *map, uint32_t ext_id,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const void **data_r, size_t *data_size_r)
{
return view->methods.get_header_ext(view, map, ext_id,
data_r, data_size_r);
}
int 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 0;
}
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;
return 0;
}
static struct mail_index_view_methods view_methods = {
_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
};
struct mail_index_view *mail_index_view_open(struct mail_index *index)
{
struct mail_index_view *view;
i_assert(index->map != NULL);
view = i_new(struct mail_index_view, 1);
view->refcount = 1;
view->methods = view_methods;
view->index = index;
view->log_view = mail_transaction_log_view_open(index->log);
view->indexid = index->indexid;
view->map = index->map;
view->map->refcount++;
view->hdr = view->map->hdr;
view->log_file_seq = view->map->hdr.log_file_seq;
view->log_file_offset =
I_MIN(view->map->hdr.log_file_int_offset,
view->map->hdr.log_file_ext_offset);
return view;
}
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 0;
return array_idx(&view->map->extensions, idx);
}