/*
* Copyright 2004-2011 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.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Random;
import org.h2.test.TestBase;
import org.h2.util.JdbcUtils;
import org.h2.util.New;
import org.h2.util.Task;
/**
* A multi-threaded test case.
*/
public class TestMultiThreadedKernel extends TestBase {
/**
* Stop the current thread.
*/
volatile boolean stop;
/**
* The exception that occurred in the thread.
*/
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");
testConcurrentRead();
testCache();
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 j = 0; j < 100 && !stop; j++) {
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;
}
deleteDb("multiThreadedKernel");
}
private void testConcurrentRead() throws Exception {
ArrayList<Task> list = New.arrayList();
int size = 2;
final int count = 1000;
String url = getURL("multiThreadedKernel;MULTI_THREADED=TRUE;CACHE_SIZE=16", true);
for (int i = 0; i < size; i++) {
final Connection conn = DriverManager.getConnection(url, getUser(), getPassword());
if (i == 0) {
Statement stat = conn.createStatement();
stat.execute("drop table test if exists");
stat.execute("create table test(id int primary key, name varchar) "
+ "as select x, x || space(10) from system_range(1, " + count + ")");
}
final Random random = new Random(i);
Task t = new Task() {
public void call() throws Exception {
PreparedStatement prep = conn.prepareStatement(
"select * from test where id = ?");
while (!stop) {
prep.setInt(1, random.nextInt(count));
prep.execute();
}
}
};
t.execute();
list.add(t);
}
Thread.sleep(1000);
for (Task t : list) {
t.get();
}
}
private void testCache() throws Exception {
ArrayList<Task> list = New.arrayList();
int size = 3;
final int count = 100;
String url = getURL("multiThreadedKernel;MULTI_THREADED=TRUE;CACHE_SIZE=1", true);
for (int i = 0; i < size; i++) {
final Connection conn = DriverManager.getConnection(url, getUser(), getPassword());
if (i == 0) {
Statement stat = conn.createStatement();
stat.execute("drop table test if exists");
stat.execute("create table test(id int primary key, name varchar) "
+ "as select x, space(3000) from system_range(1, " + count + ")");
}
final Random random = new Random(i);
Task t = new Task() {
public void call() throws SQLException {
PreparedStatement prep = conn.prepareStatement(
"select * from test where id = ?");
while (!stop) {
prep.setInt(1, random.nextInt(count));
prep.execute();
}
}
};
t.execute();
list.add(t);
}
Thread.sleep(1000);
for (Task t : list) {
t.get();
}
}
}