You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by fh...@apache.org on 2011/11/20 19:24:16 UTC

svn commit: r1204203 - in /tomcat/trunk/modules/jdbc-pool: doc/ src/main/java/org/apache/tomcat/jdbc/pool/ src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ src/main/java/org/apache/tomcat/jdbc/pool/jmx/ src/test/java/org/apache/tomcat/jdbc/test/ ...

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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org