private DruidPooledConnection getConnectionInternal()

in core/src/main/java/com/alibaba/druid/pool/DruidDataSource.java [1349:1577]


    private DruidPooledConnection getConnectionInternal(long maxWait) throws SQLException {
        if (closed) {
            connectErrorCountUpdater.incrementAndGet(this);
            throw new DataSourceClosedException("dataSource already closed at " + new Date(closeTimeMillis));
        }

        if (!enable) {
            connectErrorCountUpdater.incrementAndGet(this);

            if (disableException != null) {
                throw disableException;
            }

            throw new DataSourceDisableException();
        }

        final int maxWaitThreadCount = this.maxWaitThreadCount;

        DruidConnectionHolder holder;

        long startTime = System.currentTimeMillis();  //进入循环等待之前,先记录开始尝试获取连接的时间
        final long expiredTime = startTime + maxWait;
        for (boolean createDirect = false; ; ) {
            if (createDirect) {
                try {
                    createStartNanosUpdater.set(this, System.nanoTime());
                    if (creatingCountUpdater.compareAndSet(this, 0, 1)) {
                        PhysicalConnectionInfo pyConnInfo = DruidDataSource.this.createPhysicalConnection();
                        holder = new DruidConnectionHolder(this, pyConnInfo);

                        creatingCountUpdater.decrementAndGet(this);
                        directCreateCountUpdater.incrementAndGet(this);

                        if (LOG.isDebugEnabled()) {
                            LOG.debug("conn-direct_create ");
                        }

                        final Lock lock = this.lock;
                        lock.lock();
                        try {
                            if (activeCount + poolingCount < maxActive) {
                                activeCount++;
                                holder.active = true;
                                if (activeCount > activePeak) {
                                    activePeak = activeCount;
                                    activePeakTime = System.currentTimeMillis();
                                }
                                break;
                            }
                        } finally {
                            lock.unlock();
                        }

                        JdbcUtils.close(pyConnInfo.getPhysicalConnection());
                    }
                } finally {
                    createDirect = false;
                    createDirectCountUpdater.decrementAndGet(this);
                }
            }

            final ReentrantLock lock = this.lock;
            try {
                lock.lockInterruptibly();
            } catch (InterruptedException e) {
                connectErrorCountUpdater.incrementAndGet(this);
                throw new SQLException("interrupt", e);
            }

            try {
                if (maxWaitThreadCount > 0
                        && notEmptyWaitThreadCount > maxWaitThreadCount) {
                    connectErrorCountUpdater.incrementAndGet(this);
                    throw new SQLException("maxWaitThreadCount " + maxWaitThreadCount + ", current wait Thread count "
                            + lock.getQueueLength());
                }

                if (onFatalError
                        && onFatalErrorMaxActive > 0
                        && activeCount >= onFatalErrorMaxActive) {
                    connectErrorCountUpdater.incrementAndGet(this);

                    StringBuilder errorMsg = new StringBuilder();
                    errorMsg.append("onFatalError, activeCount ")
                            .append(activeCount)
                            .append(", onFatalErrorMaxActive ")
                            .append(onFatalErrorMaxActive);

                    if (lastFatalErrorTimeMillis > 0) {
                        errorMsg.append(", time '")
                                .append(StringUtils.formatDateTime19(
                                        lastFatalErrorTimeMillis, TimeZone.getDefault()))
                                .append("'");
                    }

                    if (lastFatalErrorSql != null) {
                        errorMsg.append(", sql \n")
                                .append(lastFatalErrorSql);
                    }

                    throw new SQLException(
                            errorMsg.toString(), lastFatalError);
                }

                connectCount++;

                if (createScheduler != null
                        && poolingCount == 0
                        && activeCount < maxActive
                        && createDirectCountUpdater.get(this) == 0
                        && creatingCountUpdater.get(this) == 0
                        && createScheduler instanceof ScheduledThreadPoolExecutor) {
                    ScheduledThreadPoolExecutor executor = (ScheduledThreadPoolExecutor) createScheduler;
                    if (executor.getQueue().size() > 0) {
                        if (maxWait > 0 && System.currentTimeMillis() - startTime >= maxWait) {
                            holder = null;
                            break;
                        }
                        createDirect = true;
                        createDirectCountUpdater.incrementAndGet(this);
                        continue;
                    }
                }

                if (maxWait > 0) {
                    if (System.currentTimeMillis() < expiredTime) {
                        holder = pollLast(startTime, expiredTime);
                    } else {
                        holder = null;
                        break;
                    }
                } else {
                    holder = takeLast(startTime);
                }

                if (holder != null) {
                    if (holder.discard) {
                        holder = null;
                        if (maxWait > 0 && System.currentTimeMillis() >= expiredTime) {
                            break;
                        }
                        continue;
                    }

                    activeCount++;
                    holder.active = true;
                    if (activeCount > activePeak) {
                        activePeak = activeCount;
                        activePeakTime = System.currentTimeMillis();
                    }
                }
            } catch (InterruptedException e) {
                connectErrorCountUpdater.incrementAndGet(this);
                throw new SQLException(e.getMessage(), e);
            } catch (SQLException e) {
                connectErrorCountUpdater.incrementAndGet(this);
                throw e;
            } finally {
                lock.unlock();
            }

            break;
        }

        if (holder == null) {
            long waitMillis = System.currentTimeMillis() - startTime;

            final long activeCount;
            final long maxActive;
            final long creatingCount;
            final long createStartNanos;
            final long createErrorCount;
            final Throwable createError;
            try {
                lock.lock();
                activeCount = this.activeCount;
                maxActive = this.maxActive;
                creatingCount = this.creatingCount;
                createStartNanos = this.createStartNanos;
                createErrorCount = this.createErrorCount;
                createError = this.createError;
            } finally {
                lock.unlock();
            }

            StringBuilder buf = new StringBuilder(128);
            buf.append("wait millis ")
                    .append(waitMillis)
                    .append(", active ").append(activeCount)
                    .append(", maxActive ").append(maxActive)
                    .append(", creating ").append(creatingCount);

            if (creatingCount > 0 && createStartNanos > 0) {
                long createElapseMillis = (System.nanoTime() - createStartNanos) / (1000 * 1000);
                if (createElapseMillis > 0) {
                    buf.append(", createElapseMillis ").append(createElapseMillis);
                }
            }

            if (createErrorCount > 0) {
                buf.append(", createErrorCount ").append(createErrorCount);
            }

            List<JdbcSqlStatValue> sqlList = this.getDataSourceStat().getRuningSqlList();
            for (int i = 0; i < sqlList.size(); ++i) {
                if (i != 0) {
                    buf.append('\n');
                } else {
                    buf.append(", ");
                }
                JdbcSqlStatValue sql = sqlList.get(i);
                buf.append("runningSqlCount ").append(sql.getRunningCount());
                buf.append(" : ");
                buf.append(sql.getSql());
            }

            String errorMessage = buf.toString();

            if (createError != null) {
                throw new GetConnectionTimeoutException(errorMessage, createError);
            } else {
                throw new GetConnectionTimeoutException(errorMessage);
            }
        }

        holder.incrementUseCount();

        return new DruidPooledConnection(holder);
    }