commit removes

pull/295/head
Brett Wooldridge 10 years ago
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…
Cancel
Save