summaryrefslogtreecommitdiff
path: root/src/main/java/com/zaxxer/hikari/HikariDataSource.java
diff options
context:
space:
mode:
authorApollon Oikonomopoulos <apoikos@debian.org>2017-03-01 14:21:59 +0200
committerApollon Oikonomopoulos <apoikos@debian.org>2017-03-01 14:21:59 +0200
commitbd7b6679cea5620446718911de7a6764f81a9a7a (patch)
treea725b29afd153ae0d18c47e41c1197e2b409313d /src/main/java/com/zaxxer/hikari/HikariDataSource.java
New upstream version 2.6.0
Diffstat (limited to 'src/main/java/com/zaxxer/hikari/HikariDataSource.java')
-rw-r--r--src/main/java/com/zaxxer/hikari/HikariDataSource.java356
1 files changed, 356 insertions, 0 deletions
diff --git a/src/main/java/com/zaxxer/hikari/HikariDataSource.java b/src/main/java/com/zaxxer/hikari/HikariDataSource.java
new file mode 100644
index 0000000..29b8953
--- /dev/null
+++ b/src/main/java/com/zaxxer/hikari/HikariDataSource.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2013 Brett Wooldridge
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.zaxxer.hikari;
+
+import java.io.Closeable;
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.sql.DataSource;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.zaxxer.hikari.metrics.MetricsTrackerFactory;
+import com.zaxxer.hikari.pool.HikariPool;
+import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException;
+
+/**
+ * The HikariCP pooled DataSource.
+ *
+ * @author Brett Wooldridge
+ */
+public class HikariDataSource extends HikariConfig implements DataSource, Closeable
+{
+ private static final Logger LOGGER = LoggerFactory.getLogger(HikariDataSource.class);
+
+ private final AtomicBoolean isShutdown = new AtomicBoolean();
+
+ private final HikariPool fastPathPool;
+ private volatile HikariPool pool;
+
+ /**
+ * Default constructor. Setters be used to configure the pool. Using
+ * this constructor vs. {@link #HikariDataSource(HikariConfig)} will
+ * result in {@link #getConnection()} performance that is slightly lower
+ * due to lazy initialization checks.
+ */
+ public HikariDataSource()
+ {
+ super();
+ fastPathPool = null;
+ }
+
+ /**
+ * Construct a HikariDataSource with the specified configuration.
+ *
+ * @param configuration a HikariConfig instance
+ */
+ public HikariDataSource(HikariConfig configuration)
+ {
+ configuration.validate();
+ configuration.copyState(this);
+
+ LOGGER.info("{} - Starting...", configuration.getPoolName());
+ pool = fastPathPool = new HikariPool(this);
+ LOGGER.info("{} - Start completed.", configuration.getPoolName());
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Connection getConnection() throws SQLException
+ {
+ if (isClosed()) {
+ throw new SQLException("HikariDataSource " + this + " has been closed.");
+ }
+
+ if (fastPathPool != null) {
+ return fastPathPool.getConnection();
+ }
+
+ // See http://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
+ HikariPool result = pool;
+ if (result == null) {
+ synchronized (this) {
+ result = pool;
+ if (result == null) {
+ validate();
+ LOGGER.info("{} - Starting...", getPoolName());
+ try {
+ pool = result = new HikariPool(this);
+ }
+ catch (PoolInitializationException pie) {
+ if (pie.getCause() instanceof SQLException) {
+ throw (SQLException) pie.getCause();
+ }
+ else {
+ throw pie;
+ }
+ }
+ LOGGER.info("{} - Start completed.", getPoolName());
+ }
+ }
+ }
+
+ return result.getConnection();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Connection getConnection(String username, String password) throws SQLException
+ {
+ throw new SQLFeatureNotSupportedException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public PrintWriter getLogWriter() throws SQLException
+ {
+ HikariPool p = pool;
+ return (p != null ? p.getUnwrappedDataSource().getLogWriter() : null);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setLogWriter(PrintWriter out) throws SQLException
+ {
+ HikariPool p = pool;
+ if (p != null) {
+ p.getUnwrappedDataSource().setLogWriter(out);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setLoginTimeout(int seconds) throws SQLException
+ {
+ HikariPool p = pool;
+ if (p != null) {
+ p.getUnwrappedDataSource().setLoginTimeout(seconds);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int getLoginTimeout() throws SQLException
+ {
+ HikariPool p = pool;
+ return (p != null ? p.getUnwrappedDataSource().getLoginTimeout() : 0);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException
+ {
+ throw new SQLFeatureNotSupportedException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T unwrap(Class<T> iface) throws SQLException
+ {
+ if (iface.isInstance(this)) {
+ return (T) this;
+ }
+
+ HikariPool p = pool;
+ if (p != null) {
+ final DataSource unwrappedDataSource = p.getUnwrappedDataSource();
+ if (iface.isInstance(unwrappedDataSource)) {
+ return (T) unwrappedDataSource;
+ }
+
+ if (unwrappedDataSource != null) {
+ return unwrappedDataSource.unwrap(iface);
+ }
+ }
+
+ throw new SQLException("Wrapped DataSource is not an instance of " + iface);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isWrapperFor(Class<?> iface) throws SQLException
+ {
+ if (iface.isInstance(this)) {
+ return true;
+ }
+
+ HikariPool p = pool;
+ if (p != null) {
+ final DataSource unwrappedDataSource = p.getUnwrappedDataSource();
+ if (iface.isInstance(unwrappedDataSource)) {
+ return true;
+ }
+
+ if (unwrappedDataSource != null) {
+ return unwrappedDataSource.isWrapperFor(iface);
+ }
+ }
+
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setMetricRegistry(Object metricRegistry)
+ {
+ boolean isAlreadySet = getMetricRegistry() != null;
+ super.setMetricRegistry(metricRegistry);
+
+ HikariPool p = pool;
+ if (p != null) {
+ if (isAlreadySet) {
+ throw new IllegalStateException("MetricRegistry can only be set one time");
+ }
+ else {
+ p.setMetricRegistry(super.getMetricRegistry());
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setMetricsTrackerFactory(MetricsTrackerFactory metricsTrackerFactory)
+ {
+ boolean isAlreadySet = getMetricsTrackerFactory() != null;
+ super.setMetricsTrackerFactory(metricsTrackerFactory);
+
+ HikariPool p = pool;
+ if (p != null) {
+ if (isAlreadySet) {
+ throw new IllegalStateException("MetricsTrackerFactory can only be set one time");
+ }
+ else {
+ p.setMetricsTrackerFactory(super.getMetricsTrackerFactory());
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setHealthCheckRegistry(Object healthCheckRegistry)
+ {
+ boolean isAlreadySet = getHealthCheckRegistry() != null;
+ super.setHealthCheckRegistry(healthCheckRegistry);
+
+ HikariPool p = pool;
+ if (p != null) {
+ if (isAlreadySet) {
+ throw new IllegalStateException("HealthCheckRegistry can only be set one time");
+ }
+ else {
+ p.setHealthCheckRegistry(super.getHealthCheckRegistry());
+ }
+ }
+ }
+
+ /**
+ * Evict a connection from the pool. If the connection has already been closed (returned to the pool)
+ * this may result in a "soft" eviction; the connection will be evicted sometime in the future if it is
+ * currently in use. If the connection has not been closed, the eviction is immediate.
+ *
+ * @param connection the connection to evict from the pool
+ */
+ public void evictConnection(Connection connection)
+ {
+ HikariPool p;
+ if (!isClosed() && (p = pool) != null && connection.getClass().getName().startsWith("com.zaxxer.hikari")) {
+ p.evictConnection(connection);
+ }
+ }
+
+ /**
+ * Suspend allocation of connections from the pool. All callers to <code>getConnection()</code>
+ * will block indefinitely until <code>resumePool()</code> is called.
+ */
+ public void suspendPool()
+ {
+ HikariPool p;
+ if (!isClosed() && (p = pool) != null) {
+ p.suspendPool();
+ }
+ }
+
+ /**
+ * Resume allocation of connections from the pool.
+ */
+ public void resumePool()
+ {
+ HikariPool p;
+ if (!isClosed() && (p = pool) != null) {
+ p.resumePool();
+ }
+ }
+
+ /**
+ * Shutdown the DataSource and its associated pool.
+ */
+ @Override
+ public void close()
+ {
+ if (isShutdown.getAndSet(true)) {
+ return;
+ }
+
+ HikariPool p = pool;
+ if (p != null) {
+ try {
+ LOGGER.info("{} - Shutdown initiated...", getPoolName());
+ p.shutdown();
+ LOGGER.info("{} - Shutdown completed.", getPoolName());
+ }
+ catch (InterruptedException e) {
+ LOGGER.warn("{} - Interrupted during closing", getPoolName(), e);
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ /**
+ * Determine whether the HikariDataSource has been closed.
+ *
+ * @return true if the HikariDataSource has been closed, false otherwise
+ */
+ public boolean isClosed()
+ {
+ return isShutdown.get();
+ }
+
+ /**
+ * Shutdown the DataSource and its associated pool.
+ *
+ * @deprecated This method has been deprecated, please use {@link #close()} instead
+ */
+ @Deprecated
+ public void shutdown()
+ {
+ LOGGER.warn("The shutdown() method has been deprecated, please use the close() method instead");
+ close();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String toString()
+ {
+ return "HikariDataSource (" + pool + ")";
+ }
+}