mail-index-view-sync.c revision 1d06a935b555024420d1c22249f0c847e51a9b7a
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2003-2007 Dovecot authors, see the included COPYING file */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen#include "lib.h"
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen#include "array.h"
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen#include "buffer.h"
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde#include "mail-index-view-private.h"
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen#include "mail-index-sync-private.h"
cda217260716cfd8d8ec5e56f91708c64c140538Timo Sirainen#include "mail-transaction-log.h"
7a7d2aa11e46195e2d92d6c337d7e78052a5ce67Timo Sirainen
d00ae137b6772f0b047cc98cb153f11c5246f82bTimo Sirainenstruct mail_index_view_sync_ctx {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct mail_index_view *view;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen enum mail_index_view_sync_flags flags;
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde struct mail_index_sync_map_ctx sync_map_ctx;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde ARRAY_TYPE(seq_range) expunges;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen unsigned int finish_min_msg_count;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const struct mail_transaction_header *hdr;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const void *data;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen size_t data_offset;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen unsigned int failed:1;
f325d795b52ce2053f914072b22ebca9c4f0dc7eTimo Sirainen unsigned int sync_map_update:1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen unsigned int skipped_expunges:1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen unsigned int last_read:1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen};
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic int
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenmail_transaction_log_sort_expunges(ARRAY_TYPE(seq_range) *expunges,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const struct seq_range *src, size_t src_size)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* Note that all the sequences are actually still UIDs at this point */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const struct seq_range *src_end;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct seq_range *dest, new_exp;
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen unsigned int first, i, dest_count;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
139cbf8d9e1cc0c65d985f525756fe47a7bfada6Timo Sirainen i_assert(src_size % sizeof(*src) == 0);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* @UNSAFE */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen dest = array_get_modifiable(expunges, &dest_count);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (dest_count == 0) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen array_append(expunges, src, src_size / sizeof(*src));
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return 0;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen src_end = CONST_PTR_OFFSET(src, src_size);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen for (i = 0; src != src_end; src++) {
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen /* src[] must be sorted. */
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen if (src->seq1 > src->seq2 ||
0f17bb103602d0c4394e3784cb96d788530fc79eTimo Sirainen (src+1 != src_end && src->seq2 >= src[1].seq1))
0f17bb103602d0c4394e3784cb96d788530fc79eTimo Sirainen return -1;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen for (; i < dest_count; i++) {
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen if (src->seq1 < dest[i].seq1)
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen break;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen new_exp = *src;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen first = i;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen while (i < dest_count && src->seq2 >= dest[i].seq1-1) {
c8cf8a605e0ddea7cb36fe04551aeca5090e684bTimo Sirainen /* we can/must merge with next record */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (new_exp.seq2 < dest[i].seq2)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen new_exp.seq2 = dest[i].seq2;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen i++;
c8cf8a605e0ddea7cb36fe04551aeca5090e684bTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (first > 0 && new_exp.seq1 <= dest[first-1].seq2+1) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* continue previous record */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (dest[first-1].seq2 < new_exp.seq2)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen dest[first-1].seq2 = new_exp.seq2;
139cbf8d9e1cc0c65d985f525756fe47a7bfada6Timo Sirainen } else if (i == first) {
f6d63a21010540d3ddf08f2e7664ffca3ea70489Timo Sirainen array_insert(expunges, i, &new_exp, 1);
139cbf8d9e1cc0c65d985f525756fe47a7bfada6Timo Sirainen i++; first++;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
139cbf8d9e1cc0c65d985f525756fe47a7bfada6Timo Sirainen dest = array_get_modifiable(expunges, &dest_count);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen } else {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* use next record */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen dest[first] = new_exp;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen first++;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (i > first) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen array_delete(expunges, first, i - first);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen dest = array_get_modifiable(expunges, &dest_count);
dc912088f84c263db1609435c2f5d7cb29bf1a33Timo Sirainen i = first;
a5bb2908b44c8bf5ce41160a64c67fb840a20006Timo Sirainen }
a5bb2908b44c8bf5ce41160a64c67fb840a20006Timo Sirainen }
a5bb2908b44c8bf5ce41160a64c67fb840a20006Timo Sirainen return 0;
a5bb2908b44c8bf5ce41160a64c67fb840a20006Timo Sirainen}
a5bb2908b44c8bf5ce41160a64c67fb840a20006Timo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic int
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenview_sync_set_log_view_range(struct mail_index_view *view, bool sync_expunges,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen bool quick_sync, bool *reset_r)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
8d90e4f9a8f79f79c393aca23d0a897471dc2d8fTimo Sirainen const struct mail_index_header *hdr = &view->index->map->hdr;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen uint32_t start_seq, end_seq;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen uoff_t start_offset, end_offset;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen int ret;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen end_seq = hdr->log_file_seq;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen end_offset = hdr->log_file_head_offset;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (quick_sync) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen start_seq = end_seq;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen start_offset = end_offset;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* we'll just directly to the end */
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen view->log_file_head_seq = end_seq;
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen view->log_file_head_offset = end_offset;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen } else {
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen start_seq = view->log_file_expunge_seq;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen start_offset = view->log_file_expunge_offset;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen }
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen for (;;) {
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen /* the view begins from the first non-synced transaction */
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen ret = mail_transaction_log_view_set(view->log_view,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen start_seq, start_offset,
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen end_seq, end_offset,
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen reset_r);
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde if (ret <= 0) {
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde if (ret < 0)
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen return -1;
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen /* FIXME: use the new index to get needed
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen changes */
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen mail_index_set_error(view->index,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen "Transaction log got desynced for index %s",
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen view->index->filepath);
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen view->inconsistent = TRUE;
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen return -1;
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen }
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen if (!*reset_r || sync_expunges)
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen break;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* we can't do this. sync only up to reset. */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mail_transaction_log_view_get_prev_pos(view->log_view,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen &end_seq, &end_offset);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen end_seq--; end_offset = (uoff_t)-1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (end_seq < start_seq) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* we have only this reset log */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mail_transaction_log_view_clear(view->log_view,
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen view->log_file_expunge_seq);
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen break;
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen }
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen }
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return 0;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainenstatic int
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainenview_sync_get_expunges(struct mail_index_view *view,
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen ARRAY_TYPE(seq_range) *expunges_r,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen unsigned int *expunge_count_r)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const struct mail_transaction_header *hdr;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen struct seq_range *src, *src_end, *dest;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen const void *data;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen unsigned int count, expunge_count = 0;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen uint32_t prev_seq = 0;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen bool reset;
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen int ret;
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (view_sync_set_log_view_range(view, TRUE, FALSE, &reset) < 0)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo 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 */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen i_array_init(expunges_r, 64);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen &hdr, &data)) > 0) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen continue;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* this is simply a request for expunge */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen continue;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (mail_transaction_log_sort_expunges(expunges_r, data,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen hdr->size) < 0) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mail_transaction_log_view_set_corrupted(view->log_view,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen "Corrupted expunge record");
35083063d0e432d0cf78206b5929750e613ad772Timo Sirainen ret = -1;
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen break;
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen }
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen }
35083063d0e432d0cf78206b5929750e613ad772Timo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (ret < 0) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen array_free(expunges_r);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen }
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* convert UIDs to sequences */
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen src = dest = array_get_modifiable(expunges_r, &count);
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen src_end = src + count;
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen for (; src != src_end; src++) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (!mail_index_lookup_seq_range(view, src->seq1, src->seq2,
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen &dest->seq1, &dest->seq2))
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen count--;
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen else {
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen i_assert(dest->seq1 > prev_seq);
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen prev_seq = dest->seq2;
d927bc5618696157fc55eb1f11b5cab05400ed52Timo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen expunge_count += dest->seq2 - dest->seq1 + 1;
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen dest++;
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen array_delete(expunges_r, count, array_count(expunges_r) - count);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *expunge_count_r = expunge_count;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return 0;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen}
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic bool have_existing_expunges(struct mail_index_view *view,
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen const struct seq_range *range, size_t size)
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen{
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen const struct seq_range *range_end;
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen uint32_t seq1, seq2;
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen range_end = CONST_PTR_OFFSET(range, size);
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen for (; range < range_end; range++) {
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen if (mail_index_lookup_seq_range(view, range->seq1, range->seq2,
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen &seq1, &seq2))
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen return TRUE;
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen }
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen return FALSE;
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen}
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic bool view_sync_have_expunges(struct mail_index_view *view)
d927bc5618696157fc55eb1f11b5cab05400ed52Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const struct mail_transaction_header *hdr;
d927bc5618696157fc55eb1f11b5cab05400ed52Timo Sirainen const void *data;
d927bc5618696157fc55eb1f11b5cab05400ed52Timo Sirainen uint32_t seq;
d927bc5618696157fc55eb1f11b5cab05400ed52Timo Sirainen uoff_t offset;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen bool have_expunges = FALSE;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen int ret;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mail_transaction_log_view_get_prev_pos(view->log_view,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen &seq, &offset);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen &hdr, &data)) > 0) {
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen continue;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* this is simply a request for expunge */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen continue;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* we have an expunge. see if it still exists. */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (have_existing_expunges(view, data, hdr->size)) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen have_expunges = TRUE;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen break;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen }
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen
f534c0d42f1470fca8e4ff3493c94927bf600260Timo Sirainen mail_transaction_log_view_seek(view->log_view, seq, offset);
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen /* handle failures as having expunges (which is safer).
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen we'll probably fail later. */
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen return ret < 0 || have_expunges;
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen}
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainenint mail_index_view_sync_begin(struct mail_index_view *view,
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen enum mail_index_view_sync_flags flags,
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen struct mail_index_view_sync_ctx **ctx_r)
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen{
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen struct mail_index_view_sync_ctx *ctx;
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen struct mail_index_map *map;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen ARRAY_TYPE(seq_range) expunges = ARRAY_INIT;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen unsigned int expunge_count = 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen bool reset, sync_expunges, quick_sync;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(!view->syncing);
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen i_assert(view->transactions == 0);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen quick_sync = (flags & MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT) != 0;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen if (mail_index_view_is_inconsistent(view)) {
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen if ((flags & MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT) == 0) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mail_index_set_error(view->index,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen "%s view is inconsistent",
1ba47b1a31e60c533631c8810400b365f785870aTimo Sirainen view->index->filepath);
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen return -1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen view->inconsistent = FALSE;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
9762e4f86950549c8186c7d3d4fa4a6b533ea848Timo Sirainen sync_expunges = (flags & MAIL_INDEX_VIEW_SYNC_FLAG_NOEXPUNGES) == 0;
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen if (quick_sync) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(sync_expunges);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen i_array_init(&expunges, 1);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen } else if (sync_expunges) {
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen /* get list of all expunges first */
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen if (view_sync_get_expunges(view, &expunges, &expunge_count) < 0)
60b42c6dfdf9edcca8a96b380ef9a0adc60c2464Timo Sirainen return -1;
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
4ed1c0fedf33299264a319b2c4e0fe2465ea321bTimo Sirainen if (view_sync_set_log_view_range(view, sync_expunges, quick_sync,
4ed1c0fedf33299264a319b2c4e0fe2465ea321bTimo Sirainen &reset) < 0) {
4ed1c0fedf33299264a319b2c4e0fe2465ea321bTimo Sirainen if (array_is_created(&expunges))
4ed1c0fedf33299264a319b2c4e0fe2465ea321bTimo Sirainen array_free(&expunges);
60b42c6dfdf9edcca8a96b380ef9a0adc60c2464Timo Sirainen return -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx = i_new(struct mail_index_view_sync_ctx, 1);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ctx->view = view;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ctx->flags = flags;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->expunges = expunges;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->finish_min_msg_count = reset ? 0 :
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen view->map->hdr.messages_count - expunge_count;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_index_sync_map_init(&ctx->sync_map_ctx, view,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen MAIL_INDEX_SYNC_HANDLER_VIEW);
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen if (reset && view->map->hdr.messages_count > 0 &&
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen (flags & MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT) == 0) {
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen view->inconsistent = TRUE;
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen mail_index_set_error(view->index,
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen "%s reset, view is now inconsistent",
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen view->index->filepath);
e9081684ea0808ed427cfd2624656d5f22fbb225Timo Sirainen }
e9081684ea0808ed427cfd2624656d5f22fbb225Timo Sirainen
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen if (sync_expunges || !view_sync_have_expunges(view)) {
e9081684ea0808ed427cfd2624656d5f22fbb225Timo Sirainen view->sync_new_map = view->index->map;
e9081684ea0808ed427cfd2624656d5f22fbb225Timo Sirainen view->sync_new_map->refcount++;
e9081684ea0808ed427cfd2624656d5f22fbb225Timo Sirainen i_assert(view->index->map->hdr.messages_count >=
e9081684ea0808ed427cfd2624656d5f22fbb225Timo Sirainen ctx->finish_min_msg_count || reset);
cc2c73be39dfe988f52c0370667e3882d01c63a2Timo Sirainen
cc2c73be39dfe988f52c0370667e3882d01c63a2Timo Sirainen /* keep the old mapping without expunges until we're
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen fully synced */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen } else {
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen /* We need a private copy of the map if we don't want to
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen sync expunges.
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen If view's map is the head map, it means that it contains
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen already all the latest changes and there's no need for us
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen to apply any changes to it. This can only happen if there
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen hadn't been any expunges. */
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen if (view->map != view->index->map) {
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen /* Using non-head mapping. We have to apply
31327a74b86728e201fcedd0acaecf69d077bf1dTimo Sirainen transactions to it to get latest changes into it. */
31327a74b86728e201fcedd0acaecf69d077bf1dTimo Sirainen ctx->sync_map_update = TRUE;
31327a74b86728e201fcedd0acaecf69d077bf1dTimo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (view->map->refcount > 1) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen map = mail_index_map_clone(view->map);
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen mail_index_unmap(&view->map);
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen view->map = map;
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen } else {
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen map = view->map;
94ce7e7700cda14a8342cb08e7285507b4b531daTimo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen#ifdef DEBUG
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mail_index_map_check(view->map);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen#endif
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* Syncing the view invalidates all previous looked up records.
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen Unreference the mappings this view keeps because of them. */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen mail_index_view_unref_maps(view);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen view->syncing = TRUE;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *ctx_r = ctx;
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen return 0;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic bool
d00ae137b6772f0b047cc98cb153f11c5246f82bTimo Sirainenview_sync_is_hidden(struct mail_index_view *view, uint32_t seq, uoff_t offset)
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainen{
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const struct mail_index_view_log_sync_area *syncs;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen unsigned int i, count;
if (!array_is_created(&view->syncs_hidden))
return FALSE;
syncs = array_get(&view->syncs_hidden, &count);
for (i = 0; i < count; i++) {
if (syncs[i].log_file_offset <= offset &&
offset - syncs[i].log_file_offset < syncs[i].length &&
syncs[i].log_file_seq == seq)
return TRUE;
}
return FALSE;
}
static bool
mail_index_view_sync_want(struct mail_index_view_sync_ctx *ctx,
const struct mail_transaction_header *hdr)
{
struct mail_index_view *view = ctx->view;
uint32_t seq;
uoff_t offset, next_offset;
mail_transaction_log_view_get_prev_pos(view->log_view, &seq, &offset);
next_offset = offset + sizeof(*hdr) + hdr->size;
if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0 &&
(hdr->type & MAIL_TRANSACTION_EXTERNAL) != 0) {
if ((ctx->flags & MAIL_INDEX_VIEW_SYNC_FLAG_NOEXPUNGES) != 0) {
i_assert(!LOG_IS_BEFORE(seq, offset,
view->log_file_expunge_seq,
view->log_file_expunge_offset));
if (!ctx->skipped_expunges) {
view->log_file_expunge_seq = seq;
view->log_file_expunge_offset = offset;
ctx->skipped_expunges = TRUE;
}
return FALSE;
}
if (LOG_IS_BEFORE(seq, offset, view->log_file_expunge_seq,
view->log_file_expunge_offset)) {
/* already synced */
return FALSE;
}
}
if (LOG_IS_BEFORE(seq, offset, view->log_file_head_seq,
view->log_file_head_offset)) {
/* already synced */
return FALSE;
}
view->log_file_head_seq = seq;
view->log_file_head_offset = next_offset;
return TRUE;
}
static int
mail_index_view_sync_get_next_transaction(struct mail_index_view_sync_ctx *ctx)
{
struct mail_transaction_log_view *log_view = ctx->view->log_view;
struct mail_index_view *view = ctx->view;
const struct mail_transaction_header *hdr;
uint32_t seq;
uoff_t offset;
int ret;
bool synced_to_map;
for (;;) {
/* Get the next transaction from log. */
ret = mail_transaction_log_view_next(log_view, &ctx->hdr,
&ctx->data);
if (ret <= 0) {
if (ret < 0)
return -1;
ctx->hdr = NULL;
ctx->last_read = TRUE;
return 0;
}
hdr = ctx->hdr;
if (!mail_index_view_sync_want(ctx, hdr)) {
/* This is a visible record that we don't want to
sync. */
continue;
}
mail_transaction_log_view_get_prev_pos(log_view, &seq, &offset);
/* If we started from a map that we didn't create ourself,
some of the transactions may already be synced. at the end
of this view sync we'll update file_seq=0 so that this check
always becomes FALSE for subsequent syncs. */
synced_to_map = view->map->hdr.log_file_seq != 0 &&
LOG_IS_BEFORE(seq, offset,
view->map->hdr.log_file_seq,
view->map->hdr.log_file_head_offset);
/* Apply transaction to view's mapping if needed (meaning we
didn't just re-map the view to head mapping). */
if (ctx->sync_map_update && !synced_to_map) {
i_assert((hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0 ||
(hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0);
if (mail_index_sync_record(&ctx->sync_map_ctx,
hdr, ctx->data) < 0)
return -1;
}
/* skip changes committed by hidden transactions (eg. in IMAP
store +flags.silent command) */
if (view_sync_is_hidden(view, seq, offset))
continue;
break;
}
return 1;
}
#define FLAG_UPDATE_IS_INTERNAL(u) \
((((u)->add_flags | (u)->remove_flags) & \
~MAIL_INDEX_MAIL_FLAG_DIRTY) == 0)
static bool
mail_index_view_sync_get_rec(struct mail_index_view_sync_ctx *ctx,
struct mail_index_view_sync_rec *rec)
{
const struct mail_transaction_header *hdr = ctx->hdr;
const void *data = ctx->data;
switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
case MAIL_TRANSACTION_APPEND: {
/* data contains the appended records, but we don't care */
rec->type = MAIL_INDEX_SYNC_TYPE_APPEND;
rec->uid1 = rec->uid2 = 0;
ctx->data_offset += hdr->size;
break;
}
case MAIL_TRANSACTION_EXPUNGE: {
const struct mail_transaction_expunge *exp =
CONST_PTR_OFFSET(data, ctx->data_offset);
if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
/* this is simply a request for expunge */
ctx->data_offset = ctx->hdr->size;
return 0;
}
/* data contains mail_transaction_expunge[] */
rec->type = MAIL_INDEX_SYNC_TYPE_EXPUNGE;
rec->uid1 = exp->uid1;
rec->uid2 = exp->uid2;
ctx->data_offset += sizeof(*exp);
break;
}
case MAIL_TRANSACTION_FLAG_UPDATE: {
const struct mail_transaction_flag_update *update =
CONST_PTR_OFFSET(data, ctx->data_offset);
/* data contains mail_transaction_flag_update[] */
for (;;) {
ctx->data_offset += sizeof(*update);
if (!FLAG_UPDATE_IS_INTERNAL(update))
break;
/* skip internal flag changes */
if (ctx->data_offset == ctx->hdr->size)
return 0;
update = CONST_PTR_OFFSET(data, ctx->data_offset);
}
rec->type = MAIL_INDEX_SYNC_TYPE_FLAGS;
rec->uid1 = update->uid1;
rec->uid2 = update->uid2;
break;
}
case MAIL_TRANSACTION_KEYWORD_UPDATE: {
const struct mail_transaction_keyword_update *update = data;
const uint32_t *uids;
/* data contains mail_transaction_keyword_update header,
the keyword name and an array of { uint32_t uid1, uid2; } */
if (ctx->data_offset == 0) {
/* skip over the header and name */
ctx->data_offset = sizeof(*update) + update->name_size;
if ((ctx->data_offset % 4) != 0)
ctx->data_offset += 4 - (ctx->data_offset % 4);
}
uids = CONST_PTR_OFFSET(data, ctx->data_offset);
rec->type = MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD;
rec->uid1 = uids[0];
rec->uid2 = uids[1];
ctx->data_offset += sizeof(uint32_t) * 2;
break;
}
case MAIL_TRANSACTION_KEYWORD_RESET: {
const struct mail_transaction_keyword_reset *reset =
CONST_PTR_OFFSET(data, ctx->data_offset);
/* data contains mail_transaction_keyword_reset[] */
rec->type = MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET;
rec->uid1 = reset->uid1;
rec->uid2 = reset->uid2;
ctx->data_offset += sizeof(*reset);
break;
}
default:
ctx->hdr = NULL;
return FALSE;
}
return TRUE;
}
bool mail_index_view_sync_next(struct mail_index_view_sync_ctx *ctx,
struct mail_index_view_sync_rec *sync_rec)
{
int ret;
do {
if (ctx->hdr == NULL || ctx->data_offset == ctx->hdr->size) {
ret = mail_index_view_sync_get_next_transaction(ctx);
if (ret <= 0) {
if (ret < 0)
ctx->failed = TRUE;
return FALSE;
}
ctx->data_offset = 0;
}
} while (!mail_index_view_sync_get_rec(ctx, sync_rec));
return TRUE;
}
void mail_index_view_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
const ARRAY_TYPE(seq_range) **expunges_r)
{
*expunges_r = &ctx->expunges;
}
static void
mail_index_view_sync_clean_log_syncs(struct mail_index_view *view)
{
const struct mail_index_view_log_sync_area *syncs;
unsigned int i, count;
if (!array_is_created(&view->syncs_hidden))
return;
/* Clean up to view's tail */
syncs = array_get(&view->syncs_hidden, &count);
for (i = 0; i < count; i++) {
if ((syncs[i].log_file_offset +
syncs[i].length > view->log_file_expunge_offset &&
syncs[i].log_file_seq == view->log_file_expunge_seq) ||
syncs[i].log_file_seq > view->log_file_expunge_seq)
break;
}
if (i > 0)
array_delete(&view->syncs_hidden, 0, i);
}
int mail_index_view_sync_commit(struct mail_index_view_sync_ctx **_ctx)
{
struct mail_index_view_sync_ctx *ctx = *_ctx;
struct mail_index_view *view = ctx->view;
int ret = ctx->failed ? -1 : 0;
i_assert(view->syncing);
*_ctx = NULL;
if ((!ctx->last_read || view->inconsistent) &&
(ctx->flags & MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT) == 0) {
/* we didn't sync everything */
view->inconsistent = TRUE;
ret = -1;
}
if (view->sync_new_map != NULL) {
mail_index_unmap(&view->map);
view->map = view->sync_new_map;
view->sync_new_map = NULL;
}
i_assert(view->map->hdr.messages_count >= ctx->finish_min_msg_count);
if (!ctx->skipped_expunges) {
view->log_file_expunge_seq = view->log_file_head_seq;
view->log_file_expunge_offset = view->log_file_head_offset;
}
if (ctx->sync_map_update) {
/* log offsets have no meaning in views. make sure they're not
tried to be used wrong by setting them to zero. */
view->map->hdr.log_file_seq = 0;
view->map->hdr.log_file_head_offset = 0;
view->map->hdr.log_file_tail_offset = 0;
}
mail_index_sync_map_deinit(&ctx->sync_map_ctx);
mail_index_view_sync_clean_log_syncs(ctx->view);
#ifdef DEBUG
mail_index_map_check(view->map);
#endif
/* set log view to empty range so unneeded memory gets freed */
mail_transaction_log_view_clear(view->log_view,
view->log_file_expunge_seq);
if (array_is_created(&ctx->expunges))
array_free(&ctx->expunges);
view->syncing = FALSE;
i_free(ctx);
return ret;
}
void mail_index_view_add_hidden_transaction(struct mail_index_view *view,
uint32_t log_file_seq,
uoff_t log_file_offset,
unsigned int length)
{
struct mail_index_view_log_sync_area *area;
if (!array_is_created(&view->syncs_hidden))
i_array_init(&view->syncs_hidden, 32);
area = array_append_space(&view->syncs_hidden);
area->log_file_seq = log_file_seq;
area->log_file_offset = log_file_offset;
area->length = length;
}