提交 2107b3c9 authored 作者: Thomas Mueller's avatar Thomas Mueller

Multi-threaded kernel bugfixes.

上级 57893f34
......@@ -224,7 +224,9 @@ public class Session extends SessionWithState {
public void removeLocalTempTable(Table table) throws SQLException {
modificationId++;
localTempTables.remove(table.getName());
table.removeChildrenAndResources(this);
synchronized (database) {
table.removeChildrenAndResources(this);
}
}
/**
......@@ -272,7 +274,9 @@ public class Session extends SessionWithState {
public void removeLocalTempTableIndex(Index index) throws SQLException {
if (localTempTableIndexes != null) {
localTempTableIndexes.remove(index.getName());
index.removeChildrenAndResources(this);
synchronized (database) {
index.removeChildrenAndResources(this);
}
}
}
......@@ -328,7 +332,9 @@ public class Session extends SessionWithState {
public void removeLocalTempTableConstraint(Constraint constraint) throws SQLException {
if (localTempTableConstraints != null) {
localTempTableConstraints.remove(constraint.getName());
constraint.removeChildrenAndResources(this);
synchronized (database) {
constraint.removeChildrenAndResources(this);
}
}
}
......@@ -647,14 +653,16 @@ public class Session extends SessionWithState {
private void cleanTempTables(boolean closeSession) throws SQLException {
if (localTempTables != null && localTempTables.size() > 0) {
for (Table table : ObjectArray.newInstance(localTempTables.values())) {
if (closeSession || table.getOnCommitDrop()) {
modificationId++;
table.setModified();
localTempTables.remove(table.getName());
table.removeChildrenAndResources(this);
} else if (table.getOnCommitTruncate()) {
table.truncate(this);
synchronized (database) {
for (Table table : ObjectArray.newInstance(localTempTables.values())) {
if (closeSession || table.getOnCommitDrop()) {
modificationId++;
table.setModified();
localTempTables.remove(table.getName());
table.removeChildrenAndResources(this);
} else if (table.getOnCommitTruncate()) {
table.truncate(this);
}
}
}
}
......
......@@ -495,7 +495,9 @@ public class Schema extends DbObjectBase {
*/
public TableData createTable(String tableName, int id, ObjectArray<Column> columns, boolean persistIndexes, boolean persistData, boolean clustered, int headPos, Session session)
throws SQLException {
return new TableData(this, tableName, id, columns, persistIndexes, persistData, clustered, headPos, session);
synchronized (database) {
return new TableData(this, tableName, id, columns, persistIndexes, persistData, clustered, headPos, session);
}
}
/**
......@@ -515,7 +517,9 @@ public class Schema extends DbObjectBase {
*/
public TableLink createTableLink(int id, String tableName, String driver, String url, String user, String password,
String originalSchema, String originalTable, boolean emitUpdates, boolean force) throws SQLException {
return new TableLink(this, id, tableName, driver, url, user, password, originalSchema, originalTable, emitUpdates, force);
synchronized (database) {
return new TableLink(this, id, tableName, driver, url, user, password, originalSchema, originalTable, emitUpdates, force);
}
}
}
......@@ -682,24 +682,26 @@ public class DiskFile implements CacheWriter {
private void reuseSpace() throws SQLException {
if (SysProperties.REUSE_SPACE_QUICKLY) {
if (potentiallyFreePages.size() >= SysProperties.REUSE_SPACE_AFTER) {
Session[] sessions = database.getSessions(true);
int oldest = 0;
for (int i = 0; i < sessions.length; i++) {
int deleteId = sessions[i].getLastUncommittedDelete();
if (oldest == 0 || (deleteId != 0 && deleteId < oldest)) {
oldest = deleteId;
synchronized (potentiallyFreePages) {
if (potentiallyFreePages.size() >= SysProperties.REUSE_SPACE_AFTER) {
Session[] sessions = database.getSessions(true);
int oldest = 0;
for (int i = 0; i < sessions.length; i++) {
int deleteId = sessions[i].getLastUncommittedDelete();
if (oldest == 0 || (deleteId != 0 && deleteId < oldest)) {
oldest = deleteId;
}
}
}
for (Iterator<Integer> it = potentiallyFreePages.iterator(); it.hasNext();) {
int p = it.next();
if (oldest == 0) {
if (isPageFree(p)) {
// the page may not be free: the storage
// could have re-used it using the storage local free list
setPageOwner(p, FREE_PAGE);
for (Iterator<Integer> it = potentiallyFreePages.iterator(); it.hasNext();) {
int p = it.next();
if (oldest == 0) {
if (isPageFree(p)) {
// the page may not be free: the storage
// could have re-used it using the storage local free list
setPageOwner(p, FREE_PAGE);
}
it.remove();
}
it.remove();
}
}
}
......@@ -733,7 +735,9 @@ public class DiskFile implements CacheWriter {
setPageOwner(page, FREE_PAGE);
} else {
if (SysProperties.REUSE_SPACE_QUICKLY) {
potentiallyFreePages.add(page);
synchronized (potentiallyFreePages) {
potentiallyFreePages.add(page);
}
}
}
}
......@@ -794,7 +798,9 @@ public class DiskFile implements CacheWriter {
if (storageId >= 0) {
database.getStorage(storageId, this).addPage(page);
if (SysProperties.REUSE_SPACE_QUICKLY) {
potentiallyFreePages.remove(page);
synchronized (potentiallyFreePages) {
potentiallyFreePages.remove(page);
}
}
} else {
firstFreePage = Math.min(firstFreePage, page);
......
......@@ -38,6 +38,7 @@ import org.h2.test.db.TestMemoryUsage;
import org.h2.test.db.TestMultiConn;
import org.h2.test.db.TestMultiDimension;
import org.h2.test.db.TestMultiThread;
import org.h2.test.db.TestMultiThreadedKernel;
import org.h2.test.db.TestOpenClose;
import org.h2.test.db.TestOptimizations;
import org.h2.test.db.TestOutOfMemory;
......@@ -115,7 +116,6 @@ import org.h2.test.unit.TestFtp;
import org.h2.test.unit.TestIntArray;
import org.h2.test.unit.TestIntIntHashMap;
import org.h2.test.unit.TestMathUtils;
import org.h2.test.unit.TestMultiThreadedKernel;
import org.h2.test.unit.TestOverflow;
import org.h2.test.unit.TestPattern;
import org.h2.test.unit.TestPgServer;
......@@ -295,6 +295,12 @@ java org.h2.test.TestAll timer
/*
better document that ddl statements commit
"This command commits an open transaction."
PostgreSQL compatibility: 2001-02-03 08:20:31+01 (:minutes optional)
Support Java 6 DatabaseMetaData.getColumns, getProcedures, getProcedureColumns, getTables.
MySQL compatibility for "show columns from test"
-------------
create a short documentation
......@@ -478,6 +484,7 @@ kill -9 `jps -l | grep "org.h2.test.TestAll" | cut -d " " -f 1`
new TestMultiConn().runTest(this);
new TestMultiDimension().runTest(this);
new TestMultiThread().runTest(this);
new TestMultiThreadedKernel().runTest(this);
new TestOpenClose().runTest(this);
new TestOptimizations().runTest(this);
new TestOutOfMemory().runTest(this);
......
/*
* 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.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import org.h2.test.TestBase;
import org.h2.util.JdbcUtils;
/**
* A multi-threaded test case.
*/
public class TestMultiThreadedKernel extends TestBase {
volatile boolean stop;
Exception exception;
/**
* Run just this test.
*
* @param a ignored
*/
public static void main(String[] a) throws Exception {
TestBase.createCaller().init().test();
}
public void test() throws Exception {
if (config.mvcc) {
return;
}
deleteDb("multiThreadedKernel");
final String url = getURL("multiThreadedKernel;DB_CLOSE_DELAY=-1;MULTI_THREADED=1", true);
final String user = getUser(), password = getPassword();
int len = 3;
Thread[] threads = new Thread[len];
for (int i = 0; i < len; i++) {
threads[i] = new Thread(new Runnable() {
public void run() {
Connection conn = null;
try {
for (int i = 0; i < 100 && !stop; i++) {
conn = DriverManager.getConnection(url, user, password);
Statement stat = conn.createStatement();
stat.execute("create local temporary table temp(id identity)");
stat.execute("insert into temp values(1)");
conn.close();
}
} catch (Exception e) {
exception = e;
} finally {
JdbcUtils.closeSilently(conn);
}
}
});
}
for (int i = 0; i < len; i++) {
threads[i].start();
}
Thread.sleep(1000);
stop = true;
for (int i = 0; i < len; i++) {
threads[i].join();
}
Connection conn = DriverManager.getConnection(url, user, password);
conn.createStatement().execute("shutdown");
conn.close();
if (exception != null) {
throw exception;
}
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论