Mailbox syncing returns hidden records as modseq changes.
--HG--
branch : HEAD
unsigned int sync_map_update:1;
unsigned int skipped_expunges:1;
unsigned int last_read:1;
+ unsigned int hidden:1;
};
static int
int ret;
bool synced_to_map;
- for (;;) {
+ do {
/* Get the next transaction from log. */
ret = mail_transaction_log_view_next(log_view, &ctx->hdr,
&ctx->data);
}
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);
-
- T_BEGIN {
- ret = mail_index_sync_record(&ctx->sync_map_ctx,
- hdr, ctx->data);
- } T_END;
- if (ret < 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;
+ /* skip records we've already synced */
+ } while (!mail_index_view_sync_want(ctx, hdr));
+
+ 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);
+
+ T_BEGIN {
+ ret = mail_index_sync_record(&ctx->sync_map_ctx,
+ hdr, ctx->data);
+ } T_END;
+ if (ret < 0)
+ return -1;
}
+
+ ctx->hidden = view_sync_is_hidden(view, seq, offset);
return 1;
}
ctx->hdr = NULL;
return FALSE;
}
+
+ rec->hidden = ctx->hidden;
return TRUE;
}
};
enum mail_index_transaction_flags {
- /* If transaction is marked as hidden, the changes won't be listed
- when the view is synchronized. */
+ /* If transaction is marked as hidden, the changes are marked with
+ hidden=TRUE when the view is synchronized. */
MAIL_INDEX_TRANSACTION_FLAG_HIDE = 0x01,
/* External transactions describe changes to mailbox that have already
happened. */
/* keyword appends and removes are packed into one and same
MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD */
enum mail_index_sync_type type;
+
+ /* TRUE if this was a hidden transaction. */
+ unsigned int hidden:1;
};
struct mail_index;
uint32_t messages_count;
ARRAY_TYPE(seq_range) flag_updates;
+ ARRAY_TYPE(seq_range) modseq_updates;
const ARRAY_TYPE(seq_range) *expunges;
- unsigned int flag_update_pos, expunge_pos;
+ unsigned int flag_update_idx, modseq_update_idx, expunge_pos;
bool failed;
};
uint32_t seq1, seq2;
i_array_init(&ctx->flag_updates, 128);
+ if ((ctx->ibox->box.enabled_features & MAILBOX_FEATURE_CONDSTORE) != 0)
+ i_array_init(&ctx->modseq_updates, 32);
while (mail_index_view_sync_next(ctx->sync_ctx, &sync)) {
switch (sync.type) {
case MAIL_INDEX_SYNC_TYPE_APPEND:
case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
- if (mail_index_lookup_seq_range(ctx->ibox->view,
+ if (!mail_index_lookup_seq_range(ctx->ibox->view,
sync.uid1, sync.uid2,
- &seq1, &seq2)) {
+ &seq1, &seq2))
+ break;
+
+ if (!sync.hidden) {
seq_range_array_add_range(&ctx->flag_updates,
seq1, seq2);
+ } else if (array_is_created(&ctx->modseq_updates)) {
+ seq_range_array_add_range(&ctx->modseq_updates,
+ seq1, seq2);
}
break;
}
}
- /* remove expunged messages from flag updates */
+ /* remove expunged messages from flag/modseq updates */
if (ctx->expunges != NULL) {
seq_range_array_remove_seq_range(&ctx->flag_updates,
ctx->expunges);
+ if (array_is_created(&ctx->modseq_updates)) {
+ seq_range_array_remove_seq_range(&ctx->modseq_updates,
+ ctx->expunges);
+ }
+ }
+ /* remove flag updates from modseq updates */
+ if (array_is_created(&ctx->modseq_updates)) {
+ seq_range_array_remove_seq_range(&ctx->modseq_updates,
+ &ctx->flag_updates);
}
}
{
struct index_mailbox_sync_context *ctx =
(struct index_mailbox_sync_context *)_ctx;
- const struct seq_range *flag_updates;
+ const struct seq_range *range;
unsigned int count;
if (ctx->failed)
return FALSE;
- flag_updates = array_get(&ctx->flag_updates, &count);
- if (ctx->flag_update_pos < count) {
+ range = array_get(&ctx->flag_updates, &count);
+ if (ctx->flag_update_idx < count) {
sync_rec_r->type = MAILBOX_SYNC_TYPE_FLAGS;
- sync_rec_r->seq1 = flag_updates[ctx->flag_update_pos].seq1;
- sync_rec_r->seq2 = flag_updates[ctx->flag_update_pos].seq2;
- ctx->flag_update_pos++;
+ sync_rec_r->seq1 = range[ctx->flag_update_idx].seq1;
+ sync_rec_r->seq2 = range[ctx->flag_update_idx].seq2;
+ ctx->flag_update_idx++;
return 1;
}
+ if (array_is_created(&ctx->modseq_updates)) {
+ range = array_get(&ctx->modseq_updates, &count);
+ if (ctx->modseq_update_idx < count) {
+ sync_rec_r->type = MAILBOX_SYNC_TYPE_MODSEQ;
+ sync_rec_r->seq1 = range[ctx->modseq_update_idx].seq1;
+ sync_rec_r->seq2 = range[ctx->modseq_update_idx].seq2;
+ ctx->modseq_update_idx++;
+ return 1;
+ }
+ }
return index_mailbox_sync_next_expunge(ctx, sync_rec_r);
}
if (array_is_created(&ctx->flag_updates))
array_free(&ctx->flag_updates);
+ if (array_is_created(&ctx->modseq_updates))
+ array_free(&ctx->modseq_updates);
i_free(ctx);
return ret;
}