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 ka...@apache.org on 2007/03/12 09:40:07 UTC

svn commit: r517131 - in /db/derby/code/trunk/java/drda/org/apache/derby/impl/drda: DRDAConnThread.java DRDAXAProtocol.java

Author: kahatlen
Date: Mon Mar 12 01:40:06 2007
New Revision: 517131

URL: http://svn.apache.org/viewvc?view=rev&rev=517131
Log:
DERBY-2220: Uncommitted transactions executed through XAResource will
hold locks after the application terminates (or crashes during the
transaction).

Abort the global transaction on a derby server when the network socket
is closed.

Patch contributed by Julius Stroffek.

Modified:
    db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java
    db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAXAProtocol.java

Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java?view=diff&rev=517131&r1=517130&r2=517131
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java (original)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java Mon Mar 12 01:40:06 2007
@@ -7556,6 +7556,12 @@
 	{
 		if (session == null)
 			return;
+
+        /* DERBY-2220: Rollback the current XA transaction if it is
+           still associated with the connection. */
+        if (xaProto != null)
+            xaProto.rollbackCurrentTransaction();
+
 		server.removeFromSessionTable(session.connNum);
 		try {
 			session.close();

Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAXAProtocol.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAXAProtocol.java?view=diff&rev=517131&r1=517130&r2=517131
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAXAProtocol.java (original)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAXAProtocol.java Mon Mar 12 01:40:06 2007
@@ -37,6 +37,9 @@
 	private DRDAConnThread connThread;
 	private DDMReader reader;
 	private DDMWriter writer;
+    /** Holds the Xid of the global transaction associated with
+      * the corresponding DRDAConnThread (and connection itself). */
+    private Xid xid;
 
 
 	DRDAXAProtocol(DRDAConnThread connThread)
@@ -44,7 +47,7 @@
 		this.connThread = connThread;
 		reader = connThread.getReader();
 		writer = connThread.getWriter();
-
+        xid = null;
 	}
 
 
@@ -142,7 +145,7 @@
 				break;
 			case CodePoint.SYNCTYPE_ROLLBACK:
 				//rollback sync type
-				rollbackTransaction(xid);
+				rollbackTransaction(xid, true);
 				break;
 			case CodePoint.SYNCTYPE_INDOUBT:
 				//recover sync type
@@ -239,6 +242,7 @@
 		try {
 			if (xid.getFormatId() != -1)
 				xaResource.start(xid,xaflags);
+            this.xid = xid;
 		} catch (XAException xe)
 		{
 			xaRetVal = processXAException(xe);
@@ -319,24 +323,29 @@
 	}
 
 	/**
-	 * Rollback transaction
+	 * Rollback transaction. Optionally send SYNCCRD response.
 	 * @param xid  Xid for rollback for global transaction.
 	 *             If xid formatid is -1 it represents a local transaction
+     * @param sendSYNCCRD Indicates whether the function should
+     *                    send a SYNCCRD response
 	 */
-	private void rollbackTransaction(Xid xid) throws DRDAProtocolException
+	private void rollbackTransaction(Xid xid, boolean sendSYNCCRD) throws DRDAProtocolException
 	{
 		boolean local  = ( xid.getFormatId() == -1);
 		if (local)
-			rollbackLocalTransaction();
+			rollbackLocalTransaction(sendSYNCCRD);
 		else
-			rollbackXATransaction(xid);
+			rollbackXATransaction(xid, sendSYNCCRD);
 	}
 	
 	/**
-	 * Rollback a local transaction
+	 * Rollback a local transaction. Optionally send SYNCCRD response.
 	 *
+     * @param sendSYNCCRD Indicates whether the function should
+     *                    send a SYNCCRD response
+	 * @throws DRDAProtocolException
 	 */
-	private void rollbackLocalTransaction() throws DRDAProtocolException
+	private void rollbackLocalTransaction(boolean sendSYNCCRD) throws DRDAProtocolException
 	{
 		int xaRetVal = XAResource.XA_OK;
 		try {
@@ -351,18 +360,21 @@
 			}
 			
 		}
-		writeSYNCCRD(CodePoint.SYNCTYPE_COMMITTED, 
-					 xaRetVal, null);
-
+        if (sendSYNCCRD) {
+            writeSYNCCRD(CodePoint.SYNCTYPE_COMMITTED,
+                         xaRetVal, null);
+        }
 	}
 
 	/**
-	 *  Rollback the xa transaction. Send SYNCCRD response.
+	 *  Rollback the xa transaction. Optionally send SYNCCRD response.
 	 * 
 	 *  @param xid - XID 
+     *  @param sendSYNCCRD Indicates whether the function should
+     *                     send a SYNCCRD response
 	 *  @throws DRDAProtocolException
 	 */
-	private void rollbackXATransaction(Xid xid) throws DRDAProtocolException
+	private void rollbackXATransaction(Xid xid, boolean sendSYNCCRD) throws DRDAProtocolException
 	{
 		XAResource xaResource = getXAResource();
 		int xaRetVal = xaResource.XA_OK;
@@ -377,9 +389,10 @@
 		{
 			xaRetVal = processXAException(xe);
 		}
-		writeSYNCCRD(CodePoint.SYNCTYPE_ROLLBACK,
-					 xaRetVal, null);
-		
+        if (sendSYNCCRD) {
+            writeSYNCCRD(CodePoint.SYNCTYPE_ROLLBACK,
+                         xaRetVal, null);
+        }
 	}
 
 	/**
@@ -396,6 +409,7 @@
 
 		try {
 			xaResource.end(xid,xaflags);
+            xid = null;
 			if (SanityManager.DEBUG)
 			{
 				connThread.trace("ended XA transaction. xid =  " + xid +
@@ -658,15 +672,44 @@
 		return xaRetVal;
 	}
 
-}
-
-
-
-
-
-
-
-
-
+    /**
+     * This function rollbacks the current global transaction associated
+     * with the XAResource or a local transaction. The function should
+     * be called only in exceptional cases - like client socket
+     * is closed. */
+    void rollbackCurrentTransaction()
+    {
+        if (xid != null) {
+            boolean local  = ( xid.getFormatId() == -1);
+            try {
+                // if the transaction is not local disassociate the transaction from
+                // the connection first because the rollback can not be performed
+                // on a transaction associated with the XAResource
+                try {
+                    if (!local) {
+                        XAResource xaResource = getXAResource();
+                        // this will throw the XAException (because TMFAIL
+                        // will throw an exception)
+                        xaResource.end(xid, XAResource.TMFAIL);
+                    }
+                } catch (XAException e) {
+                    // do not print out the exception generally thrown
+                    // when TMFAIL flag is present
+                    if (e.errorCode < XAException.XA_RBBASE
+                        || e.errorCode > XAException.XA_RBEND) {
+                        connThread.getServer().consoleExceptionPrint(e);
+                    }
+                }
+                rollbackTransaction(xid, false);
+            } catch  (DRDAProtocolException e) {
+                // because we do not dump any DRDA stuff to the socket
+                // the exception can not be thrown in this case
+                // However, we will dump the exception to the console
+                connThread.getServer().consoleExceptionPrint(e);
+            }
+            xid = null;
+        }
+    }
 
+}