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 ma...@apache.org on 2009/08/31 23:29:58 UTC

svn commit: r809750 - in /db/derby/code/branches/10.3: ./ java/drda/org/apache/derby/impl/drda/ java/engine/org/apache/derby/iapi/jdbc/ java/engine/org/apache/derby/impl/jdbc/ java/engine/org/apache/derby/jdbc/ java/testing/org/apache/derbyTesting/func...

Author: mamta
Date: Mon Aug 31 21:29:57 2009
New Revision: 809750

URL: http://svn.apache.org/viewvc?rev=809750&view=rev
Log:
DERBY-4053 

Merging DERBY-4053 into 10.3 codeline. Additionally merging partial DERBY-3319 and partial DERBY-2855 because of the code dependency of DERBY-4053 changes


Modified:
    db/derby/code/branches/10.3/   (props changed)
    db/derby/code/branches/10.3/java/drda/org/apache/derby/impl/drda/Database.java
    db/derby/code/branches/10.3/java/drda/org/apache/derby/impl/drda/XADatabase.java
    db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/jdbc/BrokeredConnection.java
    db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/jdbc/BrokeredConnectionControl.java
    db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/jdbc/EngineConnection.java
    db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java
    db/derby/code/branches/10.3/java/engine/org/apache/derby/jdbc/EmbedPooledConnection.java
    db/derby/code/branches/10.3/java/engine/org/apache/derby/jdbc/EmbedXAConnection.java
    db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/XATransactionTest.java
    db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/junit/TestConfiguration.java

Propchange: db/derby/code/branches/10.3/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Aug 31 21:29:57 2009
@@ -1 +1 @@
-/db/derby/code/trunk:552046,788436
+/db/derby/code/trunk:552046,788436,793588

Modified: db/derby/code/branches/10.3/java/drda/org/apache/derby/impl/drda/Database.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.3/java/drda/org/apache/derby/impl/drda/Database.java?rev=809750&r1=809749&r2=809750&view=diff
==============================================================================
--- db/derby/code/branches/10.3/java/drda/org/apache/derby/impl/drda/Database.java (original)
+++ db/derby/code/branches/10.3/java/drda/org/apache/derby/impl/drda/Database.java Mon Aug 31 21:29:57 2009
@@ -70,7 +70,6 @@
 	protected boolean RDBUPDRM_sent = false;	//We have sent that an update
 											// occurred in this transaction
 	protected boolean sendTRGDFTRT = false; // Send package target default value
-
     /**
      * Connection to the database in the embedded engine.
      */
@@ -80,8 +79,6 @@
 	private DRDAStatement currentStatement; // current statement we are working on
 	private Hashtable stmtTable;		// Hash table for storing statements
 
-	boolean forXA = false;
-
 	// constructor
 	/**
 	 * Database constructor
@@ -332,7 +329,12 @@
 			conn.rollback();
 	}
 	/**
-	  * Close the connection and clean up the statement table
+	  * Database close does following cleanup tasks
+	  * 1)Rollback any pending transaction on the Connection object (except 
+	  * for a global-XA Connection obejct) before closing the Connection. 
+	  * Without the rollback, the Connection close will result into an 
+	  * exception if there is a pending transaction on that Connection.
+	  * 2)Clean up the statement table 
 	  * @throws SQLException on conn.close() error to be handled in DRDAConnThread.
 	  */
 	protected void close() throws SQLException
@@ -351,7 +353,8 @@
 				defaultStatement.close();
 			if ((conn != null) && !conn.isClosed())
 			{
-				if (! forXA)
+				//rollback all the pending transactions except global XA trans
+				if (! conn.isInGlobalTransaction())
 				{
 					conn.rollback();
 				}

Modified: db/derby/code/branches/10.3/java/drda/org/apache/derby/impl/drda/XADatabase.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.3/java/drda/org/apache/derby/impl/drda/XADatabase.java?rev=809750&r1=809749&r2=809750&view=diff
==============================================================================
--- db/derby/code/branches/10.3/java/drda/org/apache/derby/impl/drda/XADatabase.java (original)
+++ db/derby/code/branches/10.3/java/drda/org/apache/derby/impl/drda/XADatabase.java Mon Aug 31 21:29:57 2009
@@ -56,7 +56,6 @@
 	XADatabase (String dbName)
 	{
 		super(dbName);
-		forXA = true;
 	}
 
 	/**

Modified: db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/jdbc/BrokeredConnection.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/jdbc/BrokeredConnection.java?rev=809750&r1=809749&r2=809750&view=diff
==============================================================================
--- db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/jdbc/BrokeredConnection.java (original)
+++ db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/jdbc/BrokeredConnection.java Mon Aug 31 21:29:57 2009
@@ -473,6 +473,11 @@
         }
 	}
 
+    /** @see EngineConnection#isInGlobalTransaction() */
+    public boolean isInGlobalTransaction() {
+    	return control.isInGlobalTransaction();
+    }
+
 	/**
 	 *  Set the internal isolation level to use for preparing statements.
 	 *  Subsequent prepares will use this isoalation level

Modified: db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/jdbc/BrokeredConnectionControl.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/jdbc/BrokeredConnectionControl.java?rev=809750&r1=809749&r2=809750&view=diff
==============================================================================
--- db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/jdbc/BrokeredConnectionControl.java (original)
+++ db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/jdbc/BrokeredConnectionControl.java Mon Aug 31 21:29:57 2009
@@ -83,6 +83,12 @@
 	*/
 	public void resetIsolationLevelFlag() throws SQLException;
 
+    /**
+     * Is this a global transaction
+     * @return true if this is a global XA transaction
+     */
+    public boolean isInGlobalTransaction();
+
 	/**
 		Close called on BrokeredConnection. If this call
 		returns true then getRealConnection().close() will be called.

Modified: db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/jdbc/EngineConnection.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/jdbc/EngineConnection.java?rev=809750&r1=809749&r2=809750&view=diff
==============================================================================
--- db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/jdbc/EngineConnection.java (original)
+++ db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/jdbc/EngineConnection.java Mon Aug 31 21:29:57 2009
@@ -40,6 +40,12 @@
      */
     public void setDrdaID(String drdaID);
 
+    /**
+     * Is this a global transaction
+     * @return true if this is a global XA transaction
+     */
+    public boolean isInGlobalTransaction();
+    
     /** 
      * Set the transaction isolation level that will be used for the 
      * next prepare.  Used by network server to implement DB2 style 

Modified: db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java?rev=809750&r1=809749&r2=809750&view=diff
==============================================================================
--- db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java (original)
+++ db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java Mon Aug 31 21:29:57 2009
@@ -2036,6 +2036,11 @@
 		getLanguageConnection().setDrdaID(drdaID);
 	}
 
+    /** @see EngineConnection#isInGlobalTransaction() */
+    public boolean isInGlobalTransaction() {
+    	return false;
+    }
+
 	/**
 		Reset the connection before it is returned from a PooledConnection
 		to a new application request (wrapped by a BrokeredConnection).

Modified: db/derby/code/branches/10.3/java/engine/org/apache/derby/jdbc/EmbedPooledConnection.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.3/java/engine/org/apache/derby/jdbc/EmbedPooledConnection.java?rev=809750&r1=809749&r2=809750&view=diff
==============================================================================
--- db/derby/code/branches/10.3/java/engine/org/apache/derby/jdbc/EmbedPooledConnection.java (original)
+++ db/derby/code/branches/10.3/java/engine/org/apache/derby/jdbc/EmbedPooledConnection.java Mon Aug 31 21:29:57 2009
@@ -369,7 +369,11 @@
 	public void resetIsolationLevelFlag() throws SQLException {
 		realConnection.getLanguageConnection().resetIsolationLevelFlagUsedForSQLandJDBC();
 	}
-	
+
+    /** @see BrokeredConnectionControl#isInGlobalTransaction() */
+    public boolean isInGlobalTransaction() {
+    	return false;
+    }	
 	
 	/**
 		Notify the control class that a SQLException was thrown

Modified: db/derby/code/branches/10.3/java/engine/org/apache/derby/jdbc/EmbedXAConnection.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.3/java/engine/org/apache/derby/jdbc/EmbedXAConnection.java?rev=809750&r1=809749&r2=809750&view=diff
==============================================================================
--- db/derby/code/branches/10.3/java/engine/org/apache/derby/jdbc/EmbedXAConnection.java (original)
+++ db/derby/code/branches/10.3/java/engine/org/apache/derby/jdbc/EmbedXAConnection.java Mon Aug 31 21:29:57 2009
@@ -22,6 +22,7 @@
 package org.apache.derby.jdbc;
 
 import org.apache.derby.impl.jdbc.Util;
+import org.apache.derby.iapi.jdbc.BrokeredConnectionControl;
 import org.apache.derby.iapi.jdbc.EngineConnection;
 import org.apache.derby.iapi.jdbc.ResourceAdapter;
 
@@ -53,6 +54,21 @@
                 xaRes = new EmbedXAResource (this, ra);
 	}
 
+	/** @see BrokeredConnectionControl#isInGlobalTransaction() */
+	public boolean isInGlobalTransaction() {
+		return isGlobal();
+	}	
+
+	/**
+	  * Check if this connection is part of a global XA transaction.
+	  *
+	  * @return {@code true} if the transaction is global, {@code false} if the
+	  * transaction is local
+	*/
+	private boolean isGlobal() {
+		return xaRes.getCurrentXid () != null;
+	}
+
 	/*
 	** XAConnection methods
 	*/

Modified: db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/XATransactionTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/XATransactionTest.java?rev=809750&r1=809749&r2=809750&view=diff
==============================================================================
--- db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/XATransactionTest.java (original)
+++ db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/XATransactionTest.java Mon Aug 31 21:29:57 2009
@@ -48,6 +48,55 @@
   */
 public class XATransactionTest extends BaseJDBCTestCase {
 
+	/**
+	  * This test does following 
+	  * 1)Start the network server
+	  * 2)Start a local xa transaction
+	  * 3)Do not commit the local XA transaction
+	  * 4)Shutdown the network server
+	  * 5)Start the server again
+	  * 
+	  * Before the fix for DERBY-4053 went in, step 4) would not shutdown the
+	  * server properly because of the pending local XA transaction. During the
+	  * server shutdown, we try to close all the open connections but the close 
+	  * on the XA connection results into an exception because there is still a
+	  * pending transaction. That exception is not handled by the server and
+	  * because of that, all the code necessary to shutdown the server is not
+	  * executed. The next time around, step 5), when we try to bring up the
+	  * server again, it ends up hanging
+	  * 2009-07-09 21:21:28.828 GMT : Invalid reply from network server: Insufficient data.
+	  * 2009-07-09 21:21:28.843 GMT : Could not listen on port 1527 on host 127.0.0.1: java.net.BindException: Address already in use: JVM_Bind
+	  * 
+	  * The fix for DERBY-4053 makes sure that before calling close on local XA
+	  * transaction, we first rollback any transaction active on the 
+	  * connection. 
+	 */
+	public void testPendingLocalTranAndServerShutdown() throws Exception {
+        if (usingEmbedded())
+            return;
+        //1)Server must be up already through the Derby junit framework
+        //2)Start a local xa transaction
+        XADataSource xaDataSource = J2EEDataSource.getXADataSource();
+        XAConnection xaconn = xaDataSource.getXAConnection();
+        XAResource xar = xaconn.getXAResource();
+        Connection conn = xaconn.getConnection();
+        Statement s = conn.createStatement();
+        s.executeUpdate("create table tab(i int)");
+        s.executeUpdate("insert into tab values (1),(2),(3),(4)");
+        conn.commit();
+        conn.setAutoCommit(false);
+        ResultSet rs = s.executeQuery("select * from tab");
+        rs.next();
+        //3)Do not commit this pending local XA transaction
+    	
+        //4)Shutdown the network server
+        //bring the server down while the local xa transaction is still active
+        TestConfiguration.getCurrent().stopNetworkServer();
+        
+        //5)Start the server again
+        TestConfiguration.getCurrent().startNetworkServer();
+	}
+
     public void testGlobalXIDinTransactionTable() throws Exception {
         Statement stm = getConnection().createStatement();
         stm.execute("create table XATT2 (i int, text char(10))");

Modified: db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/junit/TestConfiguration.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/junit/TestConfiguration.java?rev=809750&r1=809749&r2=809750&view=diff
==============================================================================
--- db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/junit/TestConfiguration.java (original)
+++ db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/junit/TestConfiguration.java Mon Aug 31 21:29:57 2009
@@ -20,6 +20,10 @@
 package org.apache.derbyTesting.junit;
 
 import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.net.InetAddress;
 import java.security.*;
 import java.sql.Connection;
 import java.sql.SQLException;
@@ -27,6 +31,8 @@
 import java.util.ArrayList;
 import java.util.Hashtable;
 
+import org.apache.derby.drda.NetworkServerControl;
+
 import junit.extensions.TestSetup;
 import junit.framework.Assert;
 import junit.framework.Test;
@@ -68,7 +74,16 @@
     public final static String DEFAULT_SSL = "off";
 
     public  final   static  String  TEST_DBO = "TEST_DBO";
-            
+    
+    private FileOutputStream serverOutput;
+
+    /** Sleep for 500 ms before pinging the network server (again) */
+    private static final int SLEEP_TIME = 1000;
+
+    /* Network Server Control */
+    private NetworkServerControl networkServerController;
+    private NetworkServerControl networkServer;            
+
     /**
      * Keys to use to look up values in properties files.
      */
@@ -1113,7 +1128,84 @@
              BaseJDBCTestCase.assertSQLState("Engine shutdown", "XJ015", e);
         }
     }    
+    
     /**
+      * stops the Network server for this configuration.
+      *
+      */
+     public void stopNetworkServer() {
+         try {
+             NetworkServerControl networkServer = new NetworkServerControl();
+             networkServer.shutdown();
+             if (serverOutput != null) {
+                 serverOutput.close();
+             }
+         } catch(Exception e) {
+             SQLException se = new SQLException("Error shutting down server");
+             se.initCause(e);
+         }
+     }
+ 
+    /**
+      * starts the Networs server for this configuration.
+      *
+      */
+     public void startNetworkServer() throws SQLException
+     {
+         Exception failException = null;
+         try {
+ 
+            NetworkServerControl networkServer =
+                      new NetworkServerControl(InetAddress.getByName("localhost"), port);
+            serverOutput = (FileOutputStream)
+             AccessController.doPrivileged(new PrivilegedAction() {
+ 	                public Object run() {
+ 	                    File logs = new File("logs");
+ 	                    logs.mkdir();
+ 	                    File console = new File(logs, "serverConsoleOutput.log");
+ 	                    FileOutputStream fos = null;
+ 	                    try {
+ 	                        fos = new FileOutputStream(console.getPath(), true);
+ 	                    } catch (FileNotFoundException ex) {
+ 	                        ex.printStackTrace();
+ 	                    }
+ 	                    return fos;
+ 	                }
+ 	            });
+ 	
+ 	            networkServer.start(new PrintWriter(serverOutput));
+ 	
+ 	            // Wait for the network server to start
+ 	            boolean started = false;
+ 	            int retries = 10;         // Max retries = max seconds to wait
+ 	
+ 	            while (!started && retries > 0) {
+ 	                try {
+ 	                    // Sleep 1 second and then ping the network server
+ 	                    Thread.sleep(SLEEP_TIME);
+ 	                    networkServer.ping();
+ 	
+ 	                    // If ping does not throw an exception the server has started
+ 	                    started = true;
+ 	                } catch(Exception e) {
+ 	                    retries--;
+ 	                    failException = e;
+ 	                 }
+ 	
+ 	             }
+ 	
+ 	            // Check if we got a reply on ping
+ 	            if (!started) {
+ 	                 throw failException;
+ 	            }
+ 	        } catch (Exception e) {
+ 	            SQLException se = new SQLException("Error starting network  server");
+ 	            se.initCause(failException);
+ 	            throw se;
+ 	      }
+ 	    }
+
+     /**
      * Set the verbosity, i.e., whether debug statements print.
      */
     public void	setVerbosity( boolean isChatty )	{ isVerbose = isChatty; }