mail-index-view-sync.c revision 1d06a935b555024420d1c22249f0c847e51a9b7a
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2003-2007 Dovecot authors, see the included COPYING file */
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. */
0f17bb103602d0c4394e3784cb96d788530fc79eTimo Sirainen (src+1 != src_end && src->seq2 >= src[1].seq1))
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen for (; i < dest_count; 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 (first > 0 && new_exp.seq1 <= dest[first-1].seq2+1) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* continue previous record */
139cbf8d9e1cc0c65d985f525756fe47a7bfada6Timo Sirainen } else if (i == first) {
139cbf8d9e1cc0c65d985f525756fe47a7bfada6Timo Sirainen dest = array_get_modifiable(expunges, &dest_count);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* use next record */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen dest = array_get_modifiable(expunges, &dest_count);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenview_sync_set_log_view_range(struct mail_index_view *view, bool sync_expunges,
8d90e4f9a8f79f79c393aca23d0a897471dc2d8fTimo Sirainen const struct mail_index_header *hdr = &view->index->map->hdr;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* we'll just directly to the end */
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen /* the view begins from the first non-synced transaction */
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen ret = mail_transaction_log_view_set(view->log_view,
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen /* FIXME: use the new index to get needed
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen "Transaction log got desynced for index %s",
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 /* we have only this reset log */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mail_transaction_log_view_clear(view->log_view,
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainenview_sync_get_expunges(struct mail_index_view *view,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (view_sync_set_log_view_range(view, TRUE, FALSE, &reset) < 0)
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 while ((ret = mail_transaction_log_view_next(view->log_view,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* this is simply a request for expunge */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (mail_transaction_log_sort_expunges(expunges_r, data,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mail_transaction_log_view_set_corrupted(view->log_view,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen "Corrupted expunge record");
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* convert UIDs to sequences */
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen src = dest = array_get_modifiable(expunges_r, &count);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (!mail_index_lookup_seq_range(view, src->seq1, src->seq2,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen array_delete(expunges_r, count, array_count(expunges_r) - count);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic bool have_existing_expunges(struct mail_index_view *view,
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen if (mail_index_lookup_seq_range(view, range->seq1, range->seq2,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic bool view_sync_have_expunges(struct mail_index_view *view)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mail_transaction_log_view_get_prev_pos(view->log_view,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* this is simply a request for expunge */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* we have an expunge. see if it still exists. */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (have_existing_expunges(view, data, hdr->size)) {
f534c0d42f1470fca8e4ff3493c94927bf600260Timo Sirainen mail_transaction_log_view_seek(view->log_view, seq, offset);
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen /* handle failures as having expunges (which is safer).
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen we'll probably fail later. */
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainenint mail_index_view_sync_begin(struct mail_index_view *view,
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen unsigned int expunge_count = 0;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen quick_sync = (flags & MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT) != 0;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen if ((flags & MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT) == 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen "%s view is inconsistent",
9762e4f86950549c8186c7d3d4fa4a6b533ea848Timo Sirainen sync_expunges = (flags & MAIL_INDEX_VIEW_SYNC_FLAG_NOEXPUNGES) == 0;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen /* get list of all expunges first */
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen if (view_sync_get_expunges(view, &expunges, &expunge_count) < 0)
4ed1c0fedf33299264a319b2c4e0fe2465ea321bTimo Sirainen if (view_sync_set_log_view_range(view, sync_expunges, quick_sync,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx = i_new(struct mail_index_view_sync_ctx, 1);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen view->map->hdr.messages_count - expunge_count;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_index_sync_map_init(&ctx->sync_map_ctx, view,
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen if (reset && view->map->hdr.messages_count > 0 &&
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen (flags & MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT) == 0) {
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen "%s reset, view is now inconsistent",
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen if (sync_expunges || !view_sync_have_expunges(view)) {
e9081684ea0808ed427cfd2624656d5f22fbb225Timo Sirainen i_assert(view->index->map->hdr.messages_count >=
cc2c73be39dfe988f52c0370667e3882d01c63a2Timo Sirainen /* keep the old mapping without expunges until we're
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen fully synced */
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen /* We need a private copy of the map if we don't want to
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen sync expunges.
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 /* Using non-head mapping. We have to apply
31327a74b86728e201fcedd0acaecf69d077bf1dTimo Sirainen transactions to it to get latest changes into it. */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* Syncing the view invalidates all previous looked up records.
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen Unreference the mappings this view keeps because of them. */
d00ae137b6772f0b047cc98cb153f11c5246f82bTimo Sirainenview_sync_is_hidden(struct mail_index_view *view, uint32_t seq, uoff_t offset)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const struct mail_index_view_log_sync_area *syncs;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen unsigned int i, count;
return FALSE;
for (i = 0; i < count; i++) {
return TRUE;
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return TRUE;
int ret;
bool synced_to_map;
if (ret <= 0) {
if (ret < 0)
store +flags.silent command) */
#define FLAG_UPDATE_IS_INTERNAL(u) \
~MAIL_INDEX_MAIL_FLAG_DIRTY) == 0)
case MAIL_TRANSACTION_APPEND: {
case MAIL_TRANSACTION_EXPUNGE: {
case MAIL_TRANSACTION_FLAG_UPDATE: {
case MAIL_TRANSACTION_KEYWORD_UPDATE: {
case MAIL_TRANSACTION_KEYWORD_RESET: {
return FALSE;
return TRUE;
int ret;
if (ret <= 0) {
if (ret < 0)
return FALSE;
return TRUE;
unsigned int i, count;
for (i = 0; i < count; i++) {
#ifdef DEBUG
return ret;
unsigned int length)