From dc6e337c4663e977abd1c56e60837a9335f26215 Mon Sep 17 00:00:00 2001 From: Vitaliy Biryukov Date: Tue, 14 Nov 2017 15:58:58 +0300 Subject: [PATCH] IGNITE-6527: Example solution 2. --- .../transactions/TxDeadlockDetection.java | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxDeadlockDetection.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxDeadlockDetection.java index 1cf7809b5098c..035e0878ab42b 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxDeadlockDetection.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxDeadlockDetection.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.ListIterator; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -306,12 +307,66 @@ private void detect(TxLocksResponse res) { List cycle = findCycle(wfg, txId); - if (cycle != null) + if (cycle != null && validateWaitForGraph(cycle)) onDone(new TxDeadlock(cycle, txs, txLockedKeys, txRequestedKeys)); else map(res.keys(), res.txLocks()); } + /** + * @param cycle Cycle. + * @return True if graph is valid. + */ + private boolean validateWaitForGraph(List cycle) { + boolean valid = false; + + GridCacheVersion waitTxId = null; + + for (ListIterator iter = cycle.listIterator(cycle.size()); iter.hasPrevious(); ) { + if (iter.previous().equals(txId)) { + waitTxId = iter.previous(); + + break; + } + } + + assert waitTxId != null; + assert waitTxId != txId; + + Set keys = txLockedKeys.get(waitTxId); + + for (IgniteTxKey key : keys) { + Set txs = txRequestedKeys.get(key); + + if (txs != null && txs.contains(txId)) + valid = true; + } + + if (!valid) { + wfg.get(txId).remove(waitTxId); + + Map> map = new HashMap<>(txRequestedKeys); + + for (IgniteTxKey key : txLockedKeys.get(waitTxId)) { + if(this.keys.contains(key)){ + Set versions = map.get(key); + + if(versions == null) + map.put(key, versions = new HashSet<>()); + + versions.add(txId); + } + } + + IgniteLogger log = cctx.logger(TxDeadlockDetection.class); + + //TODO improve log message. + log.warning(new TxDeadlock(cycle, txs, txLockedKeys, map).toString(cctx)); + } + + return valid; + } + /** * Maps tx keys on nodes. Key can be mapped on some node if this node is primary for given key or * node is near for transaction that holds or requests lock for key.