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

Reuse VersionedValue value for NULL, encapsulate "value" field

上级 c3befc2c
...@@ -1820,7 +1820,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba ...@@ -1820,7 +1820,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba
private static Row getRowFromVersionedValue(MVTable table, long recKey, private static Row getRowFromVersionedValue(MVTable table, long recKey,
VersionedValue versionedValue) { VersionedValue versionedValue) {
Object value = versionedValue == null ? null : versionedValue.value; Object value = versionedValue == null ? null : versionedValue.getCurrentValue();
if (value == null) { if (value == null) {
return null; return null;
} }
......
...@@ -36,7 +36,7 @@ final class CommitDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -36,7 +36,7 @@ final class CommitDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
// see TxDecisionMaker.decide() // 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) { } else /* this is final undo log entry for this key */ if (existingValue.getCurrentValue() == null) {
decision = MVMap.Decision.REMOVE; decision = MVMap.Decision.REMOVE;
} else { } else {
decision = MVMap.Decision.PUT; decision = MVMap.Decision.PUT;
...@@ -49,7 +49,7 @@ final class CommitDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -49,7 +49,7 @@ final class CommitDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
public VersionedValue selectValue(VersionedValue existingValue, VersionedValue providedValue) { public VersionedValue selectValue(VersionedValue existingValue, VersionedValue providedValue) {
assert decision == MVMap.Decision.PUT; assert decision == MVMap.Decision.PUT;
assert existingValue != null; assert existingValue != null;
return VersionedValue.getInstance(existingValue.value); return VersionedValue.getInstance(existingValue.getCurrentValue());
} }
@Override @Override
......
...@@ -146,7 +146,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> { ...@@ -146,7 +146,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
int txId = TransactionStore.getTransactionId(operationId); int txId = TransactionStore.getTransactionId(operationId);
boolean isVisible = txId == transaction.transactionId || boolean isVisible = txId == transaction.transactionId ||
committingTransactions.get(txId); committingTransactions.get(txId);
Object v = isVisible ? currentValue.value : currentValue.getCommittedValue(); Object v = isVisible ? currentValue.getCurrentValue() : currentValue.getCommittedValue();
if (v == null) { if (v == null) {
--size; --size;
} }
...@@ -177,7 +177,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> { ...@@ -177,7 +177,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
int txId = TransactionStore.getTransactionId(operationId); int txId = TransactionStore.getTransactionId(operationId);
boolean isVisible = txId == transaction.transactionId || boolean isVisible = txId == transaction.transactionId ||
committingTransactions.get(txId); committingTransactions.get(txId);
Object v = isVisible ? currentValue.value : currentValue.getCommittedValue(); Object v = isVisible ? currentValue.getCurrentValue() : currentValue.getCommittedValue();
if (v == null) { if (v == null) {
--size; --size;
} }
...@@ -267,7 +267,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> { ...@@ -267,7 +267,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
VersionedValue newValue = VersionedValue.getInstance(value); VersionedValue newValue = VersionedValue.getInstance(value);
VersionedValue oldValue = map.put(key, newValue); VersionedValue oldValue = map.put(key, newValue);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
V result = (V) (oldValue == null ? null : oldValue.value); V result = (V) (oldValue == null ? null : oldValue.getCurrentValue());
return result; return result;
} }
...@@ -290,7 +290,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> { ...@@ -290,7 +290,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
// and any non-null value will do // and any non-null value will do
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
K k = (K) key; K k = (K) key;
result = map.put(k, VersionedValue.DUMMY, decisionMaker); result = map.put(k, VersionedValue.VV_NULL, decisionMaker);
MVMap.Decision decision = decisionMaker.getDecision(); MVMap.Decision decision = decisionMaker.getDecision();
assert decision != null; assert decision != null;
...@@ -300,7 +300,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> { ...@@ -300,7 +300,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
transaction.blockingMap = null; transaction.blockingMap = null;
transaction.blockingKey = null; transaction.blockingKey = null;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
V res = result == null ? null : (V) result.value; V res = result == null ? null : (V) result.getCurrentValue();
return res; return res;
} }
decisionMaker.reset(); decisionMaker.reset();
...@@ -383,12 +383,12 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> { ...@@ -383,12 +383,12 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
long id = data.getOperationId(); long id = data.getOperationId();
if (id == 0) { if (id == 0) {
// it is committed // it is committed
return (V)data.value; return (V)data.getCurrentValue();
} }
int tx = TransactionStore.getTransactionId(id); int tx = TransactionStore.getTransactionId(id);
if (tx == transaction.transactionId || transaction.store.committingTransactions.get().get(tx)) { if (tx == transaction.transactionId || transaction.store.committingTransactions.get().get(tx)) {
// added by this transaction or another transaction which is committed by now // added by this transaction or another transaction which is committed by now
return (V)data.value; return (V) data.getCurrentValue();
} else { } else {
return (V) data.getCommittedValue(); return (V) data.getCommittedValue();
} }
...@@ -657,7 +657,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> { ...@@ -657,7 +657,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected Map.Entry<K, V> registerCurrent(K key, VersionedValue data) { protected Map.Entry<K, V> registerCurrent(K key, VersionedValue data) {
return new AbstractMap.SimpleImmutableEntry<>(key, (V) data.value); return new AbstractMap.SimpleImmutableEntry<>(key, (V) data.getCurrentValue());
} }
} }
...@@ -717,7 +717,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> { ...@@ -717,7 +717,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
} }
} }
} }
if (data != null && (data.value != null || if (data != null && (data.getCurrentValue() != null ||
includeAllUncommitted && transactionId != includeAllUncommitted && transactionId !=
TransactionStore.getTransactionId(data.getOperationId()))) { TransactionStore.getTransactionId(data.getOperationId()))) {
current = registerCurrent(key, data); current = registerCurrent(key, data);
......
...@@ -453,7 +453,7 @@ public class TransactionStore { ...@@ -453,7 +453,7 @@ public class TransactionStore {
// used by CommitDecisionMaker, MVRTreeMap has weird // used by CommitDecisionMaker, MVRTreeMap has weird
// traversal logic based on it, and any non-null // traversal logic based on it, and any non-null
// value will do, to signify update, not removal // value will do, to signify update, not removal
map.operate(key, VersionedValue.DUMMY, commitDecisionMaker); map.operate(key, VersionedValue.VV_NULL, commitDecisionMaker);
} }
} }
undoLog.clear(); undoLog.clear();
...@@ -640,7 +640,7 @@ public class TransactionStore { ...@@ -640,7 +640,7 @@ public class TransactionStore {
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];
current = new Change(m.getName(), op[1], oldValue == null ? null : oldValue.value); current = new Change(m.getName(), op[1], oldValue == null ? null : oldValue.getCurrentValue());
return; return;
} }
} }
......
...@@ -47,7 +47,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -47,7 +47,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
// We assume that we are looking at the final value for this transaction, // We assume that we are looking at the final value for this transaction,
// and if it's not the case, then it will fail later, // and if it's not the case, then it will fail later,
// 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.getCurrentValue() == null ? null : VersionedValue.getInstance(existingValue.getCurrentValue()));
decision = MVMap.Decision.PUT; decision = MVMap.Decision.PUT;
} else if (getBlockingTransaction() != null) { } else if (getBlockingTransaction() != null) {
// this entry comes from a different transaction, and this // this entry comes from a different transaction, and this
...@@ -163,7 +163,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -163,7 +163,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
if (id == 0 // entry is a committed one if (id == 0 // entry is a committed one
// or it came from the same transaction // or it came from the same transaction
|| isThisTransaction(blockingId = TransactionStore.getTransactionId(id))) { || isThisTransaction(blockingId = TransactionStore.getTransactionId(id))) {
if(existingValue.value != null) { if(existingValue.getCurrentValue() != null) {
return setDecision(MVMap.Decision.ABORT); return setDecision(MVMap.Decision.ABORT);
} }
logIt(existingValue); logIt(existingValue);
...@@ -171,7 +171,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -171,7 +171,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
} else if (isCommitted(blockingId)) { } else if (isCommitted(blockingId)) {
// entry belongs to a committing transaction // entry belongs to a committing transaction
// and therefore will be committed soon // and therefore will be committed soon
if(existingValue.value != null) { if(existingValue.getCurrentValue() != null) {
return setDecision(MVMap.Decision.ABORT); return setDecision(MVMap.Decision.ABORT);
} }
logIt(null); logIt(null);
...@@ -229,7 +229,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -229,7 +229,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
@Override @Override
public VersionedValue selectValue(VersionedValue existingValue, VersionedValue providedValue) { public VersionedValue selectValue(VersionedValue existingValue, VersionedValue providedValue) {
return VersionedValue.getInstance(undoKey, return VersionedValue.getInstance(undoKey,
existingValue == null ? null : existingValue.value, existingValue == null ? null : existingValue.getCurrentValue(),
existingValue == null ? null : existingValue.getCommittedValue()); existingValue == null ? null : existingValue.getCommittedValue());
} }
} }
......
...@@ -9,6 +9,7 @@ import org.h2.engine.Constants; ...@@ -9,6 +9,7 @@ import org.h2.engine.Constants;
import org.h2.mvstore.DataUtils; import org.h2.mvstore.DataUtils;
import org.h2.mvstore.WriteBuffer; import org.h2.mvstore.WriteBuffer;
import org.h2.mvstore.type.DataType; import org.h2.mvstore.type.DataType;
import org.h2.value.ValueNull;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
/** /**
...@@ -19,25 +20,18 @@ import java.nio.ByteBuffer; ...@@ -19,25 +20,18 @@ import java.nio.ByteBuffer;
*/ */
public class VersionedValue { public class VersionedValue {
public static final VersionedValue DUMMY = new VersionedValue(new Object()); static final VersionedValue VV_NULL = new VersionedValue();
/**
* The current value.
*/
public final Object value;
static VersionedValue getInstance(Object value) { static VersionedValue getInstance(Object value) {
assert value != null; assert value != null;
return new VersionedValue(value); return value == ValueNull.INSTANCE ? VV_NULL : new Committed(value);
} }
public static VersionedValue getInstance(long operationId, Object value, Object committedValue) { public static VersionedValue getInstance(long operationId, Object value, Object committedValue) {
return new Uncommitted(operationId, value, committedValue); return new Uncommitted(operationId, value, committedValue);
} }
VersionedValue(Object value) { private VersionedValue() {}
this.value = value;
}
public boolean isCommitted() { public boolean isCommitted() {
return true; return true;
...@@ -47,16 +41,40 @@ public class VersionedValue { ...@@ -47,16 +41,40 @@ public class VersionedValue {
return 0L; return 0L;
} }
public Object getCurrentValue() {
return ValueNull.INSTANCE;
}
public Object getCommittedValue() { public Object getCommittedValue() {
return value; return ValueNull.INSTANCE;
} }
@Override private static class Committed extends VersionedValue
public String toString() { {
return String.valueOf(value); /**
* The current value.
*/
public final Object value;
Committed(Object value) {
this.value = value;
}
public Object getCurrentValue() {
return value;
}
public Object getCommittedValue() {
return value;
}
@Override
public String toString() {
return String.valueOf(value);
}
} }
private static class Uncommitted extends VersionedValue private static class Uncommitted extends Committed
{ {
private final long operationId; private final long operationId;
private final Object committedValue; private final Object committedValue;
...@@ -107,7 +125,7 @@ public class VersionedValue { ...@@ -107,7 +125,7 @@ public class VersionedValue {
if(obj == null) return 0; if(obj == null) return 0;
VersionedValue v = (VersionedValue) obj; VersionedValue v = (VersionedValue) obj;
int res = Constants.MEMORY_OBJECT + 8 + 2 * Constants.MEMORY_POINTER + int res = Constants.MEMORY_OBJECT + 8 + 2 * Constants.MEMORY_POINTER +
getValMemory(v.value); getValMemory(v.getCurrentValue());
if (v.getOperationId() != 0) { if (v.getOperationId() != 0) {
res += getValMemory(v.getCommittedValue()); res += getValMemory(v.getCommittedValue());
} }
...@@ -131,7 +149,7 @@ public class VersionedValue { ...@@ -131,7 +149,7 @@ public class VersionedValue {
VersionedValue b = (VersionedValue) bObj; VersionedValue b = (VersionedValue) bObj;
long comp = a.getOperationId() - b.getOperationId(); long comp = a.getOperationId() - b.getOperationId();
if (comp == 0) { if (comp == 0) {
return valueType.compare(a.value, b.value); return valueType.compare(a.getCurrentValue(), b.getCurrentValue());
} }
return Long.signum(comp); return Long.signum(comp);
} }
...@@ -141,7 +159,7 @@ public class VersionedValue { ...@@ -141,7 +159,7 @@ public class VersionedValue {
if (buff.get() == 0) { if (buff.get() == 0) {
// fast path (no op ids or null entries) // fast path (no op ids or null entries)
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
obj[i] = new VersionedValue(valueType.read(buff)); obj[i] = new Committed(valueType.read(buff));
} }
} else { } else {
// slow path (some entries may be null) // slow path (some entries may be null)
...@@ -155,7 +173,7 @@ public class VersionedValue { ...@@ -155,7 +173,7 @@ public class VersionedValue {
public Object read(ByteBuffer buff) { public Object read(ByteBuffer buff) {
long operationId = DataUtils.readVarLong(buff); long operationId = DataUtils.readVarLong(buff);
if (operationId == 0) { if (operationId == 0) {
return new VersionedValue(valueType.read(buff)); return new Committed(valueType.read(buff));
} else { } else {
byte flags = buff.get(); byte flags = buff.get();
Object value = (flags & 1) != 0 ? valueType.read(buff) : null; Object value = (flags & 1) != 0 ? valueType.read(buff) : null;
...@@ -169,7 +187,7 @@ public class VersionedValue { ...@@ -169,7 +187,7 @@ public class VersionedValue {
boolean fastPath = true; boolean fastPath = true;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
VersionedValue v = (VersionedValue) obj[i]; VersionedValue v = (VersionedValue) obj[i];
if (v.getOperationId() != 0 || v.value == null) { if (v.getOperationId() != 0 || v.getCurrentValue() == null) {
fastPath = false; fastPath = false;
} }
} }
...@@ -177,7 +195,7 @@ public class VersionedValue { ...@@ -177,7 +195,7 @@ public class VersionedValue {
buff.put((byte) 0); buff.put((byte) 0);
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
VersionedValue v = (VersionedValue) obj[i]; VersionedValue v = (VersionedValue) obj[i];
valueType.write(buff, v.value); valueType.write(buff, v.getCurrentValue());
} }
} else { } else {
// slow path: // slow path:
...@@ -195,13 +213,13 @@ public class VersionedValue { ...@@ -195,13 +213,13 @@ public class VersionedValue {
long operationId = v.getOperationId(); long operationId = v.getOperationId();
buff.putVarLong(operationId); buff.putVarLong(operationId);
if (operationId == 0) { if (operationId == 0) {
valueType.write(buff, v.value); valueType.write(buff, v.getCurrentValue());
} else { } else {
Object committedValue = v.getCommittedValue(); Object committedValue = v.getCommittedValue();
int flags = (v.value == null ? 0 : 1) | (committedValue == null ? 0 : 2); int flags = (v.getCurrentValue() == null ? 0 : 1) | (committedValue == null ? 0 : 2);
buff.put((byte) flags); buff.put((byte) flags);
if (v.value != null) { if (v.getCurrentValue() != null) {
valueType.write(buff, v.value); valueType.write(buff, v.getCurrentValue());
} }
if (committedValue != null) { if (committedValue != null) {
valueType.write(buff, committedValue); valueType.write(buff, committedValue);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论