Search in sources :

Example 1 with HostRequirement

use of org.postgresql.hostchooser.HostRequirement in project teiid by teiid.

the class ConnectionFactoryImpl method openConnectionImpl.

public QueryExecutor openConnectionImpl(HostSpec[] hostSpecs, String user, String database, Properties info) throws SQLException {
    // Extract interesting values from the info properties:
    // - the SSL setting
    boolean requireSSL;
    boolean trySSL;
    String sslmode = PGProperty.SSL_MODE.get(info);
    if (sslmode == null) {
        // Fall back to the ssl property
        // assume "true" if the property is set but empty
        requireSSL = trySSL = PGProperty.SSL.getBoolean(info) || "".equals(PGProperty.SSL.get(info));
    } else {
        if ("disable".equals(sslmode)) {
            requireSSL = trySSL = false;
        } else if ("require".equals(sslmode) || "verify-ca".equals(sslmode) || "verify-full".equals(sslmode)) {
            requireSSL = trySSL = true;
        } else {
            throw new PSQLException(GT.tr("Invalid sslmode value: {0}", sslmode), PSQLState.CONNECTION_UNABLE_TO_CONNECT);
        }
    }
    // - the TCP keep alive setting
    boolean requireTCPKeepAlive = PGProperty.TCP_KEEP_ALIVE.getBoolean(info);
    // NOTE: To simplify this code, it is assumed that if we are
    // using the V3 protocol, then the database is at least 7.4. That
    // eliminates the need to check database versions and maintain
    // backward-compatible code here.
    // 
    // Change by Chris Smith <cdsmith@twu.net>
    int connectTimeout = PGProperty.CONNECT_TIMEOUT.getInt(info) * 1000;
    // - the targetServerType setting
    HostRequirement targetServerType;
    try {
        targetServerType = HostRequirement.valueOf(info.getProperty("targetServerType", HostRequirement.any.name()));
    } catch (IllegalArgumentException ex) {
        throw new PSQLException(GT.tr("Invalid targetServerType value: {0}", info.getProperty("targetServerType")), PSQLState.CONNECTION_UNABLE_TO_CONNECT);
    }
    SocketFactory socketFactory = SocketFactoryFactory.getSocketFactory(info);
    HostChooser hostChooser = HostChooserFactory.createHostChooser(hostSpecs, targetServerType, info);
    Iterator<HostSpec> hostIter = hostChooser.iterator();
    while (hostIter.hasNext()) {
        HostSpec hostSpec = hostIter.next();
        LOGGER.log(Level.FINE, "Trying to establish a protocol version 3 connection to {0}", hostSpec);
        // 
        // Establish a connection.
        // 
        PGStream newStream = null;
        try {
            newStream = new PGStream(socketFactory, hostSpec, connectTimeout);
            // Construct and send an ssl startup packet if requested.
            if (trySSL) {
                newStream = enableSSL(newStream, requireSSL, info, connectTimeout);
            }
            // Set the socket timeout if the "socketTimeout" property has been set.
            int socketTimeout = PGProperty.SOCKET_TIMEOUT.getInt(info);
            if (socketTimeout > 0) {
                newStream.getSocket().setSoTimeout(socketTimeout * 1000);
            }
            // Enable TCP keep-alive probe if required.
            newStream.getSocket().setKeepAlive(requireTCPKeepAlive);
            // Try to set SO_SNDBUF and SO_RECVBUF socket options, if requested.
            // If receiveBufferSize and send_buffer_size are set to a value greater
            // than 0, adjust. -1 means use the system default, 0 is ignored since not
            // supported.
            // Set SO_RECVBUF read buffer size
            int receiveBufferSize = PGProperty.RECEIVE_BUFFER_SIZE.getInt(info);
            if (receiveBufferSize > -1) {
                // value of 0 not a valid buffer size value
                if (receiveBufferSize > 0) {
                    newStream.getSocket().setReceiveBufferSize(receiveBufferSize);
                } else {
                    LOGGER.log(Level.WARNING, "Ignore invalid value for receiveBufferSize: {0}", receiveBufferSize);
                }
            }
            // Set SO_SNDBUF write buffer size
            int sendBufferSize = PGProperty.SEND_BUFFER_SIZE.getInt(info);
            if (sendBufferSize > -1) {
                if (sendBufferSize > 0) {
                    newStream.getSocket().setSendBufferSize(sendBufferSize);
                } else {
                    LOGGER.log(Level.WARNING, "Ignore invalid value for sendBufferSize: {0}", sendBufferSize);
                }
            }
            LOGGER.log(Level.FINE, "Receive Buffer Size is {0}", newStream.getSocket().getReceiveBufferSize());
            LOGGER.log(Level.FINE, "Send Buffer Size is {0}", newStream.getSocket().getSendBufferSize());
            List<String[]> paramList = new ArrayList<String[]>();
            paramList.add(new String[] { "user", user });
            paramList.add(new String[] { "database", database });
            paramList.add(new String[] { "client_encoding", "UTF8" });
            paramList.add(new String[] { "DateStyle", "ISO" });
            paramList.add(new String[] { "TimeZone", createPostgresTimeZone() });
            Version assumeVersion = ServerVersion.from(PGProperty.ASSUME_MIN_SERVER_VERSION.get(info));
            if (assumeVersion.getVersionNum() >= ServerVersion.v9_0.getVersionNum()) {
                // User is explicitly telling us this is a 9.0+ server so set properties here:
                paramList.add(new String[] { "extra_float_digits", "3" });
                String appName = PGProperty.APPLICATION_NAME.get(info);
                if (appName != null) {
                    paramList.add(new String[] { "application_name", appName });
                }
            } else {
                // User has not explicitly told us that this is a 9.0+ server so stick to old default:
                paramList.add(new String[] { "extra_float_digits", "2" });
            }
            String replication = PGProperty.REPLICATION.get(info);
            if (replication != null && assumeVersion.getVersionNum() >= ServerVersion.v9_4.getVersionNum()) {
                paramList.add(new String[] { "replication", replication });
            }
            String currentSchema = PGProperty.CURRENT_SCHEMA.get(info);
            if (currentSchema != null) {
                paramList.add(new String[] { "search_path", currentSchema });
            }
            sendStartupPacket(newStream, paramList);
            // Do authentication (until AuthenticationOk).
            doAuthentication(newStream, hostSpec.getHost(), user, info);
            int cancelSignalTimeout = PGProperty.CANCEL_SIGNAL_TIMEOUT.getInt(info) * 1000;
            // Do final startup.
            QueryExecutor queryExecutor = new ExtendedQueryExecutorImpl(newStream, user, database, cancelSignalTimeout, info);
            // Check Master or Slave
            HostStatus hostStatus = HostStatus.ConnectOK;
            if (targetServerType != HostRequirement.any) {
                hostStatus = isMaster(queryExecutor) ? HostStatus.Master : HostStatus.Slave;
            }
            GlobalHostStatusTracker.reportHostStatus(hostSpec, hostStatus);
            if (!targetServerType.allowConnectingTo(hostStatus)) {
                queryExecutor.close();
                if (hostIter.hasNext()) {
                    // still more addresses to try
                    continue;
                }
                throw new PSQLException(GT.tr("Could not find a server with specified targetServerType: {0}", targetServerType), PSQLState.CONNECTION_UNABLE_TO_CONNECT);
            }
            runInitialQueries(queryExecutor, info);
            // And we're done.
            return queryExecutor;
        } catch (UnsupportedProtocolException upe) {
            // Swallow this and return null so ConnectionFactory tries the next protocol.
            LOGGER.log(Level.SEVERE, "Protocol not supported, abandoning connection.");
            closeStream(newStream);
            return null;
        } catch (ConnectException cex) {
            // Added by Peter Mount <peter@retep.org.uk>
            // ConnectException is thrown when the connection cannot be made.
            // we trap this an return a more meaningful message for the end user
            GlobalHostStatusTracker.reportHostStatus(hostSpec, HostStatus.ConnectFail);
            if (hostIter.hasNext()) {
                // still more addresses to try
                continue;
            }
            throw new PSQLException(GT.tr("Connection to {0} refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.", hostSpec), PSQLState.CONNECTION_UNABLE_TO_CONNECT, cex);
        } catch (IOException ioe) {
            closeStream(newStream);
            GlobalHostStatusTracker.reportHostStatus(hostSpec, HostStatus.ConnectFail);
            if (hostIter.hasNext()) {
                // still more addresses to try
                continue;
            }
            throw new PSQLException(GT.tr("The connection attempt failed."), PSQLState.CONNECTION_UNABLE_TO_CONNECT, ioe);
        } catch (SQLException se) {
            closeStream(newStream);
            if (hostIter.hasNext()) {
                // still more addresses to try
                continue;
            }
            throw se;
        }
    }
    throw new PSQLException(GT.tr("The connection url is invalid."), PSQLState.CONNECTION_UNABLE_TO_CONNECT);
}
Also used : PGStream(org.postgresql.core.PGStream) PSQLException(org.postgresql.util.PSQLException) SQLException(java.sql.SQLException) SocketFactory(javax.net.SocketFactory) PSQLException(org.postgresql.util.PSQLException) ArrayList(java.util.ArrayList) HostChooser(org.postgresql.hostchooser.HostChooser) IOException(java.io.IOException) HostSpec(org.postgresql.util.HostSpec) Version(org.postgresql.core.Version) ServerVersion(org.postgresql.core.ServerVersion) HostRequirement(org.postgresql.hostchooser.HostRequirement) QueryExecutor(org.postgresql.core.QueryExecutor) HostStatus(org.postgresql.hostchooser.HostStatus) ConnectException(java.net.ConnectException)

Aggregations

IOException (java.io.IOException)1 ConnectException (java.net.ConnectException)1 SQLException (java.sql.SQLException)1 ArrayList (java.util.ArrayList)1 SocketFactory (javax.net.SocketFactory)1 PGStream (org.postgresql.core.PGStream)1 QueryExecutor (org.postgresql.core.QueryExecutor)1 ServerVersion (org.postgresql.core.ServerVersion)1 Version (org.postgresql.core.Version)1 HostChooser (org.postgresql.hostchooser.HostChooser)1 HostRequirement (org.postgresql.hostchooser.HostRequirement)1 HostStatus (org.postgresql.hostchooser.HostStatus)1 HostSpec (org.postgresql.util.HostSpec)1 PSQLException (org.postgresql.util.PSQLException)1