mail-index-view.c revision b5ea11802f2bafbec06282a7b3b6704dc5fae584
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen#include "lib.h"
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen#include "buffer.h"
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen#include "file-lock.h"
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen#include "mail-index-view-private.h"
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen#include "mail-transaction-log.h"
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainenstruct mail_index_view *mail_index_view_open(struct mail_index *index)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen{
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen struct mail_index_view *view;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view = i_new(struct mail_index_view, 1);
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->index = index;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->log_view = mail_transaction_log_view_open(index->log);
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->indexid = index->indexid;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->map = index->map;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->map->refcount++;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->messages_count = view->map->records_count;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->log_file_seq = view->map->log_file_seq;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->log_file_offset = view->map->log_file_offset;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return view;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen}
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainenvoid mail_index_view_close(struct mail_index_view *view)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen{
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen mail_index_view_unlock(view);
4b89231f4ec9cc69f4aea715e1d34f405c7e317dTimo Sirainen mail_transaction_log_view_close(view->log_view);
4b89231f4ec9cc69f4aea715e1d34f405c7e317dTimo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (view->log_syncs != NULL)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen buffer_free(view->log_syncs);
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen mail_index_unmap(view->index, view->map);
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen i_free(view);
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen}
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainenstatic int mail_index_view_map_protect(struct mail_index_view *view)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen{
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen /* not head mapping, no need to lock */
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (!view->map_protected) {
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (mail_index_map_lock_mprotect(view->index, view->map,
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen F_RDLCK) < 0)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return -1;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->map_protected = TRUE;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen }
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return 0;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen}
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainenint mail_index_view_lock_head(struct mail_index_view *view, int update_index)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen{
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen unsigned int lock_id;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (!mail_index_is_locked(view->index, view->lock_id)) {
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (mail_index_lock_shared(view->index, update_index,
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen &view->lock_id) < 0)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return -1;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (mail_index_map(view->index, FALSE) <= 0) {
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->inconsistent = TRUE;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return -1;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen }
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if (view->index->indexid != view->indexid) {
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen /* index was rebuilt */
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->inconsistent = TRUE;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return -1;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen }
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen } else if (update_index) {
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (mail_index_lock_shared(view->index, TRUE, &lock_id) < 0)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return -1;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen mail_index_unlock(view->index, view->lock_id);
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->lock_id = lock_id;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen }
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen i_assert(view->index->lock_type != F_UNLCK);
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen /* mail_index_lock_shared() may have reopened the file,
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen so do this after it. */
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (view->map != view->index->map) {
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (mail_index_view_map_protect(view) < 0)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return -1;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen }
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen return 0;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen}
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainenint mail_index_view_lock(struct mail_index_view *view)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen{
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen if (mail_index_view_is_inconsistent(view))
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen return -1;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen if (view->map != view->index->map) {
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen if (mail_index_view_map_protect(view) < 0)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return -1;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return 0;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen }
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return mail_index_view_lock_head(view, FALSE);
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen}
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainenvoid mail_index_view_unlock(struct mail_index_view *view)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen{
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (view->map_protected) {
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen (void)mail_index_map_lock_mprotect(view->index, view->map,
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen F_UNLCK);
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->map_protected = FALSE;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen }
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (view->lock_id != 0) {
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen mail_index_unlock(view->index, view->lock_id);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen view->lock_id = 0;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen }
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen}
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainenuint32_t mail_index_view_get_message_count(struct mail_index_view *view)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen{
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return view->messages_count;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen}
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainenint mail_index_view_is_inconsistent(struct mail_index_view *view)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen{
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (view->index->indexid != view->indexid)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->inconsistent = TRUE;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return view->inconsistent;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen}
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainenstruct mail_index *mail_index_view_get_index(struct mail_index_view *view)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen{
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return view->index;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen}
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainenvoid mail_index_view_transaction_ref(struct mail_index_view *view)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen{
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->transactions++;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen}
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainenvoid mail_index_view_transaction_unref(struct mail_index_view *view)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen{
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen i_assert(view->transactions > 0);
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->transactions--;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen}
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainenint mail_index_get_header(struct mail_index_view *view,
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen const struct mail_index_header **hdr_r)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen{
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (mail_index_view_lock(view) < 0)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return -1;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (view->map->hdr->messages_count == view->messages_count)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen *hdr_r = view->map->hdr;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen else {
8fcf84e6b7a55049a6d407b17af50d6ae8c6386fPhil Carmody /* messages_count differs, use a modified copy */
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->tmp_hdr_copy = *view->map->hdr;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen view->tmp_hdr_copy.messages_count = view->messages_count;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen *hdr_r = &view->tmp_hdr_copy;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen }
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen return 0;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen}
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainenstatic int mail_index_lookup_int(struct mail_index_view *view, uint32_t seq,
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen struct mail_index_map **map_r,
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen const struct mail_index_record **rec_r)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen{
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen struct mail_index_map *map;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen const struct mail_index_record *rec, *n_rec;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen uint32_t uid;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen i_assert(seq > 0);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen i_assert(seq <= view->messages_count);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen if (mail_index_view_lock(view) < 0)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen return -1;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen rec = MAIL_INDEX_MAP_IDX(view->index, view->map, seq-1);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen if (view->map == view->index->map) {
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen *map_r = view->map;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen *rec_r = rec;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen return 1;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen }
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen if (mail_index_view_lock_head(view, FALSE) < 0)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen return -1;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen /* look for it in the head mapping */
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen *map_r = map = view->index->map;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen uid = rec->uid;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen if (seq > view->index->hdr->messages_count)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen seq = view->index->hdr->messages_count;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen if (seq == 0) {
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen *rec_r = NULL;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen return 1;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen }
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen do {
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen // FIXME: we could be skipping more by uid diff
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen seq--;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen n_rec = MAIL_INDEX_MAP_IDX(view->index, map, seq);
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (n_rec->uid <= uid)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen break;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen } while (seq > 0);
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (n_rec->uid == uid) {
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen *rec_r = n_rec;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return 1;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen } else {
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen *rec_r = rec;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return 0;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen }
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen}
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainenint mail_index_lookup(struct mail_index_view *view, uint32_t seq,
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen const struct mail_index_record **rec_r)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen{
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen struct mail_index_map *map;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return mail_index_lookup_int(view, seq, &map, rec_r);
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen}
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainenint mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen uint32_t *uid_r)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen{
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen i_assert(seq > 0);
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen i_assert(seq <= view->messages_count);
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (mail_index_view_lock(view) < 0)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return -1;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen *uid_r = MAIL_INDEX_MAP_IDX(view->index, view->map, seq-1)->uid;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return 0;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen}
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainenint mail_index_lookup_extra(struct mail_index_view *view, uint32_t seq,
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen uint32_t data_id, const void **data_r)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen{
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen const struct mail_index_record *rec;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen struct mail_index_map *map;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen uint32_t offset;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen int ret;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if ((ret = mail_index_lookup_int(view, seq, &map, &rec)) < 0)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return -1;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (rec == NULL) {
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen *data_r = NULL;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return ret;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen }
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen /* FIXME: do data_id mapping conversion */
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen offset = view->index->extra_records[data_id].offset;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen *data_r = CONST_PTR_OFFSET(rec, offset);
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen return ret;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen}
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainenstatic uint32_t mail_index_bsearch_uid(struct mail_index_view *view,
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen uint32_t uid, uint32_t *left_idx_p,
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen int nearest_side)
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen{
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen const struct mail_index_record *rec_base, *rec;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen uint32_t idx, left_idx, right_idx, record_size;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen rec_base = view->map->records;
record_size = view->index->record_size;
idx = left_idx = *left_idx_p;
right_idx = view->messages_count;
while (left_idx < right_idx) {
idx = (left_idx + right_idx) / 2;
rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
if (rec->uid < uid)
left_idx = idx+1;
else if (rec->uid > uid)
right_idx = idx;
else
break;
}
if (idx == view->messages_count) {
/* no messages available */
return 0;
}
*left_idx_p = left_idx;
rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
if (rec->uid != uid) {
if (nearest_side > 0) {
/* we want uid or larger */
return rec->uid > uid ? idx+1 :
idx == view->messages_count-1 ? 0 : idx+2;
} else {
/* we want uid or smaller */
return rec->uid < uid ? idx + 1 : idx;
}
}
return idx+1;
}
int mail_index_lookup_uid_range(struct mail_index_view *view,
uint32_t first_uid, uint32_t last_uid,
uint32_t *first_seq_r, uint32_t *last_seq_r)
{
uint32_t left_idx;
i_assert(first_uid > 0);
i_assert(first_uid <= last_uid);
if (mail_index_view_lock(view) < 0)
return -1;
if (last_uid >= view->map->hdr->next_uid) {
last_uid = view->map->hdr->next_uid-1;
if (first_uid > last_uid) {
*first_seq_r = 0;
*last_seq_r = 0;
return 0;
}
}
left_idx = 0;
*first_seq_r = mail_index_bsearch_uid(view, first_uid, &left_idx, 1);
if (*first_seq_r == 0 ||
MAIL_INDEX_MAP_IDX(view->index, view->map, *first_seq_r-1)->uid >
last_uid) {
*first_seq_r = 0;
*last_seq_r = 0;
return 0;
}
if (first_uid == last_uid) {
*last_seq_r = *first_seq_r;
return 0;
}
/* optimization - binary lookup only from right side: */
*last_seq_r = mail_index_bsearch_uid(view, last_uid, &left_idx, -1);
i_assert(*last_seq_r >= *first_seq_r);
return 0;
}
int mail_index_lookup_first(struct mail_index_view *view, enum mail_flags flags,
uint8_t flags_mask, uint32_t *seq_r)
{
#define LOW_UPDATE(x) \
STMT_START { if ((x) > low_uid) low_uid = x; } STMT_END
const struct mail_index_record *rec;
uint32_t seq, low_uid = 1;
*seq_r = 0;
if (mail_index_view_lock(view) < 0)
return -1;
if ((flags_mask & MAIL_RECENT) != 0 && (flags & MAIL_RECENT) != 0)
LOW_UPDATE(view->map->hdr->first_recent_uid_lowwater);
if ((flags_mask & MAIL_SEEN) != 0 && (flags & MAIL_SEEN) == 0)
LOW_UPDATE(view->map->hdr->first_unseen_uid_lowwater);
if ((flags_mask & MAIL_DELETED) != 0 && (flags & MAIL_DELETED) != 0)
LOW_UPDATE(view->map->hdr->first_deleted_uid_lowwater);
if (low_uid == 1)
seq = 1;
else {
if (mail_index_lookup_uid_range(view, low_uid, low_uid,
&seq, &seq) < 0)
return -1;
if (seq == 0)
return 0;
}
for (; seq <= view->messages_count; seq++, rec++) {
rec = MAIL_INDEX_MAP_IDX(view->index, view->map, seq-1);
if ((rec->flags & flags_mask) == (uint8_t)flags) {
*seq_r = seq;
break;
}
}
return 0;
}