This is an automated email from the git hooks/post-receive script. ebourg-guest pushed a commit to annotated tag REL9_3_1102 in repository libpostgresql-jdbc-java.
commit bbb6fd0eca4bb9c7a44d8a47840be0feb7ff7942 Author: seregamorph <[email protected]> Date: Sat Apr 5 17:03:49 2014 +0400 connectTimeout property support --- doc/pgjdbc.xml | 12 ++++++ org/postgresql/core/PGStream.java | 17 +++++++- org/postgresql/core/v2/ConnectionFactoryImpl.java | 18 ++++++--- org/postgresql/core/v2/ProtocolConnectionImpl.java | 7 +++- org/postgresql/core/v3/ConnectionFactoryImpl.java | 18 ++++++--- org/postgresql/core/v3/ProtocolConnectionImpl.java | 7 +++- org/postgresql/test/jdbc2/ConnectTimeoutTest.java | 45 ++++++++++++++++++++++ org/postgresql/test/jdbc2/Jdbc2TestSuite.java | 4 +- 8 files changed, 110 insertions(+), 18 deletions(-) diff --git a/doc/pgjdbc.xml b/doc/pgjdbc.xml index 5f6f04e..4c7bb7b 100644 --- a/doc/pgjdbc.xml +++ b/doc/pgjdbc.xml @@ -725,6 +725,18 @@ openssl pkcs8 -topk8 -in client.key -out client.pk8 -outform DER -v1 PBE-SHA1-3D </listitem> </varlistentry> + <varlistentry> + <term><varname>connectTimeout</varname> = <type>int</type></term> + <listitem> + <para> + The timeout value used for socket connect operations. If connecting + to the server takes longer than this value, the connection is broken. + The timeout is specified in seconds and a value of zero means that + it is disabled. + </para> + </listitem> + </varlistentry> + <varlistentry> <term><varname>socketTimeout</varname> = <type>int</type></term> <listitem> diff --git a/org/postgresql/core/PGStream.java b/org/postgresql/core/PGStream.java index fad4c12..bf4b5c4 100644 --- a/org/postgresql/core/PGStream.java +++ b/org/postgresql/core/PGStream.java @@ -50,14 +50,15 @@ public class PGStream * a stream connection. * * @param hostSpec the host and port to connect to + * @param timeout timeout in milliseconds, or 0 if no timeout set * @exception IOException if an IOException occurs below it. */ - public PGStream(HostSpec hostSpec) throws IOException + public PGStream(HostSpec hostSpec, int timeout) throws IOException { this.hostSpec = hostSpec; Socket socket = new Socket(); - socket.connect(new InetSocketAddress(hostSpec.getHost(), hostSpec.getPort())); + socket.connect(new InetSocketAddress(hostSpec.getHost(), hostSpec.getPort()), timeout); changeSocket(socket); setEncoding(Encoding.getJVMEncoding("US-ASCII")); @@ -65,6 +66,18 @@ public class PGStream _int4buf = new byte[4]; } + /** + * Constructor: Connect to the PostgreSQL back end and return + * a stream connection. + * + * @param hostSpec the host and port to connect to + * @throws IOException if an IOException occurs below it. + * @deprecated use {@link #PGStream(org.postgresql.util.HostSpec, int)} + */ + public PGStream(HostSpec hostSpec) throws IOException { + this(hostSpec, 0); + } + public HostSpec getHostSpec() { return hostSpec; } diff --git a/org/postgresql/core/v2/ConnectionFactoryImpl.java b/org/postgresql/core/v2/ConnectionFactoryImpl.java index 07cf232..08ea0c3 100644 --- a/org/postgresql/core/v2/ConnectionFactoryImpl.java +++ b/org/postgresql/core/v2/ConnectionFactoryImpl.java @@ -78,16 +78,22 @@ public class ConnectionFactoryImpl extends ConnectionFactory { // // Establish a connection. // - + int connectTimeout = 0; + String connectTimeoutProperty = info.getProperty("connectTimeout", "0"); + try { + connectTimeout = Integer.parseInt(connectTimeoutProperty) * 1000; + } catch (NumberFormatException nfe) { + logger.info("Couldn't parse connectTimeout value:" + connectTimeoutProperty); + } PGStream newStream = null; try { - newStream = new PGStream(hostSpec); + newStream = new PGStream(hostSpec, connectTimeout); // Construct and send an ssl startup packet if requested. if (trySSL) - newStream = enableSSL(newStream, requireSSL, info, logger); + newStream = enableSSL(newStream, requireSSL, info, logger, connectTimeout); // Set the socket timeout if the "socketTimeout" property has been set. @@ -112,7 +118,7 @@ public class ConnectionFactoryImpl extends ConnectionFactory { doAuthentication(newStream, user, info.getProperty("password"), logger); // Do final startup. - ProtocolConnectionImpl protoConnection = new ProtocolConnectionImpl(newStream, user, database, logger); + ProtocolConnectionImpl protoConnection = new ProtocolConnectionImpl(newStream, user, database, logger, connectTimeout); readStartupMessages(newStream, protoConnection, logger); // Run some initial queries @@ -175,7 +181,7 @@ public class ConnectionFactoryImpl extends ConnectionFactory { throw new PSQLException (GT.tr("The connection url is invalid."), PSQLState.CONNECTION_UNABLE_TO_CONNECT); } - private PGStream enableSSL(PGStream pgStream, boolean requireSSL, Properties info, Logger logger) throws IOException, SQLException { + private PGStream enableSSL(PGStream pgStream, boolean requireSSL, Properties info, Logger logger, int connectTimeout) throws IOException, SQLException { if (logger.logDebug()) logger.debug(" FE=> SSLRequest"); @@ -199,7 +205,7 @@ public class ConnectionFactoryImpl extends ConnectionFactory { // We have to reconnect to continue. pgStream.close(); - return new PGStream(pgStream.getHostSpec()); + return new PGStream(pgStream.getHostSpec(), connectTimeout); case 'N': if (logger.logDebug()) diff --git a/org/postgresql/core/v2/ProtocolConnectionImpl.java b/org/postgresql/core/v2/ProtocolConnectionImpl.java index a7d588f..677c48a 100644 --- a/org/postgresql/core/v2/ProtocolConnectionImpl.java +++ b/org/postgresql/core/v2/ProtocolConnectionImpl.java @@ -24,12 +24,13 @@ import org.postgresql.util.HostSpec; * @author Oliver Jowett ([email protected]) */ class ProtocolConnectionImpl implements ProtocolConnection { - ProtocolConnectionImpl(PGStream pgStream, String user, String database, Logger logger) { + ProtocolConnectionImpl(PGStream pgStream, String user, String database, Logger logger, int connectTimeout) { this.pgStream = pgStream; this.user = user; this.database = database; this.logger = logger; this.executor = new QueryExecutorImpl(this, pgStream, logger); + this.connectTimeout = connectTimeout; } public HostSpec getHostSpec() { @@ -87,7 +88,7 @@ class ProtocolConnectionImpl implements ProtocolConnection { if (logger.logDebug()) logger.debug(" FE=> CancelRequest(pid=" + cancelPid + ",ckey=" + cancelKey + ")"); - cancelStream = new PGStream(pgStream.getHostSpec()); + cancelStream = new PGStream(pgStream.getHostSpec(), connectTimeout); cancelStream.SendInteger4(16); cancelStream.SendInteger2(1234); cancelStream.SendInteger2(5678); @@ -229,4 +230,6 @@ class ProtocolConnectionImpl implements ProtocolConnection { private final String database; private final QueryExecutorImpl executor; private final Logger logger; + + private final int connectTimeout; } diff --git a/org/postgresql/core/v3/ConnectionFactoryImpl.java b/org/postgresql/core/v3/ConnectionFactoryImpl.java index 3c7d332..84a5380 100644 --- a/org/postgresql/core/v3/ConnectionFactoryImpl.java +++ b/org/postgresql/core/v3/ConnectionFactoryImpl.java @@ -95,14 +95,22 @@ public class ConnectionFactoryImpl extends ConnectionFactory { // Establish a connection. // + int connectTimeout = 0; + String connectTimeoutProperty = info.getProperty("connectTimeout", "0"); + try { + connectTimeout = Integer.parseInt(connectTimeoutProperty) * 1000; + } catch (NumberFormatException nfe) { + logger.info("Couldn't parse connectTimeout value:" + connectTimeoutProperty); + } + PGStream newStream = null; try { - newStream = new PGStream(hostSpec); + newStream = new PGStream(hostSpec, connectTimeout); // Construct and send an ssl startup packet if requested. if (trySSL) - newStream = enableSSL(newStream, requireSSL, info, logger); + newStream = enableSSL(newStream, requireSSL, info, logger, connectTimeout); // Set the socket timeout if the "socketTimeout" property has been set. String socketTimeoutProperty = info.getProperty("socketTimeout", "0"); @@ -173,7 +181,7 @@ public class ConnectionFactoryImpl extends ConnectionFactory { doAuthentication(newStream, hostSpec.getHost(), user, info, logger); // Do final startup. - ProtocolConnectionImpl protoConnection = new ProtocolConnectionImpl(newStream, user, database, info, logger); + ProtocolConnectionImpl protoConnection = new ProtocolConnectionImpl(newStream, user, database, info, logger, connectTimeout); readStartupMessages(newStream, protoConnection, logger); runInitialQueries(protoConnection, info, logger); @@ -272,7 +280,7 @@ public class ConnectionFactoryImpl extends ConnectionFactory { return start + tz.substring(4); } - private PGStream enableSSL(PGStream pgStream, boolean requireSSL, Properties info, Logger logger) throws IOException, SQLException { + private PGStream enableSSL(PGStream pgStream, boolean requireSSL, Properties info, Logger logger, int connectTimeout) throws IOException, SQLException { if (logger.logDebug()) logger.debug(" FE=> SSLRequest"); @@ -296,7 +304,7 @@ public class ConnectionFactoryImpl extends ConnectionFactory { // We have to reconnect to continue. pgStream.close(); - return new PGStream(pgStream.getHostSpec()); + return new PGStream(pgStream.getHostSpec(), connectTimeout); case 'N': if (logger.logDebug()) diff --git a/org/postgresql/core/v3/ProtocolConnectionImpl.java b/org/postgresql/core/v3/ProtocolConnectionImpl.java index 92073e3..75e911e 100644 --- a/org/postgresql/core/v3/ProtocolConnectionImpl.java +++ b/org/postgresql/core/v3/ProtocolConnectionImpl.java @@ -27,7 +27,7 @@ import java.util.Properties; * @author Oliver Jowett ([email protected]) */ class ProtocolConnectionImpl implements ProtocolConnection { - ProtocolConnectionImpl(PGStream pgStream, String user, String database, Properties info, Logger logger) { + ProtocolConnectionImpl(PGStream pgStream, String user, String database, Properties info, Logger logger, int connectTimeout) { this.pgStream = pgStream; this.user = user; this.database = database; @@ -35,6 +35,7 @@ class ProtocolConnectionImpl implements ProtocolConnection { this.executor = new QueryExecutorImpl(this, pgStream, info, logger); // default value for server versions that don't report standard_conforming_strings this.standardConformingStrings = false; + this.connectTimeout = connectTimeout; } public HostSpec getHostSpec() { @@ -89,7 +90,7 @@ class ProtocolConnectionImpl implements ProtocolConnection { if (logger.logDebug()) logger.debug(" FE=> CancelRequest(pid=" + cancelPid + ",ckey=" + cancelKey + ")"); - cancelStream = new PGStream(pgStream.getHostSpec()); + cancelStream = new PGStream(pgStream.getHostSpec(), connectTimeout); cancelStream.SendInteger4(16); cancelStream.SendInteger2(1234); cancelStream.SendInteger2(5678); @@ -249,4 +250,6 @@ class ProtocolConnectionImpl implements ProtocolConnection { private final String database; private final QueryExecutorImpl executor; private final Logger logger; + + private final int connectTimeout; } diff --git a/org/postgresql/test/jdbc2/ConnectTimeoutTest.java b/org/postgresql/test/jdbc2/ConnectTimeoutTest.java new file mode 100644 index 0000000..71e0f34 --- /dev/null +++ b/org/postgresql/test/jdbc2/ConnectTimeoutTest.java @@ -0,0 +1,45 @@ +package org.postgresql.test.jdbc2; + +import junit.framework.Assert; +import junit.framework.TestCase; +import org.postgresql.test.TestUtil; + +import java.net.SocketTimeoutException; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Properties; + +public class ConnectTimeoutTest extends TestCase { + private static final String UNREACHABLE_HOST = "1.0.0.0"; + private static final String UNREACHABLE_URL = "jdbc:postgresql://" + UNREACHABLE_HOST + "/test"; + private static final int CONNECT_TIMEOUT = 10; + + @Override + protected void setUp() throws Exception { + super.setUp(); + TestUtil.initDriver(); + } + + public void testTimeout() { + final Properties props = new Properties(); + props.setProperty("user", "test"); + props.setProperty("password", "test"); + // with 0 (default value) it hangs for about 60 seconds (platform dependent) + props.setProperty("connectTimeout", Integer.toString(CONNECT_TIMEOUT)); + + final long startTime = System.currentTimeMillis(); + try { + DriverManager.getConnection(UNREACHABLE_URL, props); + } catch (SQLException e) { + Assert.assertTrue("Unexpected " + e.toString(), + e.getCause() instanceof SocketTimeoutException); + final long interval = System.currentTimeMillis() - startTime; + final long connectTimeoutMillis = CONNECT_TIMEOUT * 1000; + final long maxDeviation = connectTimeoutMillis / 10; + // check that it was not a default system timeout, an approximate value is used + Assert.assertTrue(Math.abs(interval - connectTimeoutMillis) < maxDeviation); + return; + } + fail("SQLException expected"); + } +} diff --git a/org/postgresql/test/jdbc2/Jdbc2TestSuite.java b/org/postgresql/test/jdbc2/Jdbc2TestSuite.java index 732e498..cda45aa 100644 --- a/org/postgresql/test/jdbc2/Jdbc2TestSuite.java +++ b/org/postgresql/test/jdbc2/Jdbc2TestSuite.java @@ -92,7 +92,9 @@ public class Jdbc2TestSuite extends TestSuite suite.addTestSuite(LoginTimeoutTest.class); suite.addTestSuite(TestACL.class); - + + suite.addTestSuite(ConnectTimeoutTest.class); + Connection conn = TestUtil.openDB(); if (TestUtil.isProtocolVersion(conn, 3)) { suite.addTestSuite(CopyTest.class); -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/libpostgresql-jdbc-java.git _______________________________________________ pkg-java-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-java-commits

