You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sd...@apache.org on 2022/06/06 09:19:16 UTC

[ignite-3] branch main updated: IGNITE-16641 [Native Persistence 3.0] Support persistent B+Tree-based storage (#845)

This is an automated email from the ASF dual-hosted git repository.

sdanilov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 706968b82 IGNITE-16641 [Native Persistence 3.0] Support persistent B+Tree-based storage (#845)
706968b82 is described below

commit 706968b8271968b69cfdbd360c1cea9bca906170
Author: Kirill Tkalenko <tk...@yandex.ru>
AuthorDate: Mon Jun 6 12:19:12 2022 +0300

    IGNITE-16641 [Native Persistence 3.0] Support persistent B+Tree-based storage (#845)
---
 .../apache/ignite/internal/util/ArrayUtils.java    |  19 ++
 .../ignite/internal/util/ArrayUtilsSelfTest.java   |  15 ++
 .../persistence/ItBplusTreePageMemoryImplTest.java |   7 +-
 .../ItBplusTreeReuseListPageMemoryImplTest.java    |   7 +-
 .../ignite/internal/pagememory/io/PageIo.java      |   1 +
 .../pagememory/mem/DirectMemoryProvider.java       |   2 +
 .../pagememory/mem/DirectMemoryRegion.java         |   6 +-
 .../mem/unsafe/UnsafeMemoryProvider.java           |   3 +-
 .../pagememory/persistence/PageMemoryImpl.java     |  21 +-
 .../persistence/checkpoint/CheckpointManager.java  |   4 +-
 .../persistence/checkpoint/CheckpointWorkflow.java |   8 +-
 .../persistence/PageMemoryImplNoLoadTest.java      |  24 +-
 .../runner/app/ItIgniteNodeRestartTest.java        |   4 +-
 .../org/apache/ignite/internal/app/IgniteImpl.java |   8 +-
 .../sql/engine/exec/MockedStructuresTest.java      |   2 +-
 .../ignite/internal/storage/DataStorageModule.java |  11 +-
 .../internal/storage/DataStorageModules.java       |  10 +-
 .../storage/AbstractPartitionStorageTest.java      |   6 +-
 .../internal/storage/DataStorageManagerTest.java   |  12 +-
 .../internal/storage/DataStorageModulesTest.java   |   9 +-
 .../TestConcurrentHashMapDataStorageModule.java    |   9 +-
 .../pagememory/AbstractPageMemoryDataRegion.java   |   1 -
 ...ge.java => AbstractPageMemoryTableStorage.java} |   9 +-
 .../pagememory/PageMemoryDataStorageModule.java    |  11 +-
 .../pagememory/PageMemoryStorageEngine.java        | 119 +++++++++-
 .../pagememory/PageMemoryStorageIoModule.java      |   4 +-
 ...eMemoryTableStorage.java => PartitionMeta.java} |  37 +--
 .../pagememory/PersistentPageMemoryDataRegion.java | 142 +++++++++++
 .../PersistentPageMemoryPartitionStorage.java      | 152 ++++++++++++
 .../PersistentPageMemoryTableStorage.java          | 262 +++++++++++++++++++++
 .../pagememory/VolatilePageMemoryDataRegion.java   |   2 +-
 ...ava => VolatilePageMemoryPartitionStorage.java} |  48 +---
 .../pagememory/VolatilePageMemoryTableStorage.java |  58 ++++-
 ...PageMemoryStorageEngineConfigurationSchema.java |   5 +
 .../storage/pagememory/io/PartitionMetaIo.java     | 110 +++++++++
 .../storage/pagememory/mv/io/RowVersionDataIo.java |   2 +-
 .../pagememory/mv/io/VersionChainDataIo.java       |   2 +-
 .../pagememory/mv/io/VersionChainInnerIo.java      |   2 +-
 .../pagememory/mv/io/VersionChainLeafIo.java       |   2 +-
 .../pagememory/mv/io/VersionChainMetaIo.java       |   2 +-
 .../PersistentPageMemoryDataRegionTest.java        |  88 +++++++
 ... PersistentPageMemoryPartitionStorageTest.java} |  68 +++---
 ...=> VolatilePageMemoryPartitionStorageTest.java} |  19 +-
 .../mv/PageMemoryMvPartitionStorageTest.java       |  11 +-
 .../storage/rocksdb/RocksDbDataStorageModule.java  |   9 +-
 .../ignite/internal/table/TableManagerTest.java    |   2 +-
 46 files changed, 1176 insertions(+), 179 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/ArrayUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/util/ArrayUtils.java
index b9a1f2fda..60b5067d2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/ArrayUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/ArrayUtils.java
@@ -315,6 +315,25 @@ public final class ArrayUtils {
         return newArr;
     }
 
+    /**
+     * Concatenates an elements to an array.
+     *
+     * @param arr Array.
+     * @param longs One or more elements.
+     * @return Concatenated array.
+     */
+    public static long[] concat(@Nullable long[] arr, long... longs) {
+        if (nullOrEmpty(arr)) {
+            return longs;
+        }
+
+        long[] newArr = Arrays.copyOf(arr, arr.length + longs.length);
+
+        System.arraycopy(longs, 0, newArr, arr.length, longs.length);
+
+        return newArr;
+    }
+
     /**
      * Removes an element from an array with decrementing the array itself.
      *
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/ArrayUtilsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/ArrayUtilsSelfTest.java
index ac8bb26ba..a81d84cd1 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/util/ArrayUtilsSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/ArrayUtilsSelfTest.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.util;
 
 import static org.apache.ignite.internal.util.ArrayUtils.clearTail;
+import static org.apache.ignite.internal.util.ArrayUtils.concat;
 import static org.apache.ignite.internal.util.ArrayUtils.remove;
 import static org.apache.ignite.internal.util.ArrayUtils.set;
 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
@@ -134,4 +135,18 @@ public class ArrayUtilsSelfTest {
             assertEquals("zz", arr[i]);
         }
     }
+
+    @Test
+    void testConcatLong() {
+        long[] arr = {};
+
+        assertSame(arr, concat(null, arr));
+        assertSame(arr, concat(new long[0], arr));
+
+        assertArrayEquals(new long[]{0}, concat(arr, 0));
+        assertArrayEquals(new long[]{0, 1}, concat(arr, 0, 1));
+        assertArrayEquals(new long[]{1, 2}, concat(new long[]{1}, 2));
+        assertArrayEquals(new long[]{1, 2, 3}, concat(new long[]{1, 2}, 3));
+        assertArrayEquals(new long[]{1, 2, 3, 4}, concat(new long[]{1, 2}, 3, 4));
+    }
 }
diff --git a/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/persistence/ItBplusTreePageMemoryImplTest.java b/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/persistence/ItBplusTreePageMemoryImplTest.java
index 88163cd51..d04703330 100644
--- a/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/persistence/ItBplusTreePageMemoryImplTest.java
+++ b/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/persistence/ItBplusTreePageMemoryImplTest.java
@@ -36,10 +36,6 @@ public class ItBplusTreePageMemoryImplTest extends ItBplusTreeSelfTest {
     protected PageMemory createPageMemory() throws Exception {
         dataRegionCfg.change(c -> c.changeInitSize(MAX_MEMORY_SIZE).changeMaxSize(MAX_MEMORY_SIZE)).get(1, TimeUnit.SECONDS);
 
-        long[] sizes = LongStream.range(0, CPUS + 1).map(i -> MAX_MEMORY_SIZE / CPUS).toArray();
-
-        sizes[CPUS] = 10 * MiB;
-
         TestPageIoRegistry ioRegistry = new TestPageIoRegistry();
 
         ioRegistry.loadFromServiceLoader();
@@ -47,7 +43,8 @@ public class ItBplusTreePageMemoryImplTest extends ItBplusTreeSelfTest {
         return new PageMemoryImpl(
                 dataRegionCfg,
                 ioRegistry,
-                sizes,
+                LongStream.range(0, CPUS).map(i -> MAX_MEMORY_SIZE / CPUS).toArray(),
+                10 * MiB,
                 new TestPageReadWriteManager(),
                 (page, fullPageId, pageMemoryImpl) -> {
                 },
diff --git a/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/persistence/ItBplusTreeReuseListPageMemoryImplTest.java b/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/persistence/ItBplusTreeReuseListPageMemoryImplTest.java
index bb428a90d..0951b875c 100644
--- a/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/persistence/ItBplusTreeReuseListPageMemoryImplTest.java
+++ b/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/persistence/ItBplusTreeReuseListPageMemoryImplTest.java
@@ -35,10 +35,6 @@ public class ItBplusTreeReuseListPageMemoryImplTest extends ItBplusTreeReuseSelf
     protected PageMemory createPageMemory() throws Exception {
         dataRegionCfg.change(c -> c.changeInitSize(MAX_MEMORY_SIZE).changeMaxSize(MAX_MEMORY_SIZE)).get(1, TimeUnit.SECONDS);
 
-        long[] sizes = LongStream.range(0, CPUS + 1).map(i -> MAX_MEMORY_SIZE / CPUS).toArray();
-
-        sizes[CPUS] = 10 * MiB;
-
         TestPageIoRegistry ioRegistry = new TestPageIoRegistry();
 
         ioRegistry.loadFromServiceLoader();
@@ -46,7 +42,8 @@ public class ItBplusTreeReuseListPageMemoryImplTest extends ItBplusTreeReuseSelf
         return new PageMemoryImpl(
                 dataRegionCfg,
                 ioRegistry,
-                sizes,
+                LongStream.range(0, CPUS).map(i -> MAX_MEMORY_SIZE / CPUS).toArray(),
+                10 * MiB,
                 new TestPageReadWriteManager(),
                 (page, fullPageId, pageMemoryImpl) -> {
                 },
diff --git a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/io/PageIo.java b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/io/PageIo.java
index 631c2d2d3..0e7879039 100644
--- a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/io/PageIo.java
+++ b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/io/PageIo.java
@@ -104,6 +104,7 @@ public abstract class PageIo {
     private final int ver;
 
     /** IO type. */
+    // TODO: IGNITE-17104 Consider the mechanism for avoiding type intersection for different structures
     private final int type;
 
     /** IO flag: either {@link PageIdAllocator#FLAG_DATA} or {@link PageIdAllocator#FLAG_AUX}. */
diff --git a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/mem/DirectMemoryProvider.java b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/mem/DirectMemoryProvider.java
index b7534981e..2926b1c50 100644
--- a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/mem/DirectMemoryProvider.java
+++ b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/mem/DirectMemoryProvider.java
@@ -28,6 +28,7 @@ public interface DirectMemoryProvider {
      *
      * @param chunkSizes Chunk sizes.
      */
+    // TODO: IGNITE-16350 Consider deleting a method
     void initialize(long[] chunkSizes);
 
     /**
@@ -43,5 +44,6 @@ public interface DirectMemoryProvider {
      * @return Next memory region.
      */
     @Nullable
+    // TODO: IGNITE-16350 Consider adding a region size argument
     DirectMemoryRegion nextRegion();
 }
diff --git a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/mem/DirectMemoryRegion.java b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/mem/DirectMemoryRegion.java
index 1070c9645..f5678589b 100644
--- a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/mem/DirectMemoryRegion.java
+++ b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/mem/DirectMemoryRegion.java
@@ -24,12 +24,12 @@ public interface DirectMemoryRegion {
     /**
      * Returns a region start address.
      */
-    public long address();
+    long address();
 
     /**
      * Returns a region size.
      */
-    public long size();
+    long size();
 
     /**
      * Creates a sub-region of this region starting from the given offset.
@@ -37,5 +37,5 @@ public interface DirectMemoryRegion {
      * @param offset Offset within this region.
      * @return Sub-region.
      */
-    public DirectMemoryRegion slice(long offset);
+    DirectMemoryRegion slice(long offset);
 }
diff --git a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/mem/unsafe/UnsafeMemoryProvider.java b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/mem/unsafe/UnsafeMemoryProvider.java
index 1b231857b..31c7a30d5 100644
--- a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/mem/unsafe/UnsafeMemoryProvider.java
+++ b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/mem/unsafe/UnsafeMemoryProvider.java
@@ -95,7 +95,8 @@ public class UnsafeMemoryProvider implements DirectMemoryProvider {
     }
 
     /** {@inheritDoc} */
-    @Override public DirectMemoryRegion nextRegion() {
+    @Override
+    public @Nullable DirectMemoryRegion nextRegion() {
         if (used == sizes.length) {
             return null;
         }
diff --git a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PageMemoryImpl.java b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PageMemoryImpl.java
index 7569db9f0..c40706af2 100644
--- a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PageMemoryImpl.java
+++ b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PageMemoryImpl.java
@@ -39,6 +39,7 @@ import static org.apache.ignite.internal.pagememory.util.PageIdUtils.pageId;
 import static org.apache.ignite.internal.pagememory.util.PageIdUtils.pageIndex;
 import static org.apache.ignite.internal.pagememory.util.PageIdUtils.partitionId;
 import static org.apache.ignite.internal.pagememory.util.PageIdUtils.tag;
+import static org.apache.ignite.internal.util.ArrayUtils.concat;
 import static org.apache.ignite.internal.util.FastTimestamps.coarseCurrentTimeMillis;
 import static org.apache.ignite.internal.util.GridUnsafe.BYTE_ARR_OFF;
 import static org.apache.ignite.internal.util.GridUnsafe.bufferAddress;
@@ -191,6 +192,7 @@ public class PageMemoryImpl implements PageMemory {
     private volatile int pageReplacementWarned;
 
     /** Segments sizes, the last one being the {@link #checkpointPool checkpoint buffer} size. */
+    // TODO: IGNITE-16350 Consider splitting into segments and the checkpoint buffer
     private final long[] sizes;
 
     /** {@code False} if memory was not started or already stopped and is not supposed for any usage. */
@@ -221,7 +223,8 @@ public class PageMemoryImpl implements PageMemory {
      *
      * @param dataRegionConfig Data region configuration.
      * @param ioRegistry IO registry.
-     * @param sizes Segments sizes, the last one being the checkpoint buffer size.
+     * @param segmentSizes Segments sizes in bytes.
+     * @param checkpointBufferSize Checkpoint buffer size in bytes.
      * @param pageStoreManager Page store manager.
      * @param changeTracker Callback invoked to track changes in pages.
      * @param flushDirtyPage Write callback invoked when a dirty page is removed for replacement.
@@ -231,7 +234,8 @@ public class PageMemoryImpl implements PageMemory {
     public PageMemoryImpl(
             PageMemoryDataRegionConfiguration dataRegionConfig,
             PageIoRegistry ioRegistry,
-            long[] sizes,
+            long[] segmentSizes,
+            long checkpointBufferSize,
             PageReadWriteManager pageStoreManager,
             @Nullable PageChangeTracker changeTracker,
             PageStoreWriter flushDirtyPage,
@@ -241,7 +245,7 @@ public class PageMemoryImpl implements PageMemory {
     ) {
         this.dataRegionConfigView = dataRegionConfig.value();
         this.ioRegistry = ioRegistry;
-        this.sizes = sizes;
+        this.sizes = concat(segmentSizes, checkpointBufferSize);
         this.pageStoreManager = pageStoreManager;
         this.changeTracker = changeTracker;
         this.flushDirtyPage = flushDirtyPage;
@@ -308,11 +312,11 @@ public class PageMemoryImpl implements PageMemory {
 
             Segment[] segments = new Segment[regs - 1];
 
-            DirectMemoryRegion cpReg = regions.get(regs - 1);
+            DirectMemoryRegion checkpointRegion = regions.get(regs - 1);
 
-            checkpointPool = new PagePool(regs - 1, cpReg, sysPageSize, rwLock);
+            checkpointPool = new PagePool(regs - 1, checkpointRegion, sysPageSize, rwLock);
 
-            long checkpointBuf = cpReg.size();
+            long checkpointBufferSize = checkpointRegion.size();
 
             long totalAllocated = 0;
             int pages = 0;
@@ -340,7 +344,7 @@ public class PageMemoryImpl implements PageMemory {
                         + ", pages=" + pages
                         + ", tableSize=" + readableSize(totalTblSize, false)
                         + ", replacementSize=" + readableSize(totalReplSize, false)
-                        + ", checkpointBuffer=" + readableSize(checkpointBuf, false)
+                        + ", checkpointBuffer=" + readableSize(checkpointBufferSize, false)
                         + ']');
             }
         }
@@ -611,8 +615,7 @@ public class PageMemoryImpl implements PageMemory {
     public long partitionMetaPageId(int grpId, int partId) {
         assert started;
 
-        //TODO IGNITE-16350 Consider reworking in FLAG_AUX.
-        return pageId(partId, FLAG_DATA, 0);
+        return pageId(partId, FLAG_AUX, 0);
     }
 
     /** {@inheritDoc} */
diff --git a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/checkpoint/CheckpointManager.java b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/checkpoint/CheckpointManager.java
index 2a8dd9ece..7e4a4896f 100644
--- a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/checkpoint/CheckpointManager.java
+++ b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/checkpoint/CheckpointManager.java
@@ -85,7 +85,7 @@ public class CheckpointManager implements IgniteComponent {
             @Nullable LongJvmPauseDetector longJvmPauseDetector,
             PageMemoryCheckpointConfiguration checkpointConfig,
             FilePageStoreManager filePageStoreManager,
-            Collection<PageMemoryDataRegion> dataRegions,
+            Collection<? extends PageMemoryDataRegion> dataRegions,
             Path storagePath,
             // TODO: IGNITE-17017 Move to common config
             int pageSize
@@ -196,7 +196,7 @@ public class CheckpointManager implements IgniteComponent {
      * @param dataRegions Data regions.
      * @see PageMemoryImpl#safeToUpdate()
      */
-    static boolean safeToUpdateAllPageMemories(Collection<PageMemoryDataRegion> dataRegions) {
+    static boolean safeToUpdateAllPageMemories(Collection<? extends PageMemoryDataRegion> dataRegions) {
         for (PageMemoryDataRegion dataRegion : dataRegions) {
             if (dataRegion.persistent() && !((PageMemoryImpl) dataRegion.pageMemory()).safeToUpdate()) {
                 return false;
diff --git a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/checkpoint/CheckpointWorkflow.java b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/checkpoint/CheckpointWorkflow.java
index 88d788e59..8b064a774 100644
--- a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/checkpoint/CheckpointWorkflow.java
+++ b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/checkpoint/CheckpointWorkflow.java
@@ -80,7 +80,7 @@ class CheckpointWorkflow implements IgniteComponent {
     private final CheckpointReadWriteLock checkpointReadWriteLock;
 
     /** Persistent data regions for the checkpointing. */
-    private final Collection<PageMemoryDataRegion> dataRegions;
+    private final Collection<? extends PageMemoryDataRegion> dataRegions;
 
     /** Checkpoint write order configuration. */
     private final CheckpointWriteOrder checkpointWriteOrder;
@@ -100,7 +100,7 @@ class CheckpointWorkflow implements IgniteComponent {
             PageMemoryCheckpointConfiguration checkpointConfig,
             CheckpointMarkersStorage checkpointMarkersStorage,
             CheckpointReadWriteLock checkpointReadWriteLock,
-            Collection<PageMemoryDataRegion> dataRegions
+            Collection<? extends PageMemoryDataRegion> dataRegions
     ) {
         PageMemoryCheckpointView checkpointConfigView = checkpointConfig.value();
 
@@ -260,7 +260,7 @@ class CheckpointWorkflow implements IgniteComponent {
      *
      * @param dataRegions Data regions.
      */
-    public List<CheckpointListener> collectCheckpointListeners(Collection<PageMemoryDataRegion> dataRegions) {
+    public List<CheckpointListener> collectCheckpointListeners(Collection<? extends PageMemoryDataRegion> dataRegions) {
         return listeners.stream()
                 .filter(tuple -> tuple.getValue() == null || dataRegions.contains(tuple.getValue()))
                 .map(IgniteBiTuple::getKey)
@@ -268,7 +268,7 @@ class CheckpointWorkflow implements IgniteComponent {
     }
 
     private CheckpointDirtyPagesInfoHolder beginCheckpoint(
-            Collection<PageMemoryDataRegion> dataRegions,
+            Collection<? extends PageMemoryDataRegion> dataRegions,
             CompletableFuture<?> allowToReplace
     ) {
         Collection<IgniteBiTuple<PageMemoryImpl, Collection<FullPageId>>> pages = new ArrayList<>(dataRegions.size());
diff --git a/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/PageMemoryImplNoLoadTest.java b/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/PageMemoryImplNoLoadTest.java
index a244f14e1..09fba505f 100644
--- a/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/PageMemoryImplNoLoadTest.java
+++ b/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/PageMemoryImplNoLoadTest.java
@@ -69,7 +69,7 @@ public class PageMemoryImplNoLoadTest extends PageMemoryNoLoadSelfTest {
     /** {@inheritDoc} */
     @Override
     protected PageMemory memory() {
-        return createPageMemoryImpl(defaultSegmentSizes(), null, null);
+        return createPageMemoryImpl(defaultSegmentSizes(), defaultCheckpointBufferSize(), null, null);
     }
 
     /** {@inheritDoc} */
@@ -90,7 +90,12 @@ public class PageMemoryImplNoLoadTest extends PageMemoryNoLoadSelfTest {
 
         CheckpointManager checkpointManager = createCheckpointManager(checkpointConfig, workDir, filePageStoreManager, dataRegions);
 
-        PageMemoryImpl pageMemoryImpl = createPageMemoryImpl(defaultSegmentSizes(), filePageStoreManager, checkpointManager);
+        PageMemoryImpl pageMemoryImpl = createPageMemoryImpl(
+                defaultSegmentSizes(),
+                defaultCheckpointBufferSize(),
+                filePageStoreManager,
+                checkpointManager
+        );
 
         dataRegions.add(newDataRegion(true, pageMemoryImpl));
 
@@ -144,7 +149,8 @@ public class PageMemoryImplNoLoadTest extends PageMemoryNoLoadSelfTest {
         dataRegionCfg.change(c -> c.changeInitSize(128 * systemPageSize).changeMaxSize(128 * systemPageSize)).get(1, SECONDS);
 
         PageMemoryImpl pageMemoryImpl = createPageMemoryImpl(
-                new long[]{100 * systemPageSize, 28 * systemPageSize},
+                new long[]{100 * systemPageSize},
+                28 * systemPageSize,
                 filePageStoreManager,
                 checkpointManager
         );
@@ -200,7 +206,8 @@ public class PageMemoryImplNoLoadTest extends PageMemoryNoLoadSelfTest {
     }
 
     protected PageMemoryImpl createPageMemoryImpl(
-            long[] sizes,
+            long[] segmentSizes,
+            long checkpointBufferSize,
             @Nullable FilePageStoreManager filePageStoreManager,
             @Nullable CheckpointManager checkpointManager
     ) {
@@ -211,7 +218,8 @@ public class PageMemoryImplNoLoadTest extends PageMemoryNoLoadSelfTest {
         return new PageMemoryImpl(
                 dataRegionCfg,
                 ioRegistry,
-                sizes,
+                segmentSizes,
+                checkpointBufferSize,
                 filePageStoreManager == null ? new TestPageReadWriteManager() : filePageStoreManager,
                 null,
                 (fullPageId, buf, tag) -> fail("Should not happen"),
@@ -235,7 +243,11 @@ public class PageMemoryImplNoLoadTest extends PageMemoryNoLoadSelfTest {
     }
 
     private static long[] defaultSegmentSizes() {
-        return LongStream.range(0, 10).map(i -> 5 * MiB).toArray();
+        return LongStream.range(0, 9).map(i -> 5 * MiB).toArray();
+    }
+
+    private static long defaultCheckpointBufferSize() {
+        return 5 * MiB;
     }
 
     private static CheckpointManager createCheckpointManager(
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
index 3e90e4979..8f15f4fd0 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
@@ -259,8 +259,10 @@ public class ItIgniteNodeRestartTest extends IgniteAbstractTest {
         DataStorageManager dataStorageManager = new DataStorageManager(
                 clusterCfgMgr.configurationRegistry().getConfiguration(TablesConfiguration.KEY),
                 dataStorageModules.createStorageEngines(
+                        name,
                         clusterCfgMgr.configurationRegistry(),
-                        getPartitionsStorePath(dir)
+                        getPartitionsStorePath(dir),
+                        null
                 )
         );
 
diff --git a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
index 354f22191..04b33842f 100644
--- a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
+++ b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
@@ -205,6 +205,8 @@ public class IgniteImpl implements Ignite {
     IgniteImpl(String name, Path workDir, @Nullable ClassLoader serviceProviderClassLoader) {
         this.name = name;
 
+        longJvmPauseDetector = new LongJvmPauseDetector(name);
+
         lifecycleManager = new LifecycleManager(name);
 
         vaultMgr = createVault(workDir);
@@ -295,8 +297,10 @@ public class IgniteImpl implements Ignite {
         dataStorageMgr = new DataStorageManager(
                 clusterCfgMgr.configurationRegistry().getConfiguration(TablesConfiguration.KEY),
                 dataStorageModules.createStorageEngines(
+                        name,
                         clusterCfgMgr.configurationRegistry(),
-                        getPartitionsStorePath(workDir)
+                        getPartitionsStorePath(workDir),
+                        longJvmPauseDetector
                 )
         );
 
@@ -338,8 +342,6 @@ public class IgniteImpl implements Ignite {
                 nettyBootstrapFactory,
                 sql
         );
-
-        longJvmPauseDetector = new LongJvmPauseDetector(name);
     }
 
     private static ConfigurationModules loadConfigurationModules(ClassLoader classLoader) {
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/MockedStructuresTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/MockedStructuresTest.java
index 765c39cc5..79195cf84 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/MockedStructuresTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/MockedStructuresTest.java
@@ -226,7 +226,7 @@ public class MockedStructuresTest extends IgniteAbstractTest {
 
         dataStorageManager = new DataStorageManager(
                 tblsCfg,
-                dataStorageModules.createStorageEngines(configRegistry, workDir)
+                dataStorageModules.createStorageEngines(NODE_NAME, configRegistry, workDir, null)
         );
 
         dataStorageManager.start();
diff --git a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageModule.java b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageModule.java
index a323f8e0a..0025b8e21 100644
--- a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageModule.java
+++ b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageModule.java
@@ -19,8 +19,10 @@ package org.apache.ignite.internal.storage;
 
 import java.nio.file.Path;
 import org.apache.ignite.configuration.schemas.store.DataStorageConfigurationSchema;
+import org.apache.ignite.internal.components.LongJvmPauseDetector;
 import org.apache.ignite.internal.configuration.ConfigurationRegistry;
 import org.apache.ignite.internal.storage.engine.StorageEngine;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * Data storage module.
@@ -36,9 +38,16 @@ public interface DataStorageModule {
     /**
      * Creates a new storage engine.
      *
+     * @param igniteInstanceName String igniteInstanceName
      * @param configRegistry Configuration register.
      * @param storagePath Storage path.
+     * @param longJvmPauseDetector Long JVM pause detector.
      * @throws StorageException If there is an error when creating the storage engine.
      */
-    StorageEngine createEngine(ConfigurationRegistry configRegistry, Path storagePath) throws StorageException;
+    StorageEngine createEngine(
+            String igniteInstanceName,
+            ConfigurationRegistry configRegistry,
+            Path storagePath,
+            @Nullable LongJvmPauseDetector longJvmPauseDetector
+    ) throws StorageException;
 }
diff --git a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageModules.java b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageModules.java
index da6238199..00db64e3a 100644
--- a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageModules.java
+++ b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageModules.java
@@ -34,8 +34,10 @@ import org.apache.ignite.configuration.annotation.PolymorphicConfigInstance;
 import org.apache.ignite.configuration.annotation.Value;
 import org.apache.ignite.configuration.schemas.store.DataStorageConfigurationSchema;
 import org.apache.ignite.configuration.schemas.store.UnknownDataStorageConfigurationSchema;
+import org.apache.ignite.internal.components.LongJvmPauseDetector;
 import org.apache.ignite.internal.configuration.ConfigurationRegistry;
 import org.apache.ignite.internal.storage.engine.StorageEngine;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * Auxiliary class for working with {@link DataStorageModule}.
@@ -86,17 +88,21 @@ public class DataStorageModules {
     /**
      * Creates new storage engines unique by {@link DataStorageModule#name name}.
      *
+     * @param igniteInstanceName String igniteInstanceName
      * @param configRegistry Configuration register.
      * @param storagePath Storage path.
+     * @param longJvmPauseDetector Long JVM pause detector.
      * @throws StorageException If there is an error when creating the storage engines.
      */
     public Map<String, StorageEngine> createStorageEngines(
+            String igniteInstanceName,
             ConfigurationRegistry configRegistry,
-            Path storagePath
+            Path storagePath,
+            @Nullable LongJvmPauseDetector longJvmPauseDetector
     ) {
         return modules.entrySet().stream().collect(toUnmodifiableMap(
                 Entry::getKey,
-                e -> e.getValue().createEngine(configRegistry, storagePath)
+                e -> e.getValue().createEngine(igniteInstanceName, configRegistry, storagePath, longJvmPauseDetector)
         ));
     }
 
diff --git a/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/AbstractPartitionStorageTest.java b/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/AbstractPartitionStorageTest.java
index be90ef4a2..990832cfa 100644
--- a/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/AbstractPartitionStorageTest.java
+++ b/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/AbstractPartitionStorageTest.java
@@ -63,10 +63,10 @@ import org.junit.jupiter.api.extension.ExtendWith;
 @ExtendWith(WorkDirectoryExtension.class)
 public abstract class AbstractPartitionStorageTest {
     /** Test key. */
-    private static final String KEY = "key";
+    protected static final String KEY = "key";
 
     /** Test value. */
-    private static final String VALUE = "value";
+    protected static final String VALUE = "value";
 
     /** Storage instance. */
     protected PartitionStorage storage;
@@ -644,7 +644,7 @@ public abstract class AbstractPartitionStorageTest {
      *
      * @param row Expected data row.
      */
-    private void checkHasSameEntry(DataRow row) {
+    protected void checkHasSameEntry(DataRow row) {
         DataRow read = storage.read(row);
 
         assertNotNull(read);
diff --git a/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/DataStorageManagerTest.java b/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/DataStorageManagerTest.java
index 873059e96..d21981f5c 100644
--- a/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/DataStorageManagerTest.java
+++ b/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/DataStorageManagerTest.java
@@ -84,7 +84,7 @@ public class DataStorageManagerTest {
 
         DataStorageManager dataStorageManager = new DataStorageManager(
                 tablesConfig,
-                dataStorageModules.createStorageEngines(mock(ConfigurationRegistry.class), workDir)
+                dataStorageModules.createStorageEngines("test", mock(ConfigurationRegistry.class), workDir, null)
         );
 
         // Checks that the current default is "pagememory" even if we have one engine and it's not "pagememory".
@@ -100,7 +100,7 @@ public class DataStorageManagerTest {
 
         DataStorageManager dataStorageManager = new DataStorageManager(
                 tablesConfig,
-                dataStorageModules.createStorageEngines(mock(ConfigurationRegistry.class), workDir)
+                dataStorageModules.createStorageEngines("test", mock(ConfigurationRegistry.class), workDir, null)
         );
 
         assertThat("pagememory", equalTo(dataStorageManager.defaultDataStorage()));
@@ -124,7 +124,7 @@ public class DataStorageManagerTest {
 
         DataStorageManager dataStorageManager = new DataStorageManager(
                 tablesConfig,
-                dataStorageModules.createStorageEngines(mock(ConfigurationRegistry.class), workDir)
+                dataStorageModules.createStorageEngines("test", mock(ConfigurationRegistry.class), workDir, null)
         );
 
         // Check random polymorphicTypeId.
@@ -167,7 +167,7 @@ public class DataStorageManagerTest {
 
         DataStorageManager dataStorageManager = new DataStorageManager(
                 tablesConfig,
-                dataStorageModules.createStorageEngines(mock(ConfigurationRegistry.class), workDir)
+                dataStorageModules.createStorageEngines("test", mock(ConfigurationRegistry.class), workDir, null)
         );
 
         DataStorageView dataStorageView = dataStorageConfig.value();
@@ -203,7 +203,7 @@ public class DataStorageManagerTest {
 
         DataStorageManager dataStorageManager = new DataStorageManager(
                 tablesConfig,
-                dataStorageModules.createStorageEngines(mock(ConfigurationRegistry.class), workDir)
+                dataStorageModules.createStorageEngines("test", mock(ConfigurationRegistry.class), workDir, null)
         );
 
         dataStorageConfig.change(dataStorageManager.defaultTableDataStorageConsumer(FIRST)).get(1, TimeUnit.SECONDS);
@@ -224,7 +224,7 @@ public class DataStorageManagerTest {
 
         DataStorageManager dataStorageManager = new DataStorageManager(
                 tablesConfig,
-                dataStorageModules.createStorageEngines(mock(ConfigurationRegistry.class), workDir)
+                dataStorageModules.createStorageEngines("test", mock(ConfigurationRegistry.class), workDir, null)
         );
 
         dataStorageConfig.change(dataStorageManager.defaultTableDataStorageConsumer(FIRST)).get(1, TimeUnit.SECONDS);
diff --git a/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/DataStorageModulesTest.java b/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/DataStorageModulesTest.java
index 234cf857f..a1f45941b 100644
--- a/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/DataStorageModulesTest.java
+++ b/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/DataStorageModulesTest.java
@@ -114,7 +114,12 @@ public class DataStorageModulesTest {
                 createMockedDataStorageModule(SECOND)
         ));
 
-        Map<String, StorageEngine> engines = dataStorageModules.createStorageEngines(mock(ConfigurationRegistry.class), workDir);
+        Map<String, StorageEngine> engines = dataStorageModules.createStorageEngines(
+                "test",
+                mock(ConfigurationRegistry.class),
+                workDir,
+                null
+        );
 
         assertThat(engines, aMapWithSize(2));
 
@@ -208,7 +213,7 @@ public class DataStorageModulesTest {
 
         when(mock.name()).thenReturn(name);
 
-        when(mock.createEngine(any(), any())).thenReturn(mock(StorageEngine.class));
+        when(mock.createEngine(any(), any(), any(), any())).thenReturn(mock(StorageEngine.class));
 
         return mock;
     }
diff --git a/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/chm/TestConcurrentHashMapDataStorageModule.java b/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/chm/TestConcurrentHashMapDataStorageModule.java
index abe6b01fd..ef52bd654 100644
--- a/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/chm/TestConcurrentHashMapDataStorageModule.java
+++ b/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/chm/TestConcurrentHashMapDataStorageModule.java
@@ -20,10 +20,12 @@ package org.apache.ignite.internal.storage.chm;
 import static org.apache.ignite.internal.storage.chm.TestConcurrentHashMapStorageEngine.ENGINE_NAME;
 
 import java.nio.file.Path;
+import org.apache.ignite.internal.components.LongJvmPauseDetector;
 import org.apache.ignite.internal.configuration.ConfigurationRegistry;
 import org.apache.ignite.internal.storage.DataStorageModule;
 import org.apache.ignite.internal.storage.StorageException;
 import org.apache.ignite.internal.storage.engine.StorageEngine;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * Implementation for creating {@link TestConcurrentHashMapStorageEngine}s.
@@ -37,7 +39,12 @@ public class TestConcurrentHashMapDataStorageModule implements DataStorageModule
 
     /** {@inheritDoc} */
     @Override
-    public StorageEngine createEngine(ConfigurationRegistry configRegistry, Path storagePath) throws StorageException {
+    public StorageEngine createEngine(
+            String igniteInstanceName,
+            ConfigurationRegistry configRegistry,
+            Path storagePath,
+            @Nullable LongJvmPauseDetector longJvmPauseDetector
+    ) throws StorageException {
         return new TestConcurrentHashMapStorageEngine();
     }
 }
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryDataRegion.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryDataRegion.java
index 4e5863076..5d62ec794 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryDataRegion.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryDataRegion.java
@@ -27,7 +27,6 @@ import org.apache.ignite.internal.pagememory.io.PageIoRegistry;
 /**
  * Abstract data region for {@link PageMemoryStorageEngine}. Based on a {@link PageMemory}.
  */
-// TODO: IGNITE-16641 Add support for persistent case.
 abstract class AbstractPageMemoryDataRegion implements PageMemoryDataRegion, IgniteComponent {
     protected final PageMemoryDataRegionConfiguration cfg;
 
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryTableStorage.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryTableStorage.java
similarity index 93%
rename from modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryTableStorage.java
rename to modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryTableStorage.java
index 80d1489da..62d688126 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryTableStorage.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryTableStorage.java
@@ -38,9 +38,8 @@ import org.jetbrains.annotations.TestOnly;
 /**
  * Abstract table storage implementation based on {@link PageMemory}.
  */
-// TODO: IGNITE-16641 Add support for persistent case.
 // TODO: IGNITE-16642 Support indexes.
-public abstract class PageMemoryTableStorage implements TableStorage {
+public abstract class AbstractPageMemoryTableStorage implements TableStorage {
     protected final AbstractPageMemoryDataRegion dataRegion;
 
     protected final TableConfiguration tableCfg;
@@ -58,7 +57,7 @@ public abstract class PageMemoryTableStorage implements TableStorage {
      * @param tableCfg – Table configuration.
      * @param dataRegion – Data region for the table.
      */
-    public PageMemoryTableStorage(TableConfiguration tableCfg, AbstractPageMemoryDataRegion dataRegion) {
+    public AbstractPageMemoryTableStorage(TableConfiguration tableCfg, AbstractPageMemoryDataRegion dataRegion) {
         this.dataRegion = dataRegion;
         this.tableCfg = tableCfg;
     }
@@ -174,12 +173,12 @@ public abstract class PageMemoryTableStorage implements TableStorage {
     }
 
     /**
-     * Returns a new instance of {@link PageMemoryPartitionStorage}.
+     * Returns a new instance of {@link VolatilePageMemoryPartitionStorage}.
      *
      * @param partId Partition id.
      * @throws StorageException If there is an error while creating the partition storage.
      */
-    protected abstract PageMemoryPartitionStorage createPartitionStorage(int partId) throws StorageException;
+    protected abstract VolatilePageMemoryPartitionStorage createPartitionStorage(int partId) throws StorageException;
 
     /**
      * This API is not yet ready. But we need to test mv storages anyways.
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryDataStorageModule.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryDataStorageModule.java
index b6699dbaa..f5ff3afe8 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryDataStorageModule.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryDataStorageModule.java
@@ -20,12 +20,14 @@ package org.apache.ignite.internal.storage.pagememory;
 import static org.apache.ignite.internal.storage.pagememory.PageMemoryStorageEngine.ENGINE_NAME;
 
 import java.nio.file.Path;
+import org.apache.ignite.internal.components.LongJvmPauseDetector;
 import org.apache.ignite.internal.configuration.ConfigurationRegistry;
 import org.apache.ignite.internal.pagememory.io.PageIoRegistry;
 import org.apache.ignite.internal.storage.DataStorageModule;
 import org.apache.ignite.internal.storage.StorageException;
 import org.apache.ignite.internal.storage.engine.StorageEngine;
 import org.apache.ignite.internal.storage.pagememory.configuration.schema.PageMemoryStorageEngineConfiguration;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * Implementation for creating {@link PageMemoryStorageEngine}s.
@@ -39,7 +41,12 @@ public class PageMemoryDataStorageModule implements DataStorageModule {
 
     /** {@inheritDoc} */
     @Override
-    public StorageEngine createEngine(ConfigurationRegistry configRegistry, Path storagePath) throws StorageException {
+    public StorageEngine createEngine(
+            String igniteInstanceName,
+            ConfigurationRegistry configRegistry,
+            Path storagePath,
+            @Nullable LongJvmPauseDetector longJvmPauseDetector
+    ) throws StorageException {
         PageMemoryStorageEngineConfiguration engineConfig = configRegistry.getConfiguration(PageMemoryStorageEngineConfiguration.KEY);
 
         assert engineConfig != null;
@@ -48,6 +55,6 @@ public class PageMemoryDataStorageModule implements DataStorageModule {
 
         ioRegistry.loadFromServiceLoader();
 
-        return new PageMemoryStorageEngine(engineConfig, ioRegistry);
+        return new PageMemoryStorageEngine(igniteInstanceName, engineConfig, ioRegistry, storagePath, longJvmPauseDetector);
     }
 }
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryStorageEngine.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryStorageEngine.java
index d95436511..91e4e912b 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryStorageEngine.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryStorageEngine.java
@@ -18,23 +18,35 @@
 package org.apache.ignite.internal.storage.pagememory;
 
 import static java.util.concurrent.CompletableFuture.completedFuture;
+import static org.apache.ignite.internal.util.IgniteUtils.closeAll;
 
+import java.nio.file.Path;
 import java.util.Map;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Stream;
 import org.apache.ignite.configuration.notifications.ConfigurationNamedListListener;
 import org.apache.ignite.configuration.notifications.ConfigurationNotificationEvent;
 import org.apache.ignite.configuration.schemas.table.TableConfiguration;
 import org.apache.ignite.configuration.schemas.table.TableView;
+import org.apache.ignite.internal.components.LongJvmPauseDetector;
+import org.apache.ignite.internal.fileio.AsyncFileIoFactory;
+import org.apache.ignite.internal.fileio.FileIoFactory;
+import org.apache.ignite.internal.fileio.RandomAccessFileIoFactory;
 import org.apache.ignite.internal.pagememory.PageMemory;
+import org.apache.ignite.internal.pagememory.PageMemoryDataRegion;
 import org.apache.ignite.internal.pagememory.configuration.schema.PageMemoryDataRegionConfiguration;
 import org.apache.ignite.internal.pagememory.configuration.schema.PageMemoryDataRegionView;
 import org.apache.ignite.internal.pagememory.io.PageIoRegistry;
+import org.apache.ignite.internal.pagememory.persistence.checkpoint.CheckpointManager;
+import org.apache.ignite.internal.pagememory.persistence.store.FilePageStoreManager;
 import org.apache.ignite.internal.storage.StorageException;
 import org.apache.ignite.internal.storage.engine.StorageEngine;
 import org.apache.ignite.internal.storage.pagememory.configuration.schema.PageMemoryDataStorageView;
 import org.apache.ignite.internal.storage.pagememory.configuration.schema.PageMemoryStorageEngineConfiguration;
-import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.lang.IgniteInternalCheckedException;
+import org.apache.ignite.lang.IgniteLogger;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * Storage engine implementation based on {@link PageMemory}.
@@ -43,29 +55,88 @@ public class PageMemoryStorageEngine implements StorageEngine {
     /** Engine name. */
     public static final String ENGINE_NAME = "pagememory";
 
+    private final String igniteInstanceName;
+
     private final PageMemoryStorageEngineConfiguration engineConfig;
 
     private final PageIoRegistry ioRegistry;
 
-    private final Map<String, VolatilePageMemoryDataRegion> regions = new ConcurrentHashMap<>();
+    private final Path storagePath;
+
+    @Nullable
+    private final LongJvmPauseDetector longJvmPauseDetector;
+
+    private final Map<String, AbstractPageMemoryDataRegion> regions = new ConcurrentHashMap<>();
+
+    @Nullable
+    private volatile FilePageStoreManager filePageStoreManager;
+
+    @Nullable
+    private volatile CheckpointManager checkpointManager;
 
     /**
      * Constructor.
      *
+     * @param igniteInstanceName String igniteInstanceName
      * @param engineConfig PageMemory storage engine configuration.
      * @param ioRegistry IO registry.
+     * @param storagePath Storage path.
+     * @param longJvmPauseDetector Long JVM pause detector.
      */
     public PageMemoryStorageEngine(
+            String igniteInstanceName,
             PageMemoryStorageEngineConfiguration engineConfig,
-            PageIoRegistry ioRegistry
+            PageIoRegistry ioRegistry,
+            Path storagePath,
+            @Nullable LongJvmPauseDetector longJvmPauseDetector
     ) {
+        this.igniteInstanceName = igniteInstanceName;
         this.engineConfig = engineConfig;
         this.ioRegistry = ioRegistry;
+        this.storagePath = storagePath;
+        this.longJvmPauseDetector = longJvmPauseDetector;
     }
 
     /** {@inheritDoc} */
     @Override
     public void start() {
+        int pageSize = engineConfig.pageSize().value();
+
+        try {
+            FileIoFactory fileIoFactory = engineConfig.checkpoint().useAsyncFileIoFactory().value()
+                    ? new AsyncFileIoFactory()
+                    : new RandomAccessFileIoFactory();
+
+            filePageStoreManager = new FilePageStoreManager(
+                    IgniteLogger.forClass(FilePageStoreManager.class),
+                    igniteInstanceName,
+                    storagePath,
+                    fileIoFactory,
+                    pageSize
+            );
+
+            filePageStoreManager.start();
+        } catch (IgniteInternalCheckedException e) {
+            throw new StorageException("Error starting file page store manager", e);
+        }
+
+        try {
+            checkpointManager = new CheckpointManager(
+                    igniteInstanceName,
+                    null,
+                    longJvmPauseDetector,
+                    engineConfig.checkpoint(),
+                    filePageStoreManager,
+                    regions.values(),
+                    storagePath,
+                    pageSize
+            );
+
+            checkpointManager.start();
+        } catch (IgniteInternalCheckedException e) {
+            throw new StorageException("Error starting checkpoint manager", e);
+        }
+
         addDataRegion(engineConfig.defaultRegion());
 
         // TODO: IGNITE-17066 Add handling deleting/updating data regions configuration
@@ -84,24 +155,42 @@ public class PageMemoryStorageEngine implements StorageEngine {
     @Override
     public void stop() throws StorageException {
         try {
-            IgniteUtils.closeAll(regions.values().stream().map(region -> region::stop));
+            Stream<AutoCloseable> closeRegions = regions.values().stream().map(region -> region::stop);
+
+            Stream<AutoCloseable> closeManagers = Stream.of(
+                    checkpointManager == null ? null : (AutoCloseable) checkpointManager::stop,
+                    filePageStoreManager == null ? null : (AutoCloseable) filePageStoreManager::stop
+            );
+
+            closeAll(Stream.concat(closeRegions, closeManagers));
         } catch (Exception e) {
-            throw new StorageException("Error when stopping regions", e);
+            throw new StorageException("Error when stopping components", e);
         }
     }
 
     /** {@inheritDoc} */
     @Override
-    public PageMemoryTableStorage createTable(TableConfiguration tableCfg) {
+    public AbstractPageMemoryTableStorage createTable(TableConfiguration tableCfg) {
         TableView tableView = tableCfg.value();
 
         assert tableView.dataStorage().name().equals(ENGINE_NAME) : tableView.dataStorage().name();
 
         PageMemoryDataStorageView dataStorageView = (PageMemoryDataStorageView) tableView.dataStorage();
 
-        VolatilePageMemoryDataRegion dataRegion = regions.get(dataStorageView.dataRegion());
+        PageMemoryDataRegion dataRegion = regions.get(dataStorageView.dataRegion());
+
+        if (dataRegion.persistent()) {
+            return new PersistentPageMemoryTableStorage(tableCfg, (PersistentPageMemoryDataRegion) dataRegion);
+        }
 
-        return new VolatilePageMemoryTableStorage(tableCfg, dataRegion);
+        return new VolatilePageMemoryTableStorage(tableCfg, (VolatilePageMemoryDataRegion) dataRegion);
+    }
+
+    /**
+     * Returns checkpoint manager, {@code null} if engine not started.
+     */
+    public @Nullable CheckpointManager checkpointManager() {
+        return checkpointManager;
     }
 
     /**
@@ -114,7 +203,19 @@ public class PageMemoryStorageEngine implements StorageEngine {
 
         String name = dataRegionConfig.name().value();
 
-        VolatilePageMemoryDataRegion dataRegion = new VolatilePageMemoryDataRegion(dataRegionConfig, ioRegistry, pageSize);
+        AbstractPageMemoryDataRegion dataRegion;
+
+        if (dataRegionConfig.persistent().value()) {
+            dataRegion = new PersistentPageMemoryDataRegion(
+                    dataRegionConfig,
+                    ioRegistry,
+                    filePageStoreManager,
+                    checkpointManager,
+                    pageSize
+            );
+        } else {
+            dataRegion = new VolatilePageMemoryDataRegion(dataRegionConfig, ioRegistry, pageSize);
+        }
 
         dataRegion.start();
 
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryStorageIoModule.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryStorageIoModule.java
index bc6ddd8b4..c1e1268cc 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryStorageIoModule.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryStorageIoModule.java
@@ -21,6 +21,7 @@ import java.util.Collection;
 import java.util.List;
 import org.apache.ignite.internal.pagememory.io.IoVersions;
 import org.apache.ignite.internal.pagememory.io.PageIoModule;
+import org.apache.ignite.internal.storage.pagememory.io.PartitionMetaIo;
 import org.apache.ignite.internal.storage.pagememory.io.TableDataIo;
 import org.apache.ignite.internal.storage.pagememory.io.TableInnerIo;
 import org.apache.ignite.internal.storage.pagememory.io.TableLeafIo;
@@ -37,7 +38,8 @@ public class PageMemoryStorageIoModule implements PageIoModule {
                 TableMetaIo.VERSIONS,
                 TableInnerIo.VERSIONS,
                 TableLeafIo.VERSIONS,
-                TableDataIo.VERSIONS
+                TableDataIo.VERSIONS,
+                PartitionMetaIo.VERSIONS
         );
     }
 }
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryTableStorage.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PartitionMeta.java
similarity index 53%
copy from modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryTableStorage.java
copy to modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PartitionMeta.java
index fab23050a..f53b4554f 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryTableStorage.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PartitionMeta.java
@@ -17,26 +17,35 @@
 
 package org.apache.ignite.internal.storage.pagememory;
 
-import org.apache.ignite.configuration.schemas.table.TableConfiguration;
-import org.apache.ignite.internal.storage.StorageException;
+import org.apache.ignite.internal.pagememory.FullPageId;
 
 /**
- * Implementation of {@link PageMemoryTableStorage} for in-memory case.
+ * Class for storing {@link TableTree} partition metadata.
  */
-class VolatilePageMemoryTableStorage extends PageMemoryTableStorage {
+class PartitionMeta {
+    /** {@link TableTree} root. */
+    final FullPageId treeRoot;
+
+    /** {@link TableFreeList} root. */
+    final FullPageId reuseListRoot;
+
+    /** Have been allocated (created) or read. */
+    final boolean allocated;
+
     /**
      * Constructor.
      *
-     * @param tableCfg – Table configuration.
-     * @param dataRegion – Data region for the table.
+     * @param reuseListRoot {@link TableFreeList} root.
+     * @param treeRoot {@link TableTree} root.
+     * @param allocated Have been allocated (created) or read.
      */
-    public VolatilePageMemoryTableStorage(TableConfiguration tableCfg, VolatilePageMemoryDataRegion dataRegion) {
-        super(tableCfg, dataRegion);
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    protected PageMemoryPartitionStorage createPartitionStorage(int partId) throws StorageException {
-        return new PageMemoryPartitionStorage(partId, tableCfg, dataRegion, ((VolatilePageMemoryDataRegion) dataRegion).tableFreeList());
+    public PartitionMeta(
+            FullPageId treeRoot,
+            FullPageId reuseListRoot,
+            boolean allocated
+    ) {
+        this.treeRoot = treeRoot;
+        this.reuseListRoot = reuseListRoot;
+        this.allocated = allocated;
     }
 }
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryDataRegion.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryDataRegion.java
new file mode 100644
index 000000000..ba76279b1
--- /dev/null
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryDataRegion.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.storage.pagememory;
+
+import static org.apache.ignite.internal.util.Constants.GiB;
+import static org.apache.ignite.internal.util.Constants.MiB;
+
+import java.util.Arrays;
+import org.apache.ignite.internal.pagememory.configuration.schema.PageMemoryDataRegionConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.PageMemoryDataRegionView;
+import org.apache.ignite.internal.pagememory.io.PageIoRegistry;
+import org.apache.ignite.internal.pagememory.persistence.PageMemoryImpl;
+import org.apache.ignite.internal.pagememory.persistence.checkpoint.CheckpointManager;
+import org.apache.ignite.internal.pagememory.persistence.store.FilePageStoreManager;
+
+/**
+ * Implementation of {@link AbstractPageMemoryDataRegion} for persistent case.
+ */
+class PersistentPageMemoryDataRegion extends AbstractPageMemoryDataRegion {
+    private final FilePageStoreManager filePageStoreManager;
+
+    private final CheckpointManager checkpointManager;
+
+    /**
+     * Constructor.
+     *
+     * @param cfg Data region configuration.
+     * @param ioRegistry IO registry.
+     * @param filePageStoreManager File page store manager.
+     * @param checkpointManager Checkpoint manager.
+     * @param pageSize Page size in bytes.
+     */
+    public PersistentPageMemoryDataRegion(
+            PageMemoryDataRegionConfiguration cfg,
+            PageIoRegistry ioRegistry,
+            FilePageStoreManager filePageStoreManager,
+            CheckpointManager checkpointManager,
+            int pageSize
+    ) {
+        super(cfg, ioRegistry, pageSize);
+
+        this.filePageStoreManager = filePageStoreManager;
+        this.checkpointManager = checkpointManager;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void start() {
+        PageMemoryDataRegionView dataRegionConfigView = cfg.value();
+
+        assert persistent() : dataRegionConfigView.name();
+
+        PageMemoryImpl pageMemoryImpl = new PageMemoryImpl(
+                cfg,
+                ioRegistry,
+                calculateSegmentSizes(dataRegionConfigView, Runtime.getRuntime().availableProcessors()),
+                calculateCheckpointBufferSize(dataRegionConfigView),
+                filePageStoreManager,
+                null,
+                (fullPageId, buf, tag) -> {
+                    // Write page to disk.
+                    filePageStoreManager.write(fullPageId.groupId(), fullPageId.pageId(), buf, tag, true);
+                },
+                checkpointManager.checkpointTimeoutLock(),
+                pageSize
+        );
+
+        pageMemoryImpl.start();
+
+        pageMemory = pageMemoryImpl;
+    }
+
+    /**
+     * Returns file page store manager.
+     */
+    public FilePageStoreManager filePageStoreManager() {
+        return filePageStoreManager;
+    }
+
+    /**
+     * Returns checkpoint manager.
+     */
+    public CheckpointManager checkpointManager() {
+        return checkpointManager;
+    }
+
+    /**
+     * Calculates the size of segments in bytes.
+     *
+     * @param dataRegionConfigView Data region configuration.
+     * @param concurrencyLevel Number of concurrent segments in Ignite internal page mapping tables, must be greater than 0.
+     */
+    // TODO: IGNITE-16350 Add more and more detailed description
+    static long[] calculateSegmentSizes(PageMemoryDataRegionView dataRegionConfigView, int concurrencyLevel) {
+        assert concurrencyLevel > 0 : concurrencyLevel;
+
+        long maxSize = dataRegionConfigView.maxSize();
+
+        long fragmentSize = Math.max(maxSize / concurrencyLevel, MiB);
+
+        long[] sizes = new long[concurrencyLevel];
+
+        Arrays.fill(sizes, fragmentSize);
+
+        return sizes;
+    }
+
+    /**
+     * Calculates the size of the checkpoint buffer in bytes.
+     *
+     * @param dataRegionConfigView Data region configuration.
+     */
+    // TODO: IGNITE-16350 Add more and more detailed description
+    static long calculateCheckpointBufferSize(PageMemoryDataRegionView dataRegionConfigView) {
+        long maxSize = dataRegionConfigView.maxSize();
+
+        if (maxSize < GiB) {
+            return Math.min(GiB / 4L, maxSize);
+        }
+
+        if (maxSize < 8L * GiB) {
+            return maxSize / 4L;
+        }
+
+        return 2L * GiB;
+    }
+}
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryPartitionStorage.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryPartitionStorage.java
new file mode 100644
index 000000000..dfbb71a66
--- /dev/null
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryPartitionStorage.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.storage.pagememory;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.ignite.internal.pagememory.persistence.checkpoint.CheckpointTimeoutLock;
+import org.apache.ignite.internal.pagememory.tree.BplusTree;
+import org.apache.ignite.internal.storage.DataRow;
+import org.apache.ignite.internal.storage.InvokeClosure;
+import org.apache.ignite.internal.storage.PartitionStorage;
+import org.apache.ignite.internal.storage.SearchRow;
+import org.apache.ignite.internal.storage.StorageException;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Implementation of {@link PartitionStorage} based on a {@link BplusTree} for persistent case.
+ */
+public class PersistentPageMemoryPartitionStorage extends VolatilePageMemoryPartitionStorage {
+    private final CheckpointTimeoutLock checkpointTimeoutLock;
+
+    /**
+     * Constructor.
+     *
+     * @param partId Partition id.
+     * @param freeList Table free list.
+     * @param tree Table tree.
+     * @param checkpointTimeoutLock Checkpoint timeout lock.
+     * @throws StorageException If there is an error while creating the partition storage.
+     */
+    public PersistentPageMemoryPartitionStorage(
+            int partId,
+            TableFreeList freeList,
+            TableTree tree,
+            CheckpointTimeoutLock checkpointTimeoutLock
+    ) throws StorageException {
+        super(partId, freeList, tree);
+
+        this.checkpointTimeoutLock = checkpointTimeoutLock;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void write(DataRow row) throws StorageException {
+        checkpointTimeoutLock.checkpointReadLock();
+
+        try {
+            super.write(row);
+        } finally {
+            checkpointTimeoutLock.checkpointReadUnlock();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void writeAll(List<? extends DataRow> rows) throws StorageException {
+        checkpointTimeoutLock.checkpointReadLock();
+
+        try {
+            super.writeAll(rows);
+        } finally {
+            checkpointTimeoutLock.checkpointReadUnlock();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Collection<DataRow> insertAll(List<? extends DataRow> rows) throws StorageException {
+        checkpointTimeoutLock.checkpointReadLock();
+
+        try {
+            return super.insertAll(rows);
+        } finally {
+            checkpointTimeoutLock.checkpointReadUnlock();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void remove(SearchRow key) throws StorageException {
+        checkpointTimeoutLock.checkpointReadLock();
+
+        try {
+            super.remove(key);
+        } finally {
+            checkpointTimeoutLock.checkpointReadUnlock();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Collection<SearchRow> removeAll(List<? extends SearchRow> keys) throws StorageException {
+        checkpointTimeoutLock.checkpointReadLock();
+
+        try {
+            return super.removeAll(keys);
+        } finally {
+            checkpointTimeoutLock.checkpointReadUnlock();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Collection<DataRow> removeAllExact(List<? extends DataRow> keyValues) throws StorageException {
+        checkpointTimeoutLock.checkpointReadLock();
+
+        try {
+            return super.removeAllExact(keyValues);
+        } finally {
+            checkpointTimeoutLock.checkpointReadUnlock();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public <T> @Nullable T invoke(SearchRow key, InvokeClosure<T> clo) throws StorageException {
+        checkpointTimeoutLock.checkpointReadLock();
+
+        try {
+            return super.invoke(key, clo);
+        } finally {
+            checkpointTimeoutLock.checkpointReadUnlock();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void destroy() throws StorageException {
+        checkpointTimeoutLock.checkpointReadLock();
+
+        try {
+            super.destroy();
+        } finally {
+            checkpointTimeoutLock.checkpointReadUnlock();
+        }
+    }
+}
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryTableStorage.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryTableStorage.java
new file mode 100644
index 000000000..930ea4717
--- /dev/null
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryTableStorage.java
@@ -0,0 +1,262 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.storage.pagememory;
+
+import static org.apache.ignite.internal.pagememory.PageIdAllocator.FLAG_AUX;
+import static org.apache.ignite.internal.storage.StorageUtils.groupId;
+
+import java.util.concurrent.atomic.AtomicLong;
+import org.apache.ignite.configuration.schemas.table.TableConfiguration;
+import org.apache.ignite.configuration.schemas.table.TableView;
+import org.apache.ignite.internal.pagememory.FullPageId;
+import org.apache.ignite.internal.pagememory.evict.PageEvictionTrackerNoOp;
+import org.apache.ignite.internal.pagememory.metric.IoStatisticsHolderNoOp;
+import org.apache.ignite.internal.pagememory.persistence.PageMemoryImpl;
+import org.apache.ignite.internal.pagememory.persistence.checkpoint.CheckpointTimeoutLock;
+import org.apache.ignite.internal.pagememory.persistence.store.FilePageStore;
+import org.apache.ignite.internal.pagememory.util.PageLockListenerNoOp;
+import org.apache.ignite.internal.storage.StorageException;
+import org.apache.ignite.internal.storage.pagememory.io.PartitionMetaIo;
+import org.apache.ignite.lang.IgniteInternalCheckedException;
+
+/**
+ * Implementation of {@link AbstractPageMemoryTableStorage} for persistent case.
+ */
+class PersistentPageMemoryTableStorage extends AbstractPageMemoryTableStorage {
+    /**
+     * Constructor.
+     *
+     * @param tableCfg Table configuration.
+     * @param dataRegion Data region for the table.
+     */
+    public PersistentPageMemoryTableStorage(
+            TableConfiguration tableCfg,
+            PersistentPageMemoryDataRegion dataRegion
+    ) {
+        super(tableCfg, dataRegion);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void start() throws StorageException {
+        super.start();
+
+        TableView tableView = tableCfg.value();
+
+        try {
+            // TODO: IGNITE-16665 Directory name needs to be corrected to support table renaming
+            ((PersistentPageMemoryDataRegion) dataRegion)
+                    .filePageStoreManager()
+                    .initialize(tableView.name(), groupId(tableView), tableView.partitions());
+        } catch (IgniteInternalCheckedException e) {
+            throw new StorageException("Error initializing file page stores for table: " + tableView.name(), e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected PersistentPageMemoryPartitionStorage createPartitionStorage(int partId) throws StorageException {
+        TableView tableView = tableCfg.value();
+
+        FilePageStore partitionFilePageStore = ensurePartitionFilePageStore(tableView, partId);
+
+        CheckpointTimeoutLock checkpointTimeoutLock = ((PersistentPageMemoryDataRegion) dataRegion)
+                .checkpointManager()
+                .checkpointTimeoutLock();
+
+        checkpointTimeoutLock.checkpointReadLock();
+
+        try {
+            PartitionMeta partitionMeta = getOrCreatePartitionMeta(tableView, partId, partitionFilePageStore);
+
+            TableFreeList tableFreeList = createTableFreeList(tableView, partId, partitionMeta);
+
+            autoCloseables.add(tableFreeList::close);
+
+            TableTree tableTree = createTableTree(tableView, partId, tableFreeList, partitionMeta);
+
+            return new PersistentPageMemoryPartitionStorage(partId, tableFreeList, tableTree, checkpointTimeoutLock);
+        } finally {
+            checkpointTimeoutLock.checkpointReadUnlock();
+        }
+    }
+
+    /**
+     * Initializes the partition file page store if it hasn't already.
+     *
+     * @param tableView Table configuration.
+     * @param partId Partition ID.
+     * @return Partition file page store.
+     * @throws StorageException If failed.
+     */
+    FilePageStore ensurePartitionFilePageStore(TableView tableView, int partId) throws StorageException {
+        try {
+            FilePageStore filePageStore = ((PersistentPageMemoryDataRegion) dataRegion)
+                    .filePageStoreManager()
+                    .getStore(groupId(tableView), partId);
+
+            filePageStore.ensure();
+
+            return filePageStore;
+        } catch (IgniteInternalCheckedException e) {
+            throw new StorageException(
+                    String.format("Error initializing file page store [tableName=%s, partitionId=%s]", tableView.name(), partId),
+                    e
+            );
+        }
+    }
+
+    /**
+     * Creates new or reads existing partition meta.
+     *
+     * @param tableView Table configuration.
+     * @param partId Partition ID.
+     * @param filePageStore Partition file page store.
+     * @return Partition meta.
+     * @throws StorageException If failed.
+     */
+    PartitionMeta getOrCreatePartitionMeta(
+            TableView tableView,
+            int partId,
+            FilePageStore filePageStore
+    ) throws StorageException {
+        PageMemoryImpl pageMemoryImpl = (PageMemoryImpl) dataRegion.pageMemory();
+
+        int grpId = groupId(tableView);
+
+        boolean allocatePartMetaPage = filePageStore.pages() == 0;
+
+        try {
+            long partMetaPageId = allocatePartMetaPage
+                    ? pageMemoryImpl.allocatePage(grpId, partId, FLAG_AUX)
+                    : pageMemoryImpl.partitionMetaPageId(grpId, partId);
+
+            long partMetaPage = pageMemoryImpl.acquirePage(grpId, partMetaPageId);
+
+            try {
+                long partMetaPageAddr = pageMemoryImpl.writeLock(grpId, partMetaPageId, partMetaPage);
+
+                try {
+                    long treeRootPageId;
+                    long reuseListRootPageId;
+
+                    if (allocatePartMetaPage) {
+                        PartitionMetaIo partMetaIo = PartitionMetaIo.VERSIONS.latest();
+
+                        partMetaIo.initNewPage(partMetaPageAddr, partMetaPageId, pageMemoryImpl.realPageSize(grpId));
+
+                        treeRootPageId = pageMemoryImpl.allocatePage(grpId, partId, FLAG_AUX);
+                        reuseListRootPageId = pageMemoryImpl.allocatePage(grpId, partId, FLAG_AUX);
+
+                        partMetaIo.setTreeRootPageId(partMetaPageAddr, treeRootPageId);
+                        partMetaIo.setReuseListRootPageId(partMetaPageAddr, reuseListRootPageId);
+                    } else {
+                        PartitionMetaIo partMetaIo = pageMemoryImpl.ioRegistry().resolve(partMetaPageAddr);
+
+                        treeRootPageId = partMetaIo.getTreeRootPageId(partMetaPageAddr);
+                        reuseListRootPageId = partMetaIo.getReuseListRootPageId(partMetaPageAddr);
+                    }
+
+                    return new PartitionMeta(
+                            new FullPageId(treeRootPageId, grpId),
+                            new FullPageId(reuseListRootPageId, grpId),
+                            allocatePartMetaPage
+                    );
+                } finally {
+                    pageMemoryImpl.writeUnlock(grpId, partMetaPageId, partMetaPage, allocatePartMetaPage);
+                }
+            } finally {
+                pageMemoryImpl.releasePage(grpId, partMetaPageId, partMetaPage);
+            }
+        } catch (IgniteInternalCheckedException e) {
+            throw new StorageException(
+                    String.format("Error getting or creating partition metadata [tableName=%s, partitionId=%s]", tableView.name(), partId),
+                    e
+            );
+        }
+    }
+
+    /**
+     * Returns new {@link TableFreeList} instance for partition.
+     *
+     * @param tableView Table configuration.
+     * @param partId Partition ID.
+     * @param partitionMeta Table partition metadata.
+     * @throws StorageException If failed.
+     */
+    TableFreeList createTableFreeList(
+            TableView tableView,
+            int partId,
+            PartitionMeta partitionMeta
+    ) throws StorageException {
+        try {
+            return new TableFreeList(
+                    groupId(tableView),
+                    dataRegion.pageMemory(),
+                    PageLockListenerNoOp.INSTANCE,
+                    partitionMeta.reuseListRoot.pageId(),
+                    partitionMeta.allocated,
+                    null,
+                    PageEvictionTrackerNoOp.INSTANCE,
+                    IoStatisticsHolderNoOp.INSTANCE
+            );
+        } catch (IgniteInternalCheckedException e) {
+            throw new StorageException(
+                    String.format("Error creating TableFreeList [tableName=%s, partitionId=%s]", tableView.name(), partId),
+                    e
+            );
+        }
+    }
+
+    /**
+     * Returns new {@link TableTree} instance for partition.
+     *
+     * @param tableView Table configuration.
+     * @param partId Partition ID.
+     * @param freeList Table free list.
+     * @param partitionMeta Table partition metadata.
+     * @throws StorageException If failed.
+     */
+    TableTree createTableTree(
+            TableView tableView,
+            int partId,
+            TableFreeList freeList,
+            PartitionMeta partitionMeta
+    ) throws StorageException {
+        int grpId = groupId(tableView);
+
+        try {
+            return new TableTree(
+                    grpId,
+                    tableView.name(),
+                    dataRegion.pageMemory(),
+                    PageLockListenerNoOp.INSTANCE,
+                    new AtomicLong(),
+                    partitionMeta.treeRoot.pageId(),
+                    freeList,
+                    partId,
+                    partitionMeta.allocated
+            );
+        } catch (IgniteInternalCheckedException e) {
+            throw new StorageException(
+                    String.format("Error creating TableTree [tableName=%s, partitionId=%s]", tableView.name(), partId),
+                    e
+            );
+        }
+    }
+}
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryDataRegion.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryDataRegion.java
index cf4ee0823..dc43778cc 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryDataRegion.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryDataRegion.java
@@ -36,7 +36,7 @@ import org.apache.ignite.lang.IgniteInternalCheckedException;
 /**
  * Implementation of {@link AbstractPageMemoryDataRegion} for in-memory case.
  */
-public class VolatilePageMemoryDataRegion extends AbstractPageMemoryDataRegion {
+class VolatilePageMemoryDataRegion extends AbstractPageMemoryDataRegion {
     private static final int FREE_LIST_GROUP_ID = 0;
 
     private TableFreeList tableFreeList;
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryPartitionStorage.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryPartitionStorage.java
similarity index 89%
rename from modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryPartitionStorage.java
rename to modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryPartitionStorage.java
index 3ec2da275..483b1a276 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PageMemoryPartitionStorage.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryPartitionStorage.java
@@ -17,9 +17,7 @@
 
 package org.apache.ignite.internal.storage.pagememory;
 
-import static org.apache.ignite.internal.pagememory.PageIdAllocator.FLAG_AUX;
 import static org.apache.ignite.internal.pagememory.PageIdAllocator.MAX_PARTITION_ID;
-import static org.apache.ignite.internal.storage.StorageUtils.groupId;
 
 import java.nio.ByteBuffer;
 import java.nio.file.Path;
@@ -29,13 +27,9 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.Predicate;
-import org.apache.ignite.configuration.schemas.table.TableConfiguration;
-import org.apache.ignite.configuration.schemas.table.TableView;
 import org.apache.ignite.internal.pagememory.tree.BplusTree;
 import org.apache.ignite.internal.pagememory.tree.IgniteTree;
-import org.apache.ignite.internal.pagememory.util.PageLockListenerNoOp;
 import org.apache.ignite.internal.storage.DataRow;
 import org.apache.ignite.internal.storage.InvokeClosure;
 import org.apache.ignite.internal.storage.OperationType;
@@ -50,10 +44,10 @@ import org.apache.ignite.lang.IgniteInternalException;
 import org.jetbrains.annotations.Nullable;
 
 /**
- * Storage implementation based on a {@link BplusTree}.
+ * Implementation of {@link PartitionStorage} based on a {@link BplusTree} for in-memory case.
  */
 // TODO: IGNITE-16644 Support snapshots.
-class PageMemoryPartitionStorage implements PartitionStorage {
+class VolatilePageMemoryPartitionStorage implements PartitionStorage {
     private final int partId;
 
     private final TableTree tree;
@@ -64,48 +58,20 @@ class PageMemoryPartitionStorage implements PartitionStorage {
      * Constructor.
      *
      * @param partId Partition id.
-     * @param tableCfg – Table configuration.
-     * @param dataRegion – Data region for the table.
      * @param freeList Table free list.
+     * @param tree Table tree.
      * @throws StorageException If there is an error while creating the partition storage.
      */
-    public PageMemoryPartitionStorage(
+    public VolatilePageMemoryPartitionStorage(
             int partId,
-            TableConfiguration tableCfg,
-            AbstractPageMemoryDataRegion dataRegion,
-            TableFreeList freeList
+            TableFreeList freeList,
+            TableTree tree
     ) throws StorageException {
         assert partId >= 0 && partId < MAX_PARTITION_ID : partId;
 
         this.partId = partId;
-
         this.freeList = freeList;
-
-        TableView tableView = tableCfg.value();
-
-        int grpId = groupId(tableView);
-
-        try {
-            // TODO: IGNITE-16641 It is necessary to do getting the tree root for the persistent case.
-            long metaPageId = dataRegion.pageMemory().allocatePage(grpId, partId, FLAG_AUX);
-
-            // TODO: IGNITE-16641 It is necessary to take into account the persistent case.
-            boolean initNew = true;
-
-            tree = new TableTree(
-                    grpId,
-                    tableView.name(),
-                    dataRegion.pageMemory(),
-                    PageLockListenerNoOp.INSTANCE,
-                    new AtomicLong(),
-                    metaPageId,
-                    freeList,
-                    partId,
-                    initNew
-            );
-        } catch (IgniteInternalCheckedException e) {
-            throw new StorageException("Error occurred while creating the partition storage", e);
-        }
+        this.tree = tree;
     }
 
     /** {@inheritDoc} */
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryTableStorage.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryTableStorage.java
index fab23050a..b6c9acda3 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryTableStorage.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryTableStorage.java
@@ -17,13 +17,20 @@
 
 package org.apache.ignite.internal.storage.pagememory;
 
+import static org.apache.ignite.internal.pagememory.PageIdAllocator.FLAG_AUX;
+import static org.apache.ignite.internal.storage.StorageUtils.groupId;
+
+import java.util.concurrent.atomic.AtomicLong;
 import org.apache.ignite.configuration.schemas.table.TableConfiguration;
+import org.apache.ignite.configuration.schemas.table.TableView;
+import org.apache.ignite.internal.pagememory.util.PageLockListenerNoOp;
 import org.apache.ignite.internal.storage.StorageException;
+import org.apache.ignite.lang.IgniteInternalCheckedException;
 
 /**
- * Implementation of {@link PageMemoryTableStorage} for in-memory case.
+ * Implementation of {@link AbstractPageMemoryTableStorage} for in-memory case.
  */
-class VolatilePageMemoryTableStorage extends PageMemoryTableStorage {
+class VolatilePageMemoryTableStorage extends AbstractPageMemoryTableStorage {
     /**
      * Constructor.
      *
@@ -36,7 +43,50 @@ class VolatilePageMemoryTableStorage extends PageMemoryTableStorage {
 
     /** {@inheritDoc} */
     @Override
-    protected PageMemoryPartitionStorage createPartitionStorage(int partId) throws StorageException {
-        return new PageMemoryPartitionStorage(partId, tableCfg, dataRegion, ((VolatilePageMemoryDataRegion) dataRegion).tableFreeList());
+    protected VolatilePageMemoryPartitionStorage createPartitionStorage(int partId) throws StorageException {
+        TableFreeList tableFreeList = ((VolatilePageMemoryDataRegion) dataRegion).tableFreeList();
+
+        TableTree tableTree = createTableTree(tableCfg.value(), partId, tableFreeList);
+
+        return new VolatilePageMemoryPartitionStorage(
+                partId,
+                tableFreeList,
+                tableTree
+        );
+    }
+
+    /**
+     * Returns new {@link TableTree} instance for partition.
+     *
+     * @param tableView Table configuration.
+     * @param partId Partition ID.
+     * @param freeList Table free list.
+     * @throws StorageException If failed.
+     */
+    TableTree createTableTree(
+            TableView tableView,
+            int partId,
+            TableFreeList freeList
+    ) throws StorageException {
+        int grpId = groupId(tableView);
+
+        try {
+            return new TableTree(
+                    grpId,
+                    tableView.name(),
+                    dataRegion.pageMemory(),
+                    PageLockListenerNoOp.INSTANCE,
+                    new AtomicLong(),
+                    dataRegion.pageMemory().allocatePage(grpId, partId, FLAG_AUX),
+                    freeList,
+                    partId,
+                    true
+            );
+        } catch (IgniteInternalCheckedException e) {
+            throw new StorageException(
+                    String.format("Error creating TableTree [tableName=%s, partitionId=%s]", tableView.name(), partId),
+                    e
+            );
+        }
     }
 }
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/configuration/schema/PageMemoryStorageEngineConfigurationSchema.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/configuration/schema/PageMemoryStorageEngineConfigurationSchema.java
index aad7896d5..1836b8d4e 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/configuration/schema/PageMemoryStorageEngineConfigurationSchema.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/configuration/schema/PageMemoryStorageEngineConfigurationSchema.java
@@ -28,6 +28,7 @@ import org.apache.ignite.configuration.validation.ExceptKeys;
 import org.apache.ignite.configuration.validation.Immutable;
 import org.apache.ignite.configuration.validation.PowerOfTwo;
 import org.apache.ignite.configuration.validation.Range;
+import org.apache.ignite.internal.pagememory.configuration.schema.PageMemoryCheckpointConfigurationSchema;
 import org.apache.ignite.internal.pagememory.configuration.schema.PageMemoryDataRegionConfigurationSchema;
 import org.apache.ignite.internal.storage.pagememory.PageMemoryStorageEngine;
 
@@ -55,4 +56,8 @@ public class PageMemoryStorageEngineConfigurationSchema {
     @ExceptKeys(DEFAULT_DATA_REGION_NAME)
     @NamedConfigValue
     public PageMemoryDataRegionConfigurationSchema regions;
+
+    /* Checkpoint configuration for persistent data regions. */
+    @ConfigValue
+    public PageMemoryCheckpointConfigurationSchema checkpoint;
 }
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/io/PartitionMetaIo.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/io/PartitionMetaIo.java
new file mode 100644
index 000000000..610995e70
--- /dev/null
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/io/PartitionMetaIo.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.storage.pagememory.io;
+
+import static org.apache.ignite.internal.pagememory.PageIdAllocator.FLAG_AUX;
+import static org.apache.ignite.internal.pagememory.util.PageUtils.getLong;
+import static org.apache.ignite.internal.pagememory.util.PageUtils.putLong;
+
+import org.apache.ignite.internal.pagememory.io.IoVersions;
+import org.apache.ignite.internal.pagememory.io.PageIo;
+import org.apache.ignite.lang.IgniteStringBuilder;
+
+/**
+ * Io for partition metadata pages.
+ */
+public class PartitionMetaIo extends PageIo {
+    private static final int TREE_ROOT_PAGE_ID_OFF = COMMON_HEADER_END;
+
+    private static final int REUSE_LIST_ROOT_PAGE_ID_OFF = TREE_ROOT_PAGE_ID_OFF + Long.BYTES;
+
+    /** Page IO type. */
+    public static final short T_TABLE_PARTITION_META_IO = 7;
+
+    /** I/O versions. */
+    public static final IoVersions<PartitionMetaIo> VERSIONS = new IoVersions<>(new PartitionMetaIo(1));
+
+    /**
+     * Constructor.
+     *
+     * @param ver Page format version.
+     */
+    protected PartitionMetaIo(int ver) {
+        super(T_TABLE_PARTITION_META_IO, ver, FLAG_AUX);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void initNewPage(long pageAddr, long pageId, int pageSize) {
+        super.initNewPage(pageAddr, pageId, pageSize);
+
+        setTreeRootPageId(pageAddr, 0);
+        setReuseListRootPageId(pageAddr, 0);
+    }
+
+    /**
+     * Sets tree root page ID.
+     *
+     * @param pageAddr Page address.
+     * @param pageId Tree root page ID.
+     */
+    public void setTreeRootPageId(long pageAddr, long pageId) {
+        assertPageType(pageAddr);
+
+        putLong(pageAddr, TREE_ROOT_PAGE_ID_OFF, pageId);
+    }
+
+    /**
+     * Returns tree root page ID.
+     *
+     * @param pageAddr Page address.
+     */
+    public long getTreeRootPageId(long pageAddr) {
+        return getLong(pageAddr, TREE_ROOT_PAGE_ID_OFF);
+    }
+
+    /**
+     * Sets reuse list root page ID.
+     *
+     * @param pageAddr Page address.
+     * @param pageId Reuse list root page ID.
+     */
+    public void setReuseListRootPageId(long pageAddr, long pageId) {
+        assertPageType(pageAddr);
+
+        putLong(pageAddr, REUSE_LIST_ROOT_PAGE_ID_OFF, pageId);
+    }
+
+    /**
+     * Returns reuse list root page ID.
+     *
+     * @param pageAddr Page address.
+     */
+    public long getReuseListRootPageId(long pageAddr) {
+        return getLong(pageAddr, REUSE_LIST_ROOT_PAGE_ID_OFF);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void printPage(long addr, int pageSize, IgniteStringBuilder sb) {
+        sb.app("TablePartitionMeta [").nl()
+                .app("treeRootPageId=").appendHex(getTreeRootPageId(addr)).nl()
+                .app(", reuseListRootPageId=").appendHex(getReuseListRootPageId(addr)).nl()
+                .app(']');
+    }
+}
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/RowVersionDataIo.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/RowVersionDataIo.java
index c7e9bdccc..11214b612 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/RowVersionDataIo.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/RowVersionDataIo.java
@@ -36,7 +36,7 @@ import org.jetbrains.annotations.Nullable;
  */
 public class RowVersionDataIo extends AbstractDataPageIo<RowVersion> {
     /** Page IO type. */
-    public static final short T_VALUE_VERSION_DATA_IO = 11;
+    public static final short T_VALUE_VERSION_DATA_IO = 12;
 
     /** I/O versions. */
     public static final IoVersions<RowVersionDataIo> VERSIONS = new IoVersions<>(new RowVersionDataIo(1));
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/VersionChainDataIo.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/VersionChainDataIo.java
index eb18573a5..7d7618792 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/VersionChainDataIo.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/VersionChainDataIo.java
@@ -34,7 +34,7 @@ import org.jetbrains.annotations.Nullable;
  */
 public class VersionChainDataIo extends AbstractDataPageIo<VersionChain> {
     /** Page IO type. */
-    public static final short T_VERSION_CHAIN_IO = 7;
+    public static final short T_VERSION_CHAIN_IO = 8;
 
     /** I/O versions. */
     public static final IoVersions<VersionChainDataIo> VERSIONS = new IoVersions<>(new VersionChainDataIo(1));
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/VersionChainInnerIo.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/VersionChainInnerIo.java
index d24e83ea4..89b036623 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/VersionChainInnerIo.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/VersionChainInnerIo.java
@@ -34,7 +34,7 @@ import org.apache.ignite.internal.storage.pagememory.mv.VersionChainTree;
  */
 public class VersionChainInnerIo extends BplusInnerIo<VersionChainLink> implements VersionChainIo {
     /** Page IO type. */
-    public static final short T_VERSION_CHAIN_INNER_IO = 9;
+    public static final short T_VERSION_CHAIN_INNER_IO = 10;
 
     /** I/O versions. */
     public static final IoVersions<VersionChainInnerIo> VERSIONS = new IoVersions<>(new VersionChainInnerIo(1));
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/VersionChainLeafIo.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/VersionChainLeafIo.java
index 15bbce063..a375a7004 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/VersionChainLeafIo.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/VersionChainLeafIo.java
@@ -34,7 +34,7 @@ import org.apache.ignite.internal.storage.pagememory.mv.VersionChainTree;
  */
 public class VersionChainLeafIo extends BplusLeafIo<VersionChainLink> implements VersionChainIo {
     /** Page IO type. */
-    public static final short T_VERSION_CHAIN_LEAF_IO = 10;
+    public static final short T_VERSION_CHAIN_LEAF_IO = 11;
 
     /** I/O versions. */
     public static final IoVersions<VersionChainLeafIo> VERSIONS = new IoVersions<>(new VersionChainLeafIo(1));
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/VersionChainMetaIo.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/VersionChainMetaIo.java
index ae66188a4..ca63625bd 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/VersionChainMetaIo.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/VersionChainMetaIo.java
@@ -26,7 +26,7 @@ import org.apache.ignite.internal.storage.pagememory.mv.VersionChainTree;
  */
 public class VersionChainMetaIo extends BplusMetaIo {
     /** Page IO type. */
-    public static final short T_VERSION_CHAIN_META_IO = 8;
+    public static final short T_VERSION_CHAIN_META_IO = 9;
 
     /** I/O versions. */
     public static final IoVersions<VersionChainMetaIo> VERSIONS = new IoVersions<>(new VersionChainMetaIo(1));
diff --git a/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryDataRegionTest.java b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryDataRegionTest.java
new file mode 100644
index 000000000..a3f1b2839
--- /dev/null
+++ b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryDataRegionTest.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.storage.pagememory;
+
+import static org.apache.ignite.internal.storage.pagememory.PersistentPageMemoryDataRegion.calculateCheckpointBufferSize;
+import static org.apache.ignite.internal.storage.pagememory.PersistentPageMemoryDataRegion.calculateSegmentSizes;
+import static org.apache.ignite.internal.util.Constants.GiB;
+import static org.apache.ignite.internal.util.Constants.MiB;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
+import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.PageMemoryDataRegionConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.PageMemoryDataRegionView;
+import org.apache.ignite.internal.pagememory.configuration.schema.UnsafeMemoryAllocatorConfigurationSchema;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+/**
+ * For {@link PersistentPageMemoryDataRegion} testing.
+ */
+@ExtendWith(ConfigurationExtension.class)
+public class PersistentPageMemoryDataRegionTest {
+    @InjectConfiguration(polymorphicExtensions = UnsafeMemoryAllocatorConfigurationSchema.class)
+    private PageMemoryDataRegionConfiguration dataRegionConfig;
+
+    @Test
+    void testCalculateSegmentSizes() throws Exception {
+        int concurrencyLevel = 2;
+
+        PageMemoryDataRegionView dataRegionConfigView = dataRegionConfig.value();
+
+        assertArrayEquals(
+                fill(new long[concurrencyLevel], dataRegionConfigView.maxSize() / concurrencyLevel),
+                calculateSegmentSizes(dataRegionConfigView, concurrencyLevel)
+        );
+
+        dataRegionConfig.maxSize().update(1024L).get(1, TimeUnit.SECONDS);
+
+        assertArrayEquals(
+                fill(new long[concurrencyLevel], MiB),
+                calculateSegmentSizes(dataRegionConfig.value(), concurrencyLevel)
+        );
+    }
+
+    @Test
+    void testCalculateCheckpointBufferSize() throws Exception {
+        PageMemoryDataRegionView dataRegionConfigView = dataRegionConfig.value();
+
+        assertEquals(dataRegionConfigView.maxSize(), calculateCheckpointBufferSize(dataRegionConfigView));
+
+        dataRegionConfig.maxSize().update(GiB / 2L).get(1, TimeUnit.SECONDS);
+
+        assertEquals(GiB / 4L, calculateCheckpointBufferSize(dataRegionConfig.value()));
+
+        dataRegionConfig.maxSize().update(6L * GiB).get(1, TimeUnit.SECONDS);
+
+        assertEquals((6L * GiB) / 4L, calculateCheckpointBufferSize(dataRegionConfig.value()));
+
+        dataRegionConfig.maxSize().update(8L * GiB).get(1, TimeUnit.SECONDS);
+
+        assertEquals(2L * GiB, calculateCheckpointBufferSize(dataRegionConfig.value()));
+    }
+
+    private long[] fill(long[] arr, long v) {
+        Arrays.fill(arr, v);
+
+        return arr;
+    }
+}
diff --git a/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PageMemoryPartitionStorageTest.java b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryPartitionStorageTest.java
similarity index 72%
copy from modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PageMemoryPartitionStorageTest.java
copy to modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryPartitionStorageTest.java
index 227357120..a081ab131 100644
--- a/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PageMemoryPartitionStorageTest.java
+++ b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryPartitionStorageTest.java
@@ -17,26 +17,27 @@
 
 package org.apache.ignite.internal.storage.pagememory;
 
-import static java.util.stream.Collectors.joining;
+import static org.apache.ignite.internal.pagememory.persistence.checkpoint.CheckpointState.FINISHED;
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.nio.file.Path;
-import java.util.concurrent.ThreadLocalRandom;
+import java.util.List;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 import org.apache.ignite.configuration.schemas.store.UnknownDataStorageConfigurationSchema;
 import org.apache.ignite.configuration.schemas.table.HashIndexConfigurationSchema;
 import org.apache.ignite.configuration.schemas.table.TableConfiguration;
+import org.apache.ignite.internal.components.LongJvmPauseDetector;
 import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
 import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
 import org.apache.ignite.internal.pagememory.configuration.schema.UnsafeMemoryAllocatorConfigurationSchema;
 import org.apache.ignite.internal.pagememory.io.PageIoRegistry;
 import org.apache.ignite.internal.storage.AbstractPartitionStorageTest;
 import org.apache.ignite.internal.storage.DataRow;
-import org.apache.ignite.internal.storage.engine.StorageEngine;
 import org.apache.ignite.internal.storage.engine.TableStorage;
 import org.apache.ignite.internal.storage.pagememory.configuration.schema.PageMemoryDataStorageChange;
 import org.apache.ignite.internal.storage.pagememory.configuration.schema.PageMemoryDataStorageConfigurationSchema;
@@ -55,12 +56,11 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 
 /**
- * Storage test implementation for {@link PageMemoryPartitionStorage}.
+ * Storage test implementation for {@link PersistentPageMemoryPartitionStorage}.
  */
-// TODO: IGNITE-16641 Add test for persistent case.
 @ExtendWith(ConfigurationExtension.class)
 @ExtendWith(WorkDirectoryExtension.class)
-public class PageMemoryPartitionStorageTest extends AbstractPartitionStorageTest {
+public class PersistentPageMemoryPartitionStorageTest extends AbstractPartitionStorageTest {
     private static PageIoRegistry ioRegistry;
 
     @InjectConfiguration(polymorphicExtensions = UnsafeMemoryAllocatorConfigurationSchema.class)
@@ -76,10 +76,15 @@ public class PageMemoryPartitionStorageTest extends AbstractPartitionStorageTest
     )
     private TableConfiguration tableCfg;
 
-    private StorageEngine engine;
+    private LongJvmPauseDetector longJvmPauseDetector;
+
+    private PageMemoryStorageEngine engine;
 
     private TableStorage table;
 
+    @WorkDirectory
+    private Path workDir;
+
     @BeforeAll
     static void beforeAll() {
         ioRegistry = new PageIoRegistry();
@@ -89,12 +94,19 @@ public class PageMemoryPartitionStorageTest extends AbstractPartitionStorageTest
 
     @BeforeEach
     void setUp() throws Exception {
-        engine = new PageMemoryStorageEngine(engineConfig, ioRegistry);
+        String nodeName = "test-node";
+
+        longJvmPauseDetector = new LongJvmPauseDetector(nodeName);
+
+        longJvmPauseDetector.start();
+
+        engineConfig.defaultRegion().persistent().update(true).get(1, TimeUnit.SECONDS);
+
+        engine = new PageMemoryStorageEngine(nodeName, engineConfig, ioRegistry, workDir, longJvmPauseDetector);
 
         engine.start();
 
-        tableCfg.change(c -> c.changeDataStorage(dsc -> dsc.convert(PageMemoryDataStorageChange.class)))
-                .get(1, TimeUnit.SECONDS);
+        tableCfg.change(c -> c.changeDataStorage(dsc -> dsc.convert(PageMemoryDataStorageChange.class))).get(1, TimeUnit.SECONDS);
 
         assertEquals(
                 PageMemoryStorageEngineConfigurationSchema.DEFAULT_DATA_REGION_NAME,
@@ -103,13 +115,13 @@ public class PageMemoryPartitionStorageTest extends AbstractPartitionStorageTest
 
         table = engine.createTable(tableCfg);
 
-        assertThat(table, is(instanceOf(PageMemoryTableStorage.class)));
+        assertThat(table, is(instanceOf(PersistentPageMemoryTableStorage.class)));
 
         table.start();
 
         storage = table.getOrCreatePartition(0);
 
-        assertThat(storage, is(instanceOf(PageMemoryPartitionStorage.class)));
+        assertThat(storage, is(instanceOf(PersistentPageMemoryPartitionStorage.class)));
     }
 
     @AfterEach
@@ -117,7 +129,8 @@ public class PageMemoryPartitionStorageTest extends AbstractPartitionStorageTest
         IgniteUtils.closeAll(
                 storage,
                 table == null ? null : table::stop,
-                engine == null ? null : engine::stop
+                engine == null ? null : engine::stop,
+                longJvmPauseDetector == null ? null : longJvmPauseDetector::stop
         );
     }
 
@@ -134,25 +147,24 @@ public class PageMemoryPartitionStorageTest extends AbstractPartitionStorageTest
         super.testSnapshot(workDir);
     }
 
-    /**
-     * Checks that fragments are written and read correctly.
-     *
-     * @throws Exception If failed.
-     */
     @Test
-    void testFragments() {
-        int pageSize = engineConfig.pageSize().value();
+    void testReadAfterRestart() throws Exception {
+        List<DataRow> rows = IntStream.range(0, 100)
+                .mapToObj(i -> dataRow(KEY + i, VALUE + i))
+                .collect(Collectors.toList());
 
-        DataRow dataRow = dataRow(createRandomString(pageSize), createRandomString(pageSize));
+        storage.writeAll(rows);
 
-        storage.write(dataRow);
+        engine
+                .checkpointManager()
+                .forceCheckpoint("before_stop_engine")
+                .futureFor(FINISHED)
+                .get(1, TimeUnit.SECONDS);
 
-        DataRow read = storage.read(dataRow);
+        tearDown();
 
-        assertArrayEquals(dataRow.valueBytes(), read.valueBytes());
-    }
+        setUp();
 
-    private String createRandomString(int len) {
-        return ThreadLocalRandom.current().ints(len).mapToObj(i -> String.valueOf(Math.abs(i % 10))).collect(joining(""));
+        rows.forEach(this::checkHasSameEntry);
     }
 }
diff --git a/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PageMemoryPartitionStorageTest.java b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryPartitionStorageTest.java
similarity index 89%
rename from modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PageMemoryPartitionStorageTest.java
rename to modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryPartitionStorageTest.java
index 227357120..7aa58c9a3 100644
--- a/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PageMemoryPartitionStorageTest.java
+++ b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryPartitionStorageTest.java
@@ -55,12 +55,11 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 
 /**
- * Storage test implementation for {@link PageMemoryPartitionStorage}.
+ * Storage test implementation for {@link VolatilePageMemoryPartitionStorage}.
  */
-// TODO: IGNITE-16641 Add test for persistent case.
 @ExtendWith(ConfigurationExtension.class)
 @ExtendWith(WorkDirectoryExtension.class)
-public class PageMemoryPartitionStorageTest extends AbstractPartitionStorageTest {
+public class VolatilePageMemoryPartitionStorageTest extends AbstractPartitionStorageTest {
     private static PageIoRegistry ioRegistry;
 
     @InjectConfiguration(polymorphicExtensions = UnsafeMemoryAllocatorConfigurationSchema.class)
@@ -80,6 +79,9 @@ public class PageMemoryPartitionStorageTest extends AbstractPartitionStorageTest
 
     private TableStorage table;
 
+    @WorkDirectory
+    private Path workDir;
+
     @BeforeAll
     static void beforeAll() {
         ioRegistry = new PageIoRegistry();
@@ -89,12 +91,13 @@ public class PageMemoryPartitionStorageTest extends AbstractPartitionStorageTest
 
     @BeforeEach
     void setUp() throws Exception {
-        engine = new PageMemoryStorageEngine(engineConfig, ioRegistry);
+        engineConfig.defaultRegion().persistent().update(false).get(1, TimeUnit.SECONDS);
+
+        engine = new PageMemoryStorageEngine("test", engineConfig, ioRegistry, workDir, null);
 
         engine.start();
 
-        tableCfg.change(c -> c.changeDataStorage(dsc -> dsc.convert(PageMemoryDataStorageChange.class)))
-                .get(1, TimeUnit.SECONDS);
+        tableCfg.change(c -> c.changeDataStorage(dsc -> dsc.convert(PageMemoryDataStorageChange.class))).get(1, TimeUnit.SECONDS);
 
         assertEquals(
                 PageMemoryStorageEngineConfigurationSchema.DEFAULT_DATA_REGION_NAME,
@@ -103,13 +106,13 @@ public class PageMemoryPartitionStorageTest extends AbstractPartitionStorageTest
 
         table = engine.createTable(tableCfg);
 
-        assertThat(table, is(instanceOf(PageMemoryTableStorage.class)));
+        assertThat(table, is(instanceOf(VolatilePageMemoryTableStorage.class)));
 
         table.start();
 
         storage = table.getOrCreatePartition(0);
 
-        assertThat(storage, is(instanceOf(PageMemoryPartitionStorage.class)));
+        assertThat(storage, is(instanceOf(VolatilePageMemoryPartitionStorage.class)));
     }
 
     @AfterEach
diff --git a/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/PageMemoryMvPartitionStorageTest.java b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/PageMemoryMvPartitionStorageTest.java
index f013eade0..1d5ae5e1c 100644
--- a/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/PageMemoryMvPartitionStorageTest.java
+++ b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/PageMemoryMvPartitionStorageTest.java
@@ -21,6 +21,7 @@ import static java.util.stream.Collectors.joining;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
+import java.nio.file.Path;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.IntStream;
 import org.apache.ignite.configuration.schemas.store.UnknownDataStorageConfigurationSchema;
@@ -33,13 +34,14 @@ import org.apache.ignite.internal.pagememory.io.PageIoRegistry;
 import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.storage.AbstractMvPartitionStorageTest;
 import org.apache.ignite.internal.storage.RowId;
+import org.apache.ignite.internal.storage.pagememory.AbstractPageMemoryTableStorage;
 import org.apache.ignite.internal.storage.pagememory.PageMemoryStorageEngine;
-import org.apache.ignite.internal.storage.pagememory.PageMemoryTableStorage;
 import org.apache.ignite.internal.storage.pagememory.configuration.schema.PageMemoryDataStorageChange;
 import org.apache.ignite.internal.storage.pagememory.configuration.schema.PageMemoryDataStorageConfigurationSchema;
 import org.apache.ignite.internal.storage.pagememory.configuration.schema.PageMemoryDataStorageView;
 import org.apache.ignite.internal.storage.pagememory.configuration.schema.PageMemoryStorageEngineConfiguration;
 import org.apache.ignite.internal.storage.pagememory.configuration.schema.PageMemoryStorageEngineConfigurationSchema;
+import org.apache.ignite.internal.testframework.WorkDirectory;
 import org.apache.ignite.internal.testframework.WorkDirectoryExtension;
 import org.apache.ignite.internal.tx.Timestamp;
 import org.apache.ignite.internal.util.Cursor;
@@ -73,13 +75,16 @@ class PageMemoryMvPartitionStorageTest extends AbstractMvPartitionStorageTest<Pa
 
     private PageMemoryStorageEngine engine;
 
-    private PageMemoryTableStorage table;
+    private AbstractPageMemoryTableStorage table;
 
     private int nextPageIndex = 100;
 
+    @WorkDirectory
+    private Path workDir;
+
     @BeforeEach
     void setUp() throws Exception {
-        engine = new PageMemoryStorageEngine(engineConfig, ioRegistry);
+        engine = new PageMemoryStorageEngine("test", engineConfig, ioRegistry, workDir, null);
 
         engine.start();
 
diff --git a/modules/storage-rocksdb/src/main/java/org/apache/ignite/internal/storage/rocksdb/RocksDbDataStorageModule.java b/modules/storage-rocksdb/src/main/java/org/apache/ignite/internal/storage/rocksdb/RocksDbDataStorageModule.java
index b6ab0ddfc..598881e73 100644
--- a/modules/storage-rocksdb/src/main/java/org/apache/ignite/internal/storage/rocksdb/RocksDbDataStorageModule.java
+++ b/modules/storage-rocksdb/src/main/java/org/apache/ignite/internal/storage/rocksdb/RocksDbDataStorageModule.java
@@ -20,11 +20,13 @@ package org.apache.ignite.internal.storage.rocksdb;
 import static org.apache.ignite.internal.storage.rocksdb.RocksDbStorageEngine.ENGINE_NAME;
 
 import java.nio.file.Path;
+import org.apache.ignite.internal.components.LongJvmPauseDetector;
 import org.apache.ignite.internal.configuration.ConfigurationRegistry;
 import org.apache.ignite.internal.storage.DataStorageModule;
 import org.apache.ignite.internal.storage.StorageException;
 import org.apache.ignite.internal.storage.engine.StorageEngine;
 import org.apache.ignite.internal.storage.rocksdb.configuration.schema.RocksDbStorageEngineConfiguration;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * Implementation for creating {@link RocksDbStorageEngine}s.
@@ -38,7 +40,12 @@ public class RocksDbDataStorageModule implements DataStorageModule {
 
     /** {@inheritDoc} */
     @Override
-    public StorageEngine createEngine(ConfigurationRegistry configRegistry, Path storagePath) throws StorageException {
+    public StorageEngine createEngine(
+            String igniteInstanceName,
+            ConfigurationRegistry configRegistry,
+            Path storagePath,
+            @Nullable LongJvmPauseDetector longJvmPauseDetector
+    ) throws StorageException {
         RocksDbStorageEngineConfiguration engineConfig = configRegistry.getConfiguration(RocksDbStorageEngineConfiguration.KEY);
 
         assert engineConfig != null;
diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/TableManagerTest.java b/modules/table/src/test/java/org/apache/ignite/internal/table/TableManagerTest.java
index 2d24d0511..60cc92552 100644
--- a/modules/table/src/test/java/org/apache/ignite/internal/table/TableManagerTest.java
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/TableManagerTest.java
@@ -656,7 +656,7 @@ public class TableManagerTest extends IgniteAbstractTest {
 
         DataStorageManager manager = new DataStorageManager(
                 tblsCfg,
-                dataStorageModules.createStorageEngines(mockedRegistry, storagePath)
+                dataStorageModules.createStorageEngines(NODE_NAME, mockedRegistry, storagePath, null)
         );
 
         manager.start();