You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by km...@apache.org on 2012/02/28 18:43:44 UTC
svn commit: r1294744 - in /db/derby/code/branches/10.6: ./
java/engine/org/apache/derby/jdbc/
java/testing/org/apache/derbyTesting/functionTests/master/
java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/
Author: kmarsden
Date: Tue Feb 28 17:43:43 2012
New Revision: 1294744
URL: http://svn.apache.org/viewvc?rev=1294744&view=rev
Log:
DERBY-5552 Derby threads hanging when using ClientXADataSource and a deadlock or lock timeout occurs
Code patch contributed by Brett Bergquist - brett at thebergquistfamily dot com
Derby will no longer null out the connection on lock timeout or deadlock.
I added test to verify proper behavior for the conneciton and transaction
state after the lock timeout occurs.
Modified:
db/derby/code/branches/10.6/ (props changed)
db/derby/code/branches/10.6/java/engine/org/apache/derby/jdbc/XATransactionState.java
db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/master/xaSimpleNegative.out
db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/XATest.java
Propchange: db/derby/code/branches/10.6/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Feb 28 17:43:43 2012
@@ -1,4 +1,4 @@
-/db/derby/code/branches/10.7:1140196
+/db/derby/code/branches/10.7:1140196,1294731
/db/derby/code/branches/10.8:1209227-1209228,1209284
-/db/derby/code/trunk:938547,938796,938959,939231,940462,940469,941627,942031,942286,942476,942480,942587,944152,946794,948045,948069,951346,951366,952138,952237,952581,954344,954421,954544,954748,955001,955540,955634,956075,956234,956445,956569,956659,957260,957902,958163,958257,958264,958508,958522,958555,958618,958939,959550,961892,962716,963206,963705,964039,964115,964402,965647,966393,967201,967304,980089,980684,986689,986834,987539,989099,990292,997325,998170,999119,999479,999485,1002291,1002682,1002853,1021426,1024511,1024528,1025615,1025795,1028716,1030043,1033485,1033864,1035164,1038514,1040658,1053724,1055169,1062096,1063809,1065061,1067250,1069661,1071886,1078461,1081455,1097247,1103681,1103718,1136363,1138341,1138444,1141924,1164370,1203050,1207729,1208775
+/db/derby/code/trunk:938547,938796,938959,939231,940462,940469,941627,942031,942286,942476,942480,942587,944152,946794,948045,948069,951346,951366,952138,952237,952581,954344,954421,954544,954748,955001,955540,955634,956075,956234,956445,956569,956659,957260,957902,958163,958257,958264,958508,958522,958555,958618,958939,959550,961892,962716,963206,963705,964039,964115,964402,965647,966393,967201,967304,980089,980684,986689,986834,987539,989099,990292,997325,998170,999119,999479,999485,1002291,1002682,1002853,1021426,1024511,1024528,1025615,1025795,1028716,1030043,1033485,1033864,1035164,1038514,1040658,1053724,1055169,1062096,1063809,1065061,1067250,1069661,1071886,1078461,1081455,1097247,1103681,1103718,1136363,1138341,1138444,1141924,1164370,1203050,1207729,1208775,1293494
/db/derby/docs/trunk:954344
Modified: db/derby/code/branches/10.6/java/engine/org/apache/derby/jdbc/XATransactionState.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.6/java/engine/org/apache/derby/jdbc/XATransactionState.java?rev=1294744&r1=1294743&r2=1294744&view=diff
==============================================================================
--- db/derby/code/branches/10.6/java/engine/org/apache/derby/jdbc/XATransactionState.java (original)
+++ db/derby/code/branches/10.6/java/engine/org/apache/derby/jdbc/XATransactionState.java Tue Feb 28 17:43:43 2012
@@ -147,8 +147,9 @@ final class XATransactionState extends C
if (se.getSeverity() == ExceptionSeverity.TRANSACTION_SEVERITY) {
synchronized (this) {
- // disable use of the connection until it is cleaned up.
- conn.setApplicationConnection(null);
+ // prior to the DERBY-5552 fix, we would disable the connection
+ // here with conn.setApplicationConnection(null);
+ // which could cause a NPE
notifyAll();
associationState = TRO_FAIL;
if (SQLState.DEADLOCK.equals(se.getMessageId()))
Modified: db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/master/xaSimpleNegative.out
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/master/xaSimpleNegative.out?rev=1294744&r1=1294743&r2=1294744&view=diff
==============================================================================
--- db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/master/xaSimpleNegative.out (original)
+++ db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/master/xaSimpleNegative.out Tue Feb 28 17:43:43 2012
@@ -199,7 +199,9 @@ A |B
ERROR 40XL1: A lock could not be obtained within the time requested
ij(XA)> -- ERROR: should have no connection underneath
select * from APP.negative;
-ERROR 08003: No current connection.
+A |B
+----------------------
+ERROR 40XL1: A lock could not be obtained within the time requested
ij(XA)> -- ERROR: should have no connection underneath and xid 2 is gone
xa_end xa_suspend 2;
IJ ERROR: XA_RBTIMEOUT
Modified: db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/XATest.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/XATest.java?rev=1294744&r1=1294743&r2=1294744&view=diff
==============================================================================
--- db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/XATest.java (original)
+++ db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/XATest.java Tue Feb 28 17:43:43 2012
@@ -21,6 +21,7 @@
package org.apache.derbyTesting.functionTests.tests.jdbcapi;
+
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -41,13 +42,17 @@ import junit.framework.TestSuite;
import org.apache.derbyTesting.junit.BaseJDBCTestCase;
import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
+import org.apache.derbyTesting.junit.DatabasePropertyTestSetup;
import org.apache.derbyTesting.junit.J2EEDataSource;
import org.apache.derbyTesting.junit.JDBC;
import org.apache.derbyTesting.junit.TestConfiguration;
+import org.apache.derbyTesting.junit.Utilities;
import org.apache.derbyTesting.junit.XATestUtil;
public class XATest extends BaseJDBCTestCase {
+ public static final String LOCKTIMEOUT="40XL1";
+
public XATest(String name) {
super(name);
@@ -1129,6 +1134,99 @@ public class XATest extends BaseJDBCTest
doXATempTableD4731Work(true, true, XATestUtil.getXid(998, 10, 50));
}
+ /**
+ * DERBY-5552 Check that lock timeout does not destroy connection
+ * during an XA Transaction.
+ *
+ * @throws SQLException
+ * @throws XAException
+ */
+ public void testXALockTimeout() throws SQLException, XAException {
+ XADataSource xads = J2EEDataSource.getXADataSource();
+ J2EEDataSource.setBeanProperty(xads, "databaseName", "wombat");
+
+ // Get the first connection and lock table in
+ // xa transaction
+ XAConnection xaconn = xads.getXAConnection();
+ XAResource xar = xaconn.getXAResource();
+ Xid xid = XATestUtil.getXid(998,10,50);
+
+ Connection conn = xaconn.getConnection();
+ Statement s = conn.createStatement();
+ xar.start(xid, XAResource.TMNOFLAGS);
+ s.executeUpdate("INSERT INTO TABLT VALUES(2)");
+
+ // Get a second connection and global xact
+ // and try to select causing lock timeout
+ XAConnection xaconn2 = xads.getXAConnection();
+ XAResource xar2 = xaconn2.getXAResource();
+ Xid xid2 = XATestUtil.getXid(999,11,51);
+ Connection conn2 = xaconn2.getConnection();
+ // Set to serializable so we get lock timeout
+ conn2.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
+ xar2.start(xid2, XAResource.TMNOFLAGS);
+ Statement s2 = conn2.createStatement();
+ s2.executeUpdate("INSERT INTO TABLT VALUES(3)");
+ assertGlobalXactCount(2);
+ try {
+ ResultSet rs = s2.executeQuery("SELECT * FROM TABLT");
+ fail("Should have gotten lock timeout error: " + LOCKTIMEOUT);
+ } catch (SQLException se) {
+ assertSQLState(LOCKTIMEOUT,se);
+ }
+ // After the lock timeout we just have one global transaction.
+ // lock timeout implicitly rolled back xid2
+ assertGlobalXactCount(1);
+ assertConnOK(conn);
+ // DERBY-5552 Make sure connection is ok after lock timeout
+ assertConnOK(conn2);
+ //Should be able to end and commit xid1
+ xar.end(xid, XAResource.TMSUCCESS);
+ xar.prepare(xid);
+ xar.commit(xid, false);
+
+ // xid2 should have already been rolled back so end should fail
+ try {
+ xar2.end(xid2, XAResource.TMSUCCESS);
+ fail("Should have gotten exception ending xid2");
+ } catch (XAException xae) {
+ //xae.printStackTrace();
+ assertEquals(XAException.XA_RBTIMEOUT, xae.errorCode);
+
+ }
+
+ // Should have no locks on TABLT
+ Statement drops = createStatement();
+ drops.executeUpdate("DROP TABLE TABLT");
+ // verify there are no more global transactions
+ assertGlobalXactCount(0);
+
+ // Need to explicitly rollback xid2 as it ended with
+ // an implicit rollback XA_RBTIMEOUT
+ xar2.rollback(xid2);
+
+ // Make sure both connections can be used to make a new global xact
+ xar.start(xid, XAResource.TMNOFLAGS);
+ s.executeUpdate("CREATE TABLE TABLT (I INT)");
+ s.executeUpdate("INSERT INTO TABLT VALUES(1)");
+ xar.end(xid, XAResource.TMSUCCESS);
+ xar.prepare(xid);
+ xar.commit(xid, false);
+
+ // now the other connection ..
+ xar2.start(xid2, XAResource.TMNOFLAGS);
+ s2.executeUpdate("INSERT INTO TABLT VALUES(2)");
+ xar2.end(xid2, XAResource.TMSUCCESS);
+ xar.prepare(xid2);
+ xar.commit(xid2, false);
+ assertGlobalXactCount(0);
+ conn.close();
+ xaconn.close();
+ conn2.close();
+ xaconn2.close();
+
+ }
+
/**
* The two cases for DERBY-4371 do essentially the same thing. Except doing
@@ -1267,11 +1365,50 @@ public class XATest extends BaseJDBCTest
*/
protected void decorateSQL(Statement s) throws SQLException {
XATestUtil.createXATransactionView(s);
+ // Table for lock timeout test
+ s.executeUpdate("CREATE TABLE TABLT (I INT)");
+ s.executeUpdate("INSERT INTO TABLT VALUES(1)");
}
};
}
-
+
+ /**
+ * Excecute a simple SQL statement to assert that the connection is valid
+ * @param conn Connection to check
+ * @throws SQLException on error
+ */
+ private static void assertConnOK(Connection conn) throws SQLException{
+ Statement s = conn.createStatement();
+ ResultSet rs = s.executeQuery("VALUES(1)");
+ JDBC.assertSingleValueResultSet(rs, "1");
+ }
+
+
+ /**
+ * Verify the expected number of global transactions.
+ * Run test with -Dderby.tests.debug to see the full transaction table on the
+ * console
+ *
+ * @param expectedCount expected number of global transaction
+ * @throws SQLException on error
+ */
+ private void assertGlobalXactCount(int expectedCount ) throws SQLException {
+ Connection conn = openDefaultConnection();
+ Statement s = conn.createStatement();
+ ResultSet rs = s.executeQuery(
+ "SELECT COUNT(*) FROM syscs_diag.transaction_table WHERE GLOBAL_XID IS NOT NULL");
+ rs.next();
+ int count = rs.getInt(1);
+ if (TestConfiguration.getCurrent().isVerbose()) {
+ System.out.println("assertGlobalXactCount(" + expectedCount +
+ "): Full Transaction Table ...");
+ Utilities.showResultSet(s.executeQuery(
+ "SELECT * FROM syscs_diag.transaction_table"));
+ }
+ assertTrue("Expected " + expectedCount + "global transactions but saw " + count, expectedCount == count);
+ }
+
/**
* Runs the test fixtures in embedded and client.
*
@@ -1287,7 +1424,8 @@ public class XATest extends BaseJDBCTest
suite.addTest(TestConfiguration
.clientServerDecorator(baseSuite("XATest:client")));
- return suite;
+
+ return DatabasePropertyTestSetup.setLockTimeouts(suite, 3, 5);
}
}