From 94e6e4dfff0f8d0904f3d612d789cbd9d440d69b Mon Sep 17 00:00:00 2001 From: v-xiangs Date: Tue, 20 Dec 2016 14:54:29 -0800 Subject: [PATCH 1/2] socket timeout implementation for both connection string and data source --- .../microsoft/sqlserver/jdbc/IOBuffer.java | 4 ++ .../sqlserver/jdbc/SQLServerConnection.java | 37 +++++++++++++++++-- .../sqlserver/jdbc/SQLServerDataSource.java | 10 +++++ .../sqlserver/jdbc/SQLServerDriver.java | 6 ++- .../sqlserver/jdbc/SQLServerResource.java | 2 + 5 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java index 8930d8118..d20754251 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java @@ -616,6 +616,10 @@ final void open( // Set socket options tcpSocket.setTcpNoDelay(true); tcpSocket.setKeepAlive(true); + + //set SO_TIMEOUT + int socketTimeout = con.getSocketTimeoutSeconds(); + tcpSocket.setSoTimeout(socketTimeout); inputStream = tcpInputStream = tcpSocket.getInputStream(); outputStream = tcpOutputStream = tcpSocket.getOutputStream(); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index c1573622a..d7bc95c7a 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -253,6 +253,8 @@ final ApplicationIntent getApplicationIntent() final String getResponseBuffering() { return responseBuffering; } private int queryTimeoutSeconds ; final int getQueryTimeoutSeconds() { return queryTimeoutSeconds; } + private int socketTimeoutSeconds ; + final int getSocketTimeoutSeconds() { return socketTimeoutSeconds; } private boolean sendTimeAsDatetime = SQLServerDriverBooleanProperty.SEND_TIME_AS_DATETIME.getDefaultValue(); @@ -1435,15 +1437,15 @@ else if (0 == requestedPacketSize) } sPropKey = SQLServerDriverIntProperty.LOCK_TIMEOUT.toString(); - int defaultTimeOut = SQLServerDriverIntProperty.LOCK_TIMEOUT.getDefaultValue(); - nLockTimeout = defaultTimeOut; //Wait forever + int defaultLockTimeOut = SQLServerDriverIntProperty.LOCK_TIMEOUT.getDefaultValue(); + nLockTimeout = defaultLockTimeOut; //Wait forever if (activeConnectionProperties.getProperty(sPropKey) != null && activeConnectionProperties.getProperty(sPropKey).length() > 0) { try { int n = (new Integer(activeConnectionProperties.getProperty(sPropKey))).intValue(); - if (n>=defaultTimeOut) + if (n>=defaultLockTimeOut) nLockTimeout = n; else { @@ -1469,7 +1471,7 @@ else if (0 == requestedPacketSize) try { int n = (new Integer(activeConnectionProperties.getProperty(sPropKey))).intValue(); - if (n>=defaultTimeOut){ + if (n>=defaultQueryTimeout){ queryTimeoutSeconds = n; } else @@ -1486,6 +1488,33 @@ else if (0 == requestedPacketSize) SQLServerException.makeFromDriverError(this, this, form.format(msgArgs), null, false); } } + + sPropKey = SQLServerDriverIntProperty.SOCKET_TIMEOUT.toString(); + int defaultSocketTimeout = SQLServerDriverIntProperty.SOCKET_TIMEOUT.getDefaultValue(); + socketTimeoutSeconds = defaultSocketTimeout; //Wait forever + if (activeConnectionProperties.getProperty(sPropKey) != null && + activeConnectionProperties.getProperty(sPropKey).length() > 0) + { + try + { + int n = (new Integer(activeConnectionProperties.getProperty(sPropKey))).intValue(); + if (n>=defaultSocketTimeout){ + socketTimeoutSeconds = n; + } + else + { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidSocketTimeout")); + Object[] msgArgs = {activeConnectionProperties.getProperty(sPropKey)}; + SQLServerException.makeFromDriverError(this, this, form.format(msgArgs), null, false); + } + } + catch (NumberFormatException e) + { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidSocketTimeout")); + Object[] msgArgs = {activeConnectionProperties.getProperty(sPropKey)}; + SQLServerException.makeFromDriverError(this, this, form.format(msgArgs), null, false); + } + } FailoverInfo fo =null; String databaseNameProperty = SQLServerDriverStringProperty.DATABASE_NAME.toString(); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java index 646030fdb..261c87775 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java @@ -618,6 +618,16 @@ public int getPacketSize() { return getIntProperty(connectionProps, SQLServerDriverIntProperty.PACKET_SIZE.toString(), SQLServerDriverIntProperty.PACKET_SIZE.getDefaultValue()); } + + public void setSocketTimeout(int socketTimeout) + { + setIntProperty(connectionProps, SQLServerDriverIntProperty.SOCKET_TIMEOUT.toString(), socketTimeout); + } + public int getSocketTimeout() + { + int defaultTimeOut = SQLServerDriverIntProperty.SOCKET_TIMEOUT.getDefaultValue(); + return getIntProperty(connectionProps, SQLServerDriverIntProperty.SOCKET_TIMEOUT.toString(), defaultTimeOut); + } // responseBuffering controls the driver's buffering of responses from SQL Server. // Possible values are: diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java index 4e0e5012d..d899b9f11 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java @@ -277,8 +277,9 @@ enum SQLServerDriverIntProperty PACKET_SIZE("packetSize", TDS.DEFAULT_PACKET_SIZE), LOCK_TIMEOUT("lockTimeout", -1), LOGIN_TIMEOUT("loginTimeout", 15), - QUERY_TIMEOUT("queryTimeout", -1), - PORT_NUMBER("portNumber", 1433); + QUERY_TIMEOUT("queryTimeout", -1), + PORT_NUMBER("portNumber", 1433), + SOCKET_TIMEOUT("socketTimeout", 0); private String name; private int defaultValue; @@ -381,6 +382,7 @@ public final class SQLServerDriver implements java.sql.Driver new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.XOPEN_STATES.toString(), Boolean.toString(SQLServerDriverBooleanProperty.XOPEN_STATES.getDefaultValue()), false, TRUE_FALSE), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.AUTHENTICATION_SCHEME.toString(), SQLServerDriverStringProperty.AUTHENTICATION_SCHEME.getDefaultValue(), false, new String[] {AuthenticationScheme.javaKerberos.toString(),AuthenticationScheme.nativeAuthentication.toString()}), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.AUTHENTICATION.toString(), SQLServerDriverStringProperty.AUTHENTICATION.getDefaultValue(), false, new String[] {SqlAuthentication.NotSpecified.toString(),SqlAuthentication.SqlPassword.toString(),SqlAuthentication.ActiveDirectoryPassword.toString(),SqlAuthentication.ActiveDirectoryIntegrated.toString()}), + new SQLServerDriverPropertyInfo(SQLServerDriverIntProperty.SOCKET_TIMEOUT.toString(), Integer.toString(SQLServerDriverIntProperty.SOCKET_TIMEOUT.getDefaultValue()), false, null), }; //Properties that can only be set by using Properties. diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index 6db659df6..6d2da6ea6 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -200,6 +200,7 @@ protected Object[][] getContents() {"R_sendTimeAsDatetimePropertyDescription", "Determines whether to use the SQL Server datetime data type to send java.sql.Time values to the database."}, {"R_TransparentNetworkIPResolutionPropertyDescription", "Determines whether to use the Transparent Network IP Resolution feature."}, {"R_queryTimeoutPropertyDescription", "The number of seconds to wait before the database reports a query time-out."}, + {"R_socketTimeoutPropertyDescription", "The number of milliseconds to wait before the java.net.SocketTimeoutException is raised."}, {"R_noParserSupport", "An error occurred while instantiating the required parser. Error: \"{0}\""}, {"R_writeOnlyXML", "Cannot read from this SQLXML instance. This instance is for writing data only."}, {"R_dataHasBeenReadXML", "Cannot read from this SQLXML instance. The data has already been read."}, @@ -382,6 +383,7 @@ protected Object[][] getContents() {"R_invalidServerCursorForTVP" , "Use different Connection for source ResultSet and prepared query, if selectMethod is set to cursor for Table-Valued Parameter."}, {"R_TVPnotWorkWithSetObjectResultSet" , "setObject() with ResultSet is not supported for Table-Valued Parameter. Please use setStructured()"}, {"R_invalidQueryTimeout", "The queryTimeout {0} is not valid."}, + {"R_invalidSocketTimeout", "The socketTimeout {0} is not valid."}, }; } From b1ab70bd12c50618cccd702ab10f15b3b55ddc1e Mon Sep 17 00:00:00 2001 From: v-xiangs Date: Wed, 21 Dec 2016 09:33:48 -0800 Subject: [PATCH 2/2] change socket timout names --- src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java | 2 +- .../com/microsoft/sqlserver/jdbc/SQLServerConnection.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java index d20754251..caa47e6a2 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java @@ -618,7 +618,7 @@ final void open( tcpSocket.setKeepAlive(true); //set SO_TIMEOUT - int socketTimeout = con.getSocketTimeoutSeconds(); + int socketTimeout = con.getSocketTimeoutMilliseconds(); tcpSocket.setSoTimeout(socketTimeout); inputStream = tcpInputStream = tcpSocket.getInputStream(); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index d7bc95c7a..db77bdf4f 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -253,8 +253,8 @@ final ApplicationIntent getApplicationIntent() final String getResponseBuffering() { return responseBuffering; } private int queryTimeoutSeconds ; final int getQueryTimeoutSeconds() { return queryTimeoutSeconds; } - private int socketTimeoutSeconds ; - final int getSocketTimeoutSeconds() { return socketTimeoutSeconds; } + private int socketTimeoutMilliseconds ; + final int getSocketTimeoutMilliseconds() { return socketTimeoutMilliseconds; } private boolean sendTimeAsDatetime = SQLServerDriverBooleanProperty.SEND_TIME_AS_DATETIME.getDefaultValue(); @@ -1491,7 +1491,7 @@ else if (0 == requestedPacketSize) sPropKey = SQLServerDriverIntProperty.SOCKET_TIMEOUT.toString(); int defaultSocketTimeout = SQLServerDriverIntProperty.SOCKET_TIMEOUT.getDefaultValue(); - socketTimeoutSeconds = defaultSocketTimeout; //Wait forever + socketTimeoutMilliseconds = defaultSocketTimeout; //Wait forever if (activeConnectionProperties.getProperty(sPropKey) != null && activeConnectionProperties.getProperty(sPropKey).length() > 0) { @@ -1499,7 +1499,7 @@ else if (0 == requestedPacketSize) { int n = (new Integer(activeConnectionProperties.getProperty(sPropKey))).intValue(); if (n>=defaultSocketTimeout){ - socketTimeoutSeconds = n; + socketTimeoutMilliseconds = n; } else {