mail-index-view.c revision 7797aa2479e99aeb71057b7a2584b2cb72e4d3f8
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_view_clone(struct mail_index_view *dest,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen dest->log_view = mail_transaction_log_view_open(src->index->log);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void _view_close(struct mail_index_view *view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_transaction_log_view_close(view->log_view);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int mail_index_view_map_protect(struct mail_index_view *view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* not head mapping, no need to lock */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_index_map_lock_mprotect(view->index, view->map,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_index_view_lock_head(struct mail_index_view *view, int update_index)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen unsigned int lock_id;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (MAIL_INDEX_MAP_IS_IN_MEMORY(view->index->map))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!mail_index_is_locked(view->index, view->lock_id)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_index_lock_shared(view->index, update_index,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (mail_index_map(view->index, FALSE) <= 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* index was rebuilt */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (mail_index_lock_shared(view->index, TRUE, &lock_id) < 0)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen mail_index_unlock(view->index, view->lock_id);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen /* mail_index_lock_shared() may have reopened the file,
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen so do this after it. */
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenint mail_index_view_lock(struct mail_index_view *view)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return mail_index_view_lock_head(view, FALSE);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenvoid mail_index_view_unlock(struct mail_index_view *view)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen (void)mail_index_map_lock_mprotect(view->index, view->map,
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen mail_index_unlock(view->index, view->lock_id);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_index_view_is_inconsistent(struct mail_index_view *view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_index *mail_index_view_get_index(struct mail_index_view *view)
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainenvoid mail_index_view_transaction_ref(struct mail_index_view *view)
e192a3b1ca8ae857e7d87298ea507d32977ba570Timo Sirainenvoid mail_index_view_transaction_unref(struct mail_index_view *view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void mail_index_view_ref_map(struct mail_index_view *view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen maps = buffer_get_data(view->map_refs, &size);
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen for (i = 0; i < size; i++) {
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen buffer_create_dynamic(default_pool, 128, (size_t)-1);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen buffer_append(view->map_refs, &map, sizeof(map));
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenvoid mail_index_view_unref_maps(struct mail_index_view *view)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen maps = buffer_get_modifyable_data(view->map_refs, &size);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen for (i = 0; i < size; i++)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainenstatic uint32_t _view_get_message_count(struct mail_index_view *view)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainenstatic int _view_get_header(struct mail_index_view *view,
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (view->map->hdr->messages_count == view->messages_count)
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen /* messages_count differs, use a modified copy.
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen FIXME: so might seen_messages_count, etc. and they're
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen more difficult to fix. maybe grab a copy of the header
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen when opening the view initially?.. */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen view->tmp_hdr_copy.messages_count = view->messages_count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int _view_lookup_full(struct mail_index_view *view, uint32_t seq,
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_message_count(view));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_index_view_lock_head(view, FALSE) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* look for it in the head mapping */
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen // FIXME: we could be skipping more by uid diff
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen } while (seq > 0);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen mail_index_view_ref_map(view, view->index->map);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int _view_lookup_uid(struct mail_index_view *view, uint32_t seq,
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_message_count(view));
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen *uid_r = MAIL_INDEX_MAP_IDX(view->map, seq-1)->uid;
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainenstatic uint32_t mail_index_bsearch_uid(struct mail_index_view *view,
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen const struct mail_index_record *rec_base, *rec;
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen uint32_t idx, left_idx, right_idx, record_size;
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen i_assert(view->messages_count <= view->map->records_count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen /* no messages available */
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* we want uid or larger */
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen /* we want uid or smaller */
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainenstatic int _view_lookup_uid_range(struct mail_index_view *view,
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen *first_seq_r = mail_index_bsearch_uid(view, first_uid, &left_idx, 1);
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen MAIL_INDEX_MAP_IDX(view->map, *first_seq_r-1)->uid > last_uid) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* optimization - binary lookup only from right side: */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen *last_seq_r = mail_index_bsearch_uid(view, last_uid, &left_idx, -1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int _view_lookup_first(struct mail_index_view *view,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen STMT_START { if ((x) > low_uid) low_uid = x; } STMT_END
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if ((flags_mask & MAIL_RECENT) != 0 && (flags & MAIL_RECENT) != 0)
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen LOW_UPDATE(view->map->hdr->first_recent_uid_lowwater);
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen if ((flags_mask & MAIL_SEEN) != 0 && (flags & MAIL_SEEN) == 0)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen LOW_UPDATE(view->map->hdr->first_unseen_uid_lowwater);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if ((flags_mask & MAIL_DELETED) != 0 && (flags & MAIL_DELETED) != 0)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen LOW_UPDATE(view->map->hdr->first_deleted_uid_lowwater);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (mail_index_lookup_uid_range(view, low_uid, low_uid,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if ((rec->flags & flags_mask) == (uint8_t)flags) {
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainenstatic int _view_lookup_ext(struct mail_index_view *view, uint32_t seq,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if ((ret = mail_index_lookup_full(view, seq, &map, &rec)) < 0)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen !mail_index_map_get_ext_idx(view->map, ext_id, &idx)) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen *data_r = offset == 0 ? NULL : CONST_PTR_OFFSET(rec, offset);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenvoid mail_index_view_close(struct mail_index_view *view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenuint32_t mail_index_view_get_message_count(struct mail_index_view *view)
21455709020274a628faa9b9bd7839cb8efe3c73Timo Sirainenint mail_index_get_header(struct mail_index_view *view,
114a0f74e0f825c6bd8aeadfafb248a030762a1fTimo Sirainenint mail_index_lookup(struct mail_index_view *view, uint32_t seq,
7981779f9aebd25728d3c26555d598ff842cf2e2Timo Sirainen return mail_index_lookup_full(view, seq, &map, rec_r);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainenint mail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return view->methods.lookup_full(view, seq, map_r, rec_r);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return view->methods.lookup_uid(view, seq, uid_r);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenint mail_index_lookup_uid_range(struct mail_index_view *view,
089756ceca55966f1a70e8591f6086026e51015cTimo Sirainen return view->methods.lookup_uid_range(view, first_uid, last_uid,
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainenint mail_index_lookup_first(struct mail_index_view *view, enum mail_flags flags,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return view->methods.lookup_first(view, flags, flags_mask, seq_r);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenint mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return view->methods.lookup_ext(view, seq, ext_id, data_r);
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainenstatic struct mail_index_view_methods view_methods = {
62cfc346eb7b0a4fd9e1ab6edd63b98711161229Timo Sirainenstruct mail_index_view *mail_index_view_open(struct mail_index *index)
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen view->log_view = mail_transaction_log_view_open(index->log);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen view->messages_count = view->map->records_count;