提交 d7efb172 authored 作者: Andrei Tokar's avatar Andrei Tokar

better determination of a blocking transaction deadlock detection

上级 7a296ebb
...@@ -175,7 +175,7 @@ public class Transaction { ...@@ -175,7 +175,7 @@ public class Transaction {
* @param status to be set * @param status to be set
* @return transaction state as it was before status change * @return transaction state as it was before status change
*/ */
long setStatus(int status) { private long setStatus(int status) {
while (true) { while (true) {
long currentState = statusAndLogId.get(); long currentState = statusAndLogId.get();
long logId = getLogId(currentState); long logId = getLogId(currentState);
...@@ -486,11 +486,13 @@ public class Transaction { ...@@ -486,11 +486,13 @@ public class Transaction {
"Transaction %d attempts to update map <%s> entry with key <%s>" "Transaction %d attempts to update map <%s> entry with key <%s>"
+ " modified by transaction %s%n", + " modified by transaction %s%n",
transactionId, blockingMap.getName(), blockingKey, toWaitFor)); transactionId, blockingMap.getName(), blockingKey, toWaitFor));
if (isDeadlocked(toWaitFor)) {
throw DataUtils.newIllegalStateException(DataUtils.ERROR_TRANSACTIONS_DEADLOCK, throw DataUtils.newIllegalStateException(DataUtils.ERROR_TRANSACTIONS_DEADLOCK,
details.toString()); details.toString());
} }
} }
} }
}
blockingTransaction = toWaitFor; blockingTransaction = toWaitFor;
try { try {
...@@ -515,8 +517,10 @@ public class Transaction { ...@@ -515,8 +517,10 @@ public class Transaction {
private synchronized boolean waitForThisToEnd(int millis) { private synchronized boolean waitForThisToEnd(int millis) {
long until = System.currentTimeMillis() + millis; long until = System.currentTimeMillis() + millis;
long state;
int status; int status;
while((status = getStatus()) != STATUS_CLOSED && status != STATUS_ROLLING_BACK) { while((status = getStatus(state = statusAndLogId.get())) != STATUS_CLOSED
&& status != STATUS_ROLLED_BACK && !hasRollback(state)) {
long dur = until - System.currentTimeMillis(); long dur = until - System.currentTimeMillis();
if(dur <= 0) { if(dur <= 0) {
return false; return false;
......
...@@ -49,7 +49,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -49,7 +49,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
// because a tree root has definitely been changed. // because a tree root has definitely been changed.
logIt(existingValue.value == null ? null : VersionedValue.getInstance(existingValue.value)); logIt(existingValue.value == null ? null : VersionedValue.getInstance(existingValue.value));
decision = MVMap.Decision.PUT; decision = MVMap.Decision.PUT;
} else if (fetchTransaction(blockingId) != null) { } else if (getBlockingTransaction() != null) {
// this entry comes from a different transaction, and this // this entry comes from a different transaction, and this
// transaction is not committed yet // transaction is not committed yet
// should wait on blockingTransaction that was determined earlier // should wait on blockingTransaction that was determined earlier
...@@ -106,11 +106,17 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -106,11 +106,17 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
} }
final boolean isCommitted(int transactionId) { final boolean isCommitted(int transactionId) {
return transaction.store.committingTransactions.get().get(transactionId); Transaction blockingTx;
} boolean result;
do {
blockingTx = transaction.store.getTransaction(transactionId);
result = transaction.store.committingTransactions.get().get(transactionId);
} while (blockingTx != transaction.store.getTransaction(transactionId));
final Transaction fetchTransaction(int transactionId) { if (!result) {
return (blockingTransaction = transaction.store.getTransaction(transactionId)); blockingTransaction = blockingTx;
}
return result;
} }
final MVMap.Decision setDecision(MVMap.Decision d) { final MVMap.Decision setDecision(MVMap.Decision d) {
...@@ -167,7 +173,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -167,7 +173,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
// and therefore will be committed soon // and therefore will be committed soon
logIt(null); logIt(null);
return setDecision(MVMap.Decision.PUT); return setDecision(MVMap.Decision.PUT);
} else if (fetchTransaction(blockingId) != null) { } else if (getBlockingTransaction() != null) {
// this entry comes from a different transaction, and this // this entry comes from a different transaction, and this
// transaction is not committed yet // transaction is not committed yet
// should wait on blockingTransaction that was determined // should wait on blockingTransaction that was determined
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论