diff --git a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java index 82ce628163..8bceb3fab7 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java @@ -37,6 +37,7 @@ import java.util.Properties; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; @@ -247,6 +248,7 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements private boolean asyncCloseConnectionEnable = false; protected int maxCreateTaskCount = 3; protected boolean failFast = false; + protected AtomicBoolean failContinuous = new AtomicBoolean(false); protected ScheduledExecutorService destroyScheduler; protected ScheduledExecutorService createScheduler; @@ -1516,6 +1518,10 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements lock.unlock(); } } + + protected void setFailContinuous(boolean fail) { + failContinuous.set(fail); + } public void initPhysicalConnection(Connection conn) throws SQLException { if (conn.getAutoCommit() != defaultAutoCommit) { diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 8c664106cc..9bdd63cb4a 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -1509,7 +1509,7 @@ public class DruidDataSource extends DruidAbstractDataSource while (poolingCount == 0) { emptySignal(); // send signal to CreateThread create connection - if (failFast && createError != null) { + if (failFast && failContinuous.get()) { throw new DataSourceNotAvailableException(createError); } @@ -1549,7 +1549,7 @@ public class DruidDataSource extends DruidAbstractDataSource if (poolingCount == 0) { emptySignal(); // send signal to CreateThread create connection - if (failFast && createError != null) { + if (failFast && failContinuous.get()) { throw new DataSourceNotAvailableException(createError); } @@ -1885,21 +1885,23 @@ public class DruidDataSource extends DruidAbstractDataSource try { physicalConnection = createPhysicalConnection(); + setFailContinuous(false); } catch (SQLException e) { LOG.error("create connection error, url: " + jdbcUrl, e); errorCount++; - - if (failFast) { - lock.lock(); - try { - notEmpty.signalAll(); - } finally { - lock.unlock(); - } - } - if (errorCount > connectionErrorRetryAttempts && timeBetweenConnectErrorMillis > 0) { + // fail over retry attempts + setFailContinuous(true); + if (failFast) { + lock.lock(); + try { + notEmpty.signalAll(); + } finally { + lock.unlock(); + } + } + if (breakAfterAcquireFailure) { lock.lock(); try { @@ -1916,6 +1918,8 @@ public class DruidDataSource extends DruidAbstractDataSource } } catch (RuntimeException e) { LOG.error("create connection error", e); + // unknow fatal exception + setFailContinuous(true); continue; } catch (Error e) { lock.lock(); @@ -1925,6 +1929,8 @@ public class DruidDataSource extends DruidAbstractDataSource lock.unlock(); } LOG.error("create connection error", e); + // unknow fatal exception + setFailContinuous(true); break; } @@ -1993,21 +1999,23 @@ public class DruidDataSource extends DruidAbstractDataSource try { connection = createPhysicalConnection(); + setFailContinuous(false); } catch (SQLException e) { LOG.error("create connection error, url: " + jdbcUrl + ", errorCode " + e.getErrorCode() + ", state " + e.getSQLState(), e); errorCount++; - - if (failFast) { - lock.lock(); - try { - notEmpty.signalAll(); - } finally { - lock.unlock(); - } - } - if (errorCount > connectionErrorRetryAttempts && timeBetweenConnectErrorMillis > 0) { + // fail over retry attempts + setFailContinuous(true); + if (failFast) { + lock.lock(); + try { + notEmpty.signalAll(); + } finally { + lock.unlock(); + } + } + if (breakAfterAcquireFailure) { break; } @@ -2020,9 +2028,11 @@ public class DruidDataSource extends DruidAbstractDataSource } } catch (RuntimeException e) { LOG.error("create connection error", e); + setFailContinuous(true); continue; } catch (Error e) { LOG.error("create connection error", e); + setFailContinuous(true); break; } diff --git a/src/test/java/com/alibaba/druid/bvt/pool/profile/FailFastTest.java b/src/test/java/com/alibaba/druid/bvt/pool/profile/FailFastTest.java index 8db142a7f4..d2537d7aa6 100644 --- a/src/test/java/com/alibaba/druid/bvt/pool/profile/FailFastTest.java +++ b/src/test/java/com/alibaba/druid/bvt/pool/profile/FailFastTest.java @@ -8,6 +8,7 @@ import java.util.concurrent.atomic.AtomicReference; import org.junit.Assert; +import com.alibaba.druid.pool.DataSourceNotAvailableException; import com.alibaba.druid.pool.DruidDataSource; import junit.framework.TestCase; @@ -70,8 +71,9 @@ public class FailFastTest extends TestCase { connectStartLatch.await(); latch.countDown(); - connectEndLatch.await(3, TimeUnit.SECONDS); + SQLException ex = errorHolder.get(); + Assert.assertTrue(ex instanceof DataSourceNotAvailableException); } }