001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (license2)
004: * Initial Developer: James Devenish
005: */
006: package org.h2.test.jdbcx;
007:
008: import java.sql.Connection;
009: import java.sql.SQLException;
010: import java.sql.Statement;
011: import javax.sql.XAConnection;
012: import javax.sql.XADataSource;
013: import javax.transaction.xa.XAResource;
014: import javax.transaction.xa.Xid;
015:
016: import org.h2.jdbcx.JdbcDataSource;
017: import org.h2.test.TestBase;
018: import org.h2.util.JdbcUtils;
019:
020: /**
021: * Basic XA tests.
022: */
023: public class TestXA extends TestBase {
024: private static final String DB_NAME1 = "xadb1";
025: private static final String DB_NAME2 = "xadb2";
026: private static final String DB_URL1 = "jdbc:h2:file:" + baseDir
027: + "/" + DB_NAME1;
028: private static final String DB_URL2 = "jdbc:h2:file:" + baseDir
029: + "/" + DB_NAME2;
030:
031: public void test() throws Exception {
032: testXAAutoCommit();
033: deleteDb(baseDir, "xa");
034: testXA(true);
035: deleteDb(baseDir, DB_NAME1);
036: deleteDb(baseDir, DB_NAME2);
037: testXA(false);
038: }
039:
040: public static class MyXid implements Xid {
041: private byte[] branchQualifier = new byte[1];
042: private byte[] globalTransactionId = new byte[1];
043:
044: public byte[] getBranchQualifier() {
045: return branchQualifier;
046: }
047:
048: public int getFormatId() {
049: return 0;
050: }
051:
052: public byte[] getGlobalTransactionId() {
053: return globalTransactionId;
054: }
055: }
056:
057: private void testXAAutoCommit() throws Exception {
058: JdbcDataSource ds = new JdbcDataSource();
059: ds.setURL("jdbc:h2:mem:test");
060: ds.setUser("sa");
061: ds.setPassword("");
062: XAConnection xa = ds.getXAConnection();
063: MyXid xid = new MyXid();
064: xa.getXAResource().start(xid, XAResource.TMNOFLAGS);
065: Connection c = xa.getConnection();
066: check(!c.getAutoCommit());
067: c.close();
068: }
069:
070: private void testXA(boolean useOneDatabase) {
071: XAConnection xaConn1 = null;
072: XAConnection xaConn2 = null;
073: Connection conn1 = null;
074: Connection conn2 = null;
075: Statement stat1 = null;
076: Statement stat2 = null;
077: try {
078: trace("xads1 = createXADatasource1()");
079: XADataSource xaDs1 = createXADatasource(useOneDatabase,
080: DB_URL1);
081: trace("xads2 = createXADatasource2()");
082: XADataSource xaDs2 = createXADatasource(useOneDatabase,
083: DB_URL2);
084:
085: trace("xacon1 = xads1.getXAConnection()");
086: xaConn1 = xaDs1.getXAConnection();
087: trace("xacon2 = xads2.getXAConnection()");
088: xaConn2 = xaDs2.getXAConnection();
089:
090: trace("xares1 = xacon1.getXAResource()");
091: XAResource xares1 = xaConn1.getXAResource();
092: trace("xares2 = xacon2.getXAResource()");
093: XAResource xares2 = xaConn2.getXAResource();
094:
095: trace("xares1.recover(XAResource.TMSTARTRSCAN)");
096: Xid[] xids1 = xares1.recover(XAResource.TMSTARTRSCAN);
097: if ((xids1 == null) || (xids1.length == 0)) {
098: trace("xares1.recover(XAResource.TMSTARTRSCAN): 0");
099: } else {
100: trace("xares1.recover(XAResource.TMSTARTRSCAN): "
101: + xids1.length);
102: }
103:
104: trace("xares2.recover(XAResource.TMSTARTRSCAN)");
105: Xid[] xids2 = xares2.recover(XAResource.TMSTARTRSCAN);
106: if ((xids2 == null) || (xids2.length == 0)) {
107: trace("xares2.recover(XAResource.TMSTARTRSCAN): 0");
108: } else {
109: trace("xares2.recover(XAResource.TMSTARTRSCAN): "
110: + xids2.length);
111: }
112:
113: trace("con1 = xacon1.getConnection()");
114: conn1 = xaConn1.getConnection();
115: trace("stmt1 = con1.createStatement()");
116: stat1 = conn1.createStatement();
117:
118: trace("con2 = xacon2.getConnection()");
119: conn2 = xaConn2.getConnection();
120: trace("stmt2 = con2.createStatement()");
121: stat2 = conn2.createStatement();
122:
123: if (useOneDatabase) {
124: trace("stmt1.executeUpdate(\"DROP TABLE xatest1\")");
125: try {
126: stat1.executeUpdate("DROP TABLE xatest1");
127: } catch (SQLException e) {
128: }
129: trace("stmt2.executeUpdate(\"DROP TABLE xatest2\")");
130: try {
131: stat2.executeUpdate("DROP TABLE xatest2");
132: } catch (SQLException e) {
133: }
134: } else {
135: trace("stmt1.executeUpdate(\"DROP TABLE xatest\")");
136: try {
137: stat1.executeUpdate("DROP TABLE xatest");
138: } catch (SQLException e) {
139: }
140: trace("stmt2.executeUpdate(\"DROP TABLE xatest\")");
141: try {
142: stat2.executeUpdate("DROP TABLE xatest");
143: } catch (SQLException e) {
144: }
145: }
146:
147: if (useOneDatabase) {
148: trace("stmt1.executeUpdate(\"CREATE TABLE xatest1 (id INT PRIMARY KEY, value INT)\")");
149: stat1
150: .executeUpdate("CREATE TABLE xatest1 (id INT PRIMARY KEY, value INT)");
151: trace("stmt2.executeUpdate(\"CREATE TABLE xatest2 (id INT PRIMARY KEY, value INT)\")");
152: stat2
153: .executeUpdate("CREATE TABLE xatest2 (id INT PRIMARY KEY, value INT)");
154: } else {
155: trace("stmt1.executeUpdate(\"CREATE TABLE xatest (id INT PRIMARY KEY, value INT)\")");
156: stat1
157: .executeUpdate("CREATE TABLE xatest (id INT PRIMARY KEY, value INT)");
158: trace("stmt2.executeUpdate(\"CREATE TABLE xatest (id INT PRIMARY KEY, value INT)\")");
159: stat2
160: .executeUpdate("CREATE TABLE xatest (id INT PRIMARY KEY, value INT)");
161: }
162:
163: if (useOneDatabase) {
164: trace("stmt1.executeUpdate(\"INSERT INTO xatest1 VALUES (1, 0)\")");
165: stat1
166: .executeUpdate("INSERT INTO xatest1 VALUES (1, 0)");
167: trace("stmt2.executeUpdate(\"INSERT INTO xatest2 VALUES (2, 0)\")");
168: stat2
169: .executeUpdate("INSERT INTO xatest2 VALUES (2, 0)");
170: } else {
171: trace("stmt1.executeUpdate(\"INSERT INTO xatest VALUES (1, 0)\")");
172: stat1.executeUpdate("INSERT INTO xatest VALUES (1, 0)");
173: trace("stmt2.executeUpdate(\"INSERT INTO xatest VALUES (2, 0)\")");
174: stat2.executeUpdate("INSERT INTO xatest VALUES (2, 0)");
175: }
176:
177: Xid xid1 = null;
178: Xid xid2 = null;
179:
180: if (useOneDatabase) {
181: xid1 = new TestXid(1);
182: xid2 = new TestXid(2);
183: } else {
184: xid1 = new TestXid(1);
185: xid2 = xid1;
186: }
187:
188: if (useOneDatabase) {
189: trace("xares1.start(xid1, XAResource.TMNOFLAGS)");
190: xares1.start(xid1, XAResource.TMNOFLAGS);
191: trace("xares2.start(xid2, XAResource.TMJOIN)");
192: xares2.start(xid2, XAResource.TMJOIN);
193: } else {
194: trace("xares1.start(xid1, XAResource.TMNOFLAGS)");
195: xares1.start(xid1, XAResource.TMNOFLAGS);
196: trace("xares2.start(xid2, XAResource.TMNOFLAGS)");
197: xares2.start(xid2, XAResource.TMNOFLAGS);
198: }
199:
200: if (useOneDatabase) {
201: trace("stmt1.executeUpdate(\"UPDATE xatest1 SET value=1 WHERE id=1\")");
202: stat1
203: .executeUpdate("UPDATE xatest1 SET value=1 WHERE id=1");
204: trace("stmt2.executeUpdate(\"UPDATE xatest2 SET value=1 WHERE id=2\")");
205: stat2
206: .executeUpdate("UPDATE xatest2 SET value=1 WHERE id=2");
207: } else {
208: trace("stmt1.executeUpdate(\"UPDATE xatest SET value=1 WHERE id=1\")");
209: stat1
210: .executeUpdate("UPDATE xatest SET value=1 WHERE id=1");
211: trace("stmt2.executeUpdate(\"UPDATE xatest SET value=1 WHERE id=2\")");
212: stat2
213: .executeUpdate("UPDATE xatest SET value=1 WHERE id=2");
214: }
215:
216: trace("xares1.end(xid1, XAResource.TMSUCCESS)");
217: xares1.end(xid1, XAResource.TMSUCCESS);
218: trace("xares2.end(xid2, XAResource.TMSUCCESS)");
219: xares2.end(xid2, XAResource.TMSUCCESS);
220:
221: int ret1;
222: int ret2;
223:
224: trace("ret1 = xares1.prepare(xid1)");
225: ret1 = xares1.prepare(xid1);
226: trace("xares1.prepare(xid1): " + ret1);
227: trace("ret2 = xares2.prepare(xid2)");
228: ret2 = xares2.prepare(xid2);
229: trace("xares2.prepare(xid2): " + ret2);
230:
231: if ((ret1 != XAResource.XA_OK)
232: && (ret1 != XAResource.XA_RDONLY)) {
233: throw new IllegalStateException(
234: "xares1.prepare(xid1) must return XA_OK or XA_RDONLY");
235: }
236: if ((ret2 != XAResource.XA_OK)
237: && (ret2 != XAResource.XA_RDONLY)) {
238: throw new IllegalStateException(
239: "xares2.prepare(xid2) must return XA_OK or XA_RDONLY");
240: }
241:
242: if (ret1 == XAResource.XA_OK) {
243: trace("xares1.commit(xid1, false)");
244: xares1.commit(xid1, false);
245: }
246: if (ret2 == XAResource.XA_OK) {
247: trace("xares2.commit(xid2, false)");
248: xares2.commit(xid2, false);
249: }
250: } catch (Exception e) {
251: e.printStackTrace();
252: } finally {
253: JdbcUtils.closeSilently(stat1);
254: JdbcUtils.closeSilently(stat2);
255: JdbcUtils.closeSilently(conn1);
256: JdbcUtils.closeSilently(conn2);
257: JdbcUtils.closeSilently(xaConn1);
258: JdbcUtils.closeSilently(xaConn2);
259: }
260: }
261:
262: private XADataSource createXADatasource(boolean useOneDatabase,
263: String url) throws SQLException {
264: JdbcDataSource ds = new JdbcDataSource();
265: ds.setPassword("");
266: ds.setUser("sa");
267: if (useOneDatabase) {
268: ds.setURL(getURL("xa", true));
269: } else {
270: ds.setURL(url);
271: }
272: return ds;
273: }
274:
275: }
|