Author: fhanik Date: Sun Nov 20 18:24:16 2011 New Revision: 1204203 URL: http://svn.apache.org/viewvc?rev=1204203&view=rev Log: 1. Implement a query timeout intercept to allow for timeouts to be set when statemements are created 2. Implement rollbackOnReturn and commitOnReturn attributes for connections that have autocommit=false
Added: tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/QueryTimeoutInterceptor.java tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestQueryTimeoutInterceptor.java Modified: tomcat/trunk/modules/jdbc-pool/doc/changelog.xml tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Statement.java Modified: tomcat/trunk/modules/jdbc-pool/doc/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/doc/changelog.xml?rev=1204203&r1=1204202&r2=1204203&view=diff ============================================================================== --- tomcat/trunk/modules/jdbc-pool/doc/changelog.xml (original) +++ tomcat/trunk/modules/jdbc-pool/doc/changelog.xml Sun Nov 20 18:24:16 2011 @@ -33,6 +33,7 @@ <changelog> <fix><rev>1073531</rev> <bug>50805</bug> Only initialize connections once when async (fhanik)</fix> <fix><rev>1076380</rev> <bug>50857</bug> Correctly handle timeouts when the pool is busy when async (fhanik)</fix> + <add>Added QueryTimeoutInterceptor to be able to configure timeouts on running queries automatically.</add> </changelog> </subsection> </section> 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=1204203&r1=1204202&r2=1204203&view=diff ============================================================================== --- tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml (original) +++ tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml Sun Nov 20 18:24:16 2011 @@ -416,6 +416,17 @@ logged and a JMX notification gets sent once. </p> </attribute> + <attribute name="rollbackOnReturn" required="false"> + <p>(boolean) If <code>autoCommit==false</code> then the pool can terminate the transaction by calling rollback on the connection as it is returned to the pool + Default value is <code>false</code>.<br/> + </p> + </attribute> + <attribute name="commitOnReturn" required="false"> + <p>(boolean) If <code>autoCommit==false</code> then the pool can complete the transaction by calling commit on the connection as it is returned to the pool + If <code>rollbackOnReturn==true</code> then this attribute is ignored. + Default value is <code>false</code>.<br/> + </p> + </attribute> <attribute name="alternateUsernameAllowed" required="false"> <p>(boolean) By default, the jdbc-pool will ignore the <a href="http://download.oracle.com/javase/6/docs/api/javax/sql/DataSource.html#getConnection(java.lang.String,%20java.lang.String)"><code>DataSource.getConnection(username,password)</code></a> @@ -504,6 +515,18 @@ <attributes> </attributes> </subsection> + <subsection name="org.apache.tomcat.jdbc.pool.interceptor.QueryTimeoutInterceptor"> + <p>Automatically calls java.sql.Statement.setQueryTimeout(seconds) when a new statement is created. + The pool itself doesn't timeout the query, it is still up to the JDBC driver to enforce query timeouts. + </p> + <attributes> + <attribute name="queryTimeout" required="true"> + <p>(int as String) The number of seconds to set for the query timeout + The default value is <code>1000</code> milliseconds. + </p> + </attribute> + </attributes> + </subsection> <subsection name="org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReport"> <p>Keeps track of query performance and issues log entries when queries exceed a time threshold of fail. The log level used is <code>WARN</code> Modified: tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java?rev=1204203&r1=1204202&r2=1204203&view=diff ============================================================================== --- tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java (original) +++ tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java Sun Nov 20 18:24:16 2011 @@ -777,6 +777,28 @@ public class ConnectionPool { } } } + /** + * return true if the connection TX termination succeeded + * @param con + * @return + */ + protected boolean terminateTransaction(PooledConnection con) { + try { + boolean autocommit = con.getConnection().getAutoCommit(); + if (!autocommit) { + if (this.getPoolProperties().getRollbackOnReturn()) { + con.getConnection().rollback(); + } else if (this.getPoolProperties().getCommitOnReturn()) { + con.getConnection().commit(); + } + } + return true; + } catch (SQLException x) { + log.warn("Unable to terminate transaction, connection will be closed.",x); + return false; + } + + } /** * Determines if a connection should be closed upon return to the pool. @@ -788,6 +810,7 @@ public class ConnectionPool { if (con.isDiscarded()) return true; if (isClosed()) return true; if (!con.validate(action)) return true; + if (!terminateTransaction(con)) return true; if (getPoolProperties().getMaxAge()>0 ) { return (System.currentTimeMillis()-con.getLastConnected()) > getPoolProperties().getMaxAge(); } else { Modified: tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java?rev=1204203&r1=1204202&r2=1204203&view=diff ============================================================================== --- tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java (original) +++ tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java Sun Nov 20 18:24:16 2011 @@ -1194,4 +1194,32 @@ public class DataSourceProxy implements getPoolProperties().setAlternateUsernameAllowed(alternateUsernameAllowed); } + /** + * {@inheritDoc} + */ + public void setCommitOnReturn(boolean commitOnReturn) { + getPoolProperties().setCommitOnReturn(commitOnReturn); + } + + /** + * {@inheritDoc} + */ + public boolean getCommitOnReturn() { + return getPoolProperties().getCommitOnReturn(); + } + + /** + * {@inheritDoc} + */ + public void setRollbackOnReturn(boolean rollbackOnReturn) { + getPoolProperties().setRollbackOnReturn(rollbackOnReturn); + } + + /** + * {@inheritDoc} + */ + public boolean getRollbackOnReturn() { + return getPoolProperties().getRollbackOnReturn(); + } + } Modified: tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java?rev=1204203&r1=1204202&r2=1204203&view=diff ============================================================================== --- tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java (original) +++ tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java Sun Nov 20 18:24:16 2011 @@ -793,6 +793,34 @@ public interface PoolConfiguration { * false if it is to be ignored. */ public void setAlternateUsernameAllowed(boolean alternateUsernameAllowed); + /** + * Set to true if you want the connection pool to commit any pending transaction when a connection is returned. + * The default value is false, as this could result in committing data. + * This parameter is only looked at if the {@link java.sql.Connection#getAutoCommit()} returns false + * @param commitOnReturn set to true if the pool should call {@link java.sql.Connection#commit()} when a connection is returned to the pool. + * Default is false + */ + public void setCommitOnReturn(boolean commitOnReturn); + + /** + * @see {@link PoolConfiguration#setCommitOnReturn(boolean)} + * @return + */ + public boolean getCommitOnReturn(); + + /** + * Set to true if you want the connection pool to rollback any pending transaction when a connection is returned. + * The default value is false, as this could result in committing data. + * This parameter is only looked at if the {@link java.sql.Connection#getAutoCommit()} returns false + * @param rollbackOnReturn set to true if the pool should call {@link java.sql.Connection#rollback()} when a connection is returned to the pool. + * Default is false + */ + public void setRollbackOnReturn(boolean rollbackOnReturn); + + /** + * @see {@link PoolConfiguration#setRollbackOnReturn(boolean)} + * @return + */ + public boolean getRollbackOnReturn(); - -} \ No newline at end of file +} Modified: tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java?rev=1204203&r1=1204202&r2=1204203&view=diff ============================================================================== --- tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java (original) +++ tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java Sun Nov 20 18:24:16 2011 @@ -83,12 +83,13 @@ public class PoolProperties implements P protected Object dataSource = null; protected String dataSourceJNDI = null; protected boolean alternateUsernameAllowed = false; - - + protected boolean commitOnReturn = false; + protected boolean rollbackOnReturn = false; + + /** * {@inheritDoc} */ - @Override public void setAbandonWhenPercentageFull(int percentage) { if (percentage<0) abandonWhenPercentageFull = 0; @@ -99,7 +100,6 @@ public class PoolProperties implements P /** * {@inheritDoc} */ - @Override public int getAbandonWhenPercentageFull() { return abandonWhenPercentageFull; @@ -108,7 +108,6 @@ public class PoolProperties implements P /** * {@inheritDoc} */ - @Override public boolean isFairQueue() { return fairQueue; @@ -117,7 +116,6 @@ public class PoolProperties implements P /** * {@inheritDoc} */ - @Override public void setFairQueue(boolean fairQueue) { this.fairQueue = fairQueue; @@ -126,7 +124,6 @@ public class PoolProperties implements P /** * {@inheritDoc} */ - @Override public boolean isAccessToUnderlyingConnectionAllowed() { return accessToUnderlyingConnectionAllowed; @@ -1164,4 +1161,32 @@ public class PoolProperties implements P this.alternateUsernameAllowed = alternateUsernameAllowed; } + + /** + * {@inheritDoc} + */ + public void setCommitOnReturn(boolean commitOnReturn) { + this.commitOnReturn = commitOnReturn; + } + + /** + * {@inheritDoc} + */ + public boolean getCommitOnReturn() { + return this.commitOnReturn; + } + + /** + * {@inheritDoc} + */ + public void setRollbackOnReturn(boolean rollbackOnReturn) { + this.rollbackOnReturn = rollbackOnReturn; + } + + /** + * {@inheritDoc} + */ + public boolean getRollbackOnReturn() { + return this.rollbackOnReturn; + } } Added: tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/QueryTimeoutInterceptor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/QueryTimeoutInterceptor.java?rev=1204203&view=auto ============================================================================== --- tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/QueryTimeoutInterceptor.java (added) +++ tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/QueryTimeoutInterceptor.java Sun Nov 20 18:24:16 2011 @@ -0,0 +1,39 @@ +package org.apache.tomcat.jdbc.pool.interceptor; + +import java.lang.reflect.Method; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Map; + +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty; + +public class QueryTimeoutInterceptor extends AbstractCreateStatementInterceptor { + private static Log log = LogFactory.getLog(QueryTimeoutInterceptor.class); + int timeout; + + @Override + public void setProperties(Map<String,InterceptorProperty> properties) { + super.setProperties(properties); + timeout = properties.get("queryTimeout").getValueAsInt(-1); + } + + @Override + public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) { + if (statement instanceof Statement && timeout > 0) { + Statement s = (Statement)statement; + try { + s.setQueryTimeout(timeout); + }catch (SQLException x) { + log.warn("[QueryTimeoutInterceptor] Unable to set query timeout:"+x.getMessage(),x); + } + } + return statement; + } + + @Override + public void closeInvoked() { + } + +} Modified: tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java?rev=1204203&r1=1204202&r2=1204203&view=diff ============================================================================== --- tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java (original) +++ tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java Sun Nov 20 18:24:16 2011 @@ -744,7 +744,34 @@ public class ConnectionPool extends Noti public void setValidator(Validator validator) { //noop } + + /** + * {@inheritDoc} + */ + public void setCommitOnReturn(boolean commitOnReturn) { + getPoolProperties().setCommitOnReturn(commitOnReturn); + } + /** + * {@inheritDoc} + */ + public boolean getCommitOnReturn() { + return getPoolProperties().getCommitOnReturn(); + } + /** + * {@inheritDoc} + */ + public void setRollbackOnReturn(boolean rollbackOnReturn) { + getPoolProperties().setRollbackOnReturn(rollbackOnReturn); + } + + /** + * {@inheritDoc} + */ + public boolean getRollbackOnReturn() { + return getPoolProperties().getRollbackOnReturn(); + } + } Added: tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestQueryTimeoutInterceptor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestQueryTimeoutInterceptor.java?rev=1204203&view=auto ============================================================================== --- tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestQueryTimeoutInterceptor.java (added) +++ tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestQueryTimeoutInterceptor.java Sun Nov 20 18:24:16 2011 @@ -0,0 +1,66 @@ +/* + * 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 java.sql.Statement; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import javax.sql.PooledConnection; + + +import org.apache.tomcat.jdbc.pool.interceptor.QueryTimeoutInterceptor; +import org.apache.tomcat.jdbc.test.driver.Driver; + + +public class TestQueryTimeoutInterceptor extends DefaultTestCase { + + private static final int iterations = 500000; //(new Random(System.currentTimeMillis())).nextInt(1000000)+100000; + public TestQueryTimeoutInterceptor(String name) { + super(name); + } + + public void testTimeout() throws Exception { + long start = System.currentTimeMillis(); + int timeout = 10; + int withoutuser =10; + int withuser = withoutuser; + this.init(); + this.datasource.setMaxActive(withuser+withoutuser); + this.datasource.setJdbcInterceptors(QueryTimeoutInterceptor.class.getName()+"(queryTimeout="+timeout+")"); + this.datasource.setDriverClassName(Driver.class.getName()); + this.datasource.setUrl("jdbc:tomcat:test"); + Connection con = this.datasource.getConnection(); + Statement st = con.createStatement(); + assertEquals(st.getClass().getName(),timeout,st.getQueryTimeout()); + st.close(); + st = con.prepareStatement(""); + assertEquals(st.getClass().getName(),timeout,st.getQueryTimeout()); + st.close(); + st = con.prepareCall(""); + assertEquals(st.getClass().getName(),timeout,st.getQueryTimeout()); + st.close(); + con.close(); + } +} Modified: tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Statement.java URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Statement.java?rev=1204203&r1=1204202&r2=1204203&view=diff ============================================================================== --- tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Statement.java (original) +++ tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Statement.java Sun Nov 20 18:24:16 2011 @@ -41,7 +41,7 @@ import java.util.Calendar; import java.util.Map; public class Statement implements CallableStatement { - + int timeout=-1; @Override public Array getArray(int parameterIndex) throws SQLException { // TODO Auto-generated method stub @@ -1179,7 +1179,7 @@ public class Statement implements Callab @Override public int getQueryTimeout() throws SQLException { // TODO Auto-generated method stub - return 0; + return timeout; } @Override @@ -1275,6 +1275,7 @@ public class Statement implements Callab @Override public void setQueryTimeout(int seconds) throws SQLException { // TODO Auto-generated method stub + this.timeout = seconds; } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org