mail-index-view.c revision ea546eaab672d441e180b7619d4750be813c08d8
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "lib.h"
685a84a0ccb55cb9359dcd57d9eb3b6b836034a2Timo Sirainen#include "buffer.h"
5ab2ee0b9b7ad3867fcfd2a31fda0790370fbbbdTimo Sirainen#include "file-lock.h"
b87761f9bbef949f31dae297e619ac3f5e9c2b2eTimo Sirainen#include "mail-index-view-private.h"
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen#include "mail-transaction-log.h"
009217abb57a24a4076092e8e4e165545747839eStephan Bosch
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct mail_index_view *mail_index_view_open(struct mail_index *index)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen struct mail_index_view *view;
06b0c3be9905099038964b068216bbed155701deTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen view = i_new(struct mail_index_view, 1);
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen view->index = index;
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen view->log_view = mail_transaction_log_view_open(index->log);
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen view->indexid = index->indexid;
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen view->map = index->map;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen view->map->refcount++;
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen view->messages_count = view->map->records_count;
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen view->log_file_seq = view->map->log_file_seq;
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainen view->log_file_offset = view->map->log_file_offset;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return view;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainenvoid mail_index_view_close(struct mail_index_view *view)
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_view_unlock(view);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_transaction_log_view_close(view->log_view);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (view->log_syncs != NULL)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen buffer_free(view->log_syncs);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_unmap(view->index, view->map);
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen i_free(view);
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen}
009217abb57a24a4076092e8e4e165545747839eStephan Bosch
009217abb57a24a4076092e8e4e165545747839eStephan Boschstatic int mail_index_view_map_protect(struct mail_index_view *view)
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen{
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen /* not head mapping, no need to lock */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (!view->map_protected) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (mail_index_map_lock_mprotect(view->index, view->map,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen F_RDLCK) < 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen view->map_protected = TRUE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenint mail_index_view_lock_head(struct mail_index_view *view, int update_index)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
b3f46fa8a890527996fd0288cf964b7f3567cd22Timo Sirainen unsigned int lock_id;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (MAIL_INDEX_MAP_IS_IN_MEMORY(view->index->map))
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen if (!mail_index_is_locked(view->index, view->lock_id)) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (mail_index_lock_shared(view->index, update_index,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen &view->lock_id) < 0)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return -1;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (mail_index_map(view->index, FALSE) <= 0) {
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen view->inconsistent = TRUE;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen return -1;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen }
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen if (view->index->indexid != view->indexid) {
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen /* index was rebuilt */
0db5b158a00c08955bdacc99b1e2cd1ec07f4311Timo Sirainen view->inconsistent = TRUE;
0db5b158a00c08955bdacc99b1e2cd1ec07f4311Timo Sirainen return -1;
0db5b158a00c08955bdacc99b1e2cd1ec07f4311Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } else if (update_index) {
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen if (mail_index_lock_shared(view->index, TRUE, &lock_id) < 0)
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen return -1;
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainen
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainen mail_index_unlock(view->index, view->lock_id);
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen view->lock_id = lock_id;
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_assert(view->index->lock_type != F_UNLCK);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* mail_index_lock_shared() may have reopened the file,
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen so do this after it. */
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen if (view->map != view->index->map) {
9250f1bc4abcd8619b65321a8f75434065e6cb38Timo Sirainen if (mail_index_view_map_protect(view) < 0)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
b57cd9928909b51fa473c3eea81442e296006438Timo Sirainen}
b57cd9928909b51fa473c3eea81442e296006438Timo Sirainen
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainenint mail_index_view_lock(struct mail_index_view *view)
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainen{
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainen if (mail_index_view_is_inconsistent(view))
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainen return -1;
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainen
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainen if (view->map != view->index->map) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (mail_index_view_map_protect(view) < 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return mail_index_view_lock_head(view, FALSE);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen}
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenvoid mail_index_view_unlock(struct mail_index_view *view)
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen{
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen if (view->map_protected) {
c87d1e148ae76cf20f3adc7fc84fd54219dc62d5Timo Sirainen (void)mail_index_map_lock_mprotect(view->index, view->map,
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen F_UNLCK);
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen view->map_protected = FALSE;
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen if (view->lock_id != 0) {
c87d1e148ae76cf20f3adc7fc84fd54219dc62d5Timo Sirainen mail_index_unlock(view->index, view->lock_id);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen view->lock_id = 0;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen}
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenuint32_t mail_index_view_get_message_count(struct mail_index_view *view)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen{
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return view->messages_count;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen}
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainenint mail_index_view_is_inconsistent(struct mail_index_view *view)
9abf4d9d5eeb74d70fc26deb024383cf87f276bcTimo Sirainen{
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen if (view->index->indexid != view->indexid)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen view->inconsistent = TRUE;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return view->inconsistent;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen}
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenstruct mail_index *mail_index_view_get_index(struct mail_index_view *view)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return view->index;
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen}
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainenvoid mail_index_view_transaction_ref(struct mail_index_view *view)
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainen{
9250f1bc4abcd8619b65321a8f75434065e6cb38Timo Sirainen view->transactions++;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen}
06b0c3be9905099038964b068216bbed155701deTimo Sirainen
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainenvoid mail_index_view_transaction_unref(struct mail_index_view *view)
9250f1bc4abcd8619b65321a8f75434065e6cb38Timo Sirainen{
06b0c3be9905099038964b068216bbed155701deTimo Sirainen i_assert(view->transactions > 0);
685a84a0ccb55cb9359dcd57d9eb3b6b836034a2Timo Sirainen
685a84a0ccb55cb9359dcd57d9eb3b6b836034a2Timo Sirainen view->transactions--;
685a84a0ccb55cb9359dcd57d9eb3b6b836034a2Timo Sirainen}
685a84a0ccb55cb9359dcd57d9eb3b6b836034a2Timo Sirainen
685a84a0ccb55cb9359dcd57d9eb3b6b836034a2Timo Sirainenint mail_index_get_header(struct mail_index_view *view,
f635aa2fd6c47ec297cf68981203a8dc7f8a23c3Timo Sirainen const struct mail_index_header **hdr_r)
f635aa2fd6c47ec297cf68981203a8dc7f8a23c3Timo Sirainen{
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (mail_index_view_lock(view) < 0)
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen return -1;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen if (view->map->hdr->messages_count == view->messages_count)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen *hdr_r = view->map->hdr;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen else {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* messages_count differs, use a modified copy */
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen view->tmp_hdr_copy = *view->map->hdr;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen view->tmp_hdr_copy.messages_count = view->messages_count;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen *hdr_r = &view->tmp_hdr_copy;
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen }
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen return 0;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen}
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenint mail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen struct mail_index_map **map_r,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen const struct mail_index_record **rec_r)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mail_index_map *map;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const struct mail_index_record *rec, *n_rec;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t uid;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_assert(seq > 0);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_assert(seq <= view->messages_count);
575fa28d92361c068b2c08d393605e1de661d922Martti Rannanjärvi
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen if (mail_index_view_lock(view) < 0)
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen return -1;
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen rec = MAIL_INDEX_MAP_IDX(view->index, view->map, seq-1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (view->map == view->index->map) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen *map_r = view->map;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen *rec_r = rec;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (mail_index_view_lock_head(view, FALSE) < 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* look for it in the head mapping */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen *map_r = map = view->index->map;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen uid = rec->uid;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (seq > view->index->hdr->messages_count)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen seq = view->index->hdr->messages_count;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (seq == 0) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen *rec_r = rec;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
009217abb57a24a4076092e8e4e165545747839eStephan Bosch
009217abb57a24a4076092e8e4e165545747839eStephan Bosch do {
009217abb57a24a4076092e8e4e165545747839eStephan Bosch // FIXME: we could be skipping more by uid diff
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch seq--;
e180615c1db31c8a6f6a586ae40b1cfc2d6ee725Timo Sirainen n_rec = MAIL_INDEX_MAP_IDX(view->index, map, seq);
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch if (n_rec->uid <= uid)
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen break;
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen } while (seq > 0);
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen if (n_rec->uid == uid) {
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen *rec_r = n_rec;
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen return 1;
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen } else {
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen *rec_r = rec;
2d33429390199b9dfbbdaace1b48626cc3a7a42bTimo Sirainen return 0;
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenint mail_index_lookup(struct mail_index_view *view, uint32_t seq,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const struct mail_index_record **rec_r)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mail_index_map *map;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return mail_index_lookup_full(view, seq, &map, rec_r);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainenint mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen uint32_t *uid_r)
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen{
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen i_assert(seq > 0);
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen i_assert(seq <= view->messages_count);
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen
09d0ffb0ddfbebb4a04b377b9f879c05749de54fTimo Sirainen if (mail_index_view_lock(view) < 0)
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen return -1;
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen *uid_r = MAIL_INDEX_MAP_IDX(view->index, view->map, seq-1)->uid;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenint mail_index_lookup_extra(struct mail_index_view *view, uint32_t seq,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t data_id, const void **data_r)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen const struct mail_index_record *rec;
6920cf9a4d7bb8fd1a5b5bd25fafc8dd0cb9817cTimo Sirainen struct mail_index_map *map;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen uint32_t offset;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen int ret;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if ((ret = mail_index_lookup_full(view, seq, &map, &rec)) < 0)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (rec == NULL) {
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen *data_r = NULL;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return ret;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* FIXME: do data_id mapping conversion */
bc27fcd011f86208feaf73da9778a66ac7d7d3abTimo Sirainen
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen offset = view->index->extra_records[data_id].offset;
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen *data_r = CONST_PTR_OFFSET(rec, offset);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return ret;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenstatic uint32_t mail_index_bsearch_uid(struct mail_index_view *view,
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen uint32_t uid, uint32_t *left_idx_p,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen int nearest_side)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const struct mail_index_record *rec_base, *rec;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen uint32_t idx, left_idx, right_idx, record_size;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen rec_base = view->map->records;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen record_size = view->index->record_size;
4c9c55e15f35474f53f11659e796c63b1c34e884Timo Sirainen
9222c96ab9f42b25d5d5260f9e7a42c694715b0aTimo Sirainen idx = left_idx = *left_idx_p;
9222c96ab9f42b25d5d5260f9e7a42c694715b0aTimo Sirainen right_idx = view->messages_count;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen while (left_idx < right_idx) {
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen idx = (left_idx + right_idx) / 2;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (rec->uid < uid)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen left_idx = idx+1;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen else if (rec->uid > uid)
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen right_idx = idx;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen else
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen break;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (idx == view->messages_count) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen /* no messages available */
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return 0;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen *left_idx_p = left_idx;
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (rec->uid != uid) {
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (nearest_side > 0) {
13a8c553f293349248b161ff851743498916e26eTimo Sirainen /* we want uid or larger */
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen return rec->uid > uid ? idx+1 :
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen idx == view->messages_count-1 ? 0 : idx+2;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen } else {
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen /* we want uid or smaller */
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen return rec->uid < uid ? idx + 1 : idx;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return idx+1;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen}
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenint mail_index_lookup_uid_range(struct mail_index_view *view,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen uint32_t first_uid, uint32_t last_uid,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen uint32_t *first_seq_r, uint32_t *last_seq_r)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen uint32_t left_idx;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_assert(first_uid > 0);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_assert(first_uid <= last_uid);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (mail_index_view_lock(view) < 0)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return -1;
c95fc202215d2451372599db7092b16459f360a3Timo Sirainen
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen if (last_uid >= view->map->hdr->next_uid) {
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen last_uid = view->map->hdr->next_uid-1;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (first_uid > last_uid) {
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen *first_seq_r = 0;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen *last_seq_r = 0;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen return 0;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen left_idx = 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen *first_seq_r = mail_index_bsearch_uid(view, first_uid, &left_idx, 1);
3db8062598ce08e9320c84f77c267b9c70cb0809Timo Sirainen if (*first_seq_r == 0 ||
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen MAIL_INDEX_MAP_IDX(view->index, view->map, *first_seq_r-1)->uid >
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen last_uid) {
3db8062598ce08e9320c84f77c267b9c70cb0809Timo Sirainen *first_seq_r = 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen *last_seq_r = 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (first_uid == last_uid) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen *last_seq_r = *first_seq_r;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return 0;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen }
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen /* optimization - binary lookup only from right side: */
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen *last_seq_r = mail_index_bsearch_uid(view, last_uid, &left_idx, -1);
eeea0a402bcd9533e9e359f2a2518e3216162151Timo Sirainen i_assert(*last_seq_r >= *first_seq_r);
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainen return 0;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenint mail_index_lookup_first(struct mail_index_view *view, enum mail_flags flags,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen uint8_t flags_mask, uint32_t *seq_r)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#define LOW_UPDATE(x) \
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen STMT_START { if ((x) > low_uid) low_uid = x; } STMT_END
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainen const struct mail_index_record *rec;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen uint32_t seq, low_uid = 1;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen *seq_r = 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen if (mail_index_view_lock(view) < 0)
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen return -1;
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if ((flags_mask & MAIL_RECENT) != 0 && (flags & MAIL_RECENT) != 0)
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen LOW_UPDATE(view->map->hdr->first_recent_uid_lowwater);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if ((flags_mask & MAIL_SEEN) != 0 && (flags & MAIL_SEEN) == 0)
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen LOW_UPDATE(view->map->hdr->first_unseen_uid_lowwater);
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainen if ((flags_mask & MAIL_DELETED) != 0 && (flags & MAIL_DELETED) != 0)
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainen LOW_UPDATE(view->map->hdr->first_deleted_uid_lowwater);
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (low_uid == 1)
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen seq = 1;
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen else {
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen if (mail_index_lookup_uid_range(view, low_uid, low_uid,
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainen &seq, &seq) < 0)
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainen return -1;
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen if (seq == 0)
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen return 0;
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen }
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen for (; seq <= view->messages_count; seq++, rec++) {
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen rec = MAIL_INDEX_MAP_IDX(view->index, view->map, seq-1);
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen if ((rec->flags & flags_mask) == (uint8_t)flags) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen *seq_r = seq;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen break;
a74e4a66db99a69cca71d7c5ac1feae46d92138fTimo Sirainen }
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainen }
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return 0;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen