提交 726c1440 authored 作者: Thomas Mueller's avatar Thomas Mueller

MVStore: Fix "version to keep"; documentation

上级 aa600f94
...@@ -49,6 +49,7 @@ TransactionStore: ...@@ -49,6 +49,7 @@ TransactionStore:
MVStore: MVStore:
- maybe change the length code to have lower gaps - maybe change the length code to have lower gaps
- data kept in stream store if transaction is not committed?
- automated 'kill process' and 'power failure' test - automated 'kill process' and 'power failure' test
- test and possibly improve compact operation (for large dbs) - test and possibly improve compact operation (for large dbs)
...@@ -1722,9 +1723,9 @@ public class MVStore { ...@@ -1722,9 +1723,9 @@ public class MVStore {
} }
/** /**
* How many versions to retain for in-memory stores. If not set, 5 versions * How many versions to retain for in-memory stores. If not set, 5 old
* are retained. * versions are retained.
* *
* @param count the number of versions to keep * @param count the number of versions to keep
*/ */
public void setVersionsToKeep(int count) { public void setVersionsToKeep(int count) {
...@@ -1732,7 +1733,7 @@ public class MVStore { ...@@ -1732,7 +1733,7 @@ public class MVStore {
} }
/** /**
* Get the oldest version to retain in memory. * Get the oldest version to retain in memory (for in-memory stores).
* *
* @return the version * @return the version
*/ */
...@@ -1749,7 +1750,7 @@ public class MVStore { ...@@ -1749,7 +1750,7 @@ public class MVStore {
long getOldestVersionToKeep() { long getOldestVersionToKeep() {
long v = currentVersion; long v = currentVersion;
if (fileStore == null) { if (fileStore == null) {
return v - versionsToKeep; return v - versionsToKeep + 1;
} }
long storeVersion = currentStoreVersion; long storeVersion = currentStoreVersion;
if (storeVersion > -1) { if (storeVersion > -1) {
...@@ -2321,12 +2322,12 @@ public class MVStore { ...@@ -2321,12 +2322,12 @@ public class MVStore {
/** /**
* Encrypt / decrypt the file using the given password. This method has * Encrypt / decrypt the file using the given password. This method has
* no effect for in-memory stores. The password is passed as a char * no effect for in-memory stores. The password is passed as a
* array so that it can be cleared as soon as possible. Please note * char array so that it can be cleared as soon as possible. Please note
* there is still a small risk that password stays in memory (due to * there is still a small risk that password stays in memory (due to
* Java garbage collection). Also, the hashed encryption key is kept in * Java garbage collection). Also, the hashed encryption key is kept in
* memory as long as the file is open. * memory as long as the file is open.
* *
* @param password the password * @param password the password
* @return this * @return this
*/ */
...@@ -2402,8 +2403,11 @@ public class MVStore { ...@@ -2402,8 +2403,11 @@ public class MVStore {
} }
/** /**
* Use the provided file store instead of the default one. * Use the provided file store instead of the default one. Please note
* * that any kind of store (including an off-heap store) is considered a
* "persistence", while an "in-memory store" means objects are not
* persisted and fully kept in the JVM heap.
*
* @param store the file store * @param store the file store
* @return this * @return this
*/ */
......
...@@ -149,10 +149,12 @@ public class StreamStore { ...@@ -149,10 +149,12 @@ public class StreamStore {
} }
boolean eof = len < maxBlockSize; boolean eof = len < maxBlockSize;
if (len < minBlockSize) { if (len < minBlockSize) {
// in-place: 0, len (int), data
id.write(0); id.write(0);
DataUtils.writeVarInt(id, len); DataUtils.writeVarInt(id, len);
id.write(buff); id.write(buff);
} else { } else {
// block: 1, len (int), blockId (long)
id.write(1); id.write(1);
DataUtils.writeVarInt(id, len); DataUtils.writeVarInt(id, len);
DataUtils.writeVarLong(id, writeBlock(buff)); DataUtils.writeVarLong(id, writeBlock(buff));
...@@ -181,6 +183,7 @@ public class StreamStore { ...@@ -181,6 +183,7 @@ public class StreamStore {
private ByteArrayOutputStream putIndirectId(ByteArrayOutputStream id) throws IOException { private ByteArrayOutputStream putIndirectId(ByteArrayOutputStream id) throws IOException {
byte[] data = id.toByteArray(); byte[] data = id.toByteArray();
id = new ByteArrayOutputStream(); id = new ByteArrayOutputStream();
// indirect: 2, total len (long), blockId (long)
id.write(2); id.write(2);
DataUtils.writeVarLong(id, length(data)); DataUtils.writeVarLong(id, length(data));
DataUtils.writeVarLong(id, writeBlock(data)); DataUtils.writeVarLong(id, writeBlock(data));
...@@ -241,15 +244,18 @@ public class StreamStore { ...@@ -241,15 +244,18 @@ public class StreamStore {
while (idBuffer.hasRemaining()) { while (idBuffer.hasRemaining()) {
switch (idBuffer.get()) { switch (idBuffer.get()) {
case 0: case 0:
// in-place: 0, len (int), data
int len = DataUtils.readVarInt(idBuffer); int len = DataUtils.readVarInt(idBuffer);
idBuffer.position(idBuffer.position() + len); idBuffer.position(idBuffer.position() + len);
break; break;
case 1: case 1:
// block: 1, len (int), blockId (long)
DataUtils.readVarInt(idBuffer); DataUtils.readVarInt(idBuffer);
long k = DataUtils.readVarLong(idBuffer); long k = DataUtils.readVarLong(idBuffer);
map.remove(k); map.remove(k);
break; break;
case 2: case 2:
// indirect: 2, total len (long), blockId (long)
DataUtils.readVarLong(idBuffer); DataUtils.readVarLong(idBuffer);
long k2 = DataUtils.readVarLong(idBuffer); long k2 = DataUtils.readVarLong(idBuffer);
// recurse // recurse
...@@ -276,15 +282,18 @@ public class StreamStore { ...@@ -276,15 +282,18 @@ public class StreamStore {
while (idBuffer.hasRemaining()) { while (idBuffer.hasRemaining()) {
switch (idBuffer.get()) { switch (idBuffer.get()) {
case 0: case 0:
// in-place: 0, len (int), data
int len = DataUtils.readVarInt(idBuffer); int len = DataUtils.readVarInt(idBuffer);
idBuffer.position(idBuffer.position() + len); idBuffer.position(idBuffer.position() + len);
length += len; length += len;
break; break;
case 1: case 1:
// block: 1, len (int), blockId (long)
length += DataUtils.readVarInt(idBuffer); length += DataUtils.readVarInt(idBuffer);
DataUtils.readVarLong(idBuffer); DataUtils.readVarLong(idBuffer);
break; break;
case 2: case 2:
// indirect: 2, total len (long), blockId (long)
length += DataUtils.readVarLong(idBuffer); length += DataUtils.readVarLong(idBuffer);
DataUtils.readVarLong(idBuffer); DataUtils.readVarLong(idBuffer);
break; break;
......
...@@ -46,8 +46,7 @@ public class LobStorageMap implements LobStorageInterface { ...@@ -46,8 +46,7 @@ public class LobStorageMap implements LobStorageInterface {
* (which is a long) to the stream store id (which is a byte array). * (which is a long) to the stream store id (which is a byte array).
* *
* Key: lobId (long) * Key: lobId (long)
* Value: { streamStoreId (byte[]), tableId (int), * Value: { streamStoreId (byte[]), tableId (int), byteCount (long), hash (long) }.
* byteCount (long), hashCode (long) }.
*/ */
private MVMap<Long, Object[]> lobMap; private MVMap<Long, Object[]> lobMap;
......
...@@ -27,6 +27,7 @@ import org.h2.mvstore.type.StringDataType; ...@@ -27,6 +27,7 @@ import org.h2.mvstore.type.StringDataType;
import org.h2.store.fs.FilePath; import org.h2.store.fs.FilePath;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.test.utils.AssertThrows;
/** /**
* Tests the MVStore. * Tests the MVStore.
...@@ -55,6 +56,7 @@ public class TestMVStore extends TestBase { ...@@ -55,6 +56,7 @@ public class TestMVStore extends TestBase {
testCacheInfo(); testCacheInfo();
testRollback(); testRollback();
testVersionsToKeep(); testVersionsToKeep();
testVersionsToKeep2();
testRemoveMap(); testRemoveMap();
testIsEmpty(); testIsEmpty();
testOffHeapStorage(); testOffHeapStorage();
...@@ -184,9 +186,9 @@ public class TestMVStore extends TestBase { ...@@ -184,9 +186,9 @@ public class TestMVStore extends TestBase {
map.put(i, i); map.put(i, i);
s.commit(); s.commit();
if (version >= 6) { if (version >= 6) {
map.openVersion(version - 6); map.openVersion(version - 5);
try { try {
map.openVersion(version - 7); map.openVersion(version - 6);
fail(); fail();
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
// expected // expected
...@@ -194,6 +196,33 @@ public class TestMVStore extends TestBase { ...@@ -194,6 +196,33 @@ public class TestMVStore extends TestBase {
} }
} }
} }
private void testVersionsToKeep2() {
MVStore s = new MVStore.Builder().autoCommitDisabled().open();
s.setVersionsToKeep(2);
final MVMap<Integer, String> m = s.openMap("data");
s.commit();
assertEquals(1, s.getCurrentVersion());
m.put(1, "version 1");
s.commit();
assertEquals(2, s.getCurrentVersion());
m.put(1, "version 2");
s.commit();
assertEquals(3, s.getCurrentVersion());
m.put(1, "version 3");
s.commit();
m.put(1, "version 4");
assertEquals("version 4", m.openVersion(4).get(1));
assertEquals("version 3", m.openVersion(3).get(1));
assertEquals("version 2", m.openVersion(2).get(1));
new AssertThrows(IllegalArgumentException.class) {
@Override
public void test() throws Exception {
m.openVersion(1);
}
};
s.close();
}
private void testRemoveMap() throws Exception { private void testRemoveMap() throws Exception {
String fileName = getBaseDir() + "/testCloseMap.h3"; String fileName = getBaseDir() + "/testCloseMap.h3";
...@@ -1083,7 +1112,7 @@ public class TestMVStore extends TestBase { ...@@ -1083,7 +1112,7 @@ public class TestMVStore extends TestBase {
// System.out.println("size: " + FileUtils.size(fileName)); // System.out.println("size: " + FileUtils.size(fileName));
} }
} }
private void testOldVersion() { private void testOldVersion() {
MVStore s; MVStore s;
for (int op = 0; op <= 1; op++) { for (int op = 0; op <= 1; op++) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论