提交 0be646df authored 作者: Thomas Mueller's avatar Thomas Mueller

New simulated power-off test

上级 ff8b9bc7
/*
* Copyright 2004-2009 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.constant.ErrorCode;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase;
import org.h2.test.utils.FileSystemDebug;
/**
* Tests that use the debug file system to simulate power failure.
*/
public class TestPowerOffFs extends TestBase {
private FileSystemDebug fs;
/**
* Run just this test.
*
* @param a ignored
*/
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
public void test() throws Exception {
int todo;
FileSystemDebug.register();
fs = (FileSystemDebug) FileSystem.getInstance("debug:/");
test(Integer.MAX_VALUE);
System.out.println(Integer.MAX_VALUE - fs.getPowerOffCount());
System.out.println("done");
for (int i = 0;; i++) {
boolean end = test(i);
if (end) {
break;
}
}
}
private boolean test(int x) throws SQLException {
deleteDb("memFS:", null);
fs.setPowerOffCount(x);
String url = "jdbc:h2:debug:memFS:powerOffFs;FILE_LOCK=NO;TRACE_LEVEL_FILE=0;WRITE_DELAY=0;CACHE_SIZE=4096";
url += ";page_store=true";
Connection conn = null;
Statement stat = null;
if (x == 16) {
System.out.println("x");
}
try {
conn = DriverManager.getConnection(url);
stat = conn.createStatement();
stat.execute("create table test(id int primary key, name varchar)");
stat.execute("insert into test values(1, 'Hello')");
stat.execute("create index idx_name on test(name)");
stat.execute("insert into test values(2, 'World')");
stat.execute("update test set name='Hallo' where id=1");
stat.execute("delete from test where name=2");
stat.execute("insert into test values(3, space(10000))");
stat.execute("update test set name='Hallo' where id=3");
stat.execute("drop table test");
conn.close();
conn = null;
return fs.getPowerOffCount() > 0;
} catch (SQLException e) {
if (e.getErrorCode() == ErrorCode.TABLE_OR_VIEW_ALREADY_EXISTS_1) {
throw e;
}
// ignore
} finally {
if (conn != null) {
try {
if (stat != null) {
stat.execute("shutdown immediately");
}
} catch (Exception e2) {
// ignore
}
try {
conn.close();
} catch (Exception e2) {
// ignore
}
}
}
fs.setPowerOffCount(0);
conn = DriverManager.getConnection(url);
stat = conn.createStatement();
stat.execute("script to 'memFS:test.sql'");
conn.close();
return false;
}
}
......@@ -55,6 +55,7 @@ public class FileObjectDebug implements FileObject {
}
public void setFileLength(long newLength) throws IOException {
checkPowerOff();
debug("setFileLength", newLength);
file.setFileLength(newLength);
}
......@@ -65,12 +66,25 @@ public class FileObjectDebug implements FileObject {
}
public void write(byte[] b, int off, int len) throws IOException {
checkPowerOff();
debug("write", off, len);
file.write(b, off, len);
}
private void debug(String method, Object... params) {
fs.debug(method, name, params);
fs.trace(method, name, params);
}
private void checkPowerOff() throws IOException {
try {
fs.checkPowerOff();
} catch (IOException e) {
try {
file.close();
} catch (IOException e2) {
// ignore
}
throw e;
}
}
}
......@@ -26,6 +26,11 @@ public class FileSystemDebug extends FileSystem {
private static final FileSystemDebug INSTANCE = new FileSystemDebug();
private static final IOException POWER_OFF = new IOException("Simulated power failure");
private int powerOffCount;
private boolean trace;
/**
* Register the file system.
*/
......@@ -33,114 +38,133 @@ public class FileSystemDebug extends FileSystem {
FileSystem.register(INSTANCE);
}
/**
* Check if the simulated power failure occurred.
* This call will decrement the countdown.
*
* @throws IOException if the simulated power failure occurred
*/
void checkPowerOff() throws IOException {
if (powerOffCount == 0) {
return;
}
if (powerOffCount > 1) {
powerOffCount--;
return;
}
powerOffCount = -1;
// throw new IOException("Simulated power failure");
throw POWER_OFF;
}
public boolean canWrite(String fileName) {
fileName = translateFileName(fileName);
debug("canWrite", fileName);
trace("canWrite", fileName);
return FileSystem.getInstance(fileName).canWrite(fileName);
}
public void copy(String original, String copy) throws SQLException {
original = translateFileName(original);
copy = translateFileName(copy);
debug("copy", original, copy);
trace("copy", original, copy);
FileSystem.getInstance(original).copy(original, copy);
}
public void createDirs(String fileName) throws SQLException {
fileName = translateFileName(fileName);
debug("createDirs", fileName);
trace("createDirs", fileName);
FileSystem.getInstance(fileName).createDirs(fileName);
}
public boolean createNewFile(String fileName) throws SQLException {
fileName = translateFileName(fileName);
debug("createNewFile", fileName);
trace("createNewFile", fileName);
return FileSystem.getInstance(fileName).createNewFile(fileName);
}
public String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir)
throws IOException {
prefix = translateFileName(prefix);
debug("createTempFile", prefix, suffix, deleteOnExit, inTempDir);
trace("createTempFile", prefix, suffix, deleteOnExit, inTempDir);
return PREFIX + FileSystem.getInstance(prefix).createTempFile(prefix, suffix, deleteOnExit, inTempDir);
}
public void delete(String fileName) throws SQLException {
fileName = translateFileName(fileName);
debug("fileName", fileName);
trace("fileName", fileName);
FileSystem.getInstance(fileName).delete(fileName);
}
public void deleteRecursive(String directory, boolean tryOnly) throws SQLException {
directory = translateFileName(directory);
debug("deleteRecursive", directory);
trace("deleteRecursive", directory);
FileSystem.getInstance(directory).deleteRecursive(directory, tryOnly);
}
public boolean exists(String fileName) {
fileName = translateFileName(fileName);
debug("exists", fileName);
trace("exists", fileName);
return FileSystem.getInstance(fileName).exists(fileName);
}
public boolean fileStartsWith(String fileName, String prefix) {
fileName = translateFileName(fileName);
prefix = translateFileName(prefix);
debug("fileStartsWith", fileName, prefix);
trace("fileStartsWith", fileName, prefix);
return FileSystem.getInstance(fileName).fileStartsWith(fileName, prefix);
}
public String getAbsolutePath(String fileName) {
fileName = translateFileName(fileName);
debug("getAbsolutePath", fileName);
trace("getAbsolutePath", fileName);
return PREFIX + FileSystem.getInstance(fileName).getAbsolutePath(fileName);
}
public String getFileName(String name) throws SQLException {
name = translateFileName(name);
debug("getFileName", name);
trace("getFileName", name);
return FileSystem.getInstance(name).getFileName(name);
}
public long getLastModified(String fileName) {
fileName = translateFileName(fileName);
debug("getLastModified", fileName);
trace("getLastModified", fileName);
return FileSystem.getInstance(fileName).getLastModified(fileName);
}
public String getParent(String fileName) {
fileName = translateFileName(fileName);
debug("getParent", fileName);
trace("getParent", fileName);
return PREFIX + FileSystem.getInstance(fileName).getParent(fileName);
}
public boolean isAbsolute(String fileName) {
fileName = translateFileName(fileName);
debug("isAbsolute", fileName);
trace("isAbsolute", fileName);
return FileSystem.getInstance(fileName).isAbsolute(fileName);
}
public boolean isDirectory(String fileName) {
fileName = translateFileName(fileName);
debug("isDirectory", fileName);
trace("isDirectory", fileName);
return FileSystem.getInstance(fileName).isDirectory(fileName);
}
public boolean isReadOnly(String fileName) {
fileName = translateFileName(fileName);
debug("isReadOnly", fileName);
trace("isReadOnly", fileName);
return FileSystem.getInstance(fileName).isReadOnly(fileName);
}
public long length(String fileName) {
fileName = translateFileName(fileName);
debug("length", fileName);
trace("length", fileName);
return FileSystem.getInstance(fileName).length(fileName);
}
public String[] listFiles(String directory) throws SQLException {
directory = translateFileName(directory);
debug("listFiles", directory);
trace("listFiles", directory);
String[] list = FileSystem.getInstance(directory).listFiles(directory);
for (int i = 0; i < list.length; i++) {
list[i] = PREFIX + list[i];
......@@ -150,38 +174,38 @@ public class FileSystemDebug extends FileSystem {
public String normalize(String fileName) throws SQLException {
fileName = translateFileName(fileName);
debug("normalize", fileName);
trace("normalize", fileName);
return PREFIX + FileSystem.getInstance(fileName).normalize(fileName);
}
public InputStream openFileInputStream(String fileName) throws IOException {
fileName = translateFileName(fileName);
debug("openFileInputStream", fileName);
trace("openFileInputStream", fileName);
return FileSystem.getInstance(fileName).openFileInputStream(fileName);
}
public FileObject openFileObject(String fileName, String mode) throws IOException {
fileName = translateFileName(fileName);
debug("openFileObject", fileName, mode);
trace("openFileObject", fileName, mode);
return new FileObjectDebug(this, FileSystem.getInstance(fileName).openFileObject(fileName, mode));
}
public OutputStream openFileOutputStream(String fileName, boolean append) throws SQLException {
fileName = translateFileName(fileName);
debug("openFileOutputStream", fileName, append);
trace("openFileOutputStream", fileName, append);
return FileSystem.getInstance(fileName).openFileOutputStream(fileName, append);
}
public void rename(String oldName, String newName) throws SQLException {
oldName = translateFileName(oldName);
newName = translateFileName(newName);
debug("rename", oldName, newName);
trace("rename", oldName, newName);
FileSystem.getInstance(oldName).copy(oldName, newName);
}
public boolean tryDelete(String fileName) {
fileName = translateFileName(fileName);
debug("tryDelete", fileName);
trace("tryDelete", fileName);
return FileSystem.getInstance(fileName).tryDelete(fileName);
}
......@@ -203,13 +227,31 @@ public class FileSystemDebug extends FileSystem {
* @param fileName the file name
* @param params parameters if any
*/
void debug(String method, String fileName, Object... params) {
StringBuilder buff = new StringBuilder(" ");
buff.append(fileName).append(' ').append(method);
for (Object s : params) {
buff.append(' ').append(s);
void trace(String method, String fileName, Object... params) {
if (trace) {
StringBuilder buff = new StringBuilder(" ");
buff.append(fileName).append(' ').append(method);
for (Object s : params) {
buff.append(' ').append(s);
}
System.out.println(buff);
}
System.out.println(buff);
}
public void setPowerOffCount(int count) {
this.powerOffCount = count;
}
public int getPowerOffCount() {
return powerOffCount;
}
public boolean isTrace() {
return trace;
}
public void setTrace(boolean trace) {
this.trace = trace;
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论