提交 d2ec2ee3 authored 作者: Thomas Mueller's avatar Thomas Mueller

MVStore: improved API (the DataTypeFactory is no longer used)

上级 1397fe53
......@@ -42,7 +42,7 @@ But it can be also directly within an application, without using JDBC or SQL.
</li><li>Transaction are supported (currently only one transaction at a time).
</li><li>Transactions (even if they are persisted) can be rolled back.
</li><li>The tool is very modular. It supports pluggable data types / serialization,
pluggable map implementations (B-tree and R-tree currently), BLOB storage,
pluggable map implementations (B-tree, R-tree, concurrent B-tree currently), BLOB storage,
and a file system abstraction to support encryption and compressed read-only files.
</li></ul>
......@@ -100,12 +100,12 @@ s.close();
<h3>Store Builder</h3>
<p>
The <code>MVStoreBuilder</code> provides a fluid interface
The <code>MVStore.Builder</code> provides a fluid interface
to build a store if more complex configuration options are used.
</p>
<pre>
MVStore s = MVStoreBuilder.
fileBased(fileName).
MVStore s = new MVStore.Builder().
fileName(fileName).
cacheSizeMB(10).
readOnly().
open();
......@@ -120,12 +120,9 @@ that supports fast spatial queries.
// create an in-memory store
MVStore s = MVStore.open(null);
// create an R-tree map
// the key has 2 dimensions, the value is a string
MVRTreeMap&lt;String&gt; r = MVRTreeMap.create(2, new ObjectType());
// open the map
r = s.openMap("data", r);
// open an R-tree map
MVRTreeMap<String> r = s.openMap("data",
new MVRTreeMap.Builder<String>());
// add two key-value pairs
// the first value is the key id (to make the key unique)
......@@ -330,10 +327,6 @@ Then, the file can be copied (the file handle is available to the application).
<h3>Tools</h3>
<p>
There is a builder for store instances (<code>MVStoreBuilder</code>)
with a fluent API to simplify building a store instance.
</p>
<p>
There is a tool (<code>MVStoreTool</code>) to dump the contents of a file.
</p>
......
......@@ -1020,18 +1020,6 @@ public class MVMap<K, V> extends AbstractMap<K, V>
if (type != null) {
DataUtils.appendMap(buff, "type", type);
}
if (keyType != null) {
String k = keyType.asString();
if (k.length() > 0) {
DataUtils.appendMap(buff, "key", k);
}
}
if (valueType != null) {
String v = valueType.asString();
if (v.length() > 0) {
DataUtils.appendMap(buff, "value", v);
}
}
return buff.toString();
}
......
......@@ -21,8 +21,6 @@ import org.h2.compress.CompressLZF;
import org.h2.compress.Compressor;
import org.h2.mvstore.cache.CacheLongKeyLIRS;
import org.h2.mvstore.cache.FilePathCache;
import org.h2.mvstore.type.DataTypeFactory;
import org.h2.mvstore.type.ObjectDataTypeFactory;
import org.h2.mvstore.type.StringDataType;
import org.h2.store.fs.FilePath;
import org.h2.store.fs.FileUtils;
......@@ -65,6 +63,9 @@ TODO:
- allow renaming maps
- file locking: solve problem that locks are shared for a VM
- online backup
- data types: maybe support InputStream, Reader
- data types: maybe support ResultSet, Date, Time, Timestamp
- data types: maybe support boolean[], short[],...
- store file "header" at the end of each chunk; at the end of the file
- is there a better name for the file header,
-- if it's no longer always at the beginning of a file?
......@@ -122,7 +123,6 @@ public class MVStore {
static final int BLOCK_SIZE = 4 * 1024;
private final String fileName;
private final DataTypeFactory dataTypeFactory;
private int pageSize = 6 * 1024;
......@@ -186,14 +186,6 @@ public class MVStore {
MVStore(HashMap<String, Object> config) {
this.fileName = (String) config.get("fileName");
DataTypeFactory parent = new ObjectDataTypeFactory();
DataTypeFactory f = (DataTypeFactory) config.get("dataTypeFactory");
if (f == null) {
f = parent;
} else {
f.setParent(parent);
}
this.dataTypeFactory = f;
this.readOnly = "r".equals(config.get("openMode"));
this.compress = "1".equals(config.get("compress"));
if (fileName != null) {
......@@ -1430,16 +1422,6 @@ public class MVStore {
return set("compress", "1");
}
/**
* Use the given data type factory.
*
* @param factory the data type factory
* @return this
*/
public Builder with(DataTypeFactory factory) {
return set("dataTypeFactory", factory);
}
/**
* Open the store.
*
......
......@@ -16,7 +16,6 @@ import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.message.DbException;
import org.h2.mvstore.MVStore;
import org.h2.mvstore.type.DataTypeFactory;
import org.h2.table.TableBase;
import org.h2.util.New;
......@@ -48,16 +47,13 @@ public class MVTableEngine implements TableEngine {
String storeName = db.getDatabasePath();
MVStore.Builder builder = new MVStore.Builder();
Store store;
DataTypeFactory f = new ValueDataTypeFactory(db.getCompareMode(), db);
if (storeName == null) {
builder.with(f);
store = new Store(db, builder.open());
} else {
synchronized (STORES) {
store = STORES.get(storeName);
if (store == null) {
builder.fileName(storeName + Constants.SUFFIX_MV_FILE);
builder.with(f);
store = new Store(db, builder.open());
STORES.put(storeName, store);
} else if (store.db != db) {
......
......@@ -26,7 +26,6 @@ import org.h2.store.DataHandler;
import org.h2.store.LobStorage;
import org.h2.tools.SimpleResultSet;
import org.h2.util.DateTimeUtils;
import org.h2.util.StringUtils;
import org.h2.util.Utils;
import org.h2.value.CompareMode;
import org.h2.value.Value;
......@@ -183,40 +182,6 @@ public class ValueArrayDataType implements DataType {
}
}
public String asString() {
StringBuilder buff = new StringBuilder();
buff.append(PREFIX);
buff.append('(');
for (int i = 0; i < sortTypes.length; i++) {
if (i > 0) {
buff.append(',');
}
buff.append(sortTypes[i]);
}
buff.append(')');
return buff.toString();
}
/**
* Convert a row type to a row.
*
* @param t the type string
* @param factory the data type factory
* @return the row type
*/
static ValueArrayDataType fromString(CompareMode compareMode, DataHandler handler, String t) {
if (!t.startsWith(PREFIX) || !t.endsWith(")")) {
throw new RuntimeException("Unknown type: " + t);
}
t = t.substring(PREFIX.length(), t.length() - 1);
String[] array = StringUtils.arraySplit(t, ',', false);
int[] sortTypes = new int[array.length];
for (int i = 0; i < array.length; i++) {
sortTypes[i] = Integer.parseInt(array[i]);
}
return new ValueArrayDataType(compareMode, handler, sortTypes);
}
private void writeValue(ByteBuffer buff, Value v) {
int start = buff.position();
if (v == ValueNull.INSTANCE) {
......
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, Version
* 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html). Initial Developer: H2 Group
*/
package org.h2.mvstore.db;
import org.h2.mvstore.type.DataType;
import org.h2.mvstore.type.DataTypeFactory;
import org.h2.store.DataHandler;
import org.h2.value.CompareMode;
/**
* A data type factory for rows.
*/
public class ValueDataTypeFactory implements DataTypeFactory {
private final CompareMode compareMode;
private final DataHandler handler;
private DataTypeFactory parent;
ValueDataTypeFactory(CompareMode compareMode, DataHandler handler) {
this.compareMode = compareMode;
this.handler = handler;
}
@Override
public void setParent(DataTypeFactory parent) {
this.parent = parent;
}
@Override
public DataType buildDataType(String s) {
if (s.startsWith(ValueArrayDataType.PREFIX)) {
return ValueArrayDataType.fromString(compareMode, handler, s);
}
return parent.buildDataType(s);
}
}
......@@ -27,16 +27,6 @@ public class SpatialDataType implements DataType {
this.dimensions = dimensions;
}
/**
* Read a value from a string.
*
* @param s the string
* @return the value
*/
public static SpatialDataType fromString(String s) {
return new SpatialDataType(Integer.parseInt(s.substring(1)));
}
@Override
public int compare(Object a, Object b) {
long la = ((SpatialKey) a).getId();
......@@ -105,11 +95,6 @@ public class SpatialDataType implements DataType {
return new SpatialKey(id, minMax);
}
@Override
public String asString() {
return "s" + dimensions;
}
/**
* Check whether the two objects overlap.
*
......
......@@ -55,16 +55,5 @@ public interface DataType {
*/
Object read(ByteBuffer buff);
/**
* Get the stable string representation that is used to build this data
* type.
* <p>
* To avoid conflict with the default factory, the returned string should
* start with the package name of the type factory.
*
* @return the string representation
*/
String asString();
}
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.mvstore.type;
/**
* A factory for maps and data types.
*/
public interface DataTypeFactory {
/**
* Set the parent factory.
*
* @param parent the parent factory
*/
void setParent(DataTypeFactory parent);
/**
* Parse the data type.
*
* @param dataType the string and type specific meta data
* @return the type, or null if unknown
*/
DataType buildDataType(String dataType);
}
......@@ -19,10 +19,6 @@ import org.h2.util.Utils;
*/
public class ObjectDataType implements DataType {
// TODO maybe support InputStream, Reader
// TODO maybe support ResultSet, Date, Time, Timestamp
// TODO maybe support boolean[], short[],...
/**
* The type constants are also used as tag values.
*/
......@@ -206,11 +202,6 @@ public class ObjectDataType implements DataType {
return last.read(buff, tag);
}
@Override
public String asString() {
return "o";
}
private static int getTypeId(Object obj) {
if (obj instanceof Integer) {
return TYPE_INTEGER;
......@@ -399,11 +390,6 @@ public class ObjectDataType implements DataType {
*/
abstract Object read(ByteBuffer buff, int tag);
@Override
public String asString() {
return "o" + typeId;
}
}
/**
......
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, Version
* 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html). Initial Developer: H2 Group
*/
package org.h2.mvstore.type;
import org.h2.mvstore.rtree.SpatialDataType;
/**
* A data type factory.
*/
public class ObjectDataTypeFactory implements DataTypeFactory {
@Override
public void setParent(DataTypeFactory parent) {
// never called for this factory
}
@Override
public DataType buildDataType(String s) {
if ("s".equals(s)) {
return SpatialDataType.fromString(s);
} else if ("o".equals(s)) {
return new ObjectDataType();
}
return null;
}
}
......@@ -40,9 +40,5 @@ public class StringDataType implements DataType {
DataUtils.writeStringData(buff, s, len);
}
public String asString() {
return "";
}
}
......@@ -267,7 +267,7 @@ public abstract class TestBase {
url = name;
}
int test;
url = addOption(url, "DEFAULT_TABLE_ENGINE", MVTableEngine.class.getName());
// url = addOption(url, "DEFAULT_TABLE_ENGINE", MVTableEngine.class.getName());
if (!config.memory) {
if (config.smallLog && admin) {
url = addOption(url, "MAX_LOG_SIZE", "1");
......
......@@ -9,8 +9,6 @@ package org.h2.test.store;
import java.nio.ByteBuffer;
import org.h2.mvstore.DataUtils;
import org.h2.mvstore.type.DataType;
import org.h2.mvstore.type.DataTypeFactory;
import org.h2.util.StringUtils;
/**
* A row type.
......@@ -86,38 +84,4 @@ public class RowDataType implements DataType {
}
}
public String asString() {
StringBuilder buff = new StringBuilder();
buff.append(PREFIX);
buff.append('(');
for (int i = 0; i < types.length; i++) {
if (i > 0) {
buff.append(',');
}
buff.append(types[i].asString());
}
buff.append(')');
return buff.toString();
}
/**
* Convert a row type to a row.
*
* @param t the type string
* @param factory the data type factory
* @return the row type
*/
static RowDataType fromString(String t, DataTypeFactory factory) {
if (!t.startsWith(PREFIX) || !t.endsWith(")")) {
throw new RuntimeException("Unknown type: " + t);
}
t = t.substring(PREFIX.length(), t.length() - 1);
String[] array = StringUtils.arraySplit(t, ',', false);
DataType[] types = new DataType[array.length];
for (int i = 0; i < array.length; i++) {
types[i] = factory.buildDataType(array[i]);
}
return new RowDataType(types);
}
}
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, Version
* 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html). Initial Developer: H2 Group
*/
package org.h2.test.store;
import org.h2.mvstore.type.DataType;
import org.h2.mvstore.type.DataTypeFactory;
/**
* A data type factory.
*/
public class SampleTypeFactory implements DataTypeFactory {
private DataTypeFactory parent;
@Override
public void setParent(DataTypeFactory parent) {
this.parent = parent;
}
@Override
public DataType buildDataType(String s) {
if (s.startsWith(RowDataType.PREFIX)) {
return RowDataType.fromString(s, this);
}
return parent.buildDataType(s);
}
}
......@@ -17,7 +17,6 @@ import java.util.Random;
import org.h2.mvstore.MVMap;
import org.h2.mvstore.MVMapConcurrent;
import org.h2.mvstore.MVStore;
import org.h2.mvstore.type.ObjectDataTypeFactory;
import org.h2.store.fs.FileUtils;
import org.h2.test.TestBase;
import org.h2.util.Task;
......@@ -167,8 +166,7 @@ public class TestConcurrent extends TestMVStore {
}
private void testConcurrentIterate() {
MVStore s = new MVStore.Builder().
with(new ObjectDataTypeFactory()).open();
MVStore s = new MVStore.Builder().open();
s.setPageSize(3);
final MVMap<Integer, Integer> map = s.openMap("test");
final int len = 10;
......
......@@ -18,7 +18,6 @@ import org.h2.mvstore.MVMap;
import org.h2.mvstore.MVStore;
import org.h2.mvstore.type.DataType;
import org.h2.mvstore.type.ObjectDataType;
import org.h2.mvstore.type.ObjectDataTypeFactory;
import org.h2.mvstore.type.StringDataType;
import org.h2.store.fs.FilePath;
import org.h2.store.fs.FileUtils;
......@@ -106,8 +105,7 @@ public class TestMVStore extends TestBase {
MVMap<Integer, String> map;
s = new MVStore.Builder().
fileName(fileName).
compressData().
with(new ObjectDataTypeFactory()).open();
compressData().open();
map = s.openMap("test");
// add 10 MB of data
for (int i = 0; i < 1024; i++) {
......@@ -116,13 +114,12 @@ public class TestMVStore extends TestBase {
s.store();
s.close();
int[] expectedReadsForCacheSize = {
3408, 2590, 1924, 1440, 1102, 956, 918
3412, 2590, 1924, 1440, 1102, 956, 918
};
for (int cacheSize = 0; cacheSize <= 6; cacheSize += 4) {
s = new MVStore.Builder().
fileName(fileName).
cacheSizeMB(1 + 3 * cacheSize).
with(new ObjectDataTypeFactory()).open();
cacheSizeMB(1 + 3 * cacheSize).open();
map = s.openMap("test");
for (int i = 0; i < 1024; i += 128) {
for (int j = 0; j < i; j++) {
......@@ -351,8 +348,7 @@ public class TestMVStore extends TestBase {
private void testIterateOldVersion() {
MVStore s;
Map<Integer, Integer> map;
s = new MVStore.Builder().
with(new ObjectDataTypeFactory()).open();
s = new MVStore.Builder().open();
map = s.openMap("test");
int len = 100;
for (int i = 0; i < len; i++) {
......@@ -377,16 +373,14 @@ public class TestMVStore extends TestBase {
FileUtils.delete(fileName);
MVStore s;
Map<Object, Object> map;
s = new MVStore.Builder().fileName(fileName).
with(new ObjectDataTypeFactory()).open();
s = new MVStore.Builder().fileName(fileName).open();
map = s.openMap("test");
map.put(1, "Hello");
map.put("2", 200);
map.put(new Object[1], new Object[]{1, "2"});
s.store();
s.close();
s = new MVStore.Builder().fileName(fileName).
with(new ObjectDataTypeFactory()).open();
s = new MVStore.Builder().fileName(fileName).open();
map = s.openMap("test");
assertEquals("Hello", map.get(1).toString());
assertEquals(200, ((Integer) map.get("2")).intValue());
......@@ -749,15 +743,15 @@ public class TestMVStore extends TestBase {
assertFalse(m.containsKey("chunk.2"));
String id = s.getMetaMap().get("name.data");
assertEquals("name:data,key:o,value:o", m.get("map." + id));
assertEquals("name:data", m.get("map." + id));
assertTrue(m.containsKey("chunk.1"));
assertEquals("Hello", data.put("1", "Hallo"));
s.store();
assertEquals("name:data,key:o,value:o", m.get("map." + id));
assertEquals("name:data", m.get("map." + id));
assertTrue(m.get("root.1").length() > 0);
assertTrue(m.containsKey("chunk.1"));
assertEquals("id:1,length:260,maxLength:288,maxLengthLive:0," +
"metaRoot:274877910924,pageCount:2," +
assertEquals("id:1,length:246,maxLength:224,maxLengthLive:0," +
"metaRoot:274877910922,pageCount:2," +
"start:8192,time:0,version:1", m.get("chunk.1"));
assertTrue(m.containsKey("chunk.2"));
......@@ -1130,8 +1124,7 @@ public class TestMVStore extends TestBase {
*/
protected static MVStore openStore(String fileName) {
MVStore store = new MVStore.Builder().
fileName(fileName).
with(new SampleTypeFactory()).open();
fileName(fileName).open();
store.setPageSize(1000);
return store;
}
......
......@@ -38,7 +38,6 @@ public class TestObjectDataType extends TestBase {
private void testCommonValues() {
BigInteger largeBigInt = BigInteger.probablePrime(200, new Random(1));
ObjectDataType ot = new ObjectDataType();
assertEquals("o", ot.asString());
Object[] array = {
false, true,
Byte.MIN_VALUE, (byte) -1, (byte) 0, (byte) 1, Byte.MAX_VALUE,
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论