proyal 2003/02/14 11:23:27 Modified: datasource/src/java/org/apache/avalon/excalibur/datasource AbstractJdbcConnection.java Jdbc3Connection.java JdbcConnection.java Log: Bugzilla 16893. Patch from Greg Steuck to close all opened Statement objects when a connection is returned to the pool Revision Changes Path 1.22 +78 -5 avalon-excalibur/datasource/src/java/org/apache/avalon/excalibur/datasource/AbstractJdbcConnection.java Index: AbstractJdbcConnection.java =================================================================== RCS file: /home/cvs/avalon-excalibur/datasource/src/java/org/apache/avalon/excalibur/datasource/AbstractJdbcConnection.java,v retrieving revision 1.21 retrieving revision 1.22 diff -u -r1.21 -r1.22 --- AbstractJdbcConnection.java 8 Nov 2002 03:24:27 -0000 1.21 +++ AbstractJdbcConnection.java 14 Feb 2003 19:23:27 -0000 1.22 @@ -13,7 +13,8 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.Iterator; -import java.util.Map; +import java.util.LinkedList; +import java.util.List; import org.apache.avalon.excalibur.pool.Pool; import org.apache.avalon.excalibur.pool.Recyclable; import org.apache.avalon.framework.activity.Disposable; @@ -38,6 +39,17 @@ protected PreparedStatement m_testStatement; protected SQLException m_testException; protected long m_lastUsed = System.currentTimeMillis(); + /** + * Contains Statements created on the original jdbc connection + * between a [EMAIL PROTECTED] JdbcDataSource#getConnection} and [EMAIL PROTECTED] + * Connection#close}. The statements are registered using + * [EMAIL PROTECTED] #registerAllocatedStatement} and deallocated in + * [EMAIL PROTECTED] #close}. LinkedList was chosen because access + * to elements is sequential through Iterator and the number + * of elements is not known in advance. Synchronization is + * done on the Link instance itself. + */ + final private List m_allocatedStatements = new LinkedList(); /** * @deprecated Use the version with keepAlive specified @@ -69,7 +81,10 @@ { try { - m_testStatement = prepareStatement( keepAlive ); + // test statement is allocated directly from the + // underlying connection, it is special and should not + // be closed during recycling session + m_testStatement = m_connection.prepareStatement( keepAlive ); } catch( final SQLException se ) { @@ -108,6 +123,7 @@ m_testException = null; try { + clearAllocatedStatements(); m_connection.clearWarnings(); } catch( SQLException se ) @@ -157,8 +173,65 @@ public void close() throws SQLException { - clearWarnings(); - m_pool.put( this ); + try + { + clearAllocatedStatements(); + clearWarnings(); + m_pool.put( this ); + } + catch ( SQLException se ) + { + // gets rid of connections that throw SQLException during + // clean up + getLogger().error( "Connection could not be recycled", se ); + this.dispose(); + } + } + + /** + * Closes statements that were registered and removes all + * statements from the list of allocated ones. If any statement + * fails to properly close, the rest of the statements is ignored. + * But the registration list if cleared in any case. + * <p> + * Holds m_allocatedStatements locked the whole time. This should + * not be a problem because connections are inherently single + * threaded objects and any attempt to use them from a different + * thread while it is being closed is a violation of the contract. + * + * @throws SQLException of the first Statement.close() + */ + protected void clearAllocatedStatements() throws SQLException + { + synchronized( m_allocatedStatements ) + { + try + { + final Iterator iterator = m_allocatedStatements.iterator(); + while( iterator.hasNext() ) + { + Statement stmt = (Statement) iterator.next(); + stmt.close(); + } + } + finally + { + m_allocatedStatements.clear(); + } + } + } + + /** + * Adds the statement to the list of this connection. Used by + * subclasses to ensure release of statements when connection is + * logically terminated and returned to the pool. + */ + protected void registerAllocatedStatement( Statement stmt ) + { + synchronized( m_allocatedStatements ) + { + m_allocatedStatements.add( stmt ); + } } public void dispose() 1.13 +12 -1 avalon-excalibur/datasource/src/java/org/apache/avalon/excalibur/datasource/Jdbc3Connection.java Index: Jdbc3Connection.java =================================================================== RCS file: /home/cvs/avalon-excalibur/datasource/src/java/org/apache/avalon/excalibur/datasource/Jdbc3Connection.java,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- Jdbc3Connection.java 16 Mar 2002 00:05:40 -0000 1.12 +++ Jdbc3Connection.java 14 Feb 2003 19:23:27 -0000 1.13 @@ -42,6 +42,7 @@ { final Statement temp = m_connection.createStatement(); m_lastUsed = System.currentTimeMillis(); + registerAllocatedStatement( temp ); return temp; } @@ -50,6 +51,7 @@ { final PreparedStatement temp = m_connection.prepareStatement( sql ); m_lastUsed = System.currentTimeMillis(); + registerAllocatedStatement( temp ); return temp; } @@ -58,6 +60,7 @@ { final CallableStatement temp = m_connection.prepareCall( sql ); m_lastUsed = System.currentTimeMillis(); + registerAllocatedStatement( temp ); return temp; } @@ -156,6 +159,7 @@ ); m_lastUsed = System.currentTimeMillis(); + registerAllocatedStatement( temp ); return temp; } @@ -169,6 +173,7 @@ ); m_lastUsed = System.currentTimeMillis(); + registerAllocatedStatement( temp ); return temp; } @@ -182,6 +187,7 @@ ); m_lastUsed = System.currentTimeMillis(); + registerAllocatedStatement( temp ); return temp; } @@ -244,6 +250,7 @@ ); m_lastUsed = System.currentTimeMillis(); + registerAllocatedStatement( temp ); return temp; } @@ -272,6 +279,7 @@ ); m_lastUsed = System.currentTimeMillis(); + registerAllocatedStatement( temp ); return temp; } @@ -284,6 +292,7 @@ ); m_lastUsed = System.currentTimeMillis(); + registerAllocatedStatement( temp ); return temp; } @@ -296,6 +305,7 @@ ); m_lastUsed = System.currentTimeMillis(); + registerAllocatedStatement( temp ); return temp; } @@ -308,6 +318,7 @@ ); m_lastUsed = System.currentTimeMillis(); + registerAllocatedStatement( temp ); return temp; } } 1.9 +7 -1 avalon-excalibur/datasource/src/java/org/apache/avalon/excalibur/datasource/JdbcConnection.java Index: JdbcConnection.java =================================================================== RCS file: /home/cvs/avalon-excalibur/datasource/src/java/org/apache/avalon/excalibur/datasource/JdbcConnection.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- JdbcConnection.java 13 Jun 2002 17:24:50 -0000 1.8 +++ JdbcConnection.java 14 Feb 2003 19:23:27 -0000 1.9 @@ -47,6 +47,7 @@ { final Statement temp = m_connection.createStatement(); m_lastUsed = System.currentTimeMillis(); + registerAllocatedStatement( temp ); return temp; } @@ -55,6 +56,7 @@ { final PreparedStatement temp = m_connection.prepareStatement( sql ); m_lastUsed = System.currentTimeMillis(); + registerAllocatedStatement( temp ); return temp; } @@ -63,6 +65,7 @@ { final CallableStatement temp = m_connection.prepareCall( sql ); m_lastUsed = System.currentTimeMillis(); + registerAllocatedStatement( temp ); return temp; } @@ -161,6 +164,7 @@ ); m_lastUsed = System.currentTimeMillis(); + registerAllocatedStatement( temp ); return temp; } @@ -174,6 +178,7 @@ ); m_lastUsed = System.currentTimeMillis(); + registerAllocatedStatement( temp ); return temp; } @@ -187,6 +192,7 @@ ); m_lastUsed = System.currentTimeMillis(); + registerAllocatedStatement( temp ); return temp; }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]