You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by gv...@apache.org on 2019/01/31 16:28:26 UTC
[ignite] branch master updated: IGNITE-11029: Public API for
edge-chasing deadlock detection configuration. This closes #5896.
This is an automated email from the ASF dual-hosted git repository.
gvvinblade 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 07a0a6a IGNITE-11029: Public API for edge-chasing deadlock detection configuration. This closes #5896.
07a0a6a is described below
commit 07a0a6a76e768f36d4caaa5ba7ea5ff48fc1983c
Author: ipavlukhin <vo...@gmail.com>
AuthorDate: Thu Jan 31 19:27:59 2019 +0300
IGNITE-11029: Public API for edge-chasing deadlock detection configuration. This closes #5896.
---
.../org/apache/ignite/IgniteSystemProperties.java | 12 --
.../configuration/TransactionConfiguration.java | 58 +++++++-
.../processors/cache/GridCacheProcessor.java | 38 +++--
.../cache/mvcc/DeadlockDetectionManager.java | 13 +-
.../platform/utils/PlatformConfigurationUtils.java | 6 +-
.../mvcc/CacheMvccSqlTxQueriesAbstractTest.java | 17 +--
...cheMvccSqlTxQueriesWithReducerAbstractTest.java | 21 +--
.../mvcc/MvccDeadlockDetectionConfigTest.java | 159 +++++++++++++++++++++
.../cache/mvcc/MvccDeadlockDetectionTest.java | 26 +---
.../testsuites/IgniteCacheMvccSqlTestSuite.java | 2 +
.../Apache.Ignite.Core/IgniteConfiguration.cs | 4 +-
.../IgniteConfigurationSection.xsd | 20 ++-
.../Transactions/TransactionConfiguration.cs | 13 +-
13 files changed, 300 insertions(+), 89 deletions(-)
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
index a2d1565..b9413e2 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
@@ -261,18 +261,6 @@ public final class IgniteSystemProperties {
public static final String IGNITE_TX_DEADLOCK_DETECTION_TIMEOUT = "IGNITE_TX_DEADLOCK_DETECTION_TIMEOUT";
/**
- * Specifies delay in milliseconds before starting deadlock detection procedure when tx encounters locked key.
- * <p>
- * Following values could be used:
- * <ul>
- * <li>< 0 disable detection;</li>
- * <li>0 start detection without a delay;</li>
- * <li>> 0 start detection after a specified number of milliseconds.</li>
- * </ul>
- */
- public static final String IGNITE_TX_DEADLOCK_DETECTION_INITIAL_DELAY = "IGNITE_TX_DEADLOCK_DETECTION_INITIAL_DELAY";
-
- /**
* System property to enable pending transaction tracker.
* Affects impact of {@link IgniteSystemProperties#IGNITE_DISABLE_WAL_DURING_REBALANCING} property:
* if this property is set, WAL anyway won't be disabled during rebalancing triggered by baseline topology change.
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/TransactionConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/TransactionConfiguration.java
index e669bcf..91048eaf 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/TransactionConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/TransactionConfiguration.java
@@ -18,7 +18,9 @@
package org.apache.ignite.configuration;
import java.io.Serializable;
+import java.util.ArrayList;
import javax.cache.configuration.Factory;
+import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.internal.util.TransientSerializable;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.lang.IgniteProductVersion;
@@ -35,6 +37,9 @@ public class TransactionConfiguration implements Serializable {
private static final IgniteProductVersion TX_PME_TIMEOUT_SINCE = IgniteProductVersion.fromString("2.5.1");
/** */
+ private static final IgniteProductVersion DEADLOCK_TIMEOUT_SINCE = IgniteProductVersion.fromString("2.7.3");
+
+ /** */
private static final long serialVersionUID = 0L;
/** Default value for 'txSerializableEnabled' flag. */
@@ -52,6 +57,9 @@ public class TransactionConfiguration implements Serializable {
/** Transaction timeout on partition map synchronization. */
public static final long TX_TIMEOUT_ON_PARTITION_MAP_EXCHANGE = 0;
+ /** Default timeout before starting deadlock detection. */
+ public static final long DFLT_DEADLOCK_TIMEOUT = 10_000;
+
/** Default size of pessimistic transactions log. */
public static final int DFLT_PESSIMISTIC_TX_LOG_LINGER = 10_000;
@@ -67,9 +75,15 @@ public class TransactionConfiguration implements Serializable {
/** Default transaction timeout. */
private long dfltTxTimeout = DFLT_TRANSACTION_TIMEOUT;
- /** Transaction timeout on partition map exchange. */
+ /**
+ * Transaction timeout on partition map exchange.
+ * Volatile in order to be changed dynamically.
+ */
private volatile long txTimeoutOnPartitionMapExchange = TX_TIMEOUT_ON_PARTITION_MAP_EXCHANGE;
+ /** Timeout before starting deadlock detection. */
+ private long deadlockTimeout = DFLT_DEADLOCK_TIMEOUT;
+
/** Pessimistic tx log size. */
private int pessimisticTxLogSize;
@@ -103,6 +117,7 @@ public class TransactionConfiguration implements Serializable {
dfltIsolation = cfg.getDefaultTxIsolation();
dfltTxTimeout = cfg.getDefaultTxTimeout();
txTimeoutOnPartitionMapExchange = cfg.getTxTimeoutOnPartitionMapExchange();
+ deadlockTimeout = cfg.getDeadlockTimeout();
pessimisticTxLogLinger = cfg.getPessimisticTxLogLinger();
pessimisticTxLogSize = cfg.getPessimisticTxLogSize();
txSerEnabled = cfg.isTxSerializableEnabled();
@@ -240,6 +255,38 @@ public class TransactionConfiguration implements Serializable {
}
/**
+ * Transaction deadlocks occurred for caches configured with {@link CacheAtomicityMode#TRANSACTIONAL_SNAPSHOT}
+ * can be resolved automatically.
+ * <p>
+ * Deadlock detection starts when one transaction is waiting for an entry lock more than a timeout specified by
+ * this property.
+ * <p>
+ * Timeout is specified in milliseconds and {@code 0} means that automatic deadlock detection is disabled. Default
+ * value is defined by {@link #DFLT_DEADLOCK_TIMEOUT}.
+ *
+ * @return Timeout before starting deadlock detection.
+ */
+ public long getDeadlockTimeout() {
+ return deadlockTimeout;
+ }
+
+ /**
+ * Sets a timeout before starting deadlock detection for caches configured with
+ * {@link CacheAtomicityMode#TRANSACTIONAL_SNAPSHOT}.
+ * <p>
+ * Timeout is specified in milliseconds and {@code 0} means that automatic deadlock detection is disabled. Default
+ * value is defined by {@link #DFLT_DEADLOCK_TIMEOUT}.
+ *
+ * @param deadlockTimeout Timeout value in milliseconds.
+ * @return {@code this} for chaining.
+ */
+ public TransactionConfiguration setDeadlockTimeout(long deadlockTimeout) {
+ this.deadlockTimeout = deadlockTimeout;
+
+ return this;
+ }
+
+ /**
* Gets size of pessimistic transactions log stored on node in order to recover transaction commit if originating
* node has left grid before it has sent all messages to transaction nodes.
* <p>
@@ -402,9 +449,14 @@ public class TransactionConfiguration implements Serializable {
*/
@SuppressWarnings("unused")
private static String[] transientSerializableFields(IgniteProductVersion ver) {
+ ArrayList<String> transients = new ArrayList<>(2);
+
if (TX_PME_TIMEOUT_SINCE.compareToIgnoreTimestamp(ver) >= 0)
- return new String[] { "txTimeoutOnPartitionMapExchange" };
+ transients.add("txTimeoutOnPartitionMapExchange");
+
+ if (DEADLOCK_TIMEOUT_SINCE.compareToIgnoreTimestamp(ver) >= 0)
+ transients.add("deadlockTimeout");
- return null;
+ return transients.isEmpty() ? null : transients.toArray(new String[transients.size()]);
}
}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
index 84dfe37..6082bd1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
@@ -4513,20 +4513,42 @@ public class GridCacheProcessor extends GridProcessorAdapter {
* @throws IgniteCheckedException If check failed.
*/
private void checkTransactionConfiguration(ClusterNode rmt) throws IgniteCheckedException {
- TransactionConfiguration txCfg = rmt.attribute(ATTR_TX_CONFIG);
+ TransactionConfiguration rmtTxCfg = rmt.attribute(ATTR_TX_CONFIG);
- if (txCfg != null) {
+ if (rmtTxCfg != null) {
TransactionConfiguration locTxCfg = ctx.config().getTransactionConfiguration();
- if (locTxCfg.isTxSerializableEnabled() != txCfg.isTxSerializableEnabled())
- throw new IgniteCheckedException("Serializable transactions enabled mismatch " +
- "(fix txSerializableEnabled property or set -D" + IGNITE_SKIP_CONFIGURATION_CONSISTENCY_CHECK + "=true " +
- "system property) [rmtNodeId=" + rmt.id() +
- ", locTxSerializableEnabled=" + locTxCfg.isTxSerializableEnabled() +
- ", rmtTxSerializableEnabled=" + txCfg.isTxSerializableEnabled() + ']');
+ checkDeadlockDetectionConfig(rmt, rmtTxCfg, locTxCfg);
+
+ checkSerializableEnabledConfig(rmt, rmtTxCfg, locTxCfg);
}
}
+ /** */
+ private void checkDeadlockDetectionConfig(ClusterNode rmt, TransactionConfiguration rmtTxCfg,
+ TransactionConfiguration locTxCfg) {
+ boolean locDeadlockDetectionEnabled = locTxCfg.getDeadlockTimeout() > 0;
+ boolean rmtDeadlockDetectionEnabled = rmtTxCfg.getDeadlockTimeout() > 0;
+
+ if (locDeadlockDetectionEnabled != rmtDeadlockDetectionEnabled) {
+ U.warn(log, "Deadlock detection is enabled on one node and disabled on another. " +
+ "Disabled detection on one node can lead to undetected deadlocks. [rmtNodeId=" + rmt.id() +
+ ", locDeadlockTimeout=" + locTxCfg.getDeadlockTimeout() +
+ ", rmtDeadlockTimeout=" + rmtTxCfg.getDeadlockTimeout());
+ }
+ }
+
+ /** */
+ private void checkSerializableEnabledConfig(ClusterNode rmt, TransactionConfiguration rmtTxCfg,
+ TransactionConfiguration locTxCfg) throws IgniteCheckedException {
+ if (locTxCfg.isTxSerializableEnabled() != rmtTxCfg.isTxSerializableEnabled())
+ throw new IgniteCheckedException("Serializable transactions enabled mismatch " +
+ "(fix txSerializableEnabled property or set -D" + IGNITE_SKIP_CONFIGURATION_CONSISTENCY_CHECK + "=true " +
+ "system property) [rmtNodeId=" + rmt.id() +
+ ", locTxSerializableEnabled=" + locTxCfg.isTxSerializableEnabled() +
+ ", rmtTxSerializableEnabled=" + rmtTxCfg.isTxSerializableEnabled() + ']');
+ }
+
/**
* @param rmt Remote node to check.
* @throws IgniteCheckedException If check failed.
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/DeadlockDetectionManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/DeadlockDetectionManager.java
index 9b1969b..880a4cc 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/DeadlockDetectionManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/DeadlockDetectionManager.java
@@ -37,7 +37,6 @@ import org.apache.ignite.internal.processors.timeout.GridTimeoutObjectAdapter;
import org.apache.ignite.internal.transactions.IgniteTxRollbackCheckedException;
import static java.util.Collections.singleton;
-import static org.apache.ignite.IgniteSystemProperties.IGNITE_TX_DEADLOCK_DETECTION_INITIAL_DELAY;
import static org.apache.ignite.internal.GridTopic.TOPIC_DEADLOCK_DETECTION;
import static org.apache.ignite.internal.managers.communication.GridIoPolicy.SYSTEM_POOL;
import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.belongToSameTx;
@@ -53,10 +52,12 @@ import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.belongT
*/
public class DeadlockDetectionManager extends GridCacheSharedManagerAdapter {
/** */
- private final long detectionStartDelay = Long.getLong(IGNITE_TX_DEADLOCK_DETECTION_INITIAL_DELAY, 10_000);
+ private long detectionStartDelay;
/** {@inheritDoc} */
@Override protected void start0() throws IgniteCheckedException {
+ detectionStartDelay = cctx.kernalContext().config().getTransactionConfiguration().getDeadlockTimeout();
+
cctx.gridIO().addMessageListener(TOPIC_DEADLOCK_DETECTION, (nodeId, msg, plc) -> {
if (msg instanceof DeadlockProbe) {
if (log.isDebugEnabled())
@@ -79,14 +80,8 @@ public class DeadlockDetectionManager extends GridCacheSharedManagerAdapter {
* @return Cancellable computation.
*/
public DelayedDeadlockComputation initDelayedComputation(MvccVersion waiterVer, MvccVersion blockerVer) {
- if (detectionStartDelay < 0)
- return null;
-
- if (detectionStartDelay == 0) {
- startComputation(waiterVer, blockerVer);
-
+ if (detectionStartDelay <= 0)
return null;
- }
return new DelayedDeadlockComputation(waiterVer, blockerVer, detectionStartDelay);
}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
index a316b59..4e0140c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
@@ -69,7 +69,6 @@ import org.apache.ignite.configuration.PersistentStoreConfiguration;
import org.apache.ignite.configuration.SqlConnectorConfiguration;
import org.apache.ignite.configuration.TransactionConfiguration;
import org.apache.ignite.configuration.WALMode;
-import org.apache.ignite.spi.encryption.EncryptionSpi;
import org.apache.ignite.events.Event;
import org.apache.ignite.failure.FailureHandler;
import org.apache.ignite.failure.NoOpFailureHandler;
@@ -100,8 +99,9 @@ import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
import org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
-import org.apache.ignite.spi.encryption.noop.NoopEncryptionSpi;
+import org.apache.ignite.spi.encryption.EncryptionSpi;
import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionSpi;
+import org.apache.ignite.spi.encryption.noop.NoopEncryptionSpi;
import org.apache.ignite.spi.eventstorage.EventStorageSpi;
import org.apache.ignite.spi.eventstorage.NoopEventStorageSpi;
import org.apache.ignite.spi.eventstorage.memory.MemoryEventStorageSpi;
@@ -788,6 +788,7 @@ public class PlatformConfigurationUtils {
tx.setDefaultTxTimeout(in.readLong());
tx.setPessimisticTxLogLinger(in.readInt());
tx.setTxTimeoutOnPartitionMapExchange(in.readLong());
+ tx.setDeadlockTimeout(in.readLong());
cfg.setTransactionConfiguration(tx);
}
@@ -1393,6 +1394,7 @@ public class PlatformConfigurationUtils {
w.writeLong(tx.getDefaultTxTimeout());
w.writeInt(tx.getPessimisticTxLogLinger());
w.writeLong(tx.getTxTimeoutOnPartitionMapExchange());
+ w.writeLong(tx.getDeadlockTimeout());
}
else
w.writeBoolean(false);
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesAbstractTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesAbstractTest.java
index a16df2a..5c53215 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesAbstractTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesAbstractTest.java
@@ -43,6 +43,8 @@ import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.cache.query.FieldsQueryCursor;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.TransactionConfiguration;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.IgniteCacheProxy;
@@ -65,7 +67,6 @@ import org.apache.ignite.transactions.Transaction;
import org.junit.Ignore;
import org.junit.Test;
-import static org.apache.ignite.IgniteSystemProperties.IGNITE_TX_DEADLOCK_DETECTION_INITIAL_DELAY;
import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
import static org.apache.ignite.internal.processors.cache.mvcc.CacheMvccAbstractTest.ReadMode.SQL;
import static org.apache.ignite.internal.processors.cache.mvcc.CacheMvccAbstractTest.ReadMode.SQL_SUM;
@@ -80,17 +81,9 @@ import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_REA
*/
public abstract class CacheMvccSqlTxQueriesAbstractTest extends CacheMvccAbstractTest {
/** {@inheritDoc} */
- @Override protected void beforeTestsStarted() throws Exception {
- super.beforeTestsStarted();
-
- System.setProperty(IGNITE_TX_DEADLOCK_DETECTION_INITIAL_DELAY, "-1");
- }
-
- /** {@inheritDoc} */
- @Override protected void afterTestsStopped() throws Exception {
- System.clearProperty(IGNITE_TX_DEADLOCK_DETECTION_INITIAL_DELAY);
-
- super.afterTestsStopped();
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ return super.getConfiguration(gridName)
+ .setTransactionConfiguration(new TransactionConfiguration().setDeadlockTimeout(0));
}
/**
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesWithReducerAbstractTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesWithReducerAbstractTest.java
index f7a5a80..ea868f9 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesWithReducerAbstractTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesWithReducerAbstractTest.java
@@ -32,6 +32,8 @@ import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.query.FieldsQueryCursor;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.TransactionConfiguration;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.processors.query.IgniteSQLException;
import org.apache.ignite.internal.transactions.IgniteTxTimeoutCheckedException;
@@ -41,7 +43,6 @@ import org.apache.ignite.testframework.GridTestUtils;
import org.apache.ignite.transactions.Transaction;
import org.junit.Test;
-import static org.apache.ignite.IgniteSystemProperties.IGNITE_TX_DEADLOCK_DETECTION_INITIAL_DELAY;
import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
import static org.apache.ignite.testframework.GridTestUtils.assertThrowsWithCause;
import static org.apache.ignite.testframework.GridTestUtils.runMultiThreaded;
@@ -52,23 +53,15 @@ import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_REA
* Tests for transactional SQL.
*/
public abstract class CacheMvccSqlTxQueriesWithReducerAbstractTest extends CacheMvccAbstractTest {
- /** {@inheritDoc} */
- @Override protected void beforeTestsStarted() throws Exception {
- super.beforeTestsStarted();
-
- System.setProperty(IGNITE_TX_DEADLOCK_DETECTION_INITIAL_DELAY, "-1");
- }
+ /** */
+ private static final int TIMEOUT = 3000;
/** {@inheritDoc} */
- @Override protected void afterTestsStopped() throws Exception {
- System.clearProperty(IGNITE_TX_DEADLOCK_DETECTION_INITIAL_DELAY);
-
- super.afterTestsStopped();
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ return super.getConfiguration(gridName)
+ .setTransactionConfiguration(new TransactionConfiguration().setDeadlockTimeout(0));
}
- /** */
- private static final int TIMEOUT = 3000;
-
/** {@inheritDoc} */
@Override protected void beforeTest() throws Exception {
super.beforeTest();
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/MvccDeadlockDetectionConfigTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/MvccDeadlockDetectionConfigTest.java
new file mode 100644
index 0000000..50157da
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/MvccDeadlockDetectionConfigTest.java
@@ -0,0 +1,159 @@
+/*
+ * 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.mvcc;
+
+import java.util.concurrent.CyclicBarrier;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.TransactionConfiguration;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.transactions.IgniteTxRollbackCheckedException;
+import org.apache.ignite.internal.transactions.IgniteTxTimeoutCheckedException;
+import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.transactions.Transaction;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT;
+import static org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC;
+import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ;
+
+/** */
+@RunWith(JUnit4.class)
+public class MvccDeadlockDetectionConfigTest extends GridCommonAbstractTest {
+ /** */
+ private boolean deadlockDetectionEnabled;
+
+ /** */
+ @After
+ public void stopCluster() {
+ stopAllGrids();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+ int timeout = deadlockDetectionEnabled ? 1 : 0;
+
+ return super.getConfiguration(igniteInstanceName)
+ .setTransactionConfiguration(new TransactionConfiguration().setDeadlockTimeout(timeout));
+ }
+
+ /** */
+ @Test
+ public void deadlockDetectionDisabled() throws Exception {
+ deadlockDetectionEnabled = false;
+
+ Ignite ign = startGrid();
+
+ IgniteCache<Object, Object> cache = ign.createCache(new CacheConfiguration<>(DEFAULT_CACHE_NAME)
+ .setAtomicityMode(TRANSACTIONAL_SNAPSHOT));
+
+ CyclicBarrier b = new CyclicBarrier(2);
+
+ int txTimeout = 3_000;
+
+ IgniteInternalFuture<?> futA = GridTestUtils.runAsync(() -> {
+ try (Transaction tx = ign.transactions().txStart(PESSIMISTIC, REPEATABLE_READ, txTimeout, 0)) {
+ cache.put(1, 'a');
+ b.await();
+ cache.put(2, 'a');
+ }
+
+ return null;
+ });
+
+ IgniteInternalFuture<?> futB = GridTestUtils.runAsync(() -> {
+ try (Transaction tx = ign.transactions().txStart(PESSIMISTIC, REPEATABLE_READ, txTimeout, 0)) {
+ cache.put(2, 'b');
+ b.await();
+ cache.put(1, 'b');
+ }
+
+ return null;
+ });
+
+ IgniteCheckedException e = awaitCompletion(futA, futB);
+
+ assertTrue(e.toString(), e.hasCause(IgniteTxTimeoutCheckedException.class));
+ }
+
+ /** */
+ @Test
+ public void deadlockDetectionEnabled() throws Exception {
+ deadlockDetectionEnabled = true;
+
+ Ignite ign = startGrid();
+
+ IgniteCache<Object, Object> cache = ign.createCache(new CacheConfiguration<>(DEFAULT_CACHE_NAME)
+ .setAtomicityMode(TRANSACTIONAL_SNAPSHOT));
+
+ CyclicBarrier b = new CyclicBarrier(2);
+
+ IgniteInternalFuture<?> futA = GridTestUtils.runAsync(() -> {
+ try (Transaction tx = ign.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
+ cache.put(1, 'a');
+ b.await();
+ cache.put(2, 'a');
+ }
+
+ return null;
+ });
+
+ IgniteInternalFuture<?> futB = GridTestUtils.runAsync(() -> {
+ try (Transaction tx = ign.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
+ cache.put(2, 'b');
+ b.await();
+ cache.put(1, 'b');
+ }
+
+ return null;
+ });
+
+ IgniteCheckedException e = awaitCompletion(futA, futB);
+
+ assertTrue(e.toString(), X.hasCause(e, "Deadlock", IgniteTxRollbackCheckedException.class));
+ }
+
+ /** */
+ private IgniteCheckedException awaitCompletion(IgniteInternalFuture<?> fut1, IgniteInternalFuture<?> fut2) {
+ IgniteCheckedException e = null;
+
+ try {
+ fut1.get(10_000);
+ }
+ catch (IgniteCheckedException e1) {
+ e = e1;
+ }
+
+ try {
+ fut2.get(10_000);
+ }
+ catch (IgniteCheckedException e1) {
+ e = e1;
+ }
+
+ return e;
+ }
+}
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/MvccDeadlockDetectionTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/MvccDeadlockDetectionTest.java
index fba0390..409e501 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/MvccDeadlockDetectionTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/MvccDeadlockDetectionTest.java
@@ -30,6 +30,7 @@ import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.TransactionConfiguration;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.IgniteInternalFuture;
import org.apache.ignite.internal.TestRecordingCommunicationSpi;
@@ -43,11 +44,8 @@ import org.apache.ignite.testframework.GridTestUtils.SF;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.apache.ignite.transactions.Transaction;
import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
import org.junit.Test;
-import static org.apache.ignite.IgniteSystemProperties.IGNITE_TX_DEADLOCK_DETECTION_INITIAL_DELAY;
import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT;
import static org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC;
import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ;
@@ -55,34 +53,22 @@ import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_REA
/** */
public class MvccDeadlockDetectionTest extends GridCommonAbstractTest {
/** */
- @BeforeClass
- public static void setUpClass() {
- System.setProperty(IGNITE_TX_DEADLOCK_DETECTION_INITIAL_DELAY, "0");
- }
-
- /** */
- @AfterClass
- public static void tearDownClass() {
- System.clearProperty(IGNITE_TX_DEADLOCK_DETECTION_INITIAL_DELAY);
- }
-
- /** */
private IgniteEx client;
/** {@inheritDoc} */
@Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
- IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
-
- cfg.setCommunicationSpi(new TestRecordingCommunicationSpi());
-
- return cfg;
+ return super.getConfiguration(igniteInstanceName)
+ .setCommunicationSpi(new TestRecordingCommunicationSpi())
+ .setTransactionConfiguration(new TransactionConfiguration().setDeadlockTimeout(1));
}
/** */
private void setUpGrids(int n, boolean indexed) throws Exception {
Ignite ign = startGridsMultiThreaded(n);
+
CacheConfiguration<Object, Object> ccfg = new CacheConfiguration<>(DEFAULT_CACHE_NAME)
.setAtomicityMode(TRANSACTIONAL_SNAPSHOT);
+
if (indexed)
ccfg.setIndexedTypes(Integer.class, Integer.class);
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheMvccSqlTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheMvccSqlTestSuite.java
index d1ed2f3..130e754 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheMvccSqlTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheMvccSqlTestSuite.java
@@ -67,6 +67,7 @@ import org.apache.ignite.internal.processors.cache.mvcc.CacheMvccSqlUpdateCounte
import org.apache.ignite.internal.processors.cache.mvcc.CacheMvccStreamingInsertTest;
import org.apache.ignite.internal.processors.cache.mvcc.CacheMvccTxNodeMappingTest;
import org.apache.ignite.internal.processors.cache.mvcc.CacheMvccTxRecoveryTest;
+import org.apache.ignite.internal.processors.cache.mvcc.MvccDeadlockDetectionConfigTest;
import org.apache.ignite.internal.processors.cache.mvcc.MvccDeadlockDetectionTest;
import org.apache.ignite.internal.processors.cache.mvcc.MvccRepeatableReadBulkOpsTest;
import org.apache.ignite.internal.processors.cache.mvcc.MvccRepeatableReadOperationsTest;
@@ -94,6 +95,7 @@ import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT;
CacheMvccTxNodeMappingTest.class,
+ MvccDeadlockDetectionConfigTest.class,
MvccDeadlockDetectionTest.class,
// SQL vs CacheAPI consistency.
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
index f293267..523ca65 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
@@ -515,6 +515,7 @@ namespace Apache.Ignite.Core
writer.WriteLong((long) TransactionConfiguration.DefaultTimeout.TotalMilliseconds);
writer.WriteInt((int) TransactionConfiguration.PessimisticTransactionLogLinger.TotalMilliseconds);
writer.WriteLong((long) TransactionConfiguration.DefaultDefaultTimeoutOnPartitionMapExchange.TotalMilliseconds);
+ writer.WriteLong((long) TransactionConfiguration.DeadlockTimeout.TotalMilliseconds);
}
else
writer.WriteBoolean(false);
@@ -841,7 +842,8 @@ namespace Apache.Ignite.Core
DefaultTransactionIsolation = (TransactionIsolation) r.ReadInt(),
DefaultTimeout = TimeSpan.FromMilliseconds(r.ReadLong()),
PessimisticTransactionLogLinger = TimeSpan.FromMilliseconds(r.ReadInt()),
- DefaultTimeoutOnPartitionMapExchange = TimeSpan.FromMilliseconds(r.ReadLong())
+ DefaultTimeoutOnPartitionMapExchange = TimeSpan.FromMilliseconds(r.ReadLong()),
+ DeadlockTimeout = TimeSpan.FromMilliseconds(r.ReadLong())
};
}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
index b023c3b..d1d7037 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
@@ -18,11 +18,10 @@
-->
<xs:schema id="IgniteConfigurationSection"
- targetNamespace="http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection"
- elementFormDefault="qualified"
- xmlns="http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection"
- xmlns:mstns="http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection"
- xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ targetNamespace="http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection"
+ elementFormDefault="qualified"
+ xmlns="http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="cacheMode" final="restriction">
<xs:restriction base="xs:string">
@@ -1278,6 +1277,13 @@
</xs:documentation>
</xs:annotation>
</xs:attribute>
+ <xs:attribute name="deadlockTimeout" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>
+ Timeout before starting deadlock detection. TimeSpan.Zero for disabling deadlock detection.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="logger" minOccurs="0">
@@ -1410,7 +1416,7 @@
</xs:annotation>
</xs:attribute>
</xs:complexType>
- </xs:element>
+ </xs:element>
<xs:element name="sqlConnectorConfiguration" minOccurs="0">
<xs:annotation>
<xs:documentation>SQL connector configuration (JDBC and ODBC).</xs:documentation>
@@ -1781,7 +1787,7 @@
<xs:documentation>Size of the checkpointing page buffer.</xs:documentation>
</xs:annotation>
</xs:attribute>
- </xs:complexType>
+ </xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Transactions/TransactionConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Transactions/TransactionConfiguration.cs
index e7f62f7..7220211 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Transactions/TransactionConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Transactions/TransactionConfiguration.cs
@@ -43,6 +43,9 @@ namespace Apache.Ignite.Core.Transactions
/// <summary> The default value for <see cref="DefaultTimeoutOnPartitionMapExchange"/></summary>
public static readonly TimeSpan DefaultDefaultTimeoutOnPartitionMapExchange = TimeSpan.Zero;
+ /// <summary> The default value for <see cref="DeadlockTimeout"/></summary>
+ public static readonly TimeSpan DefaultDeadlockTimeout = TimeSpan.FromSeconds(10);
+
/// <summary>
/// Gets or sets the cache transaction concurrency to use when one is not explicitly specified.
/// </summary>
@@ -63,7 +66,7 @@ namespace Apache.Ignite.Core.Transactions
public TimeSpan DefaultTimeout { get; set; }
/// <summary>
- /// Gets or sets the size of pessimistic transactions log stored on node in order to recover
+ /// Gets or sets the size of pessimistic transactions log stored on node in order to recover
/// transaction commit if originating node has left grid before it has sent all messages to transaction nodes.
/// <code>0</code> for unlimited.
/// </summary>
@@ -84,6 +87,13 @@ namespace Apache.Ignite.Core.Transactions
public TimeSpan DefaultTimeoutOnPartitionMapExchange { get; set; }
/// <summary>
+ /// Gets or sets timeout before starting deadlock detection.
+ /// <see cref="TimeSpan.Zero"/> for disabling deadlock detection.
+ /// </summary>
+ [DefaultValue(typeof(TimeSpan), "00:00:10")]
+ public TimeSpan DeadlockTimeout { get; set; }
+
+ /// <summary>
/// Initializes a new instance of the <see cref="TransactionConfiguration" /> class.
/// </summary>
public TransactionConfiguration()
@@ -94,6 +104,7 @@ namespace Apache.Ignite.Core.Transactions
PessimisticTransactionLogSize = DefaultPessimisticTransactionLogSize;
PessimisticTransactionLogLinger = DefaultPessimisticTransactionLogLinger;
DefaultTimeoutOnPartitionMapExchange = DefaultDefaultTimeoutOnPartitionMapExchange;
+ DeadlockTimeout = DefaultDeadlockTimeout;
}
}
}