You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ps...@apache.org on 2009/03/20 18:07:45 UTC

svn commit: r756628 - in /commons/proper/dbcp/trunk: src/java/org/apache/commons/dbcp/ src/test/org/apache/commons/dbcp/ xdocs/

Author: psteitz
Date: Fri Mar 20 17:07:44 2009
New Revision: 756628

URL: http://svn.apache.org/viewvc?rev=756628&view=rev
Log:
Added a validationQueryTimeout configuration parameter to BasicDataSource
allowing the user to specify a timeout value (in seconds) for connection
validation queries. 
JIRA: DBCP-226

Modified:
    commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/BasicDataSource.java
    commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/PoolableConnectionFactory.java
    commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/TestBasicDataSource.java
    commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/TesterStatement.java
    commons/proper/dbcp/trunk/xdocs/changes.xml

Modified: commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/BasicDataSource.java
URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/BasicDataSource.java?rev=756628&r1=756627&r2=756628&view=diff
==============================================================================
--- commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/BasicDataSource.java (original)
+++ commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/BasicDataSource.java Fri Mar 20 17:07:44 2009
@@ -811,6 +811,42 @@
     }
     
     /**
+     * Timeout in seconds before connection validation queries fail. 
+     * 
+     * @since 1.3
+     */
+    protected int validationQueryTimeout = -1;
+    
+    /**
+     * Returns the validation query timeout.
+     * 
+     * @return the timeout in seconds before connection validation queries fail.
+     * @since 1.3
+     */
+    public synchronized int getValidationQueryTimeout() {
+        return validationQueryTimeout;
+    }
+    
+    /**
+     * Sets the validation query timeout, the amount of time, in seconds, that
+     * connection validation will wait for a response from the database when
+     * executing a validation query.  Use a value less than or equal to 0 for
+     * no timeout.
+     * <p>
+     * Note: this method currently has no effect once the pool has been
+     * initialized.  The pool is initialized the first time one of the
+     * following methods is invoked: <code>getConnection, setLogwriter,
+     * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
+     * 
+     * @param timeout new validation query timeout value in seconds
+     * @since 1.3
+     */
+    public synchronized void setValidationQueryTimeout(int timeout) {
+        this.validationQueryTimeout = timeout;
+        restartNeeded = true;
+    }
+    
+    /**
      * These SQL statements run once after a Connection is created.
      * <p>
      * This property can be used for example to run ALTER SESSION SET
@@ -1303,6 +1339,7 @@
                                               connectionPool,
                                               statementPoolFactory,
                                               validationQuery,
+                                              validationQueryTimeout,
                                               connectionInitSqls,
                                               defaultReadOnly,
                                               defaultAutoCommit,

Modified: commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/PoolableConnectionFactory.java
URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/PoolableConnectionFactory.java?rev=756628&r1=756627&r2=756628&view=diff
==============================================================================
--- commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/PoolableConnectionFactory.java (original)
+++ commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/PoolableConnectionFactory.java Fri Mar 20 17:07:44 2009
@@ -79,6 +79,52 @@
         _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
         _defaultAutoCommit = defaultAutoCommit;
     }
+    
+    /**
+     * Create a new <tt>PoolableConnectionFactory</tt>.
+     * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
+     * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
+     * @param stmtPoolFactory the {@link KeyedObjectPoolFactory} to use to create {@link KeyedObjectPool}s for pooling {@link java.sql.PreparedStatement}s, or <tt>null</tt> to disable {@link java.sql.PreparedStatement} pooling
+     * @param validationQuery a query to use to {@link #validateObject validate} {@link Connection}s.  Should return at least one row. Using <tt>null</tt> turns off validation.
+     * @param validationQueryTimeout the number of seconds that validation queries will wait for database response before failing.  Use a value less than or equal to 0 for no timeout.
+     * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
+     * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
+     * @since 1.3
+     */
+    public PoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, int validationQueryTimeout, boolean defaultReadOnly, boolean defaultAutoCommit) {
+        _connFactory = connFactory;
+        _pool = pool;
+        _pool.setFactory(this);
+        _stmtPoolFactory = stmtPoolFactory;
+        _validationQuery = validationQuery;
+        _validationQueryTimeout = validationQueryTimeout;
+        _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
+        _defaultAutoCommit = defaultAutoCommit;
+    }
+    
+    /**
+     * Create a new <tt>PoolableConnectionFactory</tt>.
+     * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
+     * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
+     * @param stmtPoolFactory the {@link KeyedObjectPoolFactory} to use to create {@link KeyedObjectPool}s for pooling {@link java.sql.PreparedStatement}s, or <tt>null</tt> to disable {@link java.sql.PreparedStatement} pooling
+     * @param validationQuery a query to use to {@link #validateObject validate} {@link Connection}s.  Should return at least one row. Using <tt>null</tt> turns off validation.
+     * @param validationQueryTimeout the number of seconds that validation queries will wait for database response before failing.  Use a value less than or equal to 0 for no timeout.
+     * @param connectionInitSqls a Collection of SQL statements to initialize {@link Connection}s. Using <tt>null</tt> turns off initialization.
+     * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
+     * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
+     * @since 1.3
+     */
+    public PoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, int validationQueryTimeout, Collection connectionInitSqls, boolean defaultReadOnly, boolean defaultAutoCommit) {
+        _connFactory = connFactory;
+        _pool = pool;
+        _pool.setFactory(this);
+        _stmtPoolFactory = stmtPoolFactory;
+        _validationQuery = validationQuery;
+        _validationQueryTimeout = validationQueryTimeout;
+        _connectionInitSqls = connectionInitSqls;
+        _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
+        _defaultAutoCommit = defaultAutoCommit;
+    }
 
     /**
      * Create a new <tt>PoolableConnectionFactory</tt>.
@@ -124,6 +170,56 @@
         _defaultAutoCommit = defaultAutoCommit;
         _defaultTransactionIsolation = defaultTransactionIsolation;
     }
+    
+    /**
+     * Create a new <tt>PoolableConnectionFactory</tt>.
+     * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
+     * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
+     * @param stmtPoolFactory the {@link KeyedObjectPoolFactory} to use to create {@link KeyedObjectPool}s for pooling {@link java.sql.PreparedStatement}s, or <tt>null</tt> to disable {@link java.sql.PreparedStatement} pooling
+     * @param validationQuery a query to use to {@link #validateObject validate} {@link Connection}s.  Should return at least one row. Using <tt>null</tt> turns off validation.
+     * @param validationQueryTimeout the number of seconds that validation queries will wait for database response before failing.  Use a value less than or equal to 0 for no timeout.
+     * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
+     * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
+     * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
+     * @since 1.3
+     */
+    public PoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, int validationQueryTimeout, boolean defaultReadOnly, boolean defaultAutoCommit, int defaultTransactionIsolation) {
+        _connFactory = connFactory;
+        _pool = pool;
+        _pool.setFactory(this);
+        _stmtPoolFactory = stmtPoolFactory;
+        _validationQuery = validationQuery;
+        _validationQueryTimeout = validationQueryTimeout;
+        _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
+        _defaultAutoCommit = defaultAutoCommit;
+        _defaultTransactionIsolation = defaultTransactionIsolation;
+    }
+    
+    /**
+     * Create a new <tt>PoolableConnectionFactory</tt>.
+     * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
+     * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
+     * @param stmtPoolFactory the {@link KeyedObjectPoolFactory} to use to create {@link KeyedObjectPool}s for pooling {@link java.sql.PreparedStatement}s, or <tt>null</tt> to disable {@link java.sql.PreparedStatement} pooling
+     * @param validationQuery a query to use to {@link #validateObject validate} {@link Connection}s.  Should return at least one row. Using <tt>null</tt> turns off validation.
+     * @param validationQueryTimeout the number of seconds that validation queries will wait for database response before failing.  Use a value less than or equal to 0 for no timeout.
+     * @param connectionInitSqls a Collection of SQL statement to initialize {@link Connection}s. Using <tt>null</tt> turns off initialization.
+     * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
+     * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
+     * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
+     * @since 1.3
+     */
+    public PoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, int validationQueryTimeout, Collection connectionInitSqls, boolean defaultReadOnly, boolean defaultAutoCommit, int defaultTransactionIsolation) {
+        _connFactory = connFactory;
+        _pool = pool;
+        _pool.setFactory(this);
+        _stmtPoolFactory = stmtPoolFactory;
+        _validationQuery = validationQuery;
+        _validationQueryTimeout = validationQueryTimeout;
+        _connectionInitSqls = connectionInitSqls;
+        _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
+        _defaultAutoCommit = defaultAutoCommit;
+        _defaultTransactionIsolation = defaultTransactionIsolation;
+    }
 
     /**
      * Create a new <tt>PoolableConnectionFactory</tt>.
@@ -297,6 +393,87 @@
         _defaultTransactionIsolation = defaultTransactionIsolation;
         _defaultCatalog = defaultCatalog;
     }
+    
+    /**
+     * Create a new <tt>PoolableConnectionFactory</tt>.
+     * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
+     * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
+     * @param stmtPoolFactory the {@link KeyedObjectPoolFactory} to use to create {@link KeyedObjectPool}s for pooling {@link java.sql.PreparedStatement}s, or <tt>null</tt> to disable {@link java.sql.PreparedStatement} pooling
+     * @param validationQuery a query to use to {@link #validateObject validate} {@link Connection}s.  Should return at least one row. Using <tt>null</tt> turns off validation.
+     * @param validationQueryTimeout the number of seconds that validation queries will wait for database response before failing.  Use a value less than or equal to 0 for no timeout.
+     * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
+     * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
+     * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
+     * @param defaultCatalog the default "catalog" setting for returned {@link Connection}s
+     * @param config the AbandonedConfig if tracing SQL objects
+     * @since 1.3
+     */
+    public PoolableConnectionFactory(
+        ConnectionFactory connFactory,
+        ObjectPool pool,
+        KeyedObjectPoolFactory stmtPoolFactory,
+        String validationQuery,
+        int validationQueryTimeout,
+        Boolean defaultReadOnly,
+        boolean defaultAutoCommit,
+        int defaultTransactionIsolation,
+        String defaultCatalog,
+        AbandonedConfig config) {
+
+        _connFactory = connFactory;
+        _pool = pool;
+        _config = config;
+        _pool.setFactory(this);
+        _stmtPoolFactory = stmtPoolFactory;
+        _validationQuery = validationQuery;
+        _validationQueryTimeout = validationQueryTimeout;
+        _defaultReadOnly = defaultReadOnly;
+        _defaultAutoCommit = defaultAutoCommit;
+        _defaultTransactionIsolation = defaultTransactionIsolation;
+        _defaultCatalog = defaultCatalog;
+    }
+    
+    /**
+     * Create a new <tt>PoolableConnectionFactory</tt>.
+     * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
+     * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
+     * @param stmtPoolFactory the {@link KeyedObjectPoolFactory} to use to create {@link KeyedObjectPool}s for pooling {@link java.sql.PreparedStatement}s, or <tt>null</tt> to disable {@link java.sql.PreparedStatement} pooling
+     * @param validationQuery a query to use to {@link #validateObject validate} {@link Connection}s.  Should return at least one row. Using <tt>null</tt> turns off validation.
+     * @param validationQueryTimeout the number of seconds that validation queries will wait for database response before failing.  Use a value less than or equal to 0 for no timeout.
+     * @param connectionInitSqls a Collection of SQL statements to initialize {@link Connection}s. Using <tt>null</tt> turns off initialization.
+     * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
+     * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
+     * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
+     * @param defaultCatalog the default "catalog" setting for returned {@link Connection}s
+     * @param config the AbandonedConfig if tracing SQL objects
+     * @since 1.3
+     */
+    public PoolableConnectionFactory(
+        ConnectionFactory connFactory,
+        ObjectPool pool,
+        KeyedObjectPoolFactory stmtPoolFactory,
+        String validationQuery,
+        int validationQueryTimeout,
+        Collection connectionInitSqls,
+        Boolean defaultReadOnly,
+        boolean defaultAutoCommit,
+        int defaultTransactionIsolation,
+        String defaultCatalog,
+        AbandonedConfig config) {
+
+        _connFactory = connFactory;
+        _pool = pool;
+        _config = config;
+        _pool.setFactory(this);
+        _stmtPoolFactory = stmtPoolFactory;
+        _validationQuery = validationQuery;
+        _validationQueryTimeout = validationQueryTimeout;
+        _connectionInitSqls = connectionInitSqls;
+        _defaultReadOnly = defaultReadOnly;
+        _defaultAutoCommit = defaultAutoCommit;
+        _defaultTransactionIsolation = defaultTransactionIsolation;
+        _defaultCatalog = defaultCatalog;
+    }
 
     /**
      * Sets the {@link ConnectionFactory} from which to obtain base {@link Connection}s.
@@ -315,6 +492,19 @@
     synchronized public void setValidationQuery(String validationQuery) {
         _validationQuery = validationQuery;
     }
+    
+    /**
+     * Sets the validation query timeout, the amount of time, in seconds, that
+     * connection validation will wait for a response from the database when
+     * executing a validation query.  Use a value less than or equal to 0 for
+     * no timeout.
+     *
+     * @param timeout new validation query timeout value in seconds
+     * @since 1.3
+     */
+    synchronized public void setValidationQueryTimeout(int timeout) {
+        _validationQueryTimeout = timeout;
+    }
 
     /**
      * Sets the SQL statements I use to initialize newly created {@link Connection}s.
@@ -465,6 +655,9 @@
             ResultSet rset = null;
             try {
                 stmt = conn.createStatement();
+                if (_validationQueryTimeout > 0) {
+                    stmt.setQueryTimeout(_validationQueryTimeout);
+                }
                 rset = stmt.executeQuery(query);
                 if(!rset.next()) {
                     throw new SQLException("validationQuery didn't return a row");
@@ -531,6 +724,7 @@
 
     protected ConnectionFactory _connFactory = null;
     protected String _validationQuery = null;
+    protected int _validationQueryTimeout = -1;
     protected Collection _connectionInitSqls = null;
     protected ObjectPool _pool = null;
     protected KeyedObjectPoolFactory _stmtPoolFactory = null;

Modified: commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/TestBasicDataSource.java
URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/TestBasicDataSource.java?rev=756628&r1=756627&r2=756628&view=diff
==============================================================================
--- commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/TestBasicDataSource.java (original)
+++ commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/TestBasicDataSource.java Fri Mar 20 17:07:44 2009
@@ -234,6 +234,43 @@
             }
         }
     }
+    
+    public void testValidationQueryTimoutFail() {
+        ds.setTestOnBorrow(true);
+        ds.setValidationQueryTimeout(3); // Too fast for TesterStatement
+        try {
+            ds.getConnection();
+            fail("expected SQLException");
+        } catch (SQLException ex) {
+            if (ex.toString().indexOf("timeout") < 0) {
+                fail("expected timeout error message");
+            }
+        }
+    }
+    
+    public void testValidationQueryTimeoutZero() throws Exception {
+        ds.setTestOnBorrow(true);
+        ds.setTestOnReturn(true);
+        ds.setValidationQueryTimeout(0);
+        Connection con = ds.getConnection();
+        con.close();
+    }
+    
+    public void testValidationQueryTimeoutNegative() throws Exception {
+        ds.setTestOnBorrow(true);
+        ds.setTestOnReturn(true);
+        ds.setValidationQueryTimeout(-1);
+        Connection con = ds.getConnection();
+        con.close();
+    }
+    
+    public void testValidationQueryTimeoutSucceed() throws Exception {
+        ds.setTestOnBorrow(true);
+        ds.setTestOnReturn(true);
+        ds.setValidationQueryTimeout(100); // Works for TesterStatement
+        Connection con = ds.getConnection();
+        con.close();
+    }
 
     public void testEmptyInitConnectionSql() throws Exception {
         ds.setConnectionInitSqls(Arrays.asList(new String[]{"", "   "}));

Modified: commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/TesterStatement.java
URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/TesterStatement.java?rev=756628&r1=756627&r2=756628&view=diff
==============================================================================
--- commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/TesterStatement.java (original)
+++ commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/TesterStatement.java Fri Mar 20 17:07:44 2009
@@ -60,15 +60,22 @@
         checkOpen();
         if("null".equals(sql)) {
             return null;
-        } if("invalid".equals(sql)) {
+        } 
+        if("invalid".equals(sql)) {
             throw new SQLException("invalid query");
-        } if ("broken".equals(sql)) {
+        }
+        if ("broken".equals(sql)) {
             throw new SQLException("broken connection");
-        } if("select username".equals(sql)) {
+        }  
+        if("select username".equals(sql)) {
             String username = ((TesterConnection) _connection).getUsername();
             Object[][] data = {{username}};
             return new TesterResultSet(this, data);
         } else {
+            // Simulate timeout if queryTimout is set to less than 5 seconds
+            if (_queryTimeout > 0 && _queryTimeout < 5) { 
+                throw new SQLException("query timeout");
+            }
             return new TesterResultSet(this);
         }
     }

Modified: commons/proper/dbcp/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/xdocs/changes.xml?rev=756628&r1=756627&r2=756628&view=diff
==============================================================================
--- commons/proper/dbcp/trunk/xdocs/changes.xml (original)
+++ commons/proper/dbcp/trunk/xdocs/changes.xml Fri Mar 20 17:07:44 2009
@@ -42,6 +42,11 @@
      new features as well as bug fixes and instrumentation.  Some bug fixes
      will change semantics (e.g. connection close will become idempotent).
      The minimum JDK level will be increased to 1.4">
+      <action dev="psteitz" type="update" issue="DBCP-226">
+        Added a validationQueryTimeout configuration parameter to BasicDataSource
+        allowing the user to specify a timeout value (in seconds) for connection
+        validation queries. 
+      </action>
       <action dev="psteitz" type="update" issue="DBCP-175" due-to="Jiri Melichna and Jerome Lacoste">
         Added a connectionInitSqls configuration parameter to BasicDataSource
         allowing the user to specify a collection of SQL statements to execute