⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 googoostatementcache.java

📁 c3p0数据库连接池实现源码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
    /* non-public methods that MUST be called with this' lock */    abstract boolean prepareAssimilateNewStatement(Connection pcon);    abstract void addStatementToDeathmarches( Object pstmt, Connection physicalConnection );    abstract void removeStatementFromDeathmarches( Object pstmt, Connection physicalConnection );    final int countCachedStatements()    { return stmtToKey.size(); }        private void assimilateNewCheckedOutStatement( StatementCacheKey key, 						   Connection pConn, 						   Object ps )    {	stmtToKey.put( ps, key );	HashSet ks = keySet( key );	if (ks == null)	    keyToKeyRec.put( key, new KeyRec() );  	else 	    {		//System.err.println("-------> Multiply prepared statement! " + key.stmtText );		if (logger.isLoggable(MLevel.INFO))		    logger.info("Multiply prepared statement! " + key.stmtText );		if (Debug.DEBUG && logger.isLoggable(MLevel.FINE))		    logger.fine("(The same statement has already been prepared by this Connection, " +				"and that other instance has not yet been closed, so the statement pool " +				"has to prepare a second PreparedStatement object rather than reusing " +				"the previously-cached Statement. The new Statement will be cached, in case " +				"you frequently need multiple copies of this Statement.)");	    }	keySet( key ).add( ps );	cxnStmtMgr.addStatementForConnection( ps, pConn );	if (Debug.DEBUG && Debug.TRACE == Debug.TRACE_MAX)	    {// 		System.err.println("cxnStmtMgr.statementSet( " + pConn + " ).size(): " + // 				   cxnStmtMgr.statementSet( pConn ).size());		if (logger.isLoggable(MLevel.FINEST))		    logger.finest("cxnStmtMgr.statementSet( " + pConn + " ).size(): " + 				  cxnStmtMgr.statementSet( pConn ).size());	    }	++stmt_count;	checkedOut.add( ps );    }    private void removeStatement( Object ps , boolean force_destroy )    { removeStatement( ps, force_destroy, null ); }    /*     * SIMULTANEOUS CLOSE OF STATEMENT AND CONNECTION BUG WORKAROUND ( counter crap ) -- see closeAll(Connection c)     */    private void removeStatement( Object ps , boolean force_destroy, ChangeNotifyingSynchronizedIntHolder counter )    {	synchronized (removalPending)	    {		if ( removalPending.contains( ps ) )		    return;		else		    removalPending.add(ps);	    }	StatementCacheKey sck = (StatementCacheKey) stmtToKey.remove( ps );	removeFromKeySet( sck, ps );	Connection pConn = sck.physicalConnection;	if (! checkedOut.contains( ps ) )	    {		removeStatementFromDeathmarches( ps, pConn );		removeFromCheckoutQueue( sck , ps );		destroyStatement( ps, counter );	    }	else	    {		checkedOut.remove( ps ); // usually we let it defer destruction until check-in!		if (force_destroy)       // but occasionally we want the statement assuredly gone.		    {			destroyStatement( ps, counter );		    }	    }	boolean check =	cxnStmtMgr.removeStatementForConnection( ps, pConn );	if (Debug.DEBUG && check == false)	    {		//new Exception("WARNING: removed a statement that apparently wasn't in a statement set!!!").printStackTrace();		if (logger.isLoggable(MLevel.WARNING))		    logger.log(MLevel.WARNING, 			       this + " removed a statement that apparently wasn't in a statement set!!!",			       new Exception("LOG STACK TRACE"));	    }	--stmt_count;	synchronized (removalPending)	    { removalPending.remove(ps); }    }    private Object acquireStatement(final Connection pConn, 				    final Method stmtProducingMethod, 				    final Object[] args )	throws SQLException    {	try	    {		final Object[] outHolder = new Object[1];		final SQLException[] exceptionHolder = new SQLException[1];				Runnable r = new Runnable()		    {			public void run()			{			    try				{				    outHolder[0] = 					stmtProducingMethod.invoke( pConn, 								    args ); 				}			    catch ( InvocationTargetException e )				{ 				    Throwable targetException = e.getTargetException();				    if ( targetException instanceof SQLException )					exceptionHolder[0] = (SQLException) targetException;				    else					exceptionHolder[0] 					    = SqlUtils.toSQLException(targetException);				}			    catch ( Exception e )				{ exceptionHolder[0] = SqlUtils.toSQLException(e); }			    finally				{ 				    synchronized ( GooGooStatementCache.this )					{ GooGooStatementCache.this.notifyAll(); }				}			}		    };				blockingTaskAsyncRunner.postRunnable(r);		while ( outHolder[0] == null && exceptionHolder[0] == null )		    this.wait(); //give up our lock while the Statement gets prepared		if (exceptionHolder[0] != null)		    throw exceptionHolder[0];		else		    {			Object out = outHolder[0];			return out;		    }	    }	catch ( InterruptedException e )	    { throw SqlUtils.toSQLException( e ); }    }    private KeyRec keyRec( StatementCacheKey key )    { return ((KeyRec) keyToKeyRec.get( key )); }    private HashSet keySet( StatementCacheKey key )    { 	KeyRec rec = keyRec( key );	return (rec == null ? null : rec.allStmts);     }    private boolean removeFromKeySet( StatementCacheKey key, Object pstmt )    {	boolean out;	HashSet stmtSet = keySet( key );	out = stmtSet.remove( pstmt );	if (stmtSet.isEmpty() && checkoutQueue( key ).isEmpty())	    keyToKeyRec.remove( key );	return out;    }    private LinkedList checkoutQueue( StatementCacheKey key )    { 	KeyRec rec = keyRec( key );	return ( rec == null ? null : rec.checkoutQueue );    }    private boolean removeFromCheckoutQueue( StatementCacheKey key, Object pstmt )    {	boolean out;	LinkedList q = checkoutQueue( key );	out = q.remove( pstmt );	if (q.isEmpty() && keySet( key ).isEmpty())	    keyToKeyRec.remove( key );	return out;    }    private boolean ourResource( Object ps )    { return stmtToKey.keySet().contains( ps ); }    private void refreshStatement( PreparedStatement ps ) throws Exception    { ps.clearParameters(); }    private void printStats()    {	//new Exception("printStats()").printStackTrace();	int total_size = this.countCachedStatements();	int checked_out_size = checkedOut.size();	int num_connections  = cxnStmtMgr.getNumConnectionsWithCachedStatements(); 	int num_keys = keyToKeyRec.size(); 	System.err.print(this.getClass().getName() + " stats -- ");	System.err.print("total size: " + total_size);	System.err.print("; checked out: " + checked_out_size);	System.err.print("; num connections: " + num_connections);	System.err.println("; num keys: " + num_keys);    }    private String statsString()    {	int total_size = this.countCachedStatements();	int checked_out_size = checkedOut.size();	int num_connections  = cxnStmtMgr.getNumConnectionsWithCachedStatements(); 	int num_keys = keyToKeyRec.size(); 	StringBuffer sb = new StringBuffer(255);	sb.append(this.getClass().getName());	sb.append(" stats -- ");	sb.append("total size: ");	sb.append(total_size);	sb.append("; checked out: ");	sb.append(checked_out_size);	sb.append("; num connections: ");	sb.append(num_connections);	sb.append("; num keys: ");	sb.append(num_keys);	return sb.toString();    }    private static class KeyRec    {	HashSet  allStmts       = new HashSet();	LinkedList checkoutQueue  = new LinkedList();    }    protected class Deathmarch    {	TreeMap longsToStmts = new TreeMap(); 	HashMap stmtsToLongs = new HashMap();	long last_long = -1;	public void deathmarchStatement( Object ps )	{	    //System.err.println("deathmarchStatement( " + ps + " )");	    if (Debug.DEBUG)		{		    Long old = (Long) stmtsToLongs.get( ps );		    if (old != null)			throw new RuntimeException("Internal inconsistency: " +						   "A statement is being double-deathmatched. no checked-out statements should be in a deathmarch already; " +						   "no already checked-in statement should be deathmarched!");		}	    Long youth = getNextLong();	    stmtsToLongs.put( ps, youth );	    longsToStmts.put( youth, ps );	}	public void undeathmarchStatement( Object ps )	{	    Long old = (Long) stmtsToLongs.remove( ps );	    if (Debug.DEBUG && old == null)		throw new RuntimeException("Internal inconsistency: " +					   "A (not new) checking-out statement is not in deathmarch.");	    Object check = longsToStmts.remove( old );	    if (Debug.DEBUG && old == null)		throw new RuntimeException("Internal inconsistency: " +					   "A (not new) checking-out statement is not in deathmarch.");	}	public boolean cullNext()	{	    if ( longsToStmts.isEmpty() )		return false;	    else		{		    Long l = (Long) longsToStmts.firstKey();		    Object ps = longsToStmts.get( l );		    if (Debug.DEBUG && Debug.TRACE == Debug.TRACE_MAX)			{// 			    System.err.println("CULLING: " + // 					       ((StatementCacheKey) stmtToKey.get(ps)).stmtText);			    if (logger.isLoggable(MLevel.FINEST))				logger.finest("CULLING: " + ((StatementCacheKey) stmtToKey.get(ps)).stmtText);			}		    // we do not undeathmarch the statement ourselves, because removeStatement( ... )		    // should remove from all deathmarches...		    removeStatement( ps, true ); 		    if (Debug.DEBUG && this.contains( ps ))			throw new RuntimeException("Inconsistency!!! Statement culled from deathmarch failed to be removed by removeStatement( ... )!");		    return true;		}	}	public boolean contains( Object ps )	{ return stmtsToLongs.keySet().contains( ps ); }	public int size()	{ return longsToStmts.size(); }	private Long getNextLong()	{ return new Long( ++last_long ); }    }    protected static abstract class ConnectionStatementManager    {	Map cxnToStmtSets = new HashMap();	public int getNumConnectionsWithCachedStatements()	{ return cxnToStmtSets.size(); }	public Set statementSet( Connection pcon )	{ return (Set) cxnToStmtSets.get( pcon ); }	public int getNumStatementsForConnection( Connection pcon )	{	    Set stmtSet = statementSet( pcon );	    return (stmtSet == null ? 0 : stmtSet.size());	}	public void addStatementForConnection( Object ps, Connection pcon )	{	    Set stmtSet = statementSet( pcon );	    if (stmtSet == null)		{		    stmtSet = new HashSet();		    cxnToStmtSets.put( pcon, stmtSet );		}	    stmtSet.add( ps );	}	public boolean removeStatementForConnection( Object ps, Connection pcon )	{	    boolean out;	    Set stmtSet = statementSet( pcon );	    if ( stmtSet != null )		{		    out = stmtSet.remove( ps );		    if (stmtSet.isEmpty())			cxnToStmtSets.remove( pcon );		}	    else		out = false;	    return out;	}    }    // i want this as optimized as possible, so i'm adopting the philosophy that all    // classes are abstract or final, to help enable compiler inlining...    protected static final class SimpleConnectionStatementManager extends ConnectionStatementManager     {}    protected final class DeathmarchConnectionStatementManager extends ConnectionStatementManager    {	Map cxnsToDms = new HashMap();	public void addStatementForConnection( Object ps, Connection pcon )	{	    super.addStatementForConnection( ps, pcon );	    Deathmarch dm = (Deathmarch) cxnsToDms.get( pcon );	    if (dm == null)		{		    dm = new Deathmarch();		    cxnsToDms.put( pcon, dm );		}	}	public boolean removeStatementForConnection( Object ps, Connection pcon )	{	    boolean out = super.removeStatementForConnection( ps, pcon );	    if (out)		{		    if ( statementSet( pcon ) == null )			cxnsToDms.remove( pcon );		}	    return out;	}	public Deathmarch getDeathmarch( Connection pcon )	{ return (Deathmarch) cxnsToDms.get( pcon ); }    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -