This is an automated email from the ASF dual-hosted git repository. ilyak 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 732268e IGNITE-13507 Fix NullPointerException on tx recovery - Fixes #8547. 732268e is described below commit 732268ee040921333701bdc87fa5b77e1067d9fc Author: pvinokurov <vinokurov.pa...@gmail.com> AuthorDate: Fri Dec 25 16:15:13 2020 +0300 IGNITE-13507 Fix NullPointerException on tx recovery - Fixes #8547. Signed-off-by: Ilya Kasnacheev <ilya.kasnach...@gmail.com> --- .../cache/transactions/IgniteTxManager.java | 9 +- .../TxRecoveryOnCoordniatorFailTest.java | 116 +++++++++++++++++++++ .../ignite/testsuites/IgniteCacheTestSuite9.java | 2 + 3 files changed, 124 insertions(+), 3 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java index 34834ba..a561b9b 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java @@ -3375,9 +3375,12 @@ public class IgniteTxManager extends GridCacheSharedManagerAdapter { * @return True if message required, false otherwise. */ private boolean isMvccRecoveryMessageRequired() { - return node.isClient() && mvccCrd != null && mvccCrd.nodeId() != null && - (cctx.kernalContext().coordinators().mvccEnabled() || - !IgniteFeatures.nodeSupports(cctx.node(mvccCrd.nodeId()), IgniteFeatures.MVCC_TX_RECOVERY_PROTOCOL_V2)); + ClusterNode mvccCrdNode = null; + + if (mvccCrd != null && mvccCrd.nodeId() != null) + mvccCrdNode = cctx.node(mvccCrd.nodeId()); + + return node.isClient() && mvccCrdNode != null && cctx.kernalContext().coordinators().mvccEnabled(); } /** diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRecoveryOnCoordniatorFailTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRecoveryOnCoordniatorFailTest.java new file mode 100644 index 0000000..d45c434 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRecoveryOnCoordniatorFailTest.java @@ -0,0 +1,116 @@ +/* + * 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.transactions; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicReference; +import org.apache.ignite.Ignite; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.failure.AbstractFailureHandler; +import org.apache.ignite.failure.FailureContext; +import org.apache.ignite.internal.managers.communication.GridIoPolicy; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.junit.Assert; +import org.junit.Test; + +/** + * Tests failure handler is not triggered after client node and coordinator left cluster. + */ +public class TxRecoveryOnCoordniatorFailTest extends GridCommonAbstractTest { + /** */ + private AtomicReference<Throwable> err; + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { + return super.getConfiguration(igniteInstanceName) + .setSystemThreadPoolSize(1) + .setFailureHandler(new AbstractFailureHandler() { + @Override protected boolean handle(Ignite ignite, FailureContext failureCtx) { + err.compareAndSet(null, failureCtx.error()); + + return false; + } + }); + } + + /** {@inheritDoc} */ + @Override protected void beforeTest() throws Exception { + super.beforeTest(); + + stopAllGrids(); + + err = new AtomicReference<>(); + } + + /** {@inheritDoc} */ + @Override protected void afterTest() throws Exception { + super.afterTest(); + + stopAllGrids(); + } + + /** + * Checks for the absence of critical failures caused by tx recovery after client and coordinator left the cluster. + * <p>Test scenario:</p> + * <ul> + * <li>Start 2 server nodes and client node.</li> + * <li>Execute long runing task in the single threaded system pool on the second server node. It delays execution of tx recovery.</li> + * <li>Stop client and coordinator nodes.</li> + * <li>Check triggering of failure handler.</li> + * </ul> + * + * @throws Exception If failed. + */ + @Test + public void testCoordinatorLeftCluster() throws Exception { + startGrids(2); + + Ignite client = startClientGrid(2); + + Executor sysPool = grid(1).context().pools().poolForPolicy(GridIoPolicy.SYSTEM_POOL); + + sysPool.execute(new Runnable() { + @Override public void run() { + try { + waitForTopology(1); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + catch (Exception ignored) { + } + } + }); + + client.close(); + + grid(0).close(); + + // Make sure that tx recovery is already executed in the system thread pool. + CountDownLatch latch = new CountDownLatch(1); + sysPool.execute(latch::countDown); + + latch.await(); + + Throwable error = err.get(); + + if (error != null) + Assert.fail("Critical failure occurred '" + error + "'"); + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite9.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite9.java index 3a7dc5b..1923e5f 100644 --- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite9.java +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite9.java @@ -61,6 +61,7 @@ import org.apache.ignite.internal.processors.cache.transactions.TxPartitionCount import org.apache.ignite.internal.processors.cache.transactions.TxPartitionCounterStatePutTest; import org.apache.ignite.internal.processors.cache.transactions.TxPartitionCounterStateTwoPrimaryTwoBackupsTest; import org.apache.ignite.internal.processors.cache.transactions.TxPartitionCounterStateWithFilterTest; +import org.apache.ignite.internal.processors.cache.transactions.TxRecoveryOnCoordniatorFailTest; import org.apache.ignite.testframework.GridTestUtils; import org.apache.ignite.testframework.junits.DynamicSuite; import org.junit.runner.RunWith; @@ -140,6 +141,7 @@ public class IgniteCacheTestSuite9 { GridTestUtils.addTestIfNeeded(suite, GridCacheDataTypesCoverageTest.class, ignoredTests); GridTestUtils.addTestIfNeeded(suite, RebalanceStatisticsTest.class, ignoredTests); + GridTestUtils.addTestIfNeeded(suite, TxRecoveryOnCoordniatorFailTest.class, ignoredTests); return suite; }