commit removes
parent
c20794cbb1
commit
e3f13a888c
@ -1,26 +0,0 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>HikariCP-common</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>hikaricp-common</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP-parent</artifactId>
|
||||
<version>2.4.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>2.4.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -1,896 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013, 2014 Brett Wooldridge
|
||||
*
|
||||
* Licensed 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 com.zaxxer.hikari;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.codahale.metrics.health.HealthCheckRegistry;
|
||||
import com.zaxxer.hikari.proxy.JavassistProxyFactory;
|
||||
import com.zaxxer.hikari.util.PropertyBeanSetter;
|
||||
import com.zaxxer.hikari.util.UtilityElf;
|
||||
|
||||
public class HikariConfig implements HikariConfigMBean
|
||||
{
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(HikariConfig.class);
|
||||
|
||||
private static final long CONNECTION_TIMEOUT = TimeUnit.SECONDS.toMillis(30);
|
||||
private static final long VALIDATION_TIMEOUT = TimeUnit.SECONDS.toMillis(5);
|
||||
private static final long IDLE_TIMEOUT = TimeUnit.MINUTES.toMillis(10);
|
||||
private static final long MAX_LIFETIME = TimeUnit.MINUTES.toMillis(30);
|
||||
|
||||
private static int poolNumber;
|
||||
private static boolean unitTest;
|
||||
|
||||
// Properties changeable at runtime through the MBean
|
||||
//
|
||||
private volatile long connectionTimeout;
|
||||
private volatile long validationTimeout;
|
||||
private volatile long idleTimeout;
|
||||
private volatile long leakDetectionThreshold;
|
||||
private volatile long maxLifetime;
|
||||
private volatile int maxPoolSize;
|
||||
private volatile int minIdle;
|
||||
|
||||
// Properties NOT changeable at runtime
|
||||
//
|
||||
private String catalog;
|
||||
private String connectionCustomizerClassName;
|
||||
private String connectionInitSql;
|
||||
private String connectionTestQuery;
|
||||
private String dataSourceClassName;
|
||||
private String dataSourceJndiName;
|
||||
private String driverClassName;
|
||||
private String jdbcUrl;
|
||||
private String password;
|
||||
private String poolName;
|
||||
private String transactionIsolationName;
|
||||
private String username;
|
||||
private boolean isAutoCommit;
|
||||
private boolean isReadOnly;
|
||||
private boolean isInitializationFailFast;
|
||||
private boolean isIsolateInternalQueries;
|
||||
private boolean isRegisterMbeans;
|
||||
private boolean isAllowPoolSuspension;
|
||||
private DataSource dataSource;
|
||||
private Properties dataSourceProperties;
|
||||
private IConnectionCustomizer customizer;
|
||||
private ThreadFactory threadFactory;
|
||||
private Object metricRegistry;
|
||||
private Object healthCheckRegistry;
|
||||
private Properties healthCheckProperties;
|
||||
|
||||
static
|
||||
{
|
||||
JavassistProxyFactory.initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public HikariConfig()
|
||||
{
|
||||
dataSourceProperties = new Properties();
|
||||
healthCheckProperties = new Properties();
|
||||
|
||||
connectionTimeout = CONNECTION_TIMEOUT;
|
||||
validationTimeout = VALIDATION_TIMEOUT;
|
||||
idleTimeout = IDLE_TIMEOUT;
|
||||
isAutoCommit = true;
|
||||
isInitializationFailFast = true;
|
||||
minIdle = -1;
|
||||
maxPoolSize = 10;
|
||||
maxLifetime = MAX_LIFETIME;
|
||||
customizer = new IConnectionCustomizer() {
|
||||
@Override
|
||||
public void customize(Connection connection) throws SQLException
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
String systemProp = System.getProperty("hikaricp.configurationFile");
|
||||
if ( systemProp != null) {
|
||||
loadProperties(systemProp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a HikariConfig from the specified properties object.
|
||||
*
|
||||
* @param properties the name of the property file
|
||||
*/
|
||||
public HikariConfig(Properties properties)
|
||||
{
|
||||
this();
|
||||
PropertyBeanSetter.setTargetFromProperties(this, properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a HikariConfig from the specified property file name. <code>propertyFileName</code>
|
||||
* will first be treated as a path in the file-system, and if that fails the
|
||||
* ClassLoader.getResourceAsStream(propertyFileName) will be tried.
|
||||
*
|
||||
* @param propertyFileName the name of the property file
|
||||
*/
|
||||
public HikariConfig(String propertyFileName)
|
||||
{
|
||||
this();
|
||||
|
||||
loadProperties(propertyFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default catalog name to be set on connections.
|
||||
*
|
||||
* @return the default catalog name
|
||||
*/
|
||||
public String getCatalog()
|
||||
{
|
||||
return catalog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default catalog name to be set on connections.
|
||||
*
|
||||
* @param catalog the catalog name, or null
|
||||
*/
|
||||
public void setCatalog(String catalog)
|
||||
{
|
||||
this.catalog = catalog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the connection customizer class to instantiate and execute
|
||||
* on all new connections.
|
||||
*
|
||||
* @return the name of the customizer class, or null
|
||||
*/
|
||||
@Deprecated
|
||||
public String getConnectionCustomizerClassName()
|
||||
{
|
||||
return connectionCustomizerClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the connection customizer class to instantiate and execute
|
||||
* on all new connections.
|
||||
*
|
||||
* @param connectionCustomizerClassName the name of the customizer class
|
||||
*/
|
||||
@Deprecated
|
||||
public void setConnectionCustomizerClassName(String connectionCustomizerClassName)
|
||||
{
|
||||
this.connectionCustomizerClassName = connectionCustomizerClassName;
|
||||
LOGGER.warn("The connectionCustomizerClassName property has been deprecated and may be removed in a future release");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the customizer instance specified by the user.
|
||||
*
|
||||
* @return an instance of IConnectionCustomizer
|
||||
*/
|
||||
@Deprecated
|
||||
public IConnectionCustomizer getConnectionCustomizer()
|
||||
{
|
||||
return customizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the connection customizer to be used by the pool.
|
||||
*
|
||||
* @param customizer an instance of IConnectionCustomizer
|
||||
*/
|
||||
@Deprecated
|
||||
public void setConnectionCustomizer(IConnectionCustomizer customizer)
|
||||
{
|
||||
this.customizer = customizer;
|
||||
LOGGER.warn("The connectionCustomizer property has been deprecated and may be removed in a future release");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL query to be executed to test the validity of connections.
|
||||
*
|
||||
* @return the SQL query string, or null
|
||||
*/
|
||||
public String getConnectionTestQuery()
|
||||
{
|
||||
return connectionTestQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the SQL query to be executed to test the validity of connections. Using
|
||||
* the JDBC4 <code>Connection.isValid()</code> method to test connection validity can
|
||||
* be more efficient on some databases and is recommended. See
|
||||
* {@link HikariConfig#setJdbc4ConnectionTest(boolean)}.
|
||||
*
|
||||
* @param connectionTestQuery a SQL query string
|
||||
*/
|
||||
public void setConnectionTestQuery(String connectionTestQuery)
|
||||
{
|
||||
this.connectionTestQuery = connectionTestQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL string that will be executed on all new connections when they are
|
||||
* created, before they are added to the pool.
|
||||
*
|
||||
* @return the SQL to execute on new connections, or null
|
||||
*/
|
||||
@Deprecated
|
||||
public String getConnectionInitSql()
|
||||
{
|
||||
return connectionInitSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the SQL string that will be executed on all new connections when they are
|
||||
* created, before they are added to the pool. If this query fails, it will be
|
||||
* treated as a failed connection attempt.
|
||||
*
|
||||
* @param connectionInitSql the SQL to execute on new connections
|
||||
*/
|
||||
@Deprecated
|
||||
public void setConnectionInitSql(String connectionInitSql)
|
||||
{
|
||||
this.connectionInitSql = connectionInitSql;
|
||||
LOGGER.warn("The connectionInitSql property has been deprecated and may be removed in a future release");
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public long getConnectionTimeout()
|
||||
{
|
||||
return connectionTimeout;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setConnectionTimeout(long connectionTimeoutMs)
|
||||
{
|
||||
if (connectionTimeoutMs == 0) {
|
||||
this.connectionTimeout = Integer.MAX_VALUE;
|
||||
}
|
||||
else if (connectionTimeoutMs < 1000) {
|
||||
throw new IllegalArgumentException("connectionTimeout cannot be less than 1000ms");
|
||||
}
|
||||
else {
|
||||
this.connectionTimeout = connectionTimeoutMs;
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public long getValidationTimeout()
|
||||
{
|
||||
return validationTimeout;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setValidationTimeout(long validationTimeoutMs)
|
||||
{
|
||||
if (validationTimeoutMs < 1000) {
|
||||
throw new IllegalArgumentException("validationTimeout cannot be less than 1000ms");
|
||||
}
|
||||
else {
|
||||
this.validationTimeout = validationTimeoutMs;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link DataSource} that has been explicitly specified to be wrapped by the
|
||||
* pool.
|
||||
*
|
||||
* @return the {@link DataSource} instance, or null
|
||||
*/
|
||||
public DataSource getDataSource()
|
||||
{
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a {@link DataSource} for the pool to explicitly wrap. This setter is not
|
||||
* available through property file based initialization.
|
||||
*
|
||||
* @param dataSource a specific {@link DataSource} to be wrapped by the pool
|
||||
*/
|
||||
public void setDataSource(DataSource dataSource)
|
||||
{
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
public String getDataSourceClassName()
|
||||
{
|
||||
return dataSourceClassName;
|
||||
}
|
||||
|
||||
public void setDataSourceClassName(String className)
|
||||
{
|
||||
this.dataSourceClassName = className;
|
||||
}
|
||||
|
||||
public void addDataSourceProperty(String propertyName, Object value)
|
||||
{
|
||||
dataSourceProperties.put(propertyName, value);
|
||||
}
|
||||
|
||||
public String getDataSourceJNDI()
|
||||
{
|
||||
return this.dataSourceJndiName;
|
||||
}
|
||||
|
||||
public void setDataSourceJNDI(String jndiDataSource)
|
||||
{
|
||||
this.dataSourceJndiName = jndiDataSource;
|
||||
}
|
||||
|
||||
public Properties getDataSourceProperties()
|
||||
{
|
||||
return dataSourceProperties;
|
||||
}
|
||||
|
||||
public void setDataSourceProperties(Properties dsProperties)
|
||||
{
|
||||
dataSourceProperties.putAll(dsProperties);
|
||||
}
|
||||
|
||||
public void setDriverClassName(String driverClassName)
|
||||
{
|
||||
try {
|
||||
Class<?> driverClass = this.getClass().getClassLoader().loadClass(driverClassName);
|
||||
driverClass.newInstance();
|
||||
this.driverClassName = driverClassName;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException("driverClassName specified class '" + driverClassName + "' could not be loaded", e);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public long getIdleTimeout()
|
||||
{
|
||||
return idleTimeout;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setIdleTimeout(long idleTimeoutMs)
|
||||
{
|
||||
if (idleTimeoutMs < 0) {
|
||||
throw new IllegalArgumentException("idleTimeout cannot be negative");
|
||||
}
|
||||
this.idleTimeout = idleTimeoutMs;
|
||||
}
|
||||
|
||||
public String getJdbcUrl()
|
||||
{
|
||||
return jdbcUrl;
|
||||
}
|
||||
|
||||
public void setJdbcUrl(String jdbcUrl)
|
||||
{
|
||||
this.jdbcUrl = jdbcUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default auto-commit behavior of connections in the pool.
|
||||
*
|
||||
* @return the default auto-commit behavior of connections
|
||||
*/
|
||||
public boolean isAutoCommit()
|
||||
{
|
||||
return isAutoCommit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default auto-commit behavior of connections in the pool.
|
||||
*
|
||||
* @param isAutoCommit the desired auto-commit default for connections
|
||||
*/
|
||||
public void setAutoCommit(boolean isAutoCommit)
|
||||
{
|
||||
this.isAutoCommit = isAutoCommit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pool suspension behavior (allowed or disallowed).
|
||||
*
|
||||
* @return the pool suspension behavior
|
||||
*/
|
||||
public boolean isAllowPoolSuspension()
|
||||
{
|
||||
return isAllowPoolSuspension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether or not pool suspension is allowed. There is a performance
|
||||
* impact when pool suspension is enabled. Unless you need it (for a
|
||||
* redundancy system for example) do not enable it.
|
||||
*
|
||||
* @param isAllowPoolSuspension the desired pool suspension allowance
|
||||
*/
|
||||
public void setAllowPoolSuspension(boolean isAllowPoolSuspension)
|
||||
{
|
||||
this.isAllowPoolSuspension = isAllowPoolSuspension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether or not the construction of the pool should throw an exception
|
||||
* if the minimum number of connections cannot be created.
|
||||
*
|
||||
* @return whether or not initialization should fail on error immediately
|
||||
*/
|
||||
public boolean isInitializationFailFast()
|
||||
{
|
||||
return isInitializationFailFast;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether or not the construction of the pool should throw an exception
|
||||
* if the minimum number of connections cannot be created.
|
||||
*
|
||||
* @param failFast true if the pool should fail if the minimum connections cannot be created
|
||||
*/
|
||||
public void setInitializationFailFast(boolean failFast)
|
||||
{
|
||||
isInitializationFailFast = failFast;
|
||||
}
|
||||
|
||||
public boolean isIsolateInternalQueries()
|
||||
{
|
||||
return isIsolateInternalQueries;
|
||||
}
|
||||
|
||||
public void setIsolateInternalQueries(boolean isolate)
|
||||
{
|
||||
this.isIsolateInternalQueries = isolate;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean isJdbc4ConnectionTest()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setJdbc4ConnectionTest(boolean useIsValid)
|
||||
{
|
||||
// ignored deprecated property
|
||||
LOGGER.warn("The jdbcConnectionTest property is now deprecated, see the documentation for connectionTestQuery");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Codahale MetricRegistry, could be null.
|
||||
*
|
||||
* @return the codahale MetricRegistry instance
|
||||
*/
|
||||
public Object getMetricRegistry()
|
||||
{
|
||||
return metricRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a Codahale MetricRegistry to use for HikariCP.
|
||||
*
|
||||
* @param metricRegistry the Codahale MetricRegistry to set
|
||||
*/
|
||||
public void setMetricRegistry(Object metricRegistry)
|
||||
{
|
||||
if (metricRegistry != null) {
|
||||
if (metricRegistry instanceof String) {
|
||||
try {
|
||||
InitialContext initCtx = new InitialContext();
|
||||
metricRegistry = (MetricRegistry) initCtx.lookup((String) metricRegistry);
|
||||
}
|
||||
catch (NamingException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(metricRegistry instanceof MetricRegistry)) {
|
||||
throw new IllegalArgumentException("Class must be an instance of com.codahale.metrics.MetricRegistry");
|
||||
}
|
||||
}
|
||||
|
||||
this.metricRegistry = metricRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Codahale HealthCheckRegistry, could be null.
|
||||
*
|
||||
* @return the Codahale HealthCheckRegistry instance
|
||||
*/
|
||||
public Object getHealthCheckRegistry()
|
||||
{
|
||||
return healthCheckRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a Codahale HealthCheckRegistry to use for HikariCP.
|
||||
*
|
||||
* @param healthCheckRegistry the Codahale HealthCheckRegistry to set
|
||||
*/
|
||||
public void setHealthCheckRegistry(Object healthCheckRegistry)
|
||||
{
|
||||
if (healthCheckRegistry != null) {
|
||||
if (healthCheckRegistry instanceof String) {
|
||||
try {
|
||||
InitialContext initCtx = new InitialContext();
|
||||
healthCheckRegistry = (MetricRegistry) initCtx.lookup((String) healthCheckRegistry);
|
||||
}
|
||||
catch (NamingException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(healthCheckRegistry instanceof HealthCheckRegistry)) {
|
||||
throw new IllegalArgumentException("Class must be an instance of com.codahale.metrics.health.HealthCheckRegistry");
|
||||
}
|
||||
}
|
||||
|
||||
this.healthCheckRegistry = healthCheckRegistry;
|
||||
}
|
||||
|
||||
public Properties getHealthCheckProperties()
|
||||
{
|
||||
return healthCheckProperties;
|
||||
}
|
||||
|
||||
public void setHealthCheckProperties(Properties healthCheckProperties)
|
||||
{
|
||||
this.healthCheckProperties.putAll(healthCheckProperties);
|
||||
}
|
||||
|
||||
public void addHealthCheckProperty(String key, String value)
|
||||
{
|
||||
healthCheckProperties.setProperty(key, value);
|
||||
}
|
||||
|
||||
public boolean isReadOnly()
|
||||
{
|
||||
return isReadOnly;
|
||||
}
|
||||
|
||||
public void setReadOnly(boolean readOnly)
|
||||
{
|
||||
this.isReadOnly = readOnly;
|
||||
}
|
||||
|
||||
public boolean isRegisterMbeans()
|
||||
{
|
||||
return isRegisterMbeans;
|
||||
}
|
||||
|
||||
public void setRegisterMbeans(boolean register)
|
||||
{
|
||||
this.isRegisterMbeans = register;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public long getLeakDetectionThreshold()
|
||||
{
|
||||
return leakDetectionThreshold;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setLeakDetectionThreshold(long leakDetectionThresholdMs)
|
||||
{
|
||||
this.leakDetectionThreshold = leakDetectionThresholdMs;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public long getMaxLifetime()
|
||||
{
|
||||
return maxLifetime;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setMaxLifetime(long maxLifetimeMs)
|
||||
{
|
||||
this.maxLifetime = maxLifetimeMs;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int getMaximumPoolSize()
|
||||
{
|
||||
return maxPoolSize;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setMaximumPoolSize(int maxPoolSize)
|
||||
{
|
||||
if (maxPoolSize < 1) {
|
||||
throw new IllegalArgumentException("maxPoolSize cannot be less than 1");
|
||||
}
|
||||
this.maxPoolSize = maxPoolSize;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int getMinimumIdle()
|
||||
{
|
||||
return minIdle;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setMinimumIdle(int minIdle)
|
||||
{
|
||||
if (minIdle < 0) {
|
||||
throw new IllegalArgumentException("minimumIdle cannot be negative");
|
||||
}
|
||||
this.minIdle = minIdle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default password to use for DataSource.getConnection(username, password) calls.
|
||||
* @return the password
|
||||
*/
|
||||
public String getPassword()
|
||||
{
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default password to use for DataSource.getConnection(username, password) calls.
|
||||
* @param password the password
|
||||
*/
|
||||
public void setPassword(String password)
|
||||
{
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public String getPoolName()
|
||||
{
|
||||
return poolName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the connection pool. This is primarily used for the MBean
|
||||
* to uniquely identify the pool configuration.
|
||||
*
|
||||
* @param poolName the name of the connection pool to use
|
||||
*/
|
||||
public void setPoolName(String poolName)
|
||||
{
|
||||
this.poolName = poolName;
|
||||
}
|
||||
|
||||
public String getTransactionIsolation()
|
||||
{
|
||||
return transactionIsolationName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default transaction isolation level. The specified value is the
|
||||
* constant name from the <code>Connection</code> class, eg.
|
||||
* <code>TRANSACTION_REPEATABLE_READ</code>.
|
||||
*
|
||||
* @param isolationLevel the name of the isolation level
|
||||
*/
|
||||
public void setTransactionIsolation(String isolationLevel)
|
||||
{
|
||||
this.transactionIsolationName = isolationLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default username used for DataSource.getConnection(username, password) calls.
|
||||
*
|
||||
* @return the username
|
||||
*/
|
||||
public String getUsername()
|
||||
{
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default username used for DataSource.getConnection(username, password) calls.
|
||||
*
|
||||
* @param username the username
|
||||
*/
|
||||
public void setUsername(String username)
|
||||
{
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the thread factory used to create threads.
|
||||
*
|
||||
* @return the thread factory (may be null, in which case the default thread factory is used)
|
||||
*/
|
||||
public ThreadFactory getThreadFactory()
|
||||
{
|
||||
return threadFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the thread factory to be used to create threads.
|
||||
*
|
||||
* @param threadFactory the thread factory (setting to null causes the default thread factory to be used)
|
||||
*/
|
||||
public void setThreadFactory(ThreadFactory threadFactory)
|
||||
{
|
||||
this.threadFactory = threadFactory;
|
||||
}
|
||||
|
||||
public void validate()
|
||||
{
|
||||
Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
validateNumerics();
|
||||
|
||||
if (connectionCustomizerClassName != null) {
|
||||
try {
|
||||
getClass().getClassLoader().loadClass(connectionCustomizerClassName);
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.warn("connectionCustomizationClass specified class '" + connectionCustomizerClassName + "' could not be loaded", e);
|
||||
connectionCustomizerClassName = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (driverClassName != null && jdbcUrl == null) {
|
||||
logger.error("when specifying driverClassName, jdbcUrl must also be specified");
|
||||
throw new IllegalStateException("when specifying driverClassName, jdbcUrl must also be specified");
|
||||
}
|
||||
else if (driverClassName != null && dataSourceClassName != null) {
|
||||
logger.error("both driverClassName and dataSourceClassName are specified, one or the other should be used");
|
||||
throw new IllegalStateException("both driverClassName and dataSourceClassName are specified, one or the other should be used");
|
||||
}
|
||||
else if (jdbcUrl != null) {
|
||||
// OK
|
||||
}
|
||||
else if (dataSource == null && dataSourceClassName == null) {
|
||||
logger.error("one of either dataSource, dataSourceClassName, or jdbcUrl and driverClassName must be specified");
|
||||
throw new IllegalArgumentException("one of either dataSource or dataSourceClassName must be specified");
|
||||
}
|
||||
else if (dataSource != null && dataSourceClassName != null) {
|
||||
logger.warn("both dataSource and dataSourceClassName are specified, ignoring dataSourceClassName");
|
||||
}
|
||||
|
||||
if (transactionIsolationName != null) {
|
||||
UtilityElf.getTransactionIsolation(transactionIsolationName);
|
||||
}
|
||||
|
||||
if (poolName == null) {
|
||||
poolName = "HikariPool-" + poolNumber++;
|
||||
}
|
||||
|
||||
if (LOGGER.isDebugEnabled() || unitTest) {
|
||||
logConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
private void validateNumerics()
|
||||
{
|
||||
Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
if (validationTimeout > connectionTimeout && connectionTimeout != 0) {
|
||||
logger.warn("validationTimeout is greater than connectionTimeout, setting validationTimeout to connectionTimeout.");
|
||||
validationTimeout = connectionTimeout;
|
||||
}
|
||||
|
||||
if (minIdle < 0 || minIdle > maxPoolSize) {
|
||||
minIdle = maxPoolSize;
|
||||
}
|
||||
|
||||
if (maxLifetime < 0) {
|
||||
logger.error("maxLifetime cannot be negative.");
|
||||
throw new IllegalArgumentException("maxLifetime cannot be negative.");
|
||||
}
|
||||
else if (maxLifetime > 0 && maxLifetime < TimeUnit.SECONDS.toMillis(30)) {
|
||||
logger.warn("maxLifetime is less than 30000ms, using default {}ms.", MAX_LIFETIME);
|
||||
maxLifetime = MAX_LIFETIME;
|
||||
}
|
||||
|
||||
if (idleTimeout != 0 && idleTimeout < TimeUnit.SECONDS.toMillis(10)) {
|
||||
logger.warn("idleTimeout is less than 10000ms, using default {}ms.", IDLE_TIMEOUT);
|
||||
idleTimeout = IDLE_TIMEOUT;
|
||||
}
|
||||
else if (idleTimeout > maxLifetime && maxLifetime > 0) {
|
||||
logger.warn("idleTimeout is greater than maxLifetime, setting to maxLifetime.");
|
||||
idleTimeout = maxLifetime;
|
||||
}
|
||||
|
||||
if (leakDetectionThreshold != 0 && leakDetectionThreshold < TimeUnit.SECONDS.toMillis(2) && !unitTest) {
|
||||
logger.warn("leakDetectionThreshold is less than 2000ms, setting to minimum 2000ms.");
|
||||
leakDetectionThreshold = 2000L;
|
||||
}
|
||||
}
|
||||
|
||||
private void logConfiguration()
|
||||
{
|
||||
LOGGER.debug("HikariCP pool {} configuration:", poolName);
|
||||
final Set<String> propertyNames = new TreeSet<String>(PropertyBeanSetter.getPropertyNames(HikariConfig.class));
|
||||
for (String prop : propertyNames) {
|
||||
try {
|
||||
Object value = PropertyBeanSetter.getProperty(prop, this);
|
||||
if ("dataSourceProperties".equals(prop)) {
|
||||
Properties dsProps = PropertyBeanSetter.copyProperties(dataSourceProperties);
|
||||
dsProps.setProperty("password", "<masked>");
|
||||
value = dsProps;
|
||||
}
|
||||
value = (prop.contains("password") ? "<masked>" : value);
|
||||
LOGGER.debug((prop + "................................................").substring(0, 32) + (value != null ? value : ""));
|
||||
}
|
||||
catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadProperties(String propertyFileName)
|
||||
{
|
||||
final File propFile = new File(propertyFileName);
|
||||
try (final InputStream is = propFile.isFile() ? new FileInputStream(propFile) : this.getClass().getResourceAsStream(propertyFileName)) {
|
||||
if (is != null) {
|
||||
Properties props = new Properties();
|
||||
props.load(is);
|
||||
PropertyBeanSetter.setTargetFromProperties(this, props);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Property file " + propertyFileName + " was not found.");
|
||||
}
|
||||
}
|
||||
catch (IOException io) {
|
||||
throw new RuntimeException("Error loading properties file", io);
|
||||
}
|
||||
}
|
||||
|
||||
public void copyState(HikariConfig other)
|
||||
{
|
||||
for (Field field : HikariConfig.class.getDeclaredFields()) {
|
||||
if (!Modifier.isFinal(field.getModifiers())) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
field.set(other, field.get(this));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException("Exception copying HikariConfig state: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,265 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013, 2014 Brett Wooldridge
|
||||
*
|
||||
* Licensed 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 com.zaxxer.hikari.proxy;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javassist.ClassPool;
|
||||
import javassist.CtClass;
|
||||
import javassist.CtMethod;
|
||||
import javassist.CtNewMethod;
|
||||
import javassist.LoaderClassPath;
|
||||
import javassist.Modifier;
|
||||
import javassist.NotFoundException;
|
||||
|
||||
import com.zaxxer.hikari.util.ClassLoaderUtils;
|
||||
|
||||
/**
|
||||
* This class generates the proxy objects for {@link Connection}, {@link Statement},
|
||||
* {@link PreparedStatement}, and {@link CallableStatement}. Additionally it injects
|
||||
* method bodies into the {@link ProxyFactory} class methods that can instantiate
|
||||
* instances of the generated proxies.
|
||||
*
|
||||
* @author Brett Wooldridge
|
||||
*/
|
||||
public final class JavassistProxyFactory
|
||||
{
|
||||
private ClassPool classPool;
|
||||
|
||||
static {
|
||||
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
Thread.currentThread().setContextClassLoader(JavassistProxyFactory.class.getClassLoader());
|
||||
|
||||
JavassistProxyFactory proxyFactoryFactory = new JavassistProxyFactory();
|
||||
proxyFactoryFactory.modifyProxyFactory();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException("Fatal exception during proxy generation", e);
|
||||
}
|
||||
finally {
|
||||
Thread.currentThread().setContextClassLoader(contextClassLoader);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply invoking this method causes the initialization of this class. All work
|
||||
* by this class is performed in static initialization.
|
||||
*/
|
||||
public static void initialize()
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
private JavassistProxyFactory() throws Exception
|
||||
{
|
||||
classPool = new ClassPool();
|
||||
classPool.importPackage("java.sql");
|
||||
classPool.appendClassPath(new LoaderClassPath(this.getClass().getClassLoader()));
|
||||
|
||||
// Cast is not needed for these
|
||||
String methodBody = "{ try { return delegate.method($$); } catch (SQLException e) { throw checkException(e); } }";
|
||||
generateProxyClass(Connection.class, ConnectionProxy.class, methodBody);
|
||||
generateProxyClass(Statement.class, StatementProxy.class, methodBody);
|
||||
generateProxyClass(ResultSet.class, ResultSetProxy.class, methodBody);
|
||||
|
||||
// For these we have to cast the delegate
|
||||
methodBody = "{ try { return ((cast) delegate).method($$); } catch (SQLException e) { throw checkException(e); } }";
|
||||
generateProxyClass(PreparedStatement.class, PreparedStatementProxy.class, methodBody);
|
||||
generateProxyClass(CallableStatement.class, CallableStatementProxy.class, methodBody);
|
||||
}
|
||||
|
||||
private void modifyProxyFactory() throws Exception
|
||||
{
|
||||
String packageName = JavassistProxyFactory.class.getPackage().getName();
|
||||
CtClass proxyCt = classPool.getCtClass("com.zaxxer.hikari.proxy.ProxyFactory");
|
||||
for (CtMethod method : proxyCt.getMethods()) {
|
||||
switch (method.getName()) {
|
||||
case "getProxyConnection":
|
||||
method.setBody("{return new " + packageName + ".ConnectionJavassistProxy($$);}");
|
||||
break;
|
||||
case "getProxyStatement":
|
||||
method.setBody("{return new " + packageName + ".StatementJavassistProxy($$);}");
|
||||
break;
|
||||
case "getProxyPreparedStatement":
|
||||
method.setBody("{return new " + packageName + ".PreparedStatementJavassistProxy($$);}");
|
||||
break;
|
||||
case "getProxyCallableStatement":
|
||||
method.setBody("{return new " + packageName + ".CallableStatementJavassistProxy($$);}");
|
||||
break;
|
||||
case "getProxyResultSet":
|
||||
method.setBody("{return new " + packageName + ".ResultSetJavassistProxy($$);}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
proxyCt.toClass(classPool.getClassLoader(), getClass().getProtectionDomain());
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Javassist Proxy Classes
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> Class<T> generateProxyClass(Class<T> primaryInterface, Class<?> superClass, String methodBody) throws Exception
|
||||
{
|
||||
// Make a new class that extends one of the JavaProxy classes (ie. superClass); use the name to XxxJavassistProxy instead of XxxProxy
|
||||
String superClassName = superClass.getName();
|
||||
CtClass superClassCt = classPool.getCtClass(superClassName);
|
||||
CtClass targetCt = classPool.makeClass(superClassName.replace("Proxy", "JavassistProxy"), superClassCt);
|
||||
targetCt.setModifiers(Modifier.FINAL);
|
||||
|
||||
// Make a set of method signatures we inherit implementation for, so we don't generate delegates for these
|
||||
Set<String> superSigs = new HashSet<String>();
|
||||
for (CtMethod method : superClassCt.getMethods()) {
|
||||
if ((method.getModifiers() & Modifier.FINAL) == Modifier.FINAL) {
|
||||
superSigs.add(method.getName() + method.getSignature());
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> methods = new HashSet<String>();
|
||||
Set<Class<?>> interfaces = ClassLoaderUtils.getAllInterfaces(primaryInterface);
|
||||
for (Class<?> intf : interfaces) {
|
||||
CtClass intfCt = classPool.getCtClass(intf.getName());
|
||||
targetCt.addInterface(intfCt);
|
||||
for (CtMethod intfMethod : intfCt.getDeclaredMethods()) {
|
||||
final String signature = intfMethod.getName() + intfMethod.getSignature();
|
||||
|
||||
// don't generate delegates for methods we override
|
||||
if (superSigs.contains(signature)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore already added methods that come from other interfaces
|
||||
if (methods.contains(signature)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore default methods (only for Jre8 or later)
|
||||
if (isDefaultMethod(intf, intfCt, intfMethod)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Track what methods we've added
|
||||
methods.add(signature);
|
||||
|
||||
// Clone the method we want to inject into
|
||||
CtMethod method = CtNewMethod.copy(intfMethod, targetCt, null);
|
||||
|
||||
String modifiedBody = methodBody;
|
||||
|
||||
// If the super-Proxy has concrete methods (non-abstract), transform the call into a simple super.method() call
|
||||
CtMethod superMethod = superClassCt.getMethod(intfMethod.getName(), intfMethod.getSignature());
|
||||
if ((superMethod.getModifiers() & Modifier.ABSTRACT) != Modifier.ABSTRACT) {
|
||||
modifiedBody = modifiedBody.replace("((cast) ", "");
|
||||
modifiedBody = modifiedBody.replace("delegate", "super");
|
||||
modifiedBody = modifiedBody.replace("super)", "super");
|
||||
}
|
||||
|
||||
modifiedBody = modifiedBody.replace("cast", primaryInterface.getName());
|
||||
|
||||
// Generate a method that simply invokes the same method on the delegate
|
||||
if (isThrowsSqlException(intfMethod)) {
|
||||
modifiedBody = modifiedBody.replace("method", method.getName());
|
||||
}
|
||||
else {
|
||||
modifiedBody = "{ return ((cast) delegate).method($$); }".replace("method", method.getName()).replace("cast", primaryInterface.getName());
|
||||
}
|
||||
|
||||
if (method.getReturnType() == CtClass.voidType) {
|
||||
modifiedBody = modifiedBody.replace("return", "");
|
||||
}
|
||||
|
||||
method.setBody(modifiedBody);
|
||||
targetCt.addMethod(method);
|
||||
}
|
||||
}
|
||||
|
||||
return targetCt.toClass(classPool.getClassLoader(), getClass().getProtectionDomain());
|
||||
}
|
||||
|
||||
private boolean isThrowsSqlException(CtMethod method)
|
||||
{
|
||||
try {
|
||||
for (CtClass clazz : method.getExceptionTypes()) {
|
||||
if (clazz.getSimpleName().equals("SQLException")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NotFoundException e) {
|
||||
// fall thru
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isDefaultMethod(Class<?> intf, CtClass intfCt, CtMethod intfMethod) throws Exception
|
||||
{
|
||||
List<Class<?>> paramTypes = new ArrayList<Class<?>>();
|
||||
|
||||
for (CtClass pt : intfMethod.getParameterTypes()) {
|
||||
paramTypes.add(toJavaClass(pt));
|
||||
}
|
||||
|
||||
return intf.getDeclaredMethod(intfMethod.getName(), paramTypes.toArray(new Class[0])).toString().contains("default ");
|
||||
}
|
||||
|
||||
private Class<?> toJavaClass(CtClass cls) throws Exception
|
||||
{
|
||||
if (cls.getName().endsWith("[]")) {
|
||||
return Array.newInstance(toJavaClass(cls.getName().replace("[]", "")), 0).getClass();
|
||||
}
|
||||
else {
|
||||
return toJavaClass(cls.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?> toJavaClass(String cn) throws Exception
|
||||
{
|
||||
switch (cn) {
|
||||
case "int":
|
||||
return int.class;
|
||||
case "long":
|
||||
return long.class;
|
||||
case "short":
|
||||
return short.class;
|
||||
case "byte":
|
||||
return byte.class;
|
||||
case "float":
|
||||
return float.class;
|
||||
case "double":
|
||||
return double.class;
|
||||
case "boolean":
|
||||
return boolean.class;
|
||||
case "char":
|
||||
return char.class;
|
||||
case "void":
|
||||
return void.class;
|
||||
default:
|
||||
return Class.forName(cn);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,261 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<!-- For release: mvn release:perform -Darguments=-Dgpg.passphrase=PASSPHRASE -->
|
||||
|
||||
<artifactId>HikariCP-java7</artifactId>
|
||||
<packaging>bundle</packaging>
|
||||
|
||||
<name>HikariCP-java7</name>
|
||||
<description>Ultimate JDBC Connection Pool</description>
|
||||
<url>https://github.com/brettwooldridge/HikariCP</url>
|
||||
|
||||
<organization>
|
||||
<name>Zaxxer.com</name>
|
||||
<url>https://github.com/brettwooldridge</url>
|
||||
</organization>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:git@github.com:brettwooldridge/HikariCP.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:brettwooldridge/HikariCP.git</developerConnection>
|
||||
<url>git@github.com:brettwooldridge/HikariCP.git</url>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The Apache Software License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Brett Wooldridge</name>
|
||||
<email>brett.wooldridge@gmail.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<felix.bundle.plugin.version>2.4.0</felix.bundle.plugin.version>
|
||||
<felix.version>4.2.1</felix.version>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP-parent</artifactId>
|
||||
<version>2.4.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src/main/java</sourceDirectory>
|
||||
<testSourceDirectory>src/test/java</testSourceDirectory>
|
||||
<plugins>
|
||||
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<version>1.9.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>src</id>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>add-source</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>../hikaricp-common/src/main/java</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test</id>
|
||||
<phase>generate-test-sources</phase>
|
||||
<goals>
|
||||
<goal>add-test-source</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>../hikaricp-common/src/test/java</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test-resources</id>
|
||||
<phase>generate-test-resources</phase>
|
||||
<goals>
|
||||
<goal>add-test-resource</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>../hikaricp-common/src/test/resources</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<version>${felix.bundle.plugin.version}</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-Name>HikariCP-java7</Bundle-Name>
|
||||
<Export-Package>
|
||||
com.zaxxer.hikari,
|
||||
com.zaxxer.hikari.hibernate
|
||||
</Export-Package>
|
||||
<Private-Package>com.zaxxer.hikari.*</Private-Package>
|
||||
<_exportcontents>
|
||||
com.zaxxer.hikari.pool,
|
||||
com.zaxxer.hikari.util,
|
||||
com.zaxxer.hikari.proxy
|
||||
</_exportcontents>
|
||||
<Import-Package>
|
||||
javassist.*,
|
||||
javax.management,
|
||||
javax.naming,
|
||||
javax.naming.spi,
|
||||
javax.sql,
|
||||
javax.sql.rowset,
|
||||
javax.sql.rowset.serial,
|
||||
javax.sql.rowset.spi,
|
||||
com.codahale.metrics;resolution:=optional,
|
||||
com.codahale.metrics.health;resolution:=optional,
|
||||
org.slf4j;version="[1.6,2)",
|
||||
org.hibernate;resolution:=optional,
|
||||
org.hibernate.cfg;resolution:=optional,
|
||||
org.hibernate.engine.jdbc.connections.spi;resolution:=optional,
|
||||
org.hibernate.service;resolution:=optional,
|
||||
org.hibernate.service.spi;resolution:=optional
|
||||
</Import-Package>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<DynamicImport-Package>*</DynamicImport-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
<executions>
|
||||
<!-- This execution makes sure that the manifest is available when the tests are executed -->
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<tagNameFormat>HikariCP-@{project.version}</tagNameFormat>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself. -->
|
||||
<plugin>
|
||||
<groupId>org.eclipse.m2e</groupId>
|
||||
<artifactId>lifecycle-mapping</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<configuration>
|
||||
<lifecycleMappingMetadata>
|
||||
<pluginExecutions>
|
||||
<pluginExecution>
|
||||
<pluginExecutionFilter>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>
|
||||
maven-bundle-plugin
|
||||
</artifactId>
|
||||
<versionRange>[2.4.0,)</versionRange>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</pluginExecutionFilter>
|
||||
<action>
|
||||
<ignore />
|
||||
</action>
|
||||
</pluginExecution>
|
||||
</pluginExecutions>
|
||||
</lifecycleMappingMetadata>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>release-sign-artifacts</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>performRelease</name>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>felix</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
<property>
|
||||
<name>pax.exam.framework</name>
|
||||
<value>felix</value>
|
||||
</property>
|
||||
</activation>
|
||||
<properties>
|
||||
<pax.exam.framework>felix</pax.exam.framework>
|
||||
<pax.exam.logging>none</pax.exam.logging>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>org.apache.felix.framework</artifactId>
|
||||
<version>${felix.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
@ -1,206 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013,2014 Brett Wooldridge
|
||||
*
|
||||
* Licensed 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 com.zaxxer.hikari.pool;
|
||||
|
||||
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_IN_USE;
|
||||
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_NOT_IN_USE;
|
||||
import static com.zaxxer.hikari.util.UtilityElf.quietlySleep;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.util.ConcurrentBag;
|
||||
import com.zaxxer.hikari.util.IBagStateListener;
|
||||
import com.zaxxer.hikari.util.Java7ConcurrentBag;
|
||||
|
||||
/**
|
||||
* This is the primary connection pool class that provides the basic
|
||||
* pooling behavior for HikariCP.
|
||||
*
|
||||
* @author Brett Wooldridge
|
||||
*/
|
||||
public final class HikariPool extends BaseHikariPool
|
||||
{
|
||||
/**
|
||||
* Construct a HikariPool with the specified configuration.
|
||||
*
|
||||
* @param configuration a HikariConfig instance
|
||||
*/
|
||||
public HikariPool(HikariConfig configuration)
|
||||
{
|
||||
this(configuration, configuration.getUsername(), configuration.getPassword());
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a HikariPool with the specified configuration.
|
||||
*
|
||||
* @param configuration a HikariConfig instance
|
||||
* @param username authentication username
|
||||
* @param password authentication password
|
||||
*/
|
||||
public HikariPool(HikariConfig configuration, String username, String password)
|
||||
{
|
||||
super(configuration, username, password);
|
||||
}
|
||||
|
||||
// ***********************************************************************
|
||||
// IBagStateListener callback
|
||||
// ***********************************************************************
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void addBagItem()
|
||||
{
|
||||
class AddConnection implements Runnable
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
long sleepBackoff = 200L;
|
||||
final int maxPoolSize = configuration.getMaximumPoolSize();
|
||||
while (poolState == POOL_RUNNING && totalConnections.get() < maxPoolSize && !addConnection()) {
|
||||
// If we got into the loop, addConnection() failed, so we sleep and retry
|
||||
quietlySleep(sleepBackoff);
|
||||
sleepBackoff = Math.min(connectionTimeout / 2, (long) ((double) sleepBackoff * 1.5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addConnectionExecutor.execute(new AddConnection());
|
||||
}
|
||||
|
||||
// ***********************************************************************
|
||||
// HikariPoolMBean methods
|
||||
// ***********************************************************************
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void softEvictConnections()
|
||||
{
|
||||
for (PoolBagEntry bagEntry : connectionBag.values(STATE_IN_USE)) {
|
||||
bagEntry.evicted = true;
|
||||
}
|
||||
|
||||
for (PoolBagEntry bagEntry : connectionBag.values(STATE_NOT_IN_USE)) {
|
||||
if (connectionBag.reserve(bagEntry)) {
|
||||
closeConnection(bagEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ***********************************************************************
|
||||
// Protected methods
|
||||
// ***********************************************************************
|
||||
|
||||
/**
|
||||
* Permanently close the real (underlying) connection (eat any exception).
|
||||
*
|
||||
* @param connectionProxy the connection to actually close
|
||||
*/
|
||||
@Override
|
||||
protected void closeConnection(final PoolBagEntry bagEntry)
|
||||
{
|
||||
bagEntry.cancelMaxLifeTermination();
|
||||
if (connectionBag.remove(bagEntry)) {
|
||||
final int tc = totalConnections.decrementAndGet();
|
||||
if (tc < 0) {
|
||||
LOGGER.warn("Internal accounting inconsistency, totalConnections={}", tc, new Exception());
|
||||
}
|
||||
closeConnectionExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
poolUtils.quietlyCloseConnection(bagEntry.connection);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to abort() active connections on Java7+, or close() them on Java6.
|
||||
*
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Override
|
||||
protected void abortActiveConnections(final ExecutorService assassinExecutor) throws InterruptedException
|
||||
{
|
||||
for (PoolBagEntry bagEntry : connectionBag.values(STATE_IN_USE)) {
|
||||
try {
|
||||
bagEntry.aborted = bagEntry.evicted = true;
|
||||
bagEntry.connection.abort(assassinExecutor);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
if (e instanceof InterruptedException) {
|
||||
throw (InterruptedException) e;
|
||||
}
|
||||
poolUtils.quietlyCloseConnection(bagEntry.connection);
|
||||
}
|
||||
finally {
|
||||
if (connectionBag.remove(bagEntry)) {
|
||||
totalConnections.decrementAndGet();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
protected Runnable getHouseKeeper()
|
||||
{
|
||||
return new HouseKeeper();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
protected ConcurrentBag<PoolBagEntry> createConcurrentBag(IBagStateListener listener)
|
||||
{
|
||||
return new Java7ConcurrentBag(listener);
|
||||
}
|
||||
|
||||
// ***********************************************************************
|
||||
// Non-anonymous Inner-classes
|
||||
// ***********************************************************************
|
||||
|
||||
/**
|
||||
* The house keeping task to retire idle connections.
|
||||
*/
|
||||
private class HouseKeeper implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
logPoolState("Before cleanup ");
|
||||
|
||||
connectionTimeout = configuration.getConnectionTimeout(); // refresh member in case it changed
|
||||
|
||||
final long now = System.currentTimeMillis();
|
||||
final long idleTimeout = configuration.getIdleTimeout();
|
||||
|
||||
for (PoolBagEntry bagEntry : connectionBag.values(STATE_NOT_IN_USE)) {
|
||||
if (connectionBag.reserve(bagEntry)) {
|
||||
if (bagEntry.evicted || (idleTimeout > 0L && now > bagEntry.lastAccess + idleTimeout)) {
|
||||
closeConnection(bagEntry);
|
||||
}
|
||||
else {
|
||||
connectionBag.unreserve(bagEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logPoolState("After cleanup ");
|
||||
|
||||
fillPool(); // Try to maintain minimum connections
|
||||
}
|
||||
}
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013, 2014 Brett Wooldridge
|
||||
*
|
||||
* Licensed 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 com.zaxxer.hikari.util;
|
||||
|
||||
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_IN_USE;
|
||||
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_NOT_IN_USE;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.zaxxer.hikari.pool.PoolBagEntry;
|
||||
|
||||
/**
|
||||
* This is a specialized concurrent bag that achieves superior performance
|
||||
* to LinkedBlockingQueue and LinkedTransferQueue for the purposes of a
|
||||
* connection pool. It uses ThreadLocal storage when possible to avoid
|
||||
* locks, but resorts to scanning a common collection if there are no
|
||||
* available items in the ThreadLocal list. Not-in-use items in the
|
||||
* ThreadLocal lists can be "stolen" when the borrowing thread has none
|
||||
* of its own. It is a "lock-less" implementation using a specialized
|
||||
* AbstractQueuedLongSynchronizer to manage cross-thread signaling.
|
||||
*
|
||||
* Note that items that are "borrowed" from the bag are not actually
|
||||
* removed from any collection, so garbage collection will not occur
|
||||
* even if the reference is abandoned. Thus care must be taken to
|
||||
* "requite" borrowed objects otherwise a memory leak will result. Only
|
||||
* the "remove" method can completely remove an object from the bag.
|
||||
*
|
||||
* @author Brett Wooldridge
|
||||
*
|
||||
* @param <T> the templated type to store in the bag
|
||||
*/
|
||||
public final class Java7ConcurrentBag extends ConcurrentBag<PoolBagEntry>
|
||||
{
|
||||
public Java7ConcurrentBag(IBagStateListener listener)
|
||||
{
|
||||
super(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method provides a "snaphot" in time of the BagEntry
|
||||
* items in the bag in the specified state. It does not "lock"
|
||||
* or reserve items in any way. Call <code>reserve(BagEntry)</code>
|
||||
* on items in list before performing any action on them.
|
||||
*
|
||||
* @param state one of STATE_NOT_IN_USE or STATE_IN_USE
|
||||
* @return a possibly empty list of objects having the state specified
|
||||
*/
|
||||
public List<PoolBagEntry> values(final int state)
|
||||
{
|
||||
final ArrayList<PoolBagEntry> list = new ArrayList<PoolBagEntry>(sharedList.size());
|
||||
if (state == STATE_IN_USE || state == STATE_NOT_IN_USE) {
|
||||
for (final PoolBagEntry reference : sharedList) {
|
||||
if (reference.state.get() == state) {
|
||||
list.add(reference);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a count of the number of items in the specified state at the time of this call.
|
||||
*
|
||||
* @param state the state of the items to count
|
||||
* @return a count of how many items in the bag are in the specified state
|
||||
*/
|
||||
public int getCount(final int state)
|
||||
{
|
||||
int count = 0;
|
||||
for (final PoolBagEntry reference : sharedList) {
|
||||
if (reference.state.get() == state) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
@ -1,210 +0,0 @@
|
||||
# This is a manually maintained codex of JDBC drivers and the
|
||||
# classes within that need to be instrumented.
|
||||
#
|
||||
|
||||
# ------ HSQLDB v2.3.1 ----------------------------------------------------------
|
||||
#
|
||||
org.hsqldb.jdbc.JDBCDataSource=hsqldb
|
||||
|
||||
hsqldb.baseConnection=org.hsqldb.jdbc.JDBCConnection
|
||||
|
||||
hsqldb.baseStatement=org.hsqldb.jdbc.JDBCStatement
|
||||
|
||||
hsqldb.basePreparedStatement=org.hsqldb.jdbc.JDBCPreparedStatement
|
||||
|
||||
hsqldb.subCallableStatement=org.hsqldb.jdbc.JDBCCallableStatement
|
||||
|
||||
hsqldb.baseResultSet=org.hsqldb.jdbc.JDBCResultSet
|
||||
hsqldb.subResultSet=org.hsqldb.jdbc.JDBCResultSet$JDBCResultSetBasic
|
||||
|
||||
|
||||
# ------ Derby v10.10.1.1 -------------------------------------------------------
|
||||
#
|
||||
org.apache.derby.jdbc.ClientDataSource40=derby
|
||||
|
||||
derby.baseConnection=org.apache.derby.client.am.Connection
|
||||
derby.subConnection=org.apache.derby.client.net.NetConnection40
|
||||
|
||||
derby.baseStatement=org.apache.derby.client.am.Statement
|
||||
|
||||
derby.subPreparedStatement=org.apache.derby.client.am.PreparedStatement
|
||||
derby.subPreparedStatement=org.apache.derby.client.am.PreparedStatement40
|
||||
#derby.subPreparedStatement=org.apache.derby.client.am.PreparedStatement42
|
||||
|
||||
derby.subCallableStatement=org.apache.derby.client.am.CallableStatement
|
||||
derby.subCallableStatement=org.apache.derby.client.am.CallableStatement40
|
||||
#derby.subCallableStatement=org.apache.derby.client.am.CallableStatement42
|
||||
|
||||
derby.baseResultSet=org.apache.derby.client.am.ResultSet
|
||||
derby.subResultSet=org.apache.derby.client.net.NetResultSet40
|
||||
#derby.subResultSet=org.apache.derby.client.net.NetResultSet42
|
||||
|
||||
# ------ Derby Embedded v10.10.1.1 ----------------------------------------------
|
||||
#
|
||||
|
||||
derby-em.baseConnection=org.apache.derby.impl.jdbc.EmbedConnection
|
||||
derby-em.baseConnection=org.apache.derby.iapi.jdbc.BrokeredConnection
|
||||
derby-em.subConnection=org.apache.derby.impl.jdbc.EmbedConnection40
|
||||
derby-em.subConnection=org.apache.derby.iapi.jdbc.BrokeredConnection40
|
||||
#derby-em.subConnection=org.apache.derby.iapi.jdbc.BrokeredConnection42
|
||||
|
||||
derby-em.baseStatement=org.apache.derby.impl.jdbc.EmbedStatement
|
||||
derby-em.baseStatement=org.apache.derby.iapi.jdbc.BrokeredStatement
|
||||
derby-em.baseStatement=org.apache.derby.client.am.Statement
|
||||
derby-em.subStatement=org.apache.derby.impl.jdbc.EmbedStatement40
|
||||
derby-em.subStatement=org.apache.derby.iapi.jdbc.BrokeredStatement40
|
||||
|
||||
derby-em.subPreparedStatement=org.apache.derby.impl.jdbc.EmbedPreparedStatement
|
||||
derby-em.subPreparedStatement=org.apache.derby.impl.jdbc.EmbedPreparedStatement20
|
||||
derby-em.subPreparedStatement=org.apache.derby.impl.jdbc.EmbedPreparedStatement30
|
||||
derby-em.subPreparedStatement=org.apache.derby.impl.jdbc.EmbedPreparedStatement40
|
||||
#derby-em.subPreparedStatement=org.apache.derby.impl.jdbc.EmbedPreparedStatement42
|
||||
derby-em.subPreparedStatement=org.apache.derby.iapi.jdbc.BrokeredPreparedStatement
|
||||
derby-em.subPreparedStatement=org.apache.derby.iapi.jdbc.BrokeredPreparedStatement40
|
||||
#derby-em.subPreparedStatement=org.apache.derby.iapi.jdbc.BrokeredPreparedStatement42
|
||||
derby-em.subPreparedStatement=org.apache.derby.client.am.PreparedStatement
|
||||
derby-em.subPreparedStatement=org.apache.derby.client.am.PreparedStatement40
|
||||
#derby-em.subPreparedStatement=org.apache.derby.client.am.PreparedStatement42
|
||||
|
||||
derby-em.subCallableStatement=org.apache.derby.impl.jdbc.EmbedCallableStatement
|
||||
derby-em.subCallableStatement=org.apache.derby.impl.jdbc.EmbedCallableStatement20
|
||||
derby-em.subCallableStatement=org.apache.derby.impl.jdbc.EmbedCallableStatement30
|
||||
derby-em.subCallableStatement=org.apache.derby.impl.jdbc.EmbedCallableStatement40
|
||||
#derby-em.subCallableStatement=org.apache.derby.impl.jdbc.EmbedCallableStatement42
|
||||
derby-em.subCallableStatement=org.apache.derby.iapi.jdbc.BrokeredCallableStatement
|
||||
derby-em.subCallableStatement=org.apache.derby.iapi.jdbc.BrokeredCallableStatement40
|
||||
#derby-em.subCallableStatement=org.apache.derby.iapi.jdbc.BrokeredCallableStatement42
|
||||
derby-em.subCallableStatement=org.apache.derby.client.am.CallableStatement
|
||||
derby-em.subCallableStatement=org.apache.derby.client.am.CallableStatement40
|
||||
#derby-em.subCallableStatement=org.apache.derby.client.am.CallableStatement42
|
||||
|
||||
|
||||
# ------ PostgreSQL v9.2-1003.jdbc4 ----------------------------------------------
|
||||
#
|
||||
org.postgresql.ds.PGSimpleDataSource=pgsql
|
||||
|
||||
pgsql.baseConnection=org.postgresql.jdbc2.AbstractJdbc2Connection
|
||||
pgsql.subConnection=org.postgresql.jdbc3.AbstractJdbc3Connection
|
||||
pgsql.subConnection=org.postgresql.jdbc3g.AbstractJdbc3gConnection
|
||||
pgsql.subConnection=org.postgresql.jdbc4.AbstractJdbc4Connection
|
||||
pgsql.subConnection=org.postgresql.jdbc4.Jdbc4Connection
|
||||
|
||||
pgsql.basePreparedStatement=org.postgresql.jdbc2.AbstractJdbc2Statement
|
||||
|
||||
pgsql.subPreparedStatement=org.postgresql.jdbc3.AbstractJdbc3Statement
|
||||
pgsql.subPreparedStatement=org.postgresql.jdbc3g.AbstractJdbc3gStatement
|
||||
pgsql.subPreparedStatement=org.postgresql.jdbc4.AbstractJdbc4Statement
|
||||
pgsql.subPreparedStatement=org.postgresql.jdbc4.Jdbc4Statement
|
||||
pgsql.subPreparedStatement=org.postgresql.jdbc4.Jdbc4PreparedStatement
|
||||
|
||||
pgsql.subCallableStatement=org.postgresql.jdbc4.Jdbc4CallableStatement
|
||||
|
||||
pgsql.baseResultSet=org.postgresql.jdbc2.AbstractJdbc2ResultSet
|
||||
pgsql.subResultSet=org.postgresql.jdbc3.AbstractJdbc3ResultSet
|
||||
pgsql.subResultSet=org.postgresql.jdbc3g.AbstractJdbc3gResultSet
|
||||
pgsql.subResultSet=org.postgresql.jdbc4.AbstractJdbc4ResultSet
|
||||
pgsql.subResultSet=org.postgresql.jdbc4.Jdbc4ResultSet
|
||||
|
||||
|
||||
# ------ MySQL Connector/J v5.1.26 ----------------------------------------------
|
||||
#
|
||||
com.mysql.jdbc.jdbc2.optional.MysqlDataSource=mysql
|
||||
|
||||
mysql.baseConnection=com.mysql.jdbc.ConnectionImpl
|
||||
mysql.baseConnection=com.mysql.jdbc.ReplicationConnection
|
||||
mysql.baseConnection=com.mysql.jdbc.LoadBalancedMySQLConnection
|
||||
mysql.subConnection=com.mysql.jdbc.JDBC4Connection
|
||||
mysql.subConnection=com.mysql.jdbc.JDBC4LoadBalancedMySQLConnection
|
||||
|
||||
mysql.baseStatement=com.mysql.jdbc.StatementImpl
|
||||
|
||||
mysql.subPreparedStatement=com.mysql.jdbc.PreparedStatement
|
||||
mysql.subPreparedStatement=com.mysql.jdbc.ServerPreparedStatement
|
||||
mysql.subPreparedStatement=com.mysql.jdbc.JDBC4ServerPreparedStatement
|
||||
|
||||
mysql.subCallableStatement=com.mysql.jdbc.CallableStatement
|
||||
mysql.subCallableStatement=com.mysql.jdbc.JDBC4CallableStatement
|
||||
|
||||
mysql.baseResultSet=com.mysql.jdbc.ResultSetImpl
|
||||
mysql.subResultSet=com.mysql.jdbc.JDBC4ResultSet
|
||||
mysql.subResultSet=com.mysql.jdbc.UpdatableResultSet
|
||||
mysql.subResultSet=com.mysql.jdbc.JDBC4UpdatableResultSet
|
||||
|
||||
# ------ MariaDB JDBC v1.1.5 --------------------------------------------------
|
||||
#
|
||||
org.mariadb.jdbc.MySQLDataSource=maria
|
||||
|
||||
maria.baseConnection=org.mariadb.jdbc.MySQLConnection
|
||||
|
||||
maria.baseStatement=org.mariadb.jdbc.MySQLStatement
|
||||
|
||||
maria.subPreparedStatement=org.mariadb.jdbc.MySQLPreparedStatement
|
||||
|
||||
maria.baseCallableStatement=org.mariadb.jdbc.MySQLCallableStatement
|
||||
|
||||
maria.baseResultSet=org.mariadb.jdbc.MySQLResultSet
|
||||
|
||||
|
||||
# ------ JTDS v1.3.1 ----------------------------------------------------------
|
||||
#
|
||||
net.sourceforge.jtds.jdbcx.JtdsDataSource=jtds
|
||||
|
||||
jtds.baseConnection=net.sourceforge.jtds.jdbc.JtdsConnection
|
||||
jtds.baseConnection=net.sourceforge.jtds.jdbcx.proxy.ConnectionProxy
|
||||
|
||||
jtds.baseStatement=net.sourceforge.jtds.jdbc.JtdsStatement
|
||||
jtds.baseStatement=net.sourceforge.jtds.jdbcx.proxy.StatementProxy
|
||||
|
||||
jtds.subPreparedStatement=net.sourceforge.jtds.jdbc.JtdsPreparedStatement
|
||||
jtds.subPreparedStatement=net.sourceforge.jtds.jdbcx.proxy.PreparedStatementProxy
|
||||
|
||||
jtds.subCallableStatement=net.sourceforge.jtds.jdbc.JtdsCallableStatement
|
||||
jtds.subCallableStatement=net.sourceforge.jtds.jdbcx.proxy.CallableStatementProxy
|
||||
|
||||
jtds.baseResultSet=net.sourceforge.jtds.jdbc.JtdsResultSet
|
||||
jtds.subResultSet=net.sourceforge.jtds.jdbc.CachedResultSet
|
||||
jtds.subResultSet=net.sourceforge.jtds.jdbc.MSCursorResultSet
|
||||
|
||||
|
||||
# ------ Oracle v12.1.0.1 -----------------------------------------------------
|
||||
#
|
||||
oracle.jdbc.pool.OracleDataSource=oracle
|
||||
|
||||
oracle.baseConnection=oracle.jdbc.driver.OracleConnection
|
||||
oracle.subConnection=oracle.jdbc.driver.PhysicalConnection
|
||||
oracle.subConnection=oracle.jdbc.driver.T4CConnection
|
||||
|
||||
oracle.baseStatement=oracle.jdbc.driver.OracleStatement
|
||||
|
||||
oracle.subPreparedStatement=oracle.jdbc.driver.OraclePreparedStatement
|
||||
|
||||
oracle.subCallableStatement=oracle.jdbc.driver.OracleCallableStatement
|
||||
|
||||
oracle.baseResultSet=oracle.jdbc.driver.OracleResultSet
|
||||
oracle.subResultSet=oracle.jdbc.driver.ArrayDataResultSet
|
||||
oracle.subResultSet=oracle.jdbc.driver.GeneratedScrollableResultSet
|
||||
oracle.subResultSet=oracle.jdbc.driver.InsensitiveScrollableResultSet
|
||||
oracle.subResultSet=oracle.jdbc.driver.ForwardOnlyResultSet
|
||||
oracle.subResultSet=oracle.jdbc.driver.ArrayLocatorResultSet
|
||||
oracle.subResultSet=oracle.jdbc.driver.SensitiveScrollableResultSet
|
||||
oracle.subResultSet=oracle.jdbc.driver.OracleReturnResultSet
|
||||
oracle.subResultSet=oracle.jdbc.driver.GeneratedUpdatableResultSet
|
||||
oracle.subResultSet=oracle.jdbc.driver.UpdatableResultSet
|
||||
|
||||
|
||||
# ------ HikariCP Testing v0.0.0 ----------------------------------------------
|
||||
#
|
||||
com.zaxxer.hikari.mocks.StubDataSource=hikari
|
||||
|
||||
hikari.baseConnection=com.zaxxer.hikari.mocks.StubBaseConnection
|
||||
hikari.subConnection=com.zaxxer.hikari.mocks.StubConnection
|
||||
hikari.baseStatement=com.zaxxer.hikari.mocks.StubStatement
|
||||
hikari.subPreparedStatement=com.zaxxer.hikari.mocks.StubPreparedStatement
|
||||
hikari.baseResultSet=com.zaxxer.hikari.mocks.StubResultSet
|
||||
|
||||
com.zaxxer.hikari.performance.StubDataSource=hikari-perf
|
||||
|
||||
hikari-perf.baseConnection=com.zaxxer.hikari.performance.StubConnection
|
||||
hikari-perf.baseStatement=com.zaxxer.hikari.performance.StubStatement
|
||||
hikari-perf.subPreparedStatement=com.zaxxer.hikari.performance.StubPreparedStatement
|
||||
hikari-perf.baseResultSet=com.zaxxer.hikari.performance.StubResultSet
|
@ -1,151 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013, 2014 Brett Wooldridge
|
||||
*
|
||||
* Licensed 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 com.zaxxer.hikari;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.SortedMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.codahale.metrics.Histogram;
|
||||
import com.codahale.metrics.Metric;
|
||||
import com.codahale.metrics.MetricFilter;
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.codahale.metrics.Timer;
|
||||
import com.codahale.metrics.health.HealthCheck.Result;
|
||||
import com.codahale.metrics.health.HealthCheckRegistry;
|
||||
import com.zaxxer.hikari.util.UtilityElf;
|
||||
|
||||
/**
|
||||
* Test HikariCP/CodaHale metrics integration.
|
||||
*
|
||||
* @author Brett Wooldridge
|
||||
*/
|
||||
public class TestMetrics
|
||||
{
|
||||
@Test
|
||||
public void testMetricWait() throws SQLException
|
||||
{
|
||||
MetricRegistry metricRegistry = new MetricRegistry();
|
||||
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setMetricRegistry(metricRegistry);
|
||||
config.setInitializationFailFast(false);
|
||||
config.setPoolName("test");
|
||||
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
|
||||
|
||||
HikariDataSource ds = new HikariDataSource(config);
|
||||
try {
|
||||
ds.getConnection().close();
|
||||
|
||||
Timer timer = metricRegistry.getTimers(new MetricFilter() {
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean matches(String name, Metric metric)
|
||||
{
|
||||
return "test.pool.Wait".equals(MetricRegistry.name("test", "pool", "Wait"));
|
||||
}
|
||||
}).values().iterator().next();
|
||||
|
||||
Assert.assertEquals(1, timer.getCount());
|
||||
Assert.assertTrue(timer.getMeanRate() > 0.0);
|
||||
}
|
||||
finally {
|
||||
ds.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetricUsage() throws SQLException
|
||||
{
|
||||
MetricRegistry metricRegistry = new MetricRegistry();
|
||||
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setMetricRegistry(metricRegistry);
|
||||
config.setInitializationFailFast(false);
|
||||
config.setPoolName("test");
|
||||
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
|
||||
|
||||
HikariDataSource ds = new HikariDataSource(config);
|
||||
try {
|
||||
Connection connection = ds.getConnection();
|
||||
UtilityElf.quietlySleep(250L);
|
||||
connection.close();
|
||||
|
||||
Histogram histo = metricRegistry.getHistograms(new MetricFilter() {
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean matches(String name, Metric metric)
|
||||
{
|
||||
return "test.pool.Usage".equals(MetricRegistry.name("test", "pool", "Usage"));
|
||||
}
|
||||
}).values().iterator().next();
|
||||
|
||||
Assert.assertEquals(1, histo.getCount());
|
||||
double seventyFifth = histo.getSnapshot().get75thPercentile();
|
||||
Assert.assertTrue("Seventy-fith percentile less than 250ms: " + seventyFifth, seventyFifth >= 250.0);
|
||||
}
|
||||
finally {
|
||||
ds.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHealthChecks() throws Exception
|
||||
{
|
||||
MetricRegistry metricRegistry = new MetricRegistry();
|
||||
HealthCheckRegistry healthRegistry = new HealthCheckRegistry();
|
||||
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setMaximumPoolSize(10);
|
||||
config.setMetricRegistry(metricRegistry);
|
||||
config.setHealthCheckRegistry(healthRegistry);
|
||||
config.setPoolName("test");
|
||||
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
|
||||
config.addHealthCheckProperty("connectivityCheckTimeoutMs", "1000");
|
||||
config.addHealthCheckProperty("expected99thPercentileMs", "10");
|
||||
|
||||
HikariDataSource ds = new HikariDataSource(config);
|
||||
try {
|
||||
UtilityElf.quietlySleep(TimeUnit.SECONDS.toMillis(2));
|
||||
|
||||
Connection connection = ds.getConnection();
|
||||
connection.close();
|
||||
|
||||
connection = ds.getConnection();
|
||||
connection.close();
|
||||
|
||||
SortedMap<String, Result> healthChecks = healthRegistry.runHealthChecks();
|
||||
|
||||
Result connectivityResult = healthChecks.get("test.pool.ConnectivityCheck");
|
||||
Assert.assertTrue(connectivityResult.isHealthy());
|
||||
|
||||
Result slaResult = healthChecks.get("test.pool.Connection99Percent");
|
||||
Assert.assertTrue(slaResult.isHealthy());
|
||||
}
|
||||
finally {
|
||||
ds.close();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Brett Wooldridge
|
||||
*
|
||||
* Licensed 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 com.zaxxer.hikari.osgi;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.ops4j.pax.exam.Configuration;
|
||||
import org.ops4j.pax.exam.Option;
|
||||
import org.ops4j.pax.exam.junit.PaxExam;
|
||||
import org.osgi.framework.Bundle;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.ops4j.pax.exam.CoreOptions.*;
|
||||
|
||||
/**
|
||||
* @author lburgazzoli
|
||||
*/
|
||||
@RunWith(PaxExam.class)
|
||||
public class OSGiBundleTest
|
||||
{
|
||||
@Inject
|
||||
BundleContext context;
|
||||
|
||||
@Configuration
|
||||
public Option[] config()
|
||||
{
|
||||
return options(
|
||||
systemProperty("org.osgi.framework.storage.clean").value("true"),
|
||||
systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("WARN"),
|
||||
mavenBundle("org.slf4j","slf4j-api","1.7.5"),
|
||||
mavenBundle("org.slf4j","slf4j-simple","1.7.5").noStart(),
|
||||
mavenBundle("org.javassist", "javassist", "3.19.0-GA"),
|
||||
new File("target/classes").exists()
|
||||
? bundle("reference:file:target/classes")
|
||||
: bundle("reference:file:../target/classes"),
|
||||
junitBundles(),
|
||||
cleanCaches()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkInject()
|
||||
{
|
||||
assertNotNull(context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkBundle()
|
||||
{
|
||||
Boolean bundleFound = false;
|
||||
Boolean bundleActive = false;
|
||||
|
||||
Bundle[] bundles = context.getBundles();
|
||||
for(Bundle bundle : bundles)
|
||||
{
|
||||
if(bundle != null)
|
||||
{
|
||||
if(bundle.getSymbolicName().equals("com.zaxxer.HikariCP-java7"))
|
||||
{
|
||||
bundleFound = true;
|
||||
if(bundle.getState() == Bundle.ACTIVE)
|
||||
{
|
||||
bundleActive = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(bundleFound);
|
||||
assertTrue(bundleActive);
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
hibernate.hikari.minimumIdle=5
|
||||
hibernate.hikari.connectionTestQuery=SELECT 1
|
||||
hibernate.hikari.dataSourceClassName=com.zaxxer.hikari.mocks.StubDataSource
|
||||
hibernate.connection.autocommit=false
|
@ -1,4 +0,0 @@
|
||||
minimumIdle=5
|
||||
connectionTestQuery=SELECT 1
|
||||
autoCommit=false
|
||||
dataSourceClassName=com.zaxxer.hikari.mocks.StubDataSource
|
@ -1,5 +0,0 @@
|
||||
connectionTestQuery=SELECT 1
|
||||
autoCommit=false
|
||||
dataSourceClassName=com.zaxxer.hikari.mocks.StubDataSource
|
||||
dataSource.user=test
|
||||
dataSource.password=test
|
@ -1,6 +0,0 @@
|
||||
connectionTestQuery=SELECT 1
|
||||
autoCommit=false
|
||||
dataSourceClassName=com.zaxxer.hikari.mocks.StubDataSource
|
||||
dataSource.user=test
|
||||
dataSource.password=test
|
||||
dataSource.url=jdbc:stub:foo
|
@ -1,353 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<!-- For release: mvn release:perform -Darguments=-Dgpg.passphrase=PASSPHRASE -->
|
||||
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<packaging>bundle</packaging>
|
||||
|
||||
<name>HikariCP</name>
|
||||
<description>Ultimate JDBC Connection Pool</description>
|
||||
<url>https://github.com/brettwooldridge/HikariCP</url>
|
||||
|
||||
<organization>
|
||||
<name>Zaxxer.com</name>
|
||||
<url>https://github.com/brettwooldridge</url>
|
||||
</organization>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:git@github.com:brettwooldridge/HikariCP.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:brettwooldridge/HikariCP.git</developerConnection>
|
||||
<url>git@github.com:brettwooldridge/HikariCP.git</url>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The Apache Software License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Brett Wooldridge</name>
|
||||
<email>brett.wooldridge@gmail.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<felix.bundle.plugin.version>2.4.0</felix.bundle.plugin.version>
|
||||
<felix.version>4.2.1</felix.version>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP-parent</artifactId>
|
||||
<version>2.4.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src/main/java</sourceDirectory>
|
||||
<testSourceDirectory>src/test/java</testSourceDirectory>
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<!-- Sets the VM argument line used when unit tests are run. -->
|
||||
<argLine>${surefireArgLine}</argLine>
|
||||
<!-- Skips unit tests if the value of skip.unit.tests property is true -->
|
||||
<skipTests>${skip.unit.tests}</skipTests>
|
||||
<classpathDependencyExcludes>
|
||||
<classpathDependencyExclude>io.dropwizard.metrics:metrics-core</classpathDependencyExclude>
|
||||
<classpathDependencyExclude>io.dropwizard.metrics:metrics-healthchecks</classpathDependencyExclude>
|
||||
</classpathDependencyExcludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.7.2.201409121644</version>
|
||||
<executions>
|
||||
<!-- Prepares the property pointing to the JaCoCo runtime agent which is passed as VM argument when Maven the Surefire plugin is executed. -->
|
||||
<execution>
|
||||
<id>pre-unit-test</id>
|
||||
<goals>
|
||||
<goal>prepare-agent</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<!-- Sets the path to the file which contains the execution data. -->
|
||||
<destFile>${project.build.directory}/coverage-reports/jacoco.exec</destFile>
|
||||
<!-- Sets the name of the property containing the settings for JaCoCo runtime agent. -->
|
||||
<propertyName>surefireArgLine</propertyName>
|
||||
<excludes>
|
||||
<exclude>**/com/zaxxer/hikari/proxy/ProxyFactory</exclude>
|
||||
<exclude>**/com/zaxxer/hikari/proxy/ResultSetProxy</exclude>
|
||||
<exclude>**/com/zaxxer/hikari/proxy/StatementProxy</exclude>
|
||||
<exclude>**/com/zaxxer/hikari/proxy/CallableStatementProxy</exclude>
|
||||
<exclude>**/com/zaxxer/hikari/proxy/PreparedStatementProxy</exclude>
|
||||
<exclude>**/com/zaxxer/hikari/metrics/**</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</execution>
|
||||
<!-- Ensures that the code coverage report for unit tests is created after unit tests have been run. -->
|
||||
<execution>
|
||||
<id>post-unit-test</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>report</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<!-- Sets the path to the file which contains the execution data. -->
|
||||
<dataFile>${project.build.directory}/coverage-reports/jacoco.exec</dataFile>
|
||||
<!-- Sets the output directory for the code coverage report. -->
|
||||
<outputDirectory>${project.reporting.outputDirectory}/jacoco</outputDirectory>
|
||||
<excludes>
|
||||
<exclude>**/com/zaxxer/hikari/proxy/ProxyFactory.class</exclude>
|
||||
<exclude>**/com/zaxxer/hikari/proxy/ResultSetProxy.class</exclude>
|
||||
<exclude>**/com/zaxxer/hikari/proxy/StatementProxy.class</exclude>
|
||||
<exclude>**/com/zaxxer/hikari/proxy/CallableStatementProxy.class</exclude>
|
||||
<exclude>**/com/zaxxer/hikari/proxy/PreparedStatementProxy.class</exclude>
|
||||
<exclude>**/com/zaxxer/hikari/metrics/**</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<version>1.9.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>src</id>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>add-source</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>../hikaricp-common/src/main/java</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test</id>
|
||||
<phase>generate-test-sources</phase>
|
||||
<goals>
|
||||
<goal>add-test-source</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>../hikaricp-common/src/test/java</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test-resources</id>
|
||||
<phase>generate-test-resources</phase>
|
||||
<goals>
|
||||
<goal>add-test-resource</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>../hikaricp-common/src/test/resources</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<version>${felix.bundle.plugin.version}</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-Name>HikariCP</Bundle-Name>
|
||||
<Export-Package>
|
||||
com.zaxxer.hikari,
|
||||
com.zaxxer.hikari.hibernate
|
||||
</Export-Package>
|
||||
<Private-Package>com.zaxxer.hikari.*</Private-Package>
|
||||
<_exportcontents>
|
||||
com.zaxxer.hikari.pool,
|
||||
com.zaxxer.hikari.util,
|
||||
com.zaxxer.hikari.proxy
|
||||
</_exportcontents>
|
||||
<Import-Package>
|
||||
javassist.*,
|
||||
javax.management,
|
||||
javax.naming,
|
||||
javax.naming.spi,
|
||||
javax.sql,
|
||||
javax.sql.rowset,
|
||||
javax.sql.rowset.serial,
|
||||
javax.sql.rowset.spi,
|
||||
com.codahale.metrics;resolution:=optional,
|
||||
com.codahale.metrics.health;resolution:=optional,
|
||||
org.slf4j;version="[1.6,2)",
|
||||
org.hibernate;resolution:=optional,
|
||||
org.hibernate.cfg;resolution:=optional,
|
||||
org.hibernate.engine.jdbc.connections.spi;resolution:=optional,
|
||||
org.hibernate.service;resolution:=optional,
|
||||
org.hibernate.service.spi;resolution:=optional
|
||||
</Import-Package>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<DynamicImport-Package>*</DynamicImport-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
<executions>
|
||||
<!-- This execution makes sure that the manifest is available when the tests are executed -->
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<tagNameFormat>HikariCP-@{project.version}</tagNameFormat>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself. -->
|
||||
<plugin>
|
||||
<groupId>org.eclipse.m2e</groupId>
|
||||
<artifactId>lifecycle-mapping</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<configuration>
|
||||
<lifecycleMappingMetadata>
|
||||
<pluginExecutions>
|
||||
<pluginExecution>
|
||||
<pluginExecutionFilter>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>
|
||||
maven-bundle-plugin
|
||||
</artifactId>
|
||||
<versionRange>[2.4.0,)</versionRange>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</pluginExecutionFilter>
|
||||
<action>
|
||||
<ignore />
|
||||
</action>
|
||||
</pluginExecution>
|
||||
</pluginExecutions>
|
||||
</lifecycleMappingMetadata>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>coverage</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.eluder.coveralls</groupId>
|
||||
<artifactId>coveralls-maven-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>coveralls</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>jacoco</goal>
|
||||
</goals>
|
||||
<inherited>false</inherited>
|
||||
<configuration>
|
||||
<sourceDirectories>../hikaricp-common/src/main/java</sourceDirectories>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>release-sign-artifacts</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>performRelease</name>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>felix</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
<property>
|
||||
<name>pax.exam.framework</name>
|
||||
<value>felix</value>
|
||||
</property>
|
||||
</activation>
|
||||
<properties>
|
||||
<pax.exam.framework>felix</pax.exam.framework>
|
||||
<pax.exam.logging>none</pax.exam.logging>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>org.apache.felix.framework</artifactId>
|
||||
<version>${felix.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
@ -1,186 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013,2014 Brett Wooldridge
|
||||
*
|
||||
* Licensed 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 com.zaxxer.hikari.pool;
|
||||
|
||||
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_IN_USE;
|
||||
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_NOT_IN_USE;
|
||||
import static com.zaxxer.hikari.util.UtilityElf.quietlySleep;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.util.ConcurrentBag;
|
||||
import com.zaxxer.hikari.util.IBagStateListener;
|
||||
import com.zaxxer.hikari.util.Java8ConcurrentBag;
|
||||
|
||||
/**
|
||||
* This is the primary connection pool class that provides the basic
|
||||
* pooling behavior for HikariCP.
|
||||
*
|
||||
* @author Brett Wooldridge
|
||||
*/
|
||||
public final class HikariPool extends BaseHikariPool
|
||||
{
|
||||
/**
|
||||
* Construct a HikariPool with the specified configuration.
|
||||
*
|
||||
* @param configuration a HikariConfig instance
|
||||
*/
|
||||
public HikariPool(HikariConfig configuration)
|
||||
{
|
||||
this(configuration, configuration.getUsername(), configuration.getPassword());
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a HikariPool with the specified configuration.
|
||||
*
|
||||
* @param configuration a HikariConfig instance
|
||||
* @param username authentication username
|
||||
* @param password authentication password
|
||||
*/
|
||||
public HikariPool(HikariConfig configuration, String username, String password)
|
||||
{
|
||||
super(configuration, username, password);
|
||||
}
|
||||
|
||||
// ***********************************************************************
|
||||
// IBagStateListener callback
|
||||
// ***********************************************************************
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void addBagItem()
|
||||
{
|
||||
addConnectionExecutor.execute( () -> {
|
||||
long sleepBackoff = 200L;
|
||||
final int maxPoolSize = configuration.getMaximumPoolSize();
|
||||
while (poolState == POOL_RUNNING && totalConnections.get() < maxPoolSize && !addConnection()) {
|
||||
// If we got into the loop, addConnection() failed, so we sleep and retry
|
||||
quietlySleep(sleepBackoff);
|
||||
sleepBackoff = Math.min(connectionTimeout / 2, (long) ((double) sleepBackoff * 1.5));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ***********************************************************************
|
||||
// HikariPoolMBean methods
|
||||
// ***********************************************************************
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void softEvictConnections()
|
||||
{
|
||||
connectionBag.values(STATE_IN_USE).forEach(bagEntry -> bagEntry.evicted = true);
|
||||
connectionBag.values(STATE_NOT_IN_USE).stream().filter(p -> connectionBag.reserve(p)).forEach(bagEntry -> closeConnection(bagEntry));
|
||||
}
|
||||
|
||||
// ***********************************************************************
|
||||
// Protected methods
|
||||
// ***********************************************************************
|
||||
|
||||
/**
|
||||
* Permanently close the real (underlying) connection (eat any exception).
|
||||
*
|
||||
* @param connectionProxy the connection to actually close
|
||||
*/
|
||||
@Override
|
||||
protected void closeConnection(final PoolBagEntry bagEntry)
|
||||
{
|
||||
bagEntry.cancelMaxLifeTermination();
|
||||
if (connectionBag.remove(bagEntry)) {
|
||||
final int tc = totalConnections.decrementAndGet();
|
||||
if (tc < 0) {
|
||||
LOGGER.warn("Internal accounting inconsistency, totalConnections={}", tc, new Exception());
|
||||
}
|
||||
closeConnectionExecutor.execute(() -> { poolUtils.quietlyCloseConnection(bagEntry.connection); });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to abort() active connections on Java7+, or close() them on Java6.
|
||||
*
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Override
|
||||
protected void abortActiveConnections(final ExecutorService assassinExecutor) throws InterruptedException
|
||||
{
|
||||
connectionBag.values(STATE_IN_USE).stream().forEach(bagEntry -> {
|
||||
try {
|
||||
bagEntry.aborted = bagEntry.evicted = true;
|
||||
bagEntry.connection.abort(assassinExecutor);
|
||||
}
|
||||
catch (SQLException | NoSuchMethodError | AbstractMethodError e) {
|
||||
poolUtils.quietlyCloseConnection(bagEntry.connection);
|
||||
}
|
||||
finally {
|
||||
if (connectionBag.remove(bagEntry)) {
|
||||
totalConnections.decrementAndGet();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
protected Runnable getHouseKeeper()
|
||||
{
|
||||
return new HouseKeeper();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
protected ConcurrentBag<PoolBagEntry> createConcurrentBag(IBagStateListener listener)
|
||||
{
|
||||
return new Java8ConcurrentBag(listener);
|
||||
}
|
||||
|
||||
// ***********************************************************************
|
||||
// Non-anonymous Inner-classes
|
||||
// ***********************************************************************
|
||||
|
||||
/**
|
||||
* The house keeping task to retire idle connections.
|
||||
*/
|
||||
private class HouseKeeper implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
logPoolState("Before cleanup ");
|
||||
|
||||
connectionTimeout = configuration.getConnectionTimeout(); // refresh member in case it changed
|
||||
validationTimeout = configuration.getValidationTimeout(); // refresh member in case it changed
|
||||
|
||||
final long now = System.currentTimeMillis();
|
||||
final long idleTimeout = configuration.getIdleTimeout();
|
||||
|
||||
connectionBag.values(STATE_NOT_IN_USE).stream().filter(p -> connectionBag.reserve(p)).forEach(bagEntry -> {
|
||||
if (bagEntry.evicted || (idleTimeout > 0L && now > bagEntry.lastAccess + idleTimeout)) {
|
||||
closeConnection(bagEntry);
|
||||
}
|
||||
else {
|
||||
connectionBag.unreserve(bagEntry);
|
||||
}
|
||||
});
|
||||
|
||||
logPoolState("After cleanup ");
|
||||
|
||||
fillPool(); // Try to maintain minimum connections
|
||||
}
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013, 2014 Brett Wooldridge
|
||||
*
|
||||
* Licensed 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 com.zaxxer.hikari.util;
|
||||
|
||||
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_IN_USE;
|
||||
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_NOT_IN_USE;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.zaxxer.hikari.pool.PoolBagEntry;
|
||||
|
||||
/**
|
||||
* This is a specialized concurrent bag that achieves superior performance
|
||||
* to LinkedBlockingQueue and LinkedTransferQueue for the purposes of a
|
||||
* connection pool. It uses ThreadLocal storage when possible to avoid
|
||||
* locks, but resorts to scanning a common collection if there are no
|
||||
* available items in the ThreadLocal list. Not-in-use items in the
|
||||
* ThreadLocal lists can be "stolen" when the borrowing thread has none
|
||||
* of its own. It is a "lock-less" implementation using a specialized
|
||||
* AbstractQueuedLongSynchronizer to manage cross-thread signaling.
|
||||
*
|
||||
* Note that items that are "borrowed" from the bag are not actually
|
||||
* removed from any collection, so garbage collection will not occur
|
||||
* even if the reference is abandoned. Thus care must be taken to
|
||||
* "requite" borrowed objects otherwise a memory leak will result. Only
|
||||
* the "remove" method can completely remove an object from the bag.
|
||||
*
|
||||
* @author Brett Wooldridge
|
||||
*
|
||||
* @param <T> the templated type to store in the bag
|
||||
*/
|
||||
public final class Java8ConcurrentBag extends ConcurrentBag<PoolBagEntry>
|
||||
{
|
||||
/**
|
||||
* Construct a ConcurrentBag with the specified listener.
|
||||
*
|
||||
* @param listener the IBagStateListener to attach to this bag
|
||||
*/
|
||||
public Java8ConcurrentBag(IBagStateListener listener)
|
||||
{
|
||||
super(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method provides a "snaphot" in time of the BagEntry
|
||||
* items in the bag in the specified state. It does not "lock"
|
||||
* or reserve items in any way. Call <code>reserve(BagEntry)</code>
|
||||
* on items in list before performing any action on them.
|
||||
*
|
||||
* @param state one of STATE_NOT_IN_USE or STATE_IN_USE
|
||||
* @return a possibly empty list of objects having the state specified
|
||||
*/
|
||||
public List<PoolBagEntry> values(final int state)
|
||||
{
|
||||
if (state == STATE_IN_USE || state == STATE_NOT_IN_USE) {
|
||||
return sharedList.stream()
|
||||
.filter(reference -> reference.state.get() == state)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
return new ArrayList<PoolBagEntry>(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a count of the number of items in the specified state at the time of this call.
|
||||
*
|
||||
* @param state the state of the items to count
|
||||
* @return a count of how many items in the bag are in the specified state
|
||||
*/
|
||||
public int getCount(final int state)
|
||||
{
|
||||
return (int) sharedList.stream().filter(reference -> reference.state.get() == state).count();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue