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

better determination of a blocking transaction deadlock detection

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