mail-index-view-sync.c revision 3f99d19bf3361a4b0952e4e3ad64d4d6988de469
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2003-2009 Dovecot authors, see the included COPYING file */
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen /* After syncing view, map is replaced with sync_new_map. */
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen /* temporary variables while handling lost transaction logs: */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ARRAY_TYPE(keyword_indexes) lost_old_kw, lost_new_kw;
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen /* result of lost transaction logs: */
49e9acb52bb5d328f8cf10bce1082c4bc213caeaTimo Sirainenview_sync_set_log_view_range(struct mail_index_view *view, bool sync_expunges,
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen const struct mail_index_header *hdr = &view->index->map->hdr;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* the view begins from the first non-synced transaction */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen ret = mail_transaction_log_view_set(view->log_view,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* log was reset, but we don't want to sync expunges.
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen we can't do this, so sync only up to the reset. */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen mail_transaction_log_view_get_prev_pos(view->log_view,
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* we have only this reset log */
c680a6b35b459045e92814778908da5a93922107Timo Sirainen mail_transaction_log_view_clear(view->log_view,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic unsigned int
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenview_sync_expunges2seqs(struct mail_index_view_sync_ctx *ctx)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* convert UIDs to sequences */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen src = dest = array_get_modifiable(&ctx->expunges, &count);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (!mail_index_lookup_seq_range(view, src->seq1, src->seq2,
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainenview_sync_add_expunge_range(ARRAY_TYPE(seq_range) *dest,
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen unsigned int i, src_count;
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen for (i = 0; i < src_count; i++)
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen seq_range_array_add_range(dest, src[i].seq1, src[i].seq2);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenview_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
5cdd348121e62a6244ba2f93db781731f7129a71Timo Sirainen /* get a list of expunge transactions. there may be some that we have
5cdd348121e62a6244ba2f93db781731f7129a71Timo Sirainen already synced, but it doesn't matter because they'll get dropped
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen out when converting to sequences. the uid ranges' validity has
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen already been verified, so we can use them directly. */
b43bb773ee6534c1013b01a62fbd5703e3b0d17dTimo Sirainen mail_transaction_log_view_mark(view->log_view);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0)
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen /* this is simply a request for expunge */
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen view_sync_add_expunge_range(&ctx->expunges, data, hdr->size);
b43bb773ee6534c1013b01a62fbd5703e3b0d17dTimo Sirainen mail_transaction_log_view_rewind(view->log_view);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen *expunge_count_r = view_sync_expunges2seqs(ctx);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainenstatic bool have_existing_expunges(struct mail_index_view *view,
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen if (mail_index_lookup_seq_range(view, range->seq1, range->seq2,
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainenstatic bool view_sync_have_expunges(struct mail_index_view *view)
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen mail_transaction_log_view_mark(view->log_view);
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0)
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen /* this is simply a request for expunge */
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen /* we have an expunge. see if it still exists. */
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen if (have_existing_expunges(view, data, hdr->size)) {
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen mail_transaction_log_view_rewind(view->log_view);
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen /* handle failures as having expunges (which is safer).
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen we'll probably fail later. */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic int uint_cmp(const void *p1, const void *p2)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic bool view_sync_lost_keywords_equal(struct mail_index_view_sync_ctx *ctx)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen old_idx = array_get_modifiable(&ctx->lost_old_kw, &old_count);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen new_idx = array_get_modifiable(&ctx->lost_new_kw, &new_count);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen qsort(old_idx, old_count, sizeof(*old_idx), uint_cmp);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen qsort(new_idx, new_count, sizeof(*new_idx), uint_cmp);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return memcmp(old_idx, new_idx, old_count * sizeof(old_idx)) == 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic int view_sync_update_keywords(struct mail_index_view_sync_ctx *ctx,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen const unsigned int *kw_idx;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen const char *const *kw_names;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen unsigned int i, count;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen kw_idx = array_get(&ctx->lost_new_kw, &count);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen kw_names = array_idx(&ctx->view->index->keywords, 0);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen thdr.type = MAIL_TRANSACTION_KEYWORD_UPDATE | MAIL_TRANSACTION_EXTERNAL;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* add new flags one by one */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen for (i = 0; i < count; i++) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen kw_up.name_size = strlen(kw_names[kw_idx[i]]);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen buffer_append(ctx->lost_kw_buf, &kw_up, sizeof(kw_up));
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen buffer_append(ctx->lost_kw_buf, kw_names[kw_idx[i]],
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen buffer_append(ctx->lost_kw_buf, &uid, sizeof(uid));
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen buffer_append(ctx->lost_kw_buf, &uid, sizeof(uid));
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (mail_index_sync_record(&ctx->sync_map_ctx, &thdr,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic int view_sync_apply_lost_changes(struct mail_index_view_sync_ctx *ctx,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct mail_index_map *old_map = ctx->view->map;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct mail_index_map *new_map = ctx->view->index->map;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen const struct mail_index_record *old_rec, *new_rec;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen old_rec = MAIL_INDEX_MAP_IDX(old_map, old_seq - 1);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen new_rec = MAIL_INDEX_MAP_IDX(new_map, new_seq - 1);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct mail_transaction_flag_update flag_update;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* check this before syncing the record, since it updates
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if ((old_rec->flags & MAIL_INDEX_FLAGS_MASK) !=
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen flag_update.uid1 = flag_update.uid2 = new_rec->uid;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen flag_update.remove_flags = ~new_rec->flags & 0xff;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (mail_index_sync_record(&ctx->sync_map_ctx, &thdr,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mail_index_map_lookup_keywords(old_map, old_seq, &ctx->lost_old_kw);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mail_index_map_lookup_keywords(new_map, new_seq, &ctx->lost_new_kw);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct mail_transaction_keyword_reset kw_reset;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* remove all old flags by resetting them */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (mail_index_sync_record(&ctx->sync_map_ctx, &thdr,
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen /* flags or keywords changed */
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen /* if modseq has changed include this message in changed flags
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen list, even if we didn't see any changes above. */
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen ext = array_idx(&new_map->extensions, ctx->lost_new_ext_idx);
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen modseqp = CONST_PTR_OFFSET(new_rec, ext->record_offset);
b6612c334604eeb27e1ca2bd804ac66dcbc2eaadTimo Sirainen /* without modseqs lost_flags isn't updated perfectly correctly, because
b6612c334604eeb27e1ca2bd804ac66dcbc2eaadTimo Sirainen by the time we're comparing old flags it may have changed from what
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen we last sent to the client (because the map is shared). This could
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen be avoided by always keeping a private copy of the map in the view,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen but that's a waste of memory for as rare of a problem as this. */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen seq_range_array_add(&ctx->lost_flags, 0, new_rec->uid);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenview_sync_get_log_lost_changes(struct mail_index_view_sync_ctx *ctx,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct mail_index_map *new_map = view->index->map;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen const unsigned int old_count = old_map->hdr.messages_count;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen const unsigned int new_count = new_map->hdr.messages_count;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen const struct mail_index_record *old_rec, *new_rec;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen unsigned int i, j;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* we don't update the map in the same order as it's typically done.
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen map->rec_map may already have some messages appended that we don't
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen want. get an atomic map to make sure these get removed. */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen (void)mail_index_sync_get_atomic_map(&ctx->sync_map_ctx);
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen if (!mail_index_map_get_ext_idx(new_map, view->index->modseq_ext_id,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ctx->lost_kw_buf = buffer_create_dynamic(pool_datastack_create(), 128);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* handle expunges and sync flags */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* message found - check if flags have changed */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (view_sync_apply_lost_changes(ctx, i + 1, j + 1) < 0)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* message expunged */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen seq_range_array_add(&ctx->expunges, 0, old_rec->uid);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* new message appeared out of nowhere */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen "%s view is inconsistent: "
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen "uid=%u inserted in the middle of mailbox",
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* if there are old messages left, they're all expunged */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen for (; i < old_count; i++) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen seq_range_array_add(&ctx->expunges, 0, old_rec->uid);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* if there are new messages left, they're all new messages */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen thdr.type = MAIL_TRANSACTION_APPEND | MAIL_TRANSACTION_EXTERNAL;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen for (; j < new_count; j++) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (mail_index_sync_record(&ctx->sync_map_ctx,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mail_index_map_lookup_keywords(new_map, j + 1,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen *expunge_count_r = view_sync_expunges2seqs(ctx);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* we have no idea how far we've synced - make sure these aren't used */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if ((ctx->flags & MAIL_INDEX_VIEW_SYNC_FLAG_NOEXPUNGES) != 0) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen view->log_file_head_seq = new_map->hdr.log_file_seq;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen view->log_file_head_offset = new_map->hdr.log_file_head_offset;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainenstatic int mail_index_view_sync_init_fix(struct mail_index_view_sync_ctx *ctx)
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen /* replace the view's map */
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen /* update log positions */
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen view->log_file_head_seq = seq = view->map->hdr.log_file_seq;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen if (mail_transaction_log_view_set(view->log_view, seq, offset,
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainenmail_index_view_sync_begin(struct mail_index_view *view,
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen unsigned int expunge_count = 0;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen /* Syncing the view invalidates all previous looked up records.
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen Unreference the mappings this view keeps because of them. */
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen ctx = i_new(struct mail_index_view_sync_ctx, 1);
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen sync_expunges = (flags & MAIL_INDEX_VIEW_SYNC_FLAG_NOEXPUNGES) == 0;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen if ((flags & MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT) != 0) {
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen /* just get this view synced - don't return anything */
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen mail_index_set_error(view->index, "%s view is inconsistent",
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ret = view_sync_set_log_view_range(view, sync_expunges, &reset);
98daad9e5bf9bb1ce8fcddd45b350fce953a0bdeTimo Sirainen mail_index_sync_map_init(&ctx->sync_map_ctx, view,
98daad9e5bf9bb1ce8fcddd45b350fce953a0bdeTimo Sirainen ret = view_sync_get_log_lost_changes(ctx, &expunge_count);
98daad9e5bf9bb1ce8fcddd45b350fce953a0bdeTimo Sirainen mail_index_modseq_sync_end(&ctx->sync_map_ctx.modseq_ctx);
98daad9e5bf9bb1ce8fcddd45b350fce953a0bdeTimo Sirainen mail_index_sync_map_deinit(&ctx->sync_map_ctx);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen "%s view syncing failed to apply changes",
1d06a935b555024420d1c22249f0c847e51a9b7aTimo Sirainen /* get list of all expunges first */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (view_sync_get_expunges(ctx, &expunge_count) < 0) {
1103e7320af882c2c649841612b99b4502cb82a2Timo Sirainen have_expunges = view_sync_have_expunges(view);
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen view->map->hdr.messages_count - expunge_count;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen if (reset && view->map->hdr.messages_count > 0) {
530c3ece3717ad8193046ea7774227f91971a0dcTimo Sirainen "%s reset, view is now inconsistent",
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen /* no expunges, we can just replace the map */
07afd4db18860589803c46a3ee0559bda1c9e1b4Timo Sirainen "Index %s lost messages without expunging "
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen /* expunges seen. create a private map which we update.
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen if we're syncing expunges the map will finally be replaced
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen with the head map to remove the expunged messages. */
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen mail_index_sync_map_init(&ctx->sync_map_ctx, view,
24c6aaf3c540d078021bb4a326982ae4e3d7eaf8Timo Sirainenview_sync_is_hidden(struct mail_index_view *view, uint32_t seq, uoff_t offset)
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen const struct mail_index_view_log_sync_area *syncs;
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen unsigned int i, count;
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainen syncs = array_get(&view->syncs_hidden, &count);
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen for (i = 0; i < count; i++) {
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen offset - syncs[i].log_file_offset < syncs[i].length &&
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainenmail_index_view_sync_want(struct mail_index_view_sync_ctx *ctx,
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen mail_transaction_log_view_get_prev_pos(view->log_view, &seq, &offset);
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen next_offset = offset + sizeof(*hdr) + hdr->size;
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0 &&
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainen (hdr->type & MAIL_TRANSACTION_EXTERNAL) != 0) {
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainen if ((ctx->flags & MAIL_INDEX_VIEW_SYNC_FLAG_NOEXPUNGES) != 0) {
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen if (LOG_IS_BEFORE(seq, offset, view->log_file_expunge_seq,
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen /* already synced */
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen if (LOG_IS_BEFORE(seq, offset, view->log_file_head_seq,
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen /* already synced */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainenmail_index_view_sync_get_next_transaction(struct mail_index_view_sync_ctx *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_transaction_log_view *log_view = ctx->view->log_view;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* Get the next transaction from log. */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen ret = mail_transaction_log_view_next(log_view, &ctx->hdr,
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen /* skip records we've already synced */
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen } while (!mail_index_view_sync_want(ctx, hdr));
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen mail_transaction_log_view_get_prev_pos(log_view, &seq, &offset);
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen /* If we started from a map that we didn't create ourself,
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen some of the transactions may already be synced. at the end
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen of this view sync we'll update file_seq=0 so that this check
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen always becomes FALSE for subsequent syncs. */
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen synced_to_map = view->map->hdr.log_file_seq != 0 &&
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen LOG_IS_BEFORE(seq, offset, view->map->hdr.log_file_seq,
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen /* Apply transaction to view's mapping if needed (meaning we
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen didn't just re-map the view to head mapping). */
a641c92cc81453fa9c82e721f9bb8c06a987235bTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0) T_BEGIN {
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen ret = mail_index_sync_record(&ctx->sync_map_ctx,
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen ctx->hidden = view_sync_is_hidden(view, seq, offset);
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainenmail_index_view_sync_get_rec(struct mail_index_view_sync_ctx *ctx,
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen const struct mail_transaction_header *hdr = ctx->hdr;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen const struct mail_transaction_flag_update *update =
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* data contains mail_transaction_flag_update[] */
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen if (!MAIL_TRANSACTION_FLAG_UPDATE_IS_INTERNAL(update))
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* skip internal flag changes */
d0143523a87b41eae0b118ff03aad539903b3555Timo Sirainen update = CONST_PTR_OFFSET(data, ctx->data_offset);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen const struct mail_transaction_keyword_update *update = data;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* data contains mail_transaction_keyword_update header,
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen the keyword name and an array of { uint32_t uid1, uid2; } */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* skip over the header and name */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen ctx->data_offset = sizeof(*update) + update->name_size;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen ctx->data_offset += 4 - (ctx->data_offset % 4);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen uids = CONST_PTR_OFFSET(data, ctx->data_offset);
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen const struct mail_transaction_keyword_reset *reset =
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* data contains mail_transaction_keyword_reset[] */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenmail_index_view_sync_next_lost(struct mail_index_view_sync_ctx *ctx,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen unsigned int count;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen sync_rec->type = MAIL_INDEX_VIEW_SYNC_TYPE_FLAGS;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen sync_rec->uid1 = range[ctx->lost_flag_idx].seq1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen sync_rec->uid2 = range[ctx->lost_flag_idx].seq2;
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainenbool mail_index_view_sync_next(struct mail_index_view_sync_ctx *ctx,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return mail_index_view_sync_next_lost(ctx, sync_rec);
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen if (ctx->hdr == NULL || ctx->data_offset == ctx->hdr->size) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen ret = mail_index_view_sync_get_next_transaction(ctx);
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen } while (!mail_index_view_sync_get_rec(ctx, sync_rec));
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainenvoid mail_index_view_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainenmail_index_view_sync_clean_log_syncs(struct mail_index_view *view)
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen const struct mail_index_view_log_sync_area *syncs;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen unsigned int i, count;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen /* Clean up to view's tail */
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen syncs = array_get(&view->syncs_hidden, &count);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen for (i = 0; i < count; i++) {
cc6ed00c61fda24799c905e403b94a2a8c39ae5cTimo Sirainen syncs[i].length > view->log_file_expunge_offset &&
cc6ed00c61fda24799c905e403b94a2a8c39ae5cTimo Sirainen syncs[i].log_file_seq == view->log_file_expunge_seq) ||
cc6ed00c61fda24799c905e403b94a2a8c39ae5cTimo Sirainen syncs[i].log_file_seq > view->log_file_expunge_seq)
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainenint mail_index_view_sync_commit(struct mail_index_view_sync_ctx **_ctx,
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen if ((!ctx->last_read || view->inconsistent) &&
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen (ctx->flags & MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT) == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we didn't sync everything */
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen mail_index_modseq_sync_end(&ctx->sync_map_ctx.modseq_ctx);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* log offsets have no meaning in views. make sure they're not
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen tried to be used wrong by setting them to zero. */
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen i_assert(view->map->hdr.messages_count >= ctx->finish_min_msg_count);
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen view->log_file_expunge_seq = view->log_file_head_seq;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen view->log_file_expunge_offset = view->log_file_head_offset;
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen mail_index_sync_map_deinit(&ctx->sync_map_ctx);
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen mail_index_view_sync_clean_log_syncs(ctx->view);
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen /* set log view to empty range so unneeded memory gets freed */
c680a6b35b459045e92814778908da5a93922107Timo Sirainen mail_transaction_log_view_clear(view->log_view,
b6612c334604eeb27e1ca2bd804ac66dcbc2eaadTimo Sirainen view->highest_modseq = mail_index_map_modseq_get_highest(view->map);
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainenvoid mail_index_view_add_hidden_transaction(struct mail_index_view *view,
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen unsigned int length)