提交 56737a34 authored 作者: Thomas Mueller's avatar Thomas Mueller

When killing the process while the database was writing a checkpoint or while it…

When killing the process while the database was writing a checkpoint or while it was closing, the database could become corrupt. (improved tests)
上级 cd7f1007
......@@ -465,6 +465,8 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>Indexes of temporary tables are currently kept in-memory. Is this how it should be?
</li><li>The Shell tool should support the same built-in commands as the H2 Console.
</li><li>Maybe use PhantomReference instead of finalize.
</li><li>Database file name suffix: a way to use no or a different suffix (for example using a slash).
</li><li>Database file name suffix: should only have one dot by default. Example: .h2db
</li></ul>
<h2>Not Planned</h2>
......
......@@ -9,7 +9,6 @@ package org.h2.test;
import java.sql.SQLException;
import java.util.Properties;
import org.h2.Driver;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
import org.h2.store.fs.FileSystemDisk;
import org.h2.test.bench.TestPerformance;
......@@ -298,27 +297,12 @@ java org.h2.test.TestAll timer
test.printSystem();
System.setProperty("h2.maxMemoryRowsDistinct", "128");
System.setProperty("h2.check2", "true");
int testingRecovery;
System.setProperty("h2.delayWrongPasswordMin", "0");
System.setProperty("h2.check2", "false");
System.setProperty("h2.lobInDatabase", "true");
System.setProperty("h2.analyzeAuto", "100");
int testingRecovery2;
RecordingFileSystem.register();
// System.setProperty("h2.pageSize", "64");
/*
logFlush (& sync?) before writeBack
no commit in compact; logFlush - writeBack - switchLog
special file system with update log
test with small freeList pages, page size 64
comparative sql tests
power failure test
power failure test: MULTI_THREADED=TRUE
power failure test: larger binaries and additional index.
......@@ -344,7 +328,18 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
*/
if (args.length > 0) {
if ("crash".equals(args[0])) {
if ("reopen".equals(args[0])) {
System.setProperty("h2.delayWrongPasswordMin", "0");
System.setProperty("h2.check2", "false");
System.setProperty("h2.lobInDatabase", "true");
System.setProperty("h2.analyzeAuto", "100");
// System.setProperty("h2.pageSize", "64");
RecordingFileSystem.register();
test.record = true;
TestReopen reopen = new TestReopen();
RecordingFileSystem.setRecorder(reopen);
test.runTests();
} else if ("crash".equals(args[0])) {
test.endless = true;
new TestCrashAPI().runTest(test);
} else if ("synth".equals(args[0])) {
......@@ -419,16 +414,6 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
* Run the tests with a number of different settings.
*/
private void runTests() throws SQLException {
int test;
//this.record=true;
if(record) {
System.setProperty("h2.delayWrongPasswordMin", "0");
RecordingFileSystem.register();
TestReopen reopen = new TestReopen();
RecordingFileSystem.setRecorder(reopen);
}
jdk14 = true;
smallLog = big = networked = memory = ssl = false;
diskResult = traceSystemOut = diskUndo = false;
......@@ -673,7 +658,7 @@ if(record) {
}
}
private void afterTest() throws SQLException {
private void afterTest() {
FileSystemDisk.getInstance().deleteRecursive("trace.db", false);
if (networked && server != null) {
server.stop();
......
......@@ -205,14 +205,7 @@ public abstract class TestBase {
*/
protected String getBaseDir() {
if (config != null && config.record) {
int test;
// return "memFS:" + baseDir;
return RecordingFileSystem.PREFIX + "memFS:" + baseDir;
//return RecordingFileSystem.PREFIX + baseDir;
}
return baseDir;
}
......
......@@ -33,6 +33,10 @@ public class TestMemoryUsage extends TestBase {
}
public void test() throws SQLException {
if (getBaseDir().indexOf(':') >= 0) {
// can't test in-memory databases
return;
}
testCreateDropLoop();
testCreateIndex();
testClob();
......
......@@ -13,12 +13,14 @@ import org.h2.constant.ErrorCode;
import org.h2.engine.ConnectionInfo;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase;
import org.h2.test.utils.Recorder;
import org.h2.test.utils.RecordingFileSystem;
import org.h2.util.New;
import org.h2.util.Profiler;
/**
* A test that calls another test, and after each write operation to the
......@@ -28,10 +30,11 @@ public class TestReopen extends TestBase implements Recorder {
private String testDatabase = "memFS:" + TestBase.BASE_TEST_DIR + "/reopen";
private long lastCheck;
private int counter;
private int testEvery = 1 << 4;
private int writeCount = Integer.parseInt(System.getProperty("reopenOffset", "0"));
private int testEvery = 1 << Integer.parseInt(System.getProperty("reopenShift", "8"));
private int verifyCount;
private HashSet<String> knownErrors = New.hashSet();
private int max = 103128;
private volatile boolean testing;
/**
* Run just this test.
......@@ -48,41 +51,59 @@ public class TestReopen extends TestBase implements Recorder {
RecordingFileSystem.setRecorder(this);
config.record = true;
long time = System.currentTimeMillis();
// Profiler p = new Profiler();
// p.startCollecting();
long time = System.currentTimeMillis();
Profiler p = new Profiler();
p.startCollecting();
new TestPageStoreCoverage().init(config).test();
// System.out.println(p.getTop(3));
System.out.println(System.currentTimeMillis() - time);
System.out.println("counter: " + counter);
System.out.println(p.getTop(3));
System.out.println(System.currentTimeMillis() - time);
System.out.println("counter: " + writeCount);
}
public synchronized void log(int op, String fileName, byte[] data, long x) {
if (op != Recorder.WRITE) {
public void log(int op, String fileName, byte[] data, long x) {
if (op != Recorder.WRITE && op != Recorder.SET_LENGTH) {
return;
}
if (!fileName.endsWith(Constants.SUFFIX_PAGE_FILE)) {
return;
}
counter++;
if ((counter & 1023) == 0) {
if (testing) {
// avoid deadlocks
return;
}
testing = true;
try {
logDb(fileName);
} finally {
testing = false;
}
}
private synchronized void logDb(String fileName) {
writeCount++;
if ((writeCount & 1023) == 0) {
long now = System.currentTimeMillis();
if (now > lastCheck + 5000) {
System.out.println(" at " + counter + " of " + max + " " + (100. / max * counter));
//new Exception("currentPosition").printStackTrace(System.out);
System.out.println("+ write #" + writeCount + " verify #" + verifyCount);
lastCheck = now;
}
}
if ((counter & (testEvery - 1)) != 0) {
if ((writeCount & (testEvery - 1)) != 0) {
return;
}
FileSystem.getInstance(fileName).copy(fileName, testDatabase + Constants.SUFFIX_PAGE_FILE);
try {
verifyCount++;
// avoid using the Engine class to avoid deadlocks
Properties p = new Properties();
ConnectionInfo ci = new ConnectionInfo("jdbc:h2:" + testDatabase + ";FILE_LOCK=NO", p);
String userName = getUser();
p.setProperty("user", userName);
p.setProperty("password", getPassword());
ConnectionInfo ci = new ConnectionInfo("jdbc:h2:" + testDatabase + ";FILE_LOCK=NO;TRACE_LEVEL_FILE=0", p);
Database database = new Database(ci, null);
// close the database
Session session = database.getSystemSession();
session.prepare("shutdown immediately").update();
database.removeSession(null);
// everything OK - return
return;
......@@ -108,7 +129,7 @@ System.out.println(System.currentTimeMillis() - time);
}
e.printStackTrace(System.out);
}
System.out.println("begin ------------------------------ " + counter);
System.out.println("begin ------------------------------ " + writeCount);
testDatabase += "X";
FileSystem.getInstance(fileName).copy(fileName, testDatabase + Constants.SUFFIX_PAGE_FILE);
try {
......@@ -135,11 +156,11 @@ System.out.println(System.currentTimeMillis() - time);
}
String s = buff.toString();
if (!knownErrors.contains(s)) {
System.out.println(counter + " code: " + errorCode + " " + e.toString());
System.out.println(writeCount + " code: " + errorCode + " " + e.toString());
e.printStackTrace(System.out);
knownErrors.add(s);
} else {
System.out.println(counter + " code: " + errorCode);
System.out.println(writeCount + " code: " + errorCode);
}
}
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论