Author: markt Date: Thu May 28 19:57:56 2015 New Revision: 1682317 URL: http://svn.apache.org/r1682317 Log: Update DBCP fork to DBCP 2.1 + additional fixes to r1682314
Added: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java - copied, changed from r1682314, commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/LifetimeExceededException.java Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/ (props changed) tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolingDataSource.java tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/SwallowedExceptionLogger.java tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/Utils.java tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionManager.java Propchange: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu May 28 19:57:56 2015 @@ -1 +1 @@ -/commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2:1593516-1631451 +/commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2:1593516-1682314 Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java?rev=1682317&r1=1682316&r2=1682317&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java Thu May 28 19:57:56 2015 @@ -31,8 +31,10 @@ import java.sql.SQLFeatureNotSupportedEx import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Properties; +import java.util.Set; import java.util.logging.Logger; import javax.management.InstanceAlreadyExistsException; @@ -65,7 +67,7 @@ import org.apache.tomcat.dbcp.pool2.impl * @author Dirk Verbeeck * @since 2.0 */ -public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBeanRegistration { +public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBeanRegistration, AutoCloseable { private static final Log log = LogFactory.getLog(BasicDataSource.class); @@ -973,9 +975,11 @@ public class BasicDataSource implements * @return the current number of active connections */ @Override - public synchronized int getNumActive() { - if (connectionPool != null) { - return connectionPool.getNumActive(); + public int getNumActive() { + // Copy reference to avoid NPE if close happens after null check + GenericObjectPool<PoolableConnection> pool = connectionPool; + if (pool != null) { + return pool.getNumActive(); } return 0; } @@ -988,9 +992,11 @@ public class BasicDataSource implements * @return the current number of idle connections */ @Override - public synchronized int getNumIdle() { - if (connectionPool != null) { - return connectionPool.getNumIdle(); + public int getNumIdle() { + // Copy reference to avoid NPE if close happens after null check + GenericObjectPool<PoolableConnection> pool = connectionPool; + if (pool != null) { + return pool.getNumIdle(); } return 0; } @@ -1267,6 +1273,20 @@ public class BasicDataSource implements return maxConnLifetimeMillis; } + private boolean logExpiredConnections = true; + + /** + * When {@link #getMaxConnLifetimeMillis()} is set to limit connection lifetime, + * this property determines whether or not log messages are generated when the + * pool closes connections due to maximum lifetime exceeded. + * + * @since 2.1 + */ + @Override + public boolean getLogExpiredConnections() { + return logExpiredConnections; + } + /** * <p>Sets the maximum permitted lifetime of a connection in * milliseconds. A value of zero or less indicates an infinite lifetime.</p> @@ -1280,6 +1300,16 @@ public class BasicDataSource implements this.maxConnLifetimeMillis = maxConnLifetimeMillis; } + /** + * When {@link #getMaxConnLifetimeMillis()} is set to limit connection lifetime, + * this property determines whether or not log messages are generated when the + * pool closes connections due to maximum lifetime exceeded. Set this property + * to false to suppress log messages when connections expire. + */ + public void setLogExpiredConnections(boolean logExpiredConnections) { + this.logExpiredConnections = logExpiredConnections; + } + private String jmxName = null; /** @@ -1326,7 +1356,6 @@ public class BasicDataSource implements this.enableAutoCommitOnReturn = enableAutoCommitOnReturn; } - private boolean rollbackOnReturn = true; /** @@ -1347,6 +1376,97 @@ public class BasicDataSource implements this.rollbackOnReturn = rollbackOnReturn; } + private volatile Set<String> disconnectionSqlCodes; + + /** + * Returns the set of SQL_STATE codes considered to signal fatal conditions. + * @return fatal disconnection state codes + * @see #setDisconnectionSqlCodes(Collection) + * @since 2.1 + */ + public Set<String> getDisconnectionSqlCodes() { + Set<String> result = disconnectionSqlCodes; + if (result == null) { + return Collections.emptySet(); + } + return result; + } + + /** + * Provides the same data as {@link #getDisconnectionSqlCodes} but in an + * array so it is accessible via JMX. + * @since 2.1 + */ + @Override + public String[] getDisconnectionSqlCodesAsArray() { + Collection<String> result = getDisconnectionSqlCodes(); + return result.toArray(new String[result.size()]); + } + + /** + * Sets the SQL_STATE codes considered to signal fatal conditions. + * <p> + * Overrides the defaults in {@link Utils#DISCONNECTION_SQL_CODES} + * (plus anything starting with {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). + * If this property is non-null and {@link #getFastFailValidation()} is + * {@code true}, whenever connections created by this datasource generate exceptions + * with SQL_STATE codes in this list, they will be marked as "fatally disconnected" + * and subsequent validations will fail fast (no attempt at isValid or validation + * query).</p> + * <p> + * If {@link #getFastFailValidation()} is {@code false} setting this property has no + * effect.</p> + * <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}.</p> + * + * @param disconnectionSqlCodes SQL_STATE codes considered to signal fatal conditions + * @since 2.1 + */ + public void setDisconnectionSqlCodes(Collection<String> disconnectionSqlCodes) { + if (disconnectionSqlCodes != null && disconnectionSqlCodes.size() > 0) { + HashSet<String> newVal = null; + for (String s : disconnectionSqlCodes) { + if (s != null && s.trim().length() > 0) { + if (newVal == null) { + newVal = new HashSet<>(); + } + newVal.add(s); + } + } + this.disconnectionSqlCodes = newVal; + } else { + this.disconnectionSqlCodes = null; + } + } + + private boolean fastFailValidation; + + /** + * True means that validation will fail immediately for connections that + * have previously thrown SQLExceptions with SQL_STATE indicating fatal + * disconnection errors. + * + * @return true if connections created by this datasource will fast fail validation. + * @see #setDisconnectionSqlCodes(Collection) + * @since 2.1 + */ + @Override + public boolean getFastFailValidation() { + return fastFailValidation; + } + + /** + * @see #getFastFailValidation() + * @param fastFailValidation true means connections created by this factory will + * fast fail validation + * @since 2.1 + */ + public void setFastFailValidation(boolean fastFailValidation) { + this.fastFailValidation = fastFailValidation; + } // ----------------------------------------------------- Instance Variables @@ -1511,17 +1631,16 @@ public class BasicDataSource implements * <p>Flag to remove abandoned connections if they exceed the * removeAbandonedTimeout when borrowObject is invoked.</p> * - * <p>The default value is false.<p> + * <p>The default value is false.</p> * * <p>If set to true a connection is considered abandoned and eligible * for removal if it has not been used for more than * {@link #getRemoveAbandonedTimeout() removeAbandonedTimeout} seconds.</p> * * <p>Abandoned connections are identified and removed when - * {@link #getConnection()} is invoked and the following conditions hold: + * {@link #getConnection()} is invoked and all of the following conditions hold: * </p> - * <ul><li>{@link #getRemoveAbandonedOnBorrow()} or - * {@link #getRemoveAbandonedOnMaintenance()} = true</li> + * <ul><li>{@link #getRemoveAbandonedOnBorrow()} </li> * <li>{@link #getNumActive()} > {@link #getMaxTotal()} - 3 </li> * <li>{@link #getNumIdle()} < 2 </li></ul> * @@ -1536,19 +1655,9 @@ public class BasicDataSource implements } /** - * <p>Flag to remove abandoned connections if they exceed the - * removeAbandonedTimeout when borrowObject is invoked.</p> - * - * <p>If set to true a connection is considered abandoned and eligible - * for removal if it has been idle longer than the - * {@link #getRemoveAbandonedTimeout() removeAbandonedTimeout}.</p> - * - * <p>Setting this to true can recover db connections from poorly written - * applications which fail to close a connection.</p> - * - * @param removeAbandonedOnMaintenance true means abandoned connections will - * be removed when borrowObject is - * invoked + * @param removeAbandonedOnMaintenance true means abandoned connections may + * be removed on pool maintenance. + * @see #getRemoveAbandonedOnMaintenance() */ public void setRemoveAbandonedOnMaintenance( boolean removeAbandonedOnMaintenance) { @@ -1563,20 +1672,12 @@ public class BasicDataSource implements * <p>Flag to remove abandoned connections if they exceed the * removeAbandonedTimeout during pool maintenance.</p> * - * <p>The default value is false.<p> + * <p>The default value is false.</p> * * <p>If set to true a connection is considered abandoned and eligible * for removal if it has not been used for more than * {@link #getRemoveAbandonedTimeout() removeAbandonedTimeout} seconds.</p> * - * <p>Abandoned connections are identified and removed when - * {@link #getConnection()} is invoked and the following conditions hold: - * </p> - * <ul><li>{@link #getRemoveAbandonedOnBorrow()} or - * {@link #getRemoveAbandonedOnMaintenance()} = true</li> - * <li>{@link #getNumActive()} > {@link #getMaxTotal()} - 3 </li> - * <li>{@link #getNumIdle()} < 2 </li></ul> - * * @see #getRemoveAbandonedTimeout() */ @Override @@ -1588,18 +1689,9 @@ public class BasicDataSource implements } /** - * <p>Flag to remove abandoned connections if they exceed the - * removeAbandonedTimeout during pool maintenance.</p> - * - * <p>If set to true a connection is considered abandoned and eligible - * for removal if it has been idle longer than the - * {@link #getRemoveAbandonedTimeout() removeAbandonedTimeout}.</p> - * - * <p>Setting this to true can recover db connections from poorly written - * applications which fail to close a connection.</p> - * - * @param removeAbandonedOnBorrow true means abandoned connections will be - * removed during pool maintenance + * @param removeAbandonedOnBorrow true means abandoned connections may be + * removed when connections are borrowed from the pool. + * @see #getRemoveAbandonedOnBorrow() */ public void setRemoveAbandonedOnBorrow(boolean removeAbandonedOnBorrow) { if (abandonedConfig == null) { @@ -1809,13 +1901,14 @@ public class BasicDataSource implements * these connections to the pool, the underlying JDBC connections are closed.</p> * * <p>Attempts to acquire connections using {@link #getConnection()} after this method has been - * invoked result in SQLExceptions.<p> + * invoked result in SQLExceptions.</p> * * <p>This method is idempotent - i.e., closing an already closed BasicDataSource has no effect * and does not generate exceptions.</p> * * @throws SQLException if an error occurs closing idle connections */ + @Override public synchronized void close() throws SQLException { if (registeredJmxName != null) { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); @@ -1838,7 +1931,7 @@ public class BasicDataSource implements } catch(RuntimeException e) { throw e; } catch(Exception e) { - throw new SQLException("Cannot close connection pool", e); + throw new SQLException(Utils.getMessage("pool.close.fail"), e); } } @@ -1963,10 +2056,11 @@ public class BasicDataSource implements } // Create the pooling data source to manage connections + DataSource newDataSource; success = false; try { - dataSource = createDataSourceInstance(); - dataSource.setLogWriter(logWriter); + newDataSource = createDataSourceInstance(); + newDataSource.setLogWriter(logWriter); success = true; } catch (SQLException se) { throw se; @@ -1993,6 +2087,7 @@ public class BasicDataSource implements // If timeBetweenEvictionRunsMillis > 0, start the pool's evictor task startPoolMaintenance(); + dataSource = newDataSource; return dataSource; } } @@ -2100,6 +2195,7 @@ public class BasicDataSource implements // Create an object pool to contain our active connections GenericObjectPoolConfig config = new GenericObjectPoolConfig(); updateJmxName(config); + config.setJmxEnabled(registeredJmxName != null); // Disable JMX on the underlying pool if the DS is not registered. GenericObjectPool<PoolableConnection> gop; if (abandonedConfig != null && (abandonedConfig.getRemoveAbandonedOnBorrow() || @@ -2120,7 +2216,7 @@ public class BasicDataSource implements gop.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); gop.setTestWhileIdle(testWhileIdle); gop.setLifo(lifo); - gop.setSwallowedExceptionListener(new SwallowedExceptionLogger(log)); + gop.setSwallowedExceptionListener(new SwallowedExceptionLogger(log, logExpiredConnections)); gop.setEvictionPolicyClassName(evictionPolicyClassName); factory.setPool(gop); connectionPool = gop; @@ -2188,6 +2284,8 @@ public class BasicDataSource implements connectionFactory.setRollbackOnReturn(getRollbackOnReturn()); connectionFactory.setEnableAutoCommitOnReturn(getEnableAutoCommitOnReturn()); connectionFactory.setDefaultQueryTimeout(getDefaultQueryTimeout()); + connectionFactory.setFastFailValidation(fastFailValidation); + connectionFactory.setDisconnectionSqlCodes(disconnectionSqlCodes); validateConnectionFactory(connectionFactory); } catch (RuntimeException e) { throw e; Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java?rev=1682317&r1=1682316&r2=1682317&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java Thu May 28 19:57:56 2015 @@ -21,9 +21,13 @@ import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; import java.sql.Connection; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Enumeration; import java.util.Hashtable; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; @@ -33,6 +37,11 @@ import javax.naming.RefAddr; import javax.naming.Reference; import javax.naming.spi.ObjectFactory; +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.dbcp.pool2.impl.BaseObjectPoolConfig; +import org.apache.tomcat.dbcp.pool2.impl.GenericObjectPoolConfig; + /** * <p>JNDI object factory that creates an instance of * <code>BasicDataSource</code> that has been configured based on the @@ -41,7 +50,7 @@ import javax.naming.spi.ObjectFactory; * properties with the following exceptions:</p> * <ul> * <li><code>connectionInitSqls</code> must be passed to this factory as a - * single String using semi-colon to delimt the statements whereas + * single String using semi-colon to delimit the statements whereas * <code>BasicDataSource</code> requires a collection of Strings.</li> * </ul> * @@ -51,6 +60,8 @@ import javax.naming.spi.ObjectFactory; */ public class BasicDataSourceFactory implements ObjectFactory { + private static final Log log = LogFactory.getLog(BasicDataSourceFactory.class); + private static final String PROP_DEFAULTAUTOCOMMIT = "defaultAutoCommit"; private static final String PROP_DEFAULTREADONLY = "defaultReadOnly"; private static final String PROP_DEFAULTTRANSACTIONISOLATION = "defaultTransactionIsolation"; @@ -93,9 +104,34 @@ public class BasicDataSourceFactory impl private static final String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements"; private static final String PROP_CONNECTIONPROPERTIES = "connectionProperties"; private static final String PROP_MAXCONNLIFETIMEMILLIS = "maxConnLifetimeMillis"; + private static final String PROP_LOGEXPIREDCONNECTIONS = "logExpiredConnections"; private static final String PROP_ROLLBACK_ON_RETURN = "rollbackOnReturn"; private static final String PROP_ENABLE_AUTOCOMMIT_ON_RETURN = "enableAutoCommitOnReturn"; private static final String PROP_DEFAULT_QUERYTIMEOUT = "defaultQueryTimeout"; + private static final String PROP_FASTFAIL_VALIDATION = "fastFailValidation"; + + /** + * Value string must be of the form [STATE_CODE,]* + */ + private static final String PROP_DISCONNECTION_SQL_CODES = "disconnectionSqlCodes"; + + /* + * Block with obsolete properties from DBCP 1.x. + * Warn users that these are ignored and they should use the 2.x properties. + */ + private static final String NUPROP_MAXACTIVE = "maxActive"; + private static final String NUPROP_REMOVEABANDONED = "removeAbandoned"; + private static final String NUPROP_MAXWAIT = "maxWait"; + + /* + * Block with properties expected in a DataSource + * This props will not be listed as ignored - we know that they may appear in Resource, + * and not listing them as ignored. + */ + private static final String SILENTPROP_FACTORY = "factory"; + private static final String SILENTPROP_SCOPE = "scope"; + private static final String SILENTPROP_SINGLETON = "singleton"; + private static final String SILENTPROP_AUTH = "auth"; private static final String[] ALL_PROPERTIES = { PROP_DEFAULTAUTOCOMMIT, @@ -134,11 +170,54 @@ public class BasicDataSourceFactory impl PROP_MAXOPENPREPAREDSTATEMENTS, PROP_CONNECTIONPROPERTIES, PROP_MAXCONNLIFETIMEMILLIS, + PROP_LOGEXPIREDCONNECTIONS, PROP_ROLLBACK_ON_RETURN, PROP_ENABLE_AUTOCOMMIT_ON_RETURN, - PROP_DEFAULT_QUERYTIMEOUT + PROP_DEFAULT_QUERYTIMEOUT, + PROP_FASTFAIL_VALIDATION, + PROP_DISCONNECTION_SQL_CODES }; + /** + * Obsolete properties from DBCP 1.x. with warning strings suggesting + * new properties. LinkedHashMap will guarantee that properties will be listed + * to output in order of insertion into map. + */ + private static final Map<String, String> NUPROP_WARNTEXT = new LinkedHashMap<>(); + + static { + NUPROP_WARNTEXT.put( + NUPROP_MAXACTIVE, + "Property " + NUPROP_MAXACTIVE + " is not used in DBCP2, use " + PROP_MAXTOTAL + " instead. " + + PROP_MAXTOTAL + " default value is " + GenericObjectPoolConfig.DEFAULT_MAX_TOTAL+"."); + NUPROP_WARNTEXT.put( + NUPROP_REMOVEABANDONED, + "Property " + NUPROP_REMOVEABANDONED + " is not used in DBCP2," + + " use one or both of " + + PROP_REMOVEABANDONEDONBORROW + " or " + PROP_REMOVEABANDONEDONMAINTENANCE + " instead. " + + "Both have default value set to false."); + NUPROP_WARNTEXT.put( + NUPROP_MAXWAIT, + "Property " + NUPROP_MAXWAIT + " is not used in DBCP2" + + " , use " + PROP_MAXWAITMILLIS + " instead. " + + PROP_MAXWAITMILLIS + " default value is " + BaseObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS+"."); + } + + /** + * Silent Properties. + * These properties will not be listed as ignored - we know that they may appear in JDBC Resource references, + * and we will not list them as ignored. + */ + private static final List<String> SILENT_PROPERTIES = new ArrayList<>(); + + static { + SILENT_PROPERTIES.add(SILENTPROP_FACTORY); + SILENT_PROPERTIES.add(SILENTPROP_SCOPE); + SILENT_PROPERTIES.add(SILENTPROP_SINGLETON); + SILENT_PROPERTIES.add(SILENTPROP_AUTH); + + } + // -------------------------------------------------- ObjectFactory Methods /** @@ -170,6 +249,17 @@ public class BasicDataSourceFactory impl return null; } + // Check property names and log warnings about obsolete and / or unknown properties + final List<String> warnings = new ArrayList<>(); + final List<String> infoMessages = new ArrayList<>(); + validatePropertyNames(ref, name, warnings, infoMessages); + for (String warning : warnings) { + log.warn(warning); + } + for (String infoMessage : infoMessages) { + log.info(infoMessage); + } + Properties properties = new Properties(); for (String propertyName : ALL_PROPERTIES) { RefAddr ra = ref.get(propertyName); @@ -183,6 +273,58 @@ public class BasicDataSourceFactory impl } /** + * Collects warnings and info messages. Warnings are generated when an obsolete + * property is set. Unknown properties generate info messages. + * + * @param ref Reference to check properties of + * @param name Name provided to getObject + * @param warnings container for warning messages + * @param infoMessages container for info messages + */ + private void validatePropertyNames(Reference ref, Name name, List<String> warnings, + List<String> infoMessages) { + final List<String> allPropsAsList = Arrays.asList(ALL_PROPERTIES); + final String nameString = name != null ? "Name = " + name.toString() + " " : ""; + if (NUPROP_WARNTEXT!=null && !NUPROP_WARNTEXT.keySet().isEmpty()) { + for (String propertyName : NUPROP_WARNTEXT.keySet()) { + final RefAddr ra = ref.get(propertyName); + if (ra != null && !allPropsAsList.contains(ra.getType())) { + final StringBuilder stringBuilder = new StringBuilder(nameString); + final String propertyValue = ra.getContent().toString(); + stringBuilder.append(NUPROP_WARNTEXT.get(propertyName)) + .append(" You have set value of \"") + .append(propertyValue) + .append("\" for \"") + .append(propertyName) + .append("\" property, which is being ignored."); + warnings.add(stringBuilder.toString()); + } + } + } + + final Enumeration<RefAddr> allRefAddrs = ref.getAll(); + while (allRefAddrs.hasMoreElements()) { + final RefAddr ra = allRefAddrs.nextElement(); + final String propertyName = ra.getType(); + // If property name is not in the properties list, we haven't warned on it + // and it is not in the "silent" list, tell user we are ignoring it. + if (!(allPropsAsList.contains(propertyName) + || NUPROP_WARNTEXT.keySet().contains(propertyName) + || SILENT_PROPERTIES.contains(propertyName))) { + final String propertyValue = ra.getContent().toString(); + final StringBuilder stringBuilder = new StringBuilder(nameString); + stringBuilder.append("Ignoring unknown property: ") + .append("value of \"") + .append(propertyValue) + .append("\" for \"") + .append(propertyName) + .append("\" property"); + infoMessages.add(stringBuilder.toString()); + } + } + } + + /** * Creates and configures a {@link BasicDataSource} instance based on the * given properties. * @@ -386,15 +528,7 @@ public class BasicDataSourceFactory impl value = properties.getProperty(PROP_CONNECTIONINITSQLS); if (value != null) { - StringTokenizer tokenizer = new StringTokenizer(value, ";"); - // Have to jump through these hoops as StringTokenizer implements - // Enumeration<Object> rather than Enumeration<String> - Collection<String> tokens = - new ArrayList<>(tokenizer.countTokens()); - while (tokenizer.hasMoreTokens()) { - tokens.add(tokenizer.nextToken()); - } - dataSource.setConnectionInitSqls(tokens); + dataSource.setConnectionInitSqls(parseList(value, ';')); } value = properties.getProperty(PROP_CONNECTIONPROPERTIES); @@ -412,6 +546,11 @@ public class BasicDataSourceFactory impl dataSource.setMaxConnLifetimeMillis(Long.parseLong(value)); } + value = properties.getProperty(PROP_LOGEXPIREDCONNECTIONS); + if (value != null) { + dataSource.setLogExpiredConnections(Boolean.valueOf(value).booleanValue()); + } + value = properties.getProperty(PROP_JMX_NAME); if (value != null) { dataSource.setJmxName(value); @@ -432,6 +571,15 @@ public class BasicDataSourceFactory impl dataSource.setDefaultQueryTimeout(Integer.valueOf(value)); } + value = properties.getProperty(PROP_FASTFAIL_VALIDATION); + if (value != null) { + dataSource.setFastFailValidation(Boolean.valueOf(value).booleanValue()); + } + + value = properties.getProperty(PROP_DISCONNECTION_SQL_CODES); + if (value != null) { + dataSource.setDisconnectionSqlCodes(parseList(value, ',')); + } // DBCP-215 // Trick to make sure that initialSize connections are created @@ -457,4 +605,19 @@ public class BasicDataSourceFactory impl } return p; } + + /** + * Parse list of property values from a delimited string + * @param value delimited list of values + * @param delimiter character used to separate values in the list + * @return String Collection of values + */ + private static Collection<String> parseList(String value, char delimiter) { + StringTokenizer tokenizer = new StringTokenizer(value, Character.toString(delimiter)); + Collection<String> tokens = new ArrayList<>(tokenizer.countTokens()); + while (tokenizer.hasMoreTokens()) { + tokens.add(tokenizer.nextToken()); + } + return tokens; + } } Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java?rev=1682317&r1=1682316&r2=1682317&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java Thu May 28 19:57:56 2015 @@ -216,6 +216,13 @@ public interface BasicDataSourceMXBean { long getMaxConnLifetimeMillis(); /** + * See {@link BasicDataSource#getLogExpiredConnections()} + * @return {@link BasicDataSource#getLogExpiredConnections()} + * @since 2.1 + */ + boolean getLogExpiredConnections(); + + /** * See {@link BasicDataSource#getRemoveAbandonedOnBorrow()} * @return {@link BasicDataSource#getRemoveAbandonedOnBorrow()} */ @@ -244,4 +251,18 @@ public interface BasicDataSourceMXBean { * @return {@link BasicDataSource#isClosed()} */ boolean isClosed(); + + /** + * See {@link BasicDataSource#getFastFailValidation()} + * @return {@link BasicDataSource#getFastFailValidation()} + * @since 2.1 + */ + boolean getFastFailValidation(); + + /** + * See {@link BasicDataSource#getDisconnectionSqlCodesAsArray()} + * @return {@link BasicDataSource#getDisconnectionSqlCodesAsArray()} + * @since 2.1 + */ + String[] getDisconnectionSqlCodesAsArray(); } Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java?rev=1682317&r1=1682316&r2=1682317&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java Thu May 28 19:57:56 2015 @@ -94,7 +94,7 @@ public class DelegatingConnection<C exte /** * Returns a string representation of the metadata associated with - * the innnermost delegate connection. + * the innermost delegate connection. */ @Override public String toString() { Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java?rev=1682317&r1=1682316&r2=1682317&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java Thu May 28 19:57:56 2015 @@ -138,7 +138,7 @@ public class DelegatingStatement extends _conn = null; } - // The JDBC spec requires that a statment close any open + // The JDBC spec requires that a statement close any open // ResultSet's when it is closed. // FIXME The PreparedStatement we're wrapping should handle this for us. // See bug 17301 for what could happen when ResultSets are closed twice. Copied: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java (from r1682314, commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/LifetimeExceededException.java) URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java?p2=tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java&p1=commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/LifetimeExceededException.java&r1=1682314&r2=1682317&rev=1682317&view=diff ============================================================================== --- commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/LifetimeExceededException.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java Thu May 28 19:57:56 2015 @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.dbcp2; +package org.apache.tomcat.dbcp.dbcp2; /** * Exception thrown when a connection's maximum lifetime has been exceeded. Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties?rev=1682317&r1=1682316&r2=1682317&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties Thu May 28 19:57:56 2015 @@ -15,8 +15,12 @@ connectionFactory.lifetimeExceeded=The lifetime of the connection [{0}] milliseconds exceeds the maximum permitted value of [{1}] milliseconds -poolableConnectionFactory.validateObject.fail=Failed to validate a poolable connection +poolableConnectionFactory.validateObject.fail=Failed to validate a poolable connection. -swallowedExceptionLogger.onSwallowedException=An internal object pool swallowed an Exception +poolableConnection.validate.fastFail=Fatal SQLException was thrown previously on this connection. -poolingDataSource.factoryConfig="PoolableConnectionFactory not linked to pool. Calling setPool() to fix the configuration." +swallowedExceptionLogger.onSwallowedException=An internal object pool swallowed an Exception. + +poolingDataSource.factoryConfig=PoolableConnectionFactory not linked to pool. Calling setPool() to fix the configuration. + +pool.close.fail=Cannot close connection pool. Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java?rev=1682317&r1=1682316&r2=1682317&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java Thu May 28 19:57:56 2015 @@ -111,7 +111,7 @@ public class PoolableCallableStatement e getConnectionInternal().removeTrace(this); } - // The JDBC spec requires that a statment close any open + // The JDBC spec requires that a statement close any open // ResultSet's when it is closed. // FIXME The PreparedStatement we're wrapping should handle this for us. // See DBCP-10 for what could happen when ResultSets are closed twice. Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java?rev=1682317&r1=1682316&r2=1682317&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java Thu May 28 19:57:56 2015 @@ -21,6 +21,7 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.Collection; import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; @@ -55,7 +56,7 @@ public class PoolableConnection extends } /** The pool to which I should return. */ - private ObjectPool<PoolableConnection> _pool = null; + private final ObjectPool<PoolableConnection> _pool; private final ObjectName _jmxName; @@ -65,15 +66,38 @@ public class PoolableConnection extends private String lastValidationSql = null; /** + * Indicate that unrecoverable SQLException was thrown when using this connection. + * Such a connection should be considered broken and not pass validation in the future. + */ + private boolean _fatalSqlExceptionThrown = false; + + /** + * SQL_STATE codes considered to signal fatal conditions. Overrides the + * defaults in {@link Utils#DISCONNECTION_SQL_CODES} (plus anything starting + * with {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). + */ + private final Collection<String> _disconnectionSqlCodes; + + /** Whether or not to fast fail validation after fatal connection errors */ + private final boolean _fastFailValidation; + + /** * * @param conn my underlying connection * @param pool the pool to which I should return when closed + * @param jmxName JMX name + * @param disconnectSqlCodes SQL_STATE codes considered fatal disconnection errors + * @param fastFailValidation true means fatal disconnection errors cause subsequent + * validations to fail immediately (no attempt to run query or isValid) */ public PoolableConnection(Connection conn, - ObjectPool<PoolableConnection> pool, ObjectName jmxName) { + ObjectPool<PoolableConnection> pool, ObjectName jmxName, Collection<String> disconnectSqlCodes, + boolean fastFailValidation) { super(conn); _pool = pool; _jmxName = jmxName; + _disconnectionSqlCodes = disconnectSqlCodes; + _fastFailValidation = fastFailValidation; if (jmxName != null) { try { @@ -85,6 +109,17 @@ public class PoolableConnection extends } } + /** + * + * @param conn my underlying connection + * @param pool the pool to which I should return when closed + * @param jmxName JMX name + */ + public PoolableConnection(Connection conn, + ObjectPool<PoolableConnection> pool, ObjectName jmxName) { + this(conn, pool, jmxName, null, false); + } + @Override protected void passivate() throws SQLException { @@ -217,8 +252,29 @@ public class PoolableConnection extends return toString(); } - + /** + * Validates the connection, using the following algorithm: + * <ol> + * <li>If {@code fastFailValidation} (constructor argument) is {@code true} and + * this connection has previously thrown a fatal disconnection exception, + * a {@code SQLException} is thrown. </li> + * <li>If {@code sql} is null, the driver's + * #{@link Connection#isValid(int) isValid(timeout)} is called. + * If it returns {@code false}, {@code SQLException} is thrown; + * otherwise, this method returns successfully.</li> + * <li>If {@code sql} is not null, it is executed as a query and if the resulting + * {@code ResultSet} contains at least one row, this method returns + * successfully. If not, {@code SQLException} is thrown.</li> + * </ol> + * @param sql validation query + * @param timeout validation timeout + * @throws SQLException if validation fails or an SQLException occurs during validation + */ public void validate(String sql, int timeout) throws SQLException { + if (_fastFailValidation && _fatalSqlExceptionThrown) { + throw new SQLException(Utils.getMessage("poolableConnection.validate.fastFail")); + } + if (sql == null || sql.length() == 0) { if (timeout < 0) { timeout = 0; @@ -249,5 +305,38 @@ public class PoolableConnection extends throw sqle; } } + + /** + * Checks the SQLState of the input exception and any nested SQLExceptions it wraps. + * <p> + * If {@link #getDisconnectSqlCodes() disconnectSQLCodes} has been set, sql states + * are compared to those in the configured list of fatal exception codes. If this + * property is not set, codes are compared against the default codes in + * #{@link Utils.DISCONNECTION_SQL_CODES} and in this case anything starting with + * #{link Utils.DISCONNECTION_SQL_CODE_PREFIX} is considered a disconnection.</p> + * + * @param e SQLException to be examined + * @return true if the exception signals a disconnection + */ + private boolean isDisconnectionSqlException(SQLException e) { + boolean fatalException = false; + String sqlState = e.getSQLState(); + if (sqlState != null) { + fatalException = _disconnectionSqlCodes == null ? sqlState.startsWith(Utils.DISCONNECTION_SQL_CODE_PREFIX) + || Utils.DISCONNECTION_SQL_CODES.contains(sqlState) : _disconnectionSqlCodes.contains(sqlState); + if (!fatalException) { + if (e.getNextException() != null) { + fatalException = isDisconnectionSqlException(e.getNextException()); + } + } + } + return fatalException; + } + + @Override + protected void handleException(SQLException e) throws SQLException { + _fatalSqlExceptionThrown |= isDisconnectionSqlException(e); + super.handleException(e); + } } Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java?rev=1682317&r1=1682316&r2=1682317&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java Thu May 28 19:57:56 2015 @@ -189,7 +189,6 @@ public class PoolableConnectionFactory this.rollbackOnReturn = rollbackOnReturn; } - public Integer getDefaultQueryTimeout() { return defaultQueryTimeout; } @@ -198,6 +197,58 @@ public class PoolableConnectionFactory this.defaultQueryTimeout = defaultQueryTimeout; } + /** + * SQL_STATE codes considered to signal fatal conditions. + * <p> + * Overrides the defaults in {@link Utils#DISCONNECTION_SQL_CODES} + * (plus anything starting with {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). + * If this property is non-null and {@link #isFastFailValidation()} is + * {@code true}, whenever connections created by this factory generate exceptions + * with SQL_STATE codes in this list, they will be marked as "fatally disconnected" + * and subsequent validations will fail fast (no attempt at isValid or validation + * query).</p> + * <p> + * If {@link #isFastFailValidation()} is {@code false} setting this property has no + * effect.</p> + * + * @return SQL_STATE codes overriding defaults + * @since 2.1 + */ + public Collection<String> getDisconnectionSqlCodes() { + return _disconnectionSqlCodes; + } + + /** + * @see #getDisconnectionSqlCodes() + * @param disconnectionSqlCodes + * @since 2.1 + */ + public void setDisconnectionSqlCodes(Collection<String> disconnectionSqlCodes) { + _disconnectionSqlCodes = disconnectionSqlCodes; + } + + /** + * True means that validation will fail immediately for connections that + * have previously thrown SQLExceptions with SQL_STATE indicating fatal + * disconnection errors. + * + * @return true if connections created by this factory will fast fail validation. + * @see #setDisconnectionSqlCodes(Collection) + * @since 2.1 + */ + public boolean isFastFailValidation() { + return _fastFailValidation; + } + + /** + * @see #isFastFailValidation() + * @param fastFailValidation true means connections created by this factory will + * fast fail validation + * @since 2.1 + */ + public void setFastFailValidation(boolean fastFailValidation) { + _fastFailValidation = fastFailValidation; + } @Override public PooledObject<PoolableConnection> makeObject() throws Exception { @@ -234,6 +285,8 @@ public class PoolableConnectionFactory base.append(Long.toString(connIndex)); config.setJmxNameBase(base.toString()); config.setJmxNamePrefix(Constants.JMX_STATEMENT_POOL_PREFIX); + } else { + config.setJmxEnabled(false); } KeyedObjectPool<PStmtKey,DelegatingPreparedStatement> stmtPool = new GenericKeyedObjectPool<>((PoolingConnection)conn, config); @@ -250,7 +303,8 @@ public class PoolableConnectionFactory Constants.JMX_CONNECTION_BASE_EXT + connIndex); } - PoolableConnection pc = new PoolableConnection(conn,_pool, connJmxName); + PoolableConnection pc = new PoolableConnection(conn,_pool, connJmxName, + _disconnectionSqlCodes, _fastFailValidation); return new DefaultPooledObject<>(pc); } @@ -366,7 +420,7 @@ public class PoolableConnectionFactory if (maxConnLifetimeMillis > 0) { long lifetime = System.currentTimeMillis() - p.getCreateTime(); if (lifetime > maxConnLifetimeMillis) { - throw new Exception(Utils.getMessage( + throw new LifetimeExceededException(Utils.getMessage( "connectionFactory.lifetimeExceeded", Long.valueOf(lifetime), Long.valueOf(maxConnLifetimeMillis))); @@ -390,11 +444,21 @@ public class PoolableConnectionFactory return _cacheState; } + protected ObjectName getDataSourceJmxName() { + return dataSourceJmxName; + } + + protected AtomicLong getConnectionIndex() { + return connectionIndex; + } + private final ConnectionFactory _connFactory; private final ObjectName dataSourceJmxName; private volatile String _validationQuery = null; private volatile int _validationQueryTimeout = -1; private Collection<String> _connectionInitSqls = null; + private Collection<String> _disconnectionSqlCodes = null; + private boolean _fastFailValidation = false; private volatile ObjectPool<PoolableConnection> _pool = null; private Boolean _defaultReadOnly = null; private Boolean _defaultAutoCommit = null; Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java?rev=1682317&r1=1682316&r2=1682317&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java Thu May 28 19:57:56 2015 @@ -295,7 +295,7 @@ public class PoolingConnection extends D /** * Normalize the given SQL statement, producing a - * cannonical form that is semantically equivalent to the original. + * canonical form that is semantically equivalent to the original. */ protected String normalizeSQL(String sql) { return sql.trim(); Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolingDataSource.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolingDataSource.java?rev=1682317&r1=1682316&r2=1682317&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolingDataSource.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolingDataSource.java Thu May 28 19:57:56 2015 @@ -42,7 +42,7 @@ import org.apache.tomcat.dbcp.pool2.impl * @author Dirk Verbeeck * @since 2.0 */ -public class PoolingDataSource<C extends Connection> implements DataSource { +public class PoolingDataSource<C extends Connection> implements DataSource, AutoCloseable { private static final Log log = LogFactory.getLog(PoolingDataSource.class); @@ -70,9 +70,24 @@ public class PoolingDataSource<C extends } /** + * Close and free all {@link Connection}s from the pool. + * @since 2.1 + */ + @Override + public void close() throws Exception { + try { + _pool.close(); + } catch(RuntimeException rte) { + throw new RuntimeException(Utils.getMessage("pool.close.fail"), rte); + } catch(Exception e) { + throw new SQLException(Utils.getMessage("pool.close.fail"), e); + } + } + + /** * Returns the value of the accessToUnderlyingConnectionAllowed property. * - * @return true if access to the underlying is allowed, false otherwise. + * @return true if access to the underlying {@link Connection} is allowed, false otherwise. */ public boolean isAccessToUnderlyingConnectionAllowed() { return this.accessToUnderlyingConnectionAllowed; Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/SwallowedExceptionLogger.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/SwallowedExceptionLogger.java?rev=1682317&r1=1682316&r2=1682317&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/SwallowedExceptionLogger.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/SwallowedExceptionLogger.java Thu May 28 19:57:56 2015 @@ -20,20 +20,41 @@ import org.apache.juli.logging.Log; import org.apache.tomcat.dbcp.pool2.SwallowedExceptionListener; /** - * Class for logging swallowed exceptions + * Class for logging swallowed exceptions. * @since 2.0 */ public class SwallowedExceptionLogger implements SwallowedExceptionListener{ private final Log log; + private final boolean logExpiredConnections; + /** + * Create a SwallowedExceptionLogger with the given logger. By default, + * expired connection logging is turned on. + * + * @param log logger + */ public SwallowedExceptionLogger(Log log) { + this(log, true); + } + + /** + * Create a SwallowedExceptionLogger with the given logger and expired + * connection logging property. + * + * @param log logger + * @param logExpiredConnections false suppresses logging of expired connection events + */ + public SwallowedExceptionLogger(Log log, boolean logExpiredConnections) { this.log = log; + this.logExpiredConnections = logExpiredConnections; } @Override public void onSwallowException(Exception e) { - log.warn(Utils.getMessage( - "swallowedExceptionLogger.onSwallowedException"), e); + if (logExpiredConnections || !(e instanceof LifetimeExceededException)) { + log.warn(Utils.getMessage( + "swallowedExceptionLogger.onSwallowedException"), e); + } } } Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/Utils.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/Utils.java?rev=1682317&r1=1682316&r2=1682317&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/Utils.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/Utils.java Thu May 28 19:57:56 2015 @@ -22,10 +22,12 @@ import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.text.MessageFormat; +import java.util.HashSet; import java.util.ResourceBundle; +import java.util.Set; /** - * Utility methods + * Utility methods. * @since 2.0 */ public final class Utils { @@ -36,6 +38,31 @@ public final class Utils { public static final boolean IS_SECURITY_ENABLED = System.getSecurityManager() != null; + /** Any SQL_STATE starting with this value is considered a fatal disconnect */ + public static final String DISCONNECTION_SQL_CODE_PREFIX = "08"; + + /** + * SQL codes of fatal connection errors. + * <ul> + * <li>57P01 (ADMIN SHUTDOWN)</li> + * <li>57P02 (CRASH SHUTDOWN)</li> + * <li>57P03 (CANNOT CONNECT NOW)</li> + * <li>01002 (SQL92 disconnect error)</li> + * <li>JZ0C0 (Sybase disconnect error)</li> + * <li>JZ0C1 (Sybase disconnect error)</li> + * </ul> + */ + public static final Set<String> DISCONNECTION_SQL_CODES; + + static { + DISCONNECTION_SQL_CODES = new HashSet<>(); + DISCONNECTION_SQL_CODES.add("57P01"); // ADMIN SHUTDOWN + DISCONNECTION_SQL_CODES.add("57P02"); // CRASH SHUTDOWN + DISCONNECTION_SQL_CODES.add("57P03"); // CANNOT CONNECT NOW + DISCONNECTION_SQL_CODES.add("01002"); // SQL92 disconnect error + DISCONNECTION_SQL_CODES.add("JZ0C0"); // Sybase disconnect error + DISCONNECTION_SQL_CODES.add("JZ0C1"); // Sybase disconnect error + } private Utils() { // not instantiable Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java?rev=1682317&r1=1682316&r2=1682317&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java Thu May 28 19:57:56 2015 @@ -84,7 +84,7 @@ import org.apache.tomcat.dbcp.pool2.impl * @since 2.0 */ public abstract class InstanceKeyDataSource - implements DataSource, Referenceable, Serializable { + implements DataSource, Referenceable, Serializable, AutoCloseable { private static final long serialVersionUID = -6819270431752240878L; @@ -186,6 +186,7 @@ public abstract class InstanceKeyDataSou /** * Close the connection pool being maintained by this datasource. */ + @Override public abstract void close() throws Exception; protected abstract PooledConnectionManager getConnectionManager(UserPassKey upkey); @@ -230,7 +231,6 @@ public abstract class InstanceKeyDataSou this.defaultBlockWhenExhausted = blockWhenExhausted; } - /** * Gets the default value for * {@link GenericKeyedObjectPoolConfig#getEvictionPolicyClassName()} for @@ -251,7 +251,6 @@ public abstract class InstanceKeyDataSou this.defaultEvictionPolicyClassName = evictionPolicyClassName; } - /** * Gets the default value for * {@link GenericKeyedObjectPoolConfig#getLifo()} for each per user pool. @@ -269,7 +268,6 @@ public abstract class InstanceKeyDataSou this.defaultLifo = lifo; } - /** * Gets the default value for * {@link GenericKeyedObjectPoolConfig#getMaxIdlePerKey()} for each per user @@ -289,7 +287,6 @@ public abstract class InstanceKeyDataSou this.defaultMaxIdle = maxIdle; } - /** * Gets the default value for * {@link GenericKeyedObjectPoolConfig#getMaxTotalPerKey()} for each per @@ -309,7 +306,6 @@ public abstract class InstanceKeyDataSou this.defaultMaxTotal = maxTotal; } - /** * Gets the default value for * {@link GenericKeyedObjectPoolConfig#getMaxWaitMillis()} for each per user @@ -329,7 +325,6 @@ public abstract class InstanceKeyDataSou this.defaultMaxWaitMillis = maxWaitMillis; } - /** * Gets the default value for * {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleTimeMillis()} for @@ -350,7 +345,6 @@ public abstract class InstanceKeyDataSou this.defaultMinEvictableIdleTimeMillis = minEvictableIdleTimeMillis; } - /** * Gets the default value for * {@link GenericKeyedObjectPoolConfig#getMinIdlePerKey()} for each per user @@ -370,7 +364,6 @@ public abstract class InstanceKeyDataSou this.defaultMinIdle = minIdle; } - /** * Gets the default value for * {@link GenericKeyedObjectPoolConfig#getNumTestsPerEvictionRun()} for each @@ -390,7 +383,6 @@ public abstract class InstanceKeyDataSou this.defaultNumTestsPerEvictionRun = numTestsPerEvictionRun; } - /** * Gets the default value for * {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each @@ -410,7 +402,6 @@ public abstract class InstanceKeyDataSou this.defaultSoftMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis; } - /** * Gets the default value for * {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool GenericObjectPool#getTestOnCreate()} for each per user pool. @@ -428,7 +419,6 @@ public abstract class InstanceKeyDataSou this.defaultTestOnCreate = testOnCreate; } - /** * Gets the default value for * {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool GenericObjectPool#getTestOnBorrow()} for each per user pool. @@ -446,7 +436,6 @@ public abstract class InstanceKeyDataSou this.defaultTestOnBorrow = testOnBorrow; } - /** * Gets the default value for * {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool GenericObjectPool#getTestOnReturn()} for each per user pool. @@ -464,7 +453,6 @@ public abstract class InstanceKeyDataSou this.defaultTestOnReturn = testOnReturn; } - /** * Gets the default value for * {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool GenericObjectPool#getTestWhileIdle()} for each per user pool. @@ -482,7 +470,6 @@ public abstract class InstanceKeyDataSou this.defaultTestWhileIdle = testWhileIdle; } - /** * Gets the default value for * {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool GenericObjectPool#getTimeBetweenEvictionRunsMillis ()} for each @@ -503,22 +490,6 @@ public abstract class InstanceKeyDataSou this.defaultTimeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis ; } - - - - - - - - - - - - - - - - /** * Get the value of connectionPoolDataSource. This method will return * null, if the backing datasource is being accessed via jndi. @@ -940,7 +911,7 @@ public abstract class InstanceKeyDataSou } /* * Password must have changed -> destroy connection and keep retrying until we get a new, good one, - * destroying any idle connections with the old passowrd as we pull them from the pool. + * destroying any idle connections with the old password as we pull them from the pool. */ final UserPassKey upkey = info.getUserPassKey(); final PooledConnectionManager manager = getConnectionManager(upkey); Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java?rev=1682317&r1=1682316&r2=1682317&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java Thu May 28 19:57:56 2015 @@ -39,7 +39,7 @@ import org.apache.tomcat.dbcp.pool2.impl /** * A {@link KeyedPooledObjectFactory} that creates - * {@link PoolableConnection}s. + * {@link org.apache.tomcat.dbcp.dbcp2.PoolableConnection PoolableConnection}s. * * @author John D. McNally * @since 2.0 @@ -159,7 +159,7 @@ class KeyedCPDSConnectionFactory * @param key ignored * @param p wrapped {@link PooledConnectionAndInfo} containing the * connection to validate - * @return true if validation suceeds + * @return true if validation succeeds */ @Override public boolean validateObject(UserPassKey key, Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionManager.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionManager.java?rev=1682317&r1=1682316&r2=1682317&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionManager.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionManager.java Thu May 28 19:57:56 2015 @@ -37,7 +37,7 @@ interface PooledConnectionManager { void invalidate(PooledConnection pc) throws SQLException; /** - * Sets the databsase password used when creating connections. + * Sets the database password used when creating connections. * * @param password password used when authenticating to the database */ --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org