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

Problems in recovery.

上级 bdfc4914
......@@ -18,7 +18,12 @@ Change Log
<h1>Change Log</h1>
<h2>Next Version (unreleased)</h2>
<ul><li>Trigger that are called before a select statement are now supported.
<ul><li>Trying to alter a temporary table threw a strange exception.
It is still not possible to do that, but the exception message is better now.
</li><li>When the system property h2.maxMemoryRowsDistinct was set, and
using SELECT DISTINCT, the temporary table was not correctly dropped.
This could cause problems in recovery when the process was killed.
</li><li>Trigger that are called before a select statement are now supported.
This allows to create tables that work like materialized views.
</li><li>Non-row based triggers were called even if the action didn't match the
declared action (INSERT triggers were also called when deleting rows).
......
......@@ -232,6 +232,13 @@ Flux</a><br />
Java job scheduler, file transfer, workflow, and BPM.
</p>
<p><a href="http://code.google.com/p/gbif-providertoolkit">
GBIF Integrated Publishing Toolkit (IPT)</a><br />
The GBIF IPT is an open source, Java based web application that connects and serves
three types of biodiversity data: taxon primary occurrence data,
taxon checklists and general resource metadata.
</p>
<p><a href="http://ggc.sourceforge.net">
GNU Gluco Control</a><br />
Helps you to manage your diabetes.
......
......@@ -238,6 +238,7 @@ public class SysProperties {
* the wrong user name or password. This slows down brute force attacks. The
* delay is reset to this value after a successful login. Unsuccessful
* logins will double the time until DELAY_WRONG_PASSWORD_MAX.
* To disable the delay, set this system property to 0.
*/
public static final int DELAY_WRONG_PASSWORD_MIN = getIntSetting("h2.delayWrongPasswordMin", 250);
......
......@@ -9,6 +9,7 @@ package org.h2.result;
import java.sql.SQLException;
import org.h2.command.ddl.CreateTableData;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.index.BtreeIndex;
import org.h2.index.Cursor;
......@@ -51,7 +52,6 @@ public class ResultTempTable implements ResultExternal {
data.headPos = Index.EMPTY_HEAD;
data.session = session;
table = schema.createTable(data);
session.addLocalTempTable(table);
int indexId = session.getDatabase().allocateObjectId(true, false);
IndexColumn indexColumn = new IndexColumn();
indexColumn.column = column;
......@@ -65,7 +65,6 @@ public class ResultTempTable implements ResultExternal {
index = new BtreeIndex(session, table, indexId, data.tableName, indexCols, indexType, Index.EMPTY_HEAD);
}
index.setTemporary(true);
session.addLocalTempTableIndex(index);
table.getIndexes().add(index);
}
......@@ -102,9 +101,28 @@ public class ResultTempTable implements ResultExternal {
}
public void close() {
if (table == null) {
return;
}
try {
if (table != null) {
session.removeLocalTempTable(table);
table.truncate(session);
Database database = session.getDatabase();
synchronized (database) {
Session sysSession = database.getSystemSession();
if (!database.isSysTableLocked()) {
// this session may not lock the sys table (except if it already has locked it)
// because it must be committed immediately
// otherwise other threads can not access the sys table.
// if the table is not removed now, it will be when the database
// is opened the next time
// (the table is truncated, so this is just one record)
synchronized (sysSession) {
index.removeChildrenAndResources(sysSession);
table.removeChildrenAndResources(sysSession);
// the transaction must be committed immediately
sysSession.commit(false);
}
}
}
} catch (SQLException e) {
throw Message.convertToInternal(e);
......
......@@ -280,7 +280,7 @@ public class PageLog {
} else if (stage == RECOVERY_STAGE_REDO) {
if (isSessionCommitted(sessionId, logId, pos)) {
if (trace.isDebugEnabled()) {
trace.debug("log redo + table:" + tableId + " " + row);
trace.debug("log redo + table:" + tableId + " s:" + sessionId + " " + row);
}
store.redo(pos, tableId, row, true);
} else {
......
......@@ -61,6 +61,7 @@ public class CacheLRU implements Cache {
}
Cache cache;
if ("TQ".equals(cacheType)) {
// for backward compatibility - actually using LRU not TQ
cache = new CacheLRU(writer, cacheSize);
} else if (CacheLRU.TYPE_NAME.equals(cacheType)) {
cache = new CacheLRU(writer, cacheSize);
......
......@@ -297,7 +297,11 @@ java org.h2.test.TestAll timer
/*
file lock serialized with counter
TestClob - delete temp files
Document Shell tool
Add link to http://groups.google.com/group/h2-cn
// System.setProperty("h2.pageSize", "64");
test with small freeList pages, page size 64
......
......@@ -38,6 +38,12 @@ public abstract class TestBase {
* The base directory to write test databases.
*/
protected static String baseDir = getTestDir("");
/**
* An id used to create unique file names.
*/
protected static int uniqueId;
private static final String BASE_TEST_DIR = "data";
/**
......
......@@ -35,6 +35,8 @@ import org.h2.test.TestAll;
import org.h2.test.TestBase;
import org.h2.test.db.TestScript;
import org.h2.test.synth.sql.RandomGen;
import org.h2.tools.Backup;
import org.h2.util.FileUtils;
import org.h2.util.New;
import org.h2.util.RandomUtils;
......@@ -108,7 +110,8 @@ public class TestCrashAPI extends TestBase {
// config.logMode = 2;
// }
String url = getURL(DIR + "/crashApi" + seed, true) + add;
String dbName = "crashApi" + seed;
String url = getURL(DIR + "/" + dbName, true) + add;
// int test;
// url += ";DB_CLOSE_ON_EXIT=FALSE";
......@@ -117,7 +120,19 @@ public class TestCrashAPI extends TestBase {
Connection conn = null;
// System.gc();
conn = DriverManager.getConnection(url, "sa", getPassword(""));
String fileName = "temp/backup/db-" + uniqueId++ + ".zip";
Backup.execute(fileName, baseDir + "/" + DIR, dbName, true);
try {
conn = DriverManager.getConnection(url, "sa", getPassword(""));
// delete the backup if opening was successful
FileUtils.delete(fileName);
} catch (SQLException e) {
if (e.getErrorCode() == ErrorCode.WRONG_USER_OR_PASSWORD) {
// delete if the password changed
FileUtils.delete(fileName);
}
throw e;
}
int len = random.getInt(50);
int start = random.getInt(statements.size() - len);
int end = start + len;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论