提交 128619d2 authored 作者: Andrei Tokar's avatar Andrei Tokar

@katzyn suggested: moving classes around to keep client jar small

上级 f66a645a
......@@ -34,7 +34,7 @@ import org.h2.mvstore.db.MVTable;
import org.h2.mvstore.db.MVTableEngine;
import org.h2.mvstore.tx.Transaction;
import org.h2.mvstore.tx.TransactionStore;
import org.h2.mvstore.tx.VersionedValue;
import org.h2.value.VersionedValue;
import org.h2.result.ResultInterface;
import org.h2.result.Row;
import org.h2.result.SortOrder;
......
......@@ -28,7 +28,8 @@ import org.h2.mvstore.rtree.MVRTreeMap.RTreeCursor;
import org.h2.mvstore.rtree.SpatialKey;
import org.h2.mvstore.tx.Transaction;
import org.h2.mvstore.tx.TransactionMap;
import org.h2.mvstore.tx.VersionedValue;
import org.h2.mvstore.tx.VersionedValueType;
import org.h2.value.VersionedValue;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
......@@ -98,7 +99,7 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex {
}
String mapName = "index." + getId();
ValueDataType vt = new ValueDataType(db, null);
VersionedValue.Type valueType = new VersionedValue.Type(vt);
VersionedValueType valueType = new VersionedValueType(vt);
MVRTreeMap.Builder<VersionedValue> mapBuilder =
new MVRTreeMap.Builder<VersionedValue>().
valueType(valueType);
......
......@@ -6,6 +6,7 @@
package org.h2.mvstore.tx;
import org.h2.mvstore.MVMap;
import org.h2.value.VersionedValue;
/**
* Class CommitDecisionMaker makes a decision during post-commit processing
......@@ -49,7 +50,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.getCurrentValue());
return VersionedValueCommitted.getInstance(existingValue.getCurrentValue());
}
@Override
......
......@@ -6,6 +6,7 @@
package org.h2.mvstore.tx;
import org.h2.mvstore.MVMap;
import org.h2.value.VersionedValue;
/**
* Class RollbackDecisionMaker process undo log record during transaction rollback.
......
......@@ -9,6 +9,7 @@ import org.h2.mvstore.DataUtils;
import org.h2.mvstore.MVMap;
import org.h2.mvstore.MVStore;
import org.h2.mvstore.type.DataType;
import org.h2.value.VersionedValue;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicLong;
......
......@@ -10,6 +10,7 @@ import org.h2.mvstore.DataUtils;
import org.h2.mvstore.MVMap;
import org.h2.mvstore.Page;
import org.h2.mvstore.type.DataType;
import org.h2.value.VersionedValue;
import java.util.AbstractMap;
import java.util.AbstractSet;
......@@ -264,7 +265,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
*/
public V putCommitted(K key, V value) {
DataUtils.checkArgument(value != null, "The value may not be null");
VersionedValue newValue = VersionedValue.getInstance(value);
VersionedValue newValue = VersionedValueCommitted.getInstance(value);
VersionedValue oldValue = map.put(key, newValue);
@SuppressWarnings("unchecked")
V result = (V) (oldValue == null ? null : oldValue.getCurrentValue());
......@@ -712,7 +713,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
// current value comes from another uncommitted transaction
// take committed value instead
Object committedValue = data.getCommittedValue();
data = committedValue == null ? null : VersionedValue.getInstance(committedValue);
data = committedValue == null ? null : VersionedValueCommitted.getInstance(committedValue);
}
}
}
......
......@@ -20,6 +20,7 @@ import org.h2.mvstore.WriteBuffer;
import org.h2.mvstore.type.DataType;
import org.h2.mvstore.type.ObjectDataType;
import org.h2.util.StringUtils;
import org.h2.value.VersionedValue;
/**
* A store that supports concurrent MVCC read-committed transactions.
......@@ -128,14 +129,14 @@ public class TransactionStore {
this.timeoutMillis = timeoutMillis;
preparedTransactions = store.openMap("openTransactions",
new MVMap.Builder<Integer, Object[]>());
DataType oldValueType = new VersionedValue.Type(dataType);
DataType oldValueType = new VersionedValueType(dataType);
ArrayType undoLogValueType = new ArrayType(new DataType[]{
new ObjectDataType(), dataType, oldValueType
});
undoLogBuilder = new MVMap.Builder<Long, Object[]>()
.singleWriter()
.valueType(undoLogValueType);
DataType vt = new VersionedValue.Type(dataType);
DataType vt = new VersionedValueType(dataType);
mapBuilder = new MVMap.Builder<Object, VersionedValue>()
.keyType(dataType).valueType(vt);
}
......@@ -494,7 +495,7 @@ public class TransactionStore {
if (valueType == null) {
valueType = new ObjectDataType();
}
VersionedValue.Type vt = new VersionedValue.Type(valueType);
VersionedValueType vt = new VersionedValueType(valueType);
MVMap<K, VersionedValue> map;
MVMap.Builder<K, VersionedValue> builder =
new MVMap.Builder<K, VersionedValue>().
......
......@@ -6,6 +6,7 @@
package org.h2.mvstore.tx;
import org.h2.mvstore.MVMap;
import org.h2.value.VersionedValue;
/**
* Class TxDecisionMaker.
......@@ -47,7 +48,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.getCurrentValue() == null ? null : VersionedValue.getInstance(existingValue.getCurrentValue()));
logIt(existingValue.getCurrentValue() == null ? null : VersionedValueCommitted.getInstance(existingValue.getCurrentValue()));
decision = MVMap.Decision.PUT;
} else if (getBlockingTransaction() != null) {
// this entry comes from a different transaction, and this
......@@ -63,7 +64,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
// was written but not undo log), and will effectively roll it back
// (just assume committed value and overwrite).
Object committedValue = existingValue.getCommittedValue();
logIt(committedValue == null ? null : VersionedValue.getInstance(committedValue));
logIt(committedValue == null ? null : VersionedValueCommitted.getInstance(committedValue));
decision = MVMap.Decision.PUT;
} else {
// transaction has been committed/rolled back and is closed by now, so
......@@ -138,7 +139,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
@SuppressWarnings("unchecked")
@Override
public final VersionedValue selectValue(VersionedValue existingValue, VersionedValue providedValue) {
return VersionedValue.getInstance(undoKey, value,
return VersionedValueUncommitted.getInstance(undoKey, value,
existingValue == null ? null : existingValue.getCommittedValue());
}
}
......@@ -228,7 +229,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
@SuppressWarnings("unchecked")
@Override
public VersionedValue selectValue(VersionedValue existingValue, VersionedValue providedValue) {
return VersionedValue.getInstance(undoKey,
return VersionedValueUncommitted.getInstance(undoKey,
existingValue == null ? null : existingValue.getCurrentValue(),
existingValue == null ? null : existingValue.getCommittedValue());
}
......
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.mvstore.tx;
import org.h2.engine.Constants;
import org.h2.mvstore.DataUtils;
import org.h2.mvstore.WriteBuffer;
import org.h2.mvstore.type.DataType;
import java.nio.ByteBuffer;
/**
* A versioned value (possibly null).
* It contains current value and latest committed value if current one is uncommitted.
* Also for uncommitted values it contains operationId - a combination of
* transactionId and logId.
*/
public class VersionedValue {
static final VersionedValue DUMMY = new VersionedValue();
static VersionedValue getInstance(Object value) {
assert value != null;
return value instanceof VersionedValue ? (VersionedValue)value : new Committed(value);
}
public static VersionedValue getInstance(long operationId, Object value, Object committedValue) {
return new Uncommitted(operationId, value, committedValue);
}
protected VersionedValue() {}
public boolean isCommitted() {
return true;
}
public long getOperationId() {
return 0L;
}
public Object getCurrentValue() {
return this;
}
public Object getCommittedValue() {
return this;
}
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;
}
@Override
public String toString() {
return String.valueOf(value);
}
}
private static class Uncommitted extends Committed
{
private final long operationId;
private final Object committedValue;
Uncommitted(long operationId, Object value, Object committedValue) {
super(value);
assert operationId != 0;
this.operationId = operationId;
this.committedValue = committedValue;
}
@Override
public boolean isCommitted() {
return false;
}
@Override
public long getOperationId() {
return operationId;
}
@Override
public Object getCommittedValue() {
return committedValue;
}
@Override
public String toString() {
return super.toString() +
" " + TransactionStore.getTransactionId(operationId) + "/" +
TransactionStore.getLogId(operationId) + " " + committedValue;
}
}
/**
* The value type for a versioned value.
*/
public static class Type implements DataType {
private final DataType valueType;
public Type(DataType valueType) {
this.valueType = valueType;
}
@Override
public int getMemory(Object obj) {
if(obj == null) return 0;
VersionedValue v = (VersionedValue) obj;
int res = Constants.MEMORY_OBJECT + 8 + 2 * Constants.MEMORY_POINTER +
getValMemory(v.getCurrentValue());
if (v.getOperationId() != 0) {
res += getValMemory(v.getCommittedValue());
}
return res;
}
private int getValMemory(Object obj) {
return obj == null ? 0 : valueType.getMemory(obj);
}
@Override
public int compare(Object aObj, Object bObj) {
if (aObj == bObj) {
return 0;
} else if (aObj == null) {
return -1;
} else if (bObj == null) {
return 1;
}
VersionedValue a = (VersionedValue) aObj;
VersionedValue b = (VersionedValue) bObj;
long comp = a.getOperationId() - b.getOperationId();
if (comp == 0) {
return valueType.compare(a.getCurrentValue(), b.getCurrentValue());
}
return Long.signum(comp);
}
@Override
public void read(ByteBuffer buff, Object[] obj, int len, boolean key) {
if (buff.get() == 0) {
// fast path (no op ids or null entries)
for (int i = 0; i < len; i++) {
obj[i] = getInstance(valueType.read(buff));
}
} else {
// slow path (some entries may be null)
for (int i = 0; i < len; i++) {
obj[i] = read(buff);
}
}
}
@Override
public Object read(ByteBuffer buff) {
long operationId = DataUtils.readVarLong(buff);
if (operationId == 0) {
return getInstance(valueType.read(buff));
} else {
byte flags = buff.get();
Object value = (flags & 1) != 0 ? valueType.read(buff) : null;
Object committedValue = (flags & 2) != 0 ? valueType.read(buff) : null;
return new Uncommitted(operationId, value, committedValue);
}
}
@Override
public void write(WriteBuffer buff, Object[] obj, int len, boolean key) {
boolean fastPath = true;
for (int i = 0; i < len; i++) {
VersionedValue v = (VersionedValue) obj[i];
if (v.getOperationId() != 0 || v.getCurrentValue() == null) {
fastPath = false;
}
}
if (fastPath) {
buff.put((byte) 0);
for (int i = 0; i < len; i++) {
VersionedValue v = (VersionedValue) obj[i];
valueType.write(buff, v.getCurrentValue());
}
} else {
// slow path:
// store op ids, and some entries may be null
buff.put((byte) 1);
for (int i = 0; i < len; i++) {
write(buff, obj[i]);
}
}
}
@Override
public void write(WriteBuffer buff, Object obj) {
VersionedValue v = (VersionedValue) obj;
long operationId = v.getOperationId();
buff.putVarLong(operationId);
if (operationId == 0) {
valueType.write(buff, v.getCurrentValue());
} else {
Object committedValue = v.getCommittedValue();
int flags = (v.getCurrentValue() == null ? 0 : 1) | (committedValue == null ? 0 : 2);
buff.put((byte) flags);
if (v.getCurrentValue() != null) {
valueType.write(buff, v.getCurrentValue());
}
if (committedValue != null) {
valueType.write(buff, committedValue);
}
}
}
}
}
/*
* Copyright 2004-2017 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.mvstore.tx;
import org.h2.value.VersionedValue;
/**
* Class CommittedVersionedValue.
* <UL>
* <LI> 12/24/18 8:48 PM initial creation
* </UL>
*
* @author <a href='mailto:andrei.tokar@gmail.com'>Andrei Tokar</a>
*/
class VersionedValueCommitted extends VersionedValue {
/**
* The current value.
*/
public final Object value;
VersionedValueCommitted(Object value) {
this.value = value;
}
static VersionedValue getInstance(Object value) {
assert value != null;
return value instanceof VersionedValue ? (VersionedValue) value : new VersionedValueCommitted(value);
}
public Object getCurrentValue() {
return value;
}
public Object getCommittedValue() {
return value;
}
@Override
public String toString() {
return String.valueOf(value);
}
}
/*
* Copyright 2004-2017 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.mvstore.tx;
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.VersionedValue;
import java.nio.ByteBuffer;
/**
* The value type for a versioned value.
*/
public class VersionedValueType implements DataType {
private final DataType valueType;
public VersionedValueType(DataType valueType) {
this.valueType = valueType;
}
@Override
public int getMemory(Object obj) {
if(obj == null) return 0;
VersionedValue v = (VersionedValue) obj;
int res = Constants.MEMORY_OBJECT + 8 + 2 * Constants.MEMORY_POINTER +
getValMemory(v.getCurrentValue());
if (v.getOperationId() != 0) {
res += getValMemory(v.getCommittedValue());
}
return res;
}
private int getValMemory(Object obj) {
return obj == null ? 0 : valueType.getMemory(obj);
}
@Override
public int compare(Object aObj, Object bObj) {
if (aObj == bObj) {
return 0;
} else if (aObj == null) {
return -1;
} else if (bObj == null) {
return 1;
}
VersionedValue a = (VersionedValue) aObj;
VersionedValue b = (VersionedValue) bObj;
long comp = a.getOperationId() - b.getOperationId();
if (comp == 0) {
return valueType.compare(a.getCurrentValue(), b.getCurrentValue());
}
return Long.signum(comp);
}
@Override
public void read(ByteBuffer buff, Object[] obj, int len, boolean key) {
if (buff.get() == 0) {
// fast path (no op ids or null entries)
for (int i = 0; i < len; i++) {
obj[i] = VersionedValueCommitted.getInstance(valueType.read(buff));
}
} else {
// slow path (some entries may be null)
for (int i = 0; i < len; i++) {
obj[i] = read(buff);
}
}
}
@Override
public Object read(ByteBuffer buff) {
long operationId = DataUtils.readVarLong(buff);
if (operationId == 0) {
return VersionedValueCommitted.getInstance(valueType.read(buff));
} else {
byte flags = buff.get();
Object value = (flags & 1) != 0 ? valueType.read(buff) : null;
Object committedValue = (flags & 2) != 0 ? valueType.read(buff) : null;
return VersionedValueUncommitted.getInstance(operationId, value, committedValue);
}
}
@Override
public void write(WriteBuffer buff, Object[] obj, int len, boolean key) {
boolean fastPath = true;
for (int i = 0; i < len; i++) {
VersionedValue v = (VersionedValue) obj[i];
if (v.getOperationId() != 0 || v.getCurrentValue() == null) {
fastPath = false;
}
}
if (fastPath) {
buff.put((byte) 0);
for (int i = 0; i < len; i++) {
VersionedValue v = (VersionedValue) obj[i];
valueType.write(buff, v.getCurrentValue());
}
} else {
// slow path:
// store op ids, and some entries may be null
buff.put((byte) 1);
for (int i = 0; i < len; i++) {
write(buff, obj[i]);
}
}
}
@Override
public void write(WriteBuffer buff, Object obj) {
VersionedValue v = (VersionedValue) obj;
long operationId = v.getOperationId();
buff.putVarLong(operationId);
if (operationId == 0) {
valueType.write(buff, v.getCurrentValue());
} else {
Object committedValue = v.getCommittedValue();
int flags = (v.getCurrentValue() == null ? 0 : 1) | (committedValue == null ? 0 : 2);
buff.put((byte) flags);
if (v.getCurrentValue() != null) {
valueType.write(buff, v.getCurrentValue());
}
if (committedValue != null) {
valueType.write(buff, committedValue);
}
}
}
}
/*
* Copyright 2004-2017 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.mvstore.tx;
import org.h2.value.VersionedValue;
/**
* Class VersionedValueUncommitted.
* <UL>
* <LI> 12/24/18 8:49 PM initial creation
* </UL>
*
* @author <a href='mailto:andrei.tokar@gmail.com'>Andrei Tokar</a>
*/
class VersionedValueUncommitted extends VersionedValueCommitted {
private final long operationId;
private final Object committedValue;
VersionedValueUncommitted(long operationId, Object value, Object committedValue) {
super(value);
assert operationId != 0;
this.operationId = operationId;
this.committedValue = committedValue;
}
static VersionedValue getInstance(long operationId, Object value, Object committedValue) {
return new VersionedValueUncommitted(operationId, value, committedValue);
}
@Override
public boolean isCommitted() {
return false;
}
@Override
public long getOperationId() {
return operationId;
}
@Override
public Object getCommittedValue() {
return committedValue;
}
@Override
public String toString() {
return super.toString() +
" " + TransactionStore.getTransactionId(operationId) + "/" +
TransactionStore.getLogId(operationId) + " " + committedValue;
}
}
......@@ -23,7 +23,6 @@ import org.h2.api.IntervalQualifier;
import org.h2.engine.Mode;
import org.h2.engine.SysProperties;
import org.h2.message.DbException;
import org.h2.mvstore.tx.VersionedValue;
import org.h2.result.ResultInterface;
import org.h2.result.SimpleResult;
import org.h2.store.DataHandler;
......
/*
* Copyright 2004-2017 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.value;
/**
* A versioned value (possibly null).
* It contains current value and latest committed value if current one is uncommitted.
* Also for uncommitted values it contains operationId - a combination of
* transactionId and logId.
*/
public class VersionedValue {
public static final VersionedValue DUMMY = new VersionedValue();
protected VersionedValue() {}
public boolean isCommitted() {
return true;
}
public long getOperationId() {
return 0L;
}
public Object getCurrentValue() {
return this;
}
public Object getCommittedValue() {
return this;
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论