use of org.postgresql.hostchooser.HostStatus 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);
}
Aggregations