提交 d12bd06f authored 作者: Thomas Mueller's avatar Thomas Mueller

Improve code coverage.

上级 4646aa52
...@@ -46,8 +46,6 @@ implements XAConnection, XAResource ...@@ -46,8 +46,6 @@ implements XAConnection, XAResource
{ {
//## Java 1.4 begin ## //## Java 1.4 begin ##
private static int nextTransactionId;
private JdbcDataSourceFactory factory; private JdbcDataSourceFactory factory;
// This connection is kept open as long as the XAConnection is alive // This connection is kept open as long as the XAConnection is alive
...@@ -57,7 +55,6 @@ implements XAConnection, XAResource ...@@ -57,7 +55,6 @@ implements XAConnection, XAResource
private volatile PooledJdbcConnection handleConn; private volatile PooledJdbcConnection handleConn;
private ArrayList<ConnectionEventListener> listeners = New.arrayList(); private ArrayList<ConnectionEventListener> listeners = New.arrayList();
private Xid currentTransaction; private Xid currentTransaction;
private int currentTransactionId;
static { static {
org.h2.Driver.load(); org.h2.Driver.load();
...@@ -258,8 +255,7 @@ implements XAConnection, XAResource ...@@ -258,8 +255,7 @@ implements XAConnection, XAResource
Statement stat = null; Statement stat = null;
try { try {
stat = physicalConn.createStatement(); stat = physicalConn.createStatement();
currentTransactionId = nextTransactionId++; stat.execute("PREPARE COMMIT " + JdbcXid.toString(xid));
stat.execute("PREPARE COMMIT TX_" + currentTransactionId);
} catch (SQLException e) { } catch (SQLException e) {
throw convertException(e); throw convertException(e);
} finally { } finally {
...@@ -297,6 +293,15 @@ implements XAConnection, XAResource ...@@ -297,6 +293,15 @@ implements XAConnection, XAResource
try { try {
physicalConn.rollback(); physicalConn.rollback();
physicalConn.setAutoCommit(true); physicalConn.setAutoCommit(true);
Statement stat = null;
try {
stat = physicalConn.createStatement();
stat.execute("ROLLBACK TRANSACTION " + JdbcXid.toString(xid));
} catch (SQLException e) {
// ignore (not a two phase commit)
} finally {
JdbcUtils.closeSilently(stat);
}
} catch (SQLException e) { } catch (SQLException e) {
throw convertException(e); throw convertException(e);
} }
...@@ -375,7 +380,7 @@ implements XAConnection, XAResource ...@@ -375,7 +380,7 @@ implements XAConnection, XAResource
physicalConn.commit(); physicalConn.commit();
} else { } else {
stat = physicalConn.createStatement(); stat = physicalConn.createStatement();
stat.execute("COMMIT TRANSACTION TX_" + currentTransactionId); stat.execute("COMMIT TRANSACTION " + JdbcXid.toString(xid));
} }
physicalConn.setAutoCommit(true); physicalConn.setAutoCommit(true);
} catch (SQLException e) { } catch (SQLException e) {
......
...@@ -47,14 +47,14 @@ implements Xid ...@@ -47,14 +47,14 @@ implements Xid
/** /**
* INTERNAL * INTERNAL
*/ */
public String getAsString() { public static String toString(Xid xid) {
StringBuilder buff = new StringBuilder(PREFIX); StringBuilder buff = new StringBuilder(PREFIX);
buff.append('_'). buff.append('_').
append(formatId). append(xid.getFormatId()).
append('_'). append('_').
append(StringUtils.convertBytesToString(branchQualifier)). append(StringUtils.convertBytesToString(xid.getBranchQualifier())).
append('_'). append('_').
append(StringUtils.convertBytesToString(globalTransactionId)); append(StringUtils.convertBytesToString(xid.getGlobalTransactionId()));
return buff.toString(); return buff.toString();
} }
...@@ -92,7 +92,7 @@ implements Xid ...@@ -92,7 +92,7 @@ implements Xid
* INTERNAL * INTERNAL
*/ */
public String toString() { public String toString() {
return getTraceObjectName() + ": " + getAsString(); return getTraceObjectName() + ": " + toString(this);
} }
} }
...@@ -86,21 +86,26 @@ public class TraceObject { ...@@ -86,21 +86,26 @@ public class TraceObject {
*/ */
protected static final int XA_DATA_SOURCE = 13; protected static final int XA_DATA_SOURCE = 13;
/**
* The trace type id for XA resources.
*/
protected static final int XA_RESOURCE = 14;
/** /**
* The trace type id for transaction ids. * The trace type id for transaction ids.
*/ */
protected static final int XID = 14; protected static final int XID = 15;
/** /**
* The trace type id for array objects. * The trace type id for array objects.
*/ */
protected static final int ARRAY = 15; protected static final int ARRAY = 16;
private static final int LAST = ARRAY + 1; private static final int LAST = ARRAY + 1;
private static final int[] ID = new int[LAST]; private static final int[] ID = new int[LAST];
private static final String[] PREFIX = { private static final String[] PREFIX = {
"call", "conn", "dbMeta", "prep", "rs", "rsMeta", "sp", "ex", "stat", "blob", "clob", "pMeta", "call", "conn", "dbMeta", "prep", "rs", "rsMeta", "sp", "ex", "stat", "blob", "clob", "pMeta",
"ds", "xads", "xid", "ar" "ds", "xads", "xares", "xid", "ar"
}; };
private Trace trace; private Trace trace;
......
/*
* Copyright 2004-2010 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.jdbcx;
import java.util.concurrent.atomic.AtomicInteger;
import javax.transaction.xa.Xid;
import org.h2.util.MathUtils;
import org.h2.util.Utils;
/**
* A simple Xid implementation.
*/
public class SimpleXid implements Xid {
private static AtomicInteger next = new AtomicInteger();
private final int formatId;
private final byte[] branchQualifier;
private final byte[] globalTransactionId;
private SimpleXid(int formatId, byte[] branchQualifier, byte[] globalTransactionId) {
this.formatId = formatId;
this.branchQualifier = branchQualifier;
this.globalTransactionId = globalTransactionId;
}
public static SimpleXid createRandom() {
int formatId = next.getAndIncrement();
byte[] bq = new byte[MAXBQUALSIZE];
MathUtils.randomBytes(bq);
byte[] gt = new byte[MAXGTRIDSIZE];
MathUtils.randomBytes(gt);
return new SimpleXid(formatId, bq, gt);
}
public byte[] getBranchQualifier() {
return branchQualifier;
}
public int getFormatId() {
return formatId;
}
public byte[] getGlobalTransactionId() {
return globalTransactionId;
}
public int hashCode() {
return formatId;
}
public boolean equals(Object other) {
if (other instanceof Xid) {
Xid xid = (Xid) other;
if (xid.getFormatId() == formatId) {
if (Utils.compareNotNull(branchQualifier, xid.getBranchQualifier()) == 0) {
if (Utils.compareNotNull(globalTransactionId, xid.getGlobalTransactionId()) == 0) {
return true;
}
}
}
}
return false;
}
public String toString() {
return "xid:" + formatId;
}
}
...@@ -215,10 +215,10 @@ public class TestXA extends TestBase { ...@@ -215,10 +215,10 @@ public class TestXA extends TestBase {
Xid xid2 = null; Xid xid2 = null;
if (useOneDatabase) { if (useOneDatabase) {
xid1 = new TestXid(1); xid1 = SimpleXid.createRandom();
xid2 = new TestXid(2); xid2 = SimpleXid.createRandom();
} else { } else {
xid1 = new TestXid(1); xid1 = SimpleXid.createRandom();
xid2 = xid1; xid2 = xid1;
} }
......
...@@ -7,12 +7,15 @@ ...@@ -7,12 +7,15 @@
package org.h2.test.jdbcx; package org.h2.test.jdbcx;
import java.sql.Connection; import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.XAConnection; import javax.sql.XAConnection;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import org.h2.jdbcx.JdbcDataSource; import org.h2.jdbcx.JdbcDataSource;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.JdbcUtils;
/** /**
* A simple XA test. * A simple XA test.
...@@ -28,7 +31,83 @@ public class TestXASimple extends TestBase { ...@@ -28,7 +31,83 @@ public class TestXASimple extends TestBase {
TestBase.createCaller().init().test(); TestBase.createCaller().init().test();
} }
public void test() throws SQLException { public void test() throws Exception {
testTwoPhase();
testSimple();
}
private void testTwoPhase() throws Exception {
if (config.memory) {
return;
}
int todo;
// testTwoPhase(false, true);
// testTwoPhase(false, false);
testTwoPhase(true, true);
testTwoPhase(true, false);
}
private void testTwoPhase(boolean shutdown, boolean commit) throws Exception {
deleteDb("xaSimple");
JdbcDataSource ds = new JdbcDataSource();
ds.setPassword(getPassword());
ds.setUser("sa");
// ds.setURL(getURL("xaSimple", true) + ";trace_level_system_out=3");
ds.setURL(getURL("xaSimple", true));
XAConnection xa;
xa = ds.getXAConnection();
Connection conn;
conn = xa.getConnection();
Statement stat = conn.createStatement();
stat.execute("create table test(id int primary key, name varchar(255))");
Xid xid = SimpleXid.createRandom();
xa.getXAResource().start(xid, XAResource.TMNOFLAGS);
conn.setAutoCommit(false);
stat.execute("insert into test values(1, 'Hello')");
xa.getXAResource().end(xid, XAResource.TMSUCCESS);
xa.getXAResource().prepare(xid);
if (shutdown) {
shutdown(ds);
}
JdbcUtils.closeSilently(xa);
xa = ds.getXAConnection();
Xid[] list = xa.getXAResource().recover(XAResource.TMSTARTRSCAN);
assertEquals(1, list.length);
assertTrue(xid.equals(list[0]));
if (commit) {
xa.getXAResource().commit(list[0], false);
} else {
xa.getXAResource().rollback(list[0]);
}
if (shutdown) {
shutdown(ds);
}
JdbcUtils.closeSilently(xa);
xa = ds.getXAConnection();
list = xa.getXAResource().recover(XAResource.TMSTARTRSCAN);
assertEquals(0, list.length);
conn = xa.getConnection();
ResultSet rs;
rs = conn.createStatement().executeQuery("select * from test");
if (commit) {
assertTrue(rs.next());
} else {
assertFalse(rs.next());
}
JdbcUtils.closeSilently(xa);
}
private void shutdown(JdbcDataSource ds) throws SQLException {
Connection conn = ds.getConnection();
conn.createStatement().execute("shutdown immediately");
JdbcUtils.closeSilently(conn);
}
public void testSimple() throws SQLException {
deleteDb("xaSimple1"); deleteDb("xaSimple1");
deleteDb("xaSimple2"); deleteDb("xaSimple2");
...@@ -74,4 +153,5 @@ public class TestXASimple extends TestBase { ...@@ -74,4 +153,5 @@ public class TestXASimple extends TestBase {
deleteDb("xaSimple2"); deleteDb("xaSimple2");
} }
} }
/*
* Copyright 2004-2010 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: James Devenish
*/
package org.h2.test.jdbcx;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.NumberFormat;
import javax.transaction.xa.Xid;
/**
* A utility class for the basic XA test.
*/
public class TestXid implements Xid {
private static final NumberFormat NF;
private static int fXidCounter;
private int fFormatId;
private byte[] fGlobalTransactionId;
private byte[] fBranchQualifier;
private int fId;
private long fCreationTime;
static {
NumberFormat nf = NumberFormat.getIntegerInstance();
nf.setMaximumIntegerDigits(5);
nf.setMinimumIntegerDigits(5);
nf.setGroupingUsed(false);
NF = nf;
}
public TestXid() {
this(1);
}
public TestXid(int branch) {
synchronized (TestXid.class) {
fXidCounter++;
fId = fXidCounter;
}
fCreationTime = System.currentTimeMillis();
String host;
try {
InetAddress ia = InetAddress.getLocalHost();
host = ia.getHostName();
} catch (UnknownHostException e) {
host = "localhost";
}
fFormatId = 0;
fGlobalTransactionId = new byte[MAXGTRIDSIZE];
fBranchQualifier = new byte[MAXBQUALSIZE];
StringBuilder sb;
byte[] ba;
sb = new StringBuilder();
sb.append(host);
sb.append(":");
sb.append(fId);
sb.append(":");
sb.append(fCreationTime);
// System.out.println("global transaction id: " + sb.toString());
ba = sb.toString().getBytes();
for (int i = 0; i < MAXGTRIDSIZE; i++) {
fGlobalTransactionId[i] = (byte) ' ';
}
for (int i = 0; i < ba.length; i++) {
fGlobalTransactionId[i] = ba[i];
}
sb = new StringBuilder(NF.format(branch));
// System.out.println("branch qualifier: " + sb.toString());
ba = sb.toString().getBytes();
for (int i = 0; i < MAXBQUALSIZE; i++) {
fBranchQualifier[i] = (byte) ' ';
}
for (int i = 0; i < ba.length; i++) {
fBranchQualifier[i] = ba[i];
}
}
/**
* This method is called when executing this application.
*
* @param args the command line parameters
*/
public static void main(String... args) {
new TestXid();
}
public int getFormatId() {
return fFormatId;
}
public byte[] getGlobalTransactionId() {
return fGlobalTransactionId;
}
public byte[] getBranchQualifier() {
return fBranchQualifier;
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论