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 f3a1f9dd75 IGNITE-19737
TestMvStorageUpdateHandlerTest.testConcurrentExecuteBatchGc is flacky (#2197)
f3a1f9dd75 is described below
commit f3a1f9dd75b05255ebb26173c22b29317047064b
Author: Kirill Tkalenko <[email protected]>
AuthorDate: Fri Jun 16 14:50:36 2023 +0300
IGNITE-19737 TestMvStorageUpdateHandlerTest.testConcurrentExecuteBatchGc is
flacky (#2197)
---
.../storage/impl/TestMvPartitionStorage.java | 15 +-
.../table/distributed/StorageUpdateHandler.java | 2 +-
.../table/distributed/gc/GcUpdateHandler.java | 75 +++++--
.../internal/table/distributed/gc/IntHolder.java} | 36 +++-
.../ignite/internal/table/distributed/gc/MvGc.java | 4 +-
.../AbstractMvStorageUpdateHandlerTest.java | 139 -------------
.../internal/table/distributed/IndexGcTest.java | 22 +-
.../gc/AbstractGcUpdateHandlerTest.java | 225 +++++++++++++++++++++
.../table/distributed/gc/GcUpdateHandlerTest.java | 143 -------------
.../internal/table/distributed/gc/MvGcTest.java | 9 +-
.../PersistentPageMemoryGcUpdateHandlerTest.java} | 4 +-
.../RocksDbGcUpdateHandlerTest.java} | 4 +-
.../TestGcUpdateHandlerTest.java} | 4 +-
.../VolatilePageMemoryGcUpdateHandlerTest.java} | 4 +-
14 files changed, 346 insertions(+), 340 deletions(-)
diff --git
a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestMvPartitionStorage.java
b/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestMvPartitionStorage.java
index ba81744ea8..2f2306a3ac 100644
---
a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestMvPartitionStorage.java
+++
b/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestMvPartitionStorage.java
@@ -528,6 +528,8 @@ public class TestMvPartitionStorage implements
MvPartitionStorage {
@Override
public synchronized @Nullable GcEntry peek(HybridTimestamp lowWatermark) {
+ assert THREAD_LOCAL_LOCKER.get() != null;
+
try {
VersionChain versionChain = gcQueue.first();
@@ -543,16 +545,19 @@ public class TestMvPartitionStorage implements
MvPartitionStorage {
@Override
public synchronized @Nullable BinaryRow vacuum(GcEntry entry) {
+ assert THREAD_LOCAL_LOCKER.get() != null;
+ assert THREAD_LOCAL_LOCKER.get().isLocked(entry.getRowId());
+
checkStorageClosedOrInProcessOfRebalance();
- Iterator<VersionChain> it = gcQueue.iterator();
+ VersionChain dequeuedVersionChain;
- if (!it.hasNext()) {
+ try {
+ dequeuedVersionChain = gcQueue.first();
+ } catch (NoSuchElementException e) {
return null;
}
- VersionChain dequeuedVersionChain = it.next();
-
if (dequeuedVersionChain != entry) {
return null;
}
@@ -564,7 +569,7 @@ public class TestMvPartitionStorage implements
MvPartitionStorage {
assert versionChainToRemove.next == null;
dequeuedVersionChain.next = null;
- it.remove();
+ gcQueue.remove(dequeuedVersionChain);
// Tombstones must be deleted.
if (dequeuedVersionChain.row == null) {
diff --git
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/StorageUpdateHandler.java
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/StorageUpdateHandler.java
index 9da8aaf775..bbea32ec18 100644
---
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/StorageUpdateHandler.java
+++
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/StorageUpdateHandler.java
@@ -202,7 +202,7 @@ public class StorageUpdateHandler {
return;
}
- gcUpdateHandler.vacuumBatch(lwm, gcConfig.onUpdateBatchSize().value());
+ gcUpdateHandler.vacuumBatch(lwm, gcConfig.onUpdateBatchSize().value(),
false);
}
/**
diff --git
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/gc/GcUpdateHandler.java
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/gc/GcUpdateHandler.java
index b976075d75..8475849880 100644
---
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/gc/GcUpdateHandler.java
+++
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/gc/GcUpdateHandler.java
@@ -20,7 +20,6 @@ package org.apache.ignite.internal.table.distributed.gc;
import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.schema.BinaryRow;
import org.apache.ignite.internal.storage.MvPartitionStorage.Locker;
-import org.apache.ignite.internal.storage.MvPartitionStorage.WriteClosure;
import org.apache.ignite.internal.storage.ReadResult;
import org.apache.ignite.internal.storage.RowId;
import org.apache.ignite.internal.storage.gc.GcEntry;
@@ -69,41 +68,75 @@ public class GcUpdateHandler {
*
* @param lowWatermark Low watermark for the vacuum.
* @param count Count of entries to GC.
+ * @param strict {@code true} if needed to remove the strictly passed
{@code count} oldest stale entries, {@code false} if a premature
+ * exit is allowed when it is not possible to acquire a lock for the
{@link RowId}.
* @return {@code False} if there is no garbage left in the storage.
*/
- public boolean vacuumBatch(HybridTimestamp lowWatermark, int count) {
+ public boolean vacuumBatch(HybridTimestamp lowWatermark, int count,
boolean strict) {
+ if (count <= 0) {
+ return true;
+ }
+
+ IntHolder countHolder = new IntHolder(count);
+
+ while (countHolder.get() > 0) {
+ VacuumResult vacuumResult = internalVacuumBatch(lowWatermark,
countHolder);
+
+ switch (vacuumResult) {
+ case NO_GARBAGE_LEFT:
+ return false;
+ case SUCCESS:
+ return true;
+ case FAILED_ACQUIRE_LOCK:
+ if (strict) {
+ continue;
+ }
+
+ return true;
+ default:
+ throw new IllegalStateException(vacuumResult.toString());
+ }
+ }
+
+ return true;
+ }
+
+ private VacuumResult internalVacuumBatch(HybridTimestamp lowWatermark,
IntHolder countHolder) {
return storage.runConsistently(locker -> {
+ int count = countHolder.get();
+
for (int i = 0; i < count; i++) {
- if (!internalVacuum(lowWatermark, locker)) {
- return false;
+ // It is safe for the first iteration to use a lock instead of
tryLock, since there will be no deadlock for the first RowId
+ // and a deadlock may happen with subsequent ones.
+ VacuumResult vacuumResult = internalVacuum(lowWatermark,
locker, i > 0);
+
+ if (vacuumResult != VacuumResult.SUCCESS) {
+ return vacuumResult;
}
+
+ countHolder.getAndDecrement();
}
- return true;
+ return VacuumResult.SUCCESS;
});
}
- /**
- * Attempts to collect garbage for one {@link RowId}.
- *
- * <p>Must be called inside a {@link
PartitionDataStorage#runConsistently(WriteClosure)} closure.
- *
- * @param lowWatermark Low watermark for the vacuum.
- * @param locker From {@link
PartitionDataStorage#runConsistently(WriteClosure)}.
- * @return {@code False} if there is no garbage left in the {@link
#storage}.
- */
- private boolean internalVacuum(HybridTimestamp lowWatermark, Locker
locker) {
+ private VacuumResult internalVacuum(HybridTimestamp lowWatermark, Locker
locker, boolean useTryLock) {
while (true) {
GcEntry gcEntry = storage.peek(lowWatermark);
if (gcEntry == null) {
- return false;
+ return VacuumResult.NO_GARBAGE_LEFT;
}
RowId rowId = gcEntry.getRowId();
- if (!locker.tryLock(rowId)) {
- return true;
+ if (useTryLock) {
+ if (!locker.tryLock(rowId)) {
+ return VacuumResult.FAILED_ACQUIRE_LOCK;
+ }
+ } else {
+ locker.lock(rowId);
}
BinaryRow binaryRow = storage.vacuum(gcEntry);
@@ -117,7 +150,11 @@ public class GcUpdateHandler {
indexUpdateHandler.tryRemoveFromIndexes(binaryRow, rowId,
cursor);
}
- return true;
+ return VacuumResult.SUCCESS;
}
}
+
+ private enum VacuumResult {
+ SUCCESS, NO_GARBAGE_LEFT, FAILED_ACQUIRE_LOCK
+ }
}
diff --git
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/TestMvStorageUpdateHandlerTest.java
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/gc/IntHolder.java
similarity index 58%
copy from
modules/table/src/test/java/org/apache/ignite/internal/table/distributed/TestMvStorageUpdateHandlerTest.java
copy to
modules/table/src/main/java/org/apache/ignite/internal/table/distributed/gc/IntHolder.java
index aebcf89b52..6a759d0f0f 100644
---
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/TestMvStorageUpdateHandlerTest.java
+++
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/gc/IntHolder.java
@@ -15,16 +15,36 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.table.distributed;
+package org.apache.ignite.internal.table.distributed.gc;
-import static
org.apache.ignite.internal.distributionzones.DistributionZoneManager.DEFAULT_PARTITION_COUNT;
+/**
+ * Non-thread-safe {@code int} holder with the ability to update the number.
+ */
+class IntHolder {
+ private int value;
+
+ /**
+ * Constructor.
+ *
+ * @param value Value.
+ */
+ IntHolder(int value) {
+ this.value = value;
+ }
-import org.apache.ignite.internal.storage.impl.TestMvTableStorage;
-import org.junit.jupiter.api.BeforeEach;
+ /**
+ * Returns the current value.
+ */
+ int get() {
+ return value;
+ }
-class TestMvStorageUpdateHandlerTest extends
AbstractMvStorageUpdateHandlerTest {
- @BeforeEach
- void setUp() {
- initialize(new TestMvTableStorage(1, DEFAULT_PARTITION_COUNT));
+ /**
+ * Decrements the current value, equivalent to {@code value--}.
+ *
+ * @return Previous value.
+ */
+ int getAndDecrement() {
+ return value--;
}
}
diff --git
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/gc/MvGc.java
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/gc/MvGc.java
index 4840827a59..0d2d9defbc 100644
---
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/gc/MvGc.java
+++
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/gc/MvGc.java
@@ -47,7 +47,7 @@ import org.jetbrains.annotations.TestOnly;
/**
* Garbage collector for multi-versioned storages and their indexes in the
background.
*
- * @see GcUpdateHandler#vacuumBatch(HybridTimestamp, int)
+ * @see GcUpdateHandler#vacuumBatch(HybridTimestamp, int, boolean)
*/
public class MvGc implements ManuallyCloseable {
private static final IgniteLogger LOG = Loggers.forClass(MvGc.class);
@@ -242,7 +242,7 @@ public class MvGc implements ManuallyCloseable {
// We can only start garbage collection when the partition
safe time is reached.
gcUpdateHandler.getSafeTimeTracker()
.waitFor(lowWatermark)
- .thenApplyAsync(unused ->
gcUpdateHandler.vacuumBatch(lowWatermark, GC_BATCH_SIZE), executor)
+ .thenApplyAsync(unused ->
gcUpdateHandler.vacuumBatch(lowWatermark, GC_BATCH_SIZE, true), executor)
.whenComplete((isGarbageLeft, throwable) -> {
if (throwable != null) {
if (throwable instanceof TrackerClosedException
diff --git
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/AbstractMvStorageUpdateHandlerTest.java
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/AbstractMvStorageUpdateHandlerTest.java
deleted file mode 100644
index 6e56bcbf98..0000000000
---
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/AbstractMvStorageUpdateHandlerTest.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 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.table.distributed;
-
-import static org.apache.ignite.internal.testframework.IgniteTestUtils.runRace;
-import static
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willSucceedFast;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.mockito.Mockito.when;
-
-import java.util.Map;
-import java.util.UUID;
-import org.apache.ignite.distributed.TestPartitionDataStorage;
-import
org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
-import
org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
-import org.apache.ignite.internal.hlc.HybridTimestamp;
-import org.apache.ignite.internal.schema.BinaryRow;
-import org.apache.ignite.internal.schema.configuration.GcConfiguration;
-import org.apache.ignite.internal.storage.BaseMvStoragesTest;
-import org.apache.ignite.internal.storage.MvPartitionStorage;
-import org.apache.ignite.internal.storage.RowId;
-import org.apache.ignite.internal.storage.engine.MvTableStorage;
-import org.apache.ignite.internal.table.distributed.gc.GcUpdateHandler;
-import org.apache.ignite.internal.table.distributed.index.IndexUpdateHandler;
-import org.apache.ignite.internal.table.distributed.raft.PartitionDataStorage;
-import org.apache.ignite.internal.table.impl.DummyInternalTableImpl;
-import org.apache.ignite.internal.util.PendingComparableValuesTracker;
-import org.jetbrains.annotations.Nullable;
-import org.junit.jupiter.api.RepeatedTest;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-/**
- * Abstract class for testing {@link StorageUpdateHandler} using different
implementations of {@link MvPartitionStorage}.
- */
-@ExtendWith(MockitoExtension.class)
-@ExtendWith(ConfigurationExtension.class)
-abstract class AbstractMvStorageUpdateHandlerTest extends BaseMvStoragesTest {
- /** To be used in a loop. {@link RepeatedTest} has a smaller failure rate
due to recreating the storage every time. */
- private static final int REPEATS = 100;
-
- private static final int PARTITION_ID = 0;
-
- private TestPartitionDataStorage partitionDataStorage;
-
- private StorageUpdateHandler storageUpdateHandler;
-
- @Mock
- private LowWatermark lowWatermark;
-
- @InjectConfiguration
- private GcConfiguration gcConfig;
-
- /**
- * Initializes the internal structures needed for tests.
- *
- * <p>This method *MUST* always be called in either subclass' constructor
or setUp method.
- */
- final void initialize(MvTableStorage tableStorage) {
- MvPartitionStorage partitionStorage =
getOrCreateMvPartition(tableStorage, PARTITION_ID);
-
- partitionDataStorage = new TestPartitionDataStorage(partitionStorage);
-
- IndexUpdateHandler indexUpdateHandler = new
IndexUpdateHandler(DummyInternalTableImpl.createTableIndexStoragesSupplier(Map.of()));
-
- storageUpdateHandler = new StorageUpdateHandler(
- PARTITION_ID,
- partitionDataStorage,
- gcConfig,
- lowWatermark,
- indexUpdateHandler,
- new GcUpdateHandler(
- partitionDataStorage,
- new
PendingComparableValuesTracker<>(HybridTimestamp.MAX_VALUE),
- indexUpdateHandler
- )
- );
- }
-
- @Test
- void testConcurrentExecuteBatchGc() {
- assertThat(gcConfig.onUpdateBatchSize().update(4), willSucceedFast());
-
-
when(lowWatermark.getLowWatermark()).thenReturn(HybridTimestamp.MAX_VALUE);
-
- RowId rowId0 = new RowId(PARTITION_ID);
- RowId rowId1 = new RowId(PARTITION_ID);
-
- BinaryRow row0 = binaryRow(new TestKey(0, "key0"), new TestValue(0,
"value0"));
- BinaryRow row1 = binaryRow(new TestKey(0, "key0"), new TestValue(0,
"value0"));
-
- for (int i = 0; i < REPEATS; i++) {
- addWriteCommitted(partitionDataStorage, rowId0, row0, clock.now());
- addWriteCommitted(partitionDataStorage, rowId1, row1, clock.now());
-
- addWriteCommitted(partitionDataStorage, rowId0, row0, clock.now());
- addWriteCommitted(partitionDataStorage, rowId1, row1, clock.now());
-
- addWriteCommitted(partitionDataStorage, rowId0, null, clock.now());
- addWriteCommitted(partitionDataStorage, rowId1, null, clock.now());
-
- runRace(
- () -> storageUpdateHandler.executeBatchGc(),
- () -> storageUpdateHandler.executeBatchGc()
- );
-
-
assertNull(partitionDataStorage.getStorage().closestRowId(RowId.lowestRowId(PARTITION_ID)));
- }
- }
-
- private static void addWriteCommitted(PartitionDataStorage storage, RowId
rowId, @Nullable BinaryRow row, HybridTimestamp timestamp) {
- storage.runConsistently(locker -> {
- locker.lock(rowId);
-
- storage.addWrite(rowId, row, UUID.randomUUID(), 999, PARTITION_ID);
-
- storage.commitWrite(rowId, timestamp);
-
- return null;
- });
- }
-}
diff --git
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/IndexGcTest.java
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/IndexGcTest.java
index 498f4edefe..669b69bea8 100644
---
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/IndexGcTest.java
+++
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/IndexGcTest.java
@@ -42,7 +42,7 @@ public class IndexGcTest extends IndexBaseTest {
addWrite(storageUpdateHandler, rowUuid, row);
commitWrite(rowId);
- assertTrue(gcUpdateHandler.vacuumBatch(now(), 1));
+ assertTrue(gcUpdateHandler.vacuumBatch(now(), 1, true));
assertEquals(1, getRowVersions(rowId).size());
// Newer entry has the same index value, so it should not be removed.
@@ -70,13 +70,13 @@ public class IndexGcTest extends IndexBaseTest {
HybridTimestamp afterCommits = now();
- assertTrue(gcUpdateHandler.vacuumBatch(afterCommits, 1));
+ assertTrue(gcUpdateHandler.vacuumBatch(afterCommits, 1, true));
// row1 should still be in the index, because second write was
identical to the first.
assertTrue(inAllIndexes(row1));
- assertTrue(gcUpdateHandler.vacuumBatch(afterCommits, 1));
- assertFalse(gcUpdateHandler.vacuumBatch(afterCommits, 1));
+ assertTrue(gcUpdateHandler.vacuumBatch(afterCommits, 1, true));
+ assertFalse(gcUpdateHandler.vacuumBatch(afterCommits, 1, true));
assertEquals(1, getRowVersions(rowId).size());
// Older entries have different indexes, should be removed.
@@ -103,8 +103,8 @@ public class IndexGcTest extends IndexBaseTest {
HybridTimestamp afterCommits = now();
- assertTrue(gcUpdateHandler.vacuumBatch(afterCommits, 1));
- assertFalse(gcUpdateHandler.vacuumBatch(afterCommits, 1));
+ assertTrue(gcUpdateHandler.vacuumBatch(afterCommits, 1, true));
+ assertFalse(gcUpdateHandler.vacuumBatch(afterCommits, 1, true));
assertEquals(0, getRowVersions(rowId).size());
// The last entry was a tombstone, so no indexes should be left.
@@ -129,8 +129,8 @@ public class IndexGcTest extends IndexBaseTest {
HybridTimestamp afterCommits = now();
- assertTrue(gcUpdateHandler.vacuumBatch(afterCommits, 1));
- assertFalse(gcUpdateHandler.vacuumBatch(afterCommits, 1));
+ assertTrue(gcUpdateHandler.vacuumBatch(afterCommits, 1, true));
+ assertFalse(gcUpdateHandler.vacuumBatch(afterCommits, 1, true));
assertEquals(1, getRowVersions(rowId).size());
assertTrue(inAllIndexes(row));
@@ -154,9 +154,9 @@ public class IndexGcTest extends IndexBaseTest {
HybridTimestamp afterCommits = now();
- assertTrue(gcUpdateHandler.vacuumBatch(afterCommits, 1));
- assertTrue(gcUpdateHandler.vacuumBatch(afterCommits, 1));
- assertFalse(gcUpdateHandler.vacuumBatch(afterCommits, 1));
+ assertTrue(gcUpdateHandler.vacuumBatch(afterCommits, 1, true));
+ assertTrue(gcUpdateHandler.vacuumBatch(afterCommits, 1, true));
+ assertFalse(gcUpdateHandler.vacuumBatch(afterCommits, 1, true));
assertEquals(0, getRowVersions(rowId).size());
assertTrue(notInAnyIndex(row));
diff --git
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/AbstractGcUpdateHandlerTest.java
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/AbstractGcUpdateHandlerTest.java
new file mode 100644
index 0000000000..9fddeb950a
--- /dev/null
+++
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/AbstractGcUpdateHandlerTest.java
@@ -0,0 +1,225 @@
+/*
+ * 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.table.distributed.gc;
+
+import static org.apache.ignite.internal.testframework.IgniteTestUtils.runRace;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.Map;
+import java.util.UUID;
+import org.apache.ignite.distributed.TestPartitionDataStorage;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
+import org.apache.ignite.internal.schema.BinaryRow;
+import org.apache.ignite.internal.storage.BaseMvStoragesTest;
+import org.apache.ignite.internal.storage.MvPartitionStorage;
+import org.apache.ignite.internal.storage.RowId;
+import org.apache.ignite.internal.storage.engine.MvTableStorage;
+import org.apache.ignite.internal.table.distributed.index.IndexUpdateHandler;
+import org.apache.ignite.internal.table.distributed.raft.PartitionDataStorage;
+import org.apache.ignite.internal.table.impl.DummyInternalTableImpl;
+import org.apache.ignite.internal.util.PendingComparableValuesTracker;
+import org.jetbrains.annotations.Nullable;
+import org.junit.jupiter.api.RepeatedTest;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+/**
+ * Abstract class for testing {@link GcUpdateHandler} using different
implementations of {@link MvPartitionStorage}.
+ */
+abstract class AbstractGcUpdateHandlerTest extends BaseMvStoragesTest {
+ /** To be used in a loop. {@link RepeatedTest} has a smaller failure rate
due to recreating the storage every time. */
+ private static final int REPEATS = 1000;
+
+ private static final int PARTITION_ID = 0;
+
+ private MvTableStorage tableStorage;
+
+ /**
+ * Initializes the internal structures needed for tests.
+ *
+ * <p>This method *MUST* always be called in either subclass' constructor
or setUp method.
+ */
+ final void initialize(MvTableStorage tableStorage) {
+ this.tableStorage = tableStorage;
+ }
+
+ @ParameterizedTest(name = "strict : {0}")
+ @ValueSource(booleans = {true, false})
+ void testVacuum(boolean strict) {
+ TestPartitionDataStorage partitionStorage =
spy(createPartitionDataStorage());
+ IndexUpdateHandler indexUpdateHandler =
spy(createIndexUpdateHandler());
+
+ GcUpdateHandler gcUpdateHandler =
createGcUpdateHandler(partitionStorage, indexUpdateHandler);
+
+ HybridTimestamp lowWatermark = HybridTimestamp.MAX_VALUE;
+
+ assertFalse(gcUpdateHandler.vacuumBatch(lowWatermark, 1, strict));
+ verify(partitionStorage).peek(lowWatermark);
+
+ // Let's check that StorageUpdateHandler#vacuumBatch returns true.
+ clearInvocations(partitionStorage);
+
+ RowId rowId = new RowId(PARTITION_ID);
+ BinaryRow row = binaryRow(new TestKey(0, "key"), new TestValue(0,
"value"));
+
+ addWriteCommitted(partitionStorage, rowId, row, clock.now());
+ addWriteCommitted(partitionStorage, rowId, row, clock.now());
+
+ assertTrue(gcUpdateHandler.vacuumBatch(lowWatermark, 1, strict));
+ verify(partitionStorage).peek(lowWatermark);
+ verify(indexUpdateHandler).tryRemoveFromIndexes(any(), eq(rowId),
any());
+ }
+
+ @ParameterizedTest(name = "strict : {0}")
+ @ValueSource(booleans = {true, false})
+ void testVacuumBatch(boolean strict) {
+ TestPartitionDataStorage partitionStorage =
spy(createPartitionDataStorage());
+ IndexUpdateHandler indexUpdateHandler =
spy(createIndexUpdateHandler());
+
+ GcUpdateHandler gcUpdateHandler =
createGcUpdateHandler(partitionStorage, indexUpdateHandler);
+
+ HybridTimestamp lowWatermark = HybridTimestamp.MAX_VALUE;
+
+ RowId rowId0 = new RowId(PARTITION_ID);
+ RowId rowId1 = new RowId(PARTITION_ID);
+
+ BinaryRow row0 = binaryRow(new TestKey(0, "key0"), new TestValue(0,
"value0"));
+ BinaryRow row1 = binaryRow(new TestKey(0, "key1"), new TestValue(0,
"value0"));
+
+ addWriteCommitted(partitionStorage, rowId0, row0, clock.now());
+ addWriteCommitted(partitionStorage, rowId0, row0, clock.now());
+
+ addWriteCommitted(partitionStorage, rowId1, row1, clock.now());
+ addWriteCommitted(partitionStorage, rowId1, row1, clock.now());
+
+ assertFalse(gcUpdateHandler.vacuumBatch(lowWatermark, 5, strict));
+
+ verify(partitionStorage, times(3)).peek(lowWatermark);
+ verify(indexUpdateHandler).tryRemoveFromIndexes(any(), eq(rowId0),
any());
+ verify(indexUpdateHandler).tryRemoveFromIndexes(any(), eq(rowId1),
any());
+ }
+
+ @Test
+ void testConcurrentVacuumBatchStrictTrue() {
+ TestPartitionDataStorage partitionStorage =
createPartitionDataStorage();
+ IndexUpdateHandler indexUpdateHandler = createIndexUpdateHandler();
+
+ GcUpdateHandler gcUpdateHandler =
createGcUpdateHandler(partitionStorage, indexUpdateHandler);
+
+ RowId rowId0 = new RowId(PARTITION_ID);
+ RowId rowId1 = new RowId(PARTITION_ID);
+
+ BinaryRow row0 = binaryRow(new TestKey(0, "key0"), new TestValue(0,
"value0"));
+ BinaryRow row1 = binaryRow(new TestKey(1, "key1"), new TestValue(1,
"value1"));
+
+ for (int i = 0; i < REPEATS; i++) {
+ addWriteCommitted(partitionStorage, rowId0, row0, clock.now());
+ addWriteCommitted(partitionStorage, rowId1, row1, clock.now());
+
+ addWriteCommitted(partitionStorage, rowId0, row0, clock.now());
+ addWriteCommitted(partitionStorage, rowId1, row1, clock.now());
+
+ addWriteCommitted(partitionStorage, rowId0, null, clock.now());
+ addWriteCommitted(partitionStorage, rowId1, null, clock.now());
+
+ runRace(
+ () ->
gcUpdateHandler.vacuumBatch(HybridTimestamp.MAX_VALUE, 2, true),
+ () ->
gcUpdateHandler.vacuumBatch(HybridTimestamp.MAX_VALUE, 2, true)
+ );
+
+
assertNull(partitionStorage.getStorage().closestRowId(RowId.lowestRowId(PARTITION_ID)));
+ }
+ }
+
+ @Test
+ void testConcurrentVacuumBatchStrictFalse() {
+ TestPartitionDataStorage partitionStorage =
createPartitionDataStorage();
+ IndexUpdateHandler indexUpdateHandler = createIndexUpdateHandler();
+
+ GcUpdateHandler gcUpdateHandler =
createGcUpdateHandler(partitionStorage, indexUpdateHandler);
+
+ RowId rowId0 = new RowId(PARTITION_ID);
+ RowId rowId1 = new RowId(PARTITION_ID);
+ RowId rowId2 = new RowId(PARTITION_ID);
+ RowId rowId3 = new RowId(PARTITION_ID);
+
+ BinaryRow row0 = binaryRow(new TestKey(0, "key0"), new TestValue(0,
"value0"));
+ BinaryRow row1 = binaryRow(new TestKey(1, "key1"), new TestValue(1,
"value1"));
+ BinaryRow row2 = binaryRow(new TestKey(2, "key2"), new TestValue(2,
"value2"));
+ BinaryRow row3 = binaryRow(new TestKey(3, "key3"), new TestValue(3,
"value3"));
+
+ for (int i = 0; i < REPEATS; i++) {
+ addWriteCommitted(partitionStorage, rowId0, row0, clock.now());
+ addWriteCommitted(partitionStorage, rowId1, row1, clock.now());
+ addWriteCommitted(partitionStorage, rowId2, row2, clock.now());
+ addWriteCommitted(partitionStorage, rowId3, row3, clock.now());
+
+ addWriteCommitted(partitionStorage, rowId0, null, clock.now());
+ addWriteCommitted(partitionStorage, rowId1, null, clock.now());
+ addWriteCommitted(partitionStorage, rowId2, null, clock.now());
+ addWriteCommitted(partitionStorage, rowId3, null, clock.now());
+
+ runRace(
+ () ->
gcUpdateHandler.vacuumBatch(HybridTimestamp.MAX_VALUE, 4, false),
+ () ->
gcUpdateHandler.vacuumBatch(HybridTimestamp.MAX_VALUE, 4, false)
+ );
+
+
assertNull(partitionStorage.getStorage().closestRowId(RowId.lowestRowId(PARTITION_ID)));
+ }
+ }
+
+ private TestPartitionDataStorage createPartitionDataStorage() {
+ return new
TestPartitionDataStorage(getOrCreateMvPartition(tableStorage, PARTITION_ID));
+ }
+
+ private static IndexUpdateHandler createIndexUpdateHandler() {
+ return new
IndexUpdateHandler(DummyInternalTableImpl.createTableIndexStoragesSupplier(Map.of()));
+ }
+
+ private static GcUpdateHandler createGcUpdateHandler(
+ PartitionDataStorage partitionDataStorage,
+ IndexUpdateHandler indexUpdateHandler
+ ) {
+ return new GcUpdateHandler(
+ partitionDataStorage,
+ new PendingComparableValuesTracker<>(new HybridTimestamp(1,
0)),
+ indexUpdateHandler
+ );
+ }
+
+ private static void addWriteCommitted(PartitionDataStorage storage, RowId
rowId, @Nullable BinaryRow row, HybridTimestamp timestamp) {
+ storage.runConsistently(locker -> {
+ locker.lock(rowId);
+
+ storage.addWrite(rowId, row, UUID.randomUUID(), 999, PARTITION_ID);
+
+ storage.commitWrite(rowId, timestamp);
+
+ return null;
+ });
+ }
+}
diff --git
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/GcUpdateHandlerTest.java
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/GcUpdateHandlerTest.java
deleted file mode 100644
index ca75d719a5..0000000000
---
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/GcUpdateHandlerTest.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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.table.distributed.gc;
-
-import static org.apache.ignite.internal.util.CursorUtils.emptyCursor;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.apache.ignite.distributed.TestPartitionDataStorage;
-import org.apache.ignite.internal.hlc.HybridTimestamp;
-import org.apache.ignite.internal.schema.BinaryRow;
-import org.apache.ignite.internal.storage.RowId;
-import org.apache.ignite.internal.storage.gc.GcEntry;
-import org.apache.ignite.internal.storage.impl.TestMvPartitionStorage;
-import org.apache.ignite.internal.table.distributed.TableIndexStoragesSupplier;
-import org.apache.ignite.internal.table.distributed.index.IndexUpdateHandler;
-import org.apache.ignite.internal.table.distributed.raft.PartitionDataStorage;
-import org.apache.ignite.internal.util.PendingComparableValuesTracker;
-import org.junit.jupiter.api.Test;
-
-/**
- * For {@link GcUpdateHandler} testing.
- */
-public class GcUpdateHandlerTest {
- private static final int PARTITION_ID = 0;
-
- @Test
- void testVacuum() {
- PartitionDataStorage partitionStorage = createPartitionDataStorage();
-
- IndexUpdateHandler indexUpdateHandler = spy(new
IndexUpdateHandler(mock(TableIndexStoragesSupplier.class)));
-
- GcUpdateHandler gcUpdateHandler =
createGcUpdateHandler(partitionStorage, indexUpdateHandler);
-
- HybridTimestamp lowWatermark = new HybridTimestamp(100, 100);
-
- assertFalse(gcUpdateHandler.vacuumBatch(lowWatermark, 1));
- verify(partitionStorage).peek(lowWatermark);
-
- // Let's check that StorageUpdateHandler#vacuumBatch returns true.
- clearInvocations(partitionStorage);
-
- RowId rowId = new RowId(PARTITION_ID);
-
- GcEntry gcEntry = new GcEntryImpl(rowId, lowWatermark);
- BinaryRow binaryRow = mock(BinaryRow.class);
-
-
when(partitionStorage.scanVersions(any(RowId.class))).thenReturn(emptyCursor());
- when(partitionStorage.peek(lowWatermark)).thenReturn(gcEntry);
- when(partitionStorage.vacuum(gcEntry)).thenReturn(binaryRow);
-
- assertTrue(gcUpdateHandler.vacuumBatch(lowWatermark, 1));
- verify(partitionStorage).peek(lowWatermark);
- verify(indexUpdateHandler).tryRemoveFromIndexes(binaryRow, rowId,
emptyCursor());
- }
-
- @Test
- void testVacuumBatch() {
- PartitionDataStorage partitionStorage = createPartitionDataStorage();
-
- IndexUpdateHandler indexUpdateHandler = spy(new
IndexUpdateHandler(mock(TableIndexStoragesSupplier.class)));
-
- GcUpdateHandler gcUpdateHandler =
createGcUpdateHandler(partitionStorage, indexUpdateHandler);
-
- HybridTimestamp lowWatermark = new HybridTimestamp(100, 100);
-
- RowId rowId0 = new RowId(PARTITION_ID);
- RowId rowId1 = new RowId(PARTITION_ID);
-
- BinaryRow binaryRow0 = mock(BinaryRow.class);
- BinaryRow binaryRow1 = mock(BinaryRow.class);
-
- GcEntry gcEntry0 = new GcEntryImpl(rowId0, lowWatermark);
- GcEntry gcEntry1 = new GcEntryImpl(rowId1, lowWatermark);
-
-
when(partitionStorage.peek(lowWatermark)).thenReturn(gcEntry0).thenReturn(gcEntry1).thenReturn(null);
- when(partitionStorage.vacuum(gcEntry0)).thenReturn(binaryRow0);
- when(partitionStorage.vacuum(gcEntry1)).thenReturn(binaryRow1);
-
- assertFalse(gcUpdateHandler.vacuumBatch(lowWatermark, 5));
-
- verify(partitionStorage, times(3)).peek(lowWatermark);
- verify(partitionStorage).vacuum(gcEntry0);
- verify(partitionStorage).vacuum(gcEntry1);
- }
-
- private GcUpdateHandler createGcUpdateHandler(PartitionDataStorage
partitionStorage, IndexUpdateHandler indexUpdateHandler) {
- return new GcUpdateHandler(
- partitionStorage,
- new PendingComparableValuesTracker<>(new HybridTimestamp(1,
0)),
- indexUpdateHandler
- );
- }
-
- private static PartitionDataStorage createPartitionDataStorage() {
- PartitionDataStorage partitionStorage = spy(new
TestPartitionDataStorage(new TestMvPartitionStorage(PARTITION_ID)));
-
- return partitionStorage;
- }
-
- private static class GcEntryImpl implements GcEntry {
- private final RowId rowId;
-
- private final HybridTimestamp timestamp;
-
- private GcEntryImpl(RowId rowId, HybridTimestamp timestamp) {
- this.rowId = rowId;
- this.timestamp = timestamp;
- }
-
- @Override
- public RowId getRowId() {
- return rowId;
- }
-
- @Override
- public HybridTimestamp getTimestamp() {
- return timestamp;
- }
- }
-}
diff --git
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/MvGcTest.java
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/MvGcTest.java
index febf9fb402..c4d2268229 100644
---
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/MvGcTest.java
+++
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/MvGcTest.java
@@ -30,6 +30,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -380,7 +381,7 @@ public class MvGcTest {
CompletableFuture<Void> future,
@Nullable HybridTimestamp exp
) {
- when(gcUpdateHandler.vacuumBatch(any(HybridTimestamp.class),
anyInt())).then(invocation -> {
+ when(gcUpdateHandler.vacuumBatch(any(HybridTimestamp.class), anyInt(),
eq(true))).then(invocation -> {
if (exp != null) {
try {
assertEquals(exp, invocation.getArgument(0));
@@ -400,7 +401,7 @@ public class MvGcTest {
private GcUpdateHandler createWithCountDownOnVacuum(CountDownLatch latch) {
GcUpdateHandler gcUpdateHandler = createGcUpdateHandler();
- when(gcUpdateHandler.vacuumBatch(any(HybridTimestamp.class),
anyInt())).then(invocation -> {
+ when(gcUpdateHandler.vacuumBatch(any(HybridTimestamp.class), anyInt(),
eq(true))).then(invocation -> {
latch.countDown();
return latch.getCount() > 0;
@@ -412,7 +413,7 @@ public class MvGcTest {
private GcUpdateHandler createWithWaitFinishVacuum(CompletableFuture<Void>
startFuture, CompletableFuture<Void> finishFuture) {
GcUpdateHandler gcUpdateHandler = createGcUpdateHandler();
- when(gcUpdateHandler.vacuumBatch(any(HybridTimestamp.class),
anyInt())).then(invocation -> {
+ when(gcUpdateHandler.vacuumBatch(any(HybridTimestamp.class), anyInt(),
eq(true))).then(invocation -> {
startFuture.complete(null);
finishFuture.get(1, TimeUnit.SECONDS);
@@ -432,7 +433,7 @@ public class MvGcTest {
private GcUpdateHandler
createWithCountDownOnVacuumWithoutNextBatch(CountDownLatch latch) {
GcUpdateHandler gcUpdateHandler = createGcUpdateHandler();
- when(gcUpdateHandler.vacuumBatch(any(HybridTimestamp.class),
anyInt())).then(invocation -> {
+ when(gcUpdateHandler.vacuumBatch(any(HybridTimestamp.class), anyInt(),
eq(true))).then(invocation -> {
latch.countDown();
// So that there is no processing of the next batch.
diff --git
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/PersistentPageMemoryMvStorageUpdateHandlerTest.java
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/PersistentPageMemoryGcUpdateHandlerTest.java
similarity index 95%
rename from
modules/table/src/test/java/org/apache/ignite/internal/table/distributed/PersistentPageMemoryMvStorageUpdateHandlerTest.java
rename to
modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/PersistentPageMemoryGcUpdateHandlerTest.java
index 61e27735cd..ca779e840c 100644
---
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/PersistentPageMemoryMvStorageUpdateHandlerTest.java
+++
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/PersistentPageMemoryGcUpdateHandlerTest.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.table.distributed;
+package org.apache.ignite.internal.table.distributed.gc;
import static
org.apache.ignite.internal.distributionzones.DistributionZoneManager.DEFAULT_PARTITION_COUNT;
import static
org.apache.ignite.internal.storage.pagememory.configuration.schema.BasePageMemoryStorageEngineConfigurationSchema.DEFAULT_DATA_REGION_NAME;
@@ -40,7 +40,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(WorkDirectoryExtension.class)
@ExtendWith(ConfigurationExtension.class)
-class PersistentPageMemoryMvStorageUpdateHandlerTest extends
AbstractMvStorageUpdateHandlerTest {
+class PersistentPageMemoryGcUpdateHandlerTest extends
AbstractGcUpdateHandlerTest {
@WorkDirectory
private Path workDir;
diff --git
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/RocksDbMvStorageUpdateHandlerTest.java
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/RocksDbGcUpdateHandlerTest.java
similarity index 95%
rename from
modules/table/src/test/java/org/apache/ignite/internal/table/distributed/RocksDbMvStorageUpdateHandlerTest.java
rename to
modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/RocksDbGcUpdateHandlerTest.java
index 2ad90e3ffc..e47f5e141a 100644
---
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/RocksDbMvStorageUpdateHandlerTest.java
+++
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/RocksDbGcUpdateHandlerTest.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.table.distributed;
+package org.apache.ignite.internal.table.distributed.gc;
import static
org.apache.ignite.internal.distributionzones.DistributionZoneManager.DEFAULT_PARTITION_COUNT;
import static
org.apache.ignite.internal.storage.pagememory.configuration.schema.BasePageMemoryStorageEngineConfigurationSchema.DEFAULT_DATA_REGION_NAME;
@@ -38,7 +38,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(WorkDirectoryExtension.class)
@ExtendWith(ConfigurationExtension.class)
-class RocksDbMvStorageUpdateHandlerTest extends
AbstractMvStorageUpdateHandlerTest {
+class RocksDbGcUpdateHandlerTest extends AbstractGcUpdateHandlerTest {
@WorkDirectory
private Path workDir;
diff --git
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/TestMvStorageUpdateHandlerTest.java
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/TestGcUpdateHandlerTest.java
similarity index 89%
rename from
modules/table/src/test/java/org/apache/ignite/internal/table/distributed/TestMvStorageUpdateHandlerTest.java
rename to
modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/TestGcUpdateHandlerTest.java
index aebcf89b52..02ea69c9e4 100644
---
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/TestMvStorageUpdateHandlerTest.java
+++
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/TestGcUpdateHandlerTest.java
@@ -15,14 +15,14 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.table.distributed;
+package org.apache.ignite.internal.table.distributed.gc;
import static
org.apache.ignite.internal.distributionzones.DistributionZoneManager.DEFAULT_PARTITION_COUNT;
import org.apache.ignite.internal.storage.impl.TestMvTableStorage;
import org.junit.jupiter.api.BeforeEach;
-class TestMvStorageUpdateHandlerTest extends
AbstractMvStorageUpdateHandlerTest {
+class TestGcUpdateHandlerTest extends AbstractGcUpdateHandlerTest {
@BeforeEach
void setUp() {
initialize(new TestMvTableStorage(1, DEFAULT_PARTITION_COUNT));
diff --git
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/VolatilePageMemoryMvStorageUpdateHandlerTest.java
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/VolatilePageMemoryGcUpdateHandlerTest.java
similarity index 95%
rename from
modules/table/src/test/java/org/apache/ignite/internal/table/distributed/VolatilePageMemoryMvStorageUpdateHandlerTest.java
rename to
modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/VolatilePageMemoryGcUpdateHandlerTest.java
index c9c1ade0ea..6536bba553 100644
---
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/VolatilePageMemoryMvStorageUpdateHandlerTest.java
+++
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/gc/VolatilePageMemoryGcUpdateHandlerTest.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.table.distributed;
+package org.apache.ignite.internal.table.distributed.gc;
import static
org.apache.ignite.internal.distributionzones.DistributionZoneManager.DEFAULT_PARTITION_COUNT;
import static
org.apache.ignite.internal.storage.pagememory.configuration.schema.BasePageMemoryStorageEngineConfigurationSchema.DEFAULT_DATA_REGION_NAME;
@@ -36,7 +36,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(ConfigurationExtension.class)
-class VolatilePageMemoryMvStorageUpdateHandlerTest extends
AbstractMvStorageUpdateHandlerTest {
+class VolatilePageMemoryGcUpdateHandlerTest extends
AbstractGcUpdateHandlerTest {
private VolatilePageMemoryStorageEngine engine;
private VolatilePageMemoryTableStorage table;