diff --git a/src/main/java/com/zaxxer/hikari/HikariDataSource.java b/src/main/java/com/zaxxer/hikari/HikariDataSource.java index 3597f12c..3575847d 100644 --- a/src/main/java/com/zaxxer/hikari/HikariDataSource.java +++ b/src/main/java/com/zaxxer/hikari/HikariDataSource.java @@ -20,12 +20,10 @@ import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; +import java.util.concurrent.ConcurrentHashMap; import javax.sql.DataSource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.zaxxer.hikari.util.DriverDataSource; /** @@ -35,12 +33,12 @@ import com.zaxxer.hikari.util.DriverDataSource; */ public class HikariDataSource extends HikariConfig implements DataSource { - private static final Logger LOGGER = LoggerFactory.getLogger(HikariDataSource.class); - private volatile boolean isShutdown; private int loginTimeout; - HikariPool fastPathPool; + /* Package scopped for testing */ + ConcurrentHashMap multiPool; + final HikariPool fastPathPool; volatile HikariPool pool; /** @@ -52,6 +50,8 @@ public class HikariDataSource extends HikariConfig implements DataSource public HikariDataSource() { super(); + fastPathPool = null; + multiPool = new ConcurrentHashMap(); } /** @@ -63,6 +63,7 @@ public class HikariDataSource extends HikariConfig implements DataSource { configuration.validate(); configuration.copyState(this); + multiPool = new ConcurrentHashMap(); pool = fastPathPool = new HikariPool(this); } @@ -101,9 +102,23 @@ public class HikariDataSource extends HikariConfig implements DataSource @Override public Connection getConnection(String username, String password) throws SQLException { - LOGGER.warn("getConnection() with username and password is not supported, calling getConnection() instead"); + if (isShutdown) + { + throw new SQLException("Pool has been shutdown"); + } + + HikariPool hikariPool; + synchronized (multiPool) + { + hikariPool = multiPool.get(username + password); + if (hikariPool == null) + { + hikariPool = new HikariPool(this, username, password); + multiPool.put(username + password, hikariPool); + } + } - return getConnection(); + return hikariPool.getConnection(); } /** {@inheritDoc} */ @@ -176,18 +191,32 @@ public class HikariDataSource extends HikariConfig implements DataSource */ public void shutdown() { - boolean shutdown = isShutdown; + if (isShutdown) + { + return; + } + isShutdown = true; - if (!shutdown && pool != null) + + if (pool != null) { pool.shutdown(); - if (pool.dataSource instanceof DriverDataSource) { ((DriverDataSource) pool.dataSource).shutdown(); } - - pool = null; + } + + if (!multiPool.isEmpty()) + { + for (HikariPool hikariPool : multiPool.values()) + { + hikariPool.shutdown(); + if (hikariPool.dataSource instanceof DriverDataSource) + { + ((DriverDataSource) hikariPool.dataSource).shutdown(); + } + } } } diff --git a/src/main/java/com/zaxxer/hikari/HikariPool.java b/src/main/java/com/zaxxer/hikari/HikariPool.java index 2d468f7b..0c1d8925 100644 --- a/src/main/java/com/zaxxer/hikari/HikariPool.java +++ b/src/main/java/com/zaxxer/hikari/HikariPool.java @@ -61,20 +61,29 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener private final AtomicInteger totalConnections; private final Timer houseKeepingTimer; private final String catalog; + private final String username; + private final String password; private volatile boolean isShutdown; private volatile long lastConnectionFailureTime; private int transactionIsolation; private boolean isDebug; + HikariPool(HikariConfig configuration) + { + this(configuration, null, null); + } + /** * Construct a HikariPool with the specified configuration. * * @param configuration a HikariConfig instance */ - HikariPool(HikariConfig configuration) + HikariPool(HikariConfig configuration, String username, String password) { this.configuration = configuration; + this.username = username; + this.password = password; this.totalConnections = new AtomicInteger(); this.idleConnectionBag = new ConcurrentBag(); this.idleConnectionBag.addBagStateListener(this); @@ -276,7 +285,7 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener } dataSource.setLoginTimeout((int) loginTimeout); - connection = dataSource.getConnection(); + connection = (username == null && password == null) ? dataSource.getConnection() : dataSource.getConnection(username, password); transactionIsolation = (transactionIsolation < 0 ? connection.getTransactionIsolation() : transactionIsolation);