From 590f2eff0907d30661ffcb4ecdf2d7c1a488e94c Mon Sep 17 00:00:00 2001 From: Valera V Harseko Date: Fri, 10 Jul 2026 23:20:59 +0300 Subject: [PATCH] Make WarmupTest.readOrderIsSequential deterministic The test records the buffer inventory at shutdown, restarts with a TrackingFileChannel injected into the volume channel, preloads, and asserts the channel saw the reads. Intermittently it saw zero reads: recordBufferInventory() interleaves its own _buffer_inventory_ tree stores with the pool scan, so some recorded pages are the inventory tree's own pages; the closing checkpoint flushes those to the journal with no subsequent copyBack(), and on restart VolumeStorageV2.readPage() serves them from the journal first, bypassing the injected volume channel. Make the setup deterministic: after the first close, reopen with buffer inventory recording disabled, run copyBackPages() to drain the journal into the volume, and close again, so every recorded page lives in the volume file. Preload then reads the recorded pages through the injected channel in strictly ascending page order. Also fix TrackingFileChannel.assertOrdered, which never advanced `previous` and so only checked `position > -1`; it now verifies read order. --- .../com/persistit/TrackingFileChannel.java | 3 +- .../test/java/com/persistit/WarmupTest.java | 29 +++++++++++++++---- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/persistit/core/src/test/java/com/persistit/TrackingFileChannel.java b/persistit/core/src/test/java/com/persistit/TrackingFileChannel.java index dd4d9fc0c..41243761b 100644 --- a/persistit/core/src/test/java/com/persistit/TrackingFileChannel.java +++ b/persistit/core/src/test/java/com/persistit/TrackingFileChannel.java @@ -163,13 +163,14 @@ public List getReadPositionList() { public void assertOrdered(final boolean read, final boolean forward) { final List list = read ? _readPositions : _writePositions; - final long previous = forward ? -1 : Long.MAX_VALUE; + long previous = forward ? -1 : Long.MAX_VALUE; for (final Long position : list) { if (forward) { assertTrue("Position should be larger", position > previous); } else { assertTrue("Position should be smaller", position < previous); } + previous = position; } } } diff --git a/persistit/core/src/test/java/com/persistit/WarmupTest.java b/persistit/core/src/test/java/com/persistit/WarmupTest.java index 1d0141aae..8e3de26af 100644 --- a/persistit/core/src/test/java/com/persistit/WarmupTest.java +++ b/persistit/core/src/test/java/com/persistit/WarmupTest.java @@ -66,7 +66,6 @@ public void testWarmup() throws Exception { @Test public void readOrderIsSequential() throws Exception { - Exchange ex = _persistit.getExchange("persistit", "WarmupTest", true); BufferPool pool = ex.getBufferPool(); @@ -107,11 +106,24 @@ public void readOrderIsSequential() throws Exception { _persistit.copyBackPages(); _persistit.close(); - _persistit = new Persistit(); + /* + * recordBufferInventory() at the close above interleaves its own tree stores + * with the buffer scan, so some recorded pages are the inventory tree's own + * pages; the closing checkpoint flushes those to the journal with no + * copyBack(), and on restart they would be served from the journal + * (VolumeStorageV2.readPage consults readPageFromJournal first), bypassing + * the injected volume channel. Reopen with inventory recording disabled, + * drain the journal into the volume, and close again so every recorded page + * lives in the volume file; the preload below then reads them through the + * tracked channel deterministically instead of racing the journal. + */ _config.setBufferInventoryEnabled(false); _config.setBufferPreloadEnabled(false); - _persistit.setConfiguration(_config); - _persistit.initialize(); + _persistit = new Persistit(_config); + _persistit.copyBackPages(); + _persistit.close(); + + _persistit = new Persistit(_config); final Volume volume = _persistit.getVolume("persistit"); final MediatedFileChannel mfc = (MediatedFileChannel) volume.getStorage().getChannel(); @@ -119,7 +131,14 @@ public void readOrderIsSequential() throws Exception { mfc.injectChannelForTests(tfc); pool = volume.getStructure().getPool(); pool.preloadBufferInventory(); - assertTrue("Preload should have loaded pages from journal file", tfc.getReadPositionList().size() > 0); + /* + * With the recorded pages copied back to the volume above, preload reads + * them through the injected volume channel rather than the journal, so the + * channel sees a non-empty, strictly ascending sequence of reads (warmup + * issues them in page order via PageNode.READ_COMPARATOR). + */ + assertTrue("Preload should have read the recorded pages from the volume file", + tfc.getReadPositionList().size() > 0); tfc.assertOrdered(true, true); } }