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 {@link JdbcDataSource#getConnection} and {@link
+ * Connection#close}. The statements are registered using
+ * {@link #registerAllocatedStatement} and deallocated in
+ * {@link #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]