📄 newpooledconnection.java
字号:
/* * Distributed as part of c3p0 v.0.9.1-pre6 * * Copyright (C) 2005 Machinery For Change, Inc. * * Author: Steve Waldman <swaldman@mchange.com> * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1, as * published by the Free Software Foundation. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software; see the file LICENSE. If not, write to the * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. */package com.mchange.v2.c3p0.impl;import java.util.*;import java.sql.*;import javax.sql.*;import com.mchange.v2.c3p0.*;import com.mchange.v2.c3p0.stmt.*;import com.mchange.v2.c3p0.util.*;import com.mchange.v2.log.*;import java.lang.reflect.Method;import com.mchange.v2.lang.ObjectUtils;import com.mchange.v2.sql.SqlUtils;public final class NewPooledConnection implements PooledConnection{ private final static MLogger logger = MLog.getLogger( NewPooledConnection.class ); //MT: thread-safe post-constructor constants final Connection physicalConnection; final ConnectionTester connectionTester; final boolean autoCommitOnClose; final boolean forceIgnoreUnresolvedTransactions; final boolean supports_setHoldability; final boolean supports_setReadOnly; final boolean supports_setTypeMap; final int dflt_txn_isolation; final String dflt_catalog; final int dflt_holdability; final boolean dflt_readOnly; final Map dflt_typeMap; final ConnectionEventSupport ces; //MT: protected by this' lock GooGooStatementCache scache = null; Throwable invalidatingException = null; int connection_status = ConnectionTester.CONNECTION_IS_OKAY; Set uncachedActiveStatements = new HashSet(); //cached statements are managed by the cache Map resultSetsForStatements = new HashMap(); //for both cached and uncached statements Set metaDataResultSets = new HashSet(); Set rawConnectionResultSets = null; //very rarely used, so we lazy initialize... boolean connection_error_signaled = false; //MT: thread-safe, volatile volatile NewProxyConnection exposedProxy = null; volatile boolean isolation_lvl_nondefault = false; volatile boolean catalog_nondefault = false; volatile boolean holdability_nondefault = false; volatile boolean readOnly_nondefault = false; volatile boolean typeMap_nondefault = false; // public API public NewPooledConnection(Connection con, ConnectionTester connectionTester, boolean autoCommitOnClose, boolean forceIgnoreUnresolvedTransactions) throws SQLException { this.physicalConnection = con; this.connectionTester = connectionTester; this.autoCommitOnClose = autoCommitOnClose; this.forceIgnoreUnresolvedTransactions = forceIgnoreUnresolvedTransactions; this.supports_setHoldability = C3P0ImplUtils.supportsMethod(con, "setHoldability", new Class[]{ Integer.class }); this.supports_setReadOnly = C3P0ImplUtils.supportsMethod(con, "setReadOnly", new Class[]{ Boolean.class }); this.supports_setTypeMap = C3P0ImplUtils.supportsMethod(con, "setTypeMap", new Class[]{ Map.class }); this.dflt_txn_isolation = con.getTransactionIsolation(); this.dflt_catalog = con.getCatalog(); this.dflt_holdability = (supports_setHoldability ? con.getHoldability() : ResultSet.CLOSE_CURSORS_AT_COMMIT); this.dflt_readOnly = (supports_setReadOnly ? carefulCheckReadOnly(con) : false); this.dflt_typeMap = (supports_setTypeMap && (carefulCheckTypeMap(con) == null) ? null : Collections.EMPTY_MAP); this.ces = new ConnectionEventSupport(this); } private static boolean carefulCheckReadOnly(Connection con) { try { return con.isReadOnly(); } catch (Exception e) { if (false) { if (logger.isLoggable(MLevel.FINER)) logger.log(MLevel.FINER, con + " threw an Exception when we tried to check its default " + "read only state. This is not usually a problem! It just means the Connection " + "doesn't support the readOnly property, and c3p0 works around this.", e); } return false; } } private static Map carefulCheckTypeMap(Connection con) { try { return con.getTypeMap(); } catch (Exception e) { if (false) { if (logger.isLoggable(MLevel.FINER)) logger.log(MLevel.FINER, con + " threw an Exception when we tried to check its default " + "type map. This is not usually a problem! It just means the Connection " + "doesn't support the typeMap property, and c3p0 works around this.", e); } return null; } } public synchronized Connection getConnection() throws SQLException { try { //throw new SQLException("NOT IMPLEMENTED"); if ( exposedProxy == null ) { exposedProxy = new NewProxyConnection( physicalConnection, this ); } else {// System.err.println("c3p0 -- Uh oh... getConnection() was called on a PooledConnection when " +// "it had already provided a client with a Connection that has not yet been " +// "closed. This probably indicates a bug in the connection pool!!!"); if ( logger.isLoggable( MLevel.WARNING ) ) logger.warning("c3p0 -- Uh oh... getConnection() was called on a PooledConnection when " + "it had already provided a client with a Connection that has not yet been " + "closed. This probably indicates a bug in the connection pool!!!"); } return exposedProxy; } catch ( Exception e ) { SQLException sqle = handleThrowable( e ); throw sqle; } } public synchronized int getConnectionStatus() { return connection_status; } public synchronized void closeAll() throws SQLException { try { closeAllCachedStatements(); } catch ( Exception e ) { SQLException sqle = handleThrowable( e ); throw sqle; } } public synchronized void close() throws SQLException { close( null ); } public void addConnectionEventListener(ConnectionEventListener cel) { ces.addConnectionEventListener( cel ); } public void removeConnectionEventListener(ConnectionEventListener cel) { ces.removeConnectionEventListener( cel ); } // api for C3P0PooledConnectionPool public synchronized void initStatementCache( GooGooStatementCache scache ) { this.scache = scache; } public synchronized GooGooStatementCache getStatementCache() { return scache; } //api for NewProxyConnections void markNewTxnIsolation( int lvl ) //intentionally unsync'd -- isolation_lvl_nondefault is marked volatile { this.isolation_lvl_nondefault = (lvl != dflt_txn_isolation); //System.err.println("isolation_lvl_nondefault: " + isolation_lvl_nondefault); } void markNewCatalog( String catalog ) //intentionally unsync'd -- catalog_nondefault is marked volatile { this.catalog_nondefault = ObjectUtils.eqOrBothNull(catalog, dflt_catalog); } void markNewHoldability( int holdability ) //intentionally unsync'd -- holdability_nondefault is marked volatile { this.holdability_nondefault = (holdability != dflt_holdability); } void markNewReadOnly( boolean readOnly ) //intentionally unsync'd -- readOnly_nondefault is marked volatile { this.readOnly_nondefault = (readOnly != dflt_readOnly); } void markNewTypeMap( Map typeMap ) //intentionally unsync'd -- typeMap_nondefault is marked volatile { this.typeMap_nondefault = (typeMap != dflt_typeMap); } synchronized Object checkoutStatement( Method stmtProducingMethod, Object[] args ) throws SQLException { return scache.checkoutStatement( physicalConnection, stmtProducingMethod, args ); } synchronized void checkinStatement( Statement stmt ) throws SQLException { cleanupStatementResultSets( stmt ); scache.checkinStatement( stmt ); } synchronized void markActiveUncachedStatement( Statement stmt ) { uncachedActiveStatements.add( stmt ); } synchronized void markInactiveUncachedStatement( Statement stmt ) { cleanupStatementResultSets( stmt ); uncachedActiveStatements.remove( stmt ); } synchronized void markActiveResultSetForStatement( Statement stmt, ResultSet rs ) { Set rss = resultSets( stmt, true ); rss.add( rs ); } synchronized void markInactiveResultSetForStatement( Statement stmt, ResultSet rs ) { Set rss = resultSets( stmt, false ); if (rss == null) { if (logger.isLoggable( MLevel.FINE )) logger.fine( "ResultSet " + rs + " was apparently closed after the Statement that created it had already been closed." ); } else if ( ! rss.remove( rs ) ) throw new InternalError("Marking a ResultSet inactive that we did not know was opened!"); } synchronized void markActiveRawConnectionResultSet( ResultSet rs ) { if (rawConnectionResultSets == null) rawConnectionResultSets = new HashSet(); rawConnectionResultSets.add( rs ); } synchronized void markInactiveRawConnectionResultSet( ResultSet rs ) { if ( ! rawConnectionResultSets.remove( rs ) ) throw new InternalError("Marking a raw Connection ResultSet inactive that we did not know was opened!"); } synchronized void markActiveMetaDataResultSet( ResultSet rs ) { metaDataResultSets.add( rs ); } synchronized void markInactiveMetaDataResultSet( ResultSet rs ) { metaDataResultSets.remove( rs ); } synchronized void markClosedProxyConnection( NewProxyConnection npc, boolean txn_known_resolved ) { try { if (npc != exposedProxy) throw new InternalError("C3P0 Error: An exposed proxy asked a PooledConnection that was not its parents to clean up its resources!"); List closeExceptions = new LinkedList(); cleanupResultSets( closeExceptions ); cleanupUncachedStatements( closeExceptions ); checkinAllCachedStatements( closeExceptions ); if ( closeExceptions.size() > 0 ) {// System.err.println("[c3p0] The following Exceptions occurred while trying to clean up a Connection's stranded resources:"); if ( logger.isLoggable( MLevel.INFO ) ) logger.info("[c3p0] The following Exceptions occurred while trying to clean up a Connection's stranded resources:"); for ( Iterator ii = closeExceptions.iterator(); ii.hasNext(); ) { Throwable t = (Throwable) ii.next();// System.err.print("[c3p0 -- conection resource close Exception]: ");// t.printStackTrace(); if ( logger.isLoggable( MLevel.INFO ) ) logger.log( MLevel.INFO, "[c3p0 -- conection resource close Exception]", t ); } } reset( txn_known_resolved ); } catch (SQLException e) //Connection failed to reset! { //e.printStackTrace(); if (Debug.DEBUG && logger.isLoggable( MLevel.FINE )) logger.log(MLevel.FINE, "An exception occurred while reseting a closed Connection. Invalidating Connection.", e); updateConnectionStatus( ConnectionTester.CONNECTION_IS_INVALID ); fireConnectionErrorOccurred( e ); } finally { fireConnectionClosed(); } } private void reset( boolean txn_known_resolved ) throws SQLException { C3P0ImplUtils.resetTxnState( physicalConnection, forceIgnoreUnresolvedTransactions, autoCommitOnClose, txn_known_resolved ); if (isolation_lvl_nondefault) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -