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

LockDecisionMakers adustments to match TxDecisionMaker logic for leftover map entry

上级 01977633
......@@ -18,7 +18,7 @@ public abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue
final Object value;
private final Transaction transaction;
long undoKey;
private long lastOperationId;
protected long lastOperationId;
private Transaction blockingTransaction;
private MVMap.Decision decision;
......@@ -54,16 +54,18 @@ public abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue
// should wait on blockingTransaction that was determined earlier
decision = MVMap.Decision.ABORT;
} else if(id == lastOperationId) {
// There is no transaction with that id, so we've retried it just before,
// There is no transaction with that id, and we've tried it just before,
// but map root has not changed (which must be the case if we just missed a closed transaction),
// therefore we came back here again.
// Now we assume it's a leftover after unclean shutdown (map update was written but not undo log),
// and will effectively roll it back (just overwrite).
// and will effectively roll it back (just assume committed value and overwrite).
Object committedValue = existingValue.getCommittedValue();
logIt(committedValue == null ? null : VersionedValue.getInstance(committedValue));
decision = MVMap.Decision.PUT;
} else {
// condition above means transaction has been committed/rolled back and closed by now
// transaction has been committed/rolled back and is closed by now, so
// we can retry immediately and either that entry become committed
// or we'll hit case above
decision = MVMap.Decision.REPEAT;
lastOperationId = id;
}
......@@ -162,15 +164,28 @@ public 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) {
// map already has specified key from uncommitted
// at the time transaction, which is closed by now
// we can retry right away
return setDecision(MVMap.Decision.REPEAT);
} else {
// map already has specified key from uncommitted transaction
// we need to wait for it to close and then try again
} else if(fetchTransaction(blockingId) != null) {
// this entry comes from a different transaction, and this transaction is not committed yet
// should wait on blockingTransaction that was determined earlier and then try again
return setDecision(MVMap.Decision.ABORT);
} else if(id == lastOperationId) {
// There is no transaction with that id, and we've tried it just before,
// but map root has not changed (which must be the case if we just missed a closed transaction),
// therefore we came back here again.
// Now we assume it's a leftover after unclean shutdown (map update was written but not undo log),
// and will effectively roll it back (just assume committed value and overwrite).
Object committedValue = existingValue.getCommittedValue();
if(committedValue != null) {
return setDecision(MVMap.Decision.ABORT);
}
logIt(null);
return setDecision(MVMap.Decision.PUT);
} else {
// transaction has been committed/rolled back and is closed by now, so
// we can retry immediately and either that entry become committed
// or we'll hit case above
lastOperationId = id;
return setDecision(MVMap.Decision.REPEAT);
}
}
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论