You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by al...@apache.org on 2024/12/09 16:42:10 UTC
(ignite) branch master updated: IGNITE-23815 Fix assertion during RotatedIdPartRecord read from WAL - Fixes #11695.
This is an automated email from the ASF dual-hosted git repository.
alexpl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new fe029464b70 IGNITE-23815 Fix assertion during RotatedIdPartRecord read from WAL - Fixes #11695.
fe029464b70 is described below
commit fe029464b70ce04c21f25d5cf80ef25e1a2b742b
Author: Sergey Korotkov <se...@gmail.com>
AuthorDate: Mon Dec 9 19:37:52 2024 +0300
IGNITE-23815 Fix assertion during RotatedIdPartRecord read from WAL - Fixes #11695.
Signed-off-by: Aleksey Plekhanov <pl...@gmail.com>
---
.../wal/serializer/RecordDataV1Serializer.java | 2 +-
.../wal/WalRotatedIdPartRecordTest.java | 182 +++++++++++++++++++++
.../ignite/testsuites/IgnitePdsTestSuite7.java | 3 +
3 files changed, 186 insertions(+), 1 deletion(-)
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordDataV1Serializer.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordDataV1Serializer.java
index 0a77869f3ff..de920fddadf 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordDataV1Serializer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordDataV1Serializer.java
@@ -1177,7 +1177,7 @@ public class RecordDataV1Serializer implements RecordDataSerializer {
byte rotatedIdPart = in.readByte();
- res = new RotatedIdPartRecord(cacheId, pageId, rotatedIdPart);
+ res = new RotatedIdPartRecord(cacheId, pageId, Byte.toUnsignedInt(rotatedIdPart));
break;
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/WalRotatedIdPartRecordTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/WalRotatedIdPartRecordTest.java
new file mode 100644
index 00000000000..aa2ebb68fbd
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/WalRotatedIdPartRecordTest.java
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.persistence.wal;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import javax.cache.expiry.Duration;
+import javax.cache.expiry.TouchedExpiryPolicy;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
+import org.apache.ignite.cache.query.ScanQuery;
+import org.apache.ignite.cluster.ClusterState;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.RotatedIdPartRecord;
+import org.apache.ignite.internal.processors.cache.GridCacheMapEntry;
+import org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager;
+import org.apache.ignite.plugin.AbstractTestPluginProvider;
+import org.apache.ignite.plugin.PluginContext;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.config.Configurator;
+import org.jetbrains.annotations.Nullable;
+import org.junit.Test;
+
+import static org.apache.ignite.testframework.GridTestUtils.runAsync;
+
+/** */
+public class WalRotatedIdPartRecordTest extends GridCommonAbstractTest {
+ /** */
+ private static final int KEYS = 1000;
+
+ /** */
+ AtomicBoolean stop = new AtomicBoolean();
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+ if (!cfg.isClientMode()) {
+ cfg.setDataStorageConfiguration(new DataStorageConfiguration()
+ .setDefaultDataRegionConfiguration(new DataRegionConfiguration()
+ .setPersistenceEnabled(true)))
+ .setCacheConfiguration(new CacheConfiguration<>(DEFAULT_CACHE_NAME)
+ .setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL)
+ .setBackups(1)
+ .setAffinity(new RendezvousAffinityFunction().setPartitions(2))
+ .setExpiryPolicyFactory(TouchedExpiryPolicy.factoryOf(new Duration(TimeUnit.MINUTES, 60))));
+
+ // Plugin that creates a testing WAL manager.
+ cfg.setPluginProviders(new AbstractTestPluginProvider() {
+ /** {@inheritDoc} */
+ @Override public String name() {
+ return "testPlugin";
+ }
+
+ /** {@inheritDoc} */
+ @Override public <T> @Nullable T createComponent(PluginContext ctx, Class<T> cls) {
+ if (IgniteWriteAheadLogManager.class.equals(cls))
+ return (T)new TestFileWriteAheadLogManager(((IgniteEx)ctx.grid()).context(), stop);
+
+ return null;
+ }
+ });
+ }
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ super.beforeTest();
+
+ cleanPersistenceDir();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ super.afterTest();
+
+ stopAllGrids();
+
+ cleanPersistenceDir();
+ }
+
+ /** */
+ @Test
+ public void testRotatedIdMoreThan127() throws Exception {
+ startGrids(2).cluster().state(ClusterState.ACTIVE);
+
+ IgniteEx cln = startClientGrid(2);
+
+ for (int i = 0; i < KEYS; i++)
+ cln.cache(DEFAULT_CACHE_NAME).put(i, i);
+
+ forceCheckpoint();
+
+ disableCheckpoints(grid(0));
+ disableCheckpoints(grid(1));
+
+ IgniteInternalFuture<?> touchFut = runAsync(() -> {
+ while (!stop.get())
+ cln.cache(DEFAULT_CACHE_NAME).query(new ScanQuery<>()).forEach((v) -> {});
+ }, "touch");
+
+ try {
+ touchFut.get(getTestTimeout(), TimeUnit.MILLISECONDS);
+ }
+ catch (Exception ignored) {
+ touchFut.cancel();
+
+ fail(String.format("rotatedIdPart doesn't become > 127 in %d millisecs", getTestTimeout()));
+ }
+ finally {
+ // Turn off excessive logging of the "Failed to update TTL: class o.a.i.i.NodeStoppingException"
+ // during nodes stop. Errors are expected since not all GridCacheTtlUpdateRequest messages are processed yet.
+ Configurator.setLevel(GridCacheMapEntry.class.getName(), Level.OFF);
+ }
+
+ stopAllGrids();
+
+ // Restore logging.
+ Configurator.setLevel(GridCacheMapEntry.class.getName(), Level.ERROR);
+
+ startGrids(2).cluster().state(ClusterState.ACTIVE);
+ }
+
+ /** */
+ private void disableCheckpoints(IgniteEx ignite) throws IgniteCheckedException {
+ ((GridCacheDatabaseSharedManager)ignite.context().cache().context().database()).enableCheckpoints(false).get();
+ }
+
+ /** WAL manager that signals once meet the RotatedIdPartRecord with rotatedIdPart more than 127. */
+ private static class TestFileWriteAheadLogManager extends FileWriteAheadLogManager {
+ /** */
+ private final AtomicBoolean stop;
+
+ /** Constructor. */
+ public TestFileWriteAheadLogManager(GridKernalContext ctx, AtomicBoolean stop) {
+ super(ctx);
+
+ this.stop = stop;
+ }
+
+ /** {@inheritDoc} */
+ @Override public WALPointer log(WALRecord rec) throws IgniteCheckedException {
+ WALPointer res = super.log(rec);
+
+ if (rec instanceof RotatedIdPartRecord) {
+ byte rotatedIdPart = ((RotatedIdPartRecord)rec).rotatedIdPart();
+
+ if (Byte.toUnsignedInt(rotatedIdPart) > 127)
+ stop.set(true);
+ }
+
+ return res;
+ }
+ }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite7.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite7.java
index abc3637bb77..7cd4bb16d5b 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite7.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite7.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.ignite.internal.processors.cache.persistence.EagerTtlTest;
+import org.apache.ignite.internal.processors.cache.persistence.wal.WalRotatedIdPartRecordTest;
import org.apache.ignite.testframework.GridTestUtils;
import org.apache.ignite.testframework.junits.DynamicSuite;
import org.junit.runner.RunWith;
@@ -44,6 +45,8 @@ public class IgnitePdsTestSuite7 {
GridTestUtils.addTestIfNeeded(suite, EagerTtlTest.class, ignoredTests);
+ GridTestUtils.addTestIfNeeded(suite, WalRotatedIdPartRecordTest.class, ignoredTests);
+
return suite;
}
}