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

agoncharuk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 965be31  IGNITE-12489 Fix persistence corruption caused by invalid tag 
check (flags were not rotated for some pages) - Fixes #8358.
965be31 is described below

commit 965be312a340fb6fb9f958bc4fcabda0a5e4bc16
Author: Nikita Tolstunov <ntolstu...@gmail.com>
AuthorDate: Tue Nov 17 13:30:41 2020 +0300

    IGNITE-12489 Fix persistence corruption caused by invalid tag check (flags 
were not rotated for some pages) - Fixes #8358.
    
    Signed-off-by: Alexey Goncharuk <alexey.goncha...@gmail.com>
---
 .../benchmarks/jmh/tree/BPlusTreeBenchmark.java    |   6 +
 .../ignite/internal/pagemem/PageIdAllocator.java   |  18 ++-
 .../ignite/internal/pagemem/PageIdUtils.java       |   2 +-
 .../pagemem/store/IgnitePageStoreManager.java      |   2 +-
 .../ignite/internal/pagemem/store/PageStore.java   |   6 +
 .../cache/IgniteCacheOffheapManagerImpl.java       |   6 +-
 .../processors/cache/mvcc/txlog/TxLog.java         |   3 +-
 .../processors/cache/mvcc/txlog/TxLogTree.java     |   2 +
 .../cache/persistence/DataStructure.java           |  32 ++++-
 .../cache/persistence/GridCacheOffheapManager.java |  63 ++++----
 .../IgniteCacheDatabaseSharedManager.java          |   4 +-
 .../cache/persistence/IndexStorageImpl.java        |   2 +
 .../persistence/file/FilePageStoreFactory.java     |   5 +-
 .../persistence/file/FilePageStoreManager.java     |   5 +-
 .../persistence/freelist/AbstractFreeList.java     |  34 +++--
 .../cache/persistence/freelist/CacheFreeList.java  |   7 +-
 .../cache/persistence/freelist/PagesList.java      | 124 +++++++++++++---
 .../cache/persistence/metastorage/MetaStorage.java |  21 +--
 .../persistence/metastorage/MetastorageTree.java   |   5 +-
 .../UpgradePendingTreeToPerPartitionTask.java      |   4 +-
 .../cache/persistence/pagemem/PageMemoryImpl.java  |  13 +-
 .../persistence/partstate/GroupPartitionId.java    |  12 +-
 .../partstorage/PartitionMetaStorageImpl.java      |   6 +-
 .../snapshot/IgniteSnapshotManager.java            |   4 +-
 .../cache/persistence/tree/BPlusTree.java          |   9 +-
 .../cache/persistence/tree/io/TrackingPageIO.java  |   7 +-
 .../cache/persistence/tree/reuse/ReuseList.java    |  18 +++
 .../persistence/tree/reuse/ReuseListImpl.java      |  13 +-
 .../processors/cache/tree/CacheDataTree.java       |   5 +-
 .../processors/cache/tree/PendingEntriesTree.java  |   5 +-
 .../processors/cache/verify/IdleVerifyUtility.java |  14 +-
 ...IoStatisticsMetricsLocalMXBeanImplSelfTest.java |   2 +-
 .../internal/pagemem/impl/PageIdUtilsSelfTest.java |  41 ++++--
 .../persistence/PendingTreeCorruptionTest.java     | 159 +++++++++++++++++++++
 .../db/CheckpointBufferDeadlockTest.java           |  12 ++
 .../database/BPlusTreeFakeReuseSelfTest.java       |   6 +
 .../database/BPlusTreeReuseSelfTest.java           |   3 +-
 .../processors/database/BPlusTreeSelfTest.java     |   1 +
 .../processors/database/CacheFreeListSelfTest.java |   3 +-
 .../ignite/testsuites/IgnitePdsTestSuite4.java     |   3 +
 .../processors/query/h2/IgniteH2Indexing.java      |   2 +
 .../processors/query/h2/database/H2Tree.java       |   2 +
 42 files changed, 559 insertions(+), 132 deletions(-)

diff --git 
a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
 
b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
index 7a35430..af843cb 100644
--- 
a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
+++ 
b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
@@ -104,6 +104,11 @@ public class BPlusTreeBenchmark extends 
JmhAbstractBenchmark {
         }
 
         /** {@inheritDoc} */
+        @Override public long initRecycledPage(long pageId, byte flag, PageIO 
initIO) throws IgniteCheckedException {
+            return pageId;
+        }
+
+        /** {@inheritDoc} */
         @Override public long recycledPagesCount() throws 
IgniteCheckedException {
             return deque.size();
         }
@@ -186,6 +191,7 @@ public class BPlusTreeBenchmark extends 
JmhAbstractBenchmark {
                 reuseList,
                 new IOVersions<>(new LongInnerIO()),
                 new IOVersions<>(new LongLeafIO()),
+                PageIdAllocator.FLAG_IDX,
                 null,
                 null
             );
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageIdAllocator.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageIdAllocator.java
index 7395695..f97ada7 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageIdAllocator.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageIdAllocator.java
@@ -25,12 +25,26 @@ import static 
org.apache.ignite.internal.pagemem.PageIdUtils.pageId;
  * Allocates page ID's.
  */
 public interface PageIdAllocator {
-    /** */
+    /**
+     * Flag for Data page.
+     * Also used by partition meta and tracking pages.
+     * This type doesn't use Page ID rotation mechanizm.
+     */
     public static final byte FLAG_DATA = 1;
 
-    /** */
+    /**
+     * Flag for index page.
+     * Also used by internal structure in inmemory caches.
+     * This type uses Page ID rotation mechanizm.
+     */
     public static final byte FLAG_IDX = 2;
 
+    /**
+     * Flag for internal structure page.
+     * This type uses Page ID rotation mechanizm.
+     */
+    public static final byte FLAG_AUX = 4;
+
     /** Max partition ID that can be used by affinity. */
     public static final int MAX_PARTITION_ID = 65500;
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageIdUtils.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageIdUtils.java
index c48f4a8..395586c 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageIdUtils.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageIdUtils.java
@@ -108,7 +108,7 @@ public final class PageIdUtils {
      * @return Page ID.
      */
     public static long pageId(long link) {
-        return flag(link) == PageIdAllocator.FLAG_IDX ? link : link & 
PAGE_ID_MASK;
+        return flag(link) == PageIdAllocator.FLAG_DATA ? link & PAGE_ID_MASK : 
link;
     }
 
     /**
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/store/IgnitePageStoreManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/store/IgnitePageStoreManager.java
index 50af2a4..da606a68 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/store/IgnitePageStoreManager.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/store/IgnitePageStoreManager.java
@@ -162,7 +162,7 @@ public interface IgnitePageStoreManager extends 
GridCacheSharedManager, IgniteCh
      * Allocates a page for the given page space.
      *
      * @param grpId Cache group ID.
-     * @param partId Partition ID. Used only if {@code flags} is equal to 
{@link PageMemory#FLAG_DATA}.
+     * @param partId Partition ID. Used only if {@code flags} is not equal to 
{@link PageMemory#FLAG_IDX}.
      * @param flags Page allocation flags.
      * @return Allocated page ID.
      * @throws IgniteCheckedException If IO exception occurred while 
allocating a page ID.
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/store/PageStore.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/store/PageStore.java
index 1d9e501..528c682 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/store/PageStore.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/store/PageStore.java
@@ -26,6 +26,12 @@ import 
org.apache.ignite.internal.processors.cache.persistence.StorageException;
  * Persistent store of pages.
  */
 public interface PageStore extends Closeable {
+    /** Type for regular affinity partitions. */
+    public static byte TYPE_DATA = 1;
+
+    /** Type for index partition. */
+    public static byte TYPE_IDX = 2;
+
     /**
      * @param lsnr Page write listener to set.
      */
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
index 4743d89..024287f 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
@@ -237,7 +237,8 @@ public class IgniteCacheOffheapManagerImpl implements 
IgniteCacheOffheapManager
                 rootPage,
                 grp.reuseList(),
                 true,
-                lsnr
+                lsnr,
+                FLAG_IDX
             );
         }
     }
@@ -1291,7 +1292,8 @@ public class IgniteCacheOffheapManagerImpl implements 
IgniteCacheOffheapManager
             rowStore,
             rootPage,
             true,
-            lsnr
+            lsnr,
+            FLAG_IDX
         );
 
         return new CacheDataStoreImpl(p, rowStore, dataTree, () -> 
pendingEntries, grp, busyLock, log);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLog.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLog.java
index 0e98b8d..8cf61a8 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLog.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLog.java
@@ -184,7 +184,8 @@ public class TxLog implements CheckpointListener {
                     isNew,
                     txLogReuseListLockLsnr,
                     ctx,
-                    null
+                    null,
+                    FLAG_IDX
                 );
 
                 tree = new TxLogTree(
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLogTree.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLogTree.java
index c850928..a4df8bd 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLogTree.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLogTree.java
@@ -19,6 +19,7 @@ package 
org.apache.ignite.internal.processors.cache.mvcc.txlog;
 
 import java.util.concurrent.atomic.AtomicLong;
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.pagemem.PageIdAllocator;
 import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
 import org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree;
@@ -61,6 +62,7 @@ public class TxLogTree extends BPlusTree<TxKey, TxRow> {
             reuseList,
             TxLogInnerIO.VERSIONS,
             TxLogLeafIO.VERSIONS,
+            PageIdAllocator.FLAG_IDX,
             failureProcessor,
             lockLsnr
         );
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStructure.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStructure.java
index 68fd48e..8814d18 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStructure.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStructure.java
@@ -70,6 +70,9 @@ public abstract class DataStructure {
     /** */
     protected final PageIoResolver pageIoRslvr;
 
+    /** */
+    protected final byte pageFlag;
+
     /**
      * @param cacheGrpId Cache group ID.
      * @param grpName Cache group name.
@@ -77,6 +80,7 @@ public abstract class DataStructure {
      * @param wal Write ahead log manager.
      * @param lockLsnr Page lock listener.
      * @param pageIoRslvr Page IO resolver.
+     * @param pageFlag Default flag value for allocated pages.
      */
     public DataStructure(
         int cacheGrpId,
@@ -84,7 +88,8 @@ public abstract class DataStructure {
         PageMemory pageMem,
         IgniteWriteAheadLogManager wal,
         PageLockListener lockLsnr,
-        PageIoResolver pageIoRslvr
+        PageIoResolver pageIoRslvr,
+        byte pageFlag
     ) {
         assert pageMem != null;
 
@@ -94,6 +99,7 @@ public abstract class DataStructure {
         this.wal = wal;
         this.lockLsnr = lockLsnr == null ? NOOP_LSNR : lockLsnr;
         this.pageIoRslvr = pageIoRslvr;
+        this.pageFlag = pageFlag;
     }
 
     /**
@@ -131,16 +137,30 @@ public abstract class DataStructure {
      * @throws IgniteCheckedException If failed.
      */
     protected final long allocatePage(ReuseBag bag, boolean useRecycled) 
throws IgniteCheckedException {
-        long pageId = bag != null ? bag.pollFreePage() : 0;
+        long pageId = 0;
+
+        if (useRecycled && reuseList != null) {
+            pageId = bag != null ? bag.pollFreePage() : 0;
+
+            if (pageId == 0)
+                pageId = reuseList.takeRecycledPage();
 
-        if (pageId == 0 && useRecycled && reuseList != null)
-            pageId = reuseList.takeRecycledPage();
+            // Recycled. "pollFreePage" result should be reinitialized to move 
rotatedId to itemId.
+            if (pageId != 0)
+                pageId = reuseList.initRecycledPage(pageId, pageFlag, null);
+        }
 
         if (pageId == 0)
             pageId = allocatePageNoReuse();
 
         assert pageId != 0;
 
+        assert PageIdUtils.flag(pageId) == FLAG_IDX && 
PageIdUtils.partId(pageId) == INDEX_PARTITION ||
+            PageIdUtils.flag(pageId) != FLAG_IDX && PageIdUtils.partId(pageId) 
<= MAX_PARTITION_ID :
+            PageIdUtils.toDetailString(pageId);
+
+        assert PageIdUtils.flag(pageId) != FLAG_DATA || 
PageIdUtils.itemId(pageId) == 0 : PageIdUtils.toDetailString(pageId);
+
         return pageId;
     }
 
@@ -160,7 +180,7 @@ public abstract class DataStructure {
      */
     protected final long acquirePage(long pageId, IoStatisticsHolder 
statHolder) throws IgniteCheckedException {
         assert PageIdUtils.flag(pageId) == FLAG_IDX && 
PageIdUtils.partId(pageId) == INDEX_PARTITION ||
-            PageIdUtils.flag(pageId) == FLAG_DATA && 
PageIdUtils.partId(pageId) <= MAX_PARTITION_ID :
+            PageIdUtils.flag(pageId) != FLAG_IDX && PageIdUtils.partId(pageId) 
<= MAX_PARTITION_ID :
             U.hexLong(pageId) + " flag=" + PageIdUtils.flag(pageId) + " part=" 
+ PageIdUtils.partId(pageId);
 
         return pageMem.acquirePage(grpId, pageId, statHolder);
@@ -403,7 +423,7 @@ public abstract class DataStructure {
             int rotatedIdPart = PageIO.getRotatedIdPart(pageAddr);
 
             if (rotatedIdPart != 0) {
-                recycled = PageIdUtils.link(pageId, rotatedIdPart > 
MAX_ITEMID_NUM ? 1 : rotatedIdPart);
+                recycled = PageIdUtils.link(pageId, rotatedIdPart);
 
                 PageIO.setRotatedIdPart(pageAddr, 0);
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java
index cb7b6dc..ad062a8 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java
@@ -206,7 +206,8 @@ public class GridCacheOffheapManager extends 
IgniteCacheOffheapManagerImpl imple
             reuseListRoot.isAllocated(),
             
diagnosticMgr.pageLockTracker().createPageLockTracker(reuseListName),
             ctx.kernalContext(),
-            pageListCacheLimit
+            pageListCacheLimit,
+            PageIdAllocator.FLAG_IDX
         );
 
         RootPage metastoreRoot = metas.treeRoot;
@@ -828,7 +829,7 @@ public class GridCacheOffheapManager extends 
IgniteCacheOffheapManagerImpl imple
         boolean init = cntrsPageId == 0;
 
         if (init && !sizes.isEmpty())
-            cntrsPageId = pageMem.allocatePage(grpId, partId, 
PageIdAllocator.FLAG_DATA);
+            cntrsPageId = pageMem.allocatePage(grpId, partId, 
PageIdAllocator.FLAG_AUX);
 
         long nextId = cntrsPageId;
         int written = 0;
@@ -859,7 +860,7 @@ public class GridCacheOffheapManager extends 
IgniteCacheOffheapManagerImpl imple
 
                     if (written != items && (init = nextId == 0)) {
                         //allocate new counters page
-                        nextId = pageMem.allocatePage(grpId, partId, 
PageIdAllocator.FLAG_DATA);
+                        nextId = pageMem.allocatePage(grpId, partId, 
PageIdAllocator.FLAG_AUX);
                         partCntrIo.setNextCountersPageId(curAddr, nextId);
                     }
                 }
@@ -1959,13 +1960,14 @@ public class GridCacheOffheapManager extends 
IgniteCacheOffheapManagerImpl imple
                         reuseRoot.isAllocated(),
                         
ctx.diagnostic().pageLockTracker().createPageLockTracker(freeListName),
                         ctx.kernalContext(),
-                        pageListCacheLimit
+                        pageListCacheLimit,
+                        PageIdAllocator.FLAG_AUX
                     ) {
                         /** {@inheritDoc} */
                         @Override protected long allocatePageNoReuse() throws 
IgniteCheckedException {
                             assert 
ctx.database().checkpointLockIsHeldByThread();
 
-                            return pageMem.allocatePage(grpId, partId, 
PageIdAllocator.FLAG_DATA);
+                            return pageMem.allocatePage(grpId, partId, 
PageIdAllocator.FLAG_AUX);
                         }
                     };
 
@@ -1984,13 +1986,14 @@ public class GridCacheOffheapManager extends 
IgniteCacheOffheapManagerImpl imple
                         partMetastoreReuseListRoot.isAllocated(),
                         
ctx.diagnostic().pageLockTracker().createPageLockTracker(partitionMetaStoreName),
                         ctx.kernalContext(),
-                        pageListCacheLimit
+                        pageListCacheLimit,
+                        PageIdAllocator.FLAG_AUX
                     ) {
                         /** {@inheritDoc} */
                         @Override protected long allocatePageNoReuse() throws 
IgniteCheckedException {
                             assert 
ctx.database().checkpointLockIsHeldByThread();
 
-                            return pageMem.allocatePage(grpId, partId, 
PageIdAllocator.FLAG_DATA);
+                            return pageMem.allocatePage(grpId, partId, 
PageIdAllocator.FLAG_AUX);
                         }
                     };
 
@@ -2007,13 +2010,14 @@ public class GridCacheOffheapManager extends 
IgniteCacheOffheapManagerImpl imple
                         rowStore,
                         treeRoot.pageId().pageId(),
                         treeRoot.isAllocated(),
-                        
ctx.diagnostic().pageLockTracker().createPageLockTracker(dataTreeName)
+                        
ctx.diagnostic().pageLockTracker().createPageLockTracker(dataTreeName),
+                        PageIdAllocator.FLAG_AUX
                     ) {
                         /** {@inheritDoc} */
                         @Override protected long allocatePageNoReuse() throws 
IgniteCheckedException {
                             assert 
ctx.database().checkpointLockIsHeldByThread();
 
-                            return pageMem.allocatePage(grpId, partId, 
PageIdAllocator.FLAG_DATA);
+                            return pageMem.allocatePage(grpId, partId, 
PageIdAllocator.FLAG_AUX);
                         }
                     };
 
@@ -2028,13 +2032,14 @@ public class GridCacheOffheapManager extends 
IgniteCacheOffheapManagerImpl imple
                         pendingTreeRoot.pageId().pageId(),
                         freeList,
                         pendingTreeRoot.isAllocated(),
-                        
ctx.diagnostic().pageLockTracker().createPageLockTracker(pendingEntriesTreeName)
+                        
ctx.diagnostic().pageLockTracker().createPageLockTracker(pendingEntriesTreeName),
+                        PageIdAllocator.FLAG_AUX
                     ) {
                         /** {@inheritDoc} */
                         @Override protected long allocatePageNoReuse() throws 
IgniteCheckedException {
                             assert 
ctx.database().checkpointLockIsHeldByThread();
 
-                            return pageMem.allocatePage(grpId, partId, 
PageIdAllocator.FLAG_DATA);
+                            return pageMem.allocatePage(grpId, partId, 
PageIdAllocator.FLAG_AUX);
                         }
                     };
 
@@ -2185,15 +2190,15 @@ public class GridCacheOffheapManager extends 
IgniteCacheOffheapManagerImpl imple
 
                         io.initNewPage(pageAddr, partMetaId, 
pageMem.realPageSize(grpId));
 
-                        treeRoot = pageMem.allocatePage(grpId, partId, 
PageMemory.FLAG_DATA);
-                        reuseListRoot = pageMem.allocatePage(grpId, partId, 
PageMemory.FLAG_DATA);
-                        pendingTreeRoot = pageMem.allocatePage(grpId, partId, 
PageMemory.FLAG_DATA);
-                        partMetaStoreReuseListRoot = 
pageMem.allocatePage(grpId, partId, PageMemory.FLAG_DATA);
+                        treeRoot = pageMem.allocatePage(grpId, partId, 
PageMemory.FLAG_AUX);
+                        reuseListRoot = pageMem.allocatePage(grpId, partId, 
PageMemory.FLAG_AUX);
+                        pendingTreeRoot = pageMem.allocatePage(grpId, partId, 
PageMemory.FLAG_AUX);
+                        partMetaStoreReuseListRoot = 
pageMem.allocatePage(grpId, partId, PageMemory.FLAG_AUX);
 
-                        assert PageIdUtils.flag(treeRoot) == 
PageMemory.FLAG_DATA;
-                        assert PageIdUtils.flag(reuseListRoot) == 
PageMemory.FLAG_DATA;
-                        assert PageIdUtils.flag(pendingTreeRoot) == 
PageMemory.FLAG_DATA;
-                        assert PageIdUtils.flag(partMetaStoreReuseListRoot) == 
PageMemory.FLAG_DATA;
+                        assert PageIdUtils.flag(treeRoot) == 
PageMemory.FLAG_AUX;
+                        assert PageIdUtils.flag(reuseListRoot) == 
PageMemory.FLAG_AUX;
+                        assert PageIdUtils.flag(pendingTreeRoot) == 
PageMemory.FLAG_AUX;
+                        assert PageIdUtils.flag(partMetaStoreReuseListRoot) == 
PageMemory.FLAG_AUX;
 
                         io.setTreeRoot(pageAddr, treeRoot);
                         io.setReuseListRoot(pageAddr, reuseListRoot);
@@ -2228,8 +2233,8 @@ public class GridCacheOffheapManager extends 
IgniteCacheOffheapManagerImpl imple
 
                             ((PagePartitionMetaIOV3)io).upgradePage(pageAddr);
 
-                            pendingTreeRoot = pageMem.allocatePage(grpId, 
partId, PageMemory.FLAG_DATA);
-                            partMetaStoreReuseListRoot = 
pageMem.allocatePage(grpId, partId, PageMemory.FLAG_DATA);
+                            pendingTreeRoot = pageMem.allocatePage(grpId, 
partId, PageMemory.FLAG_AUX);
+                            partMetaStoreReuseListRoot = 
pageMem.allocatePage(grpId, partId, PageMemory.FLAG_AUX);
 
                             io.setPendingTreeRoot(pageAddr, pendingTreeRoot);
                             io.setPartitionMetaStoreReuseListRoot(pageAddr, 
partMetaStoreReuseListRoot);
@@ -2247,7 +2252,7 @@ public class GridCacheOffheapManager extends 
IgniteCacheOffheapManagerImpl imple
                             partMetaStoreReuseListRoot = 
io.getPartitionMetaStoreReuseListRoot(pageAddr);
 
                             if (partMetaStoreReuseListRoot == 0) {
-                                partMetaStoreReuseListRoot = 
pageMem.allocatePage(grpId, partId, PageMemory.FLAG_DATA);
+                                partMetaStoreReuseListRoot = 
pageMem.allocatePage(grpId, partId, PageMemory.FLAG_AUX);
 
                                 if 
(PageHandler.isWalDeltaRecordNeeded(pageMem, grpId, partMetaId, partMetaPage, 
wal,
                                     null)) {
@@ -2259,19 +2264,23 @@ public class GridCacheOffheapManager extends 
IgniteCacheOffheapManagerImpl imple
                             }
                         }
 
-                        if (PageIdUtils.flag(treeRoot) != PageMemory.FLAG_DATA)
+                        if (PageIdUtils.flag(treeRoot) != PageMemory.FLAG_AUX
+                            && PageIdUtils.flag(treeRoot) != 
PageMemory.FLAG_DATA)
                             throw new StorageException("Wrong tree root page 
id flag: treeRoot="
                                 + U.hexLong(treeRoot) + ", part=" + partId + 
", grpId=" + grpId);
 
-                        if (PageIdUtils.flag(reuseListRoot) != 
PageMemory.FLAG_DATA)
+                        if (PageIdUtils.flag(reuseListRoot) != 
PageMemory.FLAG_AUX
+                            && PageIdUtils.flag(reuseListRoot) != 
PageMemory.FLAG_DATA)
                             throw new StorageException("Wrong reuse list root 
page id flag: reuseListRoot="
                                 + U.hexLong(reuseListRoot) + ", part=" + 
partId + ", grpId=" + grpId);
 
-                        if (PageIdUtils.flag(pendingTreeRoot) != 
PageMemory.FLAG_DATA)
+                        if (PageIdUtils.flag(pendingTreeRoot) != 
PageMemory.FLAG_AUX
+                            && PageIdUtils.flag(pendingTreeRoot) != 
PageMemory.FLAG_DATA)
                             throw new StorageException("Wrong pending tree 
root page id flag: reuseListRoot="
-                                + U.hexLong(reuseListRoot) + ", part=" + 
partId + ", grpId=" + grpId);
+                                + U.hexLong(pendingTreeRoot) + ", part=" + 
partId + ", grpId=" + grpId);
 
-                        if (PageIdUtils.flag(partMetaStoreReuseListRoot) != 
PageMemory.FLAG_DATA)
+                        if (PageIdUtils.flag(partMetaStoreReuseListRoot) != 
PageMemory.FLAG_AUX
+                            && PageIdUtils.flag(partMetaStoreReuseListRoot) != 
PageMemory.FLAG_DATA)
                             throw new StorageException("Wrong partition meta 
store list root page id flag: partMetaStoreReuseListRoot="
                                 + U.hexLong(partMetaStoreReuseListRoot) + ", 
part=" + partId + ", grpId=" + grpId);
                     }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
index 9eb02fb..bfadeb2 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
@@ -55,6 +55,7 @@ import org.apache.ignite.internal.mem.DirectMemoryRegion;
 import org.apache.ignite.internal.mem.IgniteOutOfMemoryException;
 import org.apache.ignite.internal.mem.file.MappedFileMemoryProvider;
 import org.apache.ignite.internal.mem.unsafe.UnsafeMemoryProvider;
+import org.apache.ignite.internal.pagemem.PageIdAllocator;
 import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.pagemem.impl.PageMemoryNoStoreImpl;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
@@ -315,7 +316,8 @@ public class IgniteCacheDatabaseSharedManager extends 
GridCacheSharedManagerAdap
                 true,
                 lsnr,
                 cctx.kernalContext(),
-                null
+                null,
+                PageIdAllocator.FLAG_IDX
             );
 
             freeListMap.put(memPlcCfg.getName(), freeList);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorageImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorageImpl.java
index 1be0b97..94f7feb 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorageImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorageImpl.java
@@ -24,6 +24,7 @@ import java.util.concurrent.atomic.AtomicLong;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.internal.pagemem.FullPageId;
+import org.apache.ignite.internal.pagemem.PageIdAllocator;
 import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.pagemem.PageUtils;
 import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
@@ -267,6 +268,7 @@ public class IndexStorageImpl implements IndexStorage {
                 reuseList,
                 innerIos,
                 leafIos,
+                PageIdAllocator.FLAG_IDX,
                 failureProcessor,
                 lockLsnr
             );
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreFactory.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreFactory.java
index ae92359..53e9fe9 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreFactory.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreFactory.java
@@ -21,7 +21,6 @@ import java.io.File;
 import java.nio.file.Path;
 import java.util.function.LongConsumer;
 import org.apache.ignite.IgniteCheckedException;
-import org.apache.ignite.internal.pagemem.PageIdAllocator;
 import org.apache.ignite.internal.pagemem.store.PageStore;
 import org.apache.ignite.lang.IgniteOutClosure;
 
@@ -32,7 +31,7 @@ public interface FilePageStoreFactory {
     /**
      * Creates instance of PageStore based on given file.
      *
-     * @param type Data type, can be {@link PageIdAllocator#FLAG_IDX} or 
{@link PageIdAllocator#FLAG_DATA}.
+     * @param type Data type, can be {@link PageStore#TYPE_IDX} or {@link 
PageStore#TYPE_DATA}.
      * @param file File Page store file.
      * @param allocatedTracker metrics updater.
      * @return page store
@@ -46,7 +45,7 @@ public interface FilePageStoreFactory {
     /**
      * Creates instance of PageStore based on file path provider.
      *
-     * @param type Data type, can be {@link PageIdAllocator#FLAG_IDX} or 
{@link PageIdAllocator#FLAG_DATA}
+     * @param type Data type, can be {@link PageStore#TYPE_IDX} or {@link 
PageStore#TYPE_DATA}
      * @param pathProvider File Page store path provider.
      * @param allocatedTracker metrics updater
      * @return page store
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java
index 7152b1e..3f5f8a9 100755
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java
@@ -64,7 +64,6 @@ import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.client.util.GridConcurrentHashSet;
 import org.apache.ignite.internal.pagemem.PageIdAllocator;
 import org.apache.ignite.internal.pagemem.PageIdUtils;
-import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.pagemem.store.IgnitePageStoreManager;
 import org.apache.ignite.internal.pagemem.store.PageStore;
 import org.apache.ignite.internal.pagemem.store.PageStoreCollection;
@@ -741,7 +740,7 @@ public class FilePageStoreManager extends 
GridCacheSharedManagerAdapter implemen
 
             PageStore idxStore =
                 pageStoreFactory.createPageStore(
-                    PageMemory.FLAG_IDX,
+                    PageStore.TYPE_IDX,
                     idxFile,
                     allocatedTracker);
 
@@ -752,7 +751,7 @@ public class FilePageStoreManager extends 
GridCacheSharedManagerAdapter implemen
 
                 PageStore partStore =
                     pageStoreFactory.createPageStore(
-                        PageMemory.FLAG_DATA,
+                        PageStore.TYPE_DATA,
                         () -> getPartitionFilePath(cacheWorkDir, p),
                         allocatedTracker);
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/AbstractFreeList.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/AbstractFreeList.java
index b46417b..7ccaf37 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/AbstractFreeList.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/AbstractFreeList.java
@@ -50,6 +50,8 @@ import 
org.apache.ignite.internal.util.GridCursorIteratorWrapper;
 import org.apache.ignite.internal.util.lang.GridCursor;
 import org.apache.ignite.internal.util.typedef.internal.U;
 
+import static org.apache.ignite.internal.pagemem.PageIdAllocator.FLAG_DATA;
+
 /**
  */
 public abstract class AbstractFreeList<T extends Storable> extends PagesList 
implements FreeList<T>, ReuseList {
@@ -425,6 +427,7 @@ public abstract class AbstractFreeList<T extends Storable> 
extends PagesList imp
      * @param wal Write ahead log manager.
      * @param metaPageId Metadata page ID.
      * @param initNew {@code True} if new metadata should be initialized.
+     * @param pageFlag Default flag value for allocated pages.
      * @throws IgniteCheckedException If failed.
      */
     public AbstractFreeList(
@@ -438,9 +441,10 @@ public abstract class AbstractFreeList<T extends Storable> 
extends PagesList imp
         boolean initNew,
         PageLockListener lockLsnr,
         GridKernalContext ctx,
-        AtomicLong pageListCacheLimit
+        AtomicLong pageListCacheLimit,
+        byte pageFlag
     ) throws IgniteCheckedException {
-        super(cacheId, name, memPlc.pageMemory(), BUCKETS, wal, metaPageId, 
lockLsnr, ctx);
+        super(cacheId, name, memPlc.pageMemory(), BUCKETS, wal, metaPageId, 
lockLsnr, ctx, pageFlag);
 
         rmvRow = new RemoveRowHandler(cacheId == 0);
 
@@ -565,9 +569,8 @@ public abstract class AbstractFreeList<T extends Storable> 
extends PagesList imp
      */
     private long allocateDataPage(int part) throws IgniteCheckedException {
         assert part <= PageIdAllocator.MAX_PARTITION_ID;
-        assert part != PageIdAllocator.INDEX_PARTITION;
 
-        return pageMem.allocatePage(grpId, part, PageIdAllocator.FLAG_DATA);
+        return pageMem.allocatePage(grpId, part, FLAG_DATA);
     }
 
     /** {@inheritDoc} */
@@ -719,17 +722,23 @@ public abstract class AbstractFreeList<T extends 
Storable> extends PagesList imp
         }
 
         if (pageId == 0L) { // Handle reuse bucket.
-            pageId = reuseList == this ?
-                takeEmptyPage(REUSE_BUCKET, row.ioVersions(), statHolder) : 
reuseList.takeRecycledPage();
+            if (reuseList == this)
+                pageId = takeEmptyPage(REUSE_BUCKET, row.ioVersions(), 
statHolder);
+            else {
+                pageId = reuseList.takeRecycledPage();
+
+                if (pageId != 0)
+                    pageId = reuseList.initRecycledPage(pageId, FLAG_DATA, 
row.ioVersions().latest());
+            }
         }
 
         if (pageId == 0L)
             return 0;
 
-        if (PageIdUtils.tag(pageId) != PageIdAllocator.FLAG_DATA) // Page is 
taken from reuse bucket.
-            return initReusedPage(row, pageId, statHolder);
-        else // Page is taken from free space bucket. For in-memory mode 
partition must be changed.
-            return PageIdUtils.changePartitionId(pageId, row.partition());
+        assert PageIdUtils.flag(pageId) == FLAG_DATA
+            : "rowVersions=" + row.ioVersions() + ", pageId=" + 
PageIdUtils.toDetailString(pageId);
+
+        return PageIdUtils.changePartitionId(pageId, row.partition());
     }
 
     /**
@@ -912,6 +921,11 @@ public abstract class AbstractFreeList<T extends Storable> 
extends PagesList imp
     }
 
     /** {@inheritDoc} */
+    @Override public long initRecycledPage(long pageId, byte flag, PageIO 
initIO) throws IgniteCheckedException {
+        return initRecycledPage0(pageId, flag, initIO);
+    }
+
+    /** {@inheritDoc} */
     @Override public long recycledPagesCount() throws IgniteCheckedException {
         assert reuseList == this : "not allowed to be a reuse list";
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/CacheFreeList.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/CacheFreeList.java
index a4a4363..fdf50c9 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/CacheFreeList.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/CacheFreeList.java
@@ -41,6 +41,7 @@ public class CacheFreeList extends 
AbstractFreeList<CacheDataRow> {
      * @param wal Wal.
      * @param metaPageId Meta page id.
      * @param initNew Initialize new.
+     * @param pageFlag Default flag value for allocated pages.
      */
     public CacheFreeList(
         int cacheId,
@@ -52,7 +53,8 @@ public class CacheFreeList extends 
AbstractFreeList<CacheDataRow> {
         boolean initNew,
         PageLockListener lockLsnr,
         GridKernalContext ctx,
-        AtomicLong pageListCacheLimit
+        AtomicLong pageListCacheLimit,
+        byte pageFlag
     ) throws IgniteCheckedException {
         super(
             cacheId,
@@ -65,7 +67,8 @@ public class CacheFreeList extends 
AbstractFreeList<CacheDataRow> {
             initNew,
             lockLsnr,
             ctx,
-            pageListCacheLimit
+            pageListCacheLimit,
+            pageFlag
         );
     }
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java
index 530690e..bf66500 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java
@@ -32,6 +32,7 @@ import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.managers.communication.GridIoPolicy;
 import org.apache.ignite.internal.metric.IoStatisticsHolder;
 import org.apache.ignite.internal.metric.IoStatisticsHolderNoOp;
+import org.apache.ignite.internal.pagemem.PageIdAllocator;
 import org.apache.ignite.internal.pagemem.PageIdUtils;
 import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
@@ -43,6 +44,7 @@ import 
org.apache.ignite.internal.pagemem.wal.record.delta.PagesListInitNewPageR
 import 
org.apache.ignite.internal.pagemem.wal.record.delta.PagesListRemovePageRecord;
 import 
org.apache.ignite.internal.pagemem.wal.record.delta.PagesListSetNextRecord;
 import 
org.apache.ignite.internal.pagemem.wal.record.delta.PagesListSetPreviousRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.RecycleRecord;
 import org.apache.ignite.internal.pagemem.wal.record.delta.RotatedIdPartRecord;
 import org.apache.ignite.internal.processors.cache.persistence.DataStructure;
 import 
org.apache.ignite.internal.processors.cache.persistence.freelist.io.PagesListMetaIO;
@@ -65,7 +67,12 @@ import static java.lang.Boolean.FALSE;
 import static java.lang.Boolean.TRUE;
 import static org.apache.ignite.internal.pagemem.PageIdAllocator.FLAG_DATA;
 import static org.apache.ignite.internal.pagemem.PageIdAllocator.FLAG_IDX;
+import static 
org.apache.ignite.internal.pagemem.PageIdAllocator.INDEX_PARTITION;
 import static org.apache.ignite.internal.pagemem.PageIdUtils.MAX_ITEMID_NUM;
+import static 
org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO.T_DATA;
+import static 
org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO.T_DATA_METASTORAGE;
+import static 
org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO.T_DATA_PART;
+import static 
org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO.T_META;
 import static 
org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO.getPageId;
 import static 
org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIoResolver.DEFAULT_PAGE_IO_RESOLVER;
 
@@ -201,6 +208,7 @@ public abstract class PagesList extends DataStructure {
      * @param buckets Number of buckets.
      * @param wal Write ahead log manager.
      * @param metaPageId Metadata page ID.
+     * @param pageFlag Default flag value for allocated pages.
      */
     protected PagesList(
         int cacheId,
@@ -210,9 +218,10 @@ public abstract class PagesList extends DataStructure {
         IgniteWriteAheadLogManager wal,
         long metaPageId,
         PageLockListener lockLsnr,
-        GridKernalContext ctx
+        GridKernalContext ctx,
+        byte pageFlag
     ) {
-        super(cacheId, null, pageMem, wal, lockLsnr, DEFAULT_PAGE_IO_RESOLVER);
+        super(cacheId, null, pageMem, wal, lockLsnr, DEFAULT_PAGE_IO_RESOLVER, 
pageFlag);
 
         this.name = name;
         this.buckets = buckets;
@@ -1305,6 +1314,8 @@ public abstract class PagesList extends DataStructure {
                     ", pageId=" + pageId + ']');
             }
 
+            assert !isReuseBucket(bucket) : "reuse bucket detected";
+
             return pageId;
         }
 
@@ -1372,7 +1383,15 @@ public abstract class PagesList extends DataStructure {
                             PageIdUtils.itemId(pageId) > 0 && 
PageIdUtils.itemId(pageId) <= MAX_ITEMID_NUM
                             : "Incorrectly recycled pageId in reuse bucket: " 
+ U.hexLong(pageId);
 
-                        dataPageId = pageId;
+                        if (isReuseBucket(bucket)) {
+                            byte flag = getFlag(initIoVers);
+
+                            PageIO initIO = initIoVers == null ? null : 
initIoVers.latest();
+
+                            dataPageId = initRecycledPage0(pageId, flag, 
initIO);
+                        }
+                        else
+                            dataPageId = pageId;
 
                         if (io.isEmpty(tailAddr)) {
                             long prevId = io.getPreviousId(tailAddr);
@@ -1410,12 +1429,11 @@ public abstract class PagesList extends DataStructure {
 
                         decrementBucketSize(bucket);
 
-                        if (initIoVers != null) {
-                            int partId = PageIdUtils.partId(tailId);
+                        byte flag = getFlag(initIoVers);
 
-                            dataPageId = initReusedPage(tailId, tailPage, 
tailAddr, partId, FLAG_DATA, initIoVers.latest());
-                        } else
-                            dataPageId = recyclePage(tailId, tailPage, 
tailAddr, null);
+                        PageIO pageIO = initIoVers != null ? 
initIoVers.latest() : null;
+
+                        dataPageId = initReusedPage(tailId, tailPage, 
tailAddr, PageIdUtils.partId(tailId), flag, pageIO);
 
                         dirty = true;
                     }
@@ -1450,7 +1468,56 @@ public abstract class PagesList extends DataStructure {
     }
 
     /**
-     * Reused page must obtain correctly assembled page id, then initialized 
by proper {@link PageIO} instance and
+     * @param initIoVers Optional IO versions list that will be used later to 
init the page.
+     * @return {@link PageIdAllocator#FLAG_DATA} for cache group metas and 
data pages,
+     *      {@link #pageFlag} otherwise.
+     */
+    private byte getFlag(IOVersions<?> initIoVers) {
+        if (initIoVers != null) {
+            PageIO pageIO = initIoVers.latest();
+
+            switch (pageIO.getType()) {
+                case T_META:
+                case T_DATA:
+                case T_DATA_PART:
+                case T_DATA_METASTORAGE:
+                    return FLAG_DATA;
+            }
+        }
+
+        return pageFlag;
+    }
+
+    /**
+     * Create new page id and update page content accordingly if it's 
necessary.
+     *
+     * @param pageId Id of the recycled page from reuse bucket.
+     * @param flag New flag for the page.
+     * @return New page id.
+     * @throws IgniteCheckedException If failed.
+     *
+     * @see PagesList#initReusedPage(long, long, long, int, byte, PageIO)
+     */
+    protected long initRecycledPage0(long pageId, byte flag, PageIO initIO) 
throws IgniteCheckedException {
+        long page = pageMem.acquirePage(grpId, pageId);
+
+        try {
+            long pageAddr = pageMem.writeLock(grpId, pageId, page);
+
+            try {
+                return initReusedPage(pageId, page, pageAddr, 
PageIdUtils.partId(pageId), flag, initIO);
+            }
+            finally {
+                pageMem.writeUnlock(grpId, pageId, page, null, true);
+            }
+        }
+        finally {
+            pageMem.releasePage(grpId, pageId, page);
+        }
+    }
+
+    /**
+     * Reused page must obtain correctly assaembled page id, then initialized 
by proper {@link PageIO} instance and
      * non-zero {@code itemId} of reused page id must be saved into special 
place.
      *
      * @param reusedPageId Reused page id.
@@ -1464,30 +1531,47 @@ public abstract class PagesList extends DataStructure {
      */
     protected final long initReusedPage(long reusedPageId, long reusedPage, 
long reusedPageAddr,
         int partId, byte flag, PageIO initIo) throws IgniteCheckedException {
+        if (flag == FLAG_IDX)
+            partId = INDEX_PARTITION;
 
         long newPageId = PageIdUtils.pageId(partId, flag, 
PageIdUtils.pageIndex(reusedPageId));
 
-        initIo.initNewPage(reusedPageAddr, newPageId, pageSize());
-
         boolean needWalDeltaRecord = needWalDeltaRecord(reusedPageId, 
reusedPage, null);
 
-        if (needWalDeltaRecord) {
-            assert PageIdUtils.partId(reusedPageId) == 
PageIdUtils.partId(newPageId) :
-                "Partition consistency failure: " +
-                "newPageId=" + Long.toHexString(newPageId) + " (newPartId: " + 
PageIdUtils.partId(newPageId) + ") " +
-                "reusedPageId=" + Long.toHexString(reusedPageId) + " (partId: 
" + PageIdUtils.partId(reusedPageId) + ")";
+        if (initIo != null) {
+            initIo.initNewPage(reusedPageAddr, newPageId, pageSize());
+
+            if (needWalDeltaRecord) {
+                assert PageIdUtils.partId(reusedPageId) == 
PageIdUtils.partId(newPageId) :
+                    "Partition consistency failure: " +
+                    "newPageId=" + Long.toHexString(newPageId) + " (newPartId: 
" + PageIdUtils.partId(newPageId) + ") " +
+                    "reusedPageId=" + Long.toHexString(reusedPageId) + " 
(partId: " + PageIdUtils.partId(reusedPageId) + ")";
 
-            wal.log(new InitNewPageRecord(grpId, reusedPageId, 
initIo.getType(),
-                initIo.getVersion(), newPageId));
+                wal.log(new InitNewPageRecord(grpId, reusedPageId, 
initIo.getType(),
+                    initIo.getVersion(), newPageId));
+            }
         }
 
         int itemId = PageIdUtils.itemId(reusedPageId);
 
         if (itemId != 0) {
-            PageIO.setRotatedIdPart(reusedPageAddr, itemId);
+            if (flag == FLAG_DATA) {
+                PageIO.setRotatedIdPart(reusedPageAddr, itemId);
+
+                if (needWalDeltaRecord)
+                    wal.log(new RotatedIdPartRecord(grpId, newPageId, itemId));
+            }
+            else
+                newPageId = PageIdUtils.link(newPageId, itemId);
+        }
+
+        long storedPageId = getPageId(reusedPageAddr);
+
+        if (storedPageId != newPageId) {
+            PageIO.setPageId(reusedPageAddr, newPageId);
 
             if (needWalDeltaRecord)
-                wal.log(new RotatedIdPartRecord(grpId, newPageId, itemId));
+                wal.log(new RecycleRecord(grpId, storedPageId, newPageId));
         }
 
         return newPageId;
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java
index b88cad8..2c20a02 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java
@@ -72,7 +72,7 @@ import org.apache.ignite.marshaller.Marshaller;
 import org.apache.ignite.marshaller.jdk.JdkMarshaller;
 import org.jetbrains.annotations.NotNull;
 
-import static org.apache.ignite.internal.pagemem.PageIdAllocator.FLAG_DATA;
+import static org.apache.ignite.internal.pagemem.PageIdAllocator.FLAG_AUX;
 import static 
org.apache.ignite.internal.pagemem.PageIdAllocator.OLD_METASTORE_PARTITION;
 
 /**
@@ -266,10 +266,11 @@ public class MetaStorage implements CheckpointListener, 
ReadWriteMetastorage {
                 reuseListRoot.isAllocated(),
                 
diagnosticMgr.pageLockTracker().createPageLockTracker(freeListName),
                 cctx.kernalContext(),
-                null
+                null,
+                FLAG_AUX
             ) {
                 @Override protected long allocatePageNoReuse() throws 
IgniteCheckedException {
-                    return pageMem.allocatePage(grpId, partId, FLAG_DATA);
+                    return pageMem.allocatePage(grpId, partId, FLAG_AUX);
                 }
             };
 
@@ -487,11 +488,13 @@ public class MetaStorage implements CheckpointListener, 
ReadWriteMetastorage {
 
     /** */
     private void checkRootsPageIdFlag(long treeRoot, long reuseListRoot) 
throws StorageException {
-        if (PageIdUtils.flag(treeRoot) != PageMemory.FLAG_DATA)
+        if (PageIdUtils.flag(treeRoot) != PageMemory.FLAG_AUX &&
+            PageIdUtils.flag(treeRoot) != PageMemory.FLAG_DATA)
             throw new StorageException("Wrong tree root page id flag: 
treeRoot="
                 + U.hexLong(treeRoot) + ", METASTORAGE_CACHE_ID=" + 
METASTORAGE_CACHE_ID);
 
-        if (PageIdUtils.flag(reuseListRoot) != PageMemory.FLAG_DATA)
+        if (PageIdUtils.flag(treeRoot) != PageMemory.FLAG_AUX &&
+            PageIdUtils.flag(treeRoot) != PageMemory.FLAG_DATA)
             throw new StorageException("Wrong reuse list root page id flag: 
reuseListRoot="
                 + U.hexLong(reuseListRoot) + ", METASTORAGE_CACHE_ID=" + 
METASTORAGE_CACHE_ID);
     }
@@ -550,11 +553,11 @@ public class MetaStorage implements CheckpointListener, 
ReadWriteMetastorage {
                         //MetaStorage never encrypted so realPageSize == 
pageSize.
                         io.initNewPage(pageAddr, partMetaId, 
pageMem.pageSize());
 
-                        treeRoot = pageMem.allocatePage(METASTORAGE_CACHE_ID, 
partId, PageMemory.FLAG_DATA);
-                        reuseListRoot = 
pageMem.allocatePage(METASTORAGE_CACHE_ID, partId, PageMemory.FLAG_DATA);
+                        treeRoot = pageMem.allocatePage(METASTORAGE_CACHE_ID, 
partId, PageMemory.FLAG_AUX);
+                        reuseListRoot = 
pageMem.allocatePage(METASTORAGE_CACHE_ID, partId, PageMemory.FLAG_AUX);
 
-                        assert PageIdUtils.flag(treeRoot) == 
PageMemory.FLAG_DATA;
-                        assert PageIdUtils.flag(reuseListRoot) == 
PageMemory.FLAG_DATA;
+                        assert PageIdUtils.flag(treeRoot) == 
PageMemory.FLAG_AUX;
+                        assert PageIdUtils.flag(reuseListRoot) == 
PageMemory.FLAG_AUX;
 
                         io.setTreeRoot(pageAddr, treeRoot);
                         io.setReuseListRoot(pageAddr, reuseListRoot);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetastorageTree.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetastorageTree.java
index afce4e2..7b1bb6e 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetastorageTree.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetastorageTree.java
@@ -28,7 +28,7 @@ import 
org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLoc
 import org.apache.ignite.internal.processors.failure.FailureProcessor;
 import org.jetbrains.annotations.Nullable;
 
-import static org.apache.ignite.internal.pagemem.PageIdAllocator.FLAG_DATA;
+import static org.apache.ignite.internal.pagemem.PageIdAllocator.FLAG_AUX;
 
 /**
  *
@@ -79,6 +79,7 @@ public class MetastorageTree extends 
BPlusTree<MetastorageRow, MetastorageDataRo
             reuseList,
             MetastorageBPlusIO.INNER_IO_VERSIONS,
             MetastorageBPlusIO.LEAF_IO_VERSIONS,
+            FLAG_AUX,
             failureProcessor,
             lockLsnr
         );
@@ -115,6 +116,6 @@ public class MetastorageTree extends 
BPlusTree<MetastorageRow, MetastorageDataRo
 
     /** {@inheritDoc} */
     @Override protected long allocatePageNoReuse() throws 
IgniteCheckedException {
-        return pageMem.allocatePage(grpId, partId, FLAG_DATA);
+        return pageMem.allocatePage(grpId, partId, FLAG_AUX);
     }
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/migration/UpgradePendingTreeToPerPartitionTask.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/migration/UpgradePendingTreeToPerPartitionTask.java
index 4499980..6d06673 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/migration/UpgradePendingTreeToPerPartitionTask.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/migration/UpgradePendingTreeToPerPartitionTask.java
@@ -22,6 +22,7 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.pagemem.PageIdAllocator;
 import org.apache.ignite.internal.pagemem.PageIdUtils;
 import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.processors.cache.CacheGroupContext;
@@ -150,7 +151,8 @@ public class UpgradePendingTreeToPerPartitionTask 
implements IgniteCallable<Bool
                 pendingRootPage.pageId().pageId(),
                 
((GridCacheOffheapManager)grp.offheap()).reuseListForIndex(null),
                 false,
-                null
+                null,
+                PageIdAllocator.FLAG_IDX
             );
         }
         finally {
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
index 4872c6d..c6d4d87 100755
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
@@ -514,7 +514,7 @@ public class PageMemoryImpl implements PageMemoryEx {
 
     /** {@inheritDoc} */
     @Override public long allocatePage(int grpId, int partId, byte flags) 
throws IgniteCheckedException {
-        assert flags == PageIdAllocator.FLAG_DATA && partId <= 
PageIdAllocator.MAX_PARTITION_ID ||
+        assert flags != PageIdAllocator.FLAG_IDX && partId <= 
PageIdAllocator.MAX_PARTITION_ID ||
             flags == PageIdAllocator.FLAG_IDX && partId == 
PageIdAllocator.INDEX_PARTITION :
             "flags = " + flags + ", partId = " + partId;
 
@@ -536,12 +536,15 @@ public class PageMemoryImpl implements PageMemoryEx {
         DelayedDirtyPageStoreWrite delayedWriter = 
delayedPageReplacementTracker != null
             ? delayedPageReplacementTracker.delayedPageWrite() : null;
 
-        FullPageId fullId = new FullPageId(pageId, grpId);
-
         seg.writeLock().lock();
 
-        boolean isTrackingPage =
-            changeTracker != null && trackingIO.trackingPageFor(pageId, 
realPageSize(grpId)) == pageId;
+        boolean isTrackingPage = changeTracker != null &&
+            PageIdUtils.pageIndex(trackingIO.trackingPageFor(pageId, 
realPageSize(grpId))) == PageIdUtils.pageIndex(pageId);
+
+        if (isTrackingPage && PageIdUtils.flag(pageId) == 
PageIdAllocator.FLAG_AUX)
+            pageId = PageIdUtils.pageId(PageIdUtils.partId(pageId), 
PageIdAllocator.FLAG_DATA, PageIdUtils.pageIndex(pageId));
+
+        FullPageId fullId = new FullPageId(pageId, grpId);
 
         try {
             long relPtr = seg.loadedPages.get(
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/partstate/GroupPartitionId.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/partstate/GroupPartitionId.java
index c236827..275fb55 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/partstate/GroupPartitionId.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/partstate/GroupPartitionId.java
@@ -20,7 +20,7 @@ package 
org.apache.ignite.internal.processors.cache.persistence.partstate;
 import org.apache.ignite.internal.pagemem.FullPageId;
 import org.apache.ignite.internal.pagemem.PageIdAllocator;
 import org.apache.ignite.internal.pagemem.PageIdUtils;
-import org.apache.ignite.internal.pagemem.PageMemory;
+import org.apache.ignite.internal.pagemem.store.PageStore;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.jetbrains.annotations.NotNull;
 
@@ -53,7 +53,15 @@ public class GroupPartitionId implements 
Comparable<GroupPartitionId> {
      * @return flag to be used for partition
      */
     public static byte getFlagByPartId(final int partId) {
-        return partId == PageIdAllocator.INDEX_PARTITION ? PageMemory.FLAG_IDX 
: PageMemory.FLAG_DATA;
+        return partId == PageIdAllocator.INDEX_PARTITION ? 
PageIdAllocator.FLAG_IDX : PageIdAllocator.FLAG_DATA;
+    }
+
+    /**
+     * @param partId Partition ID.
+     * @return page store type to be used for partition
+     */
+    public static byte getTypeByPartId(final int partId) {
+        return partId == PageIdAllocator.INDEX_PARTITION ? PageStore.TYPE_IDX 
: PageStore.TYPE_DATA;
     }
 
     /**
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/partstorage/PartitionMetaStorageImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/partstorage/PartitionMetaStorageImpl.java
index 0e9062a..acf8334 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/partstorage/PartitionMetaStorageImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/partstorage/PartitionMetaStorageImpl.java
@@ -49,6 +49,7 @@ public class PartitionMetaStorageImpl<T extends Storable> 
extends AbstractFreeLi
      * @param wal Wal.
      * @param metaPageId Meta page id.
      * @param initNew Initialize new.
+     * @param pageFlag Default flag value for allocated pages.
      */
     public PartitionMetaStorageImpl(
         int cacheId, String name,
@@ -60,9 +61,10 @@ public class PartitionMetaStorageImpl<T extends Storable> 
extends AbstractFreeLi
         boolean initNew,
         PageLockListener lsnr,
         GridKernalContext ctx,
-        AtomicLong pageListCacheLimit
+        AtomicLong pageListCacheLimit,
+        byte pageFlag
     ) throws IgniteCheckedException {
-        super(cacheId, name, memMetrics, memPlc, reuseList, wal, metaPageId, 
initNew, lsnr, ctx, pageListCacheLimit);
+        super(cacheId, name, memMetrics, memPlc, reuseList, wal, metaPageId, 
initNew, lsnr, ctx, pageListCacheLimit, pageFlag);
     }
 
     /**
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotManager.java
index 681485d..1d9f385 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotManager.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotManager.java
@@ -132,7 +132,7 @@ import static 
org.apache.ignite.internal.processors.cache.persistence.file.FileP
 import static 
org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager.PART_FILE_TEMPLATE;
 import static 
org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager.getPartitionFile;
 import static 
org.apache.ignite.internal.processors.cache.persistence.filename.PdsConsistentIdProcessor.DB_DEFAULT_FOLDER;
-import static 
org.apache.ignite.internal.processors.cache.persistence.partstate.GroupPartitionId.getFlagByPartId;
+import static 
org.apache.ignite.internal.processors.cache.persistence.partstate.GroupPartitionId.getTypeByPartId;
 import static 
org.apache.ignite.internal.util.IgniteUtils.isLocalNodeCoordinator;
 import static 
org.apache.ignite.internal.util.distributed.DistributedProcess.DistributedProcessType.END_SNAPSHOT;
 import static 
org.apache.ignite.internal.util.distributed.DistributedProcess.DistributedProcessType.START_SNAPSHOT;
@@ -1206,7 +1206,7 @@ public class IgniteSnapshotManager extends 
GridCacheSharedManagerAdapter
             try (FileIO fileIo = ioFactory.create(delta, READ);
                  FilePageStore pageStore = (FilePageStore)storeFactory
                      .apply(pair.getGroupId(), false)
-                     .createPageStore(getFlagByPartId(pair.getPartitionId()),
+                     .createPageStore(getTypeByPartId(pair.getPartitionId()),
                          snpPart::toPath,
                          val -> {})
             ) {
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
index 5e67b7c..ca92a71 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
@@ -754,6 +754,7 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
      * @param reuseList Reuse list.
      * @param innerIos Inner IO versions.
      * @param leafIos Leaf IO versions.
+     * @param pageFlag Default flag value for allocated pages.
      * @param failureProcessor if the tree is corrupted.
      * @throws IgniteCheckedException If failed.
      */
@@ -768,6 +769,7 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
         ReuseList reuseList,
         IOVersions<? extends BPlusInnerIO<L>> innerIos,
         IOVersions<? extends BPlusLeafIO<L>> leafIos,
+        byte pageFlag,
         @Nullable FailureProcessor failureProcessor,
         @Nullable PageLockListener lockLsnr
     ) throws IgniteCheckedException {
@@ -780,6 +782,7 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
             globalRmvId,
             metaPageId,
             reuseList,
+            pageFlag,
             failureProcessor,
             lockLsnr,
             DEFAULT_PAGE_IO_RESOLVER
@@ -797,6 +800,7 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
      * @param globalRmvId Remove ID.
      * @param metaPageId Meta page ID.
      * @param reuseList Reuse list.
+     * @param pageFlag Default flag value for allocated pages.
      * @param failureProcessor if the tree is corrupted.
      * @throws IgniteCheckedException If failed.
      */
@@ -809,11 +813,12 @@ public abstract class BPlusTree<L, T extends L> extends 
DataStructure implements
         AtomicLong globalRmvId,
         long metaPageId,
         ReuseList reuseList,
+        byte pageFlag,
         @Nullable FailureProcessor failureProcessor,
         @Nullable PageLockListener lsnr,
         PageIoResolver pageIoRslvr
-    ) {
-        super(cacheGrpId, grpName, pageMem, wal, lsnr, pageIoRslvr);
+    ) throws IgniteCheckedException {
+        super(cacheGrpId, grpName, pageMem, wal, lsnr, pageIoRslvr, pageFlag);
 
         assert !F.isEmpty(name);
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/TrackingPageIO.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/TrackingPageIO.java
index b2f52a5..5fa1cdd 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/TrackingPageIO.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/TrackingPageIO.java
@@ -19,6 +19,7 @@ package 
org.apache.ignite.internal.processors.cache.persistence.tree.io;
 
 import java.nio.ByteBuffer;
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.pagemem.PageIdAllocator;
 import org.apache.ignite.internal.pagemem.PageIdUtils;
 import 
org.apache.ignite.internal.processors.cache.persistence.snapshot.TrackingPageIsCorruptedException;
 import 
org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandler;
@@ -356,7 +357,11 @@ public class TrackingPageIO extends PageIO {
         int pageIdx = ((PageIdUtils.pageIndex(pageId) - COUNT_OF_EXTRA_PAGE) /
             countOfPageToTrack(pageSize)) * countOfPageToTrack(pageSize) + 
COUNT_OF_EXTRA_PAGE;
 
-        long trackingPageId = PageIdUtils.pageId(PageIdUtils.partId(pageId), 
PageIdUtils.flag(pageId), pageIdx);
+        byte flag = PageIdUtils.partId(pageId) == 
PageIdAllocator.INDEX_PARTITION ?
+            PageIdAllocator.FLAG_IDX :
+            PageIdAllocator.FLAG_DATA;
+
+        long trackingPageId = PageIdUtils.pageId(PageIdUtils.partId(pageId), 
flag, pageIdx);
 
         assert PageIdUtils.pageIndex(trackingPageId) <= 
PageIdUtils.pageIndex(pageId);
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/reuse/ReuseList.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/reuse/ReuseList.java
index aaab186..d2a1ba0 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/reuse/ReuseList.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/reuse/ReuseList.java
@@ -18,6 +18,10 @@
 package org.apache.ignite.internal.processors.cache.persistence.tree.reuse;
 
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.pagemem.FullPageId;
+import org.apache.ignite.internal.pagemem.PageIdAllocator;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * Reuse list.
@@ -40,4 +44,18 @@ public interface ReuseList {
      * @throws IgniteCheckedException If failed.
      */
     public long recycledPagesCount() throws IgniteCheckedException;
+
+    /**
+     * Converts recycled page id back to a usable id. Might modify page 
content as well if flag is changing.
+     *
+     * @param pageId Id of the recycled page.
+     * @param flag Flag value for the page. One of {@link 
PageIdAllocator#FLAG_DATA}, {@link PageIdAllocator#FLAG_IDX}
+     *      or {@link PageIdAllocator#FLAG_AUX}.
+     * @param initIO Page IO to reinit reused page.
+     * @return Updated page id.
+     * @throws IgniteCheckedException If failed.
+     *
+     * @see FullPageId
+     */
+    long initRecycledPage(long pageId, byte flag, @Nullable PageIO initIO) 
throws IgniteCheckedException;
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/reuse/ReuseListImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/reuse/ReuseListImpl.java
index cf3897f..5d2789b 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/reuse/ReuseListImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/reuse/ReuseListImpl.java
@@ -25,6 +25,7 @@ import 
org.apache.ignite.internal.metric.IoStatisticsHolderNoOp;
 import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
 import 
org.apache.ignite.internal.processors.cache.persistence.freelist.PagesList;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
 import 
org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 
 /**
@@ -48,6 +49,7 @@ public class ReuseListImpl extends PagesList implements 
ReuseList {
      * @param wal       Write ahead log manager.
      * @param metaPageId Metadata page ID.
      * @param initNew {@code True} if new metadata should be initialized.
+     * @param pageFlag Default flag value for allocated pages.
      * @throws IgniteCheckedException If failed.
      */
     public ReuseListImpl(
@@ -59,7 +61,8 @@ public class ReuseListImpl extends PagesList implements 
ReuseList {
         boolean initNew,
         PageLockListener lockLsnr,
         GridKernalContext ctx,
-        AtomicLong pageListCacheLimit
+        AtomicLong pageListCacheLimit,
+        byte pageFlag
     ) throws IgniteCheckedException {
         super(
             cacheId,
@@ -69,7 +72,8 @@ public class ReuseListImpl extends PagesList implements 
ReuseList {
             wal,
             metaPageId,
             lockLsnr,
-            ctx
+            ctx,
+            pageFlag
         );
 
         bucketCache = new PagesCache(pageListCacheLimit);
@@ -97,6 +101,11 @@ public class ReuseListImpl extends PagesList implements 
ReuseList {
     }
 
     /** {@inheritDoc} */
+    @Override public long initRecycledPage(long pageId, byte flag, PageIO 
initIO) throws IgniteCheckedException {
+        return initRecycledPage0(pageId, flag, initIO);
+    }
+
+    /** {@inheritDoc} */
     @Override public long recycledPagesCount() throws IgniteCheckedException {
         return storedPagesCount(0);
     }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/CacheDataTree.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/CacheDataTree.java
index e9d652c..e9a88ba 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/CacheDataTree.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/CacheDataTree.java
@@ -84,6 +84,7 @@ public class CacheDataTree extends BPlusTree<CacheSearchRow, 
CacheDataRow> {
      * @param rowStore Row store.
      * @param metaPageId Meta page ID.
      * @param initNew Initialize new index.
+     * @param pageFlag Default flag value for allocated pages.
      * @throws IgniteCheckedException If failed.
      */
     public CacheDataTree(
@@ -93,7 +94,8 @@ public class CacheDataTree extends BPlusTree<CacheSearchRow, 
CacheDataRow> {
         CacheDataRowStore rowStore,
         long metaPageId,
         boolean initNew,
-        PageLockListener lockLsnr
+        PageLockListener lockLsnr,
+        byte pageFlag
     ) throws IgniteCheckedException {
         super(
             name,
@@ -106,6 +108,7 @@ public class CacheDataTree extends 
BPlusTree<CacheSearchRow, CacheDataRow> {
             reuseList,
             innerIO(grp),
             leafIO(grp),
+            pageFlag,
             grp.shared().kernalContext().failure(),
             lockLsnr
         );
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/PendingEntriesTree.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/PendingEntriesTree.java
index 9cfb2c6..6070aca 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/PendingEntriesTree.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/PendingEntriesTree.java
@@ -43,6 +43,7 @@ public class PendingEntriesTree extends BPlusTree<PendingRow, 
PendingRow> {
      * @param metaPageId Meta page ID.
      * @param reuseList Reuse list.
      * @param initNew Initialize new index.
+     * @param pageFlag Default flag value for allocated pages.
      * @throws IgniteCheckedException If failed.
      */
     public PendingEntriesTree(
@@ -52,7 +53,8 @@ public class PendingEntriesTree extends BPlusTree<PendingRow, 
PendingRow> {
         long metaPageId,
         ReuseList reuseList,
         boolean initNew,
-        PageLockListener lockLsnr
+        PageLockListener lockLsnr,
+        byte pageFlag
     ) throws IgniteCheckedException {
         super(
             name,
@@ -65,6 +67,7 @@ public class PendingEntriesTree extends BPlusTree<PendingRow, 
PendingRow> {
             reuseList,
             grp.sharedGroup() ? CacheIdAwarePendingEntryInnerIO.VERSIONS : 
PendingEntryInnerIO.VERSIONS,
             grp.sharedGroup() ? CacheIdAwarePendingEntryLeafIO.VERSIONS : 
PendingEntryLeafIO.VERSIONS,
+            pageFlag,
             grp.shared().kernalContext().failure(),
             lockLsnr
         );
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/verify/IdleVerifyUtility.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/verify/IdleVerifyUtility.java
index b93c122..c2ba3b1 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/verify/IdleVerifyUtility.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/verify/IdleVerifyUtility.java
@@ -25,7 +25,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.pagemem.PageIdAllocator;
@@ -43,6 +42,10 @@ import org.apache.ignite.internal.util.typedef.internal.SB;
 import org.apache.ignite.lang.IgniteInClosure;
 import org.jetbrains.annotations.Nullable;
 
+import static org.apache.ignite.internal.pagemem.PageIdAllocator.FLAG_AUX;
+import static org.apache.ignite.internal.pagemem.PageIdAllocator.FLAG_DATA;
+import static org.apache.ignite.internal.pagemem.PageIdAllocator.FLAG_IDX;
+
 /**
  * Utility class for idle verify command.
  */
@@ -75,7 +78,8 @@ public class IdleVerifyUtility {
      * @param pageStore Page store.
      * @param grpCtx Passed cache group context.
      * @param partId Partition id.
-     * @param pageType Page type. Possible types {@link 
PageIdAllocator#FLAG_DATA}, {@link PageIdAllocator#FLAG_IDX}.
+     * @param pageType Page type. Possible types {@link 
PageIdAllocator#FLAG_DATA}, {@link PageIdAllocator#FLAG_IDX}
+     *      and {@link PageIdAllocator#FLAG_AUX}.
      * @throws IgniteCheckedException If reading page failed.
      * @throws GridNotIdleException If cluster not idle.
      */
@@ -83,11 +87,11 @@ public class IdleVerifyUtility {
         FilePageStore pageStore,
         CacheGroupContext grpCtx,
         int partId,
-        byte pageType
+        @Deprecated byte pageType
     ) throws IgniteCheckedException, GridNotIdleException {
-        assert pageType == PageIdAllocator.FLAG_DATA || pageType == 
PageIdAllocator.FLAG_IDX : pageType;
+        assert pageType == FLAG_DATA || pageType == FLAG_IDX || pageType == 
FLAG_AUX : pageType;
 
-        long pageId = PageIdUtils.pageId(partId, pageType, 0);
+        long pageId = PageIdUtils.pageId(partId, (byte)0, 0);
 
         ByteBuffer buf = 
ByteBuffer.allocateDirect(grpCtx.dataRegion().pageMemory().pageSize());
 
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/metric/IoStatisticsMetricsLocalMXBeanImplSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/metric/IoStatisticsMetricsLocalMXBeanImplSelfTest.java
index 9f8a324..38a743a 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/metric/IoStatisticsMetricsLocalMXBeanImplSelfTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/metric/IoStatisticsMetricsLocalMXBeanImplSelfTest.java
@@ -123,7 +123,7 @@ public class IoStatisticsMetricsLocalMXBeanImplSelfTest 
extends GridCommonAbstra
 
         long cacheLogicalReadsCnt = 
mreg.<LongMetric>findMetric(LOGICAL_READS).value();
 
-        assertEquals(cnt, cacheLogicalReadsCnt);
+        assertEquals(cnt - 1, cacheLogicalReadsCnt); // 1 is for reuse bucket 
stripe.
 
         long cachePhysicalReadsCnt = 
mreg.<LongMetric>findMetric(PHYSICAL_READS).value();
 
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/pagemem/impl/PageIdUtilsSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/pagemem/impl/PageIdUtilsSelfTest.java
index 825c867..087b20c 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/pagemem/impl/PageIdUtilsSelfTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/pagemem/impl/PageIdUtilsSelfTest.java
@@ -18,7 +18,7 @@
 package org.apache.ignite.internal.pagemem.impl;
 
 import java.util.Random;
-
+import org.apache.ignite.internal.pagemem.PageIdAllocator;
 import org.apache.ignite.internal.pagemem.PageIdUtils;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
@@ -99,13 +99,15 @@ public class PageIdUtilsSelfTest extends 
GridCommonAbstractTest {
     @Test
     public void testPageIdFromLink() throws Exception {
         assertEquals(0x00FFFFFFFFFFFFFFL, 
PageIdUtils.pageId(0x00FFFFFFFFFFFFFFL));
-        assertEquals(0x00FFFFFFFFFFFFFFL, 
PageIdUtils.pageId(0x10FFFFFFFFFFFFFFL));
-        assertEquals(0x00FFFFFFFFFFFFFFL, 
PageIdUtils.pageId(0x01FFFFFFFFFFFFFFL));
-        assertEquals(0x00FFFFFFFFFFFFFFL, 
PageIdUtils.pageId(0x11FFFFFFFFFFFFFFL));
-        assertEquals(0x00FFFFFFFFFFFFFFL, 
PageIdUtils.pageId(0x80FFFFFFFFFFFFFFL));
-        assertEquals(0x00FFFFFFFFFFFFFFL, 
PageIdUtils.pageId(0x88FFFFFFFFFFFFFFL));
-        assertEquals(0x00FFFFFFFFFFFFFFL, 
PageIdUtils.pageId(0x08FFFFFFFFFFFFFFL));
-        assertEquals(0x00FFFFFFFFFFFFFFL, 
PageIdUtils.pageId(0xFFFFFFFFFFFFFFFFL));
+
+        assertEquals(0x0001FFFFFFFFFFFFL, 
PageIdUtils.pageId(0x0001FFFFFFFFFFFFL));
+        assertEquals(0x0001FFFFFFFFFFFFL, 
PageIdUtils.pageId(0x1001FFFFFFFFFFFFL));
+        assertEquals(0x0001FFFFFFFFFFFFL, 
PageIdUtils.pageId(0x0101FFFFFFFFFFFFL));
+        assertEquals(0x0001FFFFFFFFFFFFL, 
PageIdUtils.pageId(0x1101FFFFFFFFFFFFL));
+        assertEquals(0x0001FFFFFFFFFFFFL, 
PageIdUtils.pageId(0x8001FFFFFFFFFFFFL));
+        assertEquals(0x0001FFFFFFFFFFFFL, 
PageIdUtils.pageId(0x8801FFFFFFFFFFFFL));
+        assertEquals(0x0001FFFFFFFFFFFFL, 
PageIdUtils.pageId(0x0801FFFFFFFFFFFFL));
+        assertEquals(0x0001FFFFFFFFFFFFL, 
PageIdUtils.pageId(0xFF01FFFFFFFFFFFFL));
 
         assertEquals(0x0002FFFFFFFFFFFFL, 
PageIdUtils.pageId(0x0002FFFFFFFFFFFFL));
         assertEquals(0x1002FFFFFFFFFFFFL, 
PageIdUtils.pageId(0x1002FFFFFFFFFFFFL));
@@ -116,12 +118,21 @@ public class PageIdUtilsSelfTest extends 
GridCommonAbstractTest {
         assertEquals(0x0802FFFFFFFFFFFFL, 
PageIdUtils.pageId(0x0802FFFFFFFFFFFFL));
         assertEquals(0xFF02FFFFFFFFFFFFL, 
PageIdUtils.pageId(0xFF02FFFFFFFFFFFFL));
 
-        assertEquals(0L, PageIdUtils.pageId(0x0000000000000000L));
-        assertEquals(0L, PageIdUtils.pageId(0x1000000000000000L));
-        assertEquals(0L, PageIdUtils.pageId(0x0100000000000000L));
-        assertEquals(0L, PageIdUtils.pageId(0x8000000000000000L));
-        assertEquals(0L, PageIdUtils.pageId(0x0800000000000000L));
-        assertEquals(0L, PageIdUtils.pageId(0xFF00000000000000L));
+        assertEquals(0x0004FFFFFFFFFFFFL, 
PageIdUtils.pageId(0x0004FFFFFFFFFFFFL));
+        assertEquals(0x1004FFFFFFFFFFFFL, 
PageIdUtils.pageId(0x1004FFFFFFFFFFFFL));
+        assertEquals(0x0104FFFFFFFFFFFFL, 
PageIdUtils.pageId(0x0104FFFFFFFFFFFFL));
+        assertEquals(0x1104FFFFFFFFFFFFL, 
PageIdUtils.pageId(0x1104FFFFFFFFFFFFL));
+        assertEquals(0x8004FFFFFFFFFFFFL, 
PageIdUtils.pageId(0x8004FFFFFFFFFFFFL));
+        assertEquals(0x8804FFFFFFFFFFFFL, 
PageIdUtils.pageId(0x8804FFFFFFFFFFFFL));
+        assertEquals(0x0804FFFFFFFFFFFFL, 
PageIdUtils.pageId(0x0804FFFFFFFFFFFFL));
+        assertEquals(0xFF04FFFFFFFFFFFFL, 
PageIdUtils.pageId(0xFF04FFFFFFFFFFFFL));
+
+        assertEquals(0x0000000000000000L, 
PageIdUtils.pageId(0x0000000000000000L));
+        assertEquals(0x1000000000000000L, 
PageIdUtils.pageId(0x1000000000000000L));
+        assertEquals(0x0100000000000000L, 
PageIdUtils.pageId(0x0100000000000000L));
+        assertEquals(0x8000000000000000L, 
PageIdUtils.pageId(0x8000000000000000L));
+        assertEquals(0x0800000000000000L, 
PageIdUtils.pageId(0x0800000000000000L));
+        assertEquals(0xFF00000000000000L, 
PageIdUtils.pageId(0xFF00000000000000L));
     }
 
     /**
@@ -136,7 +147,7 @@ public class PageIdUtilsSelfTest extends 
GridCommonAbstractTest {
             int partId = rnd.nextInt(PageIdUtils.MAX_PART_ID + 1);
             int pageNum = rnd.nextInt();
 
-            long pageId = PageIdUtils.pageId(partId, (byte) 0, pageNum);
+            long pageId = PageIdUtils.pageId(partId, 
PageIdAllocator.FLAG_DATA, pageNum);
 
             String msg = "For values [offset=" + U.hexLong(off) + ", fileId=" 
+ U.hexLong(partId) +
                 ", pageNum=" + U.hexLong(pageNum) + ']';
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/PendingTreeCorruptionTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/PendingTreeCorruptionTest.java
new file mode 100644
index 0000000..7a748e3
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/PendingTreeCorruptionTest.java
@@ -0,0 +1,159 @@
+/*
+ * 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.processors.cache.persistence;
+
+import java.util.concurrent.TimeUnit;
+import javax.cache.expiry.AccessedExpiryPolicy;
+import javax.cache.expiry.Duration;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cluster.ClusterState;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.processors.cache.CacheGroupContext;
+import org.apache.ignite.internal.processors.cache.IgniteCacheOffheapManager;
+import 
org.apache.ignite.internal.processors.cache.IgniteCacheOffheapManagerImpl;
+import org.apache.ignite.internal.processors.cache.tree.PendingEntriesTree;
+import org.apache.ignite.internal.processors.cache.tree.PendingRow;
+import org.apache.ignite.internal.util.lang.GridCursor;
+import org.apache.ignite.internal.util.typedef.internal.CU;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+
+/** */
+public class PendingTreeCorruptionTest extends GridCommonAbstractTest {
+    /** */
+    @Before
+    public void before() throws Exception {
+        stopAllGrids();
+
+        cleanPersistenceDir();
+    }
+
+    /** */
+    @After
+    public void after() throws Exception {
+        stopAllGrids();
+
+        cleanPersistenceDir();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String 
igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setConsistentId(igniteInstanceName);
+
+        cfg.setDataStorageConfiguration(new DataStorageConfiguration()
+            .setDefaultDataRegionConfiguration(new DataRegionConfiguration()
+                .setPersistenceEnabled(true)
+            )
+            .setWalSegments(3)
+            .setWalSegmentSize(512 * 1024)
+        );
+
+        return cfg;
+    }
+
+    /** */
+    @Test
+    public void testCorruptionWhileLoadingData() throws Exception {
+        IgniteEx ig = startGrid(0);
+
+        ig.cluster().state(ClusterState.ACTIVE);
+
+        String expireCacheName = "cacheWithExpire";
+        String regularCacheName = "cacheWithoutExpire";
+        String grpName = "cacheGroup";
+
+        IgniteCache<Object, Object> expireCache = ig.getOrCreateCache(
+            new CacheConfiguration<>(expireCacheName)
+                .setExpiryPolicyFactory(AccessedExpiryPolicy.factoryOf(new 
Duration(MINUTES, 10)))
+                .setGroupName(grpName)
+        );
+
+        IgniteCache<Object, Object> regularCache = ig.getOrCreateCache(
+            new CacheConfiguration<>(regularCacheName)
+                .setGroupName(grpName)
+        );
+
+        // This will initialize partition and cache structures.
+        expireCache.put(0, 0);
+        expireCache.remove(0);
+
+        int expireCacheId = CU.cacheGroupId(expireCacheName, grpName);
+
+        CacheGroupContext grp = 
ig.context().cache().cacheGroup(CU.cacheId(grpName));
+        IgniteCacheOffheapManager.CacheDataStore store = 
((IgniteCacheOffheapManagerImpl)grp.offheap()).dataStore(0);
+
+        // Get pending tree of expire cache.
+        PendingEntriesTree pendingTree = store.pendingTree();
+
+        long year = TimeUnit.DAYS.toMillis(365);
+        long expiration = System.currentTimeMillis() + year;
+
+        ig.context().cache().context().database().checkpointReadLock();
+
+        try {
+            // Carefully calculated number. Just enough for the first split to 
happen, but not more.
+            for (int i = 0; i < 202; i++)
+                pendingTree.putx(new PendingRow(expireCacheId, expiration, 
expiration + i)); // link != 0
+
+            // Open cursor, it'll cache first leaf of the tree.
+            GridCursor<PendingRow> cur = pendingTree.find(
+                null,
+                new PendingRow(expireCacheId, expiration + year, 0),
+                PendingEntriesTree.WITHOUT_KEY
+            );
+
+            // Required for "do" loop to work.
+            assertTrue(cur.next());
+
+            int cnt = 0;
+
+            // Emulate real expiry loop but with a more precise control.
+            do {
+                PendingRow row = cur.get();
+
+                pendingTree.removex(row);
+
+                // Another carefully calculated moment. Here the page cache is 
exhausted AND the real page is merged
+                // with its sibling, meaning that cached "nextPageId" points 
to empty page from reuse list.
+                if (row.link - row.expireTime == 100) {
+                    // Put into another cache will take a page from reuse list 
first. This means that cached
+                    // "nextPageId" points to a data page.
+                    regularCache.put(0, 0);
+                }
+
+                cnt++;
+            }
+            while (cur.next());
+
+            assertEquals(202, cnt);
+        }
+        finally {
+            ig.context().cache().context().database().checkpointReadUnlock();
+        }
+    }
+}
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/CheckpointBufferDeadlockTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/CheckpointBufferDeadlockTest.java
index 660c7ff..ca808ad 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/CheckpointBufferDeadlockTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/CheckpointBufferDeadlockTest.java
@@ -51,6 +51,7 @@ import 
org.apache.ignite.internal.processors.cache.persistence.file.FileIOFactor
 import 
org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager;
 import 
org.apache.ignite.internal.processors.cache.persistence.file.RandomAccessFileIOFactory;
 import 
org.apache.ignite.internal.processors.cache.persistence.pagemem.PageMemoryImpl;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
 import org.apache.ignite.internal.util.typedef.internal.CU;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.ListeningTestLogger;
@@ -236,6 +237,17 @@ public class CheckpointBufferDeadlockTest extends 
GridCommonAbstractTest {
 
                             long pageId = PageIdUtils.pageId(0, 
PageIdAllocator.FLAG_DATA, pageIdx);
 
+                            long page = 
pageMem.acquirePage(CU.cacheId(cacheName), pageId);
+
+                            try {
+                                // We do not know correct flag(FLAG_DATA or 
FLAG_AUX). Skip page if no luck.
+                                if (pageId != PageIO.getPageId(page + 
PageMemoryImpl.PAGE_OVERHEAD))
+                                    continue;
+                            }
+                            finally {
+                                pageMem.releasePage(CU.cacheId(cacheName), 
pageId, page);
+                            }
+
                             pickedPagesSet.add(new FullPageId(pageId, 
CU.cacheId(cacheName)));
                         }
 
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeFakeReuseSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeFakeReuseSelfTest.java
index cab54a4..db00de3 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeFakeReuseSelfTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeFakeReuseSelfTest.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.processors.database;
 import java.util.concurrent.ConcurrentLinkedDeque;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.pagemem.PageMemory;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
 import 
org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseBag;
 import 
org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
 
@@ -59,5 +60,10 @@ public class BPlusTreeFakeReuseSelfTest extends 
BPlusTreeSelfTest {
         @Override public long recycledPagesCount() throws 
IgniteCheckedException {
             return deque.size();
         }
+
+        /** {@inheritDoc} */
+        @Override public long initRecycledPage(long pageId, byte flag, PageIO 
initIO) throws IgniteCheckedException {
+            return pageId;
+        }
     }
 }
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeReuseSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeReuseSelfTest.java
index 8d50fad..94b3db6 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeReuseSelfTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeReuseSelfTest.java
@@ -21,6 +21,7 @@ import java.util.HashSet;
 import java.util.Set;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.pagemem.PageIdAllocator;
 import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
@@ -83,7 +84,7 @@ public class BPlusTreeReuseSelfTest extends BPlusTreeSelfTest 
{
             boolean initNew,
             GridKernalContext ctx
         ) throws IgniteCheckedException {
-            super(cacheId, name, pageMem, wal, metaPageId, initNew, new 
TestPageLockListener(), ctx, null);
+            super(cacheId, name, pageMem, wal, metaPageId, initNew, new 
TestPageLockListener(), ctx, null, PageIdAllocator.FLAG_IDX);
         }
 
         /**
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java
index 82f11ad..9465dc7 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java
@@ -2773,6 +2773,7 @@ public class BPlusTreeSelfTest extends 
GridCommonAbstractTest {
                 reuseList,
                 new IOVersions<>(new LongInnerIO(canGetRow)),
                 new IOVersions<>(new LongLeafIO()),
+                PageIdAllocator.FLAG_IDX,
                 new FailureProcessor(new GridTestKernalContext(log)) {
                     @Override public boolean process(FailureContext 
failureCtx) {
                         lockTrackerManager.dumpLocksToLog();
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/CacheFreeListSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/CacheFreeListSelfTest.java
index a6ce732..1c0f33d 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/CacheFreeListSelfTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/CacheFreeListSelfTest.java
@@ -530,7 +530,8 @@ public class CacheFreeListSelfTest extends 
GridCommonAbstractTest {
             true,
             null,
             new GridTestKernalContext(log),
-            null
+            null,
+            PageIdAllocator.FLAG_IDX
         );
     }
 
diff --git 
a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite4.java
 
b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite4.java
index dfca746..be885e0 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite4.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite4.java
@@ -40,6 +40,7 @@ import 
org.apache.ignite.internal.processors.cache.persistence.IgnitePdsRemoveDu
 import 
org.apache.ignite.internal.processors.cache.persistence.IgnitePdsRestartAfterFailedToWriteMetaPageTest;
 import 
org.apache.ignite.internal.processors.cache.persistence.IgnitePdsSpuriousRebalancingOnNodeJoinTest;
 import 
org.apache.ignite.internal.processors.cache.persistence.IgnitePdsTaskCancelingTest;
+import 
org.apache.ignite.internal.processors.cache.persistence.PendingTreeCorruptionTest;
 import 
org.apache.ignite.internal.processors.cache.persistence.db.IgnitePdsCacheWalDisabledOnRebalancingTest;
 import 
org.apache.ignite.internal.processors.cache.persistence.db.IgnitePdsPageReplacementDuringPartitionClearTest;
 import 
org.apache.ignite.internal.processors.cache.persistence.db.IgnitePdsPartitionPreloadTest;
@@ -121,6 +122,8 @@ public class IgnitePdsTestSuite4 {
         GridTestUtils.addTestIfNeeded(suite, WarmUpSelfTest.class, 
ignoredTests);
         GridTestUtils.addTestIfNeeded(suite, 
LoadAllWarmUpStrategySelfTest.class, ignoredTests);
 
+        GridTestUtils.addTestIfNeeded(suite, PendingTreeCorruptionTest.class, 
ignoredTests);
+
         return suite;
     }
 
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index 7a31059..0ded892 100644
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -60,6 +60,7 @@ import 
org.apache.ignite.internal.managers.communication.GridMessageListener;
 import org.apache.ignite.internal.managers.eventstorage.GridLocalEventListener;
 import org.apache.ignite.internal.mxbean.SqlQueryMXBean;
 import org.apache.ignite.internal.mxbean.SqlQueryMXBeanImpl;
+import org.apache.ignite.internal.pagemem.PageIdAllocator;
 import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.pagemem.store.IgnitePageStoreManager;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
@@ -2447,6 +2448,7 @@ public class IgniteH2Indexing implements 
GridQueryIndexing {
             reuseList,
             H2ExtrasInnerIO.getVersions(inlineSize, mvccEnabled),
             H2ExtrasLeafIO.getVersions(inlineSize, mvccEnabled),
+            PageIdAllocator.FLAG_IDX,
             ctx.failure(),
             lockLsnr
         ) {
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java
index 9c6ca13..99a0add 100644
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java
+++ 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java
@@ -30,6 +30,7 @@ import org.apache.ignite.SystemProperty;
 import org.apache.ignite.failure.FailureType;
 import org.apache.ignite.internal.metric.IoStatisticsHolder;
 import org.apache.ignite.internal.pagemem.FullPageId;
+import org.apache.ignite.internal.pagemem.PageIdAllocator;
 import org.apache.ignite.internal.pagemem.PageIdUtils;
 import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
@@ -221,6 +222,7 @@ public class H2Tree extends BPlusTree<H2Row, H2Row> {
             globalRmvId,
             metaPageId,
             reuseList,
+            PageIdAllocator.FLAG_IDX,
             failureProcessor,
             null,
             pageIoRslvr

Reply via email to