mail-index-view-sync.c revision 6bc98d3898c475ba7615ba2b016e5142c8b2c09f
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenmail_transaction_log_sort_expunges(ARRAY_TYPE(seq_range) *expunges,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* Note that all the sequences are actually still UIDs at this point */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* @UNSAFE */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen dest = array_get_modifiable(expunges, &dest_count);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen array_append(expunges, src, src_size / sizeof(*src));
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen /* src[] must be sorted. */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen (src+1 != src_end && src->seq2 >= src[1].seq1))
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen for (; i < dest_count; i++) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen while (i < dest_count && src->seq2 >= dest[i].seq1-1) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* we can/must merge with next record */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (first > 0 && new_exp.seq1 <= dest[first-1].seq2+1) {
139cbf8d9e1cc0c65d985f525756fe47a7bfada6Timo Sirainen /* continue previous record */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen } else if (i == first) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen dest = array_get_modifiable(expunges, &dest_count);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* use next record */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen dest = array_get_modifiable(expunges, &dest_count);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic int view_sync_set_log_view_range(struct mail_index_view *view,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const struct mail_index_header *hdr = view->index->hdr;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen /* the view begins from the first non-synced transaction */
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen ret = mail_transaction_log_view_set(view->log_view,
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen /* FIXME: use the new index to get needed changes */
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen "Transaction log got desynced for index %s",
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenview_sync_get_expunges(struct mail_index_view *view,
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen unsigned int count;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (view_sync_set_log_view_range(view, MAIL_TRANSACTION_EXPUNGE) < 0)
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen /* get a list of expunge transactions. there may be some that we have
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen already synced, but it doesn't matter because they'll get dropped
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen out when converting to sequences */
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen i_assert((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (mail_transaction_log_sort_expunges(expunges_r, data,
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen mail_transaction_log_view_set_corrupted(view->log_view,
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen "Corrupted expunge record");
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* convert UIDs to sequences */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen src = dest = array_get_modifiable(expunges_r, &count);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen ret = mail_index_lookup_uid_range(view, src->seq1,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen array_delete(expunges_r, count, array_count(expunges_r) - count);
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainenstatic void mail_index_view_hdr_update(struct mail_index_view *view,
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen /* Keep message count the same. */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen map->hdr.messages_count = view->hdr.messages_count;
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen /* Keep the old message flag counts also, although they may be
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen somewhat stale already. We just don't want them to be more than
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen our old messages_count. */
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen map->hdr.recent_messages_count = view->hdr.recent_messages_count;
d927bc5618696157fc55eb1f11b5cab05400ed52Timo Sirainen map->hdr.seen_messages_count = view->hdr.seen_messages_count;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen map->hdr.deleted_messages_count = view->hdr.deleted_messages_count;
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen /* Keep log position so we know where to continue syncing */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen map->hdr.log_file_seq = view->hdr.log_file_seq;
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen buffer_write(map->hdr_copy_buf, 0, &map->hdr, sizeof(map->hdr));
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainenstatic void mail_index_view_check(struct mail_index_view *view)
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen unsigned int i, del = 0, recent = 0, seen = 0;
d927bc5618696157fc55eb1f11b5cab05400ed52Timo Sirainen for (i = 0; i < view->map->records_count; i++) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen i_assert(rec->uid >= view->hdr.first_deleted_uid_lowwater);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen i_assert(rec->uid >= view->hdr.first_recent_uid_lowwater);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen i_assert(rec->uid >= view->hdr.first_unseen_uid_lowwater);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(del == view->hdr.deleted_messages_count);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(recent == view->hdr.recent_messages_count);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen i_assert(seen == view->hdr.seen_messages_count);
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD | MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE)
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen (MAIL_TRANSACTION_EXPUNGE | MAIL_TRANSACTION_APPEND | \
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen MAIL_TRANSACTION_FLAG_UPDATE | MAIL_TRANSACTION_KEYWORD_UPDATE | \
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen ((hdr)->log_file_seq == (view)->log_file_seq && \
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen (hdr)->log_file_index_int_offset == (view)->log_file_offset && \
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen (hdr)->log_file_index_ext_offset == (view)->log_file_offset && \
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenint mail_index_view_sync_begin(struct mail_index_view *view,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen enum mail_transaction_type log_get_mask, visible_mask;
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen if (sync_type == MAIL_INDEX_VIEW_SYNC_TYPE_ALL) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* get list of all expunges first */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (view_sync_get_expunges(view, &expunges) < 0)
60b42c6dfdf9edcca8a96b380ef9a0adc60c2464Timo Sirainen /* only flags, appends and expunges can be left to be synced later */
4ed1c0fedf33299264a319b2c4e0fe2465ea321bTimo Sirainen visible_mask = MAIL_TRANSACTION_VISIBLE_SYNC_MASK;
4ed1c0fedf33299264a319b2c4e0fe2465ea321bTimo Sirainen case MAIL_INDEX_VIEW_SYNC_TYPE_NOAPPENDS_NOEXPUNGES:
4ed1c0fedf33299264a319b2c4e0fe2465ea321bTimo Sirainen visible_mask = MAIL_TRANSACTION_VISIBLE_SYNC_MASK &
60b42c6dfdf9edcca8a96b380ef9a0adc60c2464Timo Sirainen ~(MAIL_TRANSACTION_EXPUNGE | MAIL_TRANSACTION_APPEND);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen visible_mask = MAIL_TRANSACTION_VISIBLE_SYNC_MASK &
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* we want to also get non-visible changes. especially because we use
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen the returned skipped-flag in mail_transaction_log_view_next() to
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen tell us if any visible changes were skipped. */
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen log_get_mask = visible_mask | (MAIL_TRANSACTION_TYPE_MASK ^
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen if (view_sync_set_log_view_range(view, log_get_mask) < 0) {
cc2c73be39dfe988f52c0370667e3882d01c63a2Timo Sirainen ctx = i_new(struct mail_index_view_sync_ctx, 1);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mail_index_sync_map_init(&ctx->sync_map_ctx, view,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (sync_type == MAIL_INDEX_VIEW_SYNC_TYPE_ALL) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* since we're syncing everything, the counters get fixed */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* keep the old mapping without expunges until we're
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen fully synced */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* We need a private copy of the map if we don't want to
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen sync expunges.
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen If view's map is the head map, it means that it contains
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen already all the latest changes and there's no need for us
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen to apply any changes to it. This can only happen if there
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen hadn't been any expunges. */
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen uint32_t old_records_count = view->map->records_count;
77c462c3a415536f9c87028ee34546ee96fd1445Timo Sirainen /* Using non-head mapping. We have to apply
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainen transactions to it to get latest changes into it. */
#ifdef DEBUG
unsigned int i, count;
return FALSE;
for (i = 0; i < count; i++) {
return TRUE;
return FALSE;
int ret;
if (skipped) {
if (ret <= 0) {
if (ret < 0)
MAIL_TRANSACTION_EXPUNGE) == 0);
store +flags.silent command) */
#define FLAG_UPDATE_IS_INTERNAL(u) \
case MAIL_TRANSACTION_APPEND: {
case MAIL_TRANSACTION_EXPUNGE: {
case MAIL_TRANSACTION_FLAG_UPDATE: {
case MAIL_TRANSACTION_KEYWORD_UPDATE: {
case MAIL_TRANSACTION_KEYWORD_RESET: {
i_unreached();
int ret;
if (ret <= 0)
return ret;
bool fast_clean)
unsigned int i, count;
for (i = 0; i < count; i++) {
#ifdef DEBUG
unsigned int length)