mail-index-view-sync.c revision 94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cb
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenmail_transaction_log_sort_expunges(ARRAY_TYPE(seq_range) *expunges,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* Note that all the sequences are actually still UIDs at this point */
139cbf8d9e1cc0c65d985f525756fe47a7bfada6Timo Sirainen /* @UNSAFE */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen dest = array_get_modifiable(expunges, &dest_count);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen array_append(expunges, src, src_size / sizeof(*src));
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* src[] must be sorted. */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(src+1 == src_end || src->seq2 < src[1].seq1);
0f17bb103602d0c4394e3784cb96d788530fc79eTimo Sirainen for (; i < dest_count; i++) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen while (i < dest_count && src->seq2 >= dest[i].seq1-1) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* we can/must merge with next record */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (first > 0 && new_exp.seq1 <= dest[first-1].seq2+1) {
c8cf8a605e0ddea7cb36fe04551aeca5090e684bTimo Sirainen /* continue previous record */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen } else if (i == first) {
f6d63a21010540d3ddf08f2e7664ffca3ea70489Timo Sirainen dest = array_get_modifiable(expunges, &dest_count);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* use next record */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen dest = array_get_modifiable(expunges, &dest_count);
a5bb2908b44c8bf5ce41160a64c67fb840a20006Timo Sirainenstatic int view_sync_set_log_view_range(struct mail_index_view *view,
a5bb2908b44c8bf5ce41160a64c67fb840a20006Timo Sirainen const struct mail_index_header *hdr = view->index->hdr;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ret = mail_transaction_log_view_set(view->log_view,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* FIXME: use the new index to get needed changes */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen "Transaction log got desynced for index %s",
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainenview_sync_get_expunges(struct mail_index_view *view,
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde unsigned int count;
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen if (view_sync_set_log_view_range(view, MAIL_TRANSACTION_EXPUNGE) < 0)
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen i_assert((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0);
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen mail_transaction_log_sort_expunges(expunges_r, data, hdr->size);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* convert UIDs to sequences */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen src = dest = array_get_modifiable(expunges_r, &count);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen ret = mail_index_lookup_uid_range(view, src->seq1,
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen array_delete(expunges_r, count, array_count(expunges_r) - count);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainenstatic void mail_index_view_hdr_update(struct mail_index_view *view,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* Keep message count the same. */
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen map->hdr.messages_count = view->hdr.messages_count;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* Keep the old message flag counts also, although they may be
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen somewhat stale already. We just don't want them to be more than
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen our old messages_count. */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen map->hdr.recent_messages_count = view->hdr.recent_messages_count;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen map->hdr.seen_messages_count = view->hdr.seen_messages_count;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen map->hdr.deleted_messages_count = view->hdr.deleted_messages_count;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* Keep log position so we know where to continue syncing */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen map->hdr.log_file_seq = view->hdr.log_file_seq;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen map->hdr.log_file_int_offset = view->hdr.log_file_int_offset;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen map->hdr.log_file_ext_offset = view->hdr.log_file_ext_offset;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen buffer_write(map->hdr_copy_buf, 0, &map->hdr, sizeof(map->hdr));
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD | MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE)
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen (MAIL_TRANSACTION_EXPUNGE | MAIL_TRANSACTION_APPEND | \
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen MAIL_TRANSACTION_FLAG_UPDATE | MAIL_TRANSACTION_KEYWORD_UPDATE | \
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenint mail_index_view_sync_begin(struct mail_index_view *view,
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen enum mail_transaction_type log_get_mask, visible_mask;
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen /* We must sync flags as long as view is mmap()ed, as the flags may
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen have already changed under us. */
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen i_assert((sync_mask & MAIL_INDEX_VIEW_VISIBLE_FLAGS_MASK) ==
d927bc5618696157fc55eb1f11b5cab05400ed52Timo Sirainen /* Currently we're not handling correctly expunges + no-appends case */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen i_assert((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) == 0 ||
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen (sync_mask & MAIL_INDEX_SYNC_TYPE_APPEND) != 0);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (mail_index_view_lock_head(view, TRUE) < 0)
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0) {
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen /* get list of all expunges first */
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen if (view_sync_get_expunges(view, &expunges) < 0)
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen /* only flags, appends and expunges can be left to be synced later */
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen visible_mask = mail_transaction_type_mask_get(sync_mask);
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen i_assert((visible_mask & ~MAIL_TRANSACTION_VISIBLE_SYNC_MASK) == 0);
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen /* we want to also get non-visible changes. especially because we use
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen the returned skipped-flag in mail_transaction_log_view_next() to
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen tell us if any visible changes were skipped. */
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen log_get_mask = visible_mask | (MAIL_TRANSACTION_TYPE_MASK ^
d927bc5618696157fc55eb1f11b5cab05400ed52Timo Sirainen if (view_sync_set_log_view_range(view, log_get_mask) < 0) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen ctx = i_new(struct mail_index_view_sync_ctx, 1);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mail_index_sync_map_init(&ctx->sync_map_ctx, view,
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0 &&
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen (sync_mask & MAIL_INDEX_SYNC_TYPE_APPEND) != 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* since we're syncing everything, the counters get fixed */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* keep the old mapping without expunges until we're
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen fully synced */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* We need a private copy of the map if we don't want to
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen sync expunges.
f534c0d42f1470fca8e4ff3493c94927bf600260Timo Sirainen If view's map is the head map, it means that it contains
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen already all the latest changes and there's no need for us
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen to apply any changes to it. This can only happen if there
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen hadn't been any expunges. */
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen uint32_t old_records_count = view->map->records_count;
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen /* Using non-head mapping. We have to apply
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen transactions to it to get latest changes into it. */
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen /* Unless map was synced at the exact same position as
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen view, the message flags can't be reliably used to
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen update flag counters. */
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen /* Copy only the mails that we see currently, since
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen we're going to append the new ones when we see
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen their transactions. */
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen view->map->records_count = view->hdr.messages_count;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen /* Start the sync using our old view's header.
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen The old view->hdr may differ from map->hdr if
60b42c6dfdf9edcca8a96b380ef9a0adc60c2464Timo Sirainen another view sharing the map with us had synced
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(map->hdr_base == map->hdr_copy_buf->data);
4ed1c0fedf33299264a319b2c4e0fe2465ea321bTimo Sirainen i_assert(map->records_count == map->hdr.messages_count);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* Syncing the view invalidates all previous looked up records.
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen Unreference the mappings this view keeps because of them. */
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainenstatic bool view_sync_pos_find(ARRAY_TYPE(view_log_sync_pos) *sync_arr,
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen const struct mail_index_view_log_sync_pos *syncs;
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen unsigned int i, count;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen for (i = 0; i < count; i++) {
31327a74b86728e201fcedd0acaecf69d077bf1dTimo Sirainenmail_index_view_sync_get_next_transaction(struct mail_index_view_sync_ctx *ctx)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct mail_transaction_log_view *log_view = ctx->view->log_view;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* Get the next transaction from log. */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen ret = mail_transaction_log_view_next(log_view, &ctx->hdr,
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen mail_transaction_log_view_get_prev_pos(log_view, &seq, &offset);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* We skipped some (visible) transactions that were
d00ae137b6772f0b047cc98cb153f11c5246f82bTimo Sirainen outside our sync mask. */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* We haven't skipped anything while syncing this view.
MAIL_TRANSACTION_EXPUNGE) == 0);
store +flags.silent command) */
#define FLAG_UPDATE_IS_INTERNAL(u) \
case MAIL_TRANSACTION_APPEND: {
case MAIL_TRANSACTION_EXPUNGE: {
case MAIL_TRANSACTION_FLAG_UPDATE: {
case MAIL_TRANSACTION_KEYWORD_UPDATE: {
case MAIL_TRANSACTION_KEYWORD_RESET: {
i_unreached();
int ret;
if (ret <= 0)
return ret;
unsigned int i, count;
for (i = 0; i < count; i++) {