提交 36415f3f authored 作者: Thomas Mueller's avatar Thomas Mueller

A persistent tree map (work in progress).

上级 582ca70b
...@@ -105,7 +105,7 @@ import org.h2.test.server.TestWeb; ...@@ -105,7 +105,7 @@ import org.h2.test.server.TestWeb;
import org.h2.test.server.TestInit; import org.h2.test.server.TestInit;
import org.h2.test.store.TestCacheLIRS; import org.h2.test.store.TestCacheLIRS;
import org.h2.test.store.TestDataUtils; import org.h2.test.store.TestDataUtils;
import org.h2.test.store.TestTreeMapStore; import org.h2.test.store.TestBtreeMapStore;
import org.h2.test.synth.TestBtreeIndex; import org.h2.test.synth.TestBtreeIndex;
import org.h2.test.synth.TestCrashAPI; import org.h2.test.synth.TestCrashAPI;
import org.h2.test.synth.TestDiskFull; import org.h2.test.synth.TestDiskFull;
...@@ -664,8 +664,8 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -664,8 +664,8 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
private void testUnit() { private void testUnit() {
// store // store
new TestBtreeMapStore().runTest(this);
new TestCacheLIRS().runTest(this); new TestCacheLIRS().runTest(this);
new TestTreeMapStore().runTest(this);
new TestDataUtils().runTest(this); new TestDataUtils().runTest(this);
// unit // unit
......
...@@ -17,7 +17,7 @@ import org.h2.test.TestBase; ...@@ -17,7 +17,7 @@ import org.h2.test.TestBase;
/** /**
* Tests the tree map store. * Tests the tree map store.
*/ */
public class TestTreeMapStore extends TestBase { public class TestBtreeMapStore extends TestBase {
/** /**
* Run just this test. * Run just this test.
...@@ -28,7 +28,10 @@ public class TestTreeMapStore extends TestBase { ...@@ -28,7 +28,10 @@ public class TestTreeMapStore extends TestBase {
TestBase.createCaller().init().test(); TestBase.createCaller().init().test();
} }
public void test() throws Exception { public void test() {
testRollbackInMemory();
testRollbackStored();
testMeta();
testLargeImport(); testLargeImport();
testBtreeStore(); testBtreeStore();
testDefragment(); testDefragment();
...@@ -39,9 +42,150 @@ public class TestTreeMapStore extends TestBase { ...@@ -39,9 +42,150 @@ public class TestTreeMapStore extends TestBase {
testSimple(); testSimple();
} }
private void testLargeImport() throws Exception { private void testRollbackStored() {
String fileName = getBaseDir() + "/testMeta.h3";
FileUtils.delete(fileName);
BtreeMap<String, String> meta;
BtreeMapStore s = openStore(fileName);
assertEquals(-1, s.getRetainChunk());
s.setRetainChunk(0);
assertEquals(0, s.getRetainChunk());
assertEquals(0, s.getCurrentVersion());
assertFalse(s.hasUnsavedChanges());
BtreeMap<String, String> m = s.openMap("data", String.class, String.class);
assertTrue(s.hasUnsavedChanges());
BtreeMap<String, String> m0 = s.openMap("data0", String.class, String.class);
m.put("1", "Hello");
assertEquals(1, s.commit());
s.rollbackTo(1);
assertEquals("Hello", m.get("1"));
long v2 = s.store();
assertFalse(s.hasUnsavedChanges());
s.close();
s = openStore(fileName);
s.setRetainChunk(0);
assertEquals(2, s.getCurrentVersion());
meta = s.getMetaMap();
m = s.openMap("data", String.class, String.class);
m0 = s.openMap("data0", String.class, String.class);
BtreeMap<String, String> m1 = s.openMap("data1", String.class, String.class);
m.put("1", "Hallo");
m0.put("1", "Hallo");
m1.put("1", "Hallo");
assertEquals("Hallo", m.get("1"));
assertEquals("Hallo", m1.get("1"));
s.rollbackTo(v2);
assertFalse(s.hasUnsavedChanges());
assertNull(meta.get("map.data1"));
assertNull(m0.get("1"));
assertEquals("Hello", m.get("1"));
s.store();
s.close();
s = openStore(fileName);
s.setRetainChunk(0);
assertEquals(2, s.getCurrentVersion());
meta = s.getMetaMap();
assertTrue(meta.get("map.data") != null);
assertTrue(meta.get("map.data0") != null);
assertNull(meta.get("map.data1"));
m = s.openMap("data", String.class, String.class);
m0 = s.openMap("data0", String.class, String.class);
assertNull(m0.get("1"));
assertEquals("Hello", m.get("1"));
assertFalse(m0.isReadOnly());
m.put("1", "Hallo");
s.commit();
assertEquals(3, s.getCurrentVersion());
long v4 = s.store();
assertEquals(4, v4);
assertEquals(4, s.getCurrentVersion());
s.close();
s = openStore(fileName);
s.setRetainChunk(0);
m = s.openMap("data", String.class, String.class);
m.put("1", "Hello");
s.store();
s.close();
s = openStore(fileName);
s.setRetainChunk(0);
m = s.openMap("data", String.class, String.class);
assertEquals("Hello", m.get("1"));
s.rollbackTo(v4);
assertEquals("Hallo", m.get("1"));
s.close();
s = openStore(fileName);
s.setRetainChunk(0);
m = s.openMap("data", String.class, String.class);
assertEquals("Hallo", m.get("1"));
s.close();
}
private void testRollbackInMemory() {
String fileName = getBaseDir() + "/testMeta.h3";
FileUtils.delete(fileName);
BtreeMapStore s = openStore(fileName);
s.setMaxPageSize(5);
BtreeMap<String, String> m = s.openMap("data", String.class, String.class);
BtreeMap<String, String> m0 = s.openMap("data0", String.class, String.class);
BtreeMap<String, String> m2 = s.openMap("data2", String.class, String.class);
m.put("1", "Hello");
for (int i = 0; i < 10; i++) {
m2.put("" + i, "Test");
}
long v1 = s.commit();
assertEquals(1, v1);
BtreeMap<String, String> m1 = s.openMap("data1", String.class, String.class);
assertEquals("Test", m2.get("1"));
m.put("1", "Hallo");
m0.put("1", "Hallo");
m1.put("1", "Hallo");
m2.clear();
assertEquals("Hallo", m.get("1"));
assertEquals("Hallo", m1.get("1"));
s.rollbackTo(v1);
for (int i = 0; i < 10; i++) {
assertEquals("Test", m2.get("" + i));
}
assertEquals("Hello", m.get("1"));
assertNull(m0.get("1"));
assertTrue(m1.isClosed());
assertFalse(m0.isReadOnly());
assertTrue(m1.isReadOnly());
s.close();
}
private void testMeta() {
String fileName = getBaseDir() + "/testMeta.h3";
FileUtils.delete(fileName);
BtreeMapStore s = openStore(fileName);
BtreeMap<String, String> m = s.getMetaMap();
s.setRetainChunk(0);
BtreeMap<String, String> data = s.openMap("data", String.class, String.class);
data.put("1", "Hello");
data.put("2", "World");
s.store();
assertEquals("1/0//", m.get("map.data"));
assertTrue(m.containsKey("chunk.1"));
data.put("1", "Hallo");
s.store();
assertEquals("1/0//", m.get("map.data"));
assertTrue(m.get("root.1").length() > 0);
assertTrue(m.containsKey("chunk.1"));
assertTrue(m.containsKey("chunk.2"));
s.rollbackTo(1);
assertTrue(m.containsKey("chunk.1"));
assertFalse(m.containsKey("chunk.2"));
s.close();
}
private void testLargeImport() {
String fileName = getBaseDir() + "/testCsv.h3"; String fileName = getBaseDir() + "/testCsv.h3";
int len = 10000; int len = 1000;
for (int j = 0; j < 5; j++) { for (int j = 0; j < 5; j++) {
FileUtils.delete(fileName); FileUtils.delete(fileName);
BtreeMapStore s = openStore(fileName); BtreeMapStore s = openStore(fileName);
...@@ -188,7 +332,7 @@ public class TestTreeMapStore extends TestBase { ...@@ -188,7 +332,7 @@ public class TestTreeMapStore extends TestBase {
BtreeMap<Integer, Integer> m = s.openMap("data", Integer.class, Integer.class); BtreeMap<Integer, Integer> m = s.openMap("data", Integer.class, Integer.class);
TreeMap<Integer, Integer> map = new TreeMap<Integer, Integer>(); TreeMap<Integer, Integer> map = new TreeMap<Integer, Integer>();
Random r = new Random(1); Random r = new Random(1);
int operationCount = 10000; int operationCount = 1000;
int maxValue = 30; int maxValue = 30;
for (int i = 0; i < operationCount; i++) { for (int i = 0; i < operationCount; i++) {
int k = r.nextInt(maxValue); int k = r.nextInt(maxValue);
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
*/ */
package org.h2.test.store; package org.h2.test.store;
import org.h2.dev.store.btree.Page; import org.h2.dev.store.btree.DataUtils;
import org.h2.test.TestBase; import org.h2.test.TestBase;
/** /**
...@@ -23,30 +23,59 @@ public class TestDataUtils extends TestBase { ...@@ -23,30 +23,59 @@ public class TestDataUtils extends TestBase {
} }
public void test() throws Exception { public void test() throws Exception {
testCheckValue();
testPagePos(); testPagePos();
testEncodeLength();
}
private void testCheckValue() {
// 0 xor 0 = 0
assertEquals(0, DataUtils.getCheckValue(0));
// 1111... xor 1111... = 0
assertEquals(0, DataUtils.getCheckValue(-1));
// 0 xor 1111... = 1111...
assertEquals((short) -1, DataUtils.getCheckValue(-1 >>> 16));
// 1111... xor 0 = 1111...
assertEquals((short) -1, DataUtils.getCheckValue(-1 << 16));
// 0 xor 1000... = 1000...
assertEquals((short) (1 << 15), DataUtils.getCheckValue(1 << 15));
// 1000... xor 0 = 1000...
assertEquals((short) (1 << 15), DataUtils.getCheckValue(1 << 31));
} }
private void testPagePos() { private void testPagePos() {
for (int chunkId = 0; chunkId < 67000000; chunkId += 670000) {
for (long offset = 0; offset < Integer.MAX_VALUE; offset += Integer.MAX_VALUE / 100) {
for (int length = 0; length < 2000000; length += 200000) {
long pos = DataUtils.getPos(chunkId, (int) offset, length);
assertEquals(chunkId, DataUtils.getChunkId(pos));
assertEquals(offset, DataUtils.getOffset(pos));
assertTrue(DataUtils.getMaxLength(pos) >= length);
}
}
}
}
private void testEncodeLength() {
int lastCode = 0; int lastCode = 0;
assertEquals(0, Page.encodeLength(32)); assertEquals(0, DataUtils.encodeLength(32));
assertEquals(1, Page.encodeLength(33)); assertEquals(1, DataUtils.encodeLength(33));
assertEquals(1, Page.encodeLength(48)); assertEquals(1, DataUtils.encodeLength(48));
assertEquals(2, Page.encodeLength(49)); assertEquals(2, DataUtils.encodeLength(49));
assertEquals(30, Page.encodeLength(1024 * 1024)); assertEquals(30, DataUtils.encodeLength(1024 * 1024));
assertEquals(31, Page.encodeLength(1024 * 1024 + 1)); assertEquals(31, DataUtils.encodeLength(1024 * 1024 + 1));
for (int i = 1024 * 1024 + 1; i < 100 * 1024 * 1024; i += 1024) { for (int i = 1024 * 1024 + 1; i < 100 * 1024 * 1024; i += 1024) {
int code = Page.encodeLength(i); int code = DataUtils.encodeLength(i);
assertEquals(31, code); assertEquals(31, code);
} }
for (int i = 0; i < 1024 * 1024; i++) { for (int i = 0; i < 2 * 1024 * 1024; i++) {
int code = Page.encodeLength(i); int code = DataUtils.encodeLength(i);
assertTrue(code <= 31 && code >= 0); assertTrue(code <= 31 && code >= 0);
assertTrue(code >= lastCode); assertTrue(code >= lastCode);
if (code > lastCode) { if (code > lastCode) {
lastCode = code; lastCode = code;
} }
int max = Page.getMaxLength(code); int max = DataUtils.getMaxLength(code);
assertTrue(max >= i && max >= 32); assertTrue(max >= i && max >= 32);
} }
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论