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

Problems in recovery.

上级 bdfc4914
...@@ -18,7 +18,12 @@ Change Log ...@@ -18,7 +18,12 @@ Change Log
<h1>Change Log</h1> <h1>Change Log</h1>
<h2>Next Version (unreleased)</h2> <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. 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 </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). declared action (INSERT triggers were also called when deleting rows).
......
...@@ -232,6 +232,13 @@ Flux</a><br /> ...@@ -232,6 +232,13 @@ Flux</a><br />
Java job scheduler, file transfer, workflow, and BPM. Java job scheduler, file transfer, workflow, and BPM.
</p> </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"> <p><a href="http://ggc.sourceforge.net">
GNU Gluco Control</a><br /> GNU Gluco Control</a><br />
Helps you to manage your diabetes. Helps you to manage your diabetes.
......
...@@ -238,6 +238,7 @@ public class SysProperties { ...@@ -238,6 +238,7 @@ public class SysProperties {
* the wrong user name or password. This slows down brute force attacks. The * the wrong user name or password. This slows down brute force attacks. The
* delay is reset to this value after a successful login. Unsuccessful * delay is reset to this value after a successful login. Unsuccessful
* logins will double the time until DELAY_WRONG_PASSWORD_MAX. * 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); public static final int DELAY_WRONG_PASSWORD_MIN = getIntSetting("h2.delayWrongPasswordMin", 250);
......
...@@ -9,6 +9,7 @@ package org.h2.result; ...@@ -9,6 +9,7 @@ package org.h2.result;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.command.ddl.CreateTableData; import org.h2.command.ddl.CreateTableData;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.index.BtreeIndex; import org.h2.index.BtreeIndex;
import org.h2.index.Cursor; import org.h2.index.Cursor;
...@@ -51,7 +52,6 @@ public class ResultTempTable implements ResultExternal { ...@@ -51,7 +52,6 @@ public class ResultTempTable implements ResultExternal {
data.headPos = Index.EMPTY_HEAD; data.headPos = Index.EMPTY_HEAD;
data.session = session; data.session = session;
table = schema.createTable(data); table = schema.createTable(data);
session.addLocalTempTable(table);
int indexId = session.getDatabase().allocateObjectId(true, false); int indexId = session.getDatabase().allocateObjectId(true, false);
IndexColumn indexColumn = new IndexColumn(); IndexColumn indexColumn = new IndexColumn();
indexColumn.column = column; indexColumn.column = column;
...@@ -65,7 +65,6 @@ public class ResultTempTable implements ResultExternal { ...@@ -65,7 +65,6 @@ public class ResultTempTable implements ResultExternal {
index = new BtreeIndex(session, table, indexId, data.tableName, indexCols, indexType, Index.EMPTY_HEAD); index = new BtreeIndex(session, table, indexId, data.tableName, indexCols, indexType, Index.EMPTY_HEAD);
} }
index.setTemporary(true); index.setTemporary(true);
session.addLocalTempTableIndex(index);
table.getIndexes().add(index); table.getIndexes().add(index);
} }
...@@ -102,9 +101,28 @@ public class ResultTempTable implements ResultExternal { ...@@ -102,9 +101,28 @@ public class ResultTempTable implements ResultExternal {
} }
public void close() { public void close() {
if (table == null) {
return;
}
try { try {
if (table != null) { table.truncate(session);
session.removeLocalTempTable(table); 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) { } catch (SQLException e) {
throw Message.convertToInternal(e); throw Message.convertToInternal(e);
......
...@@ -280,7 +280,7 @@ public class PageLog { ...@@ -280,7 +280,7 @@ public class PageLog {
} else if (stage == RECOVERY_STAGE_REDO) { } else if (stage == RECOVERY_STAGE_REDO) {
if (isSessionCommitted(sessionId, logId, pos)) { if (isSessionCommitted(sessionId, logId, pos)) {
if (trace.isDebugEnabled()) { 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); store.redo(pos, tableId, row, true);
} else { } else {
......
...@@ -61,6 +61,7 @@ public class CacheLRU implements Cache { ...@@ -61,6 +61,7 @@ public class CacheLRU implements Cache {
} }
Cache cache; Cache cache;
if ("TQ".equals(cacheType)) { if ("TQ".equals(cacheType)) {
// for backward compatibility - actually using LRU not TQ
cache = new CacheLRU(writer, cacheSize); cache = new CacheLRU(writer, cacheSize);
} else if (CacheLRU.TYPE_NAME.equals(cacheType)) { } else if (CacheLRU.TYPE_NAME.equals(cacheType)) {
cache = new CacheLRU(writer, cacheSize); cache = new CacheLRU(writer, cacheSize);
......
...@@ -297,7 +297,11 @@ java org.h2.test.TestAll timer ...@@ -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"); // System.setProperty("h2.pageSize", "64");
test with small freeList pages, page size 64 test with small freeList pages, page size 64
......
...@@ -38,6 +38,12 @@ public abstract class TestBase { ...@@ -38,6 +38,12 @@ public abstract class TestBase {
* The base directory to write test databases. * The base directory to write test databases.
*/ */
protected static String baseDir = getTestDir(""); 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"; private static final String BASE_TEST_DIR = "data";
/** /**
......
...@@ -35,6 +35,8 @@ import org.h2.test.TestAll; ...@@ -35,6 +35,8 @@ import org.h2.test.TestAll;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.test.db.TestScript; import org.h2.test.db.TestScript;
import org.h2.test.synth.sql.RandomGen; 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.New;
import org.h2.util.RandomUtils; import org.h2.util.RandomUtils;
...@@ -108,7 +110,8 @@ public class TestCrashAPI extends TestBase { ...@@ -108,7 +110,8 @@ public class TestCrashAPI extends TestBase {
// config.logMode = 2; // config.logMode = 2;
// } // }
String url = getURL(DIR + "/crashApi" + seed, true) + add; String dbName = "crashApi" + seed;
String url = getURL(DIR + "/" + dbName, true) + add;
// int test; // int test;
// url += ";DB_CLOSE_ON_EXIT=FALSE"; // url += ";DB_CLOSE_ON_EXIT=FALSE";
...@@ -117,7 +120,19 @@ public class TestCrashAPI extends TestBase { ...@@ -117,7 +120,19 @@ public class TestCrashAPI extends TestBase {
Connection conn = null; Connection conn = null;
// System.gc(); // 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 len = random.getInt(50);
int start = random.getInt(statements.size() - len); int start = random.getInt(statements.size() - len);
int end = start + len; int end = start + len;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论