001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (license2)
004: * Initial Developer: H2 Group
005: */
006: package org.h2.test.db;
007:
008: import java.sql.Connection;
009: import java.sql.ResultSet;
010: import java.sql.SQLException;
011: import java.sql.Statement;
012:
013: import org.h2.api.DatabaseEventListener;
014: import org.h2.test.TestBase;
015:
016: /**
017: * Multi-connection tests.
018: */
019: public class TestMultiConn extends TestBase implements
020: DatabaseEventListener {
021:
022: public void test() throws Exception {
023: testCommitRollback();
024: testConcurrentOpen();
025: testThreeThreads();
026: }
027:
028: private static int wait;
029:
030: private void testThreeThreads() throws Exception {
031: deleteDb("multiConn");
032: final Connection conn1 = getConnection("multiConn");
033: final Connection conn2 = getConnection("multiConn");
034: final Connection conn3 = getConnection("multiConn");
035: conn1.setAutoCommit(false);
036: conn2.setAutoCommit(false);
037: conn3.setAutoCommit(false);
038: final Statement s1 = conn1.createStatement();
039: final Statement s2 = conn2.createStatement();
040: final Statement s3 = conn3.createStatement();
041: s1.execute("CREATE TABLE TEST1(ID INT)");
042: s2.execute("CREATE TABLE TEST2(ID INT)");
043: s3.execute("CREATE TABLE TEST3(ID INT)");
044: s1.execute("INSERT INTO TEST1 VALUES(1)");
045: s2.execute("INSERT INTO TEST2 VALUES(2)");
046: s3.execute("INSERT INTO TEST3 VALUES(3)");
047: s1.execute("SET LOCK_TIMEOUT 1000");
048: s2.execute("SET LOCK_TIMEOUT 1000");
049: s3.execute("SET LOCK_TIMEOUT 1000");
050: Thread t1 = new Thread(new Runnable() {
051: public void run() {
052: try {
053: s3.execute("INSERT INTO TEST2 VALUES(4)");
054: conn3.commit();
055: } catch (SQLException e) {
056: TestBase.logError("insert", e);
057: }
058: }
059: });
060: t1.start();
061: Thread.sleep(20);
062: Thread t2 = new Thread(new Runnable() {
063: public void run() {
064: try {
065: s2.execute("INSERT INTO TEST1 VALUES(5)");
066: conn2.commit();
067: } catch (SQLException e) {
068: TestBase.logError("insert", e);
069: }
070: }
071: });
072: t2.start();
073: Thread.sleep(20);
074: conn1.commit();
075: t2.join(1000);
076: t1.join(1000);
077: ResultSet rs = s1
078: .executeQuery("SELECT * FROM TEST1 ORDER BY ID");
079: rs.next();
080: check(rs.getInt(1), 1);
081: rs.next();
082: check(rs.getInt(1), 5);
083: checkFalse(rs.next());
084: conn1.close();
085: conn2.close();
086: conn3.close();
087: }
088:
089: private void testConcurrentOpen() throws Exception {
090: if (config.memory) {
091: return;
092: }
093: deleteDb("multiConn");
094: Connection conn = getConnection("multiConn");
095: conn.createStatement().execute(
096: "CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR)");
097: conn.createStatement().execute(
098: "INSERT INTO TEST VALUES(0, 'Hello'), (1, 'World')");
099: conn.createStatement().execute("SHUTDOWN");
100: conn.close();
101: final String listener = getClass().getName();
102: Runnable r = new Runnable() {
103: public void run() {
104: try {
105: Connection c1 = getConnection("multiConn;DATABASE_EVENT_LISTENER='"
106: + listener + "';file_lock=socket");
107: c1.close();
108: } catch (Exception e) {
109: TestBase.logError("connect", e);
110: }
111: }
112: };
113: Thread thread = new Thread(r);
114: thread.start();
115: Thread.sleep(10);
116: Connection c2 = getConnection("multiConn;file_lock=socket");
117: c2.close();
118: thread.join();
119: }
120:
121: public void diskSpaceIsLow(long stillAvailable) throws SQLException {
122: }
123:
124: public void exceptionThrown(SQLException e, String sql) {
125: }
126:
127: public void setProgress(int state, String name, int x, int max) {
128: while (wait > 0) {
129: try {
130: Thread.sleep(wait);
131: wait = 0;
132: } catch (InterruptedException e) {
133: TestBase.logError("sleep", e);
134: }
135: }
136: }
137:
138: public void closingDatabase() {
139: }
140:
141: private void testCommitRollback() throws Exception {
142: deleteDb("multiConn");
143: Connection c1 = getConnection("multiConn");
144: Connection c2 = getConnection("multiConn");
145: c1.setAutoCommit(false);
146: c2.setAutoCommit(false);
147: Statement s1 = c1.createStatement();
148: s1.execute("DROP TABLE IF EXISTS MULTI_A");
149: s1.execute("CREATE TABLE MULTI_A(ID INT, NAME VARCHAR(255))");
150: s1.execute("INSERT INTO MULTI_A VALUES(0, '0-insert-A')");
151: Statement s2 = c2.createStatement();
152: s1.execute("DROP TABLE IF EXISTS MULTI_B");
153: s1.execute("CREATE TABLE MULTI_B(ID INT, NAME VARCHAR(255))");
154: s2.execute("INSERT INTO MULTI_B VALUES(0, '1-insert-B')");
155: c1.commit();
156: c2.rollback();
157: s1.execute("INSERT INTO MULTI_A VALUES(1, '0-insert-C')");
158: s2.execute("INSERT INTO MULTI_B VALUES(1, '1-insert-D')");
159: c1.rollback();
160: c2.commit();
161: c1.close();
162: c2.close();
163:
164: if (!config.memory) {
165: Connection conn = getConnection("multiConn");
166: ResultSet rs;
167: rs = conn.createStatement().executeQuery(
168: "SELECT * FROM MULTI_A ORDER BY ID");
169: rs.next();
170: check(rs.getString("NAME"), "0-insert-A");
171: checkFalse(rs.next());
172: rs = conn.createStatement().executeQuery(
173: "SELECT * FROM MULTI_B ORDER BY ID");
174: rs.next();
175: check(rs.getString("NAME"), "1-insert-D");
176: checkFalse(rs.next());
177: conn.close();
178: }
179:
180: }
181:
182: public void init(String url) {
183: }
184:
185: public void opened() {
186: }
187:
188: }
|