mail-index-view.c revision b0be0bead3d6963149f7f2a9504b8ab5aced9af5
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (C) 2003-2004 Timo Sirainen */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#include "lib.h"
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#include "array.h"
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#include "buffer.h"
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#include "mail-index-view-private.h"
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#include "mail-transaction-log.h"
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenvoid mail_index_view_clone(struct mail_index_view *dest,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_view *src)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen memset(dest, 0, sizeof(dest));
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen dest->refcount = 1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen dest->v = src->v;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen dest->index = src->index;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen if (src->log_view != NULL) {
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen dest->log_view =
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_transaction_log_view_open(src->index->log);
40a5aeebf6b4858b93f0ddff0bf12fba769cf903Timo Sirainen }
40a5aeebf6b4858b93f0ddff0bf12fba769cf903Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen dest->indexid = src->indexid;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen dest->map = src->map;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if (dest->map != NULL)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen dest->map->refcount++;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen dest->hdr = src->hdr;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen dest->log_file_expunge_seq = src->log_file_expunge_seq;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen dest->log_file_expunge_offset = src->log_file_expunge_offset;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen dest->log_file_head_seq = src->log_file_head_seq;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen dest->log_file_head_offset = src->log_file_head_offset;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen i_array_init(&dest->module_contexts,
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen I_MIN(5, mail_index_module_register.id));
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen}
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainenvoid mail_index_view_ref(struct mail_index_view *view)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen{
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen view->refcount++;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen}
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainenstatic void _view_close(struct mail_index_view *view)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen{
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen i_assert(view->refcount == 0);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen mail_index_view_unlock(view);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen mail_transaction_log_view_close(&view->log_view);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if (array_is_created(&view->syncs_hidden))
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen array_free(&view->syncs_hidden);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen mail_index_unmap(&view->map);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (array_is_created(&view->map_refs)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_view_unref_maps(view);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen array_free(&view->map_refs);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen array_free(&view->module_contexts);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_free(view);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#ifdef DEBUG
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Boschstatic void mail_index_view_check_nextuid(struct mail_index_view *view)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index_record *rec;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (view->hdr.messages_count == 0)
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi return;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen rec = MAIL_INDEX_MAP_IDX(view->map, view->hdr.messages_count-1);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(rec->uid < view->hdr.next_uid);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#endif
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenint mail_index_view_lock_head(struct mail_index_view *view)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#ifdef DEBUG
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_view_check_nextuid(view);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#endif
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (mail_index_view_is_inconsistent(view))
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return -1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (MAIL_INDEX_MAP_IS_IN_MEMORY(view->index->map))
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!mail_index_is_locked(view->index, view->lock_id)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (mail_index_lock_shared(view->index, &view->lock_id) < 0) {
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen view->inconsistent = TRUE;
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen return -1;
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen }
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen }
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen return 0;
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen}
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainenint mail_index_view_lock(struct mail_index_view *view)
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen{
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen if (view->map != view->index->map) {
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen /* not head mapping, no need to lock */
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen if (mail_index_view_is_inconsistent(view))
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return -1;
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen#ifdef DEBUG
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_view_check_nextuid(view);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#endif
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return 0;
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return mail_index_view_lock_head(view);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenvoid mail_index_view_unlock(struct mail_index_view *view)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#ifdef DEBUG
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_view_check_nextuid(view);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#endif
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (view->lock_id != 0 && view->transactions == 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_unlock(view->index, view->lock_id);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen view->lock_id = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenbool mail_index_view_is_inconsistent(struct mail_index_view *view)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (view->index->indexid != view->indexid)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen view->inconsistent = TRUE;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return view->inconsistent;
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstruct mail_index *mail_index_view_get_index(struct mail_index_view *view)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return view->index;
b8864211b88ed7521e9af514590639344af38910Timo Sirainen}
b8864211b88ed7521e9af514590639344af38910Timo Sirainen
c3cb859d93a77d52d6af054d358b55d45b4a5188Timo Sirainenvoid mail_index_view_transaction_ref(struct mail_index_view *view)
b8864211b88ed7521e9af514590639344af38910Timo Sirainen{
c3cb859d93a77d52d6af054d358b55d45b4a5188Timo Sirainen view->transactions++;
c3cb859d93a77d52d6af054d358b55d45b4a5188Timo Sirainen}
c3cb859d93a77d52d6af054d358b55d45b4a5188Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenvoid mail_index_view_transaction_unref(struct mail_index_view *view)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(view->transactions > 0);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen view->transactions--;
3403e054eacf125e757bf6c66abf0ea9f086a4b6Timo Sirainen}
3403e054eacf125e757bf6c66abf0ea9f086a4b6Timo Sirainen
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainenstatic void mail_index_view_ref_map(struct mail_index_view *view,
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen struct mail_index_map *map)
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen{
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen struct mail_index_map *const *maps;
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen unsigned int i, count;
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen if (array_is_created(&view->map_refs)) {
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen maps = array_get(&view->map_refs, &count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen /* if map is already referenced, do nothing */
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen for (i = 0; i < count; i++) {
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen if (maps[i] == map)
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen return;
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen }
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen } else {
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen i_array_init(&view->map_refs, 4);
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen }
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen /* reference the given mapping. the reference is dropped when the view
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen is synchronized or closed. */
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen map->refcount++;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen array_append(&view->map_refs, &map, 1);
01e29d9d23a1844b4582592a473a3b3eac56b36bTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenvoid mail_index_view_unref_maps(struct mail_index_view *view)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index_map **maps;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen unsigned int i, count;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!array_is_created(&view->map_refs))
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen maps = array_get_modifiable(&view->map_refs, &count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (i = 0; i < count; i++)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_unmap(&maps[i]);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen array_clear(&view->map_refs);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic uint32_t _view_get_messages_count(struct mail_index_view *view)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return view->hdr.messages_count;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainenstatic const struct mail_index_header *
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen_view_get_header(struct mail_index_view *view)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return &view->hdr;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainenstatic int _view_lookup_full(struct mail_index_view *view, uint32_t seq,
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen struct mail_index_map **map_r,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_record **rec_r)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index_map *map;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_record *rec, *head_rec;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view));
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (mail_index_view_lock(view) < 0)
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch return -1;
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* look up the record */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen rec = MAIL_INDEX_MAP_IDX(view->map, seq-1);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (rec->uid == 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_set_error(view->index, "Corrupted Index file %s: "
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi "Record [%u].uid=0", view->index->filepath, seq);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_mark_corrupted(view->index);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return -1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen if (view->map == view->index->map) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* view's mapping is latest. we can use it directly. */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *map_r = view->map;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *rec_r = rec;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return 1;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen }
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen /* look up the record from head mapping. it may contain some changes. */
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen if (mail_index_view_lock_head(view) < 0)
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen return -1;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen /* start looking up from the same sequence as in the old view.
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen if there are no expunges, it's there. otherwise it's somewhere
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen before (since records can't be inserted).
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen usually there are only a few expunges, so just going downwards from
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen our initial sequence position is probably faster than binary
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen search. */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (seq > view->index->map->hdr.messages_count)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen seq = view->index->map->hdr.messages_count;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (seq == 0) {
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen /* everything is expunged from head. use the old record. */
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen *map_r = view->map;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *rec_r = rec;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen map = view->index->map;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen do {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen seq--;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen head_rec = MAIL_INDEX_MAP_IDX(map, seq);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (head_rec->uid <= rec->uid)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen break;
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen } while (seq > 0);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (head_rec->uid == rec->uid) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* found it. use it. reference the index mapping so that the
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen returned record doesn't get invalidated after next sync. */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_view_ref_map(view, view->index->map);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *map_r = view->index->map;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *rec_r = head_rec;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return 1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen } else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* expuned from head. use the old record. */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *map_r = view->map;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *rec_r = rec;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic int _view_lookup_uid(struct mail_index_view *view, uint32_t seq,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t *uid_r)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(view));
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (mail_index_view_lock(view) < 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return -1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *uid_r = MAIL_INDEX_MAP_IDX(view->map, seq-1)->uid;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic uint32_t mail_index_bsearch_uid(struct mail_index_view *view,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t uid, uint32_t left_idx,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen int nearest_side)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_record *rec_base, *rec;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t idx, right_idx, record_size;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(view->hdr.messages_count <= view->map->records_count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (uid == 1) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* optimization: the message can be only the first one */
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch return 1;
3281669db44d09a087a203201248abbc81b3cc1aTimo Sirainen }
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen rec_base = view->map->records;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen record_size = view->map->hdr.record_size;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen idx = left_idx;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen right_idx = view->hdr.messages_count;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen while (left_idx < right_idx) {
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen idx = (left_idx + right_idx) / 2;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (rec->uid < uid)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen left_idx = idx+1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen else if (rec->uid > uid)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen right_idx = idx;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen else
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen break;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(idx < view->hdr.messages_count);
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen if (rec->uid != uid) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (nearest_side > 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* we want uid or larger */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return rec->uid > uid ? idx+1 :
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen idx == view->hdr.messages_count-1 ? 0 : idx+2;
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen } else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* we want uid or smaller */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return rec->uid < uid ? idx + 1 : idx;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen return idx+1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic int _view_lookup_uid_range(struct mail_index_view *view,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t first_uid, uint32_t last_uid,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t *first_seq_r, uint32_t *last_seq_r)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(first_uid > 0);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(first_uid <= last_uid);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (mail_index_view_lock(view) < 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return -1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen if (view->hdr.messages_count == 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *first_seq_r = *last_seq_r = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *first_seq_r = mail_index_bsearch_uid(view, first_uid, 0, 1);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (*first_seq_r == 0 ||
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen MAIL_INDEX_MAP_IDX(view->map, *first_seq_r-1)->uid > last_uid) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *first_seq_r = *last_seq_r = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (last_uid >= view->map->hdr.next_uid-1) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* we want the last message */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen last_uid = view->map->hdr.next_uid-1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (first_uid > last_uid) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *first_seq_r = *last_seq_r = 0;
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen return 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *last_seq_r = view->hdr.messages_count;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (first_uid == last_uid)
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen *last_seq_r = *first_seq_r;
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* optimization - binary lookup only from right side: */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *last_seq_r = mail_index_bsearch_uid(view, last_uid,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *first_seq_r - 1, -1);
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen }
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen i_assert(*last_seq_r >= *first_seq_r);
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch return 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic int _view_lookup_first(struct mail_index_view *view,
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen enum mail_flags flags, uint8_t flags_mask,
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen uint32_t *seq_r)
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen{
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen#define LOW_UPDATE(x) \
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen STMT_START { if ((x) > low_uid) low_uid = x; } STMT_END
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen const struct mail_index_record *rec;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t seq, low_uid = 1;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *seq_r = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen if (mail_index_view_lock(view) < 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return -1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if ((flags_mask & MAIL_RECENT) != 0 && (flags & MAIL_RECENT) != 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen LOW_UPDATE(view->map->hdr.first_recent_uid_lowwater);
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen if ((flags_mask & MAIL_SEEN) != 0 && (flags & MAIL_SEEN) == 0)
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen LOW_UPDATE(view->map->hdr.first_unseen_uid_lowwater);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if ((flags_mask & MAIL_DELETED) != 0 && (flags & MAIL_DELETED) != 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen LOW_UPDATE(view->map->hdr.first_deleted_uid_lowwater);
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (low_uid == 1)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen seq = 1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (mail_index_lookup_uid_range(view, low_uid, low_uid,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen &seq, &seq) < 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return -1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen if (seq == 0)
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen return 0;
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen }
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(view->hdr.messages_count <= view->map->records_count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (; seq <= view->hdr.messages_count; seq++) {
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen rec = MAIL_INDEX_MAP_IDX(view->map, seq-1);
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen if ((rec->flags & flags_mask) == (uint8_t)flags) {
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen *seq_r = seq;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen break;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic int _view_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t ext_id, struct mail_index_map **map_r,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const void **data_r)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen const struct mail_index_ext *ext;
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen const struct mail_index_record *rec;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t idx, offset;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen int ret;
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if ((ret = mail_index_lookup_full(view, seq, map_r, &rec)) < 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return -1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen if (rec == NULL || !mail_index_map_get_ext_idx(*map_r, ext_id, &idx)) {
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen *data_r = NULL;
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen return ret;
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen }
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen ext = array_idx(&(*map_r)->extensions, idx);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen offset = ext->record_offset;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *data_r = offset == 0 ? NULL : CONST_PTR_OFFSET(rec, offset);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return ret;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainenstatic int _view_get_header_ext(struct mail_index_view *view,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index_map *map, uint32_t ext_id,
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen const void **data_r, size_t *data_size_r)
35e4905f732e1d25c71c47be3dbd747bc28cf642Timo Sirainen{
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen const struct mail_index_ext *ext;
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen uint32_t idx;
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen /* if we have a mapping, the view where it's from is already locked */
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen if (map == NULL) {
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen /* no mapping given, use head mapping */
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen if (mail_index_view_lock_head(view) < 0)
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen return -1;
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen map = view->index->map;
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen }
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen if (!mail_index_map_get_ext_idx(map, ext_id, &idx)) {
de9d79337eca11a7f9c1cd476c74dfe4f09a4bd7Timo Sirainen /* extension doesn't exist in this index file */
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen *data_r = NULL;
de9d79337eca11a7f9c1cd476c74dfe4f09a4bd7Timo Sirainen *data_size_r = 0;
de9d79337eca11a7f9c1cd476c74dfe4f09a4bd7Timo Sirainen return 0;
de9d79337eca11a7f9c1cd476c74dfe4f09a4bd7Timo Sirainen }
d1baa8c6f97cdb1b3c2c44a73cc21f9dfc7a963fTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ext = array_idx(&map->extensions, idx);
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen *data_r = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen *data_size_r = ext->hdr_size;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenvoid mail_index_view_close(struct mail_index_view **_view)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index_view *view = *_view;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *_view = NULL;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (--view->refcount > 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(view->transactions == 0);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen mail_index_view_unlock(view);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen view->v.close(view);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen}
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainenuint32_t mail_index_view_get_messages_count(struct mail_index_view *view)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return view->v.get_messages_count(view);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenconst struct mail_index_header *
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainenmail_index_get_header(struct mail_index_view *view)
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen{
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return view->v.get_header(view);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenint mail_index_lookup(struct mail_index_view *view, uint32_t seq,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_record **rec_r)
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index_map *map;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen return mail_index_lookup_full(view, seq, &map, rec_r);
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen}
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainenint mail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen struct mail_index_map **map_r,
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen const struct mail_index_record **rec_r)
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen{
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen return view->v.lookup_full(view, seq, map_r, rec_r);
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenint mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ARRAY_TYPE(keyword_indexes) *keyword_idx)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen struct mail_index_map *map;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen const void *data;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen const unsigned char *keyword_data;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen const unsigned int *keyword_idx_map;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen unsigned int i, j, keyword_count, index_idx;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen uint32_t ext_id, idx;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen uint16_t record_size;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen int ret;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen array_clear(keyword_idx);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen /* get the keywords data. */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen ext_id = view->index->keywords_ext_id;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen ret = mail_index_lookup_ext_full(view, seq, ext_id, &map, &data);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen if (ret < 0)
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return -1;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen if (data == NULL) {
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen /* no keywords at all in index */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return ret;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen }
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen (void)mail_index_ext_get_size(view, ext_id, map, NULL,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen &record_size, NULL);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen /* keyword_idx_map[] contains file => index keyword mapping */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen if (!array_is_created(&map->keyword_idx_map)) {
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen keyword_idx_map = NULL;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen keyword_count = 0;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen } else {
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen keyword_idx_map = array_get(&map->keyword_idx_map,
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen &keyword_count);
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen }
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen keyword_data = data;
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen for (i = 0, idx = 0; i < record_size; i++) {
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen /* first do the quick check to see if there's keywords at all */
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen if (keyword_data[i] == 0)
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen continue;
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen idx = i * CHAR_BIT;
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen for (j = 0; j < CHAR_BIT; j++, idx++) {
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen if ((keyword_data[i] & (1 << j)) == 0)
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen continue;
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen if (idx >= keyword_count) {
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen /* keyword header was updated, parse it again
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen it so we know what this keyword is called */
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen if (mail_index_map_parse_keywords(map) < 0)
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen return -1;
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen if (!array_is_created(&map->keyword_idx_map))
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen return ret;
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen /* pointer may have changed. update it. */
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen keyword_idx_map =
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen array_get(&map->keyword_idx_map,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen &keyword_count);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen if (idx >= keyword_count) {
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen /* extra bits set in keyword bytes.
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen shouldn't happen, but just ignore. */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen break;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen }
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen }
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen index_idx = keyword_idx_map[idx];
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen array_append(keyword_idx, &index_idx, 1);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen }
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen }
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return ret;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen}
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenint mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen uint32_t *uid_r)
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen{
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return view->v.lookup_uid(view, seq, uid_r);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen}
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenint mail_index_lookup_uid_range(struct mail_index_view *view,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen uint32_t first_uid, uint32_t last_uid,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen uint32_t *first_seq_r, uint32_t *last_seq_r)
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen{
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return view->v.lookup_uid_range(view, first_uid, last_uid,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen first_seq_r, last_seq_r);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen}
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen
af0a12ae492d79e27b29d63ff0f289f9034fecc9Stephan Boschint mail_index_lookup_first(struct mail_index_view *view, enum mail_flags flags,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen uint8_t flags_mask, uint32_t *seq_r)
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen{
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return view->v.lookup_first(view, flags, flags_mask, seq_r);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen}
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenint mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen uint32_t ext_id, const void **data_r)
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen{
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen struct mail_index_map *map;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return view->v.lookup_ext_full(view, seq, ext_id, &map, data_r);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen}
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenint mail_index_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen uint32_t ext_id, struct mail_index_map **map_r,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen const void **data_r)
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen{
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return view->v.lookup_ext_full(view, seq, ext_id, map_r, data_r);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen}
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenint mail_index_get_header_ext(struct mail_index_view *view, uint32_t ext_id,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen const void **data_r, size_t *data_size_r)
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen{
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return view->v.get_header_ext(view, NULL, ext_id, data_r, data_size_r);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen}
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
int mail_index_map_get_header_ext(struct mail_index_view *view,
struct mail_index_map *map, uint32_t ext_id,
const void **data_r, size_t *data_size_r)
{
return view->v.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_vfuncs view_vfuncs = {
_view_close,
_view_get_messages_count,
_view_get_header,
_view_lookup_full,
_view_lookup_uid,
_view_lookup_uid_range,
_view_lookup_first,
_view_lookup_ext_full,
_view_get_header_ext
};
struct mail_index_view *
mail_index_view_open_with_map(struct mail_index_map *map)
{
struct mail_index_view *view;
view = i_new(struct mail_index_view, 1);
view->refcount = 1;
view->v = view_vfuncs;
view->index = map->index;
view->log_view = mail_transaction_log_view_open(map->index->log);
view->indexid = map->index->indexid;
view->map = map;
view->map->refcount++;
view->hdr = view->map->hdr;
view->log_file_expunge_seq = view->log_file_head_seq =
view->map->hdr.log_file_seq;
view->log_file_expunge_offset = view->log_file_head_offset =
view->map->hdr.log_file_head_offset;
i_array_init(&view->module_contexts,
I_MIN(5, mail_index_module_register.id));
return view;
}
struct mail_index_view *mail_index_view_open(struct mail_index *index)
{
return mail_index_view_open_with_map(index->map);
}
const struct mail_index_ext *
mail_index_view_get_ext(struct mail_index_view *view, uint32_t ext_id)
{
uint32_t idx;
if (!mail_index_map_get_ext_idx(view->map, ext_id, &idx))
return 0;
return array_idx(&view->map->extensions, idx);
}