From c296127bab05957fa06026c56207a7de96f93454 Mon Sep 17 00:00:00 2001
From: Robin Bygrave
Date: Thu, 24 Mar 2016 14:29:21 +1300
Subject: [PATCH] #618 - Refactor - remove DataSourcePool implementation as
separate dependency
---
pom.xml | 18 +
.../avaje/ebean/config/DataSourceConfig.java | 556 ---------
.../com/avaje/ebean/config/ServerConfig.java | 5 +-
.../jdbc/ConnectionDelegator.java | 254 -----
.../jdbc/PreparedStatementDelegator.java | 435 -------
.../server/core/DefaultContainer.java | 37 +-
.../server/core/InternalConfiguration.java | 4 +-
.../server/lib/sql/BusyConnectionBuffer.java | 199 ----
.../server/lib/sql/DataSourceAlert.java | 27 -
.../server/lib/sql/DataSourcePool.java | 1003 -----------------
.../lib/sql/DataSourcePoolListener.java | 34 -
.../lib/sql/DataSourcePoolStatistics.java | 86 --
.../lib/sql/ExtendedPreparedStatement.java | 386 -------
.../server/lib/sql/ExtendedStatement.java | 327 ------
.../server/lib/sql/FreeConnectionBuffer.java | 106 --
.../server/lib/sql/PooledConnection.java | 970 ----------------
.../server/lib/sql/PooledConnectionQueue.java | 532 ---------
.../lib/sql/PooledConnectionStatistics.java | 160 ---
.../server/lib/sql/PstmtCache.java | 176 ---
.../server/lib/sql/SimpleDataSourceAlert.java | 106 --
.../server/lib/sql/TransactionIsolation.java | 38 -
.../server/lib/sql/message.properties | 20 -
.../ebeaninternal/server/lib/sql/package.html | 12 -
.../server/lib/util/MailAddress.java | 43 -
.../server/lib/util/MailEvent.java | 49 -
.../server/lib/util/MailListener.java | 13 -
.../server/lib/util/MailMessage.java | 153 ---
.../server/lib/util/MailSender.java | 206 ----
.../transaction/TransactionManager.java | 12 +-
.../server/lib/sql/TestBusyBuffer.java | 100 --
.../server/lib/sql/TestDataSourceMax.java | 131 ---
.../server/lib/sql/TestFreeBuffer.java | 74 --
.../server/lib/sql/TestFreeBufferTrim.java | 40 -
.../com/avaje/tests/basic/MainDbBoolean.java | 2 +-
.../basic/MyTestDataSourcePoolListener.java | 2 +-
.../transaction/TestAutoCommitDataSource.java | 13 +-
.../TestExplicitTransactionMode.java | 13 +-
.../avaje/tests/unitinternal/HelloMain.java | 2 +-
38 files changed, 69 insertions(+), 6275 deletions(-)
delete mode 100644 src/main/java/com/avaje/ebean/config/DataSourceConfig.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/jdbc/ConnectionDelegator.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/jdbc/PreparedStatementDelegator.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/sql/BusyConnectionBuffer.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourceAlert.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourcePool.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourcePoolListener.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourcePoolStatistics.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/sql/ExtendedPreparedStatement.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/sql/ExtendedStatement.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/sql/FreeConnectionBuffer.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnection.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnectionQueue.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnectionStatistics.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/sql/PstmtCache.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/sql/SimpleDataSourceAlert.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/sql/TransactionIsolation.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/sql/message.properties
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/sql/package.html
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/util/MailAddress.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/util/MailEvent.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/util/MailListener.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/util/MailMessage.java
delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/lib/util/MailSender.java
delete mode 100644 src/test/java/com/avaje/ebeaninternal/server/lib/sql/TestBusyBuffer.java
delete mode 100644 src/test/java/com/avaje/ebeaninternal/server/lib/sql/TestDataSourceMax.java
delete mode 100644 src/test/java/com/avaje/ebeaninternal/server/lib/sql/TestFreeBuffer.java
delete mode 100644 src/test/java/com/avaje/ebeaninternal/server/lib/sql/TestFreeBufferTrim.java
diff --git a/pom.xml b/pom.xml
index 456cd8079..cb4001070 100644
--- a/pom.xml
+++ b/pom.xml
@@ -55,6 +55,24 @@
1.0
+
+ org.avaje
+ avaje-datasource-api
+ 1.1
+
+
+
+ org.avaje
+ avaje-datasource
+ 1.1.1
+
+
+
+
+
+
+
+
org.slf4j
slf4j-api
diff --git a/src/main/java/com/avaje/ebean/config/DataSourceConfig.java b/src/main/java/com/avaje/ebean/config/DataSourceConfig.java
deleted file mode 100644
index 648138210..000000000
--- a/src/main/java/com/avaje/ebean/config/DataSourceConfig.java
+++ /dev/null
@@ -1,556 +0,0 @@
-package com.avaje.ebean.config;
-
-import java.sql.Connection;
-import java.util.Map;
-import java.util.Properties;
-
-import com.avaje.ebean.Transaction;
-import com.avaje.ebean.util.StringHelper;
-
-/**
- * Used to config a DataSource when using the internal Ebean DataSource
- * implementation.
- *
- * If a DataSource instance is already defined via
- * {@link ServerConfig#setDataSource(javax.sql.DataSource)} or defined as JNDI
- * dataSource via {@link ServerConfig#setDataSourceJndiName(String)} then those
- * will used and not this DataSourceConfig.
- *
- */
-public class DataSourceConfig {
-
- private String url;
-
- private String username;
-
- private String password;
-
- private String driver;
-
- private int minConnections = 2;
-
- private int maxConnections = 20;
-
- private int isolationLevel = Transaction.READ_COMMITTED;
-
- private boolean autoCommit;
-
- private String heartbeatSql;
-
- private int heartbeatFreqSecs = 30;
-
- private int heartbeatTimeoutSeconds = 3;
-
- private boolean captureStackTrace;
-
- private int maxStackTraceSize = 5;
-
- private int leakTimeMinutes = 30;
-
- private int maxInactiveTimeSecs = 720;
-
- private int maxAgeMinutes = 0;
-
- private int trimPoolFreqSecs = 59;
-
- private int pstmtCacheSize = 20;
-
- private int cstmtCacheSize = 20;
-
- private int waitTimeoutMillis = 1000;
-
- private String poolListener;
-
- private boolean offline;
-
- protected Map customProperties;
-
- /**
- * Return the connection URL.
- */
- public String getUrl() {
- return url;
- }
-
- /**
- * Set the connection URL.
- */
- public void setUrl(String url) {
- this.url = url;
- }
-
- /**
- * Return the database username.
- */
- public String getUsername() {
- return username;
- }
-
- /**
- * Set the database username.
- */
- public void setUsername(String username) {
- this.username = username;
- }
-
- /**
- * Return the database password.
- */
- public String getPassword() {
- return password;
- }
-
- /**
- * Set the database password.
- */
- public void setPassword(String password) {
- this.password = password;
- }
-
- /**
- * Return the database driver.
- */
- public String getDriver() {
- return driver;
- }
-
- /**
- * Set the database driver.
- */
- public void setDriver(String driver) {
- this.driver = driver;
- }
-
- /**
- * Return the transaction isolation level.
- */
- public int getIsolationLevel() {
- return isolationLevel;
- }
-
- /**
- * Set the transaction isolation level.
- */
- public void setIsolationLevel(int isolationLevel) {
- this.isolationLevel = isolationLevel;
- }
-
- /**
- * Return autoCommit setting.
- */
- public boolean isAutoCommit() {
- return autoCommit;
- }
-
- /**
- * Set to true to turn on autoCommit.
- */
- public void setAutoCommit(boolean autoCommit) {
- this.autoCommit = autoCommit;
- }
-
- /**
- * Return the minimum number of connections the pool should maintain.
- */
- public int getMinConnections() {
- return minConnections;
- }
-
- /**
- * Set the minimum number of connections the pool should maintain.
- */
- public void setMinConnections(int minConnections) {
- this.minConnections = minConnections;
- }
-
- /**
- * Return the maximum number of connections the pool can reach.
- */
- public int getMaxConnections() {
- return maxConnections;
- }
-
- /**
- * Set the maximum number of connections the pool can reach.
- */
- public void setMaxConnections(int maxConnections) {
- this.maxConnections = maxConnections;
- }
-
- /**
- * Return a SQL statement used to test the database is accessible.
- *
- * Note that if this is not set then it can get defaulted from the
- * DatabasePlatform.
- *
- */
- public String getHeartbeatSql() {
- return heartbeatSql;
- }
-
- /**
- * Set a SQL statement used to test the database is accessible.
- *
- * Note that if this is not set then it can get defaulted from the
- * DatabasePlatform.
- *
- */
- public void setHeartbeatSql(String heartbeatSql) {
- this.heartbeatSql = heartbeatSql;
- }
-
-
- /**
- * Return the heartbeat frequency in seconds.
- *
- * This is the expected frequency in which the DataSource should be checked to
- * make sure it is healthy and trim idle connections.
- *
- */
- public int getHeartbeatFreqSecs() {
- return heartbeatFreqSecs;
- }
-
- /**
- * Set the expected heartbeat frequency in seconds.
- */
- public void setHeartbeatFreqSecs(int heartbeatFreqSecs) {
- this.heartbeatFreqSecs = heartbeatFreqSecs;
- }
-
- /**
- * Return the heart beat timeout in seconds.
- */
- public int getHeartbeatTimeoutSeconds() {
- return heartbeatTimeoutSeconds;
- }
-
- /**
- * Set the heart beat timeout in seconds.
- */
- public void setHeartbeatTimeoutSeconds(int heartbeatTimeoutSeconds) {
- this.heartbeatTimeoutSeconds = heartbeatTimeoutSeconds;
- }
-
- /**
- * Return true if a stack trace should be captured when obtaining a connection
- * from the pool.
- *
- * This can be used to diagnose a suspected connection pool leak.
- *
- *
- * Obviously this has a performance overhead.
- *
- */
- public boolean isCaptureStackTrace() {
- return captureStackTrace;
- }
-
- /**
- * Set to true if a stack trace should be captured when obtaining a connection
- * from the pool.
- *
- * This can be used to diagnose a suspected connection pool leak.
- *
- *
- * Obviously this has a performance overhead.
- *
- */
- public void setCaptureStackTrace(boolean captureStackTrace) {
- this.captureStackTrace = captureStackTrace;
- }
-
- /**
- * Return the max size for reporting stack traces on busy connections.
- */
- public int getMaxStackTraceSize() {
- return maxStackTraceSize;
- }
-
- /**
- * Set the max size for reporting stack traces on busy connections.
- */
- public void setMaxStackTraceSize(int maxStackTraceSize) {
- this.maxStackTraceSize = maxStackTraceSize;
- }
-
- /**
- * Return the time in minutes after which a connection could be considered to
- * have leaked.
- */
- public int getLeakTimeMinutes() {
- return leakTimeMinutes;
- }
-
- /**
- * Set the time in minutes after which a connection could be considered to
- * have leaked.
- */
- public void setLeakTimeMinutes(int leakTimeMinutes) {
- this.leakTimeMinutes = leakTimeMinutes;
- }
-
- /**
- * Return the size of the PreparedStatement cache (per connection).
- */
- public int getPstmtCacheSize() {
- return pstmtCacheSize;
- }
-
- /**
- * Set the size of the PreparedStatement cache (per connection).
- */
- public void setPstmtCacheSize(int pstmtCacheSize) {
- this.pstmtCacheSize = pstmtCacheSize;
- }
-
- /**
- * Return the size of the CallableStatement cache (per connection).
- */
- public int getCstmtCacheSize() {
- return cstmtCacheSize;
- }
-
- /**
- * Set the size of the CallableStatement cache (per connection).
- */
- public void setCstmtCacheSize(int cstmtCacheSize) {
- this.cstmtCacheSize = cstmtCacheSize;
- }
-
- /**
- * Return the time in millis to wait for a connection before timing out once
- * the pool has reached its maximum size.
- */
- public int getWaitTimeoutMillis() {
- return waitTimeoutMillis;
- }
-
- /**
- * Set the time in millis to wait for a connection before timing out once the
- * pool has reached its maximum size.
- */
- public void setWaitTimeoutMillis(int waitTimeoutMillis) {
- this.waitTimeoutMillis = waitTimeoutMillis;
- }
-
- /**
- * Return the time in seconds a connection can be idle after which it can be
- * trimmed from the pool.
- *
- * This is so that the pool after a busy period can trend over time back
- * towards the minimum connections.
- *
- */
- public int getMaxInactiveTimeSecs() {
- return maxInactiveTimeSecs;
- }
-
- /**
- * Return the maximum age a connection is allowed to be before it is closed.
- *
- * This can be used to close really old connections.
- *
- */
- public int getMaxAgeMinutes() {
- return maxAgeMinutes;
- }
-
- /**
- * Set the maximum age a connection can be in minutes.
- */
- public void setMaxAgeMinutes(int maxAgeMinutes) {
- this.maxAgeMinutes = maxAgeMinutes;
- }
-
- /**
- * Set the time in seconds a connection can be idle after which it can be
- * trimmed from the pool.
- *
- * This is so that the pool after a busy period can trend over time back
- * towards the minimum connections.
- *
- */
- public void setMaxInactiveTimeSecs(int maxInactiveTimeSecs) {
- this.maxInactiveTimeSecs = maxInactiveTimeSecs;
- }
-
-
- /**
- * Return the minimum time gap between pool trim checks.
- *
- * This defaults to 59 seconds meaning that the pool trim check will run every
- * minute assuming the heart beat check runs every 30 seconds.
- *
- */
- public int getTrimPoolFreqSecs() {
- return trimPoolFreqSecs;
- }
-
- /**
- * Set the minimum trim gap between pool trim checks.
- */
- public void setTrimPoolFreqSecs(int trimPoolFreqSecs) {
- this.trimPoolFreqSecs = trimPoolFreqSecs;
- }
-
- /**
- * Return the pool listener.
- */
- public String getPoolListener() {
- return poolListener;
- }
-
- /**
- * Set a pool listener.
- */
- public void setPoolListener(String poolListener) {
- this.poolListener = poolListener;
- }
-
- /**
- * Return true if the DataSource should be left offline.
- *
- * This is to support DDL generation etc without having a real database.
- *
- */
- public boolean isOffline() {
- return offline;
- }
-
- /**
- * Set to true if the DataSource should be left offline.
- *
- * This is to support DDL generation etc without having a real database.
- *
- *
- * Note that you MUST specify the database platform name (oracle, postgres,
- * h2, mysql etc) using {@link ServerConfig#setDatabasePlatformName(String)}
- * when you do this.
- *
- */
- public void setOffline(boolean offline) {
- this.offline = offline;
- }
-
- /**
- * Return a map of custom properties for the jdbc driver connection.
- */
- public Map getCustomProperties() {
- return customProperties;
- }
-
- /**
- * Set custom properties for the jdbc driver connection.
- *
- * @param customProperties
- */
- public void setCustomProperties(Map customProperties) {
- this.customProperties = customProperties;
- }
-
- /**
- * Load the settings by reading the ebean.properties file.
- *
- * @param serverName name of the server
- */
- public void loadSettings(String serverName) {
- loadSettings(new PropertiesWrapper("datasource", serverName, PropertyMap.defaultProperties()));
- }
-
- /**
- * Load the settings from the properties supplied.
- *
- * You can use this when you have your own properties to use for configuration.
- *
- *
- * @param properties the properties to configure the datasource
- * @param serverName the name of the specific datasource (optional)
- */
- public void loadSettings(Properties properties, String serverName) {
- PropertiesWrapper dbProps = new PropertiesWrapper("datasource", serverName, properties);
- loadSettings(dbProps);
- }
-
- /**
- * Load the settings from the PropertiesWrapper.
- */
- public void loadSettings(PropertiesWrapper properties) {
-
- username = properties.get("username", username);
- password = properties.get("password", password);
- driver = properties.get("driver", properties.get("databaseDriver", driver));
- url = properties.get("url", properties.get("databaseUrl", url));
-
- autoCommit = properties.getBoolean("autoCommit", autoCommit);
- captureStackTrace = properties.getBoolean("captureStackTrace", captureStackTrace);
- maxStackTraceSize = properties.getInt("maxStackTraceSize", maxStackTraceSize);
- leakTimeMinutes = properties.getInt("leakTimeMinutes", leakTimeMinutes);
- maxInactiveTimeSecs = properties.getInt("maxInactiveTimeSecs", maxInactiveTimeSecs);
- trimPoolFreqSecs = properties.getInt("trimPoolFreqSecs", trimPoolFreqSecs);
- maxAgeMinutes = properties.getInt("maxAgeMinutes", maxAgeMinutes);
-
- minConnections = properties.getInt("minConnections", minConnections);
- maxConnections = properties.getInt("maxConnections", maxConnections);
- pstmtCacheSize = properties.getInt("pstmtCacheSize", pstmtCacheSize);
- cstmtCacheSize = properties.getInt("cstmtCacheSize", cstmtCacheSize);
-
- waitTimeoutMillis = properties.getInt("waitTimeout", waitTimeoutMillis);
-
- heartbeatSql = properties.get("heartbeatSql", heartbeatSql);
- heartbeatTimeoutSeconds = properties.getInt("heartbeatTimeoutSeconds", heartbeatTimeoutSeconds);
- poolListener = properties.get("poolListener", poolListener);
- offline = properties.getBoolean("offline", offline);
-
- String isoLevel = properties.get("isolationlevel", getTransactionIsolationLevel(isolationLevel));
- this.isolationLevel = getTransactionIsolationLevel(isoLevel);
-
- String customProperties = properties.get("customProperties", null);
- if (customProperties != null && customProperties.length() > 0) {
- this.customProperties = StringHelper.delimitedToMap(customProperties, ";", "=");
- }
-
- }
-
- /**
- * Return the isolation level description from the associated Connection int value.
- */
- public String getTransactionIsolationLevel(int level) {
- switch (level) {
- case Connection.TRANSACTION_NONE : return "NONE";
- case Connection.TRANSACTION_READ_COMMITTED : return "READ_COMMITTED";
- case Connection.TRANSACTION_READ_UNCOMMITTED : return "READ_UNCOMMITTED";
- case Connection.TRANSACTION_REPEATABLE_READ : return "REPEATABLE_READ";
- case Connection.TRANSACTION_SERIALIZABLE : return "SERIALIZABLE";
- default: throw new RuntimeException("Transaction Isolation level [" + level + "] is not known.");
- }
- }
-
- /**
- * Return the isolation level for a given string description.
- */
- public int getTransactionIsolationLevel(String level) {
- level = level.toUpperCase();
- if (level.startsWith("TRANSACTION")) {
- level = level.substring("TRANSACTION".length());
- }
- level = level.replace("_", "");
- if ("NONE".equalsIgnoreCase(level)) {
- return Connection.TRANSACTION_NONE;
- }
- if ("READCOMMITTED".equalsIgnoreCase(level)) {
- return Connection.TRANSACTION_READ_COMMITTED;
- }
- if ("READUNCOMMITTED".equalsIgnoreCase(level)) {
- return Connection.TRANSACTION_READ_UNCOMMITTED;
- }
- if ("REPEATABLEREAD".equalsIgnoreCase(level)) {
- return Connection.TRANSACTION_REPEATABLE_READ;
- }
- if ("SERIALIZABLE".equalsIgnoreCase(level)) {
- return Connection.TRANSACTION_SERIALIZABLE;
- }
-
- throw new RuntimeException("Transaction Isolation level [" + level + "] is not known.");
- }
-}
diff --git a/src/main/java/com/avaje/ebean/config/ServerConfig.java b/src/main/java/com/avaje/ebean/config/ServerConfig.java
index cd6e5e755..e51f81cfd 100644
--- a/src/main/java/com/avaje/ebean/config/ServerConfig.java
+++ b/src/main/java/com/avaje/ebean/config/ServerConfig.java
@@ -22,6 +22,7 @@ import com.avaje.ebean.event.readaudit.ReadAuditLogger;
import com.avaje.ebean.event.readaudit.ReadAuditPrepare;
import com.avaje.ebean.meta.MetaInfoManager;
import com.fasterxml.jackson.core.JsonFactory;
+import org.avaje.datasource.DataSourceConfig;
import javax.sql.DataSource;
import java.util.ArrayList;
@@ -1391,8 +1392,6 @@ public class ServerConfig {
*
* Values are oracle, h2, postgres, mysql, mssqlserver2005.
*
- *
- * @see DataSourceConfig#setOffline(boolean)
*/
public void setDatabasePlatformName(String databasePlatformName) {
this.databasePlatformName = databasePlatformName;
@@ -2246,7 +2245,7 @@ public class ServerConfig {
* @param p - The defined property source passed to load settings
*/
protected void loadDataSourceSettings(PropertiesWrapper p) {
- dataSourceConfig.loadSettings(p.withPrefix("datasource"));
+ dataSourceConfig.loadSettings(p.properties, name);
}
/**
diff --git a/src/main/java/com/avaje/ebeaninternal/jdbc/ConnectionDelegator.java b/src/main/java/com/avaje/ebeaninternal/jdbc/ConnectionDelegator.java
deleted file mode 100644
index 382728c2a..000000000
--- a/src/main/java/com/avaje/ebeaninternal/jdbc/ConnectionDelegator.java
+++ /dev/null
@@ -1,254 +0,0 @@
-package com.avaje.ebeaninternal.jdbc;
-
-import java.sql.Array;
-import java.sql.Blob;
-import java.sql.CallableStatement;
-import java.sql.Clob;
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-import java.sql.NClob;
-import java.sql.PreparedStatement;
-import java.sql.SQLClientInfoException;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-import java.sql.SQLXML;
-import java.sql.Savepoint;
-import java.sql.Statement;
-import java.sql.Struct;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.Executor;
-
-public class ConnectionDelegator implements Connection {
-
- private final Connection delegate;
-
- public ConnectionDelegator(Connection delegate) {
- this.delegate = delegate;
- }
-
- @Override
- public void setSchema(String schema) throws SQLException {
- delegate.setSchema(schema);
- }
-
- @Override
- public String getSchema() throws SQLException {
- return delegate.getSchema();
- }
-
- @Override
- public void abort(Executor executor) throws SQLException {
- delegate.abort(executor);
- }
-
- @Override
- public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
- delegate.setNetworkTimeout(executor, milliseconds);
- }
-
- @Override
- public int getNetworkTimeout() throws SQLException {
- return delegate.getNetworkTimeout();
- }
-
- public Statement createStatement() throws SQLException {
- return delegate.createStatement();
- }
-
- public PreparedStatement prepareStatement(String sql) throws SQLException {
- return delegate.prepareStatement(sql);
- }
-
- public CallableStatement prepareCall(String sql) throws SQLException {
- return delegate.prepareCall(sql);
- }
-
- public String nativeSQL(String sql) throws SQLException {
- return delegate.nativeSQL(sql);
- }
-
- public void setAutoCommit(boolean autoCommit) throws SQLException {
- delegate.setAutoCommit(autoCommit);
- }
-
- public boolean getAutoCommit() throws SQLException {
- return delegate.getAutoCommit();
- }
-
- public void commit() throws SQLException {
- delegate.commit();
- }
-
- public void rollback() throws SQLException {
- delegate.rollback();
- }
-
- public void close() throws SQLException {
- delegate.close();
- }
-
- public boolean isClosed() throws SQLException {
- return delegate.isClosed();
- }
-
- public DatabaseMetaData getMetaData() throws SQLException {
- return delegate.getMetaData();
- }
-
- public void setReadOnly(boolean readOnly) throws SQLException {
- delegate.setReadOnly(readOnly);
- }
-
- public boolean isReadOnly() throws SQLException {
- return delegate.isReadOnly();
- }
-
- public void setCatalog(String catalog) throws SQLException {
- delegate.setCatalog(catalog);
- }
-
- public String getCatalog() throws SQLException {
- return delegate.getCatalog();
- }
-
- public void setTransactionIsolation(int level) throws SQLException {
- delegate.setTransactionIsolation(level);
- }
-
- public int getTransactionIsolation() throws SQLException {
- return delegate.getTransactionIsolation();
- }
-
- public SQLWarning getWarnings() throws SQLException {
- return delegate.getWarnings();
- }
-
- public void clearWarnings() throws SQLException {
- delegate.clearWarnings();
- }
-
- public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
- return delegate.createStatement(resultSetType, resultSetConcurrency);
- }
-
- public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
- throws SQLException {
- return delegate.prepareStatement(sql, resultSetType, resultSetConcurrency);
- }
-
- public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency)
- throws SQLException {
- return delegate.prepareCall(sql, resultSetType, resultSetConcurrency);
- }
-
- public Map> getTypeMap() throws SQLException {
- return delegate.getTypeMap();
- }
-
- public void setTypeMap(Map> map) throws SQLException {
- delegate.setTypeMap(map);
- }
-
- public void setHoldability(int holdability) throws SQLException {
- delegate.setHoldability(holdability);
- }
-
- public int getHoldability() throws SQLException {
- return delegate.getHoldability();
- }
-
- public Savepoint setSavepoint() throws SQLException {
- return delegate.setSavepoint();
- }
-
- public Savepoint setSavepoint(String name) throws SQLException {
- return delegate.setSavepoint(name);
- }
-
- public void rollback(Savepoint savepoint) throws SQLException {
- delegate.rollback(savepoint);
- }
-
- public void releaseSavepoint(Savepoint savepoint) throws SQLException {
- delegate.releaseSavepoint(savepoint);
- }
-
- public Statement createStatement(int resultSetType, int resultSetConcurrency,
- int resultSetHoldability) throws SQLException {
- return delegate.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
- }
-
- public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
- return delegate.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
- }
-
- public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
- int resultSetHoldability) throws SQLException {
- return delegate.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
- }
-
- public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
- return delegate.prepareStatement(sql, autoGeneratedKeys);
- }
-
- public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
- return delegate.prepareStatement(sql, columnIndexes);
- }
-
- public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
- return delegate.prepareStatement(sql, columnNames);
- }
-
- public Clob createClob() throws SQLException {
- return delegate.createClob();
- }
-
- public Blob createBlob() throws SQLException {
- return delegate.createBlob();
- }
-
- public NClob createNClob() throws SQLException {
- return delegate.createNClob();
- }
-
- public SQLXML createSQLXML() throws SQLException {
- return delegate.createSQLXML();
- }
-
- public boolean isValid(int timeout) throws SQLException {
- return delegate.isValid(timeout);
- }
-
- public void setClientInfo(String name, String value) throws SQLClientInfoException {
- delegate.setClientInfo(name, value);
- }
-
- public void setClientInfo(Properties properties) throws SQLClientInfoException {
- delegate.setClientInfo(properties);
- }
-
- public String getClientInfo(String name) throws SQLException {
- return delegate.getClientInfo(name);
- }
-
- public Properties getClientInfo() throws SQLException {
- return delegate.getClientInfo();
- }
-
- public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
- return delegate.createArrayOf(typeName, elements);
- }
-
- public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
- return delegate.createStruct(typeName, attributes);
- }
-
- public T unwrap(Class iface) throws SQLException {
- return delegate.unwrap(iface);
- }
-
- public boolean isWrapperFor(Class> iface) throws SQLException {
- return delegate.isWrapperFor(iface);
- }
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/jdbc/PreparedStatementDelegator.java b/src/main/java/com/avaje/ebeaninternal/jdbc/PreparedStatementDelegator.java
deleted file mode 100644
index 47295e583..000000000
--- a/src/main/java/com/avaje/ebeaninternal/jdbc/PreparedStatementDelegator.java
+++ /dev/null
@@ -1,435 +0,0 @@
-package com.avaje.ebeaninternal.jdbc;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URL;
-import java.sql.Array;
-import java.sql.Blob;
-import java.sql.Clob;
-import java.sql.Connection;
-import java.sql.Date;
-import java.sql.NClob;
-import java.sql.ParameterMetaData;
-import java.sql.PreparedStatement;
-import java.sql.Ref;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.RowId;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-import java.sql.SQLXML;
-import java.sql.Time;
-import java.sql.Timestamp;
-import java.util.Calendar;
-
-public class PreparedStatementDelegator implements PreparedStatement {
-
- private final PreparedStatement delegate;
-
- public PreparedStatementDelegator(PreparedStatement delegate) {
- this.delegate = delegate;
- }
-
- @Override
- public void closeOnCompletion() throws SQLException {
- delegate.closeOnCompletion();
- }
-
- @Override
- public boolean isCloseOnCompletion() throws SQLException {
- return delegate.isCloseOnCompletion();
- }
-
- public ResultSet executeQuery() throws SQLException {
- return delegate.executeQuery();
- }
-
- public int executeUpdate() throws SQLException {
- return delegate.executeUpdate();
- }
-
- public void setNull(int parameterIndex, int sqlType) throws SQLException {
- delegate.setNull(parameterIndex, sqlType);
- }
-
- public void setBoolean(int parameterIndex, boolean x) throws SQLException {
- delegate.setBoolean(parameterIndex, x);
- }
-
- public void setByte(int parameterIndex, byte x) throws SQLException {
- delegate.setByte(parameterIndex, x);
- }
-
- public void setShort(int parameterIndex, short x) throws SQLException {
- delegate.setShort(parameterIndex, x);
- }
-
- public void setInt(int parameterIndex, int x) throws SQLException {
- delegate.setInt(parameterIndex, x);
- }
-
- public void setLong(int parameterIndex, long x) throws SQLException {
- delegate.setLong(parameterIndex, x);
- }
-
- public void setFloat(int parameterIndex, float x) throws SQLException {
- delegate.setFloat(parameterIndex, x);
- }
-
- public void setDouble(int parameterIndex, double x) throws SQLException {
- delegate.setDouble(parameterIndex, x);
- }
-
- public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
- delegate.setBigDecimal(parameterIndex, x);
- }
-
- public void setString(int parameterIndex, String x) throws SQLException {
- delegate.setString(parameterIndex, x);
- }
-
- public void setBytes(int parameterIndex, byte[] x) throws SQLException {
- delegate.setBytes(parameterIndex, x);
- }
-
- public void setDate(int parameterIndex, Date x) throws SQLException {
- delegate.setDate(parameterIndex, x);
- }
-
- public void setTime(int parameterIndex, Time x) throws SQLException {
- delegate.setTime(parameterIndex, x);
- }
-
- public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
- delegate.setTimestamp(parameterIndex, x);
- }
-
- public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {
- delegate.setAsciiStream(parameterIndex, x, length);
- }
-
- @SuppressWarnings("deprecation")
- public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {
- delegate.setUnicodeStream(parameterIndex, x, length);
- }
-
- public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {
- delegate.setBinaryStream(parameterIndex, x, length);
- }
-
- public void clearParameters() throws SQLException {
- delegate.clearParameters();
- }
-
- public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
- delegate.setObject(parameterIndex, x, targetSqlType);
- }
-
- public void setObject(int parameterIndex, Object x) throws SQLException {
- delegate.setObject(parameterIndex, x);
- }
-
- public boolean execute() throws SQLException {
- return delegate.execute();
- }
-
- public void addBatch() throws SQLException {
- delegate.addBatch();
- }
-
- public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException {
- delegate.setCharacterStream(parameterIndex, reader, length);
- }
-
- public void setRef(int parameterIndex, Ref x) throws SQLException {
- delegate.setRef(parameterIndex, x);
- }
-
- public void setBlob(int parameterIndex, Blob x) throws SQLException {
- delegate.setBlob(parameterIndex, x);
- }
-
- public void setClob(int parameterIndex, Clob x) throws SQLException {
- delegate.setClob(parameterIndex, x);
- }
-
- public void setArray(int parameterIndex, Array x) throws SQLException {
- delegate.setArray(parameterIndex, x);
- }
-
- public ResultSetMetaData getMetaData() throws SQLException {
- return delegate.getMetaData();
- }
-
- public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {
- delegate.setDate(parameterIndex, x, cal);
- }
-
- public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
- delegate.setTime(parameterIndex, x, cal);
- }
-
- public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
- delegate.setTimestamp(parameterIndex, x, cal);
- }
-
- public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {
- delegate.setNull(parameterIndex, sqlType, typeName);
- }
-
- public void setURL(int parameterIndex, URL x) throws SQLException {
- delegate.setURL(parameterIndex, x);
- }
-
- public ParameterMetaData getParameterMetaData() throws SQLException {
- return delegate.getParameterMetaData();
- }
-
- public void setRowId(int parameterIndex, RowId x) throws SQLException {
- delegate.setRowId(parameterIndex, x);
- }
-
- public void setNString(int parameterIndex, String value) throws SQLException {
- delegate.setNString(parameterIndex, value);
- }
-
- public void setNCharacterStream(int parameterIndex, Reader value, long length)
- throws SQLException {
- delegate.setNCharacterStream(parameterIndex, value, length);
- }
-
- public void setNClob(int parameterIndex, NClob value) throws SQLException {
- delegate.setNClob(parameterIndex, value);
- }
-
- public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
- delegate.setClob(parameterIndex, reader, length);
- }
-
- public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException {
- delegate.setBlob(parameterIndex, inputStream, length);
- }
-
- public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {
- delegate.setNClob(parameterIndex, reader, length);
- }
-
- public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
- delegate.setSQLXML(parameterIndex, xmlObject);
- }
-
- public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength)
- throws SQLException {
- delegate.setObject(parameterIndex, x, targetSqlType, scaleOrLength);
- }
-
- public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {
- delegate.setAsciiStream(parameterIndex, x, length);
- }
-
- public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {
- delegate.setBinaryStream(parameterIndex, x, length);
- }
-
- public void setCharacterStream(int parameterIndex, Reader reader, long length)
- throws SQLException {
- delegate.setCharacterStream(parameterIndex, reader, length);
- }
-
- public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
- delegate.setAsciiStream(parameterIndex, x);
- }
-
- public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
- delegate.setBinaryStream(parameterIndex, x);
- }
-
- public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
- delegate.setCharacterStream(parameterIndex, reader);
- }
-
- public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
- delegate.setNCharacterStream(parameterIndex, value);
- }
-
- public void setClob(int parameterIndex, Reader reader) throws SQLException {
- delegate.setClob(parameterIndex, reader);
- }
-
- public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
- delegate.setBlob(parameterIndex, inputStream);
- }
-
- public void setNClob(int parameterIndex, Reader reader) throws SQLException {
- delegate.setNClob(parameterIndex, reader);
- }
-
- public ResultSet executeQuery(String sql) throws SQLException {
- return delegate.executeQuery(sql);
- }
-
- public int executeUpdate(String sql) throws SQLException {
- return delegate.executeUpdate(sql);
- }
-
- public void close() throws SQLException {
- delegate.close();
- }
-
- public int getMaxFieldSize() throws SQLException {
- return delegate.getMaxFieldSize();
- }
-
- public void setMaxFieldSize(int max) throws SQLException {
- delegate.setMaxFieldSize(max);
- }
-
- public int getMaxRows() throws SQLException {
- return delegate.getMaxRows();
- }
-
- public void setMaxRows(int max) throws SQLException {
- delegate.setMaxRows(max);
- }
-
- public void setEscapeProcessing(boolean enable) throws SQLException {
- delegate.setEscapeProcessing(enable);
- }
-
- public int getQueryTimeout() throws SQLException {
- return delegate.getQueryTimeout();
- }
-
- public void setQueryTimeout(int seconds) throws SQLException {
- delegate.setQueryTimeout(seconds);
- }
-
- public void cancel() throws SQLException {
- delegate.cancel();
- }
-
- public SQLWarning getWarnings() throws SQLException {
- return delegate.getWarnings();
- }
-
- public void clearWarnings() throws SQLException {
- delegate.clearWarnings();
- }
-
- public void setCursorName(String name) throws SQLException {
- delegate.setCursorName(name);
- }
-
- public boolean execute(String sql) throws SQLException {
- return delegate.execute(sql);
- }
-
- public ResultSet getResultSet() throws SQLException {
- return delegate.getResultSet();
- }
-
- public int getUpdateCount() throws SQLException {
- return delegate.getUpdateCount();
- }
-
- public boolean getMoreResults() throws SQLException {
- return delegate.getMoreResults();
- }
-
- public void setFetchDirection(int direction) throws SQLException {
- delegate.setFetchDirection(direction);
- }
-
- public int getFetchDirection() throws SQLException {
- return delegate.getFetchDirection();
- }
-
- public void setFetchSize(int rows) throws SQLException {
- delegate.setFetchSize(rows);
- }
-
- public int getFetchSize() throws SQLException {
- return delegate.getFetchSize();
- }
-
- public int getResultSetConcurrency() throws SQLException {
- return delegate.getResultSetConcurrency();
- }
-
- public int getResultSetType() throws SQLException {
- return delegate.getResultSetType();
- }
-
- public void addBatch(String sql) throws SQLException {
- delegate.addBatch(sql);
- }
-
- public void clearBatch() throws SQLException {
- delegate.clearBatch();
- }
-
- public int[] executeBatch() throws SQLException {
- return delegate.executeBatch();
- }
-
- public Connection getConnection() throws SQLException {
- return delegate.getConnection();
- }
-
- public boolean getMoreResults(int current) throws SQLException {
- return delegate.getMoreResults(current);
- }
-
- public ResultSet getGeneratedKeys() throws SQLException {
- return delegate.getGeneratedKeys();
- }
-
- public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
- return delegate.executeUpdate(sql, autoGeneratedKeys);
- }
-
- public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
- return delegate.executeUpdate(sql, columnIndexes);
- }
-
- public int executeUpdate(String sql, String[] columnNames) throws SQLException {
- return delegate.executeUpdate(sql, columnNames);
- }
-
- public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
- return delegate.execute(sql, autoGeneratedKeys);
- }
-
- public boolean execute(String sql, int[] columnIndexes) throws SQLException {
- return delegate.execute(sql, columnIndexes);
- }
-
- public boolean execute(String sql, String[] columnNames) throws SQLException {
- return delegate.execute(sql, columnNames);
- }
-
- public int getResultSetHoldability() throws SQLException {
- return delegate.getResultSetHoldability();
- }
-
- public boolean isClosed() throws SQLException {
- return delegate.isClosed();
- }
-
- public void setPoolable(boolean poolable) throws SQLException {
- delegate.setPoolable(poolable);
- }
-
- public boolean isPoolable() throws SQLException {
- return delegate.isPoolable();
- }
-
- public T unwrap(Class iface) throws SQLException {
- return delegate.unwrap(iface);
- }
-
- public boolean isWrapperFor(Class> iface) throws SQLException {
- return delegate.isWrapperFor(iface);
- }
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultContainer.java b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultContainer.java
index 57e38a5e3..90a9b7c7f 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultContainer.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultContainer.java
@@ -6,7 +6,6 @@ import com.avaje.ebean.cache.ServerCacheManager;
import com.avaje.ebean.cache.ServerCacheOptions;
import com.avaje.ebean.common.SpiContainer;
import com.avaje.ebean.config.ContainerConfig;
-import com.avaje.ebean.config.DataSourceConfig;
import com.avaje.ebean.config.PropertyMap;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.config.UnderscoreNamingConvention;
@@ -18,10 +17,10 @@ import com.avaje.ebeaninternal.server.cache.DefaultServerCacheFactory;
import com.avaje.ebeaninternal.server.cache.DefaultServerCacheManager;
import com.avaje.ebeaninternal.server.cluster.ClusterManager;
import com.avaje.ebeaninternal.server.lib.ShutdownManager;
-import com.avaje.ebeaninternal.server.lib.sql.DataSourceAlert;
-import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool;
-import com.avaje.ebeaninternal.server.lib.sql.DataSourcePoolListener;
-import com.avaje.ebeaninternal.server.lib.sql.SimpleDataSourceAlert;
+import org.avaje.datasource.DataSourceAlertFactory;
+import org.avaje.datasource.DataSourceConfig;
+import org.avaje.datasource.DataSourceFactory;
+import org.avaje.datasource.DataSourcePoolListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -295,18 +294,32 @@ public class DefaultContainer implements SpiContainer {
return null;
}
- DataSourceAlert notify = new SimpleDataSourceAlert();
- DataSourcePoolListener listener = createListener(config, dsConfig);
+ DataSourceFactory factory = config.service(DataSourceFactory.class);
+ if (factory == null) {
+ throw new IllegalStateException("No DataSourceFactory service implementation found in class path."
+ + " Probably missing dependency to avaje-datasource?");
+ }
- return new DataSourcePool(notify, config.getName(), dsConfig, listener);
+ DataSourceAlertFactory alertFactory = config.service(DataSourceAlertFactory.class);
+ if (alertFactory != null) {
+ dsConfig.setAlert(alertFactory.createAlert());
+ }
+
+ attachListener(config, dsConfig);
+
+ return factory.createPool(config.getName(), dsConfig);
}
/**
- * Create and return a DataSourcePoolListener if it has been specified.
+ * Create and attach a DataSourcePoolListener if it has been specified via properties and there is not one already attached.
*/
- private DataSourcePoolListener createListener(ServerConfig config, DataSourceConfig dsConfig) {
- String poolListener = dsConfig.getPoolListener();
- return poolListener != null ? (DataSourcePoolListener) config.getClassLoadConfig().newInstance(poolListener) : null;
+ private void attachListener(ServerConfig config, DataSourceConfig dsConfig) {
+ if (dsConfig.getListener() == null) {
+ String poolListener = dsConfig.getPoolListener();
+ if (poolListener != null) {
+ dsConfig.setListener((DataSourcePoolListener)config.getClassLoadConfig().newInstance(poolListener));
+ }
+ }
}
/**
diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/InternalConfiguration.java b/src/main/java/com/avaje/ebeaninternal/server/core/InternalConfiguration.java
index e0e56ef3c..7a792ea43 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/InternalConfiguration.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/InternalConfiguration.java
@@ -29,7 +29,7 @@ import com.avaje.ebeaninternal.server.deploy.parse.DeployCreateProperties;
import com.avaje.ebeaninternal.server.deploy.parse.DeployInherit;
import com.avaje.ebeaninternal.server.deploy.parse.DeployUtil;
import com.avaje.ebeaninternal.server.expression.DefaultExpressionFactory;
-import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool;
+import org.avaje.datasource.DataSourcePool;
import com.avaje.ebeaninternal.server.persist.Binder;
import com.avaje.ebeaninternal.server.persist.DefaultPersister;
import com.avaje.ebeaninternal.server.query.CQueryEngine;
@@ -361,7 +361,7 @@ public class InternalConfiguration {
return true;
}
DataSource dataSource = serverConfig.getDataSource();
- return dataSource instanceof DataSourcePool && ((DataSourcePool) dataSource).getAutoCommit();
+ return dataSource instanceof DataSourcePool && ((DataSourcePool) dataSource).isAutoCommit();
}
/**
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/BusyConnectionBuffer.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/BusyConnectionBuffer.java
deleted file mode 100644
index 807377612..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/BusyConnectionBuffer.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-import java.util.Arrays;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.avaje.ebeaninternal.server.lib.sql.PooledConnectionStatistics.LoadValues;
-
-/**
- * A buffer especially designed for Busy PooledConnections.
- *
- * All thread safety controlled externally (by PooledConnectionQueue).
- *
- *
- * It has a set of 'slots' and PooledConnections know which slot they went into
- * and this allows for fast addition and removal (by slotId without looping).
- * The capacity will increase on demand by the 'growBy' amount.
- *
- *
- * @author rbygrave
- */
-class BusyConnectionBuffer {
-
- private static final Logger logger = LoggerFactory.getLogger(BusyConnectionBuffer.class);
-
- private PooledConnection[] slots;
-
- private final int growBy;
-
- private int size;
-
- private int pos = -1;
-
- /**
- * Create the buffer with an initial capacity and fixed growBy.
- * We generally do not want the buffer to grow very often.
- *
- * @param capacity the initial capacity
- * @param growBy the fixed amount to grow the buffer by.
- */
- protected BusyConnectionBuffer(int capacity, int growBy) {
- this.slots = new PooledConnection[capacity];
- this.growBy = growBy;
- }
-
- /**
- * We can only grow (not shrink) the capacity.
- */
- protected void setCapacity(int newCapacity) {
- if (newCapacity > slots.length) {
- PooledConnection[] current = this.slots;
- this.slots = new PooledConnection[newCapacity];
- System.arraycopy(current, 0, this.slots, 0, current.length);
- }
- }
-
- public String toString() {
- return Arrays.toString(slots);
- }
-
- protected int getCapacity() {
- return slots.length;
- }
-
- protected int size() {
- return size;
- }
-
- protected boolean isEmpty() {
- return size == 0;
- }
-
- protected int add(PooledConnection pc) {
- if (size == slots.length) {
- // grow the capacity
- setCapacity(slots.length + growBy);
- }
- int slot = nextEmptySlot();
- pc.setSlotId(slot);
- slots[slot] = pc;
- return ++size;
- }
-
- protected boolean remove(PooledConnection pc) {
-
- int slotId = pc.getSlotId();
- if (slots[slotId] != pc) {
- PooledConnection heldBy = slots[slotId];
- logger.warn("Failed to remove from slot[{}] PooledConnection[{}] - HeldBy[{}]", pc.getSlotId(), pc, heldBy);
- return false;
- }
- slots[slotId] = null;
- --size;
- return true;
- }
-
- /**
- * Collect the load statistics from all the busy connections.
- */
- void collectStatistics(LoadValues values, boolean reset) {
-
- for (int i = 0; i < slots.length; i++) {
- if (slots[i] != null) {
- values.plus(slots[i].getStatistics().getValues(reset));
- }
- }
- }
-
- /**
- * Close connections that should be considered leaked.
- */
- void closeBusyConnections(long leakTimeMinutes) {
-
- long olderThanTime = System.currentTimeMillis() - (leakTimeMinutes * 60000);
-
- logger.debug("Closing busy connections using leakTimeMinutes {}", leakTimeMinutes);
-
- for (int i = 0; i < slots.length; i++) {
- if (slots[i] != null) {
- //tmp.add(slots[i]);
- PooledConnection pc = slots[i];
- //noinspection StatementWithEmptyBody
- if (pc.isLongRunning() || pc.getLastUsedTime() > olderThanTime) {
- // PooledConnection has been used recently or
- // expected to be longRunning so not closing...
- } else {
- slots[i] = null;
- --size;
- closeBusyConnection(pc);
- }
- }
- }
- }
-
- private void closeBusyConnection(PooledConnection pc) {
- try {
-
- logger.warn("DataSourcePool closing busy connection? " + pc.getFullDescription());
- System.out.println("CLOSING busy connection: " + pc.getFullDescription());
-
- pc.closeConnectionFully(false);
-
- } catch (Exception ex) {
- // this should never actually happen
- logger.error("Error when closing potentially leaked connection " + pc.getDescription(), ex);
- }
- }
-
- /**
- * Returns information describing connections that are currently being used.
- */
- String getBusyConnectionInformation(boolean toLogger) {
-
- if (toLogger) {
- logger.info("Dumping [{}] busy connections: (Use datasource.xxx.capturestacktrace=true ... to get stackTraces)", size());
- }
-
- StringBuilder sb = new StringBuilder();
-
- for (int i = 0; i < slots.length; i++) {
- if (slots[i] != null) {
- PooledConnection pc = slots[i];
- if (toLogger) {
- logger.info("Busy Connection - {}", pc.getFullDescription());
- } else {
- sb.append(pc.getFullDescription()).append("\r\n");
- }
- }
- }
-
- return sb.toString();
- }
-
-
- /**
- * Return the position of the next empty slot.
- */
- private int nextEmptySlot() {
-
- // search forward
- while (++pos < slots.length) {
- if (slots[pos] == null) {
- return pos;
- }
- }
- // search from beginning
- pos = -1;
- while (++pos < slots.length) {
- if (slots[pos] == null) {
- return pos;
- }
- }
-
- // not expecting this
- throw new RuntimeException("No Empty Slot Found?");
- }
-
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourceAlert.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourceAlert.java
deleted file mode 100644
index 863defa15..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourceAlert.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-/**
- * Listener for notifications about the DataSource such as when the DataSource
- * goes down, up or gets close to it's maximum size.
- *
- * The intention is to send email notifications to an administrator (or similar)
- * when these events occur on the DataSource.
- *
- */
-public interface DataSourceAlert {
-
- /**
- * Send an alert to say the dataSource is back up.
- */
- void dataSourceUp(String dataSourceName);
-
- /**
- * Send an alert to say the dataSource is down.
- */
- void dataSourceDown(String dataSourceName);
-
- /**
- * Send an alert to say the dataSource is getting close to its max size.
- */
- void dataSourceWarning(String subject, String msg);
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourcePool.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourcePool.java
deleted file mode 100644
index 4cd196b0b..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourcePool.java
+++ /dev/null
@@ -1,1003 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-import com.avaje.ebean.config.DataSourceConfig;
-import com.avaje.ebeaninternal.api.ClassUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.persistence.PersistenceException;
-import javax.sql.DataSource;
-import java.io.PrintWriter;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
-import java.sql.Statement;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Properties;
-import java.util.Set;
-
-/**
- * A robust DataSource.
- *
- *
- * - Manages the number of connections closing connections that have been idle
- * for some time.
- *
- Notifies when the datasource goes down and comes back up.
- *
- Checks for expected downtime which is useful for schedule db backups.
- *
- Provides PreparedStatement caching
- *
- Knows the busy connections
- *
- Traces connections that have been leaked
- *
- *
- */
-public class DataSourcePool implements DataSource {
-
- private static final Logger logger = LoggerFactory.getLogger(DataSourcePool.class);
-
- /**
- * The name given to this dataSource.
- */
- private final String name;
-
- /**
- * Used to notify of changes to the DataSource status.
- */
- private final DataSourceAlert notify;
-
- /**
- * Optional listener that can be notified when connections are got from and
- * put back into the pool.
- */
- private final DataSourcePoolListener poolListener;
-
- /**
- * Properties used to create a Connection.
- */
- private final Properties connectionProps;
-
- /**
- * The jdbc connection url.
- */
- private final String databaseUrl;
-
- /**
- * The jdbc driver.
- */
- private final String databaseDriver;
-
- /**
- * The sql used to test a connection.
- */
- private final String heartbeatsql;
-
- private final int heartbeatFreqSecs;
-
- private final int heartbeatTimeoutSeconds;
-
-
- private final long trimPoolFreqMillis;
-
- /**
- * The transaction isolation level as per java.sql.Connection.
- */
- private final int transactionIsolation;
-
- /**
- * The default autoCommit setting for Connections in this pool.
- */
- private final boolean autoCommit;
-
- /**
- * Max idle time in millis.
- */
- private final int maxInactiveMillis;
-
- /**
- * Max age a connection is allowed in millis.
- * A value of 0 means no limit (no trimming based on max age).
- */
- private final long maxAgeMillis;
-
- /**
- * Flag set to true to capture stackTraces (can be expensive).
- */
- private boolean captureStackTrace;
-
- /**
- * The max size of the stack trace to report.
- */
- private final int maxStackTraceSize;
-
- /**
- * flag to indicate we have sent an alert message.
- */
- private boolean dataSourceDownAlertSent;
-
- /**
- * The time the pool was last trimmed.
- */
- private long lastTrimTime;
-
- /**
- * Assume that the DataSource is up. heartBeat checking will discover when
- * it goes down, and comes back up again.
- */
- private boolean dataSourceUp = true;
-
- /**
- * The current alert.
- */
- private boolean inWarningMode;
-
- /**
- * The minimum number of connections this pool will maintain.
- */
- private int minConnections;
-
- /**
- * The maximum number of connections this pool will grow to.
- */
- private int maxConnections;
-
- /**
- * The number of connections to exceed before a warning Alert is fired.
- */
- private int warningSize;
-
- /**
- * The time a thread will wait for a connection to become available.
- */
- private final int waitTimeoutMillis;
-
- /**
- * The size of the preparedStatement cache;
- */
- private int pstmtCacheSize;
-
- private final PooledConnectionQueue queue;
-
- /**
- * Used to find and close() leaked connections. Leaked connections are
- * thought to be busy but have not been used for some time. Each time a
- * connection is used it sets it's lastUsedTime.
- */
- private long leakTimeMinutes;
-
- private final Runnable heartbeatRunnable = new HeartBeatRunnable();
-
- public DataSourcePool(DataSourceAlert notify, String name, DataSourceConfig params) {
- this(notify, name, params, null);
- }
-
- public DataSourcePool(DataSourceAlert notify, String name, DataSourceConfig params, DataSourcePoolListener listener) {
-
- this.notify = notify;
- this.name = name;
- this.poolListener = listener;
-
- this.autoCommit = params.isAutoCommit();
- this.transactionIsolation = params.getIsolationLevel();
-
- this.maxInactiveMillis = 1000 * params.getMaxInactiveTimeSecs();
- this.maxAgeMillis = 60000 * params.getMaxAgeMinutes();
- this.leakTimeMinutes = params.getLeakTimeMinutes();
- this.captureStackTrace = params.isCaptureStackTrace();
- this.maxStackTraceSize = params.getMaxStackTraceSize();
- this.databaseDriver = params.getDriver();
- this.databaseUrl = params.getUrl();
- this.pstmtCacheSize = params.getPstmtCacheSize();
-
- this.minConnections = params.getMinConnections();
- this.maxConnections = params.getMaxConnections();
- this.waitTimeoutMillis = params.getWaitTimeoutMillis();
- this.heartbeatsql = params.getHeartbeatSql();
- this.heartbeatFreqSecs = params.getHeartbeatFreqSecs();
- this.heartbeatTimeoutSeconds = params.getHeartbeatTimeoutSeconds();
- this.trimPoolFreqMillis = 1000 * params.getTrimPoolFreqSecs();
-
- queue = new PooledConnectionQueue(this);
-
- String un = params.getUsername();
- String pw = params.getPassword();
- if (un == null) {
- throw new RuntimeException("DataSource user is null?");
- }
- if (pw == null) {
- throw new RuntimeException("DataSource password is null?");
- }
- this.connectionProps = new Properties();
- this.connectionProps.setProperty("user", un);
- this.connectionProps.setProperty("password", pw);
-
- Map customProperties = params.getCustomProperties();
- if (customProperties != null) {
- Set> entrySet = customProperties.entrySet();
- for (Entry entry : entrySet) {
- this.connectionProps.setProperty(entry.getKey(), entry.getValue());
- }
- }
-
- try {
- initialise();
- } catch (SQLException ex) {
- throw new RuntimeException(ex);
- }
- }
-
- class HeartBeatRunnable implements Runnable {
- @Override
- public void run() {
- checkDataSource();
- }
- }
-
-
- @Override
- public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
- throw new SQLFeatureNotSupportedException("We do not support java.util.logging");
- }
-
- private void initialise() throws SQLException {
-
- // Ensure database driver is loaded
- try {
- ClassUtil.forName(this.databaseDriver);
- } catch (Throwable e) {
- throw new PersistenceException("Problem loading Database Driver [" + this.databaseDriver + "]: " + e.getMessage(), e);
- }
-
- String transIsolation = TransactionIsolation.getLevelDescription(transactionIsolation);
- //noinspection StringBufferReplaceableByString
- StringBuilder sb = new StringBuilder(70);
- sb.append("DataSourcePool [").append(name);
- sb.append("] autoCommit[").append(autoCommit);
- sb.append("] transIsolation[").append(transIsolation);
- sb.append("] min[").append(minConnections);
- sb.append("] max[").append(maxConnections).append("]");
-
- logger.info(sb.toString());
-
- queue.ensureMinimumConnections();
- }
-
- /**
- * Returns false.
- */
- public boolean isWrapperFor(Class> arg0) throws SQLException {
- return false;
- }
-
- /**
- * Not Implemented.
- */
- public T unwrap(Class arg0) throws SQLException {
- throw new SQLException("Not Implemented");
- }
-
- /**
- * Return the dataSource name.
- */
- public String getName() {
- return name;
- }
-
- /**
- * Return the max size of stack traces used when trying to find connection pool leaks.
- *
- * This is only used when {@link #isCaptureStackTrace()} is true.
- *
- */
- int getMaxStackTraceSize() {
- return maxStackTraceSize;
- }
-
- /**
- * Returns false when the dataSource is down.
- */
- public boolean isDataSourceUp() {
- return dataSourceUp;
- }
-
- /**
- * Called when the pool hits the warning level.
- */
- protected void notifyWarning(String msg) {
-
- if (!inWarningMode) {
- // send an Error to the event log...
- inWarningMode = true;
- logger.warn(msg);
- if (notify != null) {
- String subject = "DataSourcePool [" + name + "] warning";
- notify.dataSourceWarning(subject, msg);
- }
- }
- }
-
- private void notifyDataSourceIsDown(SQLException ex) {
-
- if (!dataSourceDownAlertSent) {
- logger.error("FATAL: DataSourcePool [" + name + "] is down or has network error!!!", ex);
- if (notify != null) {
- notify.dataSourceDown(name);
- }
- dataSourceDownAlertSent = true;
- }
- if (dataSourceUp) {
- reset();
- }
- dataSourceUp = false;
- }
-
- private void notifyDataSourceIsUp() {
- if (dataSourceDownAlertSent) {
- logger.error("RESOLVED FATAL: DataSourcePool [" + name + "] is back up!");
- if (notify != null) {
- notify.dataSourceUp(name);
- }
- dataSourceDownAlertSent = false;
-
- } else if (!dataSourceUp) {
- logger.info("DataSourcePool [" + name + "] is back up!");
- }
-
- if (!dataSourceUp) {
- dataSourceUp = true;
- reset();
- }
- }
-
-
- /**
- * Return the heartbeat frequency in seconds.
- *
- * This is the frequency that the heartbeat runnable should be run.
- *
- */
- public int getHeartbeatFreqSecs() {
- return heartbeatFreqSecs;
- }
-
- /**
- * Returns the Runnable used to check the dataSource using a heartbeat query.
- */
- public Runnable getHeartbeatRunnable() {
- return heartbeatRunnable;
- }
-
- /**
- * Trim connections (in the free list) based on idle time and maximum age.
- */
- private void trimIdleConnections() {
- if (System.currentTimeMillis() > (lastTrimTime + trimPoolFreqMillis)) {
- try {
- queue.trim(maxInactiveMillis, maxAgeMillis);
- lastTrimTime = System.currentTimeMillis();
- } catch (Exception e) {
- logger.error("Error trying to trim idle connections", e);
- }
- }
- }
-
- /**
- * Check the dataSource is up. Trim connections.
- *
- * This is called by the HeartbeatRunnable which should be scheduled to
- * run periodically (every heartbeatFreqSecs seconds actually).
- *
- */
- private void checkDataSource() {
-
- // first trim idle connections
- trimIdleConnections();
-
- Connection conn = null;
- try {
- // Get a connection from the pool and test it
- conn = getConnection();
- if (testConnection(conn)) {
- notifyDataSourceIsUp();
-
- } else {
- notifyDataSourceIsDown(null);
- }
-
- } catch (SQLException ex) {
- notifyDataSourceIsDown(ex);
-
- } finally {
- try {
- if (conn != null) {
- conn.close();
- }
- } catch (SQLException ex) {
- logger.warn("Can't close connection in checkDataSource!");
- }
- }
- }
-
- /**
- * Create a Connection that will not be part of the connection pool.
- *
- *
- * When this connection is closed it will not go back into the pool.
- *
- *
- *
- * If withDefaults is true then the Connection will have the autoCommit and
- * transaction isolation set to the defaults for the pool.
- *
- */
- public Connection createUnpooledConnection() throws SQLException {
-
- try {
- Connection conn = DriverManager.getConnection(databaseUrl, connectionProps);
- conn.setAutoCommit(autoCommit);
- conn.setTransactionIsolation(transactionIsolation);
- return conn;
-
- } catch (SQLException ex) {
- notifyDataSourceIsDown(null);
- throw ex;
- }
- }
-
- /**
- * Set a new maximum size. The pool should respect this new maximum
- * immediately and not require a restart. You may want to increase the
- * maxConnections if the pool gets large and hits the warning level.
- */
- public void setMaxSize(int max) {
- queue.setMaxSize(max);
- this.maxConnections = max;
- }
-
- /**
- * Return the max size this pool can grow to.
- */
- public int getMaxSize() {
- return maxConnections;
- }
-
- /**
- * Set the min size this pool should maintain.
- */
- public void setMinSize(int min) {
- queue.setMinSize(min);
- this.minConnections = min;
- }
-
- /**
- * Return the min size this pool should maintain.
- */
- public int getMinSize() {
- return minConnections;
- }
-
- /**
- * Set a new maximum size. The pool should respect this new maximum
- * immediately and not require a restart. You may want to increase the
- * maxConnections if the pool gets large and hits the warning and or alert
- * levels.
- */
- public void setWarningSize(int warningSize) {
- queue.setWarningSize(warningSize);
- this.warningSize = warningSize;
- }
-
- /**
- * Return the warning size. When the pool hits this size it can send a
- * notify message to an administrator.
- */
- public int getWarningSize() {
- return warningSize;
- }
-
- /**
- * Return the time in millis that threads will wait when the pool has hit
- * the max size. These threads wait for connections to be returned by the
- * busy connections.
- */
- public int getWaitTimeoutMillis() {
- return waitTimeoutMillis;
- }
-
- /**
- * Return the time after which inactive connections are trimmed.
- */
- public int getMaxInactiveMillis() {
- return maxInactiveMillis;
- }
-
- /**
- * Return the maximum age a connection is allowed to be before it is trimmed
- * out of the pool. This value can be 0 which means there is no maximum age.
- */
- public long getMaxAgeMillis() {
- return maxAgeMillis;
- }
-
- private boolean testConnection(Connection conn) throws SQLException {
-
- if (heartbeatsql == null) {
- return conn.isValid(heartbeatTimeoutSeconds);
- }
- Statement stmt = null;
- ResultSet rset = null;
- try {
- // It should only error IF the DataSource is down or a network issue
- stmt = conn.createStatement();
- if (heartbeatTimeoutSeconds > 0) {
- stmt.setQueryTimeout(heartbeatTimeoutSeconds);
- }
- rset = stmt.executeQuery(heartbeatsql);
- conn.commit();
-
- return true;
-
- } finally {
- try {
- if (rset != null) {
- rset.close();
- }
- } catch (SQLException e) {
- logger.error(null, e);
- }
- try {
- if (stmt != null) {
- stmt.close();
- }
- } catch (SQLException e) {
- logger.error(null, e);
- }
- }
- }
-
- /**
- * Make sure the connection is still ok to use. If not then remove it from
- * the pool.
- */
- boolean validateConnection(PooledConnection conn) {
- try {
- return testConnection(conn);
-
- } catch (Exception e) {
- logger.warn("heartbeatsql test failed on connection[" + conn.getName() + "]");
- return false;
- }
- }
-
- /**
- * Called by the PooledConnection themselves, returning themselves to the
- * pool when they have been finished with.
- *
- * Note that connections may not be added back to the pool if returnToPool
- * is false or if they where created before the recycleTime. In both of
- * these cases the connection is fully closed and not pooled.
- *
- *
- * @param pooledConnection the returning connection
- */
- void returnConnection(PooledConnection pooledConnection) {
-
- // return a normal 'good' connection
- returnTheConnection(pooledConnection, false);
- }
-
- /**
- * This is a bad connection and must be removed from the pool's busy list and fully closed.
- */
- void returnConnectionForceClose(PooledConnection pooledConnection) {
-
- returnTheConnection(pooledConnection, true);
- }
-
- /**
- * Return connection. If forceClose is true then this is a bad connection that
- * must be removed and closed fully.
- */
- private void returnTheConnection(PooledConnection pooledConnection, boolean forceClose) {
-
- if (poolListener != null && !forceClose) {
- poolListener.onBeforeReturnConnection(pooledConnection);
- }
- queue.returnPooledConnection(pooledConnection, forceClose);
-
- if (forceClose) {
- // Got a bad connection so check the pool
- checkDataSource();
- }
- }
-
- /**
- * Collect statistics of a connection that is fully closing
- */
- void reportClosingConnection(PooledConnection pooledConnection) {
-
- queue.reportClosingConnection(pooledConnection);
- }
-
- /**
- * Returns information describing connections that are currently being used.
- */
- public String getBusyConnectionInformation() {
-
- return queue.getBusyConnectionInformation();
- }
-
- /**
- * Dumps the busy connection information to the logs.
- *
- * This includes the stackTrace elements if they are being captured. This is
- * useful when needing to look a potential connection pool leaks.
- *
- */
- public void dumpBusyConnectionInformation() {
-
- queue.dumpBusyConnectionInformation();
- }
-
- /**
- * Close any busy connections that have not been used for some time.
- *
- * These connections are considered to have leaked from the connection pool.
- *
- *
- * Connection leaks occur when code doesn't ensure that connections are
- * closed() after they have been finished with. There should be an
- * appropriate try catch finally block to ensure connections are always
- * closed and put back into the pool.
- *
- */
- public void closeBusyConnections(long leakTimeMinutes) {
-
- queue.closeBusyConnections(leakTimeMinutes);
- }
-
- /**
- * Grow the pool by creating a new connection. The connection can either be
- * added to the available list, or returned.
- *
- * This method is protected by synchronization in calling methods.
- *
- */
- PooledConnection createConnectionForQueue(int connId) throws SQLException {
-
- try {
- Connection c = createUnpooledConnection();
-
- PooledConnection pc = new PooledConnection(this, connId, c);
- pc.resetForUse();
-
- if (!dataSourceUp) {
- notifyDataSourceIsUp();
- }
- return pc;
-
- } catch (SQLException ex) {
- notifyDataSourceIsDown(ex);
- throw ex;
- }
- }
-
- /**
- * Close all the connections in the pool.
- *
- *
- * - Checks that the database is up.
- *
- Resets the Alert level.
- *
- Closes busy connections that have not been used for some time (aka
- * leaks).
- *
- This closes all the currently available connections.
- *
- Busy connections are closed when they are returned to the pool.
- *
- *
- */
- public void reset() {
- queue.reset(leakTimeMinutes);
- inWarningMode = false;
- }
-
- /**
- * Return a pooled connection.
- */
- public Connection getConnection() throws SQLException {
- return getPooledConnection();
- }
-
- /**
- * Get a connection from the pool.
- *
- * This will grow the pool if all the current connections are busy. This
- * will go into a wait if the pool has hit its maximum size.
- *
- */
- private PooledConnection getPooledConnection() throws SQLException {
-
- PooledConnection c = queue.getPooledConnection();
-
- if (captureStackTrace) {
- c.setStackTrace(Thread.currentThread().getStackTrace());
- }
-
- if (poolListener != null) {
- poolListener.onAfterBorrowConnection(c);
- }
- return c;
- }
-
- /**
- * Send a message to the DataSourceAlertListener to test it. This is so that
- * you can make sure the alerter is configured correctly etc.
- */
- public void testAlert() {
-
- String subject = "Test DataSourcePool [" + name + "]";
- String msg = "Just testing if alert message is sent successfully.";
-
- if (notify != null) {
- notify.dataSourceWarning(subject, msg);
- }
- }
-
- /**
- * This will close all the free connections, and then go into a wait loop,
- * waiting for the busy connections to be freed.
- *
- *
- * The DataSources's should be shutdown AFTER thread pools. Leaked
- * Connections are not waited on, as that would hang the server.
- *
- */
- public void shutdown(boolean deregisterDriver) {
- queue.shutdown();
- if (deregisterDriver) {
- deregisterDriver();
- }
- }
-
- /**
- * Return the default autoCommit setting Connections in this pool will use.
- *
- * @return true if the pool defaults autoCommit to true
- */
- public boolean getAutoCommit() {
- return autoCommit;
- }
-
- /**
- * Return the default transaction isolation level connections in this pool
- * should have.
- *
- * @return the default transaction isolation level
- */
- int getTransactionIsolation() {
- return transactionIsolation;
- }
-
- /**
- * Return true if the connection pool is currently capturing the StackTrace
- * when connections are 'got' from the pool.
- *
- * This is set to true to help diagnose connection pool leaks.
- *
- */
- public boolean isCaptureStackTrace() {
- return captureStackTrace;
- }
-
- /**
- * Set this to true means that the StackElements are captured every time a
- * connection is retrieved from the pool. This can be used to identify
- * connection pool leaks.
- */
- public void setCaptureStackTrace(boolean captureStackTrace) {
- this.captureStackTrace = captureStackTrace;
- }
-
- /**
- * Not implemented and shouldn't be used.
- */
- public Connection getConnection(String username, String password) throws SQLException {
- throw new SQLException("Method not supported");
- }
-
- /**
- * Not implemented and shouldn't be used.
- */
- public int getLoginTimeout() throws SQLException {
- throw new SQLException("Method not supported");
- }
-
- /**
- * Not implemented and shouldn't be used.
- */
- public void setLoginTimeout(int seconds) throws SQLException {
- throw new SQLException("Method not supported");
- }
-
- /**
- * Returns null.
- */
- public PrintWriter getLogWriter() {
- return null;
- }
-
- /**
- * Not implemented.
- */
- public void setLogWriter(PrintWriter writer) throws SQLException {
- throw new SQLException("Method not supported");
- }
-
- /**
- * For detecting and closing leaked connections. Connections that have been
- * busy for more than leakTimeMinutes are considered leaks and will be
- * closed on a reset().
- *
- * If you want to use a connection for that longer then you should consider
- * creating an unpooled connection or setting longRunning to true on that
- * connection.
- *
- */
- public void setLeakTimeMinutes(long leakTimeMinutes) {
- this.leakTimeMinutes = leakTimeMinutes;
- }
-
- /**
- * Return the number of minutes after which a busy connection could be
- * considered leaked from the connection pool.
- */
- public long getLeakTimeMinutes() {
- return leakTimeMinutes;
- }
-
- /**
- * Return the preparedStatement cache size.
- */
- public int getPstmtCacheSize() {
- return pstmtCacheSize;
- }
-
- /**
- * Set the preparedStatement cache size.
- */
- public void setPstmtCacheSize(int pstmtCacheSize) {
- this.pstmtCacheSize = pstmtCacheSize;
- }
-
- /**
- * Return the current status of the connection pool.
- *
- * If you pass reset = true then the counters such as
- * hitCount, waitCount and highWaterMark are reset.
- *
- */
- public Status getStatus(boolean reset) {
- return queue.getStatus(reset);
- }
-
- /**
- * Return the aggregated load statistics collected on all the connections in the pool.
- */
- public DataSourcePoolStatistics getStatistics(boolean reset) {
-
- return queue.getStatistics(reset);
- }
-
- /**
- * Deregister the JDBC driver.
- */
- private void deregisterDriver() {
- try {
- logger.debug("Deregister the JDBC driver " + this.databaseDriver);
- DriverManager.deregisterDriver(DriverManager.getDriver(this.databaseUrl));
- } catch (SQLException e) {
- logger.warn("Error trying to deregister the JDBC driver " + this.databaseDriver, e);
- }
- }
-
- public static class Status {
-
- private final String name;
- private final int minSize;
- private final int maxSize;
- private final int free;
- private final int busy;
- private final int waiting;
- private final int highWaterMark;
- private final int waitCount;
- private final int hitCount;
-
- protected Status(String name, int minSize, int maxSize, int free, int busy, int waiting, int highWaterMark,
- int waitCount, int hitCount) {
- this.name = name;
- this.minSize = minSize;
- this.maxSize = maxSize;
- this.free = free;
- this.busy = busy;
- this.waiting = waiting;
- this.highWaterMark = highWaterMark;
- this.waitCount = waitCount;
- this.hitCount = hitCount;
- }
-
- public String toString() {
- return "min[" + minSize + "] max[" + maxSize + "] free[" + free + "] busy[" + busy + "] waiting[" + waiting
- + "] highWaterMark[" + highWaterMark + "] waitCount[" + waitCount + "] hitCount[" + hitCount + "]";
- }
-
- /**
- * Return the DataSource name.
- */
- public String getName() {
- return name;
- }
-
- /**
- * Return the min pool size.
- */
- public int getMinSize() {
- return minSize;
- }
-
- /**
- * Return the max pool size.
- */
- public int getMaxSize() {
- return maxSize;
- }
-
- /**
- * Return the current number of free connections in the pool.
- */
- public int getFree() {
- return free;
- }
-
- /**
- * Return the current number of busy connections in the pool.
- */
- public int getBusy() {
- return busy;
- }
-
- /**
- * Return the current number of threads waiting for a connection.
- */
- public int getWaiting() {
- return waiting;
- }
-
- /**
- * Return the high water mark of busy connections.
- */
- public int getHighWaterMark() {
- return highWaterMark;
- }
-
- /**
- * Return the total number of times a thread had to wait.
- */
- public int getWaitCount() {
- return waitCount;
- }
-
- /**
- * Return the total number of times there was an attempt to get a
- * connection.
- *
- * If the attempt to get a connection failed with a timeout or other
- * exception those attempts are still included in this hit count.
- *
- */
- public int getHitCount() {
- return hitCount;
- }
-
- }
-
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourcePoolListener.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourcePoolListener.java
deleted file mode 100644
index 485384557..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourcePoolListener.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-import java.sql.Connection;
-
-
-/**
- * A {@link DataSourcePool} listener which allows you to hook on the
- * borrow/return process of getting or returning connections from the pool.
- *
- * In the configuration use the poolListener key to configure which listener to
- * use.
- *
- *
- * Example: datasource.ora10.poolListener=my.very.fancy.PoolListener
- *
- *
- *
- * Notice: This listener only works if you are using the default Avaje
- * {@link DataSourcePool}.
- *
- */
-public interface DataSourcePoolListener {
-
- /**
- * Called after a connection has been retrieved from the connection pool
- */
- void onAfterBorrowConnection(Connection c);
-
- /**
- * Called before a connection will be put back to the connection pool
- */
- void onBeforeReturnConnection(Connection c);
-
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourcePoolStatistics.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourcePoolStatistics.java
deleted file mode 100644
index b3c657e83..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourcePoolStatistics.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-/**
- * Represents aggregated statistics collected from the DataSourcePool.
- *
- * The goal is to present insight into the overload load of the DataSourcePool.
- * These statistics can be collected and reported regularly to show load over
- * time.
- *
- *
- * Each pooled connection collects statistics. When a pooled connection is fully
- * closed it can report it's statistics to the pool to be included as part of
- * the collected statistics.
- *
- */
-public class DataSourcePoolStatistics {
-
- private final long collectionStart;
-
- private final long count;
-
- private final long errorCount;
-
- private final long hwmMicros;
-
- private final long totalMicros;
-
- /**
- * Construct with statistics collected.
- */
- DataSourcePoolStatistics(long collectionStart, long count, long errorCount, long hwmMicros, long totalMicros) {
- this.collectionStart = collectionStart;
- this.count = count;
- this.errorCount = errorCount;
- this.hwmMicros = hwmMicros;
- this.totalMicros = totalMicros;
- }
-
- public String toString() {
- return "count[" + count + "] errors[" + errorCount + "] totalMicros[" + totalMicros + "] hwmMicros[" + hwmMicros
- + "] avgMicros[" + getAvgMicros() + "]";
- }
-
- /**
- * Return the start time this set of statistics was collected from.
- */
- public long getCollectionStart() {
- return collectionStart;
- }
-
- /**
- * Return the total number of 'get connection' requests.
- */
- public long getCount() {
- return count;
- }
-
- /**
- * Return the number of SQLExceptions reported.
- */
- public long getErrorCount() {
- return errorCount;
- }
-
- /**
- * Return the high water mark for the duration a connection was busy/used.
- */
- public long getHwmMicros() {
- return hwmMicros;
- }
-
- /**
- * Return the aggregate time connections were busy/used.
- */
- public long getTotalMicros() {
- return totalMicros;
- }
-
- /**
- * Return the average time connections were busy/used.
- */
- public long getAvgMicros() {
- return (totalMicros == 0) ? 0 : totalMicros / count;
- }
-
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/ExtendedPreparedStatement.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/ExtendedPreparedStatement.java
deleted file mode 100644
index 75aeb60a5..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/ExtendedPreparedStatement.java
+++ /dev/null
@@ -1,386 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URL;
-import java.sql.Array;
-import java.sql.Blob;
-import java.sql.Clob;
-import java.sql.Date;
-import java.sql.ParameterMetaData;
-import java.sql.PreparedStatement;
-import java.sql.Ref;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.sql.Time;
-import java.sql.Timestamp;
-import java.util.Calendar;
-
-/**
- * Extended PreparedStatement that supports caching.
- *
- * Designed so that it can be cached by the PooledConnection. It additionally
- * notes any Exceptions that occur and this is used to ensure bad connections
- * are removed from the connection pool.
- *
- */
-public class ExtendedPreparedStatement extends ExtendedStatement implements PreparedStatement {
-
- /**
- * The SQL used to create the underlying PreparedStatement.
- */
- private final String sql;
-
- /**
- * The key used to cache this in the connection.
- */
- private final String cacheKey;
-
- /**
- * Create a wrapped PreparedStatement that can be cached.
- */
- public ExtendedPreparedStatement(PooledConnection pooledConnection, PreparedStatement pstmt, String sql, String cacheKey) {
- super(pooledConnection, pstmt);
- this.sql = sql;
- this.cacheKey = cacheKey;
- }
-
- /**
- * Return the key used to cache this on the Connection.
- */
- String getCacheKey() {
- return cacheKey;
- }
-
- /**
- * Return the SQL used to create this PreparedStatement.
- */
- public String getSql() {
- return sql;
- }
-
- /**
- * Fully close the underlying PreparedStatement. After this we can no longer
- * reuse the PreparedStatement.
- */
- void closeDestroy() throws SQLException {
- pstmt.close();
- }
-
- /**
- * Returns the PreparedStatement back into the cache. This doesn't fully
- * close the underlying PreparedStatement.
- */
- public void close() throws SQLException {
- // return the connection back into the cache.
- pooledConnection.returnPreparedStatement(this);
- }
-
- /**
- * Add the last binding for batch execution.
- */
- public void addBatch() throws SQLException {
- try {
- pstmt.addBatch();
- } catch (SQLException e) {
- // we got an error... need to check this
- // connection before returning it
- pooledConnection.markWithError();
- throw e;
- }
- }
-
- /**
- * Clear parameters.
- */
- public void clearParameters() throws SQLException {
- try {
- pstmt.clearParameters();
- } catch (SQLException e) {
- // we got an error... need to check
- // this connection before returning it
- pooledConnection.markWithError();
- throw e;
- }
- }
-
- /**
- * execute the statement.
- */
- public boolean execute() throws SQLException {
- try {
- return pstmt.execute();
- } catch (SQLException e) {
- // we got an error... need to check
- // this connection before returning it
- pooledConnection.markWithError();
- throw e;
- }
- }
-
- /**
- * Execute teh query.
- */
- public ResultSet executeQuery() throws SQLException {
- try {
- return pstmt.executeQuery();
- } catch (SQLException e) {
- // we got an error... need to check
- // this connection before returning it
- pooledConnection.markWithError();
- throw e;
- }
- }
-
- /**
- * Execute the dml statement.
- */
- public int executeUpdate() throws SQLException {
- try {
- return pstmt.executeUpdate();
- } catch (SQLException e) {
- // we got an error... need to check
- // this connection before returning it
- pooledConnection.markWithError();
- throw e;
- }
- }
-
- /**
- * Return the MetaData for the query.
- */
- public ResultSetMetaData getMetaData() throws SQLException {
- try {
- return pstmt.getMetaData();
- } catch (SQLException e) {
- // we got an error... need to check
- // this connection before returning it
- pooledConnection.markWithError();
- throw e;
- }
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public ParameterMetaData getParameterMetaData() throws SQLException {
- return pstmt.getParameterMetaData();
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setArray(int i, Array x) throws SQLException {
- pstmt.setArray(i, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {
- pstmt.setAsciiStream(parameterIndex, x, length);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
- pstmt.setBigDecimal(parameterIndex, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {
- pstmt.setBinaryStream(parameterIndex, x, length);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setBlob(int i, Blob x) throws SQLException {
- pstmt.setBlob(i, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setBoolean(int parameterIndex, boolean x) throws SQLException {
- pstmt.setBoolean(parameterIndex, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setByte(int parameterIndex, byte x) throws SQLException {
- pstmt.setByte(parameterIndex, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setBytes(int parameterIndex, byte[] x) throws SQLException {
- pstmt.setBytes(parameterIndex, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setCharacterStream(int parameterIndex, Reader reader, int length)
- throws SQLException {
- pstmt.setCharacterStream(parameterIndex, reader, length);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setClob(int i, Clob x) throws SQLException {
- pstmt.setClob(i, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setDate(int parameterIndex, Date x) throws SQLException {
- pstmt.setDate(parameterIndex, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {
- pstmt.setDate(parameterIndex, x, cal);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setDouble(int parameterIndex, double x) throws SQLException {
- pstmt.setDouble(parameterIndex, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setFloat(int parameterIndex, float x) throws SQLException {
- pstmt.setFloat(parameterIndex, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setInt(int parameterIndex, int x) throws SQLException {
- pstmt.setInt(parameterIndex, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setLong(int parameterIndex, long x) throws SQLException {
- pstmt.setLong(parameterIndex, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setNull(int parameterIndex, int sqlType) throws SQLException {
- pstmt.setNull(parameterIndex, sqlType);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setNull(int paramIndex, int sqlType, String typeName) throws SQLException {
- pstmt.setNull(paramIndex, sqlType, typeName);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setObject(int parameterIndex, Object x) throws SQLException {
- pstmt.setObject(parameterIndex, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
- pstmt.setObject(parameterIndex, x, targetSqlType);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setObject(int parameterIndex, Object x, int targetSqlType, int scale)
- throws SQLException {
- pstmt.setObject(parameterIndex, x, targetSqlType, scale);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setRef(int i, Ref x) throws SQLException {
- pstmt.setRef(i, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setShort(int parameterIndex, short x) throws SQLException {
- pstmt.setShort(parameterIndex, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setString(int parameterIndex, String x) throws SQLException {
- pstmt.setString(parameterIndex, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setTime(int parameterIndex, Time x) throws SQLException {
- pstmt.setTime(parameterIndex, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
- pstmt.setTime(parameterIndex, x, cal);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
- pstmt.setTimestamp(parameterIndex, x);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
- pstmt.setTimestamp(parameterIndex, x, cal);
- }
-
- /**
- * Standard PreparedStatement method execution.
- *
- * @deprecated
- */
- public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {
- pstmt.setUnicodeStream(parameterIndex, x, length);
- }
-
- /**
- * Standard PreparedStatement method execution.
- */
- public void setURL(int parameterIndex, URL x) throws SQLException {
- pstmt.setURL(parameterIndex, x);
- }
-
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/ExtendedStatement.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/ExtendedStatement.java
deleted file mode 100644
index ec2d484cd..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/ExtendedStatement.java
+++ /dev/null
@@ -1,327 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-
-import com.avaje.ebeaninternal.jdbc.PreparedStatementDelegator;
-
-/**
- * Implements the Statement methods for ExtendedPreparedStatement.
- *
- * PreparedStatements should always be used and the intention is that there
- * should be no use of Statement at all. The implementation here is generally
- * for the case where someone uses the Statement api on an ExtendedPreparedStatement.
- *
- */
-abstract class ExtendedStatement extends PreparedStatementDelegator {
-
- /**
- * The pooled connection this Statement belongs to.
- */
- final PooledConnection pooledConnection;
-
- /**
- * The underlying Statement that this object wraps.
- */
- protected final PreparedStatement pstmt;
-
- /**
- * Create the ExtendedStatement for a given pooledConnection.
- */
- ExtendedStatement(PooledConnection pooledConnection, PreparedStatement pstmt) {
- super(pstmt);
-
- this.pooledConnection = pooledConnection;
- this.pstmt = pstmt;
- }
-
- /**
- * Put the statement back into the statement cache.
- */
- public abstract void close() throws SQLException;
-
- /**
- * Return the underlying connection.
- */
- public Connection getConnection() throws SQLException {
- try {
- return pstmt.getConnection();
- } catch (SQLException e) {
- pooledConnection.markWithError();
- throw e;
- }
- }
-
- /**
- * Add the sql for batch execution.
- */
- public void addBatch(String sql) throws SQLException {
- try {
- pooledConnection.setLastStatement(sql);
- pstmt.addBatch(sql);
- } catch (SQLException e) {
- pooledConnection.markWithError();
- throw e;
- }
- }
-
- /**
- * Execute the sql.
- */
- public boolean execute(String sql) throws SQLException {
- try {
- pooledConnection.setLastStatement(sql);
- return pstmt.execute(sql);
- } catch (SQLException e) {
- pooledConnection.markWithError();
- throw e;
- }
- }
-
- /**
- * Execute the query.
- */
- public ResultSet executeQuery(String sql) throws SQLException {
- try {
- pooledConnection.setLastStatement(sql);
- return pstmt.executeQuery(sql);
- } catch (SQLException e) {
- pooledConnection.markWithError();
- throw e;
- }
- }
-
- /**
- * Execute the dml sql.
- */
- public int executeUpdate(String sql) throws SQLException {
- try {
- pooledConnection.setLastStatement(sql);
- return pstmt.executeUpdate(sql);
- } catch (SQLException e) {
- pooledConnection.markWithError();
- throw e;
- }
- }
-
- /**
- * Standard Statement method call.
- */
- public int[] executeBatch() throws SQLException {
- return pstmt.executeBatch();
- }
-
- /**
- * Standard Statement method call.
- */
- public void cancel() throws SQLException {
- pstmt.cancel();
- }
-
- /**
- * Standard Statement method call.
- */
- public void clearBatch() throws SQLException {
- pstmt.clearBatch();
- }
-
- /**
- * Standard Statement method call.
- */
- public void clearWarnings() throws SQLException {
- pstmt.clearWarnings();
- }
-
- /**
- * Standard Statement method call.
- */
- public int getFetchDirection() throws SQLException {
- return pstmt.getFetchDirection();
- }
-
- /**
- * Standard Statement method call.
- */
- public int getFetchSize() throws SQLException {
- return pstmt.getFetchSize();
- }
-
- /**
- * Standard Statement method call.
- */
- public int getMaxFieldSize() throws SQLException {
- return pstmt.getMaxFieldSize();
- }
-
- /**
- * Standard Statement method call.
- */
- public int getMaxRows() throws SQLException {
- return pstmt.getMaxRows();
- }
-
- /**
- * Standard Statement method call.
- */
- public boolean getMoreResults() throws SQLException {
- return pstmt.getMoreResults();
- }
-
- /**
- * Standard Statement method call.
- */
- public int getQueryTimeout() throws SQLException {
- return pstmt.getQueryTimeout();
- }
-
- /**
- * Standard Statement method call.
- */
- public ResultSet getResultSet() throws SQLException {
- return pstmt.getResultSet();
- }
-
- /**
- * Standard Statement method call.
- */
- public int getResultSetConcurrency() throws SQLException {
- return pstmt.getResultSetConcurrency();
- }
-
- /**
- * Standard Statement method call.
- */
- public int getResultSetType() throws SQLException {
- return pstmt.getResultSetType();
- }
-
- /**
- * Standard Statement method call.
- */
- public int getUpdateCount() throws SQLException {
- return pstmt.getUpdateCount();
- }
-
- /**
- * Standard Statement method call.
- */
- public SQLWarning getWarnings() throws SQLException {
- return pstmt.getWarnings();
- }
-
- /**
- * Standard Statement method call.
- */
- public void setCursorName(String name) throws SQLException {
- pstmt.setCursorName(name);
- }
-
- /**
- * Standard Statement method call.
- */
- public void setEscapeProcessing(boolean enable) throws SQLException {
- pstmt.setEscapeProcessing(enable);
- }
-
- /**
- * Standard Statement method call.
- */
- public void setFetchDirection(int direction) throws SQLException {
- pstmt.setFetchDirection(direction);
- }
-
- /**
- * Standard Statement method call.
- */
- public void setFetchSize(int rows) throws SQLException {
- pstmt.setFetchSize(rows);
- }
-
- /**
- * Standard Statement method call.
- */
- public void setMaxFieldSize(int max) throws SQLException {
- pstmt.setMaxFieldSize(max);
- }
-
- /**
- * Standard Statement method call.
- */
- public void setMaxRows(int max) throws SQLException {
- pstmt.setMaxRows(max);
- }
-
- /**
- * Standard Statement method call.
- */
- public void setQueryTimeout(int seconds) throws SQLException {
- pstmt.setQueryTimeout(seconds);
- }
-
- /**
- * Standard Statement method call.
- */
- public boolean getMoreResults(int i) throws SQLException {
- return pstmt.getMoreResults(i);
- }
-
- /**
- * Standard Statement method call.
- */
- public ResultSet getGeneratedKeys() throws SQLException {
- return pstmt.getGeneratedKeys();
- }
-
- /**
- * Standard Statement method call.
- */
- public int executeUpdate(String s, int i) throws SQLException {
- return pstmt.executeUpdate(s, i);
- }
-
- /**
- * Standard Statement method call.
- */
- public int executeUpdate(String s, int[] i) throws SQLException {
- return pstmt.executeUpdate(s, i);
- }
-
- /**
- * Standard Statement method call.
- */
- public int executeUpdate(String s, String[] i) throws SQLException {
- return pstmt.executeUpdate(s, i);
- }
-
- /**
- * Standard Statement method call.
- */
- public boolean execute(String s, int i) throws SQLException {
- return pstmt.execute(s, i);
- }
-
- /**
- * Standard Statement method call.
- */
- public boolean execute(String s, int[] i) throws SQLException {
- return pstmt.execute(s, i);
- }
-
- /**
- * Standard Statement method call.
- */
- public boolean execute(String s, String[] i) throws SQLException {
- return pstmt.execute(s, i);
- }
-
- /**
- * Standard Statement method call.
- */
- public int getResultSetHoldability() throws SQLException {
- return pstmt.getResultSetHoldability();
- }
-
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/FreeConnectionBuffer.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/FreeConnectionBuffer.java
deleted file mode 100644
index 5676f6509..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/FreeConnectionBuffer.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.avaje.ebeaninternal.server.lib.sql.PooledConnectionStatistics.LoadValues;
-
-/**
- * A buffer designed especially to hold free pooled connections.
- *
- * All thread safety controlled externally (by PooledConnectionQueue).
- *
- */
-class FreeConnectionBuffer {
-
- private static final Logger logger = LoggerFactory.getLogger(FreeConnectionBuffer.class);
-
- /**
- * Buffer oriented for add and remove.
- */
- private final LinkedList freeBuffer = new LinkedList();
-
- FreeConnectionBuffer() {
- }
-
- protected int size() {
- return freeBuffer.size();
- }
-
- protected boolean isEmpty() {
- return freeBuffer.isEmpty();
- }
-
- /**
- * Add connection to the free list.
- */
- protected void add(PooledConnection pc) {
- freeBuffer.addLast(pc);
- }
-
- /**
- * Remove a connection from the free list.
- */
- protected PooledConnection remove() {
- return freeBuffer.removeFirst();
- }
-
- /**
- * Close all connections in this buffer.
- */
- void closeAll(boolean logErrors) {
-
- // create a temporary list
- List tempList = new ArrayList(freeBuffer.size());
-
- // add all the connections into it
- for (PooledConnection c : freeBuffer) {
- tempList.add(c);
- }
-
- // clear the buffer (in case it takes some time to close these connections).
- freeBuffer.clear();
-
- logger.debug("... closing all {} connections from the free list with logErrors: {}", tempList.size(), logErrors);
- for (int i = 0; i < tempList.size(); i++) {
- PooledConnection pooledConnection = tempList.get(i);
- logger.debug("... closing {} of {} connections from the free list", i, tempList.size());
- pooledConnection.closeConnectionFully(logErrors);
- }
- }
-
- /**
- * Trim any inactive connections that have not been used since usedSince.
- */
- protected int trim(long usedSince, long createdSince) {
-
- int trimCount = 0;
-
- Iterator iterator = freeBuffer.iterator();
- while (iterator.hasNext()) {
- PooledConnection pooledConnection = iterator.next();
- if (pooledConnection.shouldTrim(usedSince, createdSince)) {
- iterator.remove();
- pooledConnection.closeConnectionFully(true);
- trimCount++;
- }
- }
-
- return trimCount;
- }
-
- /**
- * Collect the load statistics from all the free connections.
- */
- void collectStatistics(LoadValues values, boolean reset) {
-
- for (PooledConnection c : freeBuffer) {
- values.plus(c.getStatistics().getValues(reset));
- }
- }
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnection.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnection.java
deleted file mode 100644
index 2edbc9c02..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnection.java
+++ /dev/null
@@ -1,970 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-import java.sql.CallableStatement;
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-import java.sql.Savepoint;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.avaje.ebeaninternal.jdbc.ConnectionDelegator;
-
-/**
- * Is a connection that belongs to a DataSourcePool.
- *
- *
- * It is designed to be part of DataSourcePool. Closing the connection puts it
- * back into the pool.
- *
- *
- *
- * It defaults autoCommit and Transaction Isolation to the defaults of the
- * DataSourcePool.
- *
- *
- *
- * It has caching of Statements and PreparedStatements. Remembers the last
- * statement that was executed. Keeps statistics on how long it is in use.
- *
- */
-public class PooledConnection extends ConnectionDelegator {
-
- private static final Logger logger = LoggerFactory.getLogger(PooledConnection.class);
-
- private static final String IDLE_CONNECTION_ACCESSED_ERROR = "Pooled Connection has been accessed whilst idle in the pool, via method: ";
-
- /**
- * Marker for when connection is closed due to exceeding the max allowed age.
- */
- private static final String REASON_MAXAGE = "maxAge";
-
- /**
- * Marker for when connection is closed due to exceeding the max inactive time.
- */
- private static final String REASON_IDLE = "idleTime";
-
- /**
- * Marker for when the connection is closed due to a reset.
- */
- private static final String REASON_RESET = "reset";
-
- /**
- * Set when connection is idle in the pool. In general when in the pool the
- * connection should not be modified.
- */
- private static final int STATUS_IDLE = 88;
-
- /**
- * Set when connection given to client.
- */
- private static final int STATUS_ACTIVE = 89;
-
- /**
- * Set when commit() or rollback() called.
- */
- private static final int STATUS_ENDED = 87;
-
- /**
- * Name used to identify the PooledConnection for logging.
- */
- private final String name;
-
- /**
- * The pool this connection belongs to.
- */
- private final DataSourcePool pool;
-
- /**
- * The underlying connection.
- */
- private final Connection connection;
-
- /**
- * The time this connection was created.
- */
- private final long creationTime;
-
- /**
- * Cache of the PreparedStatements
- */
- private final PstmtCache pstmtCache;
-
- private final Object pstmtMonitor = new Object();
-
- /**
- * Helper for statistics collection.
- */
- private final PooledConnectionStatistics stats = new PooledConnectionStatistics();
-
- /**
- * The status of the connection. IDLE, ACTIVE or ENDED.
- */
- private int status = STATUS_IDLE;
-
- /**
- * The reason for a connection closing.
- */
- private String closeReason;
-
- /**
- * Set this to true if the connection will be busy for a long time.
- *
- * This means it should skip the suspected connection pool leak checking.
- *
- */
- private boolean longRunning;
-
- /**
- * Flag to indicate that this connection had errors and should be checked to
- * make sure it is okay.
- */
- private boolean hadErrors;
-
- /**
- * The last start time. When the connection was given to a thread.
- */
- private long startUseTime;
-
- /**
- * The last end time of this connection. This is to calculate the usage
- * time.
- */
- private long lastUseTime;
-
- private long exeStartNanos;
-
- /**
- * The last statement executed by this connection.
- */
- private String lastStatement;
-
- /**
- * The non avaje method that created the connection.
- */
- private String createdByMethod;
-
- /**
- * Used to find connection pool leaks.
- */
- private StackTraceElement[] stackTrace;
-
- private final int maxStackTrace;
-
- /**
- * Slot position in the BusyConnectionBuffer.
- */
- private int slotId;
-
- private boolean resetIsolationReadOnlyRequired;
-
-
- /**
- * Construct the connection that can refer back to the pool it belongs to.
- *
- * close() will return the connection back to the pool , while
- * closeDestroy() will close() the underlining connection properly.
- *
- */
- public PooledConnection(DataSourcePool pool, int uniqueId, Connection connection) {
- super(connection);
-
- this.pool = pool;
- this.connection = connection;
- this.name = pool.getName() + "." + uniqueId;
- this.pstmtCache = new PstmtCache(pool.getPstmtCacheSize());
- this.maxStackTrace = pool.getMaxStackTraceSize();
- this.creationTime = System.currentTimeMillis();
- this.lastUseTime = creationTime;
- }
-
- /**
- * For testing the pool without real connections.
- */
- protected PooledConnection(String name) {
- super(null);
- this.name = name;
- this.pool = null;
- this.connection = null;
- this.pstmtCache = null;
- this.maxStackTrace = 0;
- this.creationTime = System.currentTimeMillis();
- this.lastUseTime = creationTime;
- }
-
- /**
- * Return the slot position in the busy buffer.
- */
- int getSlotId() {
- return slotId;
- }
-
- /**
- * Set the slot position in the busy buffer.
- */
- void setSlotId(int slotId) {
- this.slotId = slotId;
- }
-
- /**
- * Return a string to identify the connection.
- */
- public String getName() {
- return name;
- }
-
- private String getNameSlot() {
- return name + ":" + slotId;
- }
-
- public String toString() {
- return getDescription();
- }
-
- private long getBusySeconds() {
- return (System.currentTimeMillis() - startUseTime) / 1000;
- }
-
- public String getDescription() {
- return "name[" + name + "] slot[" + slotId + "] startTime[" + getStartUseTime() + "] busySeconds[" + getBusySeconds() + "] createdBy[" + getCreatedByMethod() + "] stmt[" + getLastStatement() + "]";
- }
-
- String getFullDescription() {
- return "name[" + name + "] slot[" + slotId + "] startTime[" + getStartUseTime() + "] busySeconds[" + getBusySeconds() + "] stackTrace[" + getStackTraceAsString() + "] stmt[" + getLastStatement() + "]";
- }
-
- public PooledConnectionStatistics getStatistics() {
- return stats;
- }
-
- /**
- * Return true if the connection should be treated as long running (skip connection pool leak check).
- */
- boolean isLongRunning() {
- return longRunning;
- }
-
- /**
- * Set this to true if the connection is a long running connection and should skip the
- * 'suspected connection pool leak' checking.
- */
- public void setLongRunning(boolean longRunning) {
- this.longRunning = longRunning;
- }
-
- /**
- * Close the connection fully NOT putting in back into the pool.
- *
- * The logErrors parameter exists so that expected errors are not logged
- * such as when the database is known to be down.
- *
- *
- * @param logErrors if false then don't log errors when closing
- */
- void closeConnectionFully(boolean logErrors) {
-
- if (pool != null) {
- // allow collection of load statistics
- pool.reportClosingConnection(this);
- }
-
- if (logger.isDebugEnabled()) {
- logger.debug("Closing Connection[{}] slot[{}] reason[{}] stats: {} , pstmtStats: {} ", name, slotId, closeReason, stats.getValues(false), pstmtCache.getDescription());
- }
-
- try {
- if (connection.isClosed()) {
- // Typically the JDBC Driver has its own JVM shutdown hook and already
- // closed the connections in our DataSource pool so making this DEBUG level
- logger.debug("Closing Connection[{}] that is already closed?", name);
- return;
- }
- } catch (SQLException ex) {
- if (logErrors) {
- logger.error("Error checking if connection [" + getNameSlot() + "] is closed", ex);
- }
- }
-
- try {
- for (ExtendedPreparedStatement ps : pstmtCache.values()) {
- ps.closeDestroy();
- }
-
- } catch (SQLException ex) {
- if (logErrors) {
- logger.warn("Error when closing connection Statements", ex);
- }
- }
-
- try {
- connection.close();
- } catch (SQLException ex) {
- if (logErrors || logger.isDebugEnabled()) {
- logger.error("Error when fully closing connection [" + getFullDescription() + "]", ex);
- }
- }
- }
-
- /**
- * Creates a wrapper ExtendedStatement so that I can get the executed sql. I
- * want to do this so that I can get the slowest query statments etc, and
- * log that information.
- */
- public Statement createStatement() throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "createStatement()");
- }
- try {
- return connection.createStatement();
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- public Statement createStatement(int resultSetType, int resultSetConcurreny) throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "createStatement()");
- }
- try {
- return connection.createStatement(resultSetType, resultSetConcurreny);
-
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- /**
- * Return a PreparedStatement back into the cache.
- */
- void returnPreparedStatement(ExtendedPreparedStatement pstmt) {
-
- synchronized (pstmtMonitor) {
- if (!pstmtCache.returnStatement(pstmt)) {
- try {
- // Already an entry in the cache with the exact same SQL...
- pstmt.closeDestroy();
-
- } catch (SQLException e) {
- logger.error("Error closing Pstmt", e);
- }
- }
- }
- }
-
- /**
- * This will try to use a cache of PreparedStatements.
- */
- public PreparedStatement prepareStatement(String sql, int returnKeysFlag) throws SQLException {
- String cacheKey = sql + returnKeysFlag;
- return prepareStatement(sql, true, returnKeysFlag, cacheKey);
- }
-
- /**
- * This will try to use a cache of PreparedStatements.
- */
- public PreparedStatement prepareStatement(String sql) throws SQLException {
- return prepareStatement(sql, false, 0, sql);
- }
-
- /**
- * This will try to use a cache of PreparedStatements.
- */
- private PreparedStatement prepareStatement(String sql, boolean useFlag, int flag, String cacheKey) throws SQLException {
-
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "prepareStatement()");
- }
- try {
- synchronized (pstmtMonitor) {
- lastStatement = sql;
-
- // try to get a matching cached PStmt from the cache.
- ExtendedPreparedStatement pstmt = pstmtCache.remove(cacheKey);
-
- if (pstmt != null) {
- return pstmt;
- }
-
- // create a new PreparedStatement
- PreparedStatement actualPstmt;
- if (useFlag) {
- actualPstmt = connection.prepareStatement(sql, flag);
- } else {
- actualPstmt = connection.prepareStatement(sql);
- }
- return new ExtendedPreparedStatement(this, actualPstmt, sql, cacheKey);
- }
-
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurreny) throws SQLException {
-
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "prepareStatement()");
- }
- try {
- // no caching when creating PreparedStatements this way
- lastStatement = sql;
- return connection.prepareStatement(sql, resultSetType, resultSetConcurreny);
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- /**
- * Reset the connection for returning to the client. Resets the status,
- * startUseTime and hadErrors.
- */
- void resetForUse() {
- this.status = STATUS_ACTIVE;
- this.startUseTime = System.currentTimeMillis();
- this.exeStartNanos = System.nanoTime();
- this.createdByMethod = null;
- this.lastStatement = null;
- this.hadErrors = false;
- this.longRunning = false;
- }
-
- /**
- * When an error occurs during use add it the connection.
- *
- * Any PooledConnection that has an error is checked to make sure it works
- * before it is placed back into the connection pool.
- *
- */
- void markWithError() {
- hadErrors = true;
- }
-
- /**
- * close the connection putting it back into the connection pool.
- *
- * Note that to ensure that the next transaction starts at the correct time
- * a commit() or rollback() should be called. If neither has occured at this
- * time then a rollback() is used (to end the transaction).
- *
- *
- * To close the connection fully use closeConnectionFully().
- *
- */
- public void close() throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "close()");
- }
-
- long durationNanos = System.nanoTime() - exeStartNanos;
- stats.add(durationNanos, hadErrors);
-
- if (hadErrors) {
- if (!pool.validateConnection(this)) {
- // the connection is BAD, remove it, close it and test the pool
- pool.returnConnectionForceClose(this);
- return;
- }
- }
-
- try {
- // reset the autoCommit back if client code changed it
- if (connection.getAutoCommit() != pool.getAutoCommit()) {
- connection.setAutoCommit(pool.getAutoCommit());
- }
- // Generally resetting Isolation level seems expensive.
- // Hence using resetIsolationReadOnlyRequired flag
- // performance reasons.
- if (resetIsolationReadOnlyRequired) {
- resetIsolationReadOnly();
- resetIsolationReadOnlyRequired = false;
- }
-
- // the connection is assumed GOOD so put it back in the pool
- lastUseTime = System.currentTimeMillis();
- // connection.clearWarnings();
- status = STATUS_IDLE;
- pool.returnConnection(this);
-
- } catch (Exception ex) {
- // the connection is BAD, remove it, close it and test the pool
- logger.warn("Error when trying to return connection to pool, closing fully.", ex);
- pool.returnConnectionForceClose(this);
- }
- }
-
- private void resetIsolationReadOnly() throws SQLException {
- // reset the transaction isolation if the client code changed it
- //noinspection MagicConstant
- if (connection.getTransactionIsolation() != pool.getTransactionIsolation()) {
- //noinspection MagicConstant
- connection.setTransactionIsolation(pool.getTransactionIsolation());
- }
- // reset readonly to false
- if (connection.isReadOnly()) {
- connection.setReadOnly(false);
- }
- }
-
- protected void finalize() throws Throwable {
- try {
- if (connection != null && !connection.isClosed()) {
- // connect leak?
- logger.warn("Closing Connection on finalize() - {}", getFullDescription());
- closeConnectionFully(false);
- }
- } catch (Exception e) {
- logger.error("Error when finalize is closing a connection? (unexpected)", e);
- }
- super.finalize();
- }
-
- /**
- * Return true if the connection is too old.
- */
- private boolean exceedsMaxAge(long maxAgeMillis) {
- if (maxAgeMillis > 0 && (creationTime < (System.currentTimeMillis() - maxAgeMillis))) {
- this.closeReason = REASON_MAXAGE;
- return true;
- }
- return false;
- }
-
- boolean shouldTrimOnReturn(long lastResetTime, long maxAgeMillis) {
- if (creationTime <= lastResetTime) {
- this.closeReason = REASON_RESET;
- return true;
- }
- return exceedsMaxAge(maxAgeMillis);
- }
-
- /**
- * Return true if the connection has been idle for too long or is too old.
- */
- boolean shouldTrim(long usedSince, long createdSince) {
- if (lastUseTime < usedSince) {
- // been idle for too long so trim it
- this.closeReason = REASON_IDLE;
- return true;
- }
- if (createdSince > 0 && createdSince > creationTime) {
- // exceeds max age so trim it
- this.closeReason = REASON_MAXAGE;
- return true;
- }
- return false;
- }
-
- /**
- * Return the time the connection was passed to the client code.
- *
- * Used to detect busy connections that could be leaks.
- *
- */
- private long getStartUseTime() {
- return startUseTime;
- }
-
- /**
- * Returns the time the connection was last used.
- *
- * Used to close connections that have been idle for some time. Typically 5
- * minutes.
- *
- */
- long getLastUsedTime() {
- return lastUseTime;
- }
-
- /**
- * Returns the last sql statement executed.
- */
- private String getLastStatement() {
- return lastStatement;
- }
-
- /**
- * Called by ExtendedStatement to trace the sql being executed.
- *
- * Note with addBatch() this will not really work.
- *
- */
- void setLastStatement(String lastStatement) {
- this.lastStatement = lastStatement;
- if (logger.isTraceEnabled()) {
- logger.trace(".setLastStatement[" + lastStatement + "]");
- }
- }
-
-
- /**
- * Also note the read only status needs to be reset when put back into the
- * pool.
- */
- public void setReadOnly(boolean readOnly) throws SQLException {
- // A bit loose not checking for STATUS_IDLE
- // if (status == STATUS_IDLE) {
- // throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR +
- // "setReadOnly()");
- // }
- resetIsolationReadOnlyRequired = true;
- connection.setReadOnly(readOnly);
- }
-
- /**
- * Also note the Isolation level needs to be reset when put back into the
- * pool.
- */
- public void setTransactionIsolation(int level) throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "setTransactionIsolation()");
- }
- try {
- resetIsolationReadOnlyRequired = true;
- connection.setTransactionIsolation(level);
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- //
- //
- // Simple wrapper methods which pass a method call onto the acutal
- // connection object. These methods are safe-guarded to prevent use of
- // the methods whilst the connection is in the connection pool.
- //
- //
- public void clearWarnings() throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "clearWarnings()");
- }
- connection.clearWarnings();
- }
-
- public void commit() throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "commit()");
- }
- try {
- status = STATUS_ENDED;
- connection.commit();
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- public boolean getAutoCommit() throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "getAutoCommit()");
- }
- return connection.getAutoCommit();
- }
-
- public String getCatalog() throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "getCatalog()");
- }
- return connection.getCatalog();
- }
-
- public DatabaseMetaData getMetaData() throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "getMetaData()");
- }
- return connection.getMetaData();
- }
-
- public int getTransactionIsolation() throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "getTransactionIsolation()");
- }
- return connection.getTransactionIsolation();
- }
-
- public Map> getTypeMap() throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "getTypeMap()");
- }
- return connection.getTypeMap();
- }
-
- public SQLWarning getWarnings() throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "getWarnings()");
- }
- return connection.getWarnings();
- }
-
- public boolean isClosed() throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "isClosed()");
- }
- return connection.isClosed();
- }
-
- public boolean isReadOnly() throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "isReadOnly()");
- }
- return connection.isReadOnly();
- }
-
- public String nativeSQL(String sql) throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "nativeSQL()");
- }
- lastStatement = sql;
- return connection.nativeSQL(sql);
- }
-
- public CallableStatement prepareCall(String sql) throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "prepareCall()");
- }
- lastStatement = sql;
- return connection.prepareCall(sql);
- }
-
- public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurreny) throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "prepareCall()");
- }
- lastStatement = sql;
- return connection.prepareCall(sql, resultSetType, resultSetConcurreny);
- }
-
- public void rollback() throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "rollback()");
- }
- try {
- status = STATUS_ENDED;
- connection.rollback();
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- public void setAutoCommit(boolean autoCommit) throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "setAutoCommit()");
- }
- try {
- connection.setAutoCommit(autoCommit);
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- public void setCatalog(String catalog) throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "setCatalog()");
- }
- connection.setCatalog(catalog);
- }
-
- public void setTypeMap(Map> map) throws SQLException {
- if (status == STATUS_IDLE) {
- throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "setTypeMap()");
- }
- connection.setTypeMap(map);
- }
-
- public Savepoint setSavepoint() throws SQLException {
- try {
- return connection.setSavepoint();
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- public Savepoint setSavepoint(String savepointName) throws SQLException {
- try {
- return connection.setSavepoint(savepointName);
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- public void rollback(Savepoint sp) throws SQLException {
- try {
- connection.rollback(sp);
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- public void releaseSavepoint(Savepoint sp) throws SQLException {
- try {
- connection.releaseSavepoint(sp);
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- public void setHoldability(int i) throws SQLException {
- try {
- connection.setHoldability(i);
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- public int getHoldability() throws SQLException {
- try {
- return connection.getHoldability();
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- public Statement createStatement(int i, int x, int y) throws SQLException {
- try {
- return connection.createStatement(i, x, y);
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- public PreparedStatement prepareStatement(String s, int i, int x, int y) throws SQLException {
- try {
- return connection.prepareStatement(s, i, x, y);
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- public PreparedStatement prepareStatement(String s, int[] i) throws SQLException {
- try {
- return connection.prepareStatement(s, i);
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- public PreparedStatement prepareStatement(String s, String[] s2) throws SQLException {
- try {
- return connection.prepareStatement(s, s2);
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- public CallableStatement prepareCall(String s, int i, int x, int y) throws SQLException {
- try {
- return connection.prepareCall(s, i, x, y);
- } catch (SQLException ex) {
- markWithError();
- throw ex;
- }
- }
-
- /**
- * Returns the method that created the connection.
- *
- * Used to help finding connection pool leaks.
- *
- */
- private String getCreatedByMethod() {
- if (createdByMethod != null) {
- return createdByMethod;
- }
- if (stackTrace == null) {
- return null;
- }
-
- for (int j = 0; j < stackTrace.length; j++) {
- String methodLine = stackTrace[j].toString();
- if (!skipElement(methodLine)) {
- createdByMethod = methodLine;
- return createdByMethod;
- }
- }
-
- return null;
- }
-
- private boolean skipElement(String methodLine) {
- if (methodLine.startsWith("java.lang.")) {
- return true;
- } else if (methodLine.startsWith("java.util.")) {
- return true;
- } else if (methodLine.startsWith("com.avaje.ebeaninternal.server.query.CallableQuery.")) {
- // creating connection on future...
- return true;
- } else if (methodLine.startsWith("com.avaje.ebeaninternal.server.query.Callable")) {
- // it is a future task being executed...
- return false;
- } else {
- return methodLine.startsWith("com.avaje.ebeaninternal");
- }
- }
-
- /**
- * Set the stack trace to help find connection pool leaks.
- */
- protected void setStackTrace(StackTraceElement[] stackTrace) {
- this.stackTrace = stackTrace;
- }
-
- /**
- * Return the stackTrace as a String for logging purposes.
- */
- private String getStackTraceAsString() {
- StackTraceElement[] stackTrace = getStackTrace();
- if (stackTrace == null) {
- return "";
- }
- return Arrays.toString(stackTrace);
- }
-
- /**
- * Return the full stack trace that got the connection from the pool. You
- * could use this if getCreatedByMethod() doesn't work for you.
- */
- public StackTraceElement[] getStackTrace() {
-
- if (stackTrace == null) {
- return null;
- }
-
- // filter off the top of the stack that we are not interested in
- ArrayList filteredList = new ArrayList();
- boolean include = false;
- for (int i = 0; i < stackTrace.length; i++) {
- if (!include && !skipElement(stackTrace[i].toString())) {
- include = true;
- }
- if (include && filteredList.size() < maxStackTrace) {
- filteredList.add(stackTrace[i]);
- }
- }
- return filteredList.toArray(new StackTraceElement[filteredList.size()]);
-
- }
-
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnectionQueue.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnectionQueue.java
deleted file mode 100644
index 3f7818d6f..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnectionQueue.java
+++ /dev/null
@@ -1,532 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-import java.sql.SQLException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool.Status;
-import com.avaje.ebeaninternal.server.lib.sql.PooledConnectionStatistics.LoadValues;
-
-public class PooledConnectionQueue {
-
- private static final Logger logger = LoggerFactory.getLogger(PooledConnectionQueue.class);
-
- private static final TimeUnit MILLIS_TIME_UNIT = TimeUnit.MILLISECONDS;
-
- private final String name;
-
- private final DataSourcePool pool;
-
- /**
- * A 'circular' buffer designed specifically for free connections.
- */
- private final FreeConnectionBuffer freeList;
-
- /**
- * A 'slots' buffer designed specifically for busy connections.
- * Fast add remove based on slot id.
- */
- private final BusyConnectionBuffer busyList;
-
- /**
- * Load statistics collected off connections that have closed fully (left the pool).
- */
- private final PooledConnectionStatistics collectedStats = new PooledConnectionStatistics();
-
- /**
- * Currently accumulated load statistics.
- */
- private LoadValues accumulatedValues = new LoadValues();
-
- /**
- * Main lock guarding all access
- */
- private final ReentrantLock lock;
-
- /**
- * Condition for threads waiting to take a connection
- */
- private final Condition notEmpty;
-
- private int connectionId;
-
- private final long waitTimeoutMillis;
-
- private final long leakTimeMinutes;
-
- private final long maxAgeMillis;
-
- private int warningSize;
-
- private int maxSize;
-
- private int minSize;
-
- /**
- * Number of threads in the wait queue.
- */
- private int waitingThreads;
-
- /**
- * Number of times a thread had to wait.
- */
- private int waitCount;
-
- /**
- * Number of times a connection was got from this queue.
- */
- private int hitCount;
-
- /**
- * The high water mark for the queue size.
- */
- private int highWaterMark;
-
- /**
- * Last time the pool was reset. Used to close busy connections as they are
- * returned to the pool that where created prior to the lastResetTime.
- */
- private long lastResetTime;
-
- private boolean doingShutdown;
-
- public PooledConnectionQueue(DataSourcePool pool) {
-
- this.pool = pool;
- this.name = pool.getName();
- this.minSize = pool.getMinSize();
- this.maxSize = pool.getMaxSize();
-
- this.warningSize = pool.getWarningSize();
- this.waitTimeoutMillis = pool.getWaitTimeoutMillis();
- this.leakTimeMinutes = pool.getLeakTimeMinutes();
- this.maxAgeMillis = pool.getMaxAgeMillis();
-
- this.busyList = new BusyConnectionBuffer(maxSize, 20);
- this.freeList = new FreeConnectionBuffer();
-
- this.lock = new ReentrantLock(false);
- this.notEmpty = lock.newCondition();
- }
-
- private Status createStatus() {
- return new Status(name, minSize, maxSize, freeList.size(), busyList.size(), waitingThreads, highWaterMark, waitCount, hitCount);
- }
-
- public String toString() {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- return createStatus().toString();
- } finally {
- lock.unlock();
- }
- }
-
- /**
- * Collect statistics of a connection that is fully closing
- */
- void reportClosingConnection(PooledConnection pooledConnection) {
-
- collectedStats.add(pooledConnection.getStatistics());
- }
-
- public DataSourcePoolStatistics getStatistics(boolean reset) {
-
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
-
- LoadValues aggregate = collectedStats.getValues(reset);
-
- freeList.collectStatistics(aggregate, reset);
- busyList.collectStatistics(aggregate, reset);
-
- aggregate.plus(accumulatedValues);
-
- this.accumulatedValues = (reset) ? new LoadValues() : aggregate;
-
- return new DataSourcePoolStatistics(aggregate.getCollectionStart(), aggregate.getCount(), aggregate.getErrorCount(), aggregate.getHwmMicros(), aggregate.getTotalMicros());
-
- } finally {
- lock.unlock();
- }
- }
-
- public Status getStatus(boolean reset) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- Status s = createStatus();
- if (reset) {
- highWaterMark = busyList.size();
- hitCount = 0;
- waitCount = 0;
- }
- return s;
- } finally {
- lock.unlock();
- }
- }
-
- void setMinSize(int minSize) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- if (minSize > this.maxSize) {
- throw new IllegalArgumentException("minSize " + minSize + " > maxSize " + this.maxSize);
- }
- this.minSize = minSize;
- } finally {
- lock.unlock();
- }
- }
-
- void setMaxSize(int maxSize) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- if (maxSize < this.minSize) {
- throw new IllegalArgumentException("maxSize " + maxSize + " < minSize " + this.minSize);
- }
- this.busyList.setCapacity(maxSize);
- this.maxSize = maxSize;
- } finally {
- lock.unlock();
- }
- }
-
- void setWarningSize(int warningSize) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- if (warningSize > this.maxSize) {
- throw new IllegalArgumentException("warningSize " + warningSize + " > maxSize " + this.maxSize);
- }
- this.warningSize = warningSize;
- } finally {
- lock.unlock();
- }
- }
-
- private int totalConnections() {
- return freeList.size() + busyList.size();
- }
-
- void ensureMinimumConnections() throws SQLException {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- int add = minSize - totalConnections();
- if (add > 0) {
- for (int i = 0; i < add; i++) {
- PooledConnection c = pool.createConnectionForQueue(connectionId++);
- freeList.add(c);
- }
- notEmpty.signal();
- }
-
- } finally {
- lock.unlock();
- }
- }
-
- /**
- * Return a PooledConnection.
- */
- void returnPooledConnection(PooledConnection c, boolean forceClose) {
-
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- if (!busyList.remove(c)) {
- logger.error("Connection [{}] not found in BusyList? ", c);
- }
- if (forceClose || c.shouldTrimOnReturn(lastResetTime, maxAgeMillis)) {
- c.closeConnectionFully(false);
-
- } else {
- freeList.add(c);
- notEmpty.signal();
- }
- } finally {
- lock.unlock();
- }
- }
-
- private PooledConnection extractFromFreeList() {
- PooledConnection c = freeList.remove();
- registerBusyConnection(c);
- return c;
- }
-
- PooledConnection getPooledConnection() throws SQLException {
-
- try {
- PooledConnection pc = _getPooledConnection();
- pc.resetForUse();
- return pc;
-
- } catch (InterruptedException e) {
- String msg = "Interrupted getting connection from pool " + e;
- throw new SQLException(msg);
- }
- }
-
- /**
- * Register the PooledConnection with the busyList.
- */
- private int registerBusyConnection(PooledConnection c) {
- int busySize = busyList.add(c);
- if (busySize > highWaterMark) {
- highWaterMark = busySize;
- }
- return busySize;
- }
-
- private PooledConnection _getPooledConnection() throws InterruptedException, SQLException {
- final ReentrantLock lock = this.lock;
- lock.lockInterruptibly();
- try {
- if (doingShutdown) {
- throw new SQLException("Trying to access the Connection Pool when it is shutting down");
- }
-
- // this includes attempts that fail with InterruptedException
- // or SQLException but that is ok as its only an indicator
- hitCount++;
-
- // are other threads already waiting? (they get priority)
- if (waitingThreads == 0) {
-
- if (!freeList.isEmpty()) {
- // we have a free connection to return
- return extractFromFreeList();
- }
-
- if (busyList.size() < maxSize) {
- // grow the connection pool
- PooledConnection c = pool.createConnectionForQueue(connectionId++);
- int busySize = registerBusyConnection(c);
-
- if (logger.isDebugEnabled()) {
- logger.debug("DataSourcePool [{}] grow; id[{}] busy[{}] max[{}]", name, c.getName(), busySize, maxSize);
- }
- checkForWarningSize();
- return c;
- }
- }
-
- try {
- // The pool is at maximum size. We are going to go into
- // a wait loop until connections are returned into the pool.
- waitCount++;
- waitingThreads++;
- return _getPooledConnectionWaitLoop();
- } finally {
- waitingThreads--;
- }
-
- } finally {
- lock.unlock();
- }
- }
-
- /**
- * Got into a loop waiting for connections to be returned to the pool.
- */
- private PooledConnection _getPooledConnectionWaitLoop() throws SQLException, InterruptedException {
-
- long nanos = MILLIS_TIME_UNIT.toNanos(waitTimeoutMillis);
- for (; ; ) {
-
- if (nanos <= 0) {
- String msg = "Unsuccessfully waited [" + waitTimeoutMillis + "] millis for a connection to be returned."
- + " No connections are free. You need to Increase the max connections of [" + maxSize + "]"
- + " or look for a connection pool leak using datasource.xxx.capturestacktrace=true";
- if (pool.isCaptureStackTrace()) {
- dumpBusyConnectionInformation();
- }
-
- throw new SQLException(msg);
- }
-
- try {
- nanos = notEmpty.awaitNanos(nanos);
- if (!freeList.isEmpty()) {
- // successfully waited
- return extractFromFreeList();
- }
- } catch (InterruptedException ie) {
- notEmpty.signal(); // propagate to non-interrupted thread
- throw ie;
- }
- }
- }
-
- public void shutdown() {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- doingShutdown = true;
- Status status = createStatus();
- DataSourcePoolStatistics statistics = pool.getStatistics(false);
- logger.debug("DataSourcePool [{}] shutdown {} - Statistics {}", name, status, statistics);
-
- closeFreeConnections(true);
-
- if (!busyList.isEmpty()) {
- logger.warn("Closing busy connections on shutdown size: " + busyList.size());
- dumpBusyConnectionInformation();
- closeBusyConnections(0);
- }
- } finally {
- lock.unlock();
- }
- }
-
- /**
- * Close all the connections in the pool and any current busy connections
- * when they are returned. New connections will be then created on demand.
- *
- * This is typically done when a database down event occurs.
- *
- */
- public void reset(long leakTimeMinutes) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- Status status = createStatus();
- logger.info("Reseting DataSourcePool [{}] {}", name, status);
- lastResetTime = System.currentTimeMillis();
-
- closeFreeConnections(false);
- closeBusyConnections(leakTimeMinutes);
-
- logger.info("Busy Connections:\n" + getBusyConnectionInformation());
-
- } finally {
- lock.unlock();
- }
- }
-
- public void trim(long maxInactiveMillis, long maxAgeMillis) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- if (trimInactiveConnections(maxInactiveMillis, maxAgeMillis) > 0) {
- try {
- ensureMinimumConnections();
- } catch (SQLException e) {
- logger.error("Error trying to ensure minimum connections", e);
- }
- }
- } finally {
- lock.unlock();
- }
- }
-
- /**
- * Trim connections that have been not used for some time.
- */
- private int trimInactiveConnections(long maxInactiveMillis, long maxAgeMillis) {
-
- long usedSince = System.currentTimeMillis() - maxInactiveMillis;
- long createdSince = (maxAgeMillis == 0) ? 0 : System.currentTimeMillis() - maxAgeMillis;
-
- int trimedCount = freeList.trim(usedSince, createdSince);
- if (trimedCount > 0) {
- logger.debug("DataSourcePool [{}] trimmed [{}] inactive connections. New size[{}]", name, trimedCount, totalConnections());
- }
- return trimedCount;
- }
-
- /**
- * Close all the connections that are in the free list.
- */
- private void closeFreeConnections(boolean logErrors) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- freeList.closeAll(logErrors);
- } finally {
- lock.unlock();
- }
- }
-
- /**
- * Close any busy connections that have not been used for some time.
- *
- * These connections are considered to have leaked from the connection pool.
- *
- *
- * Connection leaks occur when code doesn't ensure that connections are
- * closed() after they have been finished with. There should be an
- * appropriate try catch finally block to ensure connections are always
- * closed and put back into the pool.
- *
- */
- void closeBusyConnections(long leakTimeMinutes) {
-
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- busyList.closeBusyConnections(leakTimeMinutes);
- } finally {
- lock.unlock();
- }
- }
-
- /**
- * As the pool grows it gets closer to the maxConnections limit. We can send
- * an Alert (or warning) as we get close to this limit and hence an
- * Administrator could increase the pool size if desired.
- *
- * This is called whenever the pool grows in size (towards the max limit).
- *
- */
- private void checkForWarningSize() {
-
- // the the total number of connections that we can add
- // to the pool before it hits the maximum
- int availableGrowth = (maxSize - totalConnections());
-
- if (availableGrowth < warningSize) {
-
- closeBusyConnections(leakTimeMinutes);
-
- String msg = "DataSourcePool [" + name + "] is [" + availableGrowth + "] connections from its maximum size.";
- pool.notifyWarning(msg);
- }
- }
-
- String getBusyConnectionInformation() {
- return getBusyConnectionInformation(false);
- }
-
- void dumpBusyConnectionInformation() {
- getBusyConnectionInformation(true);
- }
-
- /**
- * Returns information describing connections that are currently being used.
- */
- private String getBusyConnectionInformation(boolean toLogger) {
-
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
-
- return busyList.getBusyConnectionInformation(toLogger);
-
- } finally {
- lock.unlock();
- }
- }
-
-}
-
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnectionStatistics.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnectionStatistics.java
deleted file mode 100644
index dd4e96daf..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnectionStatistics.java
+++ /dev/null
@@ -1,160 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * Collects load statistics for a PooledConnection.
- */
-class PooledConnectionStatistics {
-
- private final AtomicLong count = new AtomicLong();
-
- private final AtomicLong errorCount = new AtomicLong();
-
- private final AtomicLong hwmNanos = new AtomicLong();
-
- private final AtomicLong totalNanos = new AtomicLong();
-
- private final AtomicLong collectionStart;
-
- PooledConnectionStatistics() {
- this.collectionStart = new AtomicLong(System.currentTimeMillis());
- }
-
- /**
- * Add statistics from another collector.
- */
- public void add(PooledConnectionStatistics other) {
-
- errorCount.addAndGet(other.getErrorCount());
- totalNanos.addAndGet(other.totalNanos.get());
- count.addAndGet(other.getCount());
-
- final long otherHwm = other.hwmNanos.get();
- if (otherHwm > hwmNanos.get()) {
- hwmNanos.set(otherHwm);
- }
- }
-
- /**
- * Add some time duration to the statistics.
- */
- public void add(long durationNanos, boolean hasError) {
-
- // This will be done in pretty much single threaded fashion
- // as the Connections generally are not shared across threads
-
- if (hasError) {
- errorCount.incrementAndGet();
- }
- count.incrementAndGet();
- totalNanos.addAndGet(durationNanos);
- if (durationNanos > hwmNanos.get()) {
- hwmNanos.set(durationNanos);
- }
- }
-
- public String toString() {
- return "count[" + count + "] errors[" + errorCount + "] totalMicros[" + getTotalMicros() + "] hwmMicros[" + getHwmMicros() + "]";
- }
-
- public long getCollectionStart() {
- return collectionStart.get();
- }
-
- public long getCount() {
- return count.get();
- }
-
- private long getErrorCount() {
- return errorCount.get();
- }
-
- private long getTotalMicros() {
- return TimeUnit.MICROSECONDS.convert(totalNanos.get(), TimeUnit.NANOSECONDS);
- }
-
- private long getHwmMicros() {
- return TimeUnit.MICROSECONDS.convert(hwmNanos.get(), TimeUnit.NANOSECONDS);
- }
-
- /**
- * Get the current values and reset the statistics if necessary.
- */
- LoadValues getValues(boolean reset) {
- LoadValues value = new LoadValues(collectionStart.get(), count.get(), errorCount.get(), getHwmMicros(), getTotalMicros());
- if (reset) {
- count.set(0);
- errorCount.set(0);
- hwmNanos.set(0);
- totalNanos.set(0);
- collectionStart.set(System.currentTimeMillis());
- }
- return value;
- }
-
- /**
- * Values representing the load or activity of a PooledConnection.
- *
- * These are aggregated up to get a total for the DataSourcePool.
- *
- */
- static class LoadValues {
-
- private long collectionStart;
- private long count;
- private long errorCount;
- private long hwmMicros;
- private long totalMicros;
-
- LoadValues() {
- }
-
- LoadValues(long collectionStart, long count, long errorCount, long hwmMicros, long totalMicros) {
- this.collectionStart = collectionStart;
- this.count = count;
- this.errorCount = errorCount;
- this.hwmMicros = hwmMicros;
- this.totalMicros = totalMicros;
- }
-
- public void plus(LoadValues additional) {
- collectionStart = (collectionStart == 0) ? additional.collectionStart : Math.min(collectionStart, additional.collectionStart);
- count += additional.count;
- errorCount += additional.errorCount;
- hwmMicros = Math.max(hwmMicros, additional.hwmMicros);
- totalMicros += additional.totalMicros;
- }
-
- public String toString() {
- return "count[" + count + "] errors[" + errorCount + "] totalMicros[" + totalMicros + "] hwmMicros[" + hwmMicros + "] avgMicros[" + getAvgMicros() + "]";
- }
-
- long getCollectionStart() {
- return collectionStart;
- }
-
- public long getCount() {
- return count;
- }
-
- long getErrorCount() {
- return errorCount;
- }
-
- long getHwmMicros() {
- return hwmMicros;
- }
-
- long getTotalMicros() {
- return totalMicros;
- }
-
- long getAvgMicros() {
- return (count == 0) ? 0 : totalMicros / count;
- }
- }
-
-
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PstmtCache.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PstmtCache.java
deleted file mode 100644
index 64b3cd894..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PstmtCache.java
+++ /dev/null
@@ -1,176 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.sql.SQLException;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/**
- * A LRU based cache for PreparedStatements.
- */
-class PstmtCache extends LinkedHashMap {
-
- private static final Logger logger = LoggerFactory.getLogger(PstmtCache.class);
-
- static final long serialVersionUID = -3096406924865550697L;
-
- /**
- * The maximum size of the cache. When this is exceeded the oldest entry is removed.
- */
- private final int maxSize;
-
- /**
- * The total number of entries removed from this cache.
- */
- private int removeCounter;
-
- /**
- * The number of get hits.
- */
- private int hitCounter;
-
- /**
- * The number of get() misses.
- */
- private int missCounter;
-
- /**
- * The number of puts into this cache.
- */
- private int putCounter;
-
- PstmtCache(int maxCacheSize) {
- // note = access ordered list. This is what gives it the LRU order
- super(maxCacheSize * 3, 0.75f, true);
- this.maxSize = maxCacheSize;
- }
-
- /**
- * Return a summary description of this cache.
- */
- public String getDescription() {
- return "size[" + size() + "] max[" + maxSize + "] hits[" + hitCounter + "] miss[" + missCounter + "] hitRatio[" + getHitRatio() + "] removes[" + removeCounter + "]";
- }
-
- /**
- * returns the current maximum size of the cache.
- */
- public int getMaxSize() {
- return maxSize;
- }
-
- /**
- * Gets the hit ratio. A number between 0 and 100 indicating the number of
- * hits to misses. A number approaching 100 is desirable.
- */
- private int getHitRatio() {
- if (hitCounter == 0) {
- return 0;
- } else {
- return hitCounter * 100 / (hitCounter + missCounter);
- }
- }
-
- /**
- * The total number of hits against this cache.
- */
- public int getHitCounter() {
- return hitCounter;
- }
-
- /**
- * The total number of misses against this cache.
- */
- public int getMissCounter() {
- return missCounter;
- }
-
- /**
- * The total number of puts against this cache.
- */
- public int getPutCounter() {
- return putCounter;
- }
-
- /**
- * Try to add the returning statement to the cache. If there is already a
- * matching ExtendedPreparedStatement in the cache return false else add
- * the statement to the cache and return true.
- */
- boolean returnStatement(ExtendedPreparedStatement pstmt) {
-
- ExtendedPreparedStatement alreadyInCache = super.get(pstmt.getCacheKey());
- if (alreadyInCache != null) {
- return false;
- }
- // add the returning prepared statement to the cache.
- // Note that the LRUCache will automatically close fully old unused
- // PStmts when the cache has hit its maximum size.
- put(pstmt.getCacheKey(), pstmt);
- return true;
- }
-
- /**
- * additionally maintains hit and miss statistics.
- */
- public ExtendedPreparedStatement get(Object key) {
-
- ExtendedPreparedStatement o = super.get(key);
- if (o == null) {
- missCounter++;
- } else {
- hitCounter++;
- }
- return o;
- }
-
- /**
- * additionally maintains hit and miss statistics.
- */
- public ExtendedPreparedStatement remove(Object key) {
-
- ExtendedPreparedStatement o = super.remove(key);
- if (o == null) {
- missCounter++;
- } else {
- hitCounter++;
- }
- return o;
- }
-
- /**
- * additionally maintains put counter statistics.
- */
- public ExtendedPreparedStatement put(String key, ExtendedPreparedStatement value) {
-
- putCounter++;
- return super.put(key, value);
- }
-
- /**
- * will check to see if we need to remove entries and
- * if so call the cacheCleanup.cleanupEldestLRUCacheEntry() if
- * one has been set.
- */
- protected boolean removeEldestEntry(Map.Entry eldest) {
-
- if (size() < maxSize) {
- return false;
- }
-
- removeCounter++;
-
- try {
- ExtendedPreparedStatement pstmt = eldest.getValue();
- pstmt.closeDestroy();
- } catch (SQLException e) {
- logger.error("Error closing ExtendedPreparedStatement", e);
- }
- return true;
- }
-
-
-}
-
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/SimpleDataSourceAlert.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/SimpleDataSourceAlert.java
deleted file mode 100644
index 03af1d41e..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/SimpleDataSourceAlert.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-import com.avaje.ebeaninternal.server.lib.util.MailEvent;
-import com.avaje.ebeaninternal.server.lib.util.MailListener;
-import com.avaje.ebeaninternal.server.lib.util.MailMessage;
-import com.avaje.ebeaninternal.server.lib.util.MailSender;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A simple smtp email alert that sends a email message on dataSourceDown and
- * dataSourceUp etc.
- *
- * - alert.fromuser = the from user name
- *
- alert.fromemail = the from email account
- *
- alert.toemail = comma delimited list of email accounts to email
- *
- alert.mailserver = the smpt server name
- *
- */
-public class SimpleDataSourceAlert implements DataSourceAlert, MailListener {
-
- private static final Logger logger = LoggerFactory.getLogger(SimpleDataSourceAlert.class);
-
- private static final String alertMailServerName = System.getProperty("ebean.datasource.alert.mailserver");
-
- private static final String fromUser = System.getProperty("ebean.datasource.alert.fromUser");
- private static final String fromEmail = System.getProperty("ebean.datasource.alert.fromEmail");
- private static final String toEmail = System.getProperty("ebean.datasource.alert.toEmail");
-
- /**
- * Create a SimpleAlerter.
- */
- public SimpleDataSourceAlert() {
- }
-
- /**
- * If the email failed then log the error.
- */
- public void handleEvent(MailEvent event) {
- Throwable e = event.getError();
- if (e != null) {
- logger.error(null, e);
- }
- }
-
- /**
- * Send the dataSource down alert.
- */
- @Override
- public void dataSourceDown(String dataSourceName) {
- String msg = getSubject(true, dataSourceName);
- sendMessage(msg, msg);
- }
-
- /**
- * Send the dataSource up alert.
- */
- @Override
- public void dataSourceUp(String dataSourceName) {
- String msg = getSubject(false, dataSourceName);
- sendMessage(msg, msg);
- }
-
- /**
- * Send the warning message.
- */
- @Override
- public void dataSourceWarning(String subject, String msg) {
- sendMessage(subject, msg);
- }
-
- private String getSubject(boolean isDown, String dsName) {
- String msg = "The DataSource " + dsName;
- if (isDown) {
- msg += " is DOWN!!";
- } else {
- msg += " is UP.";
- }
- return msg;
- }
-
- private void sendMessage(String subject, String msg) {
-
- if (alertMailServerName == null) {
- return;
- }
-
- MailMessage data = new MailMessage();
- data.setSender(fromUser, fromEmail);
- data.addBodyLine(msg);
- data.setSubject(subject);
-
- String[] toList = toEmail.split(",");
- if (toList.length == 0) {
- logger.error("alert.toemail has not been set?");
- } else {
- for (int i = 0; i < toList.length; i++) {
- data.addRecipient(null, toList[i].trim());
- }
- MailSender sender = new MailSender(alertMailServerName);
- sender.setMailListener(this);
- sender.sendInBackground(data);
- }
- }
-
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/TransactionIsolation.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/TransactionIsolation.java
deleted file mode 100644
index bbc7becb9..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/TransactionIsolation.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-import java.sql.Connection;
-
-/**
- * Helper object that can convert between transaction isolation descriptions and values.
- */
-class TransactionIsolation {
-
- /**
- * Return the string description of the transaction isolation level specified.
- * Returned value is one of NONE, READ_COMMITTED,READ_UNCOMMITTED,
- * REPEATABLE_READ or SERIALIZABLE.
- *
- * @param level the transaction isolation level as per java.sql.Connection
- * @return the level description as a string.
- */
- static String getLevelDescription(int level) {
- switch (level) {
- case Connection.TRANSACTION_NONE:
- return "NONE";
- case Connection.TRANSACTION_READ_COMMITTED:
- return "READ_COMMITTED";
- case Connection.TRANSACTION_READ_UNCOMMITTED:
- return "READ_UNCOMMITTED";
- case Connection.TRANSACTION_REPEATABLE_READ:
- return "REPEATABLE_READ";
- case Connection.TRANSACTION_SERIALIZABLE:
- return "SERIALIZABLE";
- case -1:
- return "NotSet";
- default:
- throw new RuntimeException("Transaction Isolaction level [" + level + "] is not defined.");
- }
- }
-
-
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/message.properties b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/message.properties
deleted file mode 100644
index 8fe526f32..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/message.properties
+++ /dev/null
@@ -1,20 +0,0 @@
-FATAL_ERROR=ERROR: A fatal error has occured. Check the error log. {0}
-DATASOURCE_OK=DataSource {0} working ok.
-SHUTTING_DOWN=DataSource shutdown all datasources in [{0}]
-SHUT_DOWN_FINISHED=DataSource shutdown has finished.
-CANT_FIND_PROPS=ERROR: Can't find the datasource props file.
-ERROR_CREATING_FACTORY=ERROR: An error occured when creating the DataSourceFactory {0}.
-CANT_SHUTDOWN_TYPE=WARN: Can't shutdown DataSource objects of this type {0}.
-
-DB_DRIVER_NOTFOUND=ERROR: The JDBC Driver {0} can't be found.
-POOL_IN_SHUTDOWN=ERROR: Trying to use the pool while it is shutting down.
-WAIT_TIME_EXCEEDED=ERROR: Wait time {0} for connection exceeded. {1}.
-SHUTDOWN_START=DataSource [{0}] Shutting down.
-SHUTDOWN_LEAK=A Connection leak has been detected on shutdown {0}.
-SHUTDOWN_END=DataSource [{0}] Shutdown ended.
-METHOD_NOT_SUPPORTED=ERROR: this method is not supported.
-SET_ALERT=WARN: Alert {0} has been set.
-MISSING_PARAMETER=ERROR: A parameter {0} is missing from the props file.
-IDLE_CONNECTION_ACCESSED=Pooled Connection has been accessed whilst idle in the pool, via method:
-
-DEFAULT_DS_NOT_SPECIFIED=ERROR: No default dataSource has been specified.
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/package.html b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/package.html
deleted file mode 100644
index 6c537f2a6..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/package.html
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
- AvajeLib
-
-
-Enhanced JDBC objects and connection pool.
-
-Provides Database meta data objects, Robust connection pooling, PreparedStatement Caching.
-
-
-
\ No newline at end of file
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/util/MailAddress.java b/src/main/java/com/avaje/ebeaninternal/server/lib/util/MailAddress.java
deleted file mode 100644
index 571014f31..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/util/MailAddress.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.util;
-
-/**
- * An Email address with an associated alias.
- */
-public class MailAddress {
-
-
- final String alias;
-
- final String emailAddress;
-
- /**
- * Create an address with an optional alias.
- */
- public MailAddress(String alias, String emailAddress) {
- this.alias = alias;
- this.emailAddress = emailAddress;
- }
-
- /**
- * Return the alias.
- * If the alias is null this returns an empty string.
- */
- public String getAlias() {
- if (alias == null) {
- return "";
- }
- return alias;
- }
-
- /**
- * Return the email address.
- */
- public String getEmailAddress() {
- return emailAddress;
- }
-
- public String toString() {
- return getAlias() + " " + "<" + getEmailAddress() + ">";
- }
-
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/util/MailEvent.java b/src/main/java/com/avaje/ebeaninternal/server/lib/util/MailEvent.java
deleted file mode 100644
index 413c63966..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/util/MailEvent.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.util;
-
-/**
- * Represents the success or failure of a mail send.
- */
-public class MailEvent {
-
-
- /**
- * The error indicating a send failure.
- */
- final Throwable error;
-
- /**
- * The message that was sent.
- */
- final MailMessage message;
-
-
- /**
- * The message send failed with an error.
- */
- public MailEvent(MailMessage message, Throwable error) {
- this.message = message;
- this.error = error;
- }
-
- /**
- * The message that we attempted to send.
- */
- public MailMessage getMailMessage() {
- return message;
- }
-
- /**
- * Returns true if the message was sent successfully.
- */
- public boolean wasSuccessful() {
- return (error == null);
- }
-
- /**
- * The error indicating the send failed.
- */
- public Throwable getError() {
- return error;
- }
-
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/util/MailListener.java b/src/main/java/com/avaje/ebeaninternal/server/lib/util/MailListener.java
deleted file mode 100644
index 7bde4b328..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/util/MailListener.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.util;
-
-/**
- * Listens to see if the message was successfully sent.
- */
-public interface MailListener {
-
- /**
- * Handle the message event.
- */
- void handleEvent(MailEvent event);
-
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/util/MailMessage.java b/src/main/java/com/avaje/ebeaninternal/server/lib/util/MailMessage.java
deleted file mode 100644
index a88d67c9a..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/util/MailMessage.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.util;
-
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * A simple test message that can be sent via smtp.
- */
-public class MailMessage {
-
- /**
- * The body content.
- */
- final ArrayList bodylines;
-
- /**
- * The sender email address.
- */
- MailAddress senderAddress;
-
- /**
- * The headers.
- */
- final HashMap header = new HashMap();
-
- /**
- * the recipient of the email.
- */
- MailAddress currentRecipient;
-
- /**
- * The list of recipients.
- */
- final ArrayList recipientList = new ArrayList();
-
- /**
- * Create the message.
- */
- public MailMessage() {
- bodylines = new ArrayList();
- }
-
- /**
- * Set the current recipient.
- */
- public void setCurrentRecipient(MailAddress currentRecipient) {
- this.currentRecipient = currentRecipient;
- }
-
- /**
- * Return the current recipient.
- */
- public MailAddress getCurrentRecipient() {
- return currentRecipient;
- }
-
- /**
- * Add a recipient.
- */
- public void addRecipient(String alias, String emailAddress) {
- recipientList.add(new MailAddress(alias, emailAddress));
- }
-
- /**
- * Set the sender details.
- */
- public void setSender(String alias, String senderEmail) {
- this.senderAddress = new MailAddress(alias, senderEmail);
- }
-
- /**
- * Return the sender address.
- */
- public MailAddress getSender() {
- return senderAddress;
- }
-
- /**
- * Return the recipient list.
- */
- public List getRecipientList() {
- return recipientList;
- }
-
- /**
- * add a header to the message.
- */
- public void addHeader(String key, String val) {
- header.put(key, val);
- }
-
- /**
- * Set the subject text.
- */
- public void setSubject(String subject) {
- addHeader("Subject", subject);
- }
-
- /**
- * Return the subject text.
- */
- public String getSubject() {
- return getHeader("Subject");
- }
-
- /**
- * Add text to the body.
- */
- public void addBodyLine(String line) {
- bodylines.add(line);
- }
-
- /**
- * Return the body text.
- */
- public List getBodyLines() {
- return bodylines;
- }
-
- /**
- * Return the headers.
- */
- public Collection getHeaderFields() {
- return header.keySet();
- }
-
- /**
- * Return a given header.
- */
- public String getHeader(String key) {
- return header.get(key);
- }
-
- public String toString() {
- StringBuilder sb = new StringBuilder(100);
- sb.append("Sender: ").append(senderAddress).append("\tRecipient: ").append(recipientList).append("\n");
- for (String key : header.keySet()) {
- String hline = key + ": " + header.get(key) + "\n";
- sb.append(hline);
- }
- sb.append("\n");
- for (String line : bodylines) {
- sb.append(line).append("\n");
- }
- return sb.toString();
- }
-}
-
-
-
diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/util/MailSender.java b/src/main/java/com/avaje/ebeaninternal/server/lib/util/MailSender.java
deleted file mode 100644
index dfdd7a3fa..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/lib/util/MailSender.java
+++ /dev/null
@@ -1,206 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.util;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.UnknownHostException;
-
-/**
- * Sends simple MailMessages via smtp.
- */
-public class MailSender implements Runnable {
-
- private static final Logger logger = LoggerFactory.getLogger(MailSender.class);
-
- int traceLevel = 0;
-
- Socket sserver;
- final String server;
-
- BufferedReader in;
-
- OutputStreamWriter out;
-
- MailMessage message;
-
- MailListener listener = null;
-
- private static final int SMTP_PORT = 25;
-
- /**
- * Create for a given mail server.
- */
- public MailSender(String server) {
- this.server = server;
- }
-
- /**
- * Set the listener to handle MessageEvents.
- */
- public void setMailListener(MailListener listener) {
- this.listener = listener;
- }
-
- /**
- * Send the message.
- */
- public void run() {
- send(message);
- }
-
- /**
- * Send the message in a background thread.
- */
- public void sendInBackground(MailMessage message) {
- this.message = message;
- Thread thread = new Thread(this);
- thread.start();
- }
-
- /**
- * Send the message in the current thread.
- */
- public void send(MailMessage message) {
- try {
- for (MailAddress recipientAddress : message.getRecipientList()) {
- sserver = new Socket(server, SMTP_PORT);
- send(message, sserver, recipientAddress);
- sserver.close();
-
- if (listener != null) {
- MailEvent event = new MailEvent(message, null);
- listener.handleEvent(event);
- }
- }
- } catch (Exception ex) {
- if (listener != null) {
- MailEvent event = new MailEvent(message, ex);
- listener.handleEvent(event);
- } else {
- logger.error(null, ex);
- }
- }
- }
-
- private void send(MailMessage message, Socket sserver, MailAddress recipientAddress) throws IOException {
-
- // A bit convoluted, but doesn't depend on DNS in any way...
- InetAddress localhost = sserver.getLocalAddress();
- String localaddress = localhost.getHostAddress();
- MailAddress sender = message.getSender();
- message.setCurrentRecipient(recipientAddress);
-
- // Mandatory header fields, Date and From
- if (message.getHeader("Date") == null) {
- message.addHeader("Date", new java.util.Date().toString());
- }
- if (message.getHeader("From") == null) {
- message.addHeader("From", sender.getAlias() + " <" + sender.getEmailAddress() + ">");
- }
-
- // if (message.getHeader("From") == null){
- message.addHeader("To", recipientAddress.getAlias() + " <" + recipientAddress.getEmailAddress() + ">");
- // }
-
- out = new OutputStreamWriter(sserver.getOutputStream());
- in = new BufferedReader(new InputStreamReader(sserver.getInputStream()));
- String sintro = readln();
- if (!sintro.startsWith("220")) { // 220
- logger.debug("SmtpSender: intro==" + sintro);
- return;
- }
-
- writeln("EHLO " + localaddress);
- if (!expect250()) {
- return;
- }
-
- writeln("MAIL FROM:<" + sender.getEmailAddress() + ">");
- if (!expect250()) {
- return;
- }
- writeln("RCPT TO:<" + recipientAddress.getEmailAddress() + ">");
- if (!expect250()) {
- return;
- }
- writeln("DATA");
- while (true) { // may be multiple 250 replies pending from server
- String line = readln();
- if (line.startsWith("3"))
- break; // ready to send
- if (!line.startsWith("2")) {
- logger.debug("SmtpSender.send reponse to DATA: " + line);
- return;
- }
- }
- for (String key : message.getHeaderFields()) {
- writeln(key + ": " + message.getHeader(key));
- }
- writeln(""); // end of header;
- for (String bline : message.getBodyLines()) {
- if (bline.startsWith(".")) {
- bline = "." + bline;
- }
- writeln(bline);
- }
- writeln(".");
- expect250();
- writeln("QUIT");
-
- }
-
- private boolean expect250() throws IOException {
- String line = readln();
- if (!line.startsWith("2")) {
- logger.info("SmtpSender.expect250: " + line);
- return false;
- }
- return true;
- }
-
- private void writeln(String s) throws IOException {
- if (traceLevel > 2) {
- logger.debug("From client: " + s);
- }
- out.write(s + "\r\n");
- out.flush();
- }
-
- private String readln() throws IOException {
- String line = in.readLine();
- if (traceLevel > 1) {
- logger.debug("From server: " + line);
- }
- return line;
- }
-
- /**
- * Set the trace level.
- */
- public void setTraceLevel(int traceLevel) {
- this.traceLevel = traceLevel;
- }
-
- /**
- * Return the hostname of the local machine.
- */
- public String getLocalHostName() {
- try {
- InetAddress ipaddress = InetAddress.getLocalHost();
- String localHost = ipaddress.getHostName();
- if (localHost == null) {
- return "localhost";
- } else {
- return localHost;
- }
- } catch (UnknownHostException e) {
- return "localhost";
- }
- }
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/TransactionManager.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/TransactionManager.java
index 239aa0ffa..0f466c649 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/transaction/TransactionManager.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/TransactionManager.java
@@ -16,7 +16,7 @@ import com.avaje.ebeaninternal.api.TransactionEventTable.TableIUD;
import com.avaje.ebeaninternal.server.cluster.ClusterManager;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
-import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool;
+import org.avaje.datasource.DataSourcePool;
import com.avaje.ebeanservice.docstore.api.DocStoreUpdateProcessor;
import com.avaje.ebeanservice.docstore.api.DocStoreUpdates;
import org.slf4j.Logger;
@@ -27,7 +27,6 @@ import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
/**
@@ -129,15 +128,6 @@ public class TransactionManager {
this.externalTransPrefix = "e";
this.onQueryOnly = initOnQueryOnly(config.getDatabasePlatform().getOnQueryOnly(), dataSource);
-
- initialiseHeartbeat();
- }
-
- private void initialiseHeartbeat() {
- if (dataSource instanceof DataSourcePool) {
- DataSourcePool ds = (DataSourcePool) dataSource;
- backgroundExecutor.executePeriodically(ds.getHeartbeatRunnable(), ds.getHeartbeatFreqSecs(), TimeUnit.SECONDS);
- }
}
public void shutdown(boolean shutdownDataSource, boolean deregisterDriver) {
diff --git a/src/test/java/com/avaje/ebeaninternal/server/lib/sql/TestBusyBuffer.java b/src/test/java/com/avaje/ebeaninternal/server/lib/sql/TestBusyBuffer.java
deleted file mode 100644
index 24fc550d4..000000000
--- a/src/test/java/com/avaje/ebeaninternal/server/lib/sql/TestBusyBuffer.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import com.avaje.ebean.BaseTestCase;
-
-public class TestBusyBuffer extends BaseTestCase {
-
- @Test
- public void test() {
-
- BusyConnectionBuffer b = new BusyConnectionBuffer(2, 4);
-
- PooledConnection p0 = new PooledConnection("0");
- PooledConnection p1 = new PooledConnection("1");
- PooledConnection p2 = new PooledConnection("2");
- PooledConnection p3 = new PooledConnection("3");
-
- Assert.assertEquals(2, b.getCapacity());
- b.add(p0);
- b.add(p1);
- Assert.assertEquals(2, b.getCapacity());
- b.add(p2);
- Assert.assertEquals(6, b.getCapacity());
- b.add(p3);
-
- Assert.assertEquals(0, p0.getSlotId());
- Assert.assertEquals(1, p1.getSlotId());
- Assert.assertEquals(2, p2.getSlotId());
- Assert.assertEquals(3, p3.getSlotId());
-
- b.remove(p2);
- b.add(p2);
- Assert.assertEquals(4, p2.getSlotId());
-
- b.remove(p0);
- b.add(p0);
- Assert.assertEquals(5, p0.getSlotId());
-
- b.remove(p2);
- b.add(p2);
- Assert.assertEquals(0, p2.getSlotId());
-
- }
-
- @Test
- public void test_rotate() {
-
- BusyConnectionBuffer b = new BusyConnectionBuffer(2, 2);
-
- PooledConnection p0 = new PooledConnection("0");
- PooledConnection p1 = new PooledConnection("1");
- PooledConnection p2 = new PooledConnection("2");
- PooledConnection p3 = new PooledConnection("3");
-
- Assert.assertEquals(2, b.getCapacity());
- Assert.assertEquals(0, b.size());
-
- b.add(p0);
- b.add(p1);
- Assert.assertEquals(2, b.size());
- Assert.assertEquals(2, b.getCapacity());
- b.add(p2);
- Assert.assertEquals(3, b.size());
- Assert.assertEquals(4, b.getCapacity());
- b.add(p3);
- Assert.assertEquals(4, b.size());
- Assert.assertEquals(4, b.getCapacity());
-
- Assert.assertEquals(0, p0.getSlotId());
- Assert.assertEquals(1, p1.getSlotId());
- Assert.assertEquals(2, p2.getSlotId());
- Assert.assertEquals(3, p3.getSlotId());
-
- b.remove(p2);
- Assert.assertEquals(3, b.size());
- b.remove(p0);
- Assert.assertEquals(2, b.size());
- b.remove(p3);
- Assert.assertEquals(1, b.size());
- b.add(p2);
- Assert.assertEquals(2, b.size());
- Assert.assertEquals(0, p2.getSlotId());
-
- b.remove(p0);
- Assert.assertEquals(2, b.size());
- b.add(p0);
- Assert.assertEquals(3, b.size());
-
- // p1 is still in it's slot
- Assert.assertEquals(2, p0.getSlotId());
-
- b.remove(p2);
- b.add(p2);
- Assert.assertEquals(3, p2.getSlotId());
-
- }
-
-}
diff --git a/src/test/java/com/avaje/ebeaninternal/server/lib/sql/TestDataSourceMax.java b/src/test/java/com/avaje/ebeaninternal/server/lib/sql/TestDataSourceMax.java
deleted file mode 100644
index 4283609ba..000000000
--- a/src/test/java/com/avaje/ebeaninternal/server/lib/sql/TestDataSourceMax.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-
-import org.junit.Test;
-
-import com.avaje.ebean.BaseTestCase;
-import com.avaje.ebean.config.DataSourceConfig;
-import com.avaje.ebeaninternal.server.core.DefaultBackgroundExecutor;
-import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool.Status;
-
-public class TestDataSourceMax extends BaseTestCase {
-
- @Test
- public void test() {
-
- boolean skipThisTest = true;
-
- if (skipThisTest) {
- return;
- }
-
- String name = "mysql";
-
- DataSourceConfig dsConfig = new DataSourceConfig();
- dsConfig.loadSettings(name);
- dsConfig.setMinConnections(2);
- dsConfig.setMaxConnections(25);
- dsConfig.setWaitTimeoutMillis(30000);
- dsConfig.setCaptureStackTrace(true);
-
- DataSourcePool pool = new DataSourcePool(null, name, dsConfig);
-
-
- //pool.checkDataSource();
-
-// if (true) {
-// pool.shutdown(false);
-// return;
-// }
-
- DefaultBackgroundExecutor bg = new DefaultBackgroundExecutor(1, 1, 2, 180, 30, "testDs");
-
- try {
- for (int i = 0; i < 12; i++) {
- // Thread.sleep(10*i);
- bg.execute(new ConnRunner(pool, 4000, i));
- }
-
- Thread.sleep(10000);
- pool.getStatistics(true);
-
- Thread.sleep(30000);
-
- Status status = pool.getStatus(false);
- System.out.println(status);
-
- pool.shutdown(false);
-
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-
- private static class ConnRunner implements Runnable {
-
- final DataSourcePool pool;
- final long sleepMillis;
- final int position;
-
- ConnRunner(DataSourcePool pool, long sleepMillis, int position) {
- this.pool = pool;
- this.sleepMillis = sleepMillis;
- this.position = position;
- }
-
- private void waitSomeTime(long count) {
- try {
- Thread.sleep(sleepMillis);
- } catch (InterruptedException e){
- throw new RuntimeException(e);
- }
- }
-
- public void run() {
- Connection connection = null;
- PreparedStatement pstmt = null;
- ResultSet rset = null;
- long count = -1;
- try {
- connection = pool.getConnection();
- pstmt = connection.prepareStatement("select count(*) from o_customer");
- rset = pstmt.executeQuery();
-
- while (rset.next()) {
- // do nothing actually
- count = rset.getLong(1);
- }
-
- } catch (Exception ex) {
- ex.printStackTrace();
- } finally {
- if (rset != null) {
- try {
- rset.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- if (pstmt != null) {
- try {
- pstmt.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- if (connection != null) {
- try {
- connection.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- waitSomeTime(count);
- }
- }
- }
-}
diff --git a/src/test/java/com/avaje/ebeaninternal/server/lib/sql/TestFreeBuffer.java b/src/test/java/com/avaje/ebeaninternal/server/lib/sql/TestFreeBuffer.java
deleted file mode 100644
index 85e0f1a4e..000000000
--- a/src/test/java/com/avaje/ebeaninternal/server/lib/sql/TestFreeBuffer.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import com.avaje.ebean.BaseTestCase;
-
-public class TestFreeBuffer extends BaseTestCase {
-
- @Test
- public void test() {
-
- FreeConnectionBuffer b = new FreeConnectionBuffer();
-
- PooledConnection p0 = new PooledConnection("0");
- PooledConnection p1 = new PooledConnection("1");
- PooledConnection p2 = new PooledConnection("2");
- // PooledConnection p3 = new PooledConnection("3");
-
- Assert.assertEquals(0, b.size());
- Assert.assertEquals(true, b.isEmpty());
-
- b.add(p0);
-
- Assert.assertEquals(1, b.size());
- Assert.assertEquals(false, b.isEmpty());
-
- PooledConnection r0 = b.remove();
- Assert.assertTrue(p0 == r0);
-
- Assert.assertEquals(0, b.size());
- Assert.assertEquals(true, b.isEmpty());
-
- b.add(p0);
- b.add(p1);
- b.add(p2);
-
- Assert.assertEquals(3, b.size());
-
- PooledConnection r1 = b.remove();
- Assert.assertTrue(p0 == r1);
- PooledConnection r2 = b.remove();
- Assert.assertTrue(p1 == r2);
-
- Assert.assertEquals(1, b.size());
- b.add(p0);
- Assert.assertEquals(2, b.size());
- PooledConnection r3 = b.remove();
- Assert.assertTrue(p2 == r3);
- Assert.assertEquals(1, b.size());
- PooledConnection r4 = b.remove();
- Assert.assertTrue(p0 == r4);
- Assert.assertEquals(0, b.size());
-
- b.add(p2);
- b.add(p1);
- b.add(p0);
-
- Assert.assertEquals(3, b.size());
-
- PooledConnection r5 = b.remove();
- Assert.assertTrue(p2 == r5);
- Assert.assertEquals(2, b.size());
-
- PooledConnection r6 = b.remove();
- Assert.assertTrue(p1 == r6);
- Assert.assertEquals(1, b.size());
-
- PooledConnection r7 = b.remove();
- Assert.assertTrue(p0 == r7);
- Assert.assertEquals(0, b.size());
-
- }
-}
diff --git a/src/test/java/com/avaje/ebeaninternal/server/lib/sql/TestFreeBufferTrim.java b/src/test/java/com/avaje/ebeaninternal/server/lib/sql/TestFreeBufferTrim.java
deleted file mode 100644
index a7a4052c2..000000000
--- a/src/test/java/com/avaje/ebeaninternal/server/lib/sql/TestFreeBufferTrim.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.avaje.ebeaninternal.server.lib.sql;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import com.avaje.ebean.BaseTestCase;
-
-public class TestFreeBufferTrim extends BaseTestCase {
-
- @Test
- public void testWithTime() {
-
- FreeConnectionBuffer b = new FreeConnectionBuffer();
- Assert.assertEquals(0, b.size());
-
- PooledConnection p0 = Mockito.mock(PooledConnection.class);
- Mockito.when(p0.shouldTrim(1500, 0)).thenReturn(true);
-
- PooledConnection p1 = Mockito.mock(PooledConnection.class);
- Mockito.when(p1.shouldTrim(1500, 0)).thenReturn(true);
-
- PooledConnection p2 = Mockito.mock(PooledConnection.class);
- Mockito.when(p2.shouldTrim(1500, 0)).thenReturn(false);
-
- b.add(p0);
- b.add(p1);
- b.add(p2);
-
- Assert.assertEquals(3, b.size());
-
- int trimCount = b.trim(1500, 0);
-
- Assert.assertEquals(1, b.size());
- Assert.assertEquals(2, trimCount);
- }
-
-
-
-}
diff --git a/src/test/java/com/avaje/tests/basic/MainDbBoolean.java b/src/test/java/com/avaje/tests/basic/MainDbBoolean.java
index 712616eff..37669b177 100644
--- a/src/test/java/com/avaje/tests/basic/MainDbBoolean.java
+++ b/src/test/java/com/avaje/tests/basic/MainDbBoolean.java
@@ -8,7 +8,7 @@ import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.EbeanServerFactory;
import com.avaje.ebean.Query;
import com.avaje.ebean.SqlRow;
-import com.avaje.ebean.config.DataSourceConfig;
+import org.avaje.datasource.DataSourceConfig;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.config.dbplatform.PostgresPlatform;
import com.avaje.tests.model.basic.TOne;
diff --git a/src/test/java/com/avaje/tests/basic/MyTestDataSourcePoolListener.java b/src/test/java/com/avaje/tests/basic/MyTestDataSourcePoolListener.java
index ceb4c68a8..acb2c85b9 100644
--- a/src/test/java/com/avaje/tests/basic/MyTestDataSourcePoolListener.java
+++ b/src/test/java/com/avaje/tests/basic/MyTestDataSourcePoolListener.java
@@ -2,7 +2,7 @@ package com.avaje.tests.basic;
import java.sql.Connection;
-import com.avaje.ebeaninternal.server.lib.sql.DataSourcePoolListener;
+import org.avaje.datasource.DataSourcePoolListener;
public class MyTestDataSourcePoolListener implements DataSourcePoolListener
{
diff --git a/src/test/java/com/avaje/tests/transaction/TestAutoCommitDataSource.java b/src/test/java/com/avaje/tests/transaction/TestAutoCommitDataSource.java
index 75ec8d753..61395f226 100644
--- a/src/test/java/com/avaje/tests/transaction/TestAutoCommitDataSource.java
+++ b/src/test/java/com/avaje/tests/transaction/TestAutoCommitDataSource.java
@@ -5,16 +5,19 @@ import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.EbeanServerFactory;
import com.avaje.ebean.Query;
import com.avaje.ebean.Transaction;
-import com.avaje.ebean.config.DataSourceConfig;
+import com.avaje.ebean.config.PropertyMap;
import com.avaje.ebean.config.ServerConfig;
-import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool;
import com.avaje.tests.model.basic.UTDetail;
import com.avaje.tests.model.basic.UTMaster;
+import org.avaje.datasource.DataSourceConfig;
+import org.avaje.datasource.DataSourcePool;
+import org.avaje.datasource.pool.ConnectionPool;
import org.junit.Test;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
+import java.util.Properties;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -24,11 +27,13 @@ public class TestAutoCommitDataSource extends BaseTestCase {
@Test
public void test() throws SQLException {
+ Properties properties = PropertyMap.defaultProperties();
+
DataSourceConfig dsConfig = new DataSourceConfig();
- dsConfig.loadSettings("h2autocommit");//"pg"
+ dsConfig.loadSettings(properties, "h2autocommit");//"pg"
dsConfig.setAutoCommit(true);
- DataSourcePool pool = new DataSourcePool(null, "h2autocommit", dsConfig);
+ DataSourcePool pool = new ConnectionPool("h2autocommit", dsConfig);
Connection connection = pool.getConnection();
assertTrue(connection.getAutoCommit());
diff --git a/src/test/java/com/avaje/tests/transaction/TestExplicitTransactionMode.java b/src/test/java/com/avaje/tests/transaction/TestExplicitTransactionMode.java
index 04d63a0e5..d5957589a 100644
--- a/src/test/java/com/avaje/tests/transaction/TestExplicitTransactionMode.java
+++ b/src/test/java/com/avaje/tests/transaction/TestExplicitTransactionMode.java
@@ -5,16 +5,19 @@ import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.EbeanServerFactory;
import com.avaje.ebean.Query;
import com.avaje.ebean.Transaction;
-import com.avaje.ebean.config.DataSourceConfig;
+import com.avaje.ebean.config.PropertyMap;
import com.avaje.ebean.config.ServerConfig;
-import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool;
import com.avaje.tests.model.basic.UTDetail;
import com.avaje.tests.model.basic.UTMaster;
+import org.avaje.datasource.DataSourceConfig;
+import org.avaje.datasource.DataSourcePool;
+import org.avaje.datasource.pool.ConnectionPool;
import org.junit.Test;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
+import java.util.Properties;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -24,11 +27,13 @@ public class TestExplicitTransactionMode extends BaseTestCase {
@Test
public void test() throws SQLException {
+ Properties properties = PropertyMap.defaultProperties();
+
DataSourceConfig dsConfig = new DataSourceConfig();
- dsConfig.loadSettings("h2autocommit");//"h2autocommit","pg"
+ dsConfig.loadSettings(properties, "h2autocommit");//"h2autocommit","pg"
dsConfig.setAutoCommit(true);
- DataSourcePool pool = new DataSourcePool(null, "h2autocommit", dsConfig);
+ DataSourcePool pool = new ConnectionPool("h2autocommit", dsConfig);
Connection connection = pool.getConnection();
assertTrue(connection.getAutoCommit());
diff --git a/src/test/java/com/avaje/tests/unitinternal/HelloMain.java b/src/test/java/com/avaje/tests/unitinternal/HelloMain.java
index 50a5f52c9..659ade8a4 100644
--- a/src/test/java/com/avaje/tests/unitinternal/HelloMain.java
+++ b/src/test/java/com/avaje/tests/unitinternal/HelloMain.java
@@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.EbeanServerFactory;
-import com.avaje.ebean.config.DataSourceConfig;
+import org.avaje.datasource.DataSourceConfig;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.tests.model.basic.TOne;