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

MVStore: compact (including MVTableEngine)

上级 1bb9cb16
...@@ -17,7 +17,6 @@ import java.util.Set; ...@@ -17,7 +17,6 @@ import java.util.Set;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import org.h2.api.DatabaseEventListener; import org.h2.api.DatabaseEventListener;
import org.h2.api.JavaObjectSerializer; import org.h2.api.JavaObjectSerializer;
import org.h2.command.CommandInterface;
import org.h2.command.ddl.CreateTableData; import org.h2.command.ddl.CreateTableData;
import org.h2.command.dml.SetTypes; import org.h2.command.dml.SetTypes;
import org.h2.constant.DbSettings; import org.h2.constant.DbSettings;
...@@ -1255,7 +1254,7 @@ public class Database implements DataHandler { ...@@ -1255,7 +1254,7 @@ public class Database implements DataHandler {
if (mvStore != null) { if (mvStore != null) {
if (!readOnly) { if (!readOnly) {
if (compactMode != 0) { if (compactMode != 0) {
mvStore.compact(compactMode == CommandInterface.SHUTDOWN_DEFRAG); mvStore.compact();
} }
} }
mvStore.close(); mvStore.close();
...@@ -1774,11 +1773,11 @@ public class Database implements DataHandler { ...@@ -1774,11 +1773,11 @@ public class Database implements DataHandler {
mvStore.setWriteDelay(value); mvStore.setWriteDelay(value);
} }
} }
public int getRetentionTime() { public int getRetentionTime() {
return retentionTime; return retentionTime;
} }
public void setRetentionTime(int value) { public void setRetentionTime(int value) {
retentionTime = value; retentionTime = value;
if (mvStore != null) { if (mvStore != null) {
...@@ -2093,18 +2092,17 @@ public class Database implements DataHandler { ...@@ -2093,18 +2092,17 @@ public class Database implements DataHandler {
} }
public QueryStatisticsData getQueryStatisticsData() { public QueryStatisticsData getQueryStatisticsData() {
if (queryStatistics) { if (!queryStatistics) {
if (queryStatisticsData == null) { return null;
synchronized (this) { }
if (queryStatisticsData == null) { if (queryStatisticsData == null) {
queryStatisticsData = new QueryStatisticsData(); synchronized (this) {
} if (queryStatisticsData == null) {
queryStatisticsData = new QueryStatisticsData();
} }
} }
return queryStatisticsData;
} else {
return null;
} }
return queryStatisticsData;
} }
/** /**
......
...@@ -144,7 +144,7 @@ public class FreeSpaceBitSet { ...@@ -144,7 +144,7 @@ public class FreeSpaceBitSet {
/** /**
* Get the fill rate of the space in percent. The value 0 means the space is * Get the fill rate of the space in percent. The value 0 means the space is
* completely free, and 100 means it is completely full. * completely free, and 100 means it is completely full.
* *
* @return the fill rate (0 - 100) * @return the fill rate (0 - 100)
*/ */
public int getFillRate() { public int getFillRate() {
...@@ -159,10 +159,10 @@ public class FreeSpaceBitSet { ...@@ -159,10 +159,10 @@ public class FreeSpaceBitSet {
} }
return Math.max(1, (int) (100L * count / total)); return Math.max(1, (int) (100L * count / total));
} }
/** /**
* Get the position of the first free space. * Get the position of the first free space.
* *
* @return the position. * @return the position.
*/ */
public long getFirstFree() { public long getFirstFree() {
......
...@@ -123,6 +123,10 @@ MVStore: ...@@ -123,6 +123,10 @@ MVStore:
- temporary file storage - temporary file storage
- simple rollback method (rollback to last committed version) - simple rollback method (rollback to last committed version)
- MVMap to implement SortedMap, then NavigableMap - MVMap to implement SortedMap, then NavigableMap
- add abstraction ChunkStore,
with free space handling, retention time / flush,
possibly one file per chunk to support SSD trim on file system level,
and free up memory for off-heap storage)
*/ */
...@@ -850,6 +854,9 @@ public class MVStore { ...@@ -850,6 +854,9 @@ public class MVStore {
* @return the new version (incremented if there were changes) * @return the new version (incremented if there were changes)
*/ */
public long store() { public long store() {
;
new Exception().printStackTrace(System.out);
checkOpen(); checkOpen();
return store(false); return store(false);
} }
...@@ -1036,11 +1043,11 @@ public class MVStore { ...@@ -1036,11 +1043,11 @@ public class MVStore {
} }
return version; return version;
} }
/** /**
* Get a buffer for writing. This caller must synchronize on the store * Get a buffer for writing. This caller must synchronize on the store
* before calling the method and until after using the buffer. * before calling the method and until after using the buffer.
* *
* @return the buffer * @return the buffer
*/ */
private ByteBuffer getWriteBuffer() { private ByteBuffer getWriteBuffer() {
...@@ -1057,7 +1064,7 @@ public class MVStore { ...@@ -1057,7 +1064,7 @@ public class MVStore {
/** /**
* Release a buffer for writing. This caller must synchronize on the store * Release a buffer for writing. This caller must synchronize on the store
* before calling the method and until after using the buffer. * before calling the method and until after using the buffer.
* *
* @param buff the buffer than can be re-used * @param buff the buffer than can be re-used
*/ */
private void releaseWriteBuffer(ByteBuffer buff) { private void releaseWriteBuffer(ByteBuffer buff) {
...@@ -1101,6 +1108,10 @@ public class MVStore { ...@@ -1101,6 +1108,10 @@ public class MVStore {
Map<Integer, Chunk> freed = freedPages.get(v); Map<Integer, Chunk> freed = freedPages.get(v);
for (Chunk f : freed.values()) { for (Chunk f : freed.values()) {
Chunk c = chunks.get(f.id); Chunk c = chunks.get(f.id);
if (c == null) {
// already removed
continue;
}
c.maxLengthLive += f.maxLengthLive; c.maxLengthLive += f.maxLengthLive;
c.pageCountLive += f.pageCountLive; c.pageCountLive += f.pageCountLive;
if (c.pageCountLive < 0) { if (c.pageCountLive < 0) {
...@@ -1213,10 +1224,12 @@ public class MVStore { ...@@ -1213,10 +1224,12 @@ public class MVStore {
buff.rewind(); buff.rewind();
return Chunk.fromHeader(buff, start); return Chunk.fromHeader(buff, start);
} }
/** /**
* Compact the store by moving all chunks next to each other, if there is * Compact the store by moving all chunks next to each other, if there is
* free space between chunks. This might temporarily double the file size. * free space between chunks. This might temporarily double the file size.
* Chunks are overwritten irrespective of the current retention time. Before
* overwriting chunks and before resizing the file, syncFile() is called.
* *
* @return if anything was written * @return if anything was written
*/ */
...@@ -1226,6 +1239,23 @@ public class MVStore { ...@@ -1226,6 +1239,23 @@ public class MVStore {
// nothing to do // nothing to do
return false; return false;
} }
int oldRetentionTime = retentionTime;
retentionTime = 0;
long time = getTime();
ArrayList<Chunk> free = New.arrayList();
for (Chunk c : chunks.values()) {
if (c.maxLengthLive == 0) {
if (canOverwriteChunk(c, time)) {
free.add(c);
}
}
}
for (Chunk c : free) {
chunks.remove(c.id);
meta.remove("chunk." + c.id);
int length = MathUtils.roundUpInt(c.length, BLOCK_SIZE) + BLOCK_SIZE;
freeSpace.free(c.start, length);
}
if (freeSpace.getFillRate() == 100) { if (freeSpace.getFillRate() == 100) {
return false; return false;
} }
...@@ -1266,12 +1296,15 @@ public class MVStore { ...@@ -1266,12 +1296,15 @@ public class MVStore {
reuseSpace = false; reuseSpace = false;
store(); store();
syncFile();
// now re-use the empty space // now re-use the empty space
reuseSpace = true; reuseSpace = true;
for (Chunk c : move) { for (Chunk c : move) {
ByteBuffer buff = getWriteBuffer(); ByteBuffer buff = getWriteBuffer();
int length = MathUtils.roundUpInt(c.length, BLOCK_SIZE) + BLOCK_SIZE; int length = MathUtils.roundUpInt(c.length, BLOCK_SIZE) + BLOCK_SIZE;
buff = DataUtils.ensureCapacity(buff, length); buff = DataUtils.ensureCapacity(buff, length);
buff.limit(length);
DataUtils.readFully(file, c.start, buff); DataUtils.readFully(file, c.start, buff);
long pos = freeSpace.allocate(length); long pos = freeSpace.allocate(length);
freeSpace.free(c.start, length); freeSpace.free(c.start, length);
...@@ -1283,7 +1316,6 @@ public class MVStore { ...@@ -1283,7 +1316,6 @@ public class MVStore {
buff.put(header); buff.put(header);
// fill the header with zeroes // fill the header with zeroes
buff.put(new byte[BLOCK_SIZE - header.length]); buff.put(new byte[BLOCK_SIZE - header.length]);
buff.limit(length);
buff.position(0); buff.position(0);
fileWriteCount++; fileWriteCount++;
DataUtils.writeFully(file, pos, buff); DataUtils.writeFully(file, pos, buff);
...@@ -1291,12 +1323,31 @@ public class MVStore { ...@@ -1291,12 +1323,31 @@ public class MVStore {
releaseWriteBuffer(buff); releaseWriteBuffer(buff);
meta.put("chunk." + c.id, c.asString()); meta.put("chunk." + c.id, c.asString());
} }
// update the metadata (within the file) // update the metadata (within the file)
store(); store();
syncFile();
shrinkFileIfPossible(0);
reuseSpace = oldReuse; reuseSpace = oldReuse;
retentionTime = oldRetentionTime;
return true; return true;
} }
/**
* Force all changes to be written to the file. The default implementation
* calls FileChannel.force(true).
*/
public void syncFile() {
try {
file.force(true);
} catch (IOException e) {
throw DataUtils.newIllegalStateException(
DataUtils.ERROR_WRITING_FAILED,
"Could not sync file {0}", fileName, e);
}
}
/** /**
* Try to reduce the file size by re-writing partially full chunks. Chunks * Try to reduce the file size by re-writing partially full chunks. Chunks
...@@ -1306,7 +1357,7 @@ public class MVStore { ...@@ -1306,7 +1357,7 @@ public class MVStore {
* Only data of open maps can be moved. For maps that are not open, the old * Only data of open maps can be moved. For maps that are not open, the old
* chunk is still referenced. Therefore, it is recommended to open all maps * chunk is still referenced. Therefore, it is recommended to open all maps
* before calling this method. * before calling this method.
* *
* @param fillRate the minimum percentage of live entries * @param fillRate the minimum percentage of live entries
* @return if anything was written * @return if anything was written
*/ */
...@@ -1327,7 +1378,7 @@ public class MVStore { ...@@ -1327,7 +1378,7 @@ public class MVStore {
} }
// the fill rate of all chunks combined // the fill rate of all chunks combined
int totalChunkFillRate = (int) (100 * maxLengthLiveSum / maxLengthSum); int totalChunkFillRate = (int) (100 * maxLengthLiveSum / maxLengthSum);
if (totalChunkFillRate > fillRate) { if (totalChunkFillRate > fillRate) {
return false; return false;
} }
......
...@@ -13,7 +13,6 @@ import java.util.ArrayList; ...@@ -13,7 +13,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.h2.api.TableEngine; import org.h2.api.TableEngine;
import org.h2.command.CommandInterface;
import org.h2.command.ddl.CreateTableData; import org.h2.command.ddl.CreateTableData;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.engine.Constants; import org.h2.engine.Constants;
...@@ -169,11 +168,13 @@ public class MVTableEngine implements TableEngine { ...@@ -169,11 +168,13 @@ public class MVTableEngine implements TableEngine {
* Store all pending changes. * Store all pending changes.
*/ */
public void store() { public void store() {
if (!store.isReadOnly()) { if (store.isReadOnly()) {
store.commit(); return;
store.compact(50);
store.store();
} }
int todo;
store.commit();
store.compact(50);
store.store();
} }
/** /**
...@@ -248,7 +249,7 @@ public class MVTableEngine implements TableEngine { ...@@ -248,7 +249,7 @@ public class MVTableEngine implements TableEngine {
public InputStream getInputStream() { public InputStream getInputStream() {
return new FileChannelInputStream(store.getFile(), false); return new FileChannelInputStream(store.getFile(), false);
} }
/** /**
* Force the changes to disk. * Force the changes to disk.
*/ */
...@@ -261,14 +262,11 @@ public class MVTableEngine implements TableEngine { ...@@ -261,14 +262,11 @@ public class MVTableEngine implements TableEngine {
} }
} }
public void compact(boolean defrag) { public void compact() {
sync();
store.setRetentionTime(0);
while (store.compact(90)) { while (store.compact(90)) {
System.out.println("compact"); // repeat
sync();
} }
System.out.println("compact done"); store.compactMoveChunks();
} }
} }
......
...@@ -248,6 +248,11 @@ java org.h2.test.TestAll timer ...@@ -248,6 +248,11 @@ java org.h2.test.TestAll timer
* Whether to use the MVStore. * Whether to use the MVStore.
*/ */
public boolean mvStore; public boolean mvStore;
/**
* Whether the test is running with code coverage.
*/
public boolean coverage;
/** /**
* If code coverage is enabled. * If code coverage is enabled.
...@@ -505,6 +510,8 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -505,6 +510,8 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
* Run the tests with a number of different settings. * Run the tests with a number of different settings.
*/ */
private void runTests() throws SQLException { private void runTests() throws SQLException {
coverage = isCoverage();
{} {}
mvStore = false; mvStore = false;
...@@ -569,6 +576,20 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -569,6 +576,20 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
memory = true; memory = true;
test(); test();
} }
/**
* Check whether this method is running with "Emma" code coverage turned on.
*
* @return true if the stack trace contains ".emma."
*/
private static boolean isCoverage() {
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
if (e.toString().indexOf(".emma.") >= 0) {
return true;
}
}
return false;
}
/** /**
* Run all tests with the current settings. * Run all tests with the current settings.
......
...@@ -47,7 +47,7 @@ public class TestMVStore extends TestBase { ...@@ -47,7 +47,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());
testCompactFully();
testBackgroundExceptionListener(); testBackgroundExceptionListener();
testOldVersion(); testOldVersion();
testAtomicOperations(); testAtomicOperations();
...@@ -92,6 +92,30 @@ public class TestMVStore extends TestBase { ...@@ -92,6 +92,30 @@ public class TestMVStore extends TestBase {
testLargerThan2G(); testLargerThan2G();
} }
private void testCompactFully() throws Exception {
String fileName = getBaseDir() + "/testCompactFully.h3";
FileUtils.delete(fileName);
MVStore s = new MVStore.Builder().
fileName(fileName).
open();
MVMap<Integer, String> m;
for (int i = 0; i < 10; i++) {
m = s.openMap("data" + i);
m.put(0, "Hello World");
s.store();
}
for (int i = 0; i < 10; i += 2) {
m = s.openMap("data" + i);
m.removeMap();
s.store();
}
long sizeOld = s.getFile().size();
s.compactMoveChunks();
long sizeNew = s.getFile().size();
assertTrue("old: " + sizeOld + " new: " + sizeNew, sizeNew < sizeOld);
s.close();
}
private void testBackgroundExceptionListener() throws Exception { private void testBackgroundExceptionListener() throws Exception {
String fileName = getBaseDir() + "/testBackgroundExceptionListener.h3"; String fileName = getBaseDir() + "/testBackgroundExceptionListener.h3";
FileUtils.delete(fileName); FileUtils.delete(fileName);
...@@ -1221,7 +1245,7 @@ public class TestMVStore extends TestBase { ...@@ -1221,7 +1245,7 @@ public class TestMVStore extends TestBase {
} }
s.close(); s.close();
} }
private void testCompactMapNotOpen() { private void testCompactMapNotOpen() {
String fileName = getBaseDir() + "/testCompactNotOpen.h3"; String fileName = getBaseDir() + "/testCompactNotOpen.h3";
FileUtils.delete(fileName); FileUtils.delete(fileName);
...@@ -1235,10 +1259,10 @@ public class TestMVStore extends TestBase { ...@@ -1235,10 +1259,10 @@ public class TestMVStore extends TestBase {
s.store(); s.store();
} }
s.close(); s.close();
s = openStore(fileName); s = openStore(fileName);
s.setRetentionTime(0); s.setRetentionTime(0);
Map<String, String> meta = s.getMetaMap(); Map<String, String> meta = s.getMetaMap();
int chunkCount1 = 0; int chunkCount1 = 0;
for (String k : meta.keySet()) { for (String k : meta.keySet()) {
......
...@@ -39,17 +39,24 @@ public class TestMVStoreBenchmark extends TestBase { ...@@ -39,17 +39,24 @@ public class TestMVStoreBenchmark extends TestBase {
if (!config.big) { if (!config.big) {
return; return;
} }
if (config.coverage || config.codeCoverage) {
// run only when _not_ using a code coverage tool,
// because the tool might instrument our code but not
// java.util.*
return;
}
testPerformanceComparison(); testPerformanceComparison();
testMemoryUsageComparison(); testMemoryUsageComparison();
} }
private void testMemoryUsageComparison() { private void testMemoryUsageComparison() {
long[] mem; long[] mem;
long hash, tree, mv; long hash, tree, mv;
String msg; String msg;
mem = getMemoryUsed(10000, 10); mem = getMemoryUsed(10000, 10);
hash = mem[0]; hash = mem[0];
tree = mem[1]; tree = mem[1];
mv = mem[2]; mv = mem[2];
msg = Arrays.toString(mem); msg = Arrays.toString(mem);
...@@ -65,12 +72,12 @@ public class TestMVStoreBenchmark extends TestBase { ...@@ -65,12 +72,12 @@ public class TestMVStoreBenchmark extends TestBase {
assertTrue(msg, mv < tree); assertTrue(msg, mv < tree);
} }
private static long[] getMemoryUsed(int count, int size) { private static long[] getMemoryUsed(int count, int size) {
long hash, tree, mv; long hash, tree, mv;
ArrayList<Map<Integer, String>> mapList; ArrayList<Map<Integer, String>> mapList;
long mem; long mem;
mapList = New.arrayList(); mapList = New.arrayList();
mem = getMemory(); mem = getMemory();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
...@@ -79,7 +86,7 @@ public class TestMVStoreBenchmark extends TestBase { ...@@ -79,7 +86,7 @@ public class TestMVStoreBenchmark extends TestBase {
addEntries(mapList, size); addEntries(mapList, size);
hash = getMemory() - mem; hash = getMemory() - mem;
mapList.size(); mapList.size();
mapList = New.arrayList(); mapList = New.arrayList();
mem = getMemory(); mem = getMemory();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
...@@ -91,7 +98,7 @@ public class TestMVStoreBenchmark extends TestBase { ...@@ -91,7 +98,7 @@ public class TestMVStoreBenchmark extends TestBase {
mapList = New.arrayList(); mapList = New.arrayList();
mem = getMemory(); mem = getMemory();
MVStore store = MVStore.open(null); MVStore store = MVStore.open(null);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
Map<Integer, String> map = store.openMap("t" + i); Map<Integer, String> map = store.openMap("t" + i);
mapList.add(map); mapList.add(map);
...@@ -99,10 +106,10 @@ public class TestMVStoreBenchmark extends TestBase { ...@@ -99,10 +106,10 @@ public class TestMVStoreBenchmark extends TestBase {
addEntries(mapList, size); addEntries(mapList, size);
mv = getMemory() - mem; mv = getMemory() - mem;
mapList.size(); mapList.size();
return new long[]{hash, tree, mv}; return new long[]{hash, tree, mv};
} }
private static void addEntries(List<Map<Integer, String>> mapList, int size) { private static void addEntries(List<Map<Integer, String>> mapList, int size) {
for (Map<Integer, String> map : mapList) { for (Map<Integer, String> map : mapList) {
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
...@@ -110,7 +117,7 @@ public class TestMVStoreBenchmark extends TestBase { ...@@ -110,7 +117,7 @@ public class TestMVStoreBenchmark extends TestBase {
} }
} }
} }
static long getMemory() { static long getMemory() {
try { try {
LinkedList<byte[]> list = new LinkedList<byte[]>(); LinkedList<byte[]> list = new LinkedList<byte[]>();
...@@ -130,7 +137,7 @@ public class TestMVStoreBenchmark extends TestBase { ...@@ -130,7 +137,7 @@ public class TestMVStoreBenchmark extends TestBase {
} }
return getMemoryUsedBytes(); return getMemoryUsedBytes();
} }
private void testPerformanceComparison() { private void testPerformanceComparison() {
if (!config.big) { if (!config.big) {
return; return;
...@@ -144,14 +151,12 @@ public class TestMVStoreBenchmark extends TestBase { ...@@ -144,14 +151,12 @@ public class TestMVStoreBenchmark extends TestBase {
MVStore store = MVStore.open(null); MVStore store = MVStore.open(null);
map = store.openMap("test"); map = store.openMap("test");
long mv = testPerformance(map, size); long mv = testPerformance(map, size);
String msg = "mv " + mv + " tree " + tree + " hash " + hash; String msg = "mv " + mv + " tree " + tree + " hash " + hash;
assertTrue(msg, hash < tree); assertTrue(msg, hash < tree);
assertTrue(msg, hash < mv); assertTrue(msg, hash < mv);
int todo; assertTrue(msg, mv < tree);
// check only when _not_ using a code coverage tool
// assertTrue(msg, mv < tree);
} }
private long testPerformance(Map<Integer, String> map, int size) { private long testPerformance(Map<Integer, String> map, int size) {
System.gc(); System.gc();
long time = 0; long time = 0;
......
...@@ -8,7 +8,6 @@ package org.h2.test.store; ...@@ -8,7 +8,6 @@ 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;
...@@ -22,7 +21,8 @@ import org.h2.constant.ErrorCode; ...@@ -22,7 +21,8 @@ import org.h2.constant.ErrorCode;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.jdbc.JdbcConnection; import org.h2.jdbc.JdbcConnection;
import org.h2.mvstore.MVStoreTool; import org.h2.mvstore.MVStore;
import org.h2.mvstore.db.TransactionStore;
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.tools.DeleteDbFiles; import org.h2.tools.DeleteDbFiles;
...@@ -47,8 +47,9 @@ public class TestMVTableEngine extends TestBase { ...@@ -47,8 +47,9 @@ public class TestMVTableEngine extends TestBase {
@Override @Override
public void test() throws Exception { public void test() throws Exception {
;;
// testTransactionLogUsuallyNotStored();
testShrinkDatabaseFile(); testShrinkDatabaseFile();
testTransactionLogUsuallyNotStored();
testTwoPhaseCommit(); testTwoPhaseCommit();
testRecover(); testRecover();
testSeparateKey(); testSeparateKey();
...@@ -67,6 +68,35 @@ public class TestMVTableEngine extends TestBase { ...@@ -67,6 +68,35 @@ public class TestMVTableEngine extends TestBase {
testLocking(); testLocking();
testSimple(); testSimple();
} }
private void testTransactionLogUsuallyNotStored() throws Exception {
int todo;
FileUtils.deleteRecursive(getBaseDir(), true);
Connection conn;
Statement stat;
String url = "mvstore;MV_STORE=TRUE";
url = getURL(url, true);
conn = getConnection(url);
stat = conn.createStatement();
stat.execute("create table test(id identity, name varchar)");
conn.setAutoCommit(false);
for (int j = 0; j < 100; j++) {
for (int i = 0; i < 100; i++) {
stat.execute("insert into test(name) values('Hello World')");
}
conn.commit();
}
stat.execute("shutdown immediately");
JdbcUtils.closeSilently(conn);
String file = getBaseDir() + "/mvstore" + Constants.SUFFIX_MV_FILE;
MVStore store = MVStore.open(file);
TransactionStore t = new TransactionStore(store);
assertEquals(0, t.getOpenTransactions().size());
store.close();
}
private void testShrinkDatabaseFile() throws Exception { private void testShrinkDatabaseFile() throws Exception {
FileUtils.deleteRecursive(getBaseDir(), true); FileUtils.deleteRecursive(getBaseDir(), true);
...@@ -88,7 +118,7 @@ public class TestMVTableEngine extends TestBase { ...@@ -88,7 +118,7 @@ public class TestMVTableEngine extends TestBase {
retentionTime = 0; retentionTime = 0;
} }
ResultSet rs = stat.executeQuery( ResultSet rs = stat.executeQuery(
"select value from information_schema.settings " + "select value from information_schema.settings " +
"where name='RETENTION_TIME'"); "where name='RETENTION_TIME'");
assertTrue(rs.next()); assertTrue(rs.next());
assertEquals(retentionTime, rs.getInt(1)); assertEquals(retentionTime, rs.getInt(1));
...@@ -104,21 +134,15 @@ public class TestMVTableEngine extends TestBase { ...@@ -104,21 +134,15 @@ public class TestMVTableEngine extends TestBase {
fail(i + " size: " + size + " max: " + maxSize); fail(i + " size: " + size + " max: " + maxSize);
} }
} }
int todo; long sizeOld = FileUtils.size(getBaseDir() + "/mvstore"
// conn = getConnection(dbName); + Constants.SUFFIX_MV_FILE);
// stat = conn.createStatement(); conn = getConnection(dbName);
// stat.execute("shutdown compact"); stat = conn.createStatement();
// conn.close(); stat.execute("shutdown compact");
// conn.close();
// MVStoreTool.dump(getBaseDir() + "/mvstore.mv.db", new PrintWriter(System.out)); long sizeNew = FileUtils.size(getBaseDir() + "/mvstore"
// + Constants.SUFFIX_MV_FILE);
// long size = FileUtils.size(getBaseDir() + "/mvstore" assertTrue(sizeNew < sizeOld);
// + Constants.SUFFIX_MV_FILE);
// assertTrue(size < 16 * 1024);
}
private void testTransactionLogUsuallyNotStored() {
int todo;
} }
private void testTwoPhaseCommit() throws Exception { private void testTwoPhaseCommit() throws Exception {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论