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

MVStore table engine

上级 674328ac
......@@ -828,7 +828,6 @@ public class MVStore {
meta.remove("rollbackOnOpen");
retainChunk = null;
}
// the last chunk was not completely correct in the last store()
// this needs to be updated now (it's better not to update right after
// storing, because that would modify the meta map again)
......@@ -1746,6 +1745,10 @@ public class MVStore {
return readOnly;
}
public boolean isClosed() {
return closed;
}
/**
* A background writer to automatically store changes from time to time.
*/
......
......@@ -106,8 +106,24 @@ public class MVPrimaryIndex extends BaseIndex {
Long c = row.getValue(mainIndexColumn).getLong();
row.setKey(c);
}
if (mvTable.getContainsLargeObject()) {
for (int i = 0, len = row.getColumnCount(); i < len; i++) {
Value v = row.getValue(i);
Value v2 = v.link(database, getId());
if (v2.isLinked()) {
session.unlinkAtCommitStop(v2);
}
if (v != v2) {
row.setValue(i, v2);
}
}
}
TransactionMap<Value, Value> map = getMap(session);
if (map.containsKey(ValueLong.get(row.getKey()))) {
Value key = ValueLong.get(row.getKey());
Value old = map.getLatest(key);
if (old != null) {
String sql = "PRIMARY KEY ON " + table.getSQL();
if (mainIndexColumn >= 0 && mainIndexColumn < indexColumns.length) {
sql += "(" + indexColumns[mainIndexColumn].getSQL() + ")";
......@@ -116,12 +132,20 @@ public class MVPrimaryIndex extends BaseIndex {
e.setSource(this);
throw e;
}
map.put(ValueLong.get(row.getKey()), ValueArray.get(row.getValueList()));
map.put(key, ValueArray.get(row.getValueList()));
lastKey = Math.max(lastKey, row.getKey());
}
@Override
public void remove(Session session, Row row) {
if (mvTable.getContainsLargeObject()) {
for (int i = 0, len = row.getColumnCount(); i < len; i++) {
Value v = row.getValue(i);
if (v.isLinked()) {
session.unlinkAtCommit(v);
}
}
}
TransactionMap<Value, Value> map = getMap(session);
Value old = map.remove(ValueLong.get(row.getKey()));
if (old == null) {
......@@ -172,8 +196,7 @@ public class MVPrimaryIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
TransactionMap<Value, Value> map = getMap(session);
long cost = 10 * (map.getSize() + Constants.COST_ROW_OFFSET);
long cost = 10 * (dataMap.map.getSize() + Constants.COST_ROW_OFFSET);
return cost;
}
......@@ -208,10 +231,11 @@ public class MVPrimaryIndex extends BaseIndex {
@Override
public Cursor findFirstOrLast(Session session, boolean first) {
TransactionMap<Value, Value> map = getMap(session);
if (map.getSize() == 0) {
Value v = first ? map.firstKey() : map.lastKey();
if (v == null) {
return new MVStoreCursor(session, Collections.<Value>emptyList().iterator(), 0);
}
long key = first ? map.firstKey().getLong() : map.lastKey().getLong();
long key = v.getLong();
MVStoreCursor cursor = new MVStoreCursor(session,
Arrays.asList((Value) ValueLong.get(key)).iterator(), key);
cursor.next();
......@@ -231,7 +255,7 @@ public class MVPrimaryIndex extends BaseIndex {
@Override
public long getRowCountApproximation() {
return getMap(null).getSize();
return dataMap.map.getSize();
}
public long getDiskSpaceUsed() {
......
......@@ -172,8 +172,7 @@ public class MVSecondaryIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
TransactionMap<Value, Value> map = getMap(session);
return 10 * getCostRangeIndex(masks, map.getSize(), sortOrder);
return 10 * getCostRangeIndex(masks, dataMap.map.getSize(), sortOrder);
}
@Override
......@@ -217,7 +216,7 @@ public class MVSecondaryIndex extends BaseIndex {
@Override
public boolean needRebuild() {
return getMap(null).getSize() == 0;
return dataMap.map.getSize() == 0;
}
@Override
......@@ -228,7 +227,7 @@ public class MVSecondaryIndex extends BaseIndex {
@Override
public long getRowCountApproximation() {
return getMap(null).getSize();
return dataMap.map.getSize();
}
public long getDiskSpaceUsed() {
......
......@@ -234,6 +234,9 @@ public class TransactionStore {
* @param maxLogId the last log id
*/
void commit(Transaction t, long maxLogId) {
if (store.isClosed()) {
return;
}
for (long logId = 0; logId < maxLogId; logId++) {
long[] undoKey = new long[] {
t.getId(), logId };
......@@ -634,6 +637,7 @@ public class TransactionStore {
*
* @param key the key
* @param value the new value (not null)
* @return the old value
* @throws IllegalStateException if a lock timeout occurs
*/
public V put(K key, V value) {
......
......@@ -8,6 +8,7 @@ package org.h2.test.store;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
......@@ -38,8 +39,9 @@ public class TestMVTableEngine extends TestBase {
}
public void test() throws Exception {
//testSpeed();
// testBlob();
// testSpeed();
testReopen();
testBlob();
testExclusiveLock();
testEncryption();
testReadOnly();
......@@ -61,7 +63,7 @@ int tes;
dbName = "mvstore" +
";DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine";
dbName += ";LOCK_MODE=0";
// dbName += ";LOG=0";
dbName += ";LOG=0";
testSpeed(dbName);
//System.out.println(prof.getTop(10));
}
......@@ -117,8 +119,8 @@ int tes;
// 1541 mvstore;DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine;LOCK_MODE=0 before
// 1551 mvstore;DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine;LOCK_MODE=0 after
prep.setString(2, new String(new char[10]).replace((char) 0, 'x'));
for (int i = 0; i < 80000; i++) {
prep.setString(2, new String(new char[100]).replace((char) 0, 'x'));
for (int i = 0; i < 200000; i++) {
prep.setInt(1, i);
prep.execute();
......@@ -128,6 +130,21 @@ int tes;
//System.out.println(prof.getTop(10));
System.out.println((System.currentTimeMillis() - time) + " " + dbName + " after");
}
private void testReopen() throws SQLException {
FileUtils.deleteRecursive(getBaseDir(), true);
Connection conn;
Statement stat;
conn = getConnection("mvstore");
stat = conn.createStatement();
stat.execute("create table test(id int, name varchar) "
+ "engine \"org.h2.mvstore.db.MVTableEngine\"");
conn.close();
conn = getConnection("mvstore");
stat = conn.createStatement();
stat.execute("drop table test");
conn.close();
}
private void testBlob() throws SQLException, IOException {
FileUtils.deleteRecursive(getBaseDir(), true);
......@@ -139,10 +156,9 @@ int tes;
stat = conn.createStatement();
stat.execute("create table test(id int, name blob)");
PreparedStatement prep = conn.prepareStatement("insert into test values(1, ?)");
prep.setBinaryStream(1, new ByteArrayInputStream(new byte[1000]));
prep.setBinaryStream(1, new ByteArrayInputStream(new byte[129]));
prep.execute();
conn.close();
conn = getConnection(dbName);
stat = conn.createStatement();
ResultSet rs = stat.executeQuery("select * from test");
......@@ -152,7 +168,7 @@ int tes;
while (in.read() >= 0) {
len++;
}
assertEquals(10000, len);
assertEquals(129, len);
}
conn.close();
FileUtils.deleteRecursive(getBaseDir(), true);
......@@ -169,11 +185,12 @@ int tes;
String password = "123 123";
conn = DriverManager.getConnection(url, user, password);
stat = conn.createStatement();
stat.execute("create table test(id int)");
stat.execute("create table test(id int primary key)");
conn.close();
conn = DriverManager.getConnection(url, user, password);
stat = conn.createStatement();
stat.execute("select * from test");
stat.execute("drop table test");
conn.close();
FileUtils.deleteRecursive(getBaseDir(), true);
}
......@@ -450,6 +467,8 @@ int tes;
assertEquals(1, rs.getInt(1));
assertEquals("Hello", rs.getString(2));
assertEquals(1, rs.getInt(3));
stat.execute("update test set name = 'Hello' where id = 1");
if (!config.memory) {
conn.close();
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论