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

MVStore table engine

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