ignite-8297 For optimistic txs need finish KeyLockFutuer on timeout, otherwise it is possible it never finish
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/f4d834b6 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/f4d834b6 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/f4d834b6 Branch: refs/heads/ignite-8446 Commit: f4d834b697745a7b04c42cbb08ac7451300b8ab3 Parents: ce8c67e Author: sboikov <sboi...@apache.org> Authored: Thu Jul 26 15:01:00 2018 +0300 Committer: sboikov <sboi...@apache.org> Committed: Thu Jul 26 15:01:00 2018 +0300 ---------------------------------------------------------------------- ...arOptimisticSerializableTxPrepareFuture.java | 4 -- .../near/GridNearOptimisticTxPrepareFuture.java | 12 +++--- ...ridNearOptimisticTxPrepareFutureAdapter.java | 39 ++++++++++++++++++++ .../GridNearPessimisticTxPrepareFuture.java | 5 +++ .../cache/distributed/near/GridNearTxLocal.java | 25 +++---------- .../near/GridNearTxPrepareFutureAdapter.java | 5 +++ ...ollbackOnTimeoutNoDeadlockDetectionTest.java | 4 -- .../transactions/TxRollbackOnTimeoutTest.java | 19 ++++++++-- 8 files changed, 76 insertions(+), 37 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/f4d834b6/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java index 974de6b..75a768f 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java @@ -69,10 +69,6 @@ import static org.apache.ignite.transactions.TransactionState.PREPARING; public class GridNearOptimisticSerializableTxPrepareFuture extends GridNearOptimisticTxPrepareFutureAdapter { /** */ @GridToStringExclude - private KeyLockFuture keyLockFut; - - /** */ - @GridToStringExclude private ClientRemapFuture remapFut; /** */ http://git-wip-us.apache.org/repos/asf/ignite/blob/f4d834b6/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java index 247af84..36755b8 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java @@ -78,10 +78,6 @@ import static org.apache.ignite.transactions.TransactionState.PREPARING; public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepareFutureAdapter implements IgniteDiagnosticAware { /** */ - @GridToStringExclude - private KeyLockFuture keyLockFut; - - /** */ private int miniId; /** */ @@ -144,7 +140,7 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa * @param e Error. * @param discoThread {@code True} if executed from discovery thread. */ - void onError(Throwable e, boolean discoThread) { + private void onError(Throwable e, boolean discoThread) { if (e instanceof IgniteTxTimeoutCheckedException) { onTimeout(); @@ -434,7 +430,7 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa GridDistributedTxMapping updated = map(write, topVer, cur, topLocked, remap); - if(updated == null) + if (updated == null) // an exception occurred while transaction mapping, stop further processing break; @@ -769,6 +765,10 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa e = new IgniteTxTimeoutCheckedException("Failed to acquire lock within provided timeout for " + "transaction [timeout=" + tx.timeout() + ", tx=" + CU.txString(tx) + ']', deadlock != null ? new TransactionDeadlockException(deadlock.toString(cctx)) : null); + + if (!ERR_UPD.compareAndSet(GridNearOptimisticTxPrepareFuture.this, null, e) && err instanceof IgniteTxTimeoutCheckedException) { + err = e; + } } onDone(null, e); http://git-wip-us.apache.org/repos/asf/ignite/blob/f4d834b6/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFutureAdapter.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFutureAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFutureAdapter.java index 780674e..317ada3 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFutureAdapter.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFutureAdapter.java @@ -23,10 +23,13 @@ import org.apache.ignite.internal.IgniteInternalFuture; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; import org.apache.ignite.internal.processors.cache.GridCacheSharedContext; import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTopologyFuture; +import org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry; import org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey; +import org.apache.ignite.internal.transactions.IgniteTxTimeoutCheckedException; import org.apache.ignite.internal.util.GridConcurrentHashSet; import org.apache.ignite.internal.util.future.GridFutureAdapter; import org.apache.ignite.internal.util.lang.GridPlainRunnable; +import org.apache.ignite.internal.util.tostring.GridToStringExclude; import org.apache.ignite.internal.util.tostring.GridToStringInclude; import org.apache.ignite.internal.util.typedef.CI1; import org.apache.ignite.internal.util.typedef.internal.S; @@ -36,6 +39,10 @@ import org.jetbrains.annotations.Nullable; * */ public abstract class GridNearOptimisticTxPrepareFutureAdapter extends GridNearTxPrepareFutureAdapter { + /** */ + @GridToStringExclude + protected KeyLockFuture keyLockFut; + /** * @param cctx Context. * @param tx Transaction. @@ -44,6 +51,38 @@ public abstract class GridNearOptimisticTxPrepareFutureAdapter extends GridNearT super(cctx, tx); assert tx.optimistic() : tx; + + if (tx.timeout() > 0) { + // Init keyLockFut to make sure it is created when {@link #onNearTxLocalTimeout} is called. + for (IgniteTxEntry e : tx.writeEntries()) { + if (e.context().isNear() || e.context().isLocal()) { + keyLockFut = new KeyLockFuture(); + break; + } + } + + if (tx.serializable() && keyLockFut == null) { + for (IgniteTxEntry e : tx.readEntries()) { + if (e.context().isNear() || e.context().isLocal()) { + keyLockFut = new KeyLockFuture(); + break; + } + } + } + + if (keyLockFut != null) + add(keyLockFut); + } + } + + /** {@inheritDoc} */ + @Override public final void onNearTxLocalTimeout() { + if (keyLockFut != null && !keyLockFut.isDone()) { + ERR_UPD.compareAndSet(this, null, new IgniteTxTimeoutCheckedException("Failed to acquire lock " + + "within provided timeout for transaction [timeout=" + tx.timeout() + ", tx=" + tx + ']')); + + keyLockFut.onDone(); + } } /** {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/ignite/blob/f4d834b6/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java index da9bdac..c16a934 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java @@ -67,6 +67,11 @@ public class GridNearPessimisticTxPrepareFuture extends GridNearTxPrepareFutureA } /** {@inheritDoc} */ + @Override public void onNearTxLocalTimeout() { + // No-op. + } + + /** {@inheritDoc} */ @Override protected boolean ignoreFailure(Throwable err) { return IgniteCheckedException.class.isAssignableFrom(err.getClass()); } http://git-wip-us.apache.org/repos/asf/ignite/blob/f4d834b6/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java index 16653e0..65e1ea4 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java @@ -3395,6 +3395,11 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter implements GridTimeou if (!onTimeout && trackTimeout) removeTimeoutHandler(); + IgniteInternalFuture<?> prepFut = this.prepFut; + + if (onTimeout && prepFut instanceof GridNearTxPrepareFutureAdapter && !prepFut.isDone()) + ((GridNearTxPrepareFutureAdapter) prepFut).onNearTxLocalTimeout(); + NearTxFinishFuture fut = finishFut; if (fut != null) @@ -3419,8 +3424,6 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter implements GridTimeou cctx.mvcc().addFuture(fut0, fut0.futureId()); - IgniteInternalFuture<?> prepFut = this.prepFut; - if (prepFut == null || prepFut.isDone()) { try { // Check for errors in prepare future. @@ -4230,32 +4233,16 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter implements GridTimeou } /** - * @return {@code True} if need register callback which cancels tx on timeout. - */ - public boolean trackTimeout() { - return trackTimeout; - } - - /** * Removes timeout handler. * * @return {@code True} if handler was removed. */ - public boolean removeTimeoutHandler() { + private boolean removeTimeoutHandler() { assert trackTimeout; return cctx.time().removeTimeoutObject(this); } - /** - * @return {@code True} if handler was added. - */ - public boolean addTimeoutHandler() { - assert trackTimeout; - - return cctx.time().addTimeoutObject(this); - } - /** {@inheritDoc} */ @Override public IgniteUuid timeoutId() { return xid(); http://git-wip-us.apache.org/repos/asf/ignite/blob/f4d834b6/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareFutureAdapter.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareFutureAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareFutureAdapter.java index 1be84c5..5c0fcec 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareFutureAdapter.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareFutureAdapter.java @@ -136,6 +136,11 @@ public abstract class GridNearTxPrepareFutureAdapter extends } /** + * Called when related {@link GridNearTxLocal} is completed asynchronously on timeout, + */ + public abstract void onNearTxLocalTimeout(); + + /** * @return Transaction. */ public IgniteInternalTx tx() { http://git-wip-us.apache.org/repos/asf/ignite/blob/f4d834b6/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTimeoutNoDeadlockDetectionTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTimeoutNoDeadlockDetectionTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTimeoutNoDeadlockDetectionTest.java index 11148aa..e14eef6 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTimeoutNoDeadlockDetectionTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTimeoutNoDeadlockDetectionTest.java @@ -42,8 +42,4 @@ public class TxRollbackOnTimeoutNoDeadlockDetectionTest extends TxRollbackOnTime assertEquals("TimeoutException is expected", TransactionTimeoutException.class, e.getCause().getClass()); } - - @Override public void testRandomMixedTxConfigurations() throws Exception { - super.testRandomMixedTxConfigurations(); - } } http://git-wip-us.apache.org/repos/asf/ignite/blob/f4d834b6/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTimeoutTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTimeoutTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTimeoutTest.java index 88c1bbb..9c37cfa 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTimeoutTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTimeoutTest.java @@ -36,7 +36,9 @@ import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.configuration.NearCacheConfiguration; import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.internal.IgniteFutureTimeoutCheckedException; import org.apache.ignite.internal.IgniteInternalFuture; +import org.apache.ignite.internal.IgniteKernal; import org.apache.ignite.internal.TestRecordingCommunicationSpi; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxPrepareResponse; @@ -55,7 +57,6 @@ import org.apache.ignite.transactions.Transaction; import org.apache.ignite.transactions.TransactionConcurrency; import org.apache.ignite.transactions.TransactionDeadlockException; import org.apache.ignite.transactions.TransactionIsolation; -import org.apache.ignite.transactions.TransactionOptimisticException; import org.apache.ignite.transactions.TransactionTimeoutException; import static java.lang.Thread.sleep; @@ -394,8 +395,6 @@ public class TxRollbackOnTimeoutTest extends GridCommonAbstractTest { * Test timeouts with random values and different tx configurations. */ public void testRandomMixedTxConfigurations() throws Exception { - fail("https://issues.apache.org/jira/browse/IGNITE-8509"); - final Ignite client = startClient(); final AtomicBoolean stop = new AtomicBoolean(); @@ -471,7 +470,19 @@ public class TxRollbackOnTimeoutTest extends GridCommonAbstractTest { stop.set(true); - fut.get(10_000); + try { + fut.get(30_000); + } + catch (IgniteFutureTimeoutCheckedException e) { + error("Transactions hang", e); + + for (Ignite node : G.allGrids()) + ((IgniteKernal)node).dumpDebugInfo(); + + fut.cancel(); // Try to interrupt hanging threads. + + throw e; + } log.info("Tx test stats: started=" + cntr0.sum() + ", completed=" + cntr1.sum() +