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

Fix bookkeeping of live pages

上级 c9f55a5b
...@@ -154,6 +154,11 @@ public class Chunk { ...@@ -154,6 +154,11 @@ public class Chunk {
while (buff.position() - pos < minLength - 1) { while (buff.position() - pos < minLength - 1) {
buff.put((byte) ' '); buff.put((byte) ' ');
} }
if (minLength != 0 && buff.position() > minLength) {
throw DataUtils.newIllegalStateException(
DataUtils.ERROR_INTERNAL,
"Chunk metadata too long");
}
buff.put((byte) '\n'); buff.put((byte) '\n');
} }
......
...@@ -1844,7 +1844,8 @@ public class MVStore { ...@@ -1844,7 +1844,8 @@ public class MVStore {
version = currentStoreVersion; version = currentStoreVersion;
} }
} }
registerFreePage(version, c.id, DataUtils.getPageMaxLength(pos), 1); registerFreePage(version, c.id,
DataUtils.getPageMaxLength(pos), 1);
} }
private void registerFreePage(long version, int chunkId, private void registerFreePage(long version, int chunkId,
......
...@@ -918,12 +918,14 @@ public class Page { ...@@ -918,12 +918,14 @@ public class Page {
store.cachePage(pos, this, getMemory()); store.cachePage(pos, this, getMemory());
long max = DataUtils.getPageMaxLength(pos); long max = DataUtils.getPageMaxLength(pos);
chunk.maxLen += max; chunk.maxLen += max;
chunk.pageCount++;
if (!removedInMemory) {
// if the page was removed _before_ the position was assigned, we
// must not increase the live fields.
chunk.maxLenLive += max; chunk.maxLenLive += max;
chunk.pageCount++;
chunk.pageCountLive++; chunk.pageCountLive++;
if (removedInMemory) {
// if the page was removed _before_ the position was assigned, we
// need to mark it removed here, so the fields are updated
// when the next chunk is stored
map.removePage(pos, memory);
} }
return typePos + 1; return typePos + 1;
} }
......
...@@ -342,14 +342,18 @@ public class MVTableEngine implements TableEngine { ...@@ -342,14 +342,18 @@ public class MVTableEngine implements TableEngine {
} }
String fileName = store.getFileStore().getFileName(); String fileName = store.getFileStore().getFileName();
store.close(); store.close();
if (compactFully) { if (compactFully && FileUtils.exists(fileName)) {
// the file could have been deleted concurrently,
// so only compact if the file still exists
MVStoreTool.compact(fileName, true); MVStoreTool.compact(fileName, true);
} }
} }
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
if (DataUtils.getErrorCode(e.getMessage()) == int errorCode = DataUtils.getErrorCode(e.getMessage());
DataUtils.ERROR_WRITING_FAILED) { if (errorCode == DataUtils.ERROR_WRITING_FAILED) {
// disk full - ok // disk full - ok
} else if (errorCode == DataUtils.ERROR_FILE_CORRUPT) {
// wrong encryption key - ok
} else { } else {
// TODO // TODO
; ;
......
...@@ -85,9 +85,8 @@ public class TestBackup extends TestBase { ...@@ -85,9 +85,8 @@ public class TestBackup extends TestBase {
updateEnd.set(System.currentTimeMillis() + 2000); updateEnd.set(System.currentTimeMillis() + 2000);
stat2.execute("backup to '"+getBaseDir()+"/backup.zip'"); stat2.execute("backup to '"+getBaseDir()+"/backup.zip'");
stat2.execute("checkpoint"); stat2.execute("checkpoint");
Restore.execute(getBaseDir() + "/backup.zip", getBaseDir() + "/t2", "backup"); Restore.execute(getBaseDir() + "/backup.zip", getBaseDir() + "/t" + i, "backup");
Connection conn3; Connection conn3 = getConnection("t" + i + "/backup");
conn3 = getConnection("t2/backup");
Statement stat3 = conn3.createStatement(); Statement stat3 = conn3.createStatement();
stat3.execute("script"); stat3.execute("script");
ResultSet rs = stat3.executeQuery( ResultSet rs = stat3.executeQuery(
...@@ -98,9 +97,9 @@ public class TestBackup extends TestBase { ...@@ -98,9 +97,9 @@ public class TestBackup extends TestBase {
conn3.close(); conn3.close();
} }
task.get(); task.get();
conn2.close();
conn.close(); conn.close();
conn1.close(); conn1.close();
conn2.close();
} }
/** /**
......
...@@ -52,6 +52,7 @@ public class TestMVStore extends TestBase { ...@@ -52,6 +52,7 @@ public class TestMVStore extends TestBase {
public void test() throws Exception { public void test() throws Exception {
FileUtils.deleteRecursive(getBaseDir(), true); FileUtils.deleteRecursive(getBaseDir(), true);
FileUtils.createDirectories(getBaseDir()); FileUtils.createDirectories(getBaseDir());
testRemoveMapRollback();
testProvidedFileStoreNotOpenedAndClosed(); testProvidedFileStoreNotOpenedAndClosed();
testVolatileMap(); testVolatileMap();
testEntrySet(); testEntrySet();
...@@ -112,6 +113,37 @@ public class TestMVStore extends TestBase { ...@@ -112,6 +113,37 @@ public class TestMVStore extends TestBase {
testLargerThan2G(); testLargerThan2G();
} }
private void testRemoveMapRollback() {
MVStore store = new MVStore.Builder().
open();
MVMap<String, String> map = store.openMap("test");
map.put("1", "Hello");
store.commit();
store.removeMap(map);
store.rollback();
assertTrue(store.hasMap("test"));
map = store.openMap("test");
// TODO the data should get back alive
assertNull(map.get("1"));
store.close();
String fileName = getBaseDir() + "/testRemoveMapRollback.h3";
store = new MVStore.Builder().
autoCommitDisabled().
fileName(fileName).
open();
map = store.openMap("test");
map.put("1", "Hello");
store.commit();
store.removeMap(map);
store.rollback();
assertTrue(store.hasMap("test"));
map = store.openMap("test");
// TODO the data should get back alive
assertNull(map.get("1"));
store.close();
}
private void testProvidedFileStoreNotOpenedAndClosed() { private void testProvidedFileStoreNotOpenedAndClosed() {
final AtomicInteger openClose = new AtomicInteger(); final AtomicInteger openClose = new AtomicInteger();
FileStore fileStore = new OffHeapStore() { FileStore fileStore = new OffHeapStore() {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论