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

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


The following commit(s) were added to refs/heads/main by this push:
     new 2a887000644 IGNITE-26037 Error saving FreeList metadata causing 
checkpointer to crash (#6354)
2a887000644 is described below

commit 2a887000644abe2010bac21575a8bb0e58e3e46f
Author: Kirill Tkalenko <[email protected]>
AuthorDate: Wed Aug 27 15:52:03 2025 +0300

    IGNITE-26037 Error saving FreeList metadata causing checkpointer to crash 
(#6354)
---
 .../internal/pagememory/freelist/FreeListImpl.java    | 11 ++++++++++-
 .../mv/PersistentPageMemoryMvPartitionStorage.java    |  3 +++
 .../PersistentPageMemoryMvTableStorageTest.java       | 19 +++++++++++++++++++
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git 
a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/freelist/FreeListImpl.java
 
b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/freelist/FreeListImpl.java
index b1d237207b5..85a70aa468a 100644
--- 
a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/freelist/FreeListImpl.java
+++ 
b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/freelist/FreeListImpl.java
@@ -78,6 +78,8 @@ public class FreeListImpl extends PagesList implements 
FreeList, ReuseList {
     /** Page list cache limit. */
     private final @Nullable AtomicLong pageListCacheLimit;
 
+    private volatile boolean closed;
+
     /** Write a single row on a single page. */
     private final WriteRowHandler writeRowHnd = new WriteRowHandler();
 
@@ -817,11 +819,18 @@ public class FreeListImpl extends PagesList implements 
FreeList, ReuseList {
     public void saveMetadata() throws IgniteInternalCheckedException {
         // Double inheritance here. We inherit interface method from the 
FreeList interface, and the implementation from the PagesList
         // class. These two versions must be joined here by calling the super 
method.
-        super.saveMetadata();
+        if (!closed) {
+            super.saveMetadata();
+        }
     }
 
     @Override
     public String toString() {
         return "FreeListImpl [name=" + name() + ']';
     }
+
+    @Override
+    public void close() {
+        closed = true;
+    }
 }
diff --git 
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java
 
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java
index 01e2cdfda58..59626b843f4 100644
--- 
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java
+++ 
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java
@@ -510,6 +510,8 @@ public class PersistentPageMemoryMvPartitionStorage extends 
AbstractPageMemoryMv
                 indexMetaTree,
                 gcQueue
         );
+
+        checkpointManager.addCheckpointListener(checkpointListener, 
tableStorage.dataRegion());
     }
 
     @Override
@@ -517,6 +519,7 @@ public class PersistentPageMemoryMvPartitionStorage extends 
AbstractPageMemoryMv
         RenewablePartitionStorageState localState = renewableState;
 
         return List.of(
+                () -> 
checkpointManager.removeCheckpointListener(checkpointListener),
                 localState.freeList()::close,
                 localState.versionChainTree()::close,
                 localState.indexMetaTree()::close,
diff --git 
a/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryMvTableStorageTest.java
 
b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryMvTableStorageTest.java
index ed78919baca..470ffeedcd2 100644
--- 
a/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryMvTableStorageTest.java
+++ 
b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryMvTableStorageTest.java
@@ -36,6 +36,7 @@ import static org.mockito.Mockito.mock;
 import java.nio.file.Path;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutorService;
+import java.util.stream.IntStream;
 import org.apache.ignite.internal.components.LogSyncer;
 import 
org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
 import org.apache.ignite.internal.failure.FailureManager;
@@ -354,6 +355,24 @@ public class PersistentPageMemoryMvTableStorageTest 
extends AbstractMvTableStora
         }
     }
 
+    @Test
+    void testSyncFreeListOnCheckpointAfterStartRebalance() {
+        MvPartitionStorage storage = getOrCreateMvPartition(PARTITION_ID);
+
+        var meta = new MvPartitionMeta(1, 1, BYTE_EMPTY_ARRAY, null, 
BYTE_EMPTY_ARRAY);
+
+        for (int i = 0; i < 10; i++) {
+            IntStream.rangeClosed(0, 10).forEach(n -> 
addWriteCommitted(storage));
+
+            runRace(
+                    () -> 
assertThat(tableStorage.startRebalancePartition(PARTITION_ID), 
willCompleteSuccessfully()),
+                    () -> assertThat(forceCheckpointAsync(), 
willCompleteSuccessfully())
+            );
+
+            assertThat(tableStorage.finishRebalancePartition(PARTITION_ID, 
meta), willCompleteSuccessfully());
+        }
+    }
+
     private CompletableFuture<Void> forceCheckpointAsync() {
         return 
engine.checkpointManager().forceCheckpoint("test").futureFor(FINISHED);
     }

Reply via email to