uint32_t last_tail_seq, last_tail_offset;
unsigned int no_warning:1;
+ unsigned int seen_nonexternal_transactions:1;
};
static void mail_index_sync_add_expunge(struct mail_index_sync_ctx *ctx)
mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
&seq, &offset);
+ ctx->seen_nonexternal_transactions = TRUE;
ctx->last_tail_seq = seq;
ctx->last_tail_offset = offset + ctx->hdr->size + sizeof(*ctx->hdr);
}
mail_transaction_log_set_mailbox_sync_pos(ctx->index->log, seq, offset);
/* If tail offset has changed, make sure it gets written to
- transaction log. do this only if we're required to changes. */
- if (ctx->last_tail_seq != seq ||
- ctx->last_tail_offset < offset) {
+ transaction log. do this only if we're required to make changes.
+
+ avoid writing a new tail offset if all the transactions were
+ external, because that wouldn't change effective the tail offset.
+ except e.g. mdbox map requires this to happen, so do it
+ optionally. */
+ if ((ctx->last_tail_seq != seq || ctx->last_tail_offset < offset) &&
+ (ctx->seen_nonexternal_transactions ||
+ (ctx->flags & MAIL_INDEX_SYNC_FLAG_UPDATE_TAIL_OFFSET) != 0)) {
ctx->ext_trans->log_updates = TRUE;
ctx->ext_trans->tail_offset_changed = TRUE;
}
/* Same as MAIL_INDEX_SYNC_FLAG_DELETING_INDEX, but finish index
deletion only once and fail the rest (= avoid race conditions when
multiple processes try to mark the index deleted) */
- MAIL_INDEX_SYNC_FLAG_TRY_DELETING_INDEX = 0x40
+ MAIL_INDEX_SYNC_FLAG_TRY_DELETING_INDEX = 0x40,
+ /* Update header's tail_offset to head_offset, even if it's the only
+ thing we do and there's no strict need for it. */
+ MAIL_INDEX_SYNC_FLAG_UPDATE_TAIL_OFFSET = 0x80
};
enum mail_index_view_sync_flags {
/* use syncing to lock the transaction log, so that we always see
log's head_offset = tail_offset */
ret = mail_index_sync_begin(atomic->map->index, &atomic->sync_ctx,
- &atomic->sync_view, &atomic->sync_trans, 0);
+ &atomic->sync_view, &atomic->sync_trans,
+ MAIL_INDEX_SYNC_FLAG_UPDATE_TAIL_OFFSET);
if (mail_index_reset_fscked(atomic->map->index))
mdbox_storage_set_corrupted(atomic->map->storage);
if (ret <= 0) {