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);
}