c3p0连接测试的源码分析
来源:互联网 发布:mac迅雷提示信任 编辑:程序博客网 时间:2024/05/22 06:08
1.1 C3p0有三种方式检测连接的有效性
1:idleConnectionTestPeriod(异步)
每多少秒检查所有连接池中的空闲连接。Default: 0
C3P0PooledConnectionPool$PooledConnectionResourcePoolManager.refurbishIdleResource ()
public void refurbishIdleResource( Object resc ) throws Exception
{
if (logger.isLoggable( MLevel.FINER ) )
finerLoggingTestPooledConnection( resc, "IDLE CHECK" );
else
//测试连接
testPooledConnection(resc );
}
2:testConnectionOnCheckout(同步)
从池中取得可用的连接,同时检查有效性
C3P0PooledConnectionPool$PooledConnectionResourcePoolManager.refurbishResourceOnCheckout()
if ( testConnectionOnCheckout )
{
if (logger.isLoggable(MLevel.FINER ) )
finerLoggingTestPooledConnection( resc,"CHECKOUT" );
else
//测试连接
testPooledConnection( resc );
}
if ( connectionCustomizer !=null )
{
ConnectionphysicalConnection = null;
try
{
physicalConnection= ((AbstractC3P0PooledConnection)resc).getPhysicalConnection();
connectionCustomizer.onCheckOut( physicalConnection,parentDataSourceIdentityToken );
}
catch(ClassCastException e)
{
throw SqlUtils.toSQLException("Cannot use a ConnectionCustomizer with a non-c3p0PooledConnection." +
" PooledConnection: " + resc +
"; ConnectionPoolDataSource: " + cpds.getClass().getName(), e);
}
}
3:testConnectionOnCheckin(异步)
释放连接到连接池,同时检查有效性
C3P0PooledConnectionPool$PooledConnectionResourcePoolManager.refurbishResourceOnCheckin ()
if ( connectionCustomizer !=null )
{
ConnectionphysicalConnection = null;
try
{
physicalConnection= ((AbstractC3P0PooledConnection)resc).getPhysicalConnection();
connectionCustomizer.onCheckIn( physicalConnection,parentDataSourceIdentityToken );
SQLWarnings.logAndClearWarnings(physicalConnection );
}
catch(ClassCastException e)
{
throw SqlUtils.toSQLException("Cannot use a ConnectionCustomizer with a non-c3p0PooledConnection." +
" PooledConnection: " + resc +
"; ConnectionPoolDataSource: " + cpds.getClass().getName(), e);
}
}
else
{
PooledConnection pc =(PooledConnection) resc;
Connection con = null;
try
{
//we don't want anycallbacks while we're clearingwarnings
pc.removeConnectionEventListener( cl );
con =pc.getConnection();
SQLWarnings.logAndClearWarnings(con);
}
finally
{
// close theproxy Connection
ConnectionUtils.attemptClose(con);
pc.addConnectionEventListener( cl );
}
}
if ( testConnectionOnCheckin )
{
if (logger.isLoggable(MLevel.FINER ) )
finerLoggingTestPooledConnection( resc,"CHECKIN" );
else
//测试连接
testPooledConnection( resc );
}
总结:从代码上看,所有的方法的测试都是通过testPooledConnection方法实现的,只是采用不同的方式(同步或是异步),不同的场景(定时测试,获取连接,释放连接)调用之。
1.2 testPooledConnection
测试连接的方法
PooledConnection pc =(PooledConnection) resc;
Throwable[] throwableHolder= EMPTY_THROWABLE_HOLDER;
int status;
Connection conn = null;
Throwable rootCause = null;
try
{
//we don't want anycallbacks while we're testingthe resource
pc.removeConnectionEventListener( cl );
conn =pc.getConnection(); //checkout proxyconnection
// if this is a c3p0 pooled-connection, let's getunderneath the
// proxy wrapper, and test the physical connectionsometimes.
// this is faster, when the testQuery would not otherwisebe cached,
// and it avoids a potential statusOnException()double-check by the
// PooledConnection implementation should the test queryprovoke an
// Exception
Connection testConn;
if (scache !=null) //when there is a statement cache...
{
// if it's the slow, default query, faster to test theraw Connection
if (testQuery ==null && connectionTesterIsDefault && c3p0PooledConnections)
testConn =((AbstractC3P0PooledConnection) pc).getPhysicalConnection();
else//test will likely be faster on the proxiedConnection, because the test query is probably cached
testConn =conn;
}
else//where there's no statement cache, better to use thephysical connection, if we can get it
{
if (c3p0PooledConnections)
testConn =((AbstractC3P0PooledConnection) pc).getPhysicalConnection();
else
testConn =conn;
}
//具体的测试(测试类connectionTester(UnifiedConnectionTester和QueryConnectionTester)的实现类,测试sql: testQuery)
if ( testQuery ==null )
status =connectionTester.activeCheckConnection( testConn );
else
{
if (connectionTesterinstanceofUnifiedConnectionTester)
{
throwableHolder= thp.getThrowableHolder();
status =((UnifiedConnectionTester) connectionTester).activeCheckConnection( testConn,testQuery, throwableHolder );
}
elseif (connectionTester instanceofQueryConnectionTester)
status =((QueryConnectionTester) connectionTester).activeCheckConnection( testConn,testQuery );
else
{
// System.err.println("[c3p0] WARNING: testQuery'" + testQuery +
// "' ignored. Please set a ConnectionTester thatimplements " +
//"com.mchange.v2.c3p0.advanced.QueryConnectionTester, or use the " +
// "DefaultConnectionTester, to test with the testQuery.");
logger.warning("[c3p0] testQuery '" + testQuery +
"' ignored. Please set aConnectionTester that implements " +
"com.mchange.v2.c3p0.QueryConnectionTester,or use the " +
"DefaultConnectionTester, to test with thetestQuery.");
status =connectionTester.activeCheckConnection( testConn );
}
}
}
catch (Exception e)
{
if (Debug.DEBUG)
logger.log(MLevel.FINE,"A Connection test failed with an Exception.", e);
//e.printStackTrace();
status =ConnectionTester.CONNECTION_IS_INVALID;
// System.err.println("rootCause------>");
// e.printStackTrace();
rootCause = e;
}
finally
{
if (rootCause ==null)
rootCause =throwableHolder[0];
elseif(throwableHolder[0] != null &&logger.isLoggable(MLevel.FINE))
logger.log(MLevel.FINE,"Internal Connection Test Exception", throwableHolder[0]);
if (throwableHolder!=EMPTY_THROWABLE_HOLDER)
thp.returnThrowableHolder(throwableHolder );
ConnectionUtils.attemptClose(conn );//invalidate proxy connection
pc.addConnectionEventListener( cl ); //should we move this to CONNECTION_IS_OKAY case? (itshould work either way)
}
switch (status)
{
case ConnectionTester.CONNECTION_IS_OKAY:
break;//no problem, babe
case ConnectionTester.DATABASE_IS_INVALID:
rp.resetPool();
//intentional cascade...
case ConnectionTester.CONNECTION_IS_INVALID:
Exception throwMe;
if (rootCause ==null)
throwMe = new SQLException("Connection is invalid");
else
throwMe = SqlUtils.toSQLException("Connection is invalid", rootCause);
throw throwMe;
default:
thrownew Error("Bad Connection Tester (" +
connectionTester + ") " +
"returned invalid status (" + status + ").");
}
测试类:
Default:com.mchange.v2.c3p0.impl.DefaultConnectionTester-->
<property name=" connectionTesterClassName "></property>
可以自定义,需要实现(UnifiedConnectionTester或者是
QueryConnectionTester)
测试sql
1. automaticTestTable (优先级高)(测试时自动生成对应的查询语句)
2. preferredTestQuery(默认为null,可以设置查询语句)
源码:C3P0PooledConnectionPoolManager
private C3P0PooledConnectionPool createPooledConnectionPool(DbAuth auth)throws SQLException
{
String userName = auth.getUser();
String automaticTestTable =getAutomaticTestTable( userName );
String realTestQuery;
//优先判断是否有automaticTestTable
if (automaticTestTable != null)
{
//通过automaticTestTable生成testQuery;
realTestQuery = initializeAutomaticTestTable( automaticTestTable, auth);
if (this.getPreferredTestQuery( userName ) != null)
{
if ( logger.isLoggable(MLevel.WARNING ) )
{
logger.logp(MLevel.WARNING,
C3P0PooledConnectionPoolManager.class.getName(),
"createPooledConnectionPool",
"[c3p0] Both automaticTestTable and preferredTestQuery have beenset! " +
"UsingautomaticTestTable, and ignoring preferredTestQuery. Real test query is''{0}''.",
realTestQuery
);
}
}
}
Else//否则使用PreferredTestQuery
{
if (! defaultAuth.equals( auth ))
ensureFirstConnectionAcquisition(auth );
realTestQuery = this.getPreferredTestQuery( userName );
}
C3P0PooledConnectionPool out = new C3P0PooledConnectionPool( cpds,
auth,
this.getMinPoolSize(userName ),
this.getMaxPoolSize(userName ),
this.getInitialPoolSize( userName ),
this.getAcquireIncrement( userName ),
this.getAcquireRetryAttempts( userName ),
this.getAcquireRetryDelay( userName ),
this.getBreakAfterAcquireFailure(userName ),
this.getCheckoutTimeout( userName ),
this.getIdleConnectionTestPeriod( userName ),
this.getMaxIdleTime(userName ),
this.getMaxIdleTimeExcessConnections( userName),
this.getMaxConnectionAge( userName ),
this.getPropertyCycle(userName ),
this.getUnreturnedConnectionTimeout( userName ),
this.getDebugUnreturnedConnectionStackTraces(userName ),
this.getTestConnectionOnCheckout( userName ),
this.getTestConnectionOnCheckin( userName ),
this.getMaxStatements(userName ),
this.getMaxStatementsPerConnection( userName ),
this.getConnectionTester( userName ),
this.getConnectionCustomizer( userName ),
realTestQuery,
rpfact,
taskRunner,
parentDataSourceIdentityToken );
return out;
}
- c3p0连接测试的源码分析
- c3p0配置连接测试
- C3P0连接超时分析
- c3p0源码分析
- c3p0的连接数据库
- C3p0连接池 连接数据库的通用类及测试类
- C3P0连接池初始化过程分析之一
- c3p0连接池的使用
- 基于C3P0的连接池
- c3p0连接池的配置
- C3P0连接池的配置
- c3p0连接池的配置
- c3p0连接池的使用
- C3P0连接池的使用
- DBCP,C3P0,Tomcat_JDBC 等连接池的性能及稳定性测试 druid待补充
- Hibernate使用C3P0的连接池,并队c3p0配置。
- C3P0数据连接池的配置文件c3p0-config.xml
- 在Eclipse中测试MySQL-JDBC(13)Apache的DBCP连接池和c3p0连接池
- OCM_Session8_1_Preparing the Primary Database for Standby Database Creation
- apidemos 实例解析
- 教你OpenERP 7.0 怎样使用本地addons而跳过使用官网模块
- 第五周项目3-对象数组操作长方体类
- C++一点感司
- c3p0连接测试的源码分析
- 关于unsigned long 转化我char[]的问题
- UML系列
- 应用程序内购买类型
- SQL效率分析之01
- 用plsql连接数据库 报错 无法解析指定的连接标识符 ora06413 连接未打开
- Java字符串之性能优化
- 000
- Centos下搭建svn并且和web服务器同步