提交 900b5667 authored 作者: Thomas Mueller's avatar Thomas Mueller

MVStore: simpler API

上级 e845504a
......@@ -23,6 +23,7 @@ Change Log
</li><li>Issue 73: MySQL compatibility: support REPLACE, patch by Cemo Koc.
</li><li>The spatial index now works in MVCC mode when using the MVStore storage.
</li><li>MVStore: concurrency problems have been fixed.
The API has been simplified.
</li><li>Improve error message when dropping an index that belongs to a constraint,
specify constraint in error message.
</li><li>Issue 518: java.sql.Connection.commit() freezes after LOB modification with EXCLUSIVE connection
......
......@@ -121,8 +121,7 @@ public class OffHeapStore extends FileStore {
@Override
public void close() {
truncate(0);
freeSpace.clear();
// do nothing (keep the data until it is garbage collected)
}
@Override
......
......@@ -260,7 +260,7 @@ public class MVTableEngine implements TableEngine {
public void compactFile(long maxCompactTime) {
store.setRetentionTime(0);
long start = System.currentTimeMillis();
while (store.compact(90)) {
while (store.compact(99)) {
store.sync();
long time = System.currentTimeMillis() - start;
if (time > maxCompactTime) {
......@@ -280,7 +280,7 @@ public class MVTableEngine implements TableEngine {
public void close(long maxCompactTime) {
if (!store.isClosed() && store.getFileStore() != null) {
if (!store.getFileStore().isReadOnly()) {
store.store();
transactionStore.close();
long start = System.currentTimeMillis();
while (store.compact(90)) {
long time = System.currentTimeMillis() - start;
......
......@@ -170,8 +170,10 @@ public class TransactionStore {
public synchronized void close() {
// to avoid losing transaction ids
settings.put(LAST_TRANSACTION_ID, "" + lastTransactionId);
if (store.getFileStore() != null) {
store.store();
}
}
/**
* Begin a new transaction.
......@@ -191,7 +193,6 @@ public class TransactionStore {
private void commitIfNeeded() {
if (store.getUnsavedPageCount() > MAX_UNSAVED_PAGES) {
if (store.getFileStore() != null) {
store.commit();
store.store();
}
}
......@@ -354,10 +355,10 @@ public class TransactionStore {
firstOpenTransaction = -1;
}
if (store.getWriteDelay() == 0) {
if (store.getFileStore() == null) {
return;
if (store.getFileStore() != null) {
store.store();
}
store.commit();
return;
}
// to avoid having to store the transaction log,
// if there is no open transaction,
......@@ -1207,7 +1208,7 @@ public class TransactionStore {
*/
public Iterator<K> keyIterator(K from, boolean includeUncommitted) {
Cursor<K> it = map.keyIterator(from);
return wrapIterator(it, false);
return wrapIterator(it, includeUncommitted);
}
/**
......
......@@ -470,18 +470,18 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
prof.interval = 1;
prof.startCollecting();
if (test.mvStore) {
TestPerformance.main("-init", "-db", "9", "-size", "10000");
TestPerformance.main("-init", "-db", "9", "-size", "1000");
} else {
TestPerformance.main("-init", "-db", "1");
}
prof.stopCollecting();
System.out.println(prof.getTop(3));
System.out.println(prof.getTop(30));
if (test.mvStore) {
prof = new Profiler();
prof.depth = 16;
prof.interval = 1;
prof.startCollecting();
TestPerformance.main("-init", "-db", "1", "-size", "10000");
TestPerformance.main("-init", "-db", "1", "-size", "1000");
prof.stopCollecting();
System.out.println(prof.getTop(3));
}
......
......@@ -43,7 +43,6 @@ public class TestConcurrent extends TestMVStore {
@Override
public void test() throws Exception {
FileUtils.deleteRecursive(getBaseDir(), true);
FileUtils.createDirectories(getBaseDir());
FileUtils.deleteRecursive("memFS:", false);
......@@ -110,7 +109,7 @@ public class TestConcurrent extends TestMVStore {
m.clear();
s.removeMap(m);
if (x % 5 == 0) {
s.incrementVersion();
s.commit();
}
}
task.get();
......@@ -124,9 +123,9 @@ public class TestConcurrent extends TestMVStore {
}
}
assertEquals(1, chunkCount);
s.close();
}
FileUtils.deleteRecursive("memFS:", false);
}
private void testConcurrentStoreAndRemoveMap() throws InterruptedException {
......@@ -159,6 +158,7 @@ public class TestConcurrent extends TestMVStore {
}
task.get();
s.close();
FileUtils.deleteRecursive("memFS:", false);
}
private void testConcurrentStoreAndClose() throws InterruptedException {
......@@ -200,6 +200,7 @@ public class TestConcurrent extends TestMVStore {
}
s.close();
}
FileUtils.deleteRecursive("memFS:", false);
}
/**
......@@ -249,7 +250,7 @@ public class TestConcurrent extends TestMVStore {
}
m.get(rand.nextInt(size));
}
s.incrementVersion();
s.commit();
Thread.sleep(1);
}
task.get();
......@@ -341,7 +342,7 @@ public class TestConcurrent extends TestMVStore {
for (int k = 0; k < 10000; k++) {
Iterator<Integer> it = map.keyIterator(r.nextInt(len));
long old = s.getCurrentVersion();
s.incrementVersion();
s.commit();
s.setRetainVersion(old - 100);
while (map.getVersion() == old) {
Thread.yield();
......@@ -423,7 +424,7 @@ public class TestConcurrent extends TestMVStore {
notDetected.incrementAndGet();
}
}
s.incrementVersion();
s.commit();
Thread.sleep(1);
}
task.get();
......@@ -438,7 +439,7 @@ public class TestConcurrent extends TestMVStore {
for (int i = 0; i < size; i++) {
m.put(i, x);
}
s.incrementVersion();
s.commit();
Task task = new Task() {
@Override
public void call() throws Exception {
......@@ -462,7 +463,7 @@ public class TestConcurrent extends TestMVStore {
for (int i = 0; i < size; i++) {
m.put(i, x);
}
s.incrementVersion();
s.commit();
Thread.sleep(1);
}
task.get();
......
......@@ -148,7 +148,7 @@ public class TestMVStore extends TestBase {
s.store();
}
assertTrue(1000 < offHeap.getWriteCount());
// s.close();
s.close();
s = new MVStore.Builder().
fileStore(offHeap).
......@@ -253,7 +253,6 @@ public class TestMVStore extends TestBase {
m = s.openMap("data");
s.getFileStore().getFile().close();
m.put(1, "Hello");
s.commit();
for (int i = 0; i < 100; i++) {
if (exRef.get() != null) {
break;
......@@ -330,19 +329,19 @@ public class TestMVStore extends TestBase {
fileName(fileName).
open();
m = s.openMap("data");
assertFalse(m.containsKey(1));
assertTrue(m.containsKey(1));
m.put(1, data);
s.commit();
m.put(2, data);
m.put(-1, data);
s.store();
m.put(-2, data);
s.close();
s = new MVStore.Builder().
fileName(fileName).
open();
m = s.openMap("data");
assertTrue(m.containsKey(1));
assertFalse(m.containsKey(2));
assertTrue(m.containsKey(-1));
assertTrue(m.containsKey(-2));
s.close();
FileUtils.delete(fileName);
......@@ -377,7 +376,7 @@ public class TestMVStore extends TestBase {
m.put(1, "Hello");
s.store();
long v = s.getCurrentVersion();
m.put(2, "World");
m.put(2, "World.");
Thread.sleep(5);
// must not store, as nothing has been committed yet
s.closeImmediately();
......@@ -386,9 +385,11 @@ public class TestMVStore extends TestBase {
open();
s.setWriteDelay(1);
m = s.openMap("data");
assertEquals(null, m.get(2));
assertEquals("World.", m.get(2));
m.put(2, "World");
s.commit();
s.store();
v = s.getCurrentVersion();
m.put(3, "!");
for (int i = 100; i > 0; i--) {
......@@ -400,7 +401,7 @@ public class TestMVStore extends TestBase {
}
Thread.sleep(1);
}
s.close();
s.closeImmediately();
s = new MVStore.Builder().
fileName(fileName).
......@@ -408,7 +409,7 @@ public class TestMVStore extends TestBase {
m = s.openMap("data");
assertEquals("Hello", m.get(1));
assertEquals("World", m.get(2));
assertFalse(m.containsKey(3));
assertEquals("!", m.get(3));
s.close();
FileUtils.delete(fileName);
......@@ -517,7 +518,7 @@ public class TestMVStore extends TestBase {
MVMap<Integer, Integer> map;
map = s.openMap("hello");
map.put(1, 10);
long old = s.incrementVersion();
long old = s.commit();
s.renameMap(map, "world");
map.put(2, 20);
assertEquals("world", map.getName());
......@@ -557,7 +558,7 @@ public class TestMVStore extends TestBase {
s.store();
s.close();
int[] expectedReadsForCacheSize = {
3405, 2590, 1924, 1440, 1103, 956, 918
3405, 2590, 1924, 1440, 1108, 956, 918
};
for (int cacheSize = 0; cacheSize <= 6; cacheSize += 4) {
s = new MVStore.Builder().
......@@ -816,8 +817,10 @@ public class TestMVStore extends TestBase {
MVStore s = MVStore.open(fileName);
assertEquals(0, s.getCurrentVersion());
assertEquals(0, s.getStoreVersion());
s.setStoreVersion(0);
s.store();
s.setStoreVersion(1);
s.close();
s.closeImmediately();
s = MVStore.open(fileName);
assertEquals(1, s.getCurrentVersion());
assertEquals(0, s.getStoreVersion());
......@@ -840,7 +843,7 @@ public class TestMVStore extends TestBase {
map.put(i, 10 * i);
}
Iterator<Integer> it = map.keySet().iterator();
s.incrementVersion();
s.commit();
for (int i = 0; i < len; i += 2) {
map.remove(i);
}
......@@ -916,7 +919,7 @@ public class TestMVStore extends TestBase {
long oldVersion = s.getCurrentVersion();
// from now on, the old version is read-only
s.incrementVersion();
s.commit();
// more changes, in the new version
// changes can be rolled back if required
......@@ -976,7 +979,7 @@ public class TestMVStore extends TestBase {
if (op == 1) {
m.put("1", "" + s.getCurrentVersion());
}
s.incrementVersion();
s.commit();
}
for (int j = 0; j < s.getCurrentVersion(); j++) {
MVMap<String, String> old = m.openVersion(j);
......@@ -997,14 +1000,14 @@ public class TestMVStore extends TestBase {
MVMap<String, String> m;
m = s.openMap("data");
long first = s.getCurrentVersion();
s.incrementVersion();
s.commit();
m.put("1", "Hello");
m.put("2", "World");
for (int i = 10; i < 20; i++) {
m.put("" + i, "data");
}
long old = s.getCurrentVersion();
s.incrementVersion();
s.commit();
m.put("1", "Hallo");
m.put("2", "Welt");
MVMap<String, String> mFirst;
......@@ -1119,7 +1122,7 @@ public class TestMVStore extends TestBase {
assertTrue(s.hasUnsavedChanges());
MVMap<String, String> m0 = s.openMap("data0");
m.put("1", "Hello");
assertEquals(1, s.incrementVersion());
assertEquals(1, s.commit());
s.rollbackTo(1);
assertEquals(1, s.getCurrentVersion());
assertEquals("Hello", m.get("1"));
......@@ -1167,16 +1170,13 @@ public class TestMVStore extends TestBase {
assertEquals("Hello", m.get("1"));
assertFalse(m0.isReadOnly());
m.put("1", "Hallo");
s.incrementVersion();
s.commit();
long v3 = s.getCurrentVersion();
assertEquals(3, v3);
long v4 = s.store();
assertEquals(4, v4);
assertEquals(4, s.getCurrentVersion());
s.close();
s = openStore(fileName);
assertEquals(4, s.getCurrentVersion());
assertEquals(3, s.getCurrentVersion());
m = s.openMap("data");
m.put("1", "Hi");
s.store();
......@@ -1185,7 +1185,7 @@ public class TestMVStore extends TestBase {
s = openStore(fileName);
m = s.openMap("data");
assertEquals("Hi", m.get("1"));
s.rollbackTo(v4);
s.rollbackTo(v3);
assertEquals("Hallo", m.get("1"));
s.close();
......@@ -1212,7 +1212,7 @@ public class TestMVStore extends TestBase {
for (int i = 0; i < 10; i++) {
m2.put("" + i, "Test");
}
long v1 = s.incrementVersion();
long v1 = s.commit();
assertEquals(1, v1);
assertEquals(1, s.getCurrentVersion());
MVMap<String, String> m1 = s.openMap("data1");
......
......@@ -73,7 +73,7 @@ public class TestMVStoreBenchmark extends TestBase {
}
private static long[] getMemoryUsed(int count, int size) {
private long[] getMemoryUsed(int count, int size) {
long hash, tree, mv;
ArrayList<Map<Integer, String>> mapList;
long mem;
......@@ -107,6 +107,10 @@ public class TestMVStoreBenchmark extends TestBase {
mv = getMemory() - mem;
mapList.size();
trace("hash: " + hash / 1024 / 1024 + " mb");
trace("tree: " + tree / 1024 / 1024 + " mb");
trace("mv: " + mv / 1024 / 1024 + " mb");
return new long[]{hash, tree, mv};
}
......@@ -179,7 +183,7 @@ public class TestMVStoreBenchmark extends TestBase {
}
time = System.currentTimeMillis() - time;
}
// System.out.println(map.getClass().getName() + ": " + time);
trace(map.getClass().getName() + ": " + time);
return time;
}
......
......@@ -141,7 +141,7 @@ public class TestMVTableEngine extends TestBase {
conn.close();
long sizeNew = FileUtils.size(getBaseDir() + "/mvstore"
+ Constants.SUFFIX_MV_FILE);
assertTrue(sizeNew < sizeOld);
assertTrue("new: " + sizeNew + " old: " + sizeOld, sizeNew < sizeOld);
}
private void testTwoPhaseCommit() throws Exception {
......
......@@ -59,6 +59,7 @@ public class TestTransactionStore extends TestBase {
private void testStopWhileCommitting() throws Exception {
String fileName = getBaseDir() + "/testStopWhileCommitting.h3";
FileUtils.delete(fileName);
Random r = new Random(0);
for (int i = 0; i < 10;) {
MVStore s;
......@@ -100,6 +101,16 @@ public class TestTransactionStore extends TestBase {
task.get();
store.close();
s = MVStore.open(fileName);
// roll back a bit, until we have some undo log entries
assertTrue(s.hasMap("undoLog"));
for (int back = 0; back < 100; back++) {
int minus = r.nextInt(10);
s.rollbackTo(Math.max(0, s.getCurrentVersion() - minus));
MVMap<?, ?> undo = s.openMap("undoLog");
if (undo.size() > 0) {
break;
}
}
ts = new TransactionStore(s);
List<Transaction> list = ts.getOpenTransactions();
if (list.size() != 0) {
......@@ -111,10 +122,6 @@ public class TestTransactionStore extends TestBase {
s.close();
FileUtils.delete(fileName);
assertFalse(FileUtils.exists(fileName));
FileUtils.delete(fileName);
assertFalse(FileUtils.exists(fileName));
s.close();
FileUtils.delete(fileName);
}
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论