Continuing yesterday’s analysis of the process initialized by the init() method, the next step is the availability connection check

This interface helps Druid applications easily and quickly determine the availability of java.SQL. Connection objects and identify Connection objects that should no longer be used for Connection pooling. similar


public class OracleValidConnectionChecker extends ValidConnectionCheckerAdapter implements ValidConnectionChecker, Serializable 

Copy the code

Inheriting the common ValidConnectionChecker method, the isValid () method can be used to check connections or in conjunction with a retry mechanism, such as a retry mechanism in response to fast connection failover processing.

private void initValidConnectionChecker() {
    if (this.validConnectionChecker != null) {
        return;
    }

    String realDriverClassName = driver.getClass().getName();
    if (JdbcUtils.isMySqlDriver(realDriverClassName)) {
        this.validConnectionChecker = new MySqlValidConnectionChecker();

    } else if (realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER)
            || realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER2)) {
        this.validConnectionChecker = new OracleValidConnectionChecker();

    } else if (realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER)
               || realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER_SQLJDBC4)
               || realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER_JTDS)) {
        this.validConnectionChecker = new MSSQLValidConnectionChecker();

    } else if (realDriverClassName.equals(JdbcConstants.POSTGRESQL_DRIVER)
            || realDriverClassName.equals(JdbcConstants.ENTERPRISEDB_DRIVER)
            || realDriverClassName.equals(JdbcConstants.POLARDB_DRIVER)) {
        this.validConnectionChecker = new PGValidConnectionChecker();
    }
}
Copy the code

Finally, there is the validationQueryCheck method. A validationQuery is a query statement that validates a database connection. The query statement must be a SELECT statement that returns at least one data. Each database has its own validation statement. This is also used to verify database links

private void validationQueryCheck() { if (! (testOnBorrow || testOnReturn || testWhileIdle)) { return; } if (this.validConnectionChecker ! = null) { return; } if (this.validationQuery ! = null && this.validationQuery.length() > 0) { return; } String errorMessage = ""; if (testOnBorrow) { errorMessage += "testOnBorrow is true, "; } if (testOnReturn) { errorMessage += "testOnReturn is true, "; } if (testWhileIdle) { errorMessage += "testWhileIdle is true, "; } LOG.error(errorMessage + "validationQuery not set"); }Copy the code

The next step is to configure the public monitoring data. The configuration parameter is useGloalDataSourceStat, which is used to initialize the public monitoring data

if (isUseGlobalDataSourceStat()) {
    dataSourceStat = JdbcDataSourceStat.getGlobal();
    if (dataSourceStat == null) {
        dataSourceStat = new JdbcDataSourceStat("Global", "Global", this.dbTypeName);
        JdbcDataSourceStat.setGlobal(dataSourceStat);
    }
    if (dataSourceStat.getDbType() == null) {
        dataSourceStat.setDbType(this.dbTypeName);
    }
} else {
    dataSourceStat = new JdbcDataSourceStat(this.name, this.jdbcUrl, this.dbTypeName, this.connectProperties);
}
Copy the code

Now comes the specific initialization part:

connections = new DruidConnectionHolder[maxActive];
evictConnections = new DruidConnectionHolder[maxActive];
keepAliveConnections = new DruidConnectionHolder[maxActive];

SQLException connectError = null;

if (createScheduler != null && asyncInit) {
    for (int i = 0; i < initialSize; ++i) {
        submitCreateTask(true);
    }
}
Copy the code

Druid supports two ways to create connections. One is to create connections asynchronously from the thread pool by starting different daemons to communicate with await and signal (the default). This is done by calling asyncInit=true when the DruID is initialized. CreateScheduler is passed in with asyncInit set to true and submitCreaterTask is called to create a connection.

else if (!asyncInit) {
    // init connections
    while (poolingCount < initialSize) {
        try {
            PhysicalConnectionInfo pyConnectInfo = createPhysicalConnection();
            DruidConnectionHolder holder = new DruidConnectionHolder(this, pyConnectInfo);
            connections[poolingCount++] = holder;
        } catch (SQLException ex) {
            LOG.error("init datasource error, url: " + this.getUrl(), ex);
            if (initExceptionThrow) {
                connectError = ex;
                break;
            } else {
                Thread.sleep(3000);
            }
        }
    }

    if (poolingCount > 0) {
        poolingPeak = poolingCount;
        poolingPeakTime = System.currentTimeMillis();
    }
}
Copy the code

The above method first calculates the poolingCount size before it reaches initialSize- the maximum number of initialized threads and then calls the createPhysicalConnection method

public PhysicalConnectionInfo createPhysicalConnection() throws SQLException { String url = this.getUrl(); Properties connectProperties = getConnectProperties(); String user; if (getUserCallback() ! = null) { user = getUserCallback().getName(); } else { user = getUsername(); } String password = getPassword(); PasswordCallback passwordCallback = getPasswordCallback(); if (passwordCallback ! = null) { if (passwordCallback instanceof DruidPasswordCallback) { DruidPasswordCallback druidPasswordCallback = (DruidPasswordCallback) passwordCallback; druidPasswordCallback.setUrl(url); druidPasswordCallback.setProperties(connectProperties); } char[] chars = passwordCallback.getPassword(); if (chars ! = null) { password = new String(chars); } } Properties physicalConnectProperties = new Properties(); if (connectProperties ! = null) { physicalConnectProperties.putAll(connectProperties); }Copy the code

The createPhysicalConnection method is the part of the method that actually creates the connection. The method is too long to paste in here and returns one

return new PhysicalConnectionInfo(conn, connectStartNanos, connectedNanos, initedNanos, validatedNanos, variables, globalVariables);
Copy the code

The INFO class contains most of the parameters you just initialized.

Conclusion: Today, I also analyzed some method realization in the getConnection method and connection processing. The discussion process in these days is very unregulated, which belongs to what counts. Tomorrow, I will change the way, first make diagram to clarify the process and then analyze the code from the diagram again