ibessonov commented on code in PR #920:
URL: https://github.com/apache/ignite-3/pull/920#discussion_r923052401


##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PartitionMeta.java:
##########
@@ -17,33 +17,54 @@
 
 package org.apache.ignite.internal.pagememory.persistence;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
 import org.apache.ignite.internal.tostring.S;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * Partition meta information.
  */
 public class PartitionMeta {
+    private static final AtomicIntegerFieldUpdater<PartitionMeta> 
PAGE_COUNT_UPDATER = AtomicIntegerFieldUpdater.newUpdater(

Review Comment:
   You can use VarHandle here as well



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PartitionMeta.java:
##########
@@ -86,24 +113,89 @@ public int pageCount() {
     }
 
     /**
-     * Sets count of pages in the partition.
-     *
-     * @param pageCount Count of pages in the partition.
+     * Increases the number of pages in a partition.
      */
-    public void pageCount(int pageCount) {
-        this.pageCount = pageCount;
+    public void incrementPageCount(@Nullable UUID checkpointId) {
+        updateSnapshot(checkpointId);
+
+        PAGE_COUNT_UPDATER.incrementAndGet(this);
     }
 
     /**
-     * Returns {@code true} if the partition meta was created, {@code false} 
if it was read from a partition file.
+     * Returns the latest snapshot of the partition meta.
+     *
+     * @param checkpointId Checkpoint ID.
      */
-    public boolean isCreated() {
-        return created;
+    public PartitionMetaSnapshot metaSnapshot(@Nullable UUID checkpointId) {
+        updateSnapshot(checkpointId);
+
+        return metaSnapshot;
+    }
+
+    private void updateSnapshot(@Nullable UUID checkpointId) {

Review Comment:
   This method deserves a comment as well



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PartitionMeta.java:
##########
@@ -86,24 +113,89 @@ public int pageCount() {
     }
 
     /**
-     * Sets count of pages in the partition.
-     *
-     * @param pageCount Count of pages in the partition.
+     * Increases the number of pages in a partition.
      */
-    public void pageCount(int pageCount) {
-        this.pageCount = pageCount;
+    public void incrementPageCount(@Nullable UUID checkpointId) {
+        updateSnapshot(checkpointId);
+
+        PAGE_COUNT_UPDATER.incrementAndGet(this);
     }
 
     /**
-     * Returns {@code true} if the partition meta was created, {@code false} 
if it was read from a partition file.
+     * Returns the latest snapshot of the partition meta.
+     *
+     * @param checkpointId Checkpoint ID.
      */
-    public boolean isCreated() {
-        return created;
+    public PartitionMetaSnapshot metaSnapshot(@Nullable UUID checkpointId) {
+        updateSnapshot(checkpointId);
+
+        return metaSnapshot;
+    }
+
+    private void updateSnapshot(@Nullable UUID checkpointId) {
+        PartitionMetaSnapshot current = this.metaSnapshot;
+
+        if (current.checkpointId != checkpointId) {
+            META_SNAPSHOT_VH.compareAndSet(this, current, new 
PartitionMetaSnapshot(checkpointId, this));

Review Comment:
   I believe that conventional name for var handle would be "META_SNAPSHOT", 
please rename it



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PartitionMeta.java:
##########
@@ -17,33 +17,54 @@
 
 package org.apache.ignite.internal.pagememory.persistence;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
 import org.apache.ignite.internal.tostring.S;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * Partition meta information.
  */
 public class PartitionMeta {
+    private static final AtomicIntegerFieldUpdater<PartitionMeta> 
PAGE_COUNT_UPDATER = AtomicIntegerFieldUpdater.newUpdater(
+            PartitionMeta.class,
+            "pageCount"
+    );
+
+    private static final VarHandle META_SNAPSHOT_VH;
+
+    static {
+        try {
+            META_SNAPSHOT_VH = 
MethodHandles.lookup().findVarHandle(PartitionMeta.class, "metaSnapshot", 
PartitionMetaSnapshot.class);
+        } catch (ReflectiveOperationException e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
+
     private volatile long treeRootPageId;
 
     private volatile long reuseListRootPageId;
 
     private volatile int pageCount;
 
-    private final boolean created;
+    private volatile PartitionMetaSnapshot metaSnapshot;
 
     /**
      * Constructor.
      *
+     * @param checkpointId Checkpoint ID.
      * @param treeRootPageId Tree root page ID.
      * @param reuseListRootPageId Reuse list root page ID.
      * @param pageCount Count of pages in the partition.
-     * @param created {@code True} if the partition meta was created, {@code 
false} if it was read from a partition file.
      */
-    public PartitionMeta(long treeRootPageId, long reuseListRootPageId, int 
pageCount, boolean created) {
+    public PartitionMeta(@Nullable UUID checkpointId, long treeRootPageId, 
long reuseListRootPageId, int pageCount) {

Review Comment:
   Why is "checkpointId" nullable? It can be null only on initialization, 
right? We could just use (0, 0) in that case



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PartitionMetaManager.java:
##########
@@ -0,0 +1,168 @@
+/*
+ * 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.pagememory.persistence;
+
+import static org.apache.ignite.internal.util.GridUnsafe.allocateBuffer;
+import static org.apache.ignite.internal.util.GridUnsafe.bufferAddress;
+import static org.apache.ignite.internal.util.GridUnsafe.freeBuffer;
+
+import java.nio.ByteBuffer;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.ignite.internal.pagememory.io.PageIoRegistry;
+import 
org.apache.ignite.internal.pagememory.persistence.PartitionMeta.PartitionMetaSnapshot;
+import org.apache.ignite.internal.pagememory.persistence.io.PartitionMetaIo;
+import org.apache.ignite.internal.pagememory.persistence.store.FilePageStore;
+import org.apache.ignite.lang.IgniteInternalCheckedException;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Partition meta information manager.
+ */
+// TODO: IGNITE-17132 Do not forget about deleting the partition meta 
information
+public class PartitionMetaManager {
+    private final Map<GroupPartitionId, PartitionMeta> metas = new 
ConcurrentHashMap<>();
+
+    private final PageIoRegistry ioRegistry;
+
+    private final int pageSize;
+
+    /**
+     * Constructor.
+     *
+     * @param ioRegistry Page IO Registry.
+     * @param pageSize Page size in bytes.
+     */
+    public PartitionMetaManager(PageIoRegistry ioRegistry, int pageSize) {
+        this.ioRegistry = ioRegistry;
+        this.pageSize = pageSize;
+    }
+
+    /**
+     * Returns the partition's meta information.
+     *
+     * @param groupPartitionId Partition of the group.
+     */
+    public @Nullable PartitionMeta getMeta(GroupPartitionId groupPartitionId) {
+        return metas.get(groupPartitionId);
+    }
+
+    /**
+     * Adds partition meta information.
+     *
+     * @param groupPartitionId Partition of the group.
+     * @param partitionMeta Partition meta information.
+     */
+    public void addMeta(GroupPartitionId groupPartitionId, PartitionMeta 
partitionMeta) {
+        metas.put(groupPartitionId, partitionMeta);
+    }
+
+    /**
+     * Reads the partition {@link PartitionMeta meta} from the partition file 
or creates a new one.
+     *
+     * <p>If it creates a new one, it writes the meta to the file.
+     *
+     * @param checkpointId Checkpoint ID.
+     * @param groupPartitionId Partition of the group.
+     * @param pageMemory Page memory.
+     * @param filePageStore Partition file page store.
+     */
+    public PartitionMeta readOrCreateMeta(
+            @Nullable UUID checkpointId,
+            GroupPartitionId groupPartitionId,
+            PersistentPageMemory pageMemory,
+            FilePageStore filePageStore
+    ) throws IgniteInternalCheckedException {
+        ByteBuffer buffer = allocateBuffer(pageSize);
+
+        long bufferAddr = bufferAddress(buffer);
+
+        long partitionMetaPageId = 
pageMemory.partitionMetaPageId(groupPartitionId.getGroupId(), 
groupPartitionId.getPartitionId());
+
+        try {
+            if (filePageStore.size() > filePageStore.headerSize()) {
+                // Reads the partition meta.
+                if (filePageStore.pages() == 0) {

Review Comment:
   I don't get it, what's happening here? We need a better comment or even 
changing this code. Looks like a dangerous workaround



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/checkpoint/CheckpointDirtyPages.java:
##########
@@ -108,33 +100,54 @@ public 
IgniteConcurrentMultiPairQueue<PersistentPageMemory, GroupPartitionId> to
      * @param partId Partition ID.
      */
     public @Nullable CheckpointDirtyPagesView findView(int grpId, int partId) {

Review Comment:
   I see that you have not renamed this method. "View" is a very general term



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PartitionMetaManager.java:
##########
@@ -0,0 +1,168 @@
+/*
+ * 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.pagememory.persistence;
+
+import static org.apache.ignite.internal.util.GridUnsafe.allocateBuffer;
+import static org.apache.ignite.internal.util.GridUnsafe.bufferAddress;
+import static org.apache.ignite.internal.util.GridUnsafe.freeBuffer;
+
+import java.nio.ByteBuffer;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.ignite.internal.pagememory.io.PageIoRegistry;
+import 
org.apache.ignite.internal.pagememory.persistence.PartitionMeta.PartitionMetaSnapshot;
+import org.apache.ignite.internal.pagememory.persistence.io.PartitionMetaIo;
+import org.apache.ignite.internal.pagememory.persistence.store.FilePageStore;
+import org.apache.ignite.lang.IgniteInternalCheckedException;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Partition meta information manager.
+ */
+// TODO: IGNITE-17132 Do not forget about deleting the partition meta 
information
+public class PartitionMetaManager {
+    private final Map<GroupPartitionId, PartitionMeta> metas = new 
ConcurrentHashMap<>();
+
+    private final PageIoRegistry ioRegistry;
+
+    private final int pageSize;
+
+    /**
+     * Constructor.
+     *
+     * @param ioRegistry Page IO Registry.
+     * @param pageSize Page size in bytes.
+     */
+    public PartitionMetaManager(PageIoRegistry ioRegistry, int pageSize) {
+        this.ioRegistry = ioRegistry;
+        this.pageSize = pageSize;
+    }
+
+    /**
+     * Returns the partition's meta information.
+     *
+     * @param groupPartitionId Partition of the group.
+     */
+    public @Nullable PartitionMeta getMeta(GroupPartitionId groupPartitionId) {
+        return metas.get(groupPartitionId);
+    }
+
+    /**
+     * Adds partition meta information.
+     *
+     * @param groupPartitionId Partition of the group.
+     * @param partitionMeta Partition meta information.
+     */
+    public void addMeta(GroupPartitionId groupPartitionId, PartitionMeta 
partitionMeta) {
+        metas.put(groupPartitionId, partitionMeta);
+    }
+
+    /**
+     * Reads the partition {@link PartitionMeta meta} from the partition file 
or creates a new one.
+     *
+     * <p>If it creates a new one, it writes the meta to the file.
+     *
+     * @param checkpointId Checkpoint ID.
+     * @param groupPartitionId Partition of the group.
+     * @param pageMemory Page memory.
+     * @param filePageStore Partition file page store.
+     */
+    public PartitionMeta readOrCreateMeta(
+            @Nullable UUID checkpointId,
+            GroupPartitionId groupPartitionId,
+            PersistentPageMemory pageMemory,
+            FilePageStore filePageStore
+    ) throws IgniteInternalCheckedException {
+        ByteBuffer buffer = allocateBuffer(pageSize);
+
+        long bufferAddr = bufferAddress(buffer);
+
+        long partitionMetaPageId = 
pageMemory.partitionMetaPageId(groupPartitionId.getGroupId(), 
groupPartitionId.getPartitionId());
+
+        try {
+            if (filePageStore.size() > filePageStore.headerSize()) {
+                // Reads the partition meta.
+                if (filePageStore.pages() == 0) {
+                    filePageStore.pages(1);
+                }
+
+                boolean read = filePageStore.read(partitionMetaPageId, buffer, 
false);
+
+                assert read : filePageStore.filePath();
+
+                return createMeta(ioRegistry.resolve(bufferAddr), bufferAddr, 
checkpointId);
+            } else {
+                // Creates and writes a partition meta.
+                PartitionMetaIo partitionMetaIo = 
PartitionMetaIo.VERSIONS.latest();
+                partitionMetaIo.initNewPage(bufferAddr, partitionMetaPageId, 
pageSize);
+
+                // Because we will now write this page.
+                partitionMetaIo.setPageCount(bufferAddr, 1);
+
+                filePageStore.pages(1);
+
+                filePageStore.write(partitionMetaPageId, buffer.rewind(), 
true);
+
+                filePageStore.sync();
+
+                return createMeta(partitionMetaIo, bufferAddr, checkpointId);
+            }
+        } finally {
+            freeBuffer(buffer);
+        }
+    }
+
+    /**
+     * Writes the partition meta to the buffer.
+     *
+     * @param groupPartitionId Partition of the group.
+     * @param pageMemory Page memory.
+     * @param partitionMeta Snapshot of the partition meta.
+     * @param writeToBuffer Direct byte buffer to write partition meta.
+     */
+    public void writeMetaToBuffer(
+            GroupPartitionId groupPartitionId,
+            PersistentPageMemory pageMemory,
+            PartitionMetaSnapshot partitionMeta,
+            ByteBuffer writeToBuffer
+    ) {
+        assert writeToBuffer.remaining() == pageSize : 
writeToBuffer.remaining();
+
+        long partitionMetaPageId = 
pageMemory.partitionMetaPageId(groupPartitionId.getGroupId(), 
groupPartitionId.getPartitionId());
+
+        long pageAddr = bufferAddress(writeToBuffer);
+
+        PartitionMetaIo io = PartitionMetaIo.VERSIONS.latest();
+
+        io.initNewPage(pageAddr, partitionMetaPageId, pageSize);
+
+        io.setTreeRootPageId(pageAddr, partitionMeta.treeRootPageId());

Review Comment:
   I already asked you to encapsulate such lists of calls



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PartitionMetaManager.java:
##########
@@ -0,0 +1,168 @@
+/*
+ * 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.pagememory.persistence;
+
+import static org.apache.ignite.internal.util.GridUnsafe.allocateBuffer;
+import static org.apache.ignite.internal.util.GridUnsafe.bufferAddress;
+import static org.apache.ignite.internal.util.GridUnsafe.freeBuffer;
+
+import java.nio.ByteBuffer;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.ignite.internal.pagememory.io.PageIoRegistry;
+import 
org.apache.ignite.internal.pagememory.persistence.PartitionMeta.PartitionMetaSnapshot;
+import org.apache.ignite.internal.pagememory.persistence.io.PartitionMetaIo;
+import org.apache.ignite.internal.pagememory.persistence.store.FilePageStore;
+import org.apache.ignite.lang.IgniteInternalCheckedException;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Partition meta information manager.
+ */
+// TODO: IGNITE-17132 Do not forget about deleting the partition meta 
information
+public class PartitionMetaManager {
+    private final Map<GroupPartitionId, PartitionMeta> metas = new 
ConcurrentHashMap<>();
+
+    private final PageIoRegistry ioRegistry;
+
+    private final int pageSize;
+
+    /**
+     * Constructor.
+     *
+     * @param ioRegistry Page IO Registry.
+     * @param pageSize Page size in bytes.
+     */
+    public PartitionMetaManager(PageIoRegistry ioRegistry, int pageSize) {
+        this.ioRegistry = ioRegistry;
+        this.pageSize = pageSize;
+    }
+
+    /**
+     * Returns the partition's meta information.
+     *
+     * @param groupPartitionId Partition of the group.
+     */
+    public @Nullable PartitionMeta getMeta(GroupPartitionId groupPartitionId) {
+        return metas.get(groupPartitionId);
+    }
+
+    /**
+     * Adds partition meta information.
+     *
+     * @param groupPartitionId Partition of the group.
+     * @param partitionMeta Partition meta information.
+     */
+    public void addMeta(GroupPartitionId groupPartitionId, PartitionMeta 
partitionMeta) {
+        metas.put(groupPartitionId, partitionMeta);
+    }
+
+    /**
+     * Reads the partition {@link PartitionMeta meta} from the partition file 
or creates a new one.
+     *
+     * <p>If it creates a new one, it writes the meta to the file.
+     *
+     * @param checkpointId Checkpoint ID.
+     * @param groupPartitionId Partition of the group.
+     * @param pageMemory Page memory.
+     * @param filePageStore Partition file page store.
+     */
+    public PartitionMeta readOrCreateMeta(
+            @Nullable UUID checkpointId,
+            GroupPartitionId groupPartitionId,
+            PersistentPageMemory pageMemory,
+            FilePageStore filePageStore
+    ) throws IgniteInternalCheckedException {
+        ByteBuffer buffer = allocateBuffer(pageSize);
+
+        long bufferAddr = bufferAddress(buffer);
+
+        long partitionMetaPageId = 
pageMemory.partitionMetaPageId(groupPartitionId.getGroupId(), 
groupPartitionId.getPartitionId());
+
+        try {
+            if (filePageStore.size() > filePageStore.headerSize()) {
+                // Reads the partition meta.
+                if (filePageStore.pages() == 0) {
+                    filePageStore.pages(1);
+                }
+
+                boolean read = filePageStore.read(partitionMetaPageId, buffer, 
false);
+
+                assert read : filePageStore.filePath();
+
+                return createMeta(ioRegistry.resolve(bufferAddr), bufferAddr, 
checkpointId);
+            } else {
+                // Creates and writes a partition meta.
+                PartitionMetaIo partitionMetaIo = 
PartitionMetaIo.VERSIONS.latest();
+                partitionMetaIo.initNewPage(bufferAddr, partitionMetaPageId, 
pageSize);
+
+                // Because we will now write this page.
+                partitionMetaIo.setPageCount(bufferAddr, 1);
+
+                filePageStore.pages(1);
+
+                filePageStore.write(partitionMetaPageId, buffer.rewind(), 
true);
+
+                filePageStore.sync();
+
+                return createMeta(partitionMetaIo, bufferAddr, checkpointId);
+            }
+        } finally {
+            freeBuffer(buffer);
+        }
+    }
+
+    /**
+     * Writes the partition meta to the buffer.
+     *
+     * @param groupPartitionId Partition of the group.
+     * @param pageMemory Page memory.
+     * @param partitionMeta Snapshot of the partition meta.
+     * @param writeToBuffer Direct byte buffer to write partition meta.
+     */
+    public void writeMetaToBuffer(
+            GroupPartitionId groupPartitionId,
+            PersistentPageMemory pageMemory,
+            PartitionMetaSnapshot partitionMeta,
+            ByteBuffer writeToBuffer
+    ) {
+        assert writeToBuffer.remaining() == pageSize : 
writeToBuffer.remaining();
+
+        long partitionMetaPageId = 
pageMemory.partitionMetaPageId(groupPartitionId.getGroupId(), 
groupPartitionId.getPartitionId());
+
+        long pageAddr = bufferAddress(writeToBuffer);
+
+        PartitionMetaIo io = PartitionMetaIo.VERSIONS.latest();
+
+        io.initNewPage(pageAddr, partitionMetaPageId, pageSize);
+
+        io.setTreeRootPageId(pageAddr, partitionMeta.treeRootPageId());
+        io.setReuseListRootPageId(pageAddr, 
partitionMeta.reuseListRootPageId());
+        io.setPageCount(pageAddr, partitionMeta.pageCount());
+    }
+
+    private PartitionMeta createMeta(PartitionMetaIo metaIo, long pageAddr, 
@Nullable UUID checkpointId) {
+        return new PartitionMeta(

Review Comment:
   Same here



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PartitionMetaManager.java:
##########
@@ -0,0 +1,168 @@
+/*
+ * 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.pagememory.persistence;
+
+import static org.apache.ignite.internal.util.GridUnsafe.allocateBuffer;
+import static org.apache.ignite.internal.util.GridUnsafe.bufferAddress;
+import static org.apache.ignite.internal.util.GridUnsafe.freeBuffer;
+
+import java.nio.ByteBuffer;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.ignite.internal.pagememory.io.PageIoRegistry;
+import 
org.apache.ignite.internal.pagememory.persistence.PartitionMeta.PartitionMetaSnapshot;
+import org.apache.ignite.internal.pagememory.persistence.io.PartitionMetaIo;
+import org.apache.ignite.internal.pagememory.persistence.store.FilePageStore;
+import org.apache.ignite.lang.IgniteInternalCheckedException;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Partition meta information manager.
+ */
+// TODO: IGNITE-17132 Do not forget about deleting the partition meta 
information
+public class PartitionMetaManager {
+    private final Map<GroupPartitionId, PartitionMeta> metas = new 
ConcurrentHashMap<>();
+
+    private final PageIoRegistry ioRegistry;
+
+    private final int pageSize;
+
+    /**
+     * Constructor.
+     *
+     * @param ioRegistry Page IO Registry.
+     * @param pageSize Page size in bytes.
+     */
+    public PartitionMetaManager(PageIoRegistry ioRegistry, int pageSize) {
+        this.ioRegistry = ioRegistry;
+        this.pageSize = pageSize;
+    }
+
+    /**
+     * Returns the partition's meta information.
+     *
+     * @param groupPartitionId Partition of the group.
+     */
+    public @Nullable PartitionMeta getMeta(GroupPartitionId groupPartitionId) {
+        return metas.get(groupPartitionId);
+    }
+
+    /**
+     * Adds partition meta information.
+     *
+     * @param groupPartitionId Partition of the group.
+     * @param partitionMeta Partition meta information.
+     */
+    public void addMeta(GroupPartitionId groupPartitionId, PartitionMeta 
partitionMeta) {
+        metas.put(groupPartitionId, partitionMeta);
+    }
+
+    /**
+     * Reads the partition {@link PartitionMeta meta} from the partition file 
or creates a new one.
+     *
+     * <p>If it creates a new one, it writes the meta to the file.
+     *
+     * @param checkpointId Checkpoint ID.
+     * @param groupPartitionId Partition of the group.
+     * @param pageMemory Page memory.
+     * @param filePageStore Partition file page store.
+     */
+    public PartitionMeta readOrCreateMeta(
+            @Nullable UUID checkpointId,
+            GroupPartitionId groupPartitionId,
+            PersistentPageMemory pageMemory,
+            FilePageStore filePageStore
+    ) throws IgniteInternalCheckedException {
+        ByteBuffer buffer = allocateBuffer(pageSize);
+
+        long bufferAddr = bufferAddress(buffer);
+
+        long partitionMetaPageId = 
pageMemory.partitionMetaPageId(groupPartitionId.getGroupId(), 
groupPartitionId.getPartitionId());
+
+        try {
+            if (filePageStore.size() > filePageStore.headerSize()) {
+                // Reads the partition meta.
+                if (filePageStore.pages() == 0) {
+                    filePageStore.pages(1);
+                }
+
+                boolean read = filePageStore.read(partitionMetaPageId, buffer, 
false);
+
+                assert read : filePageStore.filePath();
+
+                return createMeta(ioRegistry.resolve(bufferAddr), bufferAddr, 
checkpointId);
+            } else {
+                // Creates and writes a partition meta.
+                PartitionMetaIo partitionMetaIo = 
PartitionMetaIo.VERSIONS.latest();
+                partitionMetaIo.initNewPage(bufferAddr, partitionMetaPageId, 
pageSize);
+
+                // Because we will now write this page.
+                partitionMetaIo.setPageCount(bufferAddr, 1);
+
+                filePageStore.pages(1);
+
+                filePageStore.write(partitionMetaPageId, buffer.rewind(), 
true);
+
+                filePageStore.sync();
+
+                return createMeta(partitionMetaIo, bufferAddr, checkpointId);
+            }
+        } finally {
+            freeBuffer(buffer);
+        }
+    }
+
+    /**
+     * Writes the partition meta to the buffer.
+     *
+     * @param groupPartitionId Partition of the group.
+     * @param pageMemory Page memory.
+     * @param partitionMeta Snapshot of the partition meta.
+     * @param writeToBuffer Direct byte buffer to write partition meta.
+     */
+    public void writeMetaToBuffer(
+            GroupPartitionId groupPartitionId,
+            PersistentPageMemory pageMemory,
+            PartitionMetaSnapshot partitionMeta,
+            ByteBuffer writeToBuffer
+    ) {
+        assert writeToBuffer.remaining() == pageSize : 
writeToBuffer.remaining();
+
+        long partitionMetaPageId = 
pageMemory.partitionMetaPageId(groupPartitionId.getGroupId(), 
groupPartitionId.getPartitionId());

Review Comment:
   So, the only reason of passing page memory instance is to construct meta 
page id? Are there helper methods for it somewhere? I'd ask you to remove page 
memory parameter in such places.



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/checkpoint/CheckpointDirtyPages.java:
##########
@@ -108,33 +100,54 @@ public 
IgniteConcurrentMultiPairQueue<PersistentPageMemory, GroupPartitionId> to
      * @param partId Partition ID.
      */
     public @Nullable CheckpointDirtyPagesView findView(int grpId, int partId) {
-        if (dirtyPages.isEmpty()) {
-            return null;
+        for (int i = 0; i < dirtyPages.size(); i++) {
+            CheckpointDirtyPagesView view = findView(i, grpId, partId);
+
+            if (view != null) {
+                return view;
+            }
         }
 
-        FullPageId startPageId = new FullPageId(pageId(partId, (byte) 0, 0), 
grpId);
-        FullPageId endPageId = new FullPageId(pageId(partId + 1, (byte) 0, 0), 
grpId);
+        return null;
+    }
 
+    /**
+     * Looks for dirty page IDs views for a specific group and partition.
+     *
+     * @param pageMemory Page memory.
+     * @param grpId Group ID.
+     * @param partId Partition ID.
+     */
+    public @Nullable CheckpointDirtyPagesView findView(PersistentPageMemory 
pageMemory, int grpId, int partId) {
         for (int i = 0; i < dirtyPages.size(); i++) {
-            FullPageId[] pageIds = dirtyPages.get(i).dirtyPages.pageIds;
+            if (dirtyPages.get(i).pageMemory == pageMemory) {
+                return findView(i, grpId, partId);
+            }
+        }
 
-            int fromIndex = binarySearch(pageIds, startPageId, 
DIRTY_PAGE_COMPARATOR);
+        return null;
+    }
 
-            fromIndex = fromIndex >= 0 ? fromIndex : Math.min(pageIds.length - 
1, -fromIndex - 1);
+    private @Nullable CheckpointDirtyPagesView findView(int dirtyPagesIdx, int 
grpId, int partId) {
+        FullPageId startPageId = new FullPageId(pageId(partId, (byte) 0, 0), 
grpId);
+        FullPageId endPageId = new FullPageId(pageId(partId + 1, (byte) 0, 0), 
grpId);
 
-            if (!equalsByGroupAndPartition(startPageId, pageIds[fromIndex])) {
-                continue;
-            }
+        FullPageId[] pageIds = 
dirtyPages.get(dirtyPagesIdx).dirtyPages.pageIds;
 
-            int toIndex = binarySearch(pageIds, fromIndex, pageIds.length, 
endPageId, DIRTY_PAGE_COMPARATOR);
+        int fromIndex = binarySearch(pageIds, startPageId, 
DIRTY_PAGE_COMPARATOR);
 
-            // toIndex cannot be 0 because endPageId is greater than 
startPageId by DIRTY_PAGE_COMPARATOR.
-            toIndex = toIndex > 0 ? toIndex - 1 : -toIndex - 2;
+        fromIndex = fromIndex >= 0 ? fromIndex : Math.min(pageIds.length - 1, 
-fromIndex - 1);
 
-            return new CheckpointDirtyPagesView(i, fromIndex, toIndex);
+        if (!equalsByGroupAndPartition(startPageId, pageIds[fromIndex])) {
+            return null;
         }
 
-        return null;
+        int toIndex = binarySearch(pageIds, fromIndex, pageIds.length, 
endPageId, DIRTY_PAGE_COMPARATOR);
+
+        // toIndex cannot be 0 because endPageId is greater than startPageId 
by DIRTY_PAGE_COMPARATOR.
+        toIndex = toIndex > 0 ? toIndex : -toIndex - 1;

Review Comment:
   This comment wouldn't be required if you wrote ">= 0". Why does it have to 
be more complicated?



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/checkpoint/CheckpointDirtyPages.java:
##########
@@ -229,15 +242,15 @@ public PersistentPageMemory pageMemory() {
          * Returns the size of the view.
          */
         public int size() {
-            return toPosition - fromPosition + 1;
+            return toPosition - fromPosition;
         }
 
         private CheckpointDirtyPages owner() {
             return CheckpointDirtyPages.this;
         }
 
-        private boolean isToPositionLast() {
-            return toPosition == 
dirtyPages.get(regionIndex).dirtyPages.pageIds.length - 1;
+        private boolean needsNextRegion() {
+            return toPosition == 
dirtyPages.get(regionIndex).dirtyPages.pageIds.length;

Review Comment:
   Why don't we store `dirtyPages.get(regionIndex)` precalculated? No one needs 
this extra lookup on every access



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/checkpoint/CheckpointDirtyPages.java:
##########
@@ -167,15 +180,15 @@ public 
IgniteConcurrentMultiPairQueue<PersistentPageMemory, GroupPartitionId> to
         FullPageId[] pageIds = dirtyPages.get(regionIndex).dirtyPages.pageIds;
 
         if (fromPosition == pageIds.length - 1 || 
!equalsByGroupAndPartition(pageIds[fromPosition], pageIds[fromPosition + 1])) {

Review Comment:
   This is weirdly specific case, why did you add this code? Does it break with 
regular binary searches?
   Again, this makes code more complicated. That's why I'm asking. If we can 
just remove it then let's remove it



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/store/FilePageStore.java:
##########
@@ -156,10 +138,18 @@ public void stop(boolean clean) throws 
IgniteInternalCheckedException {
 
     /** {@inheritDoc} */
     @Override
-    public long allocatePage() throws IgniteInternalCheckedException {
+    public int allocatePage() throws IgniteInternalCheckedException {
         ensure();
 
-        return pageCount.getAndIncrement();
+        int pageIdx = pageCount.getAndIncrement();
+
+        PageAllocationListener listener = this.pageAllocationListener;
+
+        if (listener != null) {
+            listener.onAllocationPage(pageIdx);

Review Comment:
   "onAllocationPage" is grammatically incorrect. Please use better names, like 
"onPageAllocated", for example. Don't ignore proper English in naming



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/checkpoint/CheckpointWorkflow.java:
##########
@@ -289,31 +282,26 @@ private DataRegionsDirtyPages beginCheckpoint(
             Collection<? extends DataRegion<PersistentPageMemory>> dataRegions,
             CompletableFuture<?> allowToReplace
     ) throws IgniteInternalCheckedException {
-        Collection<DataRegionDirtyPages<CollectionDirtyPages>> 
dataRegionsDirtyPages = new ArrayList<>(dataRegions.size());
+        Collection<DataRegionDirtyPages<DirtyPagesCollection>> 
dataRegionsDirtyPages = new ArrayList<>(dataRegions.size());

Review Comment:
   Can I ask you to add assertions that write lock is locked in every method 
that needs it? Currently it's impossible to understand it by just looking at 
method names or javadocs



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/store/FilePageStoreFactory.java:
##########
@@ -0,0 +1,102 @@
+/*
+ * 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.pagememory.persistence.store;
+
+import static 
org.apache.ignite.internal.pagememory.persistence.store.FilePageStoreHeader.readHeader;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.apache.ignite.internal.fileio.FileIo;
+import org.apache.ignite.internal.fileio.FileIoFactory;
+import org.apache.ignite.lang.IgniteInternalCheckedException;
+
+/**
+ * Factory for creating {@link FilePageStore}.
+ */
+class FilePageStoreFactory {
+    /** Latest file page store version. */
+    private final int latestVersion = FilePageStore.VERSION_1;
+
+    private final FileIoFactory fileIoFactory;
+
+    private final int pageSize;
+
+    /**
+     * Constructor.
+     *
+     * @param fileIoFactory File IO factory.
+     * @param pageSize Page size in bytes.
+     */
+    public FilePageStoreFactory(FileIoFactory fileIoFactory, int pageSize) {
+        this.fileIoFactory = fileIoFactory;
+        this.pageSize = pageSize;
+    }
+
+    /**
+     * Creates instance of {@link FilePageStore}.
+     *
+     * <p>If the file exists, an attempt will be reads its {@link 
FilePageStoreHeader header} and create the {@link FilePageStore}.
+     *
+     * @param filePath File page store path.
+     * @param readIntoBuffer Buffer for reading {@link FilePageStoreHeader 
header} from {@code filePath}.

Review Comment:
   Can you just call it "headerBuffer"?
   Phrase like "read-into buffer" is very unusual imo. Usually people use word 
"output" for this purpose



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/store/FilePageStoreFactory.java:
##########
@@ -0,0 +1,102 @@
+/*
+ * 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.pagememory.persistence.store;
+
+import static 
org.apache.ignite.internal.pagememory.persistence.store.FilePageStoreHeader.readHeader;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.apache.ignite.internal.fileio.FileIo;
+import org.apache.ignite.internal.fileio.FileIoFactory;
+import org.apache.ignite.lang.IgniteInternalCheckedException;
+
+/**
+ * Factory for creating {@link FilePageStore}.
+ */
+class FilePageStoreFactory {
+    /** Latest file page store version. */
+    private final int latestVersion = FilePageStore.VERSION_1;
+
+    private final FileIoFactory fileIoFactory;
+
+    private final int pageSize;
+
+    /**
+     * Constructor.
+     *
+     * @param fileIoFactory File IO factory.
+     * @param pageSize Page size in bytes.
+     */
+    public FilePageStoreFactory(FileIoFactory fileIoFactory, int pageSize) {
+        this.fileIoFactory = fileIoFactory;
+        this.pageSize = pageSize;
+    }
+
+    /**
+     * Creates instance of {@link FilePageStore}.
+     *
+     * <p>If the file exists, an attempt will be reads its {@link 
FilePageStoreHeader header} and create the {@link FilePageStore}.
+     *
+     * @param filePath File page store path.
+     * @param readIntoBuffer Buffer for reading {@link FilePageStoreHeader 
header} from {@code filePath}.
+     * @return File page store.
+     * @throws IgniteInternalCheckedException if failed
+     */
+    public FilePageStore createPageStore(Path filePath, ByteBuffer 
readIntoBuffer) throws IgniteInternalCheckedException {
+        assert readIntoBuffer.remaining() == pageSize : 
readIntoBuffer.remaining();
+
+        if (!Files.exists(filePath)) {
+            return createPageStore(filePath, new 
FilePageStoreHeader(latestVersion, pageSize));
+        }
+
+        try (FileIo fileIo = fileIoFactory.create(filePath)) {
+            FilePageStoreHeader header = readHeader(fileIo, readIntoBuffer);
+
+            if (header == null) {
+                header = new FilePageStoreHeader(latestVersion, pageSize);
+            }
+
+            return createPageStore(filePath, header);
+        } catch (IOException e) {
+            throw new IgniteInternalCheckedException("Error while creating 
file page store [file=" + filePath + "]:", e);

Review Comment:
   What's up with the colon at the end?



##########
modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageEngine.java:
##########
@@ -106,27 +110,29 @@ public void start() throws StorageException {
                     ? new AsyncFileIoFactory()
                     : new RandomAccessFileIoFactory();
 
-            partitionFilePageStoreManager = new PartitionFilePageStoreManager(
-                    Loggers.forClass(PartitionFilePageStoreManager.class),
+            filePageStoreManager = new FilePageStoreManager(

Review Comment:
   Can these fields be instantiated in constructor? Then they wouldn't have to 
be nullable



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/store/FilePageStoreHeader.java:
##########
@@ -97,18 +97,19 @@ ByteBuffer toByteBuffer() {
      * Reads the header of a file page store.
      *
      * @param fileIo File page store fileIo.
+     * @param readIntoBuffer Buffer for reading {@link FilePageStoreHeader 
header} from {@code fileIo}.

Review Comment:
   Same here, strange naming



##########
modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageEngine.java:
##########
@@ -106,27 +110,29 @@ public void start() throws StorageException {
                     ? new AsyncFileIoFactory()
                     : new RandomAccessFileIoFactory();
 
-            partitionFilePageStoreManager = new PartitionFilePageStoreManager(
-                    Loggers.forClass(PartitionFilePageStoreManager.class),
+            filePageStoreManager = new FilePageStoreManager(
+                    Loggers.forClass(FilePageStoreManager.class),
                     igniteInstanceName,
                     storagePath,
                     fileIoFactory,
-                    ioRegistry,
                     pageSize
             );
 
-            partitionFilePageStoreManager.start();
+            filePageStoreManager.start();
         } catch (IgniteInternalCheckedException e) {
             throw new StorageException("Error starting file page store 
manager", e);
         }
 
+        partitionMetaManager = new PartitionMetaManager(ioRegistry, pageSize);

Review Comment:
   Same here. Constructor initializes object, "start" starts all 
sub-components. This is how it was intended to work



##########
modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageEngine.java:
##########
@@ -159,11 +165,11 @@ public void stop() throws StorageException {
             Stream<AutoCloseable> closeRegions = 
regions.values().stream().map(region -> region::stop);
 
             CheckpointManager checkpointManager = this.checkpointManager;
-            PartitionFilePageStoreManager partitionFilePageStoreManager = 
this.partitionFilePageStoreManager;
+            FilePageStoreManager filePageStoreManager = 
this.filePageStoreManager;
 
             Stream<AutoCloseable> closeManagers = Stream.of(
                     checkpointManager == null ? null : (AutoCloseable) 
checkpointManager::stop,
-                    partitionFilePageStoreManager == null ? null : 
(AutoCloseable) partitionFilePageStoreManager::stop
+                    filePageStoreManager == null ? null : (AutoCloseable) 
filePageStoreManager::stop

Review Comment:
   All these null checks won't be required anymore



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/checkpoint/CheckpointDirtyPages.java:
##########
@@ -108,33 +100,54 @@ public 
IgniteConcurrentMultiPairQueue<PersistentPageMemory, GroupPartitionId> to
      * @param partId Partition ID.
      */
     public @Nullable CheckpointDirtyPagesView findView(int grpId, int partId) {

Review Comment:
   Why do we need two versions of the method now? Don't we always have a page 
memory instance when we need a "view"?



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/checkpoint/CheckpointDirtyPages.java:
##########
@@ -108,33 +100,54 @@ public 
IgniteConcurrentMultiPairQueue<PersistentPageMemory, GroupPartitionId> to
      * @param partId Partition ID.
      */
     public @Nullable CheckpointDirtyPagesView findView(int grpId, int partId) {
-        if (dirtyPages.isEmpty()) {
-            return null;
+        for (int i = 0; i < dirtyPages.size(); i++) {
+            CheckpointDirtyPagesView view = findView(i, grpId, partId);
+
+            if (view != null) {
+                return view;
+            }
         }
 
-        FullPageId startPageId = new FullPageId(pageId(partId, (byte) 0, 0), 
grpId);
-        FullPageId endPageId = new FullPageId(pageId(partId + 1, (byte) 0, 0), 
grpId);
+        return null;
+    }
 
+    /**
+     * Looks for dirty page IDs views for a specific group and partition.
+     *
+     * @param pageMemory Page memory.
+     * @param grpId Group ID.
+     * @param partId Partition ID.
+     */
+    public @Nullable CheckpointDirtyPagesView findView(PersistentPageMemory 
pageMemory, int grpId, int partId) {
         for (int i = 0; i < dirtyPages.size(); i++) {
-            FullPageId[] pageIds = dirtyPages.get(i).dirtyPages.pageIds;
+            if (dirtyPages.get(i).pageMemory == pageMemory) {
+                return findView(i, grpId, partId);
+            }
+        }
 
-            int fromIndex = binarySearch(pageIds, startPageId, 
DIRTY_PAGE_COMPARATOR);
+        return null;

Review Comment:
   Technically, this must be impossible, right? Maybe we should add an 
assertion or something?



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/checkpoint/CheckpointPagesWriter.java:
##########
@@ -253,38 +251,21 @@ private void updatePartitions() throws 
IgniteInternalCheckedException {
         while (!shutdownNow.getAsBoolean() && 
updatePartitionIds.next(queueResult)) {
             GroupPartitionId partitionId = queueResult.getValue();
 
-            PartitionFilePageStore partitionFilePageStore = 
partitionFilePageStoreManager.getStore(
-                    partitionId.getGroupId(),
-                    partitionId.getPartitionId()
-            );
-
             ByteBuffer buffer = threadBuf.get();
 
             PersistentPageMemory pageMemory = queueResult.getKey();
 
-            long partitionMetaPageId = 
pageMemory.partitionMetaPageId(partitionId.getGroupId(), 
partitionId.getPartitionId());
-
-            long pageAddr = GridUnsafe.bufferAddress(buffer);
-
-            // TODO: IGNITE-16657 Merger will put the page into a partition 
file.
-            PartitionMetaIo io = PartitionMetaIo.VERSIONS.latest();
+            PartitionMetaSnapshot partitionMetaSnapshot = 
partitionMetaManager.getMeta(partitionId).metaSnapshot(checkpointProgress.id());

Review Comment:
   Ok, you're not gonna like what I want to say. But, a collection of dirty 
partition ids is not required anymore once you implemented "async" meta 
snapshots.
   Here's what you can do: for each page you need to write you additionally 
check if its partition has its meta saved. This can be done with a simple `if 
(saveMetaPage.put(groupPartitionId))`. Then, if current thread is the one that 
needs to write meta, you just do it by acquiring meta object the same way as it 
is in the code right now.
   The point is, a regular list of dirty pages already contains all information 
about dirty partitions.
   Please ask questions if I didn't manage to explain myself here.



##########
modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/store/FilePageStoreFactory.java:
##########
@@ -0,0 +1,102 @@
+/*
+ * 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.pagememory.persistence.store;
+
+import static 
org.apache.ignite.internal.pagememory.persistence.store.FilePageStoreHeader.readHeader;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.apache.ignite.internal.fileio.FileIo;
+import org.apache.ignite.internal.fileio.FileIoFactory;
+import org.apache.ignite.lang.IgniteInternalCheckedException;
+
+/**
+ * Factory for creating {@link FilePageStore}.
+ */
+class FilePageStoreFactory {
+    /** Latest file page store version. */
+    private final int latestVersion = FilePageStore.VERSION_1;
+
+    private final FileIoFactory fileIoFactory;
+
+    private final int pageSize;
+
+    /**
+     * Constructor.
+     *
+     * @param fileIoFactory File IO factory.
+     * @param pageSize Page size in bytes.
+     */
+    public FilePageStoreFactory(FileIoFactory fileIoFactory, int pageSize) {
+        this.fileIoFactory = fileIoFactory;
+        this.pageSize = pageSize;
+    }
+
+    /**
+     * Creates instance of {@link FilePageStore}.
+     *
+     * <p>If the file exists, an attempt will be reads its {@link 
FilePageStoreHeader header} and create the {@link FilePageStore}.

Review Comment:
   What did you try to say with "an attempt will be reads its"? I don't 
understand it



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to