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 da...@apache.org on 2007/04/24 00:44:26 UTC

svn commit: r531638 - /db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java

Author: dag
Date: Mon Apr 23 15:44:25 2007
New Revision: 531638

URL: http://svn.apache.org/viewvc?view=rev&rev=531638
Log:
DERBY-1947 OutOfMemoryError after repeated calls to boot and shutdown a database

Committed DERBY-1947-4.diff.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java?view=diff&rev=531638&r1=531637&r2=531638
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java Mon Apr 23 15:44:25 2007
@@ -1141,21 +1141,14 @@
      */
     public void close() throws SQLException {
 		// JDK 1.4 javadoc indicates close on a closed connection is a no-op
-		if (isClosed())
-		   	return;
-
-
-		if (rootConnection == this)
-		{
-			/* Throw error to match DB2/JDBC if a tran is pending in non-autocommit mode */
-			if (!autoCommit && !transactionIsIdle()) {
-				throw newSQLException(SQLState.LANG_INVALID_TRANSACTION_STATE);
-			}
-
-			close(exceptionClose);
+		if (!isClosed() &&
+				(rootConnection == this) && 
+				(!autoCommit && !transactionIsIdle())) {
+			throw newSQLException(
+				SQLState.LANG_INVALID_TRANSACTION_STATE);
 		}
-		else
-			setInactive(); // nested connection
+		
+		close(exceptionClose);
 	}
 
 	// This inner close takes the exception and calls 
@@ -1174,22 +1167,30 @@
 				 * If it isn't active, it's already been closed.
 				 */
 				if (active) {
-					setupContextStack();
-					try {
-						tr.rollback();
-
-						// Let go of lcc reference so it can be GC'ed after
-						// cleanupOnError, the tr will stay around until the
-						// rootConnection itself is GC'ed, which is dependent
-						// on how long the client program wants to hold on to
-						// the Connection object.
+					if (tr.isActive()) {
+						setupContextStack();
+						try {
+							tr.rollback();
+							
+							// Let go of lcc reference so it can be GC'ed after
+							// cleanupOnError, the tr will stay around until the
+							// rootConnection itself is GC'ed, which is dependent
+							// on how long the client program wants to hold on to
+							// the Connection object.
+							tr.clearLcc(); 
+							tr.cleanupOnError(e);
+							
+						} catch (Throwable t) {
+							throw handleException(t);
+						} finally {
+							restoreContextStack();
+						}
+					} else {
+						// DERBY-1947: If another connection has closed down
+						// the database, the transaction is not active, but
+						// the cleanup has not been done yet.
 						tr.clearLcc(); 
 						tr.cleanupOnError(e);
-
-					} catch (Throwable t) {
-						throw handleException(t);
-					} finally {
-						restoreContextStack();
 					}
 				}
 			}
@@ -1211,9 +1212,6 @@
 			if (getTR().isActive()) {
 				return false;
 			}
-
-			setInactive();
-
 		}
 		return true;
 	}
@@ -1608,11 +1606,19 @@
 	 */
 	protected void finalize() throws Throwable 
 	{
-		if (rootConnection == this)
-		{
+		try {
+			// Only close root connections, since for nested
+			// connections, it is not strictly necessary and close()
+			// synchronizes on the root connection which can cause
+			// deadlock with the call to runFinalization from
+			// GenericPreparedStatement#prepareToInvalidate (see
+			// DERBY-1947) on SUN VMs.
+			if (rootConnection == this) {
+				close(exceptionClose);
+			}
+		}
+		finally {
 			super.finalize();
-			if (!isClosed())
-	    		close(exceptionClose);
 		}
 	}