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