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

addressing code review comments

上级 21642a27
...@@ -594,7 +594,8 @@ public class Select extends Query { ...@@ -594,7 +594,8 @@ public class Select extends Query {
} }
} }
ArrayList<Row> forUpdateRows = null; ArrayList<Row> forUpdateRows = null;
if (isForUpdateMvcc) { boolean lockRows = this.isForUpdateMvcc;
if (lockRows) {
forUpdateRows = Utils.newSmallArrayList(); forUpdateRows = Utils.newSmallArrayList();
} }
int sampleSize = getSampleSizeValue(session); int sampleSize = getSampleSizeValue(session);
...@@ -604,7 +605,7 @@ public class Select extends Query { ...@@ -604,7 +605,7 @@ public class Select extends Query {
return lazyResult; return lazyResult;
} }
while (lazyResult.next()) { while (lazyResult.next()) {
if (isForUpdateMvcc) { if (lockRows) {
topTableFilter.lockRowAdd(forUpdateRows); topTableFilter.lockRowAdd(forUpdateRows);
} }
result.addRow(lazyResult.currentRow()); result.addRow(lazyResult.currentRow());
...@@ -613,8 +614,7 @@ public class Select extends Query { ...@@ -613,8 +614,7 @@ public class Select extends Query {
break; break;
} }
} }
if (isForUpdateMvcc) { if (lockRows) {
assert forUpdateRows != null;
topTableFilter.lockRows(forUpdateRows); topTableFilter.lockRows(forUpdateRows);
} }
return null; return null;
......
...@@ -150,7 +150,7 @@ public class Cursor<K, V> implements Iterator<K> { ...@@ -150,7 +150,7 @@ public class Cursor<K, V> implements Iterator<K> {
* @param p the page to start from * @param p the page to start from
* @param key the key to search, null means search for the first key * @param key the key to search, null means search for the first key
*/ */
public static CursorPos traverseDown(Page p, Object key) { private static CursorPos traverseDown(Page p, Object key) {
CursorPos cursorPos = null; CursorPos cursorPos = null;
while (!p.isLeaf()) { while (!p.isLeaf()) {
assert p.getKeyCount() > 0; assert p.getKeyCount() > 0;
......
...@@ -131,6 +131,7 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -131,6 +131,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
*/ */
@Override @Override
public V put(K key, V value) { public V put(K key, V value) {
DataUtils.checkArgument(value != null, "The value may not be null");
return put(key, value, DecisionMaker.PUT); return put(key, value, DecisionMaker.PUT);
} }
...@@ -142,7 +143,6 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -142,7 +143,6 @@ public class MVMap<K, V> extends AbstractMap<K, V>
* @return the old value if the key existed, or null otherwise * @return the old value if the key existed, or null otherwise
*/ */
public final V put(K key, V value, DecisionMaker<? super V> decisionMaker) { public final V put(K key, V value, DecisionMaker<? super V> decisionMaker) {
DataUtils.checkArgument(value != null, "The value may not be null");
return operate(key, value, decisionMaker); return operate(key, value, decisionMaker);
} }
......
...@@ -18,7 +18,7 @@ final class CommitDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -18,7 +18,7 @@ final class CommitDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
private long undoKey; private long undoKey;
private MVMap.Decision decision; private MVMap.Decision decision;
public void setUndoKey(long undoKey) { void setUndoKey(long undoKey) {
this.undoKey = undoKey; this.undoKey = undoKey;
reset(); reset();
} }
...@@ -26,25 +26,20 @@ final class CommitDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -26,25 +26,20 @@ final class CommitDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
@Override @Override
public MVMap.Decision decide(VersionedValue existingValue, VersionedValue providedValue) { public MVMap.Decision decide(VersionedValue existingValue, VersionedValue providedValue) {
assert decision == null; assert decision == null;
if (existingValue == null) { if (existingValue == null ||
// map entry was treated as committed already and // map entry was treated as already committed, and then
// removed already by another commited by now transaction // it has been removed by another transaction (commited and closed by now )
existingValue.getOperationId() != undoKey) {
// this is not a final undo log entry for this key,
// or map entry was treated as already committed and then
// overwritten by another transaction
// see TxDecisionMaker.decide()
decision = MVMap.Decision.ABORT; decision = MVMap.Decision.ABORT;
} else /* this is final undo log entry for this key */ if (existingValue.value == null) {
decision = MVMap.Decision.REMOVE;
} else { } else {
if (existingValue.getOperationId() == undoKey) { decision = MVMap.Decision.PUT;
// this is final undo log entry for this key
if (existingValue.value == null) {
decision = MVMap.Decision.REMOVE;
} else {
decision = MVMap.Decision.PUT;
}
} else {
// this is not a final undo log entry for this key,
// or map entry was treated as committed already and
// overwritten already by another transaction
// see TxDecisionMaker.decide()
decision = MVMap.Decision.ABORT;
}
} }
return decision; return decision;
} }
......
...@@ -31,30 +31,21 @@ final class RollbackDecisionMaker extends MVMap.DecisionMaker<Object[]> { ...@@ -31,30 +31,21 @@ final class RollbackDecisionMaker extends MVMap.DecisionMaker<Object[]> {
public MVMap.Decision decide(Object[] existingValue, Object[] providedValue) { public MVMap.Decision decide(Object[] existingValue, Object[] providedValue) {
assert decision == null; assert decision == null;
assert existingValue != null; assert existingValue != null;
/* VersionedValue valueToRestore = (VersionedValue) existingValue[2];
if (existingValue == null) { long operationId;
// this should only be possible during initialization if (valueToRestore == null ||
// when previously database was abruptly killed (operationId = valueToRestore.getOperationId()) == 0 ||
// assert !store.isInitialized(); TransactionStore.getTransactionId(operationId) == transactionId
decision = MVMap.Decision.ABORT; && TransactionStore.getLogId(operationId) < toLogId) {
} else { int mapId = (Integer) existingValue[0];
*/ MVMap<Object, VersionedValue> map = store.openMap(mapId);
VersionedValue valueToRestore = (VersionedValue) existingValue[2]; if (map != null && !map.isClosed()) {
long operationId; Object key = existingValue[1];
if (valueToRestore == null || VersionedValue previousValue = map.operate(key, valueToRestore, MVMap.DecisionMaker.DEFAULT);
(operationId = valueToRestore.getOperationId()) == 0 || listener.onRollback(map, key, previousValue, valueToRestore);
TransactionStore.getTransactionId(operationId) == transactionId
&& TransactionStore.getLogId(operationId) < toLogId) {
int mapId = (Integer) existingValue[0];
MVMap<Object, VersionedValue> map = store.openMap(mapId);
if (map != null && !map.isClosed()) {
Object key = existingValue[1];
VersionedValue previousValue = map.operate(key, valueToRestore, MVMap.DecisionMaker.DEFAULT);
listener.onRollback(map, key, previousValue, valueToRestore);
}
} }
decision = MVMap.Decision.REMOVE; }
// } decision = MVMap.Decision.REMOVE;
return decision; return decision;
} }
......
...@@ -99,7 +99,6 @@ public class TransactionMap<K, V> { ...@@ -99,7 +99,6 @@ public class TransactionMap<K, V> {
*/ */
public long sizeAsLong() { public long sizeAsLong() {
TransactionStore store = transaction.store; TransactionStore store = transaction.store;
MVMap<Long, Object[]> undo = transaction.store.undoLog;
BitSet committingTransactions; BitSet committingTransactions;
MVMap.RootReference mapRootReference; MVMap.RootReference mapRootReference;
...@@ -135,14 +134,13 @@ public class TransactionMap<K, V> { ...@@ -135,14 +134,13 @@ public class TransactionMap<K, V> {
} }
// the undo log is smaller than the map - // the undo log is smaller than the map -
// scan the undo log and subtract invisible entries // scan the undo log and subtract invisible entries
MVMap<Object, Integer> temp = transaction.store MVMap<Object, Integer> temp = store.createTempMap();
.createTempMap();
try { try {
Cursor cursor = new Cursor<Long, Object[]>(undoRootPage, null); Cursor<Long, Object[]> cursor = new Cursor<>(undoRootPage, null);
while (cursor.hasNext()) { while (cursor.hasNext()) {
cursor.next(); cursor.next();
Object[] op = (Object[]) cursor.getValue(); Object[] op = cursor.getValue();
int m = (Integer) op[0]; int m = (int) op[0];
if (m != mapId) { if (m != mapId) {
// a different map - ignore // a different map - ignore
continue; continue;
...@@ -233,12 +231,13 @@ public class TransactionMap<K, V> { ...@@ -233,12 +231,13 @@ public class TransactionMap<K, V> {
* @param value the value * @param value the value
* @return the old value * @return the old value
*/ */
@SuppressWarnings("unchecked")
public V putCommitted(K key, V value) { public V putCommitted(K key, V value) {
DataUtils.checkArgument(value != null, "The value may not be null"); DataUtils.checkArgument(value != null, "The value may not be null");
VersionedValue newValue = new VersionedValue(0L, value); VersionedValue newValue = new VersionedValue(0L, value);
VersionedValue oldValue = map.put(key, newValue); VersionedValue oldValue = map.put(key, newValue);
return (V) (oldValue == null ? null : oldValue.value); @SuppressWarnings("unchecked")
V result = (V) (oldValue == null ? null : oldValue.value);
return result;
} }
private V set(K key, V value) { private V set(K key, V value) {
...@@ -246,7 +245,6 @@ public class TransactionMap<K, V> { ...@@ -246,7 +245,6 @@ public class TransactionMap<K, V> {
return set(key, decisionMaker); return set(key, decisionMaker);
} }
@SuppressWarnings("unchecked")
private V set(K key, TxDecisionMaker decisionMaker) { private V set(K key, TxDecisionMaker decisionMaker) {
TransactionStore store = transaction.store; TransactionStore store = transaction.store;
Transaction blockingTransaction; Transaction blockingTransaction;
...@@ -255,7 +253,10 @@ public class TransactionMap<K, V> { ...@@ -255,7 +253,10 @@ public class TransactionMap<K, V> {
do { do {
sequenceNumWhenStarted = store.openTransactions.get().getVersion(); sequenceNumWhenStarted = store.openTransactions.get().getVersion();
assert transaction.getBlockerId() == 0; assert transaction.getBlockerId() == 0;
// although second parameter (value) is not really used,
// since TxDecisionMaker has it embedded,
// MVRTreeMap has weird traversal logic based on it,
// and any non-null value will do
result = map.put(key, VersionedValue.DUMMY, decisionMaker); result = map.put(key, VersionedValue.DUMMY, decisionMaker);
MVMap.Decision decision = decisionMaker.getDecision(); MVMap.Decision decision = decisionMaker.getDecision();
...@@ -265,7 +266,9 @@ public class TransactionMap<K, V> { ...@@ -265,7 +266,9 @@ public class TransactionMap<K, V> {
if (decision != MVMap.Decision.ABORT || blockingTransaction == null) { if (decision != MVMap.Decision.ABORT || blockingTransaction == null) {
transaction.blockingMap = null; transaction.blockingMap = null;
transaction.blockingKey = null; transaction.blockingKey = null;
return result == null ? null : (V) result.value; @SuppressWarnings("unchecked")
V res = result == null ? null : (V) result.value;
return res;
} }
decisionMaker.reset(); decisionMaker.reset();
transaction.blockingMap = map; transaction.blockingMap = map;
......
...@@ -39,7 +39,7 @@ public class TransactionStore { ...@@ -39,7 +39,7 @@ public class TransactionStore {
* The persisted map of prepared transactions. * The persisted map of prepared transactions.
* Key: transactionId, value: [ status, name ]. * Key: transactionId, value: [ status, name ].
*/ */
final MVMap<Integer, Object[]> preparedTransactions; private final MVMap<Integer, Object[]> preparedTransactions;
/** /**
* The undo log. * The undo log.
...@@ -228,7 +228,7 @@ public class TransactionStore { ...@@ -228,7 +228,7 @@ public class TransactionStore {
* @param logId the log id * @param logId the log id
* @return the operation id * @return the operation id
*/ */
static long getOperationId(int transactionId, long logId) { private static long getOperationId(int transactionId, long logId) {
DataUtils.checkArgument(transactionId >= 0 && transactionId < (1 << (64 - LOG_ID_BITS)), DataUtils.checkArgument(transactionId >= 0 && transactionId < (1 << (64 - LOG_ID_BITS)),
"Transaction id out of range: {0}", transactionId); "Transaction id out of range: {0}", transactionId);
DataUtils.checkArgument(logId >= 0 && logId <= LOG_ID_MASK, DataUtils.checkArgument(logId >= 0 && logId <= LOG_ID_MASK,
...@@ -362,11 +362,11 @@ public class TransactionStore { ...@@ -362,11 +362,11 @@ public class TransactionStore {
} }
/** /**
* Add an undoLog entry. * Add an undo log entry.
* *
* @param transactionId id of the transaction * @param transactionId id of the transaction
* @param logId sequential number of the log record within transaction * @param logId sequential number of the log record within transaction
* @param undoLogRecord Object[] * @param undoLogRecord Object[mapId, key, previousValue]
*/ */
long addUndoLogRecord(int transactionId, long logId, Object[] undoLogRecord) { long addUndoLogRecord(int transactionId, long logId, Object[] undoLogRecord) {
Long undoKey = getOperationId(transactionId, logId); Long undoKey = getOperationId(transactionId, logId);
...@@ -550,9 +550,9 @@ public class TransactionStore { ...@@ -550,9 +550,9 @@ public class TransactionStore {
* and amount of unsaved changes is sizable. * and amount of unsaved changes is sizable.
* *
* @param t the transaction * @param t the transaction
* @param hasChanges true if transaction has done any updated * @param hasChanges true if transaction has done any updates
* (even if fully rolled back), * (even if they are fully rolled back),
* false if just data access * false if it just performed a data access
*/ */
synchronized void endTransaction(Transaction t, boolean hasChanges) { synchronized void endTransaction(Transaction t, boolean hasChanges) {
t.closeIt(); t.closeIt();
...@@ -646,7 +646,7 @@ public class TransactionStore { ...@@ -646,7 +646,7 @@ public class TransactionStore {
logId = getLogId(undoKey); logId = getLogId(undoKey);
continue; continue;
} }
int mapId = ((Integer) op[0]).intValue(); int mapId = (int)op[0];
MVMap<Object, VersionedValue> m = openMap(mapId); MVMap<Object, VersionedValue> m = openMap(mapId);
if (m != null) { // could be null if map was removed later on if (m != null) { // could be null if map was removed later on
VersionedValue oldValue = (VersionedValue) op[2]; VersionedValue oldValue = (VersionedValue) op[2];
......
...@@ -32,7 +32,6 @@ public abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue ...@@ -32,7 +32,6 @@ public abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue
@Override @Override
public MVMap.Decision decide(VersionedValue existingValue, VersionedValue providedValue) { public MVMap.Decision decide(VersionedValue existingValue, VersionedValue providedValue) {
assert decision == null; assert decision == null;
assert providedValue != null;
long id; long id;
int blockingId; int blockingId;
// if map does not have that entry yet // if map does not have that entry yet
...@@ -52,7 +51,7 @@ public abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue ...@@ -52,7 +51,7 @@ public abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue
decision = MVMap.Decision.PUT; decision = MVMap.Decision.PUT;
} else if(fetchTransaction(blockingId) == null) { } else if(fetchTransaction(blockingId) == null) {
// condition above means transaction has been committed/rplled back and closed by now // condition above means transaction has been committed/rplled back and closed by now
return setDecision(MVMap.Decision.REPEAT); decision = MVMap.Decision.REPEAT;
} else { } else {
// this entry comes from a different transaction, and this transaction is not committed yet // this entry comes from a different transaction, and this transaction is not committed yet
// should wait on blockingTransaction that was determined earlier // should wait on blockingTransaction that was determined earlier
...@@ -129,7 +128,6 @@ public abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue ...@@ -129,7 +128,6 @@ public abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue
@Override @Override
public MVMap.Decision decide(VersionedValue existingValue, VersionedValue providedValue) { public MVMap.Decision decide(VersionedValue existingValue, VersionedValue providedValue) {
assert getDecision() == null; assert getDecision() == null;
assert providedValue != null;
int blockingId; int blockingId;
// if map does not have that entry yet // if map does not have that entry yet
if (existingValue == null) { if (existingValue == null) {
......
...@@ -7,7 +7,6 @@ package org.h2.table; ...@@ -7,7 +7,6 @@ package org.h2.table;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.command.Parser; import org.h2.command.Parser;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论