?? c3p0pooledconnection.java
字號(hào):
/* * 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.lang.reflect.*;import java.sql.*;import java.util.*;import javax.sql.*;import com.mchange.v2.log.*;import com.mchange.v2.sql.*;import com.mchange.v2.sql.filter.*;import com.mchange.v2.c3p0.*;import com.mchange.v2.c3p0.stmt.*;import com.mchange.v1.util.ClosableResource;import com.mchange.v2.c3p0.C3P0ProxyConnection;import com.mchange.v2.c3p0.util.ConnectionEventSupport;import com.mchange.v2.lang.ObjectUtils;public final class C3P0PooledConnection implements PooledConnection, ClosableResource{ final static MLogger logger = MLog.getLogger( C3P0PooledConnection.class ); final static ClassLoader CL = C3P0PooledConnection.class.getClassLoader(); final static Class[] PROXY_CTOR_ARGS = new Class[]{ InvocationHandler.class }; final static Constructor CON_PROXY_CTOR; final static Method RS_CLOSE_METHOD; final static Method STMT_CLOSE_METHOD; final static Object[] CLOSE_ARGS; final static Set OBJECT_METHODS; /** * @deprecated use or rewrite in terms of ReflectUtils.findProxyConstructor() */ private static Constructor createProxyConstructor(Class intfc) throws NoSuchMethodException { Class[] proxyInterfaces = new Class[] { intfc }; Class proxyCl = Proxy.getProxyClass(CL, proxyInterfaces); return proxyCl.getConstructor( PROXY_CTOR_ARGS ); } static { try { CON_PROXY_CTOR = createProxyConstructor( ProxyConnection.class ); Class[] argClasses = new Class[0]; RS_CLOSE_METHOD = ResultSet.class.getMethod("close", argClasses); STMT_CLOSE_METHOD = Statement.class.getMethod("close", argClasses); CLOSE_ARGS = new Object[0]; OBJECT_METHODS = Collections.unmodifiableSet( new HashSet( Arrays.asList( Object.class.getMethods() ) ) ); } catch (Exception e) { //e.printStackTrace(); logger.log(MLevel.SEVERE, "An Exception occurred in static initializer of" + C3P0PooledConnection.class.getName(), e); throw new InternalError("Something is very wrong, or this is a pre 1.3 JVM." + "We cannot set up dynamic proxies and/or methods!"); } } //MT: post-constructor constants final ConnectionTester connectionTester; final boolean autoCommitOnClose; final boolean forceIgnoreUnresolvedTransactions; final boolean supports_setTypeMap; final boolean supports_setHoldability; final int dflt_txn_isolation; final String dflt_catalog; final int dflt_holdability; //MT: thread-safe final ConnectionEventSupport ces = new ConnectionEventSupport(this); //MT: threadsafe, but reassigned (on close) volatile Connection physicalConnection; volatile Exception invalidatingException = null; //MT: threadsafe, but reassigned, and a read + reassignment must happen // atomically. protected by this' lock. ProxyConnection exposedProxy; //MT: protected by this' lock int connection_status = ConnectionTester.CONNECTION_IS_OKAY; /* * contains all unclosed Statements not managed by a StatementCache * associated with the physical connection * * MT: protected by its own lock, not reassigned */ final Set uncachedActiveStatements = Collections.synchronizedSet( new HashSet() ); //MT: Thread-safe, assigned volatile GooGooStatementCache scache; volatile boolean isolation_lvl_nondefault = false; volatile boolean catalog_nondefault = false; volatile boolean holdability_nondefault = false; public C3P0PooledConnection(Connection con, ConnectionTester connectionTester, boolean autoCommitOnClose, boolean forceIgnoreUnresolvedTransactions) throws SQLException { this.physicalConnection = con; this.connectionTester = connectionTester; this.autoCommitOnClose = autoCommitOnClose; this.forceIgnoreUnresolvedTransactions = forceIgnoreUnresolvedTransactions; this.supports_setTypeMap = C3P0ImplUtils.supportsMethod(con, "setTypeMap", new Class[]{ Map.class }); this.supports_setHoldability = C3P0ImplUtils.supportsMethod(con, "setHoldability", new Class[]{ Integer.class }); this.dflt_txn_isolation = con.getTransactionIsolation(); this.dflt_catalog = con.getCatalog(); this.dflt_holdability = (supports_setHoldability ? con.getHoldability() : ResultSet.CLOSE_CURSORS_AT_COMMIT); } Connection getPhysicalConnection() { return physicalConnection; } boolean isClosed() throws SQLException { return (physicalConnection == null); } void initStatementCache( GooGooStatementCache scache ) { this.scache = scache; } //DEBUG //Exception origGet = null; // synchronized to protect exposedProxy public synchronized Connection getConnection() throws SQLException { if ( exposedProxy != null) { //DEBUG //System.err.println("[DOUBLE_GET_TESTER] -- double getting a Connection from " + this ); //new Exception("[DOUBLE_GET_TESTER] -- Double-Get Stack Trace").printStackTrace(); //origGet.printStackTrace();// 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!!!"); 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; } else { return getCreateNewConnection(); } } // must be called from sync'ed method to protecte // exposedProxy private Connection getCreateNewConnection() throws SQLException { try { //DEBUG //origGet = new Exception("[DOUBLE_GET_TESTER] -- Orig Get"); ensureOkay(); /* * we reset the physical connection when we close an exposed proxy * no need to do it again when we create one */ //reset(); return (exposedProxy = createProxyConnection()); } catch (SQLException e) { throw e; } catch (Exception e) { //e.printStackTrace(); logger.log(MLevel.WARNING, "Failed to acquire connection!", e); throw new SQLException("Failed to acquire connection!"); } } public void closeAll() throws SQLException { if (scache != null) scache.closeAll( physicalConnection ); } public void close() throws SQLException { this.close( false ); } //TODO: factor out repetitive debugging code private synchronized void close(boolean known_invalid) throws SQLException { //System.err.println("Closing " + this); if ( physicalConnection != null ) { try { StringBuffer debugOnlyLog = null; if ( Debug.DEBUG && known_invalid ) { debugOnlyLog = new StringBuffer(); debugOnlyLog.append("[ exceptions: "); } Exception exc = cleanupUncachedActiveStatements(); if (Debug.DEBUG && exc != null) { if (known_invalid) debugOnlyLog.append( exc.toString() + ' ' ); else logger.log(MLevel.WARNING, "An exception occurred while cleaning up uncached active Statements.", exc); //exc.printStackTrace(); } try { // we've got to use silentClose() rather than close() here, // 'cuz if there's still an exposedProxy (say a user forgot to // close his Connection) before we close, and we use regular (loud) // close, we will try to check this dead or dying PooledConnection // back into the pool. We only want to do this when close is called // on user proxies, and the underlying PooledConnection might still // be good. The PooledConnection itself should only be closed by the // pool. if (exposedProxy != null) exposedProxy.silentClose( known_invalid ); } catch (Exception e) { if (Debug.DEBUG) { if (known_invalid) debugOnlyLog.append( e.toString() + ' ' ); else logger.log(MLevel.WARNING, "An exception occurred.", exc); //e.printStackTrace(); } exc = e; } try { this.closeAll(); } catch (Exception e) { if (Debug.DEBUG) { if (known_invalid) debugOnlyLog.append( e.toString() + ' ' ); else logger.log(MLevel.WARNING, "An exception occurred.", exc); //e.printStackTrace(); } exc = e; } try { physicalConnection.close(); } catch (Exception e) { if (Debug.DEBUG) { if (known_invalid) debugOnlyLog.append( e.toString() + ' ' ); else logger.log(MLevel.WARNING, "An exception occurred.", exc); e.printStackTrace(); } exc = e; } if (exc != null) { if (known_invalid) { debugOnlyLog.append(" ]"); if (Debug.DEBUG) {// System.err.print("[DEBUG]" + this + ": while closing a PooledConnection known to be invalid, ");// System.err.println(" some exceptions occurred. This is probably not a problem:");// System.err.println( debugOnlyLog.toString() ); logger.fine(this + ": while closing a PooledConnection known to be invalid, " + " some exceptions occurred. This is probably not a problem: " + debugOnlyLog.toString() ); } } else throw new SQLException("At least one error occurred while attempting " + "to close() the PooledConnection: " + exc); } if (Debug.TRACE == Debug.TRACE_MAX) logger.fine("C3P0PooledConnection closed. [" + this + ']'); //System.err.println("C3P0PooledConnection closed. [" + this + ']'); } finally { physicalConnection = null; } } } public void addConnectionEventListener(ConnectionEventListener listener) { ces.addConnectionEventListener( listener ); } public void removeConnectionEventListener(ConnectionEventListener listener) { ces.removeConnectionEventListener( listener ); } private void reset() throws SQLException { reset( false ); } private void reset( boolean known_resolved_txn ) throws SQLException { ensureOkay(); C3P0ImplUtils.resetTxnState( physicalConnection, forceIgnoreUnresolvedTransactions, autoCommitOnClose, known_resolved_txn ); if (isolation_lvl_nondefault) { physicalConnection.setTransactionIsolation( dflt_txn_isolation ); isolation_lvl_nondefault = false; } if (catalog_nondefault) { physicalConnection.setCatalog( dflt_catalog ); catalog_nondefault = false; } if (holdability_nondefault) //we don't test if holdability is supported, 'cuz it can never go nondefault if it's not. { physicalConnection.setHoldability( dflt_holdability ); holdability_nondefault = false; } try { physicalConnection.setReadOnly( false ); } catch ( Throwable t ) { if (logger.isLoggable( MLevel.FINE )) logger.log(MLevel.FINE, "A Throwable occurred while trying to reset the readOnly property of our Connection to false!", t); } try { if (supports_setTypeMap) physicalConnection.setTypeMap( Collections.EMPTY_MAP ); } catch ( Throwable t ) { if (logger.isLoggable( MLevel.FINE )) logger.log(MLevel.FINE, "A Throwable occurred while trying to reset the typeMap property of our Connection to Collections.EMPTY_MAP!", t); } } boolean closeAndRemoveResultSets(Set rsSet) { boolean okay = true; synchronized (rsSet) { for (Iterator ii = rsSet.iterator(); ii.hasNext(); ) { ResultSet rs = (ResultSet) ii.next(); try { rs.close(); } catch (SQLException e) { if (Debug.DEBUG) logger.log(MLevel.WARNING, "An exception occurred while cleaning up a ResultSet.", e); //e.printStackTrace(); okay = false; } finally { ii.remove(); }
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -