提交 46188bab authored 作者: Thomas Mueller's avatar Thomas Mueller

MVTableEngine

上级 684c03ce
...@@ -268,7 +268,7 @@ public class MVStore { ...@@ -268,7 +268,7 @@ public class MVStore {
MVStore(HashMap<String, Object> config) { MVStore(HashMap<String, Object> config) {
this.compress = config.containsKey("compress"); this.compress = config.containsKey("compress");
Object o = config.get("pageSplitSize"); Object o = config.get("pageSplitSize");
pageSplitSize = o == null ? 6 * 1024 : (Integer) o; pageSplitSize = o == null ? 16 * 1024 : (Integer) o;
o = config.get("backgroundExceptionHandler"); o = config.get("backgroundExceptionHandler");
this.backgroundExceptionHandler = (UncaughtExceptionHandler) o; this.backgroundExceptionHandler = (UncaughtExceptionHandler) o;
meta = new MVMapConcurrent<String, String>(StringDataType.INSTANCE, meta = new MVMapConcurrent<String, String>(StringDataType.INSTANCE,
...@@ -1056,6 +1056,7 @@ public class MVStore { ...@@ -1056,6 +1056,7 @@ public class MVStore {
chunks.remove(c.id); chunks.remove(c.id);
meta.remove("chunk." + c.id); meta.remove("chunk." + c.id);
} else { } else {
meta.put("chunk." + c.id, c.asString());
// remove this chunk in the next save operation // remove this chunk in the next save operation
registerFreePage(storeVersion + 1, c.id, 0, 0); registerFreePage(storeVersion + 1, c.id, 0, 0);
} }
...@@ -2153,7 +2154,7 @@ public class MVStore { ...@@ -2153,7 +2154,7 @@ public class MVStore {
/** /**
* Set the amount of memory a page should contain at most, in bytes, * Set the amount of memory a page should contain at most, in bytes,
* before it is split. The default is 6 KB. This is not a limit in the * before it is split. The default is 16 KB. This is not a limit in the
* page size, as pages with one entry can get larger. It is just the * page size, as pages with one entry can get larger. It is just the
* point where pages that contain more than one entry are split. * point where pages that contain more than one entry are split.
* *
......
...@@ -159,7 +159,10 @@ public class MVSecondaryIndex extends BaseIndex { ...@@ -159,7 +159,10 @@ public class MVSecondaryIndex extends BaseIndex {
for (int i = 0; i < columns.length; i++) { for (int i = 0; i < columns.length; i++) {
Column c = columns[i]; Column c = columns[i];
int idx = c.getColumnId(); int idx = c.getColumnId();
array[i] = r.getValue(idx); Value v = r.getValue(idx);
if (v != null) {
array[i] = v.convertTo(c.getType());
}
} }
array[keyColumns - 1] = ValueLong.get(r.getKey()); array[keyColumns - 1] = ValueLong.get(r.getKey());
return ValueArray.get(array); return ValueArray.get(array);
......
...@@ -8,6 +8,7 @@ package org.h2.mvstore.db; ...@@ -8,6 +8,7 @@ package org.h2.mvstore.db;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -53,6 +54,8 @@ public class TransactionStore { ...@@ -53,6 +54,8 @@ public class TransactionStore {
* Key: [ transactionId, logId ], value: [ opType, mapId, key, oldValue ]. * Key: [ transactionId, logId ], value: [ opType, mapId, key, oldValue ].
*/ */
final MVMap<long[], Object[]> undoLog; final MVMap<long[], Object[]> undoLog;
;
// TODO should be <long, Object[]>
/** /**
* The lock timeout in milliseconds. 0 means timeout immediately. * The lock timeout in milliseconds. 0 means timeout immediately.
...@@ -73,6 +76,8 @@ public class TransactionStore { ...@@ -73,6 +76,8 @@ public class TransactionStore {
private long firstOpenTransaction = -1; private long firstOpenTransaction = -1;
private HashMap<Integer, MVMap<Object, VersionedValue>> maps = New.hashMap();
/** /**
* Create a new transaction store. * Create a new transaction store.
* *
...@@ -145,7 +150,7 @@ public class TransactionStore { ...@@ -145,7 +150,7 @@ public class TransactionStore {
int status; int status;
String name; String name;
if (data == null) { if (data == null) {
key[1] = 0; key = new long[] { key[0], 0 };
if (undoLog.containsKey(key)) { if (undoLog.containsKey(key)) {
status = Transaction.STATUS_OPEN; status = Transaction.STATUS_OPEN;
} else { } else {
...@@ -242,6 +247,11 @@ public class TransactionStore { ...@@ -242,6 +247,11 @@ public class TransactionStore {
} }
} }
<K, V> void removeMap(TransactionMap<K, V> map) {
maps.remove(map.mapId);
store.removeMap(map.map);
}
/** /**
* Commit a transaction. * Commit a transaction.
* *
...@@ -289,6 +299,10 @@ public class TransactionStore { ...@@ -289,6 +299,10 @@ public class TransactionStore {
} }
private synchronized MVMap<Object, VersionedValue> openMap(int mapId) { private synchronized MVMap<Object, VersionedValue> openMap(int mapId) {
MVMap<Object, VersionedValue> map = maps.get(mapId);
if (map != null) {
return map;
}
// TODO open map by id if possible // TODO open map by id if possible
Map<String, String> meta = store.getMetaMap(); Map<String, String> meta = store.getMetaMap();
String m = meta.get("map." + mapId); String m = meta.get("map." + mapId);
...@@ -301,7 +315,8 @@ public class TransactionStore { ...@@ -301,7 +315,8 @@ public class TransactionStore {
MVMap.Builder<Object, VersionedValue> mapBuilder = MVMap.Builder<Object, VersionedValue> mapBuilder =
new MVMap.Builder<Object, VersionedValue>(). new MVMap.Builder<Object, VersionedValue>().
keyType(dataType).valueType(vt); keyType(dataType).valueType(vt);
MVMap<Object, VersionedValue> map = store.openMap(mapName, mapBuilder); map = store.openMap(mapName, mapBuilder);
maps.put(mapId, map);
return map; return map;
} }
...@@ -735,7 +750,12 @@ public class TransactionStore { ...@@ -735,7 +750,12 @@ public class TransactionStore {
* @param map the map * @param map the map
*/ */
public <K, V> void removeMap(TransactionMap<K, V> map) { public <K, V> void removeMap(TransactionMap<K, V> map) {
store.store.removeMap(map.map); store.removeMap(map);
}
@Override
public String toString() {
return "" + transactionId;
} }
} }
...@@ -756,9 +776,12 @@ public class TransactionStore { ...@@ -756,9 +776,12 @@ public class TransactionStore {
*/ */
final MVMap<K, VersionedValue> map; final MVMap<K, VersionedValue> map;
private Transaction transaction; /**
* The map id.
*/
final int mapId;
private final int mapId; private Transaction transaction;
/** /**
* If a record was read that was updated by this transaction, and the * If a record was read that was updated by this transaction, and the
...@@ -1074,7 +1097,7 @@ public class TransactionStore { ...@@ -1074,7 +1097,7 @@ public class TransactionStore {
return data; return data;
} }
} }
// added or updated by another transaction // added, updated, or removed by another transaction
boolean open = transaction.store.isTransactionOpen(tx); boolean open = transaction.store.isTransactionOpen(tx);
if (!open) { if (!open) {
// it is committed // it is committed
...@@ -1087,7 +1110,8 @@ public class TransactionStore { ...@@ -1087,7 +1110,8 @@ public class TransactionStore {
d = transaction.store.undoLog.get(x); d = transaction.store.undoLog.get(x);
} }
if (d == null) { if (d == null) {
// committed or rolled back in the meantime // this entry was committed or rolled back
// in the meantime (the transaction might still be open)
data = map.get(key); data = map.get(key);
} else { } else {
data = (VersionedValue) d[3]; data = (VersionedValue) d[3];
...@@ -1298,6 +1322,12 @@ public class TransactionStore { ...@@ -1298,6 +1322,12 @@ public class TransactionStore {
* The value. * The value.
*/ */
public Object value; public Object value;
@Override
public String toString() {
return "{" + transactionId + "/" + logId + "}: " + value;
}
} }
/** /**
......
...@@ -130,9 +130,6 @@ public class ValueDataType implements DataType { ...@@ -130,9 +130,6 @@ public class ValueDataType implements DataType {
if (a == b) { if (a == b) {
return 0; return 0;
} }
int dataType = Value.getHigherOrder(a.getType(), b.getType());
a = a.convertTo(dataType);
b = b.convertTo(dataType);
return a.compareTypeSave(b, compareMode); return a.compareTypeSave(b, compareMode);
} }
......
...@@ -486,6 +486,8 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -486,6 +486,8 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
TestPerformance.main("-init", "-db", "1", "-size", "1000"); TestPerformance.main("-init", "-db", "1", "-size", "1000");
prof.stopCollecting(); prof.stopCollecting();
System.out.println(prof.getTop(3)); System.out.println(prof.getTop(3));
TestPerformance.main("-init", "-db", "1", "-size", "1000");
TestPerformance.main("-init", "-db", "9", "-size", "1000");
} }
// Recover.execute("data", null); // Recover.execute("data", null);
// RunScript.execute("jdbc:h2:data/test2", // RunScript.execute("jdbc:h2:data/test2",
......
...@@ -573,7 +573,7 @@ public class TestMVStore extends TestBase { ...@@ -573,7 +573,7 @@ public class TestMVStore extends TestBase {
} }
s.close(); s.close();
int[] expectedReadsForCacheSize = { int[] expectedReadsForCacheSize = {
3413, 2590, 1924, 1440, 1112, 956, 918 3406, 2590, 1924, 1440, 1102, 956, 918
}; };
for (int cacheSize = 0; cacheSize <= 6; cacheSize += 4) { for (int cacheSize = 0; cacheSize <= 6; cacheSize += 4) {
s = new MVStore.Builder(). s = new MVStore.Builder().
...@@ -905,10 +905,12 @@ public class TestMVStore extends TestBase { ...@@ -905,10 +905,12 @@ public class TestMVStore extends TestBase {
map.put(1, "Hello World"); map.put(1, "Hello World");
// System.out.println(map.get(1)); // System.out.println(map.get(1));
// mark the changes as committed // close the store (this will persist changes)
s.commit(); s.close();
// close the store s = MVStore.open(fileName);
map = s.openMap("data");
assertEquals("Hello World", map.get(1));
s.close(); s.close();
} }
......
...@@ -124,6 +124,9 @@ public class TestMVTableEngine extends TestBase { ...@@ -124,6 +124,9 @@ public class TestMVTableEngine extends TestBase {
stat.execute("create table test(id int primary key, data varchar)"); stat.execute("create table test(id int primary key, data varchar)");
stat.execute("insert into test select x, space(1000) from system_range(1, 1000)"); stat.execute("insert into test select x, space(1000) from system_range(1, 1000)");
stat.execute("drop table test"); stat.execute("drop table test");
// this table is kept
stat.execute("create table test" + i + "(id int primary key) " +
"as select x from system_range(1, 1000)");
conn.close(); conn.close();
long size = FileUtils.size(getBaseDir() + "/mvstore" long size = FileUtils.size(getBaseDir() + "/mvstore"
+ Constants.SUFFIX_MV_FILE); + Constants.SUFFIX_MV_FILE);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论