From e91d2cf272c1d3698a087d5ace96301f07a1151e Mon Sep 17 00:00:00 2001 From: Valera V Harseko Date: Fri, 10 Jul 2026 22:17:46 +0300 Subject: [PATCH] persistit: settle MVCC state at the end of Persistit.initialize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Recovery completes synchronously inside initialize(), but two maintenance tasks were left to background timers: the TransactionIndex active-transaction cache update and CleanupManager's pruneTimelyResources() (first pass no earlier than 1s after startup). Until they ran, residual tree-version state from before a crash could leak into step-based MVCC visibility — e.g. Volume.getTree(name, false) reporting a tree created at step 1 as visible at step 0. Update the active-transaction cache and prune timely resources synchronously at the end of initialize(), before the background managers start, so applications get correct step visibility immediately after initialize() returns. Both calls are idempotent and their cost is bounded (one ATC recompute plus one pass over recovered timely resources). Fixes #264. --- .../core/src/main/java/com/persistit/Persistit.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/persistit/core/src/main/java/com/persistit/Persistit.java b/persistit/core/src/main/java/com/persistit/Persistit.java index 7bf86b388..bbea6343b 100644 --- a/persistit/core/src/main/java/com/persistit/Persistit.java +++ b/persistit/core/src/main/java/com/persistit/Persistit.java @@ -448,6 +448,15 @@ public synchronized void initialize() throws PersistitException { flush(); _checkpointManager.checkpoint(); _journalManager.pruneObsoleteTransactions(); + /* + * Settle MVCC state left over from recovery before returning: without + * this, step-based visibility (e.g. Volume#getTree(String, boolean)) + * can return stale answers until the CleanupManager timer fires. The + * active-transaction cache must be updated first because pruning + * consults it. + */ + _transactionIndex.updateActiveTransactionCache(); + pruneTimelyResources(); startCheckpointManager(); startCleanupManager(); _initialized.set(true);