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/27 19:02:46 UTC

svn commit: r1294251 - in /db/derby/code/branches/10.8: ./ java/engine/org/apache/derby/jdbc/ java/testing/org/apache/derbyTesting/functionTests/master/ java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ java/testing/org/apache/derbyTest...

Author: kmarsden
Date: Mon Feb 27 18:02:46 2012
New Revision: 1294251

URL: http://svn.apache.org/viewvc?rev=1294251&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.8/   (props changed)
    db/derby/code/branches/10.8/java/engine/org/apache/derby/jdbc/XATransactionState.java
    db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/master/xaSimpleNegative.out
    db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/XATest.java
    db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/junit/Utilities.java

Propchange: db/derby/code/branches/10.8/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Feb 27 18:02:46 2012
@@ -1,2 +1,2 @@
 /db/derby/code/branches/10.7:1061570,1061578,1082235
-/db/derby/code/trunk:1088633,1089795,1091000,1091221,1091285,1092067,1092795,1094315,1094572,1094728,1095247,1096741,1096890,1096991,1097247,1097249,1097460,1097469,1097471,1098033,1101059,1101839,1102620,1102826,1103681,1103718,1103742,1104365,1125305,1126358,1126468,1127825,1127883,1128243,1128942,1129136,1129764,1129797,1130077,1130084,1130632,1130895,1131030,1131272,1132546,1132664,1132747,1132860,1132928,1133304,1133317,1133741,1133752,1134139,1136363,1136371,1136397,1136844,1137213,1138201,1138341,1138444,1138787,1138795,1139449,1139451,1140222,1140744,1141924,1142583,1142635,1145057,1146644,1146915,1146962,1147219,1147242,1147335,1148344,1148354,1148429,1148658,1149054,1149090,1149270,1149482,1149662,1151101,1151612,1158108,1160593,1160597,1161208,1162737,1163131,1163616,1164358,1164370,1164495,1165221,1166313,1167017,1167226,1167470,1169692,1170470,1171227,1171665,1171672,1173446,1173647,1174436,1174646,1176633,1176636,1177589,1179374,1179546,1180790,1180858,1181756,
 1183463,1183503,1183671,1186020,1186691,1189201,1189222,1203050,1203252,1204128,1207729,1208775,1210846,1212541,1213251,1230480,1236887,1239898,1241841,1242098,1242409,1242413,1242460,1242610,1243878,1292109
+/db/derby/code/trunk:1088633,1089795,1091000,1091221,1091285,1092067,1092795,1094315,1094572,1094728,1095247,1096741,1096890,1096991,1097247,1097249,1097460,1097469,1097471,1098033,1101059,1101839,1102620,1102826,1103681,1103718,1103742,1104365,1125305,1126358,1126468,1127825,1127883,1128243,1128942,1129136,1129764,1129797,1130077,1130084,1130632,1130895,1131030,1131272,1132546,1132664,1132747,1132860,1132928,1133304,1133317,1133741,1133752,1134139,1136363,1136371,1136397,1136844,1137213,1138201,1138341,1138444,1138787,1138795,1139449,1139451,1140222,1140744,1141924,1142583,1142635,1145057,1146644,1146915,1146962,1147219,1147242,1147335,1148344,1148354,1148429,1148658,1149054,1149090,1149270,1149482,1149662,1151101,1151612,1158108,1160593,1160597,1161208,1162737,1163131,1163616,1164358,1164370,1164495,1165221,1166313,1167017,1167226,1167470,1169692,1170470,1171227,1171665,1171672,1173446,1173647,1174436,1174646,1176633,1176636,1177589,1179374,1179546,1180790,1180858,1181756,
 1183463,1183503,1183671,1186020,1186691,1189201,1189222,1203050,1203252,1204128,1207729,1208775,1210846,1212541,1213251,1230480,1236887,1239898,1241841,1242098,1242409,1242413,1242460,1242610,1243878,1292109,1293494

Modified: db/derby/code/branches/10.8/java/engine/org/apache/derby/jdbc/XATransactionState.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/engine/org/apache/derby/jdbc/XATransactionState.java?rev=1294251&r1=1294250&r2=1294251&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/engine/org/apache/derby/jdbc/XATransactionState.java (original)
+++ db/derby/code/branches/10.8/java/engine/org/apache/derby/jdbc/XATransactionState.java Mon Feb 27 18:02:46 2012
@@ -148,8 +148,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.8/java/testing/org/apache/derbyTesting/functionTests/master/xaSimpleNegative.out
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/master/xaSimpleNegative.out?rev=1294251&r1=1294250&r2=1294251&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/master/xaSimpleNegative.out (original)
+++ db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/master/xaSimpleNegative.out Mon Feb 27 18:02:46 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.8/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/XATest.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/XATest.java?rev=1294251&r1=1294250&r2=1294251&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/XATest.java (original)
+++ db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/XATest.java Mon Feb 27 18:02:46 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
@@ -1275,11 +1373,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.
      * 
@@ -1295,7 +1432,8 @@ public class XATest extends BaseJDBCTest
 
         suite.addTest(TestConfiguration
                 .clientServerDecorator(baseSuite("XATest:client")));
-        return suite;
+        
+        return DatabasePropertyTestSetup.setLockTimeouts(suite, 3, 5);
     }
 
 }

Modified: db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/junit/Utilities.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/junit/Utilities.java?rev=1294251&r1=1294250&r2=1294251&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/junit/Utilities.java (original)
+++ db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/junit/Utilities.java Mon Feb 27 18:02:46 2012
@@ -137,10 +137,9 @@ public class Utilities {
 
             if (next) {
                 System.out.println(",");
-            } else {
-                System.out.println("};\n");
-            }
+            } 
         }
+        System.out.println("};\n");
     }
 
     /**