From 2b0a0893e7bf5d8c12dad86b6b11b235d325efc1 Mon Sep 17 00:00:00 2001 From: fhanik Date: Thu, 23 Apr 2009 14:40:16 +0000 Subject: [PATCH] Configure fair queue by default, its faster. Implement logic around when/how connections are treated as abandoned. First one is by pool utilization, abandonWhenPercentageFull, the second one is to add a ResetAbandonTimer interceptor, so when successful invokations take place on the connection, it resets the time git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@767934 13f79535-47bb-0310-9956-ffa450edef68 --- modules/jdbc-pool/doc/jdbc-pool.xml | 21 +++++ .../apache/tomcat/jdbc/pool/ConnectionPool.java | 10 +++ .../org/apache/tomcat/jdbc/pool/DataSource.java | 8 ++ .../apache/tomcat/jdbc/pool/DataSourceFactory.java | 12 ++- .../apache/tomcat/jdbc/pool/PoolProperties.java | 17 +++- .../jdbc/pool/interceptor/AbstractQueryReport.java | 1 - .../jdbc/pool/interceptor/ResetAbandonedTimer.java | 93 ++++++++++++++++++++++ .../tomcat/jdbc/pool/jmx/ConnectionPool.java | 3 + .../tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java | 2 + 9 files changed, 160 insertions(+), 7 deletions(-) create mode 100644 modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java diff --git a/modules/jdbc-pool/doc/jdbc-pool.xml b/modules/jdbc-pool/doc/jdbc-pool.xml index 27880ce77..84cf4eac9 100644 --- a/modules/jdbc-pool/doc/jdbc-pool.xml +++ b/modules/jdbc-pool/doc/jdbc-pool.xml @@ -329,6 +329,15 @@ This flag is required when you want to use asynchronous connection retrieval.

+ + +

(int) Connections that have been abandoned (timed out) wont get closed and reported up unless + the number of connections in use are above the percentage defined by abandonWhenPercentageFull. + The value should be between 0-100. + The default value is 0, which implies that connections are eligible for closure as soon + as removeAbandonedTimeout has been reached.

+
+

(boolean) Set to true if you wish the ProxyConnection class to use String.equals instead of == when comparing method names. This property does not apply to added interceptors as those are configured individually. @@ -419,6 +428,18 @@ + +

+ The abandoned timer starts when a connection is checked out from the pool. + This means if you have a 30second timeout and run 10x10second queries using the connection + it will be marked abandoned and potentially reclaimed depending on the abandonWhenPercentageFull + attribute. + Using this interceptor it will reset the checkout timer every time you perform an operation on the connection or execute a + query successfully. +

+ + +
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java index 2cea90d2b..f5a39a255 100644 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java +++ b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java @@ -654,9 +654,19 @@ public class ConnectionPool { } //end if } //checkIn + public 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; + } + public void checkAbandoned() { try { if (busy.size()==0) return; + if (!shouldAbandon()) return; Iterator locked = busy.iterator(); while (locked.hasNext()) { PooledConnection con = locked.next(); diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSource.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSource.java index 94b84a68c..65eb82ddd 100644 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSource.java +++ b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSource.java @@ -374,6 +374,14 @@ public class DataSource extends DataSourceProxy implements MBeanRegistration,jav } } + public int getAbandonWhenPercentageFull() { + try { + return createPool().getPoolProperties().getAbandonWhenPercentageFull(); + }catch (SQLException x) { + throw new RuntimeException(x); + } + } + public boolean isTestOnBorrow() { try { return createPool().getPoolProperties().isTestOnBorrow(); diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java index d78388bf3..ac09e202c 100644 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java +++ b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java @@ -94,6 +94,7 @@ public class DataSourceFactory implements ObjectFactory { protected final static String PROP_REMOVEABANDONED = "removeAbandoned"; protected final static String PROP_REMOVEABANDONEDTIMEOUT = "removeAbandonedTimeout"; protected final static String PROP_LOGABANDONED = "logAbandoned"; + protected final static String PROP_ABANDONWHENPERCENTAGEFULL = "abandonWhenPercentageFull"; protected final static String PROP_POOLPREPAREDSTATEMENTS = "poolPreparedStatements"; protected final static String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements"; @@ -147,7 +148,8 @@ public class DataSourceFactory implements ObjectFactory { PROP_JMX_ENABLED, PROP_FAIR_QUEUE, PROP_USE_EQUALS, - OBJECT_NAME + OBJECT_NAME, + PROP_ABANDONWHENPERCENTAGEFULL }; // -------------------------------------------------- ObjectFactory Methods @@ -409,9 +411,13 @@ public class DataSourceFactory implements ObjectFactory { if (value != null) { poolProperties.setName(ObjectName.quote(value)); } - - return poolProperties; + value = properties.getProperty(PROP_ABANDONWHENPERCENTAGEFULL); + if (value != null) { + poolProperties.setAbandonWhenPercentageFull(Integer.parseInt(value)); + } + + return poolProperties; } /** diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java index 760d347cd..37e01d244 100644 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java +++ b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java @@ -67,12 +67,23 @@ public class PoolProperties { protected boolean jmxEnabled = true; protected String initSQL; protected boolean testOnConnect =false; - private String jdbcInterceptors=null; - private boolean fairQueue = true; - private boolean useEquals = false; + protected String jdbcInterceptors=null; + protected boolean fairQueue = true; + protected boolean useEquals = false; + protected int abandonWhenPercentageFull = 0; private InterceptorDefinition[] interceptors = null; + public void setAbandonWhenPercentageFull(int percentage) { + if (percentage<0) abandonWhenPercentageFull = 0; + else if (percentage>100) abandonWhenPercentageFull = 100; + else abandonWhenPercentageFull = percentage; + } + + public int getAbandonWhenPercentageFull() { + return abandonWhenPercentageFull; + } + public boolean isFairQueue() { return fairQueue; } diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java index fe8b26eaf..46b1763cc 100644 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java +++ b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java @@ -51,7 +51,6 @@ public abstract class AbstractQueryReport extends AbstractCreateStatementInterce super(); } - /** * Invoked when prepareStatement has been called and completed. * @param sql - the string used to prepare the statement with diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java new file mode 100644 index 000000000..fd0f56759 --- /dev/null +++ b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java @@ -0,0 +1,93 @@ +/* + * 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.pool.interceptor; + +import java.lang.reflect.Method; + +import org.apache.tomcat.jdbc.pool.JdbcInterceptor; +import org.apache.tomcat.jdbc.pool.PooledConnection; +import org.apache.tomcat.jdbc.pool.ProxyConnection; + +/** + * Class that resets the abandoned timer on any activity on the + * Connection or any successful query executions + * @author fhanik + * + */ +public class ResetAbandonedTimer extends AbstractQueryReport { + + public ResetAbandonedTimer() { + // TODO Auto-generated constructor stub + } + + public boolean resetTimer() { + boolean result = false; + JdbcInterceptor interceptor = this.getNext(); + while (interceptor!=null && result==false) { + if (interceptor instanceof ProxyConnection) { + PooledConnection con = ((ProxyConnection)interceptor).getConnection(); + if (con!=null) { + con.setTimestamp(System.currentTimeMillis()); + result = true; + } else { + break; + } + } + interceptor = interceptor.getNext(); + } + return result; + } + + + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + // TODO Auto-generated method stub + Object result = super.invoke(proxy, method, args); + resetTimer(); + return result; + } + + @Override + protected void prepareCall(String query, long time) { + resetTimer(); + } + + @Override + protected void prepareStatement(String sql, long time) { + resetTimer(); + + } + + @Override + public void closeInvoked() { + resetTimer(); + } + + @Override + protected String reportQuery(String query, Object[] args, String name,long start, long delta) { + resetTimer(); + return super.reportQuery(query, args, name, start, delta); + } + + @Override + protected String reportSlowQuery(String query, Object[] args, String name,long start, long delta) { + resetTimer(); + return super.reportSlowQuery(query, args, name, start, delta); + } +} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java index a658d9858..cdc18a1fc 100644 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java +++ b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java @@ -273,5 +273,8 @@ public class ConnectionPool extends NotificationBroadcasterSupport implements Co public int getWaitCount() { return pool.getWaitCount(); } + public int getAbandonWhenPercentageFull() { + return pool.getPoolProperties().getAbandonWhenPercentageFull(); + } } diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java index 904c4beea..1b8711bfa 100644 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java +++ b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java @@ -116,4 +116,6 @@ public interface ConnectionPoolMBean { public String getJdbcInterceptors(); + public int getAbandonWhenPercentageFull(); + } -- 2.11.0