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