mail-index-view-sync.c revision bcb4e51a409d94ae670de96afb8483a4f7855294
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "array.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "buffer.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-view-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-sync-private.h"
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen#include "mail-index-modseq.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-transaction-log.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_index_view_sync_ctx {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_view *view;
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainen enum mail_index_view_sync_flags flags;
56561d472db25ebda35ae6afdc7f7deb75c323fcTimo Sirainen struct mail_index_sync_map_ctx sync_map_ctx;
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen /* After syncing view, map is replaced with sync_new_map. */
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen struct mail_index_map *sync_new_map;
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen ARRAY_TYPE(seq_range) expunges;
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen unsigned int finish_min_msg_count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_transaction_header *hdr;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const void *data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen /* temporary variables while handling lost transaction logs: */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ARRAY_TYPE(keyword_indexes) lost_old_kw, lost_new_kw;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen buffer_t *lost_kw_buf;
b6612c334604eeb27e1ca2bd804ac66dcbc2eaadTimo Sirainen uint32_t lost_new_ext_idx;
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen /* result of lost transaction logs: */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ARRAY_TYPE(seq_range) lost_flags;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen unsigned int lost_flag_idx;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen size_t data_offset;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool failed:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool sync_map_update:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool skipped_expunges:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool last_read:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool log_was_lost:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool hidden:1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen};
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenstatic int
49e9acb52bb5d328f8cf10bce1082c4bc213caeaTimo Sirainenview_sync_set_log_view_range(struct mail_index_view *view, bool sync_expunges,
407d64647d77771080eb75f800162014927f10c6Timo Sirainen bool *reset_r, bool *partial_sync_r)
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen{
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen const struct mail_index_header *hdr = &view->index->map->hdr;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen uint32_t start_seq, end_seq;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen uoff_t start_offset, end_offset;
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen const char *reason;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen int ret;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen
407d64647d77771080eb75f800162014927f10c6Timo Sirainen *partial_sync_r = FALSE;
407d64647d77771080eb75f800162014927f10c6Timo Sirainen
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen start_seq = view->log_file_expunge_seq;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen start_offset = view->log_file_expunge_offset;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen end_seq = hdr->log_file_seq;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen end_offset = hdr->log_file_head_offset;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen if (end_seq < view->log_file_head_seq ||
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen (end_seq == view->log_file_head_seq &&
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen end_offset < view->log_file_head_offset)) {
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen mail_index_set_error(view->index,
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen "%s log position went backwards "
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen "(%u,%"PRIuUOFF_T" < %u,%"PRIuUOFF_T")",
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen view->index->filepath, end_seq, end_offset,
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen view->log_file_head_seq, view->log_file_head_offset);
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen return -1;
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen }
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen for (;;) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* the view begins from the first non-synced transaction */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen ret = mail_transaction_log_view_set(view->log_view,
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen start_seq, start_offset,
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen end_seq, end_offset,
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen reset_r, &reason);
20a10690f6dd922b36f72f995c95b96face85971Timo Sirainen if (ret <= 0) {
20a10690f6dd922b36f72f995c95b96face85971Timo Sirainen mail_index_set_error(view->index,
20a10690f6dd922b36f72f995c95b96face85971Timo Sirainen "Failed to map view for %s: %s",
20a10690f6dd922b36f72f995c95b96face85971Timo Sirainen view->index->filepath, reason);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return ret;
20a10690f6dd922b36f72f995c95b96face85971Timo Sirainen }
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
49e9acb52bb5d328f8cf10bce1082c4bc213caeaTimo Sirainen if (!*reset_r || sync_expunges)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen break;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
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 &end_seq, &end_offset);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen end_seq--; end_offset = (uoff_t)-1;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (end_seq < start_seq) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* we have only this reset log */
c680a6b35b459045e92814778908da5a93922107Timo Sirainen mail_transaction_log_view_clear(view->log_view,
c680a6b35b459045e92814778908da5a93922107Timo Sirainen view->log_file_expunge_seq);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen break;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen }
407d64647d77771080eb75f800162014927f10c6Timo Sirainen *partial_sync_r = TRUE;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return 1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen}
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic unsigned int
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenview_sync_expunges2seqs(struct mail_index_view_sync_ctx *ctx)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen{
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct mail_index_view *view = ctx->view;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct seq_range *src, *src_end, *dest;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen unsigned int count, expunge_count = 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen uint32_t prev_seq = 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* convert UIDs to sequences */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen src = dest = array_get_modifiable(&ctx->expunges, &count);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen src_end = src + count;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen for (; src != src_end; src++) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (!mail_index_lookup_seq_range(view, src->seq1, src->seq2,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen &dest->seq1, &dest->seq2))
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen count--;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen else {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen i_assert(dest->seq1 > prev_seq);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen prev_seq = dest->seq2;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen expunge_count += dest->seq2 - dest->seq1 + 1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen dest++;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen array_delete(&ctx->expunges, count,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen array_count(&ctx->expunges) - count);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return expunge_count;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen}
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainenstatic void
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainenview_sync_add_expunge_range(ARRAY_TYPE(seq_range) *dest,
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen const struct seq_range *src, size_t src_size)
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen{
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen unsigned int i, src_count;
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen i_assert(src_size % sizeof(*src) == 0);
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen src_count = src_size / sizeof(*src);
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen for (i = 0; i < src_count; i++)
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen seq_range_array_add_range(dest, src[i].seq1, src[i].seq2);
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen}
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainenstatic void
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainenview_sync_add_expunge_guids(ARRAY_TYPE(seq_range) *dest,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen const struct mail_transaction_expunge_guid *src,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen size_t src_size)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen{
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen unsigned int i, src_count;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen i_assert(src_size % sizeof(*src) == 0);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen src_count = src_size / sizeof(*src);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen for (i = 0; i < src_count; i++)
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen seq_range_array_add(dest, src[i].uid);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen}
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenview_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen unsigned int *expunge_count_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct mail_index_view *view = ctx->view;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen const struct mail_transaction_header *hdr;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen const void *data;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen int ret;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
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 &hdr, &data)) > 0) {
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen /* skip expunge requests */
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen continue;
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE_GUID) != 0) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen view_sync_add_expunge_guids(&ctx->expunges,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen data, hdr->size);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen } else if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen view_sync_add_expunge_range(&ctx->expunges,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen data, hdr->size);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
659fe5d24825b160cae512538088020d97a60239Timo Sirainen }
b43bb773ee6534c1013b01a62fbd5703e3b0d17dTimo Sirainen mail_transaction_log_view_rewind(view->log_view);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen *expunge_count_r = view_sync_expunges2seqs(ctx);
f4ca89823693b9faa82a0c39c24510a7b0e606afTimo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainenstatic bool have_existing_expunges(struct mail_index_view *view,
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen const struct seq_range *range, size_t size)
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen{
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen const struct seq_range *range_end;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen uint32_t seq1, seq2;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen range_end = CONST_PTR_OFFSET(range, size);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen for (; range != range_end; range++) {
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen if (mail_index_lookup_seq_range(view, range->seq1, range->seq2,
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen &seq1, &seq2))
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen return TRUE;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen }
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen return FALSE;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen}
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainenstatic bool
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainenhave_existing_guid_expunge(struct mail_index_view *view,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen const struct mail_transaction_expunge_guid *expunges,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen size_t size)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen{
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen const struct mail_transaction_expunge_guid *expunges_end;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen uint32_t seq;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen expunges_end = CONST_PTR_OFFSET(expunges, size);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen for (; expunges != expunges_end; expunges++) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (mail_index_lookup_seq(view, expunges->uid, &seq))
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return TRUE;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return FALSE;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen}
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainenstatic bool view_sync_have_expunges(struct mail_index_view *view)
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen{
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen const struct mail_transaction_header *hdr;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen const void *data;
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen bool have_expunges = FALSE;
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen int ret;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen mail_transaction_log_view_mark(view->log_view);
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen &hdr, &data)) > 0) {
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen /* skip expunge requests */
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen continue;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE_GUID) != 0) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen /* we have an expunge. see if it still exists. */
220195605754218b4d6e3a51f5a25be9d0e202e0Timo Sirainen if (have_existing_guid_expunge(view, data, hdr->size)) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen have_expunges = TRUE;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen break;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen } else if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen /* we have an expunge. see if it still exists. */
220195605754218b4d6e3a51f5a25be9d0e202e0Timo Sirainen if (have_existing_expunges(view, data, hdr->size)) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen have_expunges = TRUE;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen break;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen }
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen }
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen mail_transaction_log_view_rewind(view->log_view);
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen /* handle failures as having expunges (which is safer).
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen we'll probably fail later. */
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen return ret < 0 || have_expunges;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen}
fd3f33bdb57170d63aea66ecacc8bea0f0145d6aTimo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic int uint_cmp(const void *p1, const void *p2)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen{
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen const unsigned int *u1 = p1, *u2 = p2;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (*u1 < *u2)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return -1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (*u1 > *u2)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return 1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen}
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic bool view_sync_lost_keywords_equal(struct mail_index_view_sync_ctx *ctx)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen{
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen unsigned int *old_idx, *new_idx;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen unsigned int old_count, new_count;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
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 if (old_count != new_count)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return FALSE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen qsort(old_idx, old_count, sizeof(*old_idx), uint_cmp);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen qsort(new_idx, new_count, sizeof(*new_idx), uint_cmp);
ee248252648e99f5d701ecd6e33640ea77e11cb7Timo Sirainen return memcmp(old_idx, new_idx, old_count * sizeof(*old_idx)) == 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen}
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic int view_sync_update_keywords(struct mail_index_view_sync_ctx *ctx,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen uint32_t uid)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen{
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct mail_transaction_header thdr;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct mail_transaction_keyword_update kw_up;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen const unsigned int *kw_idx;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen const char *const *kw_names;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen unsigned int i, count;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen kw_idx = array_get(&ctx->lost_new_kw, &count);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (count == 0)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen kw_names = array_idx(&ctx->view->index->keywords, 0);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&thdr);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen thdr.type = MAIL_TRANSACTION_KEYWORD_UPDATE | MAIL_TRANSACTION_EXTERNAL;
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&kw_up);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen kw_up.modify_type = MODIFY_ADD;
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_set_used_size(ctx->lost_kw_buf, 0);
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 kw_up.name_size);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (ctx->lost_kw_buf->used % 4 != 0) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen buffer_append_zero(ctx->lost_kw_buf,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen 4 - ctx->lost_kw_buf->used % 4);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen buffer_append(ctx->lost_kw_buf, &uid, sizeof(uid));
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen buffer_append(ctx->lost_kw_buf, &uid, sizeof(uid));
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen thdr.size = ctx->lost_kw_buf->used;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (mail_index_sync_record(&ctx->sync_map_ctx, &thdr,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ctx->lost_kw_buf->data) < 0)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return -1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen}
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic int view_sync_apply_lost_changes(struct mail_index_view_sync_ctx *ctx,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen uint32_t old_seq, uint32_t new_seq)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen{
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 struct mail_transaction_header thdr;
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen const struct mail_index_ext *ext;
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen const uint64_t *modseqp;
b6612c334604eeb27e1ca2bd804ac66dcbc2eaadTimo Sirainen uint64_t new_modseq;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen bool changed = FALSE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody old_rec = MAIL_INDEX_REC_AT_SEQ(old_map, old_seq);
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody new_rec = MAIL_INDEX_REC_AT_SEQ(new_map, new_seq);
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&thdr);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (old_rec->flags != new_rec->flags) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct mail_transaction_flag_update flag_update;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* check this before syncing the record, since it updates
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen old_rec. */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if ((old_rec->flags & MAIL_INDEX_FLAGS_MASK) !=
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen (new_rec->flags & MAIL_INDEX_FLAGS_MASK))
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen changed = TRUE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen thdr.type = MAIL_TRANSACTION_FLAG_UPDATE |
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen MAIL_TRANSACTION_EXTERNAL;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen thdr.size = sizeof(flag_update);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&flag_update);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen flag_update.uid1 = flag_update.uid2 = new_rec->uid;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen flag_update.add_flags = new_rec->flags;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen flag_update.remove_flags = ~new_rec->flags & 0xff;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (mail_index_sync_record(&ctx->sync_map_ctx, &thdr,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen &flag_update) < 0)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return -1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
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 if (!view_sync_lost_keywords_equal(ctx)) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct mail_transaction_keyword_reset kw_reset;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen thdr.type = MAIL_TRANSACTION_KEYWORD_RESET |
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen MAIL_TRANSACTION_EXTERNAL;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen thdr.size = sizeof(kw_reset);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* remove all old flags by resetting them */
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&kw_reset);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen kw_reset.uid1 = kw_reset.uid2 = new_rec->uid;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (mail_index_sync_record(&ctx->sync_map_ctx, &thdr,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen &kw_reset) < 0)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return -1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen if (view_sync_update_keywords(ctx, new_rec->uid) < 0)
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen return -1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen changed = TRUE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen if (changed) {
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen /* flags or keywords changed */
b6612c334604eeb27e1ca2bd804ac66dcbc2eaadTimo Sirainen } else if (ctx->view->highest_modseq != 0 &&
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen ctx->lost_new_ext_idx != (uint32_t)-1) {
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);
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen new_modseq = *modseqp;
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen
b6612c334604eeb27e1ca2bd804ac66dcbc2eaadTimo Sirainen if (new_modseq > ctx->view->highest_modseq)
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen changed = TRUE;
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen }
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen
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 if (changed)
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen seq_range_array_add(&ctx->lost_flags, new_rec->uid);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen}
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic int
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenview_sync_get_log_lost_changes(struct mail_index_view_sync_ctx *ctx,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen unsigned int *expunge_count_r)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen{
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct mail_index_view *view = ctx->view;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct mail_index_map *old_map = view->map;
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 struct mail_transaction_header thdr;
7604ee75aa54ab2e400de45999e326c358bc2d24Phil Carmody uint32_t seqi, seqj;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
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);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen if (!mail_index_map_get_ext_idx(new_map, view->index->modseq_ext_id,
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen &ctx->lost_new_ext_idx))
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen ctx->lost_new_ext_idx = (uint32_t)-1;
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen i_array_init(&ctx->lost_flags, 64);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen t_array_init(&ctx->lost_old_kw, 32);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen t_array_init(&ctx->lost_new_kw, 32);
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi ctx->lost_kw_buf = t_buffer_create(128);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* handle expunges and sync flags */
7604ee75aa54ab2e400de45999e326c358bc2d24Phil Carmody seqi = seqj = 1;
41a6be2852b10158e98934aa7e4922baf887a0c3Timo Sirainen while (seqi <= old_count && seqj <= new_count) {
7604ee75aa54ab2e400de45999e326c358bc2d24Phil Carmody old_rec = MAIL_INDEX_REC_AT_SEQ(old_map, seqi);
7604ee75aa54ab2e400de45999e326c358bc2d24Phil Carmody new_rec = MAIL_INDEX_REC_AT_SEQ(new_map, seqj);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (old_rec->uid == new_rec->uid) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* message found - check if flags have changed */
7604ee75aa54ab2e400de45999e326c358bc2d24Phil Carmody if (view_sync_apply_lost_changes(ctx, seqi, seqj) < 0)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return -1;
7604ee75aa54ab2e400de45999e326c358bc2d24Phil Carmody seqi++; seqj++;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen } else if (old_rec->uid < new_rec->uid) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* message expunged */
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen seq_range_array_add(&ctx->expunges, old_rec->uid);
7604ee75aa54ab2e400de45999e326c358bc2d24Phil Carmody seqi++;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen } else {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* new message appeared out of nowhere */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mail_index_set_error(view->index,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen "%s view is inconsistent: "
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen "uid=%u inserted in the middle of mailbox",
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen view->index->filepath, new_rec->uid);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return -1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* if there are old messages left, they're all expunged */
7604ee75aa54ab2e400de45999e326c358bc2d24Phil Carmody for (; seqi <= old_count; seqi++) {
7604ee75aa54ab2e400de45999e326c358bc2d24Phil Carmody old_rec = MAIL_INDEX_REC_AT_SEQ(old_map, seqi);
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen seq_range_array_add(&ctx->expunges, old_rec->uid);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
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 thdr.size = sizeof(*new_rec);
7604ee75aa54ab2e400de45999e326c358bc2d24Phil Carmody for (; seqj <= new_count; seqj++) {
7604ee75aa54ab2e400de45999e326c358bc2d24Phil Carmody new_rec = MAIL_INDEX_REC_AT_SEQ(new_map, seqj);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (mail_index_sync_record(&ctx->sync_map_ctx,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen &thdr, new_rec) < 0)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return -1;
7604ee75aa54ab2e400de45999e326c358bc2d24Phil Carmody mail_index_map_lookup_keywords(new_map, seqj,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen &ctx->lost_new_kw);
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen if (view_sync_update_keywords(ctx, new_rec->uid) < 0)
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen return -1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen *expunge_count_r = view_sync_expunges2seqs(ctx);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* we have no idea how far we've synced - make sure these aren't used */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen old_map->hdr.log_file_seq = 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen old_map->hdr.log_file_head_offset = 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen old_map->hdr.log_file_tail_offset = 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if ((ctx->flags & MAIL_INDEX_VIEW_SYNC_FLAG_NOEXPUNGES) != 0) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen array_clear(&ctx->expunges);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ctx->skipped_expunges = *expunge_count_r > 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen } else {
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;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen}
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainenstatic int mail_index_view_sync_init_fix(struct mail_index_view_sync_ctx *ctx)
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen{
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen struct mail_index_view *view = ctx->view;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen uint32_t seq;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen uoff_t offset;
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen const char *reason;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen bool reset;
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen int ret;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen /* replace the view's map */
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen view->index->map->refcount++;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen mail_index_unmap(&view->map);
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen view->map = view->index->map;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen /* update log positions */
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen view->log_file_head_seq = seq = view->map->hdr.log_file_seq;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen view->log_file_head_offset = offset =
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen view->map->hdr.log_file_head_offset;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen ret = mail_transaction_log_view_set(view->log_view, seq, offset,
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen seq, offset, &reset, &reason);
20a10690f6dd922b36f72f995c95b96face85971Timo Sirainen if (ret <= 0) {
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen mail_index_set_error(view->index, "Failed to fix view for %s: %s",
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen view->index->filepath, reason);
20a10690f6dd922b36f72f995c95b96face85971Timo Sirainen return ret;
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen }
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen view->inconsistent = FALSE;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen return 0;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen}
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainenstruct mail_index_view_sync_ctx *
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainenmail_index_view_sync_begin(struct mail_index_view *view,
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen enum mail_index_view_sync_flags flags)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_view_sync_ctx *ctx;
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen struct mail_index_map *tmp_map;
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen unsigned int expunge_count = 0;
407d64647d77771080eb75f800162014927f10c6Timo Sirainen bool reset, partial_sync, sync_expunges, have_expunges;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(!view->syncing);
d39c0e195c67be5f2b0a15f25a8d6039bef02711Timo Sirainen i_assert(view->transactions == 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen view->syncing = TRUE;
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen /* Syncing the view invalidates all previous looked up records.
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen Unreference the mappings this view keeps because of them. */
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen mail_index_view_unref_maps(view);
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen ctx = i_new(struct mail_index_view_sync_ctx, 1);
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen ctx->view = view;
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen ctx->flags = flags;
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen sync_expunges = (flags & MAIL_INDEX_VIEW_SYNC_FLAG_NOEXPUNGES) == 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (sync_expunges)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen i_array_init(&ctx->expunges, 64);
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 i_assert(sync_expunges);
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen if (mail_index_view_sync_init_fix(ctx) < 0)
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen ctx->failed = TRUE;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen return ctx;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen }
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen if (mail_index_view_is_inconsistent(view)) {
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen mail_index_set_error(view->index, "%s view is inconsistent",
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen view->index->filepath);
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen ctx->failed = TRUE;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen return ctx;
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen }
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen
407d64647d77771080eb75f800162014927f10c6Timo Sirainen ret = view_sync_set_log_view_range(view, sync_expunges, &reset, &partial_sync);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (ret < 0) {
b43bb773ee6534c1013b01a62fbd5703e3b0d17dTimo Sirainen ctx->failed = TRUE;
b43bb773ee6534c1013b01a62fbd5703e3b0d17dTimo Sirainen return ctx;
b43bb773ee6534c1013b01a62fbd5703e3b0d17dTimo Sirainen }
b43bb773ee6534c1013b01a62fbd5703e3b0d17dTimo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (ret == 0) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ctx->log_was_lost = TRUE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (!sync_expunges)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen i_array_init(&ctx->expunges, 64);
98daad9e5bf9bb1ce8fcddd45b350fce953a0bdeTimo Sirainen mail_index_sync_map_init(&ctx->sync_map_ctx, view,
98daad9e5bf9bb1ce8fcddd45b350fce953a0bdeTimo Sirainen MAIL_INDEX_SYNC_HANDLER_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);
98daad9e5bf9bb1ce8fcddd45b350fce953a0bdeTimo Sirainen if (ret < 0) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mail_index_set_error(view->index,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen "%s view syncing failed to apply changes",
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen view->index->filepath);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen view->inconsistent = TRUE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ctx->failed = TRUE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return ctx;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen have_expunges = expunge_count > 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen } else if (sync_expunges) {
1d06a935b555024420d1c22249f0c847e51a9b7aTimo Sirainen /* get list of all expunges first */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (view_sync_get_expunges(ctx, &expunge_count) < 0) {
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen ctx->failed = TRUE;
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen return ctx;
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen }
1103e7320af882c2c649841612b99b4502cb82a2Timo Sirainen have_expunges = expunge_count > 0;
1103e7320af882c2c649841612b99b4502cb82a2Timo Sirainen } else {
1103e7320af882c2c649841612b99b4502cb82a2Timo Sirainen have_expunges = view_sync_have_expunges(view);
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen }
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen ctx->finish_min_msg_count = reset ? 0 :
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen view->map->hdr.messages_count - expunge_count;
96d1b0c8126121fdceff98144c932433e3fdeb92Timo Sirainen if (reset) {
530c3ece3717ad8193046ea7774227f91971a0dcTimo Sirainen view->inconsistent = TRUE;
530c3ece3717ad8193046ea7774227f91971a0dcTimo Sirainen mail_index_set_error(view->index,
530c3ece3717ad8193046ea7774227f91971a0dcTimo Sirainen "%s reset, view is now inconsistent",
530c3ece3717ad8193046ea7774227f91971a0dcTimo Sirainen view->index->filepath);
83cd96ee87e8fb88b2467a1c51604961a5db3d71Timo Sirainen ctx->failed = TRUE;
83cd96ee87e8fb88b2467a1c51604961a5db3d71Timo Sirainen return ctx;
530c3ece3717ad8193046ea7774227f91971a0dcTimo Sirainen }
530c3ece3717ad8193046ea7774227f91971a0dcTimo Sirainen
407d64647d77771080eb75f800162014927f10c6Timo Sirainen if (!have_expunges && !partial_sync) {
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen /* no expunges, we can just replace the map */
07afd4db18860589803c46a3ee0559bda1c9e1b4Timo Sirainen if (view->index->map->hdr.messages_count <
07afd4db18860589803c46a3ee0559bda1c9e1b4Timo Sirainen ctx->finish_min_msg_count) {
07afd4db18860589803c46a3ee0559bda1c9e1b4Timo Sirainen mail_index_set_error(view->index,
07afd4db18860589803c46a3ee0559bda1c9e1b4Timo Sirainen "Index %s lost messages without expunging "
07afd4db18860589803c46a3ee0559bda1c9e1b4Timo Sirainen "(%u -> %u)", view->index->filepath,
07afd4db18860589803c46a3ee0559bda1c9e1b4Timo Sirainen view->map->hdr.messages_count,
07afd4db18860589803c46a3ee0559bda1c9e1b4Timo Sirainen view->index->map->hdr.messages_count);
07afd4db18860589803c46a3ee0559bda1c9e1b4Timo Sirainen ctx->finish_min_msg_count = 0;
07afd4db18860589803c46a3ee0559bda1c9e1b4Timo Sirainen view->inconsistent = TRUE;
07afd4db18860589803c46a3ee0559bda1c9e1b4Timo Sirainen }
07afd4db18860589803c46a3ee0559bda1c9e1b4Timo Sirainen
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen view->index->map->refcount++;
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen mail_index_unmap(&view->map);
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen view->map = view->index->map;
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen } else {
407d64647d77771080eb75f800162014927f10c6Timo Sirainen /* a) expunges seen. b) doing a partial sync because we saw
407d64647d77771080eb75f800162014927f10c6Timo Sirainen a reset.
407d64647d77771080eb75f800162014927f10c6Timo Sirainen
407d64647d77771080eb75f800162014927f10c6Timo Sirainen Create a private map which we update. If we're syncing
407d64647d77771080eb75f800162014927f10c6Timo Sirainen expunges the map will finally be replaced with the head map
407d64647d77771080eb75f800162014927f10c6Timo Sirainen to remove the expunged messages. */
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen ctx->sync_map_update = TRUE;
0c09e57c5d5a649c248d0073438d79acbb80c72bTimo Sirainen
9bc6e10d9c6d6ffb4a2ed49a3b3d2a180f2a87a3Timo Sirainen if (view->map->refcount > 1) {
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen tmp_map = mail_index_map_clone(view->map);
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen mail_index_unmap(&view->map);
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen view->map = tmp_map;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen }
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen if (sync_expunges) {
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen ctx->sync_new_map = view->index->map;
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen ctx->sync_new_map->refcount++;
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen }
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen }
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen mail_index_sync_map_init(&ctx->sync_map_ctx, view,
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen MAIL_INDEX_SYNC_HANDLER_VIEW);
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen#ifdef DEBUG
3776ed607821b502468bdfd5a4533af3002125d1Timo Sirainen mail_index_map_check(view->map);
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen#endif
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen return ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainenstatic bool
24c6aaf3c540d078021bb4a326982ae4e3d7eaf8Timo Sirainenview_sync_is_hidden(struct mail_index_view *view, uint32_t seq, uoff_t offset)
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen{
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen const struct mail_index_view_log_sync_area *sync;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainen if (!array_is_created(&view->syncs_hidden))
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen array_foreach(&view->syncs_hidden, sync) {
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen if (sync->log_file_offset <= offset &&
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen offset - sync->log_file_offset < sync->length &&
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen sync->log_file_seq == seq)
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
bbe90c4805e7032fdcefde3df125df0ca8be1befTimo Sirainenstatic bool
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainenmail_index_view_sync_want(struct mail_index_view_sync_ctx *ctx,
bbe90c4805e7032fdcefde3df125df0ca8be1befTimo Sirainen const struct mail_transaction_header *hdr)
bbe90c4805e7032fdcefde3df125df0ca8be1befTimo Sirainen{
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen struct mail_index_view *view = ctx->view;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen uint32_t seq;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen uoff_t offset, next_offset;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen mail_transaction_log_view_get_prev_pos(view->log_view, &seq, &offset);
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen next_offset = offset + sizeof(*hdr) + hdr->size;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if ((hdr->type & (MAIL_TRANSACTION_EXPUNGE |
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen MAIL_TRANSACTION_EXPUNGE_GUID)) != 0 &&
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainen (hdr->type & MAIL_TRANSACTION_EXTERNAL) != 0) {
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainen if ((ctx->flags & MAIL_INDEX_VIEW_SYNC_FLAG_NOEXPUNGES) != 0) {
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen i_assert(!LOG_IS_BEFORE(seq, offset,
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen view->log_file_expunge_seq,
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen view->log_file_expunge_offset));
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen if (!ctx->skipped_expunges) {
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen view->log_file_expunge_seq = seq;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen view->log_file_expunge_offset = offset;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen ctx->skipped_expunges = TRUE;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen }
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen return FALSE;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen }
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen if (LOG_IS_BEFORE(seq, offset, view->log_file_expunge_seq,
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen view->log_file_expunge_offset)) {
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen /* already synced */
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen return FALSE;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen }
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen }
bbe90c4805e7032fdcefde3df125df0ca8be1befTimo Sirainen
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen if (LOG_IS_BEFORE(seq, offset, view->log_file_head_seq,
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen view->log_file_head_offset)) {
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen /* already synced */
bbe90c4805e7032fdcefde3df125df0ca8be1befTimo Sirainen return FALSE;
bbe90c4805e7032fdcefde3df125df0ca8be1befTimo Sirainen }
bbe90c4805e7032fdcefde3df125df0ca8be1befTimo Sirainen
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen view->log_file_head_seq = seq;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen view->log_file_head_offset = next_offset;
bbe90c4805e7032fdcefde3df125df0ca8be1befTimo Sirainen return TRUE;
bbe90c4805e7032fdcefde3df125df0ca8be1befTimo Sirainen}
bbe90c4805e7032fdcefde3df125df0ca8be1befTimo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainenstatic int
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainenmail_index_view_sync_get_next_transaction(struct mail_index_view_sync_ctx *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_transaction_log_view *log_view = ctx->view->log_view;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_view *view = ctx->view;
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen const struct mail_transaction_header *hdr;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen uint32_t seq;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen uoff_t offset;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen int ret;
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen bool synced_to_map;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen do {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* Get the next transaction from log. */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen ret = mail_transaction_log_view_next(log_view, &ctx->hdr,
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen &ctx->data);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if (ret <= 0) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if (ret < 0)
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen return -1;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen ctx->hdr = NULL;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen ctx->last_read = TRUE;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen return 0;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen hdr = ctx->hdr;
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen /* skip records we've already synced */
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen } while (!mail_index_view_sync_want(ctx, hdr));
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen mail_transaction_log_view_get_prev_pos(log_view, &seq, &offset);
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen
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 view->map->hdr.log_file_head_offset);
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen /* Apply transaction to view's mapping if needed (meaning we
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen didn't just re-map the view to head mapping). */
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen if (ctx->sync_map_update && !synced_to_map) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if ((hdr->type & (MAIL_TRANSACTION_EXPUNGE |
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen MAIL_TRANSACTION_EXPUNGE_GUID)) == 0) {
6d25194a4230037c0999aa6a01ae6814e03ec06cTimo Sirainen ret = mail_index_sync_record(&ctx->sync_map_ctx,
6d25194a4230037c0999aa6a01ae6814e03ec06cTimo Sirainen hdr, ctx->data);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen if (ret < 0)
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen ctx->hidden = view_sync_is_hidden(view, seq, offset);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainenstatic bool
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainenmail_index_view_sync_get_rec(struct mail_index_view_sync_ctx *ctx,
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen struct mail_index_view_sync_rec *rec)
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen{
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen const struct mail_transaction_header *hdr = ctx->hdr;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen const void *data = ctx->data;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen case MAIL_TRANSACTION_FLAG_UPDATE: {
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen const struct mail_transaction_flag_update *update =
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen CONST_PTR_OFFSET(data, ctx->data_offset);
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* data contains mail_transaction_flag_update[] */
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen for (;;) {
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen ctx->data_offset += sizeof(*update);
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen if (!MAIL_TRANSACTION_FLAG_UPDATE_IS_INTERNAL(update))
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen break;
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* skip internal flag changes */
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen if (ctx->data_offset == ctx->hdr->size)
ffb79efcac37f807f75ab0a04c7b17a3d4af7167Timo Sirainen return FALSE;
d0143523a87b41eae0b118ff03aad539903b3555Timo Sirainen
d0143523a87b41eae0b118ff03aad539903b3555Timo Sirainen update = CONST_PTR_OFFSET(data, ctx->data_offset);
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen }
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen
e68fc7dc8c8a75842f1e39deb49d196d1cfdb3b3Timo Sirainen if (update->add_flags != 0 || update->remove_flags != 0)
e68fc7dc8c8a75842f1e39deb49d196d1cfdb3b3Timo Sirainen rec->type = MAIL_INDEX_VIEW_SYNC_TYPE_FLAGS;
e68fc7dc8c8a75842f1e39deb49d196d1cfdb3b3Timo Sirainen else
e68fc7dc8c8a75842f1e39deb49d196d1cfdb3b3Timo Sirainen rec->type = MAIL_INDEX_VIEW_SYNC_TYPE_MODSEQ;
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen rec->uid1 = update->uid1;
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen rec->uid2 = update->uid2;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen break;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen case MAIL_TRANSACTION_KEYWORD_UPDATE: {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen const struct mail_transaction_keyword_update *update = data;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen const uint32_t *uids;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* data contains mail_transaction_keyword_update header,
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen the keyword name and an array of { uint32_t uid1, uid2; } */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (ctx->data_offset == 0) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* skip over the header and name */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen ctx->data_offset = sizeof(*update) + update->name_size;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if ((ctx->data_offset % 4) != 0)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen ctx->data_offset += 4 - (ctx->data_offset % 4);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen uids = CONST_PTR_OFFSET(data, ctx->data_offset);
1f43c8ac132c153c224c4fffe34b2c3075d87ef7Timo Sirainen rec->type = MAIL_INDEX_VIEW_SYNC_TYPE_FLAGS;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen rec->uid1 = uids[0];
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen rec->uid2 = uids[1];
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen ctx->data_offset += sizeof(uint32_t) * 2;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen break;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen }
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen case MAIL_TRANSACTION_KEYWORD_RESET: {
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen const struct mail_transaction_keyword_reset *reset =
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen CONST_PTR_OFFSET(data, ctx->data_offset);
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* data contains mail_transaction_keyword_reset[] */
1f43c8ac132c153c224c4fffe34b2c3075d87ef7Timo Sirainen rec->type = MAIL_INDEX_VIEW_SYNC_TYPE_FLAGS;
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen rec->uid1 = reset->uid1;
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen rec->uid2 = reset->uid2;
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen ctx->data_offset += sizeof(*reset);
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen break;
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen }
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen default:
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainen ctx->hdr = NULL;
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainen return FALSE;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen }
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen rec->hidden = ctx->hidden;
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainen return TRUE;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen}
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic bool
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenmail_index_view_sync_next_lost(struct mail_index_view_sync_ctx *ctx,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct mail_index_view_sync_rec *sync_rec)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen{
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen const struct seq_range *range;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen unsigned int count;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen range = array_get(&ctx->lost_flags, &count);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (ctx->lost_flag_idx == count) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ctx->last_read = TRUE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return FALSE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
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;
ffb79efcac37f807f75ab0a04c7b17a3d4af7167Timo Sirainen sync_rec->hidden = FALSE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ctx->lost_flag_idx++;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return TRUE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen}
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainenbool mail_index_view_sync_next(struct mail_index_view_sync_ctx *ctx,
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen struct mail_index_view_sync_rec *sync_rec)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (ctx->log_was_lost)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return mail_index_view_sync_next_lost(ctx, sync_rec);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen do {
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen if (ctx->hdr == NULL || ctx->data_offset == ctx->hdr->size) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen ret = mail_index_view_sync_get_next_transaction(ctx);
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen if (ret <= 0) {
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen if (ret < 0)
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen ctx->failed = TRUE;
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen return FALSE;
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen }
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen ctx->data_offset = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen } while (!mail_index_view_sync_get_rec(ctx, sync_rec));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainenvoid mail_index_view_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen const ARRAY_TYPE(seq_range) **expunges_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen *expunges_r = &ctx->expunges;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainenstatic void
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainenmail_index_view_sync_clean_log_syncs(struct mail_index_view *view)
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen{
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen const struct mail_index_view_log_sync_area *syncs;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen unsigned int i, count;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen if (!array_is_created(&view->syncs_hidden))
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen return;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
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 if ((syncs[i].log_file_offset +
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)
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen break;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen }
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if (i > 0)
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen array_delete(&view->syncs_hidden, 0, i);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen}
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainenint mail_index_view_sync_commit(struct mail_index_view_sync_ctx **_ctx,
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen bool *delayed_expunges_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct mail_index_view_sync_ctx *ctx = *_ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_view *view = ctx->view;
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen int ret = ctx->failed ? -1 : 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(view->syncing);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen *_ctx = NULL;
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen *delayed_expunges_r = ctx->skipped_expunges;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
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 */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->inconsistent = TRUE;
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen ret = -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
ebee99dd900dc68fa280b1e93b8a71706013b31bTimo Sirainen if (ctx->sync_map_ctx.modseq_ctx != NULL)
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen mail_index_modseq_sync_end(&ctx->sync_map_ctx.modseq_ctx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen if (ctx->sync_new_map != NULL) {
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen mail_index_unmap(&view->map);
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen view->map = ctx->sync_new_map;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen } else if (ctx->sync_map_update) {
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. */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen view->map->hdr.log_file_seq = 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen view->map->hdr.log_file_head_offset = 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen view->map->hdr.log_file_tail_offset = 0;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
23230b2a3fe09ed29bd1314c7b8b4a0b17ea0ecfTimo Sirainen
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen i_assert(view->map->hdr.messages_count >= ctx->finish_min_msg_count);
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen if (!ctx->skipped_expunges) {
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen view->log_file_expunge_seq = view->log_file_head_seq;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen view->log_file_expunge_offset = view->log_file_head_offset;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen }
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen if (ctx->sync_map_ctx.view != NULL)
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen mail_index_sync_map_deinit(&ctx->sync_map_ctx);
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen mail_index_view_sync_clean_log_syncs(ctx->view);
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#ifdef DEBUG
3776ed607821b502468bdfd5a4533af3002125d1Timo Sirainen mail_index_map_check(view->map);
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#endif
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen /* set log view to empty range so unneeded memory gets freed */
c680a6b35b459045e92814778908da5a93922107Timo Sirainen mail_transaction_log_view_clear(view->log_view,
c680a6b35b459045e92814778908da5a93922107Timo Sirainen view->log_file_expunge_seq);
7888a9d2008eab9985096c46e1da9ee985c22a2aTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (array_is_created(&ctx->expunges))
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen array_free(&ctx->expunges);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (array_is_created(&ctx->lost_flags))
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen array_free(&ctx->lost_flags);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b6612c334604eeb27e1ca2bd804ac66dcbc2eaadTimo Sirainen view->highest_modseq = mail_index_map_modseq_get_highest(view->map);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->syncing = FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(ctx);
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainenvoid mail_index_view_add_hidden_transaction(struct mail_index_view *view,
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen uint32_t log_file_seq,
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen uoff_t log_file_offset,
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen unsigned int length)
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen{
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen struct mail_index_view_log_sync_area *area;
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen if (!array_is_created(&view->syncs_hidden))
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen i_array_init(&view->syncs_hidden, 32);
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen area = array_append_space(&view->syncs_hidden);
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen area->log_file_seq = log_file_seq;
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen area->log_file_offset = log_file_offset;
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen area->length = length;
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen}