Author: fhanik
Date: Thu Apr 30 19:41:07 2009
New Revision: 770411
URL: http://svn.apache.org/viewvc?rev=770411&view=rev
Log:
Add the following features
- max age for a connection kept alive
- an ability to reset the abandon timer when queries are executed
- an abandoned test, abandon when a percentage of the pool has been utilized
Added:
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/AbandonPercentageTest.java
(with props)
Modified:
tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSource.java
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java
Modified: tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml?rev=770411&r1=770410&r2=770411&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml (original)
+++ tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml Thu Apr 30 19:41:07 2009
@@ -73,6 +73,15 @@
that has over 200 source files(last time we checked), Tomcat jdbc
has a core of 8 files, the connection pool itself is about half
that. As bugs may occur, they will be faster to track down, and
easier to fix. Complexity reduction has been a focus from inception.</li>
<li>Asynchronous connection retrieval - you can queue your request for a
connection and receive a Future<Connection> back.</li>
+ <li>Better idle connection handling. Instead of closing connections
directly, it can still pool connections and sizes the idle pool with a smarter
algorithm.</li>
+ <li>You can decide at what moment connections are considered abandoned,
is it when the pool is full, or directly at a timeout
+ by specifying a threshold.
+ </li>
+ <li>The abandon connection timer will reset upon a statement/query
activity. Allowing a connections that is in use for a long time to not timeout.
+ This is achieved using the ResetAbandonedTimer
+ </li>
+ <li>Close connections after they have been connected for a certain time.
Age based close upon return to the pool.
+ </li>
</ol>
</p>
@@ -338,6 +347,14 @@
as <code>removeAbandonedTimeout</code> has been reached.</p>
</attribute>
+ <attribute name="maxAge" required="false">
+ <p>(long) Time in milliseconds to keep this connection. When a
connection is returned to the pool,
+ the pool will check to see if the <code>now - time-when-connected >
maxAge</code> has been reached,
+ and if so, it closes the connection rather than returning it to the
pool.
+ The default value is <code>0</code>, which implies that connections
will be left open and no age check
+ will be done upon returning the connection to the pool.</p>
+ </attribute>
+
<attribute name="useEquals" required="false">
<p>(boolean) Set to true if you wish the <code>ProxyConnection</code>
class to use <code>String.equals</code> instead of
<code>==</code> when comparing method names. This property does not
apply to added interceptors as those are configured individually.
Modified:
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java?rev=770411&r1=770410&r2=770411&view=diff
==============================================================================
---
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java
(original)
+++
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java
Thu Apr 30 19:41:07 2009
@@ -609,6 +609,17 @@
}
}
+ protected boolean shouldClose(PooledConnection con, int action) {
+ if (con.isDiscarded()) return true;
+ if (isClosed()) return true;
+ if (!con.validate(action)) return true;
+ if (getPoolProperties().getMaxAge()>0 ) {
+ return (System.currentTimeMillis()-con.getLastConnected()) >
getPoolProperties().getMaxAge();
+ } else {
+ return false;
+ }
+ }
+
/**
* Returns a connection to the pool
* @param con PooledConnection
@@ -626,8 +637,8 @@
con.lock();
if (busy.remove(con)) {
- if ((!con.isDiscarded()) && (!isClosed()) &&
- con.validate(PooledConnection.VALIDATE_RETURN)) {
+
+ if (!shouldClose(con,PooledConnection.VALIDATE_RETURN)) {
con.setStackTrace(null);
con.setTimestamp(System.currentTimeMillis());
if (((idle.size()>=poolProperties.getMaxIdle()) &&
!poolProperties.isPoolSweeperEnabled()) || (!idle.offer(con))) {
@@ -654,12 +665,11 @@
} //end if
} //checkIn
- public boolean shouldAbandon() {
+ protected boolean shouldAbandon() {
if (poolProperties.getAbandonWhenPercentageFull()==0) return true;
float used = (float)busy.size();
float max = (float)poolProperties.getMaxActive();
float perc = (float)poolProperties.getAbandonWhenPercentageFull();
- System.out.println("Abandon rate:"+(used/max*100f));
return (used/max*100f)>=perc;
}
Modified:
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSource.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSource.java?rev=770411&r1=770410&r2=770411&view=diff
==============================================================================
---
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSource.java
(original)
+++
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSource.java
Thu Apr 30 19:41:07 2009
@@ -249,6 +249,14 @@
throw new RuntimeException(x);
}
}
+
+ public long getMaxAge() {
+ try {
+ return createPool().getPoolProperties().getMaxAge();
+ }catch (SQLException x) {
+ throw new RuntimeException(x);
+ }
+ }
public String getName() {
try {
Modified:
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java?rev=770411&r1=770410&r2=770411&view=diff
==============================================================================
---
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java
(original)
+++
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java
Thu Apr 30 19:41:07 2009
@@ -78,6 +78,7 @@
protected final static String PROP_MINIDLE = "minIdle";
protected final static String PROP_INITIALSIZE = "initialSize";
protected final static String PROP_MAXWAIT = "maxWait";
+ protected final static String PROP_MAXAGE = "maxAge";
protected final static String PROP_TESTONBORROW = "testOnBorrow";
protected final static String PROP_TESTONRETURN = "testOnReturn";
@@ -149,7 +150,8 @@
PROP_FAIR_QUEUE,
PROP_USE_EQUALS,
OBJECT_NAME,
- PROP_ABANDONWHENPERCENTAGEFULL
+ PROP_ABANDONWHENPERCENTAGEFULL,
+ PROP_MAXAGE
};
// -------------------------------------------------- ObjectFactory Methods
@@ -417,6 +419,11 @@
poolProperties.setAbandonWhenPercentageFull(Integer.parseInt(value));
}
+ value = properties.getProperty(PROP_MAXAGE);
+ if (value != null) {
+ poolProperties.setMaxAge(Long.parseLong(value));
+ }
+
return poolProperties;
}
Modified:
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java?rev=770411&r1=770410&r2=770411&view=diff
==============================================================================
---
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java
(original)
+++
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java
Thu Apr 30 19:41:07 2009
@@ -71,6 +71,7 @@
protected boolean fairQueue = true;
protected boolean useEquals = false;
protected int abandonWhenPercentageFull = 0;
+ protected long maxAge = 0;
private InterceptorDefinition[] interceptors = null;
@@ -523,4 +524,14 @@
this.useEquals = useEquals;
}
+ public long getMaxAge() {
+ return maxAge;
+ }
+
+ public void setMaxAge(long maxAge) {
+ this.maxAge = maxAge;
+ }
+
+
+
}
Modified:
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java?rev=770411&r1=770410&r2=770411&view=diff
==============================================================================
---
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java
(original)
+++
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java
Thu Apr 30 19:41:07 2009
@@ -86,6 +86,10 @@
*/
protected boolean discarded = false;
/**
+ * The Timestamp when the last time the connect() method was called
successfully
+ */
+ protected volatile long lastConnected = -1;
+ /**
* timestamp to keep track of validation intervals
*/
protected long lastValidated = System.currentTimeMillis();
@@ -163,6 +167,7 @@
if
(poolProperties.getDefaultTransactionIsolation()!=DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION)
connection.setTransactionIsolation(poolProperties.getDefaultTransactionIsolation());
}
this.discarded = false;
+ this.lastConnected = System.currentTimeMillis();
}
/**
@@ -193,6 +198,7 @@
}
}
connection = null;
+ lastConnected = -1;
if (finalize) parent.finalize(this);
}
@@ -381,6 +387,12 @@
public java.sql.Connection getConnection() {
return this.connection;
}
+
+
+
+ public long getLastConnected() {
+ return lastConnected;
+ }
/**
* Returns the first handler in the interceptor chain
Modified:
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java?rev=770411&r1=770410&r2=770411&view=diff
==============================================================================
---
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java
(original)
+++
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java
Thu Apr 30 19:41:07 2009
@@ -276,5 +276,8 @@
public int getAbandonWhenPercentageFull() {
return pool.getPoolProperties().getAbandonWhenPercentageFull();
}
+ public long getMaxAge() {
+ return pool.getPoolProperties().getMaxAge();
+ }
}
Modified:
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java?rev=770411&r1=770410&r2=770411&view=diff
==============================================================================
---
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java
(original)
+++
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java
Thu Apr 30 19:41:07 2009
@@ -118,4 +118,6 @@
public int getAbandonWhenPercentageFull();
+ public long getMaxAge();
+
}
Added:
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/AbandonPercentageTest.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/AbandonPercentageTest.java?rev=770411&view=auto
==============================================================================
---
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/AbandonPercentageTest.java
(added)
+++
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/AbandonPercentageTest.java
Thu Apr 30 19:41:07 2009
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tomcat.jdbc.test;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer;
+
+public class AbandonPercentageTest extends DefaultTestCase {
+
+ public AbandonPercentageTest(String name) {
+ super(name);
+ }
+
+ public void testDefaultAbandon() throws Exception {
+ this.init();
+ this.datasource.setMaxActive(100);
+ this.datasource.setMaxIdle(100);
+ this.datasource.setInitialSize(0);
+ this.datasource.getPoolProperties().setAbandonWhenPercentageFull(0);
+
this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(100);
+ this.datasource.getPoolProperties().setRemoveAbandoned(true);
+ this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1);
+ Connection con = datasource.getConnection();
+ long start = System.currentTimeMillis();
+ assertEquals("Number of connections active/busy should be
1",1,datasource.getPool().getActive());
+ Thread.sleep(2000);
+ assertEquals("Number of connections active/busy should be
0",0,datasource.getPool().getActive());
+ con.close();
+ }
+
+ public void testMaxedOutAbandon() throws Exception {
+ int size = 100;
+ this.init();
+ this.datasource.setMaxActive(size);
+ this.datasource.setMaxIdle(size);
+ this.datasource.setInitialSize(0);
+ this.datasource.getPoolProperties().setAbandonWhenPercentageFull(100);
+
this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(100);
+ this.datasource.getPoolProperties().setRemoveAbandoned(true);
+ this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1);
+ Connection con = datasource.getConnection();
+ long start = System.currentTimeMillis();
+ assertEquals("Number of connections active/busy should be
1",1,datasource.getPool().getActive());
+ Thread.sleep(2000);
+ assertEquals("Number of connections active/busy should be
1",1,datasource.getPool().getActive());
+ con.close();
+ }
+
+ public void testResetConnection() throws Exception {
+ int size = 1;
+ this.init();
+ this.datasource.setMaxActive(size);
+ this.datasource.setMaxIdle(size);
+ this.datasource.setInitialSize(0);
+ this.datasource.getPoolProperties().setAbandonWhenPercentageFull(100);
+
this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(100);
+ this.datasource.getPoolProperties().setRemoveAbandoned(true);
+ this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1);
+
this.datasource.getPoolProperties().setJdbcInterceptors(ResetAbandonedTimer.class.getName());
+ Connection con = datasource.getConnection();
+ long start = System.currentTimeMillis();
+ assertEquals("Number of connections active/busy should be
1",1,datasource.getPool().getActive());
+ for (int i=0; i<20; i++) {
+ Thread.sleep(200);
+ con.isClosed();
+ }
+ assertEquals("Number of connections active/busy should be
1",1,datasource.getPool().getActive());
+ con.close();
+ }
+
+ public void testHalfway() throws Exception {
+ int size = 100;
+ this.init();
+ this.datasource.setMaxActive(size);
+ this.datasource.setMaxIdle(size);
+ this.datasource.setInitialSize(0);
+ this.datasource.getPoolProperties().setAbandonWhenPercentageFull(50);
+
this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(500);
+ this.datasource.getPoolProperties().setRemoveAbandoned(true);
+ this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1);
+ Connection[] con = new Connection[size];
+ con[0] = datasource.getConnection();
+ long start = System.currentTimeMillis();
+ assertEquals("Number of connections active/busy should be
1",1,datasource.getPool().getActive());
+ for (int i=1; i<25; i++) {
+ con[i] = datasource.getConnection();
+ }
+ assertEquals("Number of connections active/busy should be
25",25,datasource.getPool().getActive());
+ Thread.sleep(2500);
+ assertEquals("Number of connections active/busy should be
25",25,datasource.getPool().getActive());
+ for (int i=25; i<con.length; i++) {
+ con[i] = datasource.getConnection();
+ }
+ int active = datasource.getPool().getActive();
+ System.out.println("Active!:"+active);
+ assertEquals("Number of connections active/busy should be
"+con.length,con.length,datasource.getPool().getActive());
+ Thread.sleep(2500);
+ assertEquals("Number of connections active/busy should be
0",0,datasource.getPool().getActive());
+ }
+}
Propchange:
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/AbandonPercentageTest.java
------------------------------------------------------------------------------
svn:eol-style = native
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]