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

Multi-threaded kernel bugfixes.

上级 57893f34
...@@ -224,8 +224,10 @@ public class Session extends SessionWithState { ...@@ -224,8 +224,10 @@ public class Session extends SessionWithState {
public void removeLocalTempTable(Table table) throws SQLException { public void removeLocalTempTable(Table table) throws SQLException {
modificationId++; modificationId++;
localTempTables.remove(table.getName()); localTempTables.remove(table.getName());
synchronized (database) {
table.removeChildrenAndResources(this); table.removeChildrenAndResources(this);
} }
}
/** /**
* Get the local temporary index if one exists with that name, or null if * Get the local temporary index if one exists with that name, or null if
...@@ -272,9 +274,11 @@ public class Session extends SessionWithState { ...@@ -272,9 +274,11 @@ public class Session extends SessionWithState {
public void removeLocalTempTableIndex(Index index) throws SQLException { public void removeLocalTempTableIndex(Index index) throws SQLException {
if (localTempTableIndexes != null) { if (localTempTableIndexes != null) {
localTempTableIndexes.remove(index.getName()); localTempTableIndexes.remove(index.getName());
synchronized (database) {
index.removeChildrenAndResources(this); index.removeChildrenAndResources(this);
} }
} }
}
/** /**
* Get the local temporary constraint if one exists with that name, or * Get the local temporary constraint if one exists with that name, or
...@@ -328,9 +332,11 @@ public class Session extends SessionWithState { ...@@ -328,9 +332,11 @@ public class Session extends SessionWithState {
public void removeLocalTempTableConstraint(Constraint constraint) throws SQLException { public void removeLocalTempTableConstraint(Constraint constraint) throws SQLException {
if (localTempTableConstraints != null) { if (localTempTableConstraints != null) {
localTempTableConstraints.remove(constraint.getName()); localTempTableConstraints.remove(constraint.getName());
synchronized (database) {
constraint.removeChildrenAndResources(this); constraint.removeChildrenAndResources(this);
} }
} }
}
protected void finalize() { protected void finalize() {
if (!SysProperties.runFinalize) { if (!SysProperties.runFinalize) {
...@@ -647,6 +653,7 @@ public class Session extends SessionWithState { ...@@ -647,6 +653,7 @@ public class Session extends SessionWithState {
private void cleanTempTables(boolean closeSession) throws SQLException { private void cleanTempTables(boolean closeSession) throws SQLException {
if (localTempTables != null && localTempTables.size() > 0) { if (localTempTables != null && localTempTables.size() > 0) {
synchronized (database) {
for (Table table : ObjectArray.newInstance(localTempTables.values())) { for (Table table : ObjectArray.newInstance(localTempTables.values())) {
if (closeSession || table.getOnCommitDrop()) { if (closeSession || table.getOnCommitDrop()) {
modificationId++; modificationId++;
...@@ -659,6 +666,7 @@ public class Session extends SessionWithState { ...@@ -659,6 +666,7 @@ public class Session extends SessionWithState {
} }
} }
} }
}
public Random getRandom() { public Random getRandom() {
if (random == null) { if (random == null) {
......
...@@ -495,8 +495,10 @@ public class Schema extends DbObjectBase { ...@@ -495,8 +495,10 @@ 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) public TableData createTable(String tableName, int id, ObjectArray<Column> columns, boolean persistIndexes, boolean persistData, boolean clustered, int headPos, Session session)
throws SQLException { throws SQLException {
synchronized (database) {
return new TableData(this, tableName, id, columns, persistIndexes, persistData, clustered, headPos, session); return new TableData(this, tableName, id, columns, persistIndexes, persistData, clustered, headPos, session);
} }
}
/** /**
* Add a linked table to the schema. * Add a linked table to the schema.
...@@ -515,7 +517,9 @@ public class Schema extends DbObjectBase { ...@@ -515,7 +517,9 @@ public class Schema extends DbObjectBase {
*/ */
public TableLink createTableLink(int id, String tableName, String driver, String url, String user, String password, 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 { String originalSchema, String originalTable, boolean emitUpdates, boolean force) throws SQLException {
synchronized (database) {
return new TableLink(this, id, tableName, driver, url, user, password, originalSchema, originalTable, emitUpdates, force); return new TableLink(this, id, tableName, driver, url, user, password, originalSchema, originalTable, emitUpdates, force);
} }
}
} }
...@@ -682,6 +682,7 @@ public class DiskFile implements CacheWriter { ...@@ -682,6 +682,7 @@ public class DiskFile implements CacheWriter {
private void reuseSpace() throws SQLException { private void reuseSpace() throws SQLException {
if (SysProperties.REUSE_SPACE_QUICKLY) { if (SysProperties.REUSE_SPACE_QUICKLY) {
synchronized (potentiallyFreePages) {
if (potentiallyFreePages.size() >= SysProperties.REUSE_SPACE_AFTER) { if (potentiallyFreePages.size() >= SysProperties.REUSE_SPACE_AFTER) {
Session[] sessions = database.getSessions(true); Session[] sessions = database.getSessions(true);
int oldest = 0; int oldest = 0;
...@@ -705,6 +706,7 @@ public class DiskFile implements CacheWriter { ...@@ -705,6 +706,7 @@ public class DiskFile implements CacheWriter {
} }
} }
} }
}
/** /**
* Called after a session deleted a row. This sets the last uncommitted * Called after a session deleted a row. This sets the last uncommitted
...@@ -733,10 +735,12 @@ public class DiskFile implements CacheWriter { ...@@ -733,10 +735,12 @@ public class DiskFile implements CacheWriter {
setPageOwner(page, FREE_PAGE); setPageOwner(page, FREE_PAGE);
} else { } else {
if (SysProperties.REUSE_SPACE_QUICKLY) { if (SysProperties.REUSE_SPACE_QUICKLY) {
synchronized (potentiallyFreePages) {
potentiallyFreePages.add(page); potentiallyFreePages.add(page);
} }
} }
} }
}
/** /**
* Calculate the page number from a block number. * Calculate the page number from a block number.
...@@ -794,8 +798,10 @@ public class DiskFile implements CacheWriter { ...@@ -794,8 +798,10 @@ public class DiskFile implements CacheWriter {
if (storageId >= 0) { if (storageId >= 0) {
database.getStorage(storageId, this).addPage(page); database.getStorage(storageId, this).addPage(page);
if (SysProperties.REUSE_SPACE_QUICKLY) { if (SysProperties.REUSE_SPACE_QUICKLY) {
synchronized (potentiallyFreePages) {
potentiallyFreePages.remove(page); potentiallyFreePages.remove(page);
} }
}
} else { } else {
firstFreePage = Math.min(firstFreePage, page); firstFreePage = Math.min(firstFreePage, page);
} }
......
...@@ -38,6 +38,7 @@ import org.h2.test.db.TestMemoryUsage; ...@@ -38,6 +38,7 @@ import org.h2.test.db.TestMemoryUsage;
import org.h2.test.db.TestMultiConn; import org.h2.test.db.TestMultiConn;
import org.h2.test.db.TestMultiDimension; import org.h2.test.db.TestMultiDimension;
import org.h2.test.db.TestMultiThread; import org.h2.test.db.TestMultiThread;
import org.h2.test.db.TestMultiThreadedKernel;
import org.h2.test.db.TestOpenClose; import org.h2.test.db.TestOpenClose;
import org.h2.test.db.TestOptimizations; import org.h2.test.db.TestOptimizations;
import org.h2.test.db.TestOutOfMemory; import org.h2.test.db.TestOutOfMemory;
...@@ -115,7 +116,6 @@ import org.h2.test.unit.TestFtp; ...@@ -115,7 +116,6 @@ import org.h2.test.unit.TestFtp;
import org.h2.test.unit.TestIntArray; import org.h2.test.unit.TestIntArray;
import org.h2.test.unit.TestIntIntHashMap; import org.h2.test.unit.TestIntIntHashMap;
import org.h2.test.unit.TestMathUtils; import org.h2.test.unit.TestMathUtils;
import org.h2.test.unit.TestMultiThreadedKernel;
import org.h2.test.unit.TestOverflow; import org.h2.test.unit.TestOverflow;
import org.h2.test.unit.TestPattern; import org.h2.test.unit.TestPattern;
import org.h2.test.unit.TestPgServer; import org.h2.test.unit.TestPgServer;
...@@ -295,6 +295,12 @@ java org.h2.test.TestAll timer ...@@ -295,6 +295,12 @@ java org.h2.test.TestAll timer
/* /*
better document that ddl statements commit 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 create a short documentation
...@@ -478,6 +484,7 @@ kill -9 `jps -l | grep "org.h2.test.TestAll" | cut -d " " -f 1` ...@@ -478,6 +484,7 @@ kill -9 `jps -l | grep "org.h2.test.TestAll" | cut -d " " -f 1`
new TestMultiConn().runTest(this); new TestMultiConn().runTest(this);
new TestMultiDimension().runTest(this); new TestMultiDimension().runTest(this);
new TestMultiThread().runTest(this); new TestMultiThread().runTest(this);
new TestMultiThreadedKernel().runTest(this);
new TestOpenClose().runTest(this); new TestOpenClose().runTest(this);
new TestOptimizations().runTest(this); new TestOptimizations().runTest(this);
new TestOutOfMemory().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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论