Skip to content

Commit

Permalink
Hotfix 10.2.1 (#1830)
Browse files Browse the repository at this point in the history
  • Loading branch information
tkyc authored May 11, 2022
1 parent 468a35a commit 11179a5
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 227 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/)

## [10.2.1] HotFix & Stable Release
### Fixed issues
- Refactored Idle Connection Resiliency timeout to use existing SharedTimer [1794](https://github.com/microsoft/mssql-jdbc/pull/1794)
- Fixed Managed Identity retry interval to exponential backoff properly [1770](https://github.com/microsoft/mssql-jdbc/pull/1770)
- Removed extra call to executeCommand() within connectionCommand() [1754](https://github.com/microsoft/mssql-jdbc/pull/1754)

## [10.2.0] Stable Release
### Added
- Support for datetimeoffset with sql_variant [1673](https://github.com/microsoft/mssql-jdbc/pull/1673)
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ We're now on the Maven Central Repository. Add the following to your POM file to
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>10.2.0.jre17</version>
<version>10.2.1.jre17</version>
</dependency>
```
The driver can be downloaded from the [Microsoft Download Center](https://go.microsoft.com/fwlink/?linkid=2168495).
Expand All @@ -91,7 +91,7 @@ To get the latest preview version of the driver, add the following to your POM f
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>10.2.0.jre17</version>
<version>10.2.1.jre17</version>
</dependency>
```

Expand Down Expand Up @@ -126,7 +126,7 @@ Projects that require either of the two features need to explicitly declare the
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>10.2.0.jre17</version>
<version>10.2.1.jre17</version>
<scope>compile</scope>
</dependency>

Expand All @@ -144,7 +144,7 @@ Projects that require either of the two features need to explicitly declare the
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>10.2.0.jre17</version>
<version>10.2.1.jre17</version>
<scope>compile</scope>
</dependency>

Expand All @@ -171,7 +171,7 @@ When setting 'useFmtOnly' property to 'true' for establishing a connection or cr
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>10.2.0.jre17</version>
<version>10.2.1.jre17</version>
</dependency>

<dependency>
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

apply plugin: 'java'

version = '10.2.0'
version = '10.2.1'
def jreVersion = ""
def testOutputDir = file("build/classes/java/test")
def archivesBaseName = 'mssql-jdbc'
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>10.2.0</version>
<version>10.2.1</version>
<packaging>jar</packaging>

<name>Microsoft JDBC Driver for SQL Server</name>
Expand Down
56 changes: 0 additions & 56 deletions src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -7531,43 +7531,6 @@ final void trySetSensitivityClassification(SensitivityClassification sensitivity
}


/**
* The tds default implementation of a timeout command
*/
class TdsTimeoutCommand extends TimeoutCommand<TDSCommand> {
protected TdsTimeoutCommand(int timeout, TDSCommand command, SQLServerConnection sqlServerConnection) {
super(timeout, command, sqlServerConnection);
}

protected void interrupt() throws Exception {
TDSCommand command = getCommand();
SQLServerConnection sqlServerConnection = getSqlServerConnection();
try {
// If TCP Connection to server is silently dropped, exceeding the query timeout
// on the same connection does
// not throw SQLTimeoutException
// The application stops responding instead until SocketTimeoutException is
// thrown. In this case, we must
// manually terminate the connection.
if (null == command && null != sqlServerConnection) {
sqlServerConnection.terminate(SQLServerException.DRIVER_ERROR_IO_FAILED,
SQLServerException.getErrString("R_connectionIsClosed"));
} else {
// If the timer wasn't canceled before it ran out of
// time then interrupt the registered command.
if (null != command)
command.interrupt(SQLServerException.getErrString("R_queryTimedOut"));
}
} catch (SQLServerException e) {
// Request failed to time out and SQLServerConnection does not exist
if (null != command)
command.log(Level.FINE, "Command could not be timed out. Reason: " + e.getMessage());
throw new SQLServerException(SQLServerException.getErrString("R_crCommandCannotTimeOut"), e);
}
}
}


/**
* TDSCommand encapsulates an interruptable TDS conversation.
*
Expand Down Expand Up @@ -7695,13 +7658,7 @@ protected void setProcessedResponse(boolean processedResponse) {
private int queryTimeoutSeconds;
private int cancelQueryTimeoutSeconds;
private ScheduledFuture<?> timeout;
private TdsTimeoutCommand timeoutCommand;

/*
* Some flags for Connection Resiliency. We need to know if a command has already been registered in the poller, or
* if it was actually executed.
*/
private boolean isRegisteredInPoller = false;
private boolean isExecuted = false;

protected int getQueryTimeoutSeconds() {
Expand Down Expand Up @@ -7735,18 +7692,6 @@ void createCounter(ICounter previousCounter, Properties activeConnectionProperti
}
}

synchronized void addToPoller() {
if (!isRegisteredInPoller) {
// If command execution is subject to timeout then start timing until
// the server returns the first response packet.
if (queryTimeoutSeconds > 0) {
this.timeoutCommand = new TdsTimeoutCommand(queryTimeoutSeconds, this, null);
TimeoutPoller.getTimeoutPoller().addTimeoutCommand(this.timeoutCommand);
isRegisteredInPoller = true;
}
}
}

boolean wasExecuted() {
return isExecuted;
}
Expand Down Expand Up @@ -8162,7 +8107,6 @@ final TDSReader startResponse(boolean isAdaptive) throws SQLServerException {
SQLServerConnection conn = tdsReader != null ? tdsReader.getConnection() : null;
this.timeout = tdsWriter.getSharedTimer().schedule(new TDSTimeoutTask(this, conn), queryTimeoutSeconds);
}
addToPoller();

if (logger.isLoggable(Level.FINEST))
logger.finest(this.toString() + ": Reading response...");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,23 @@

package com.microsoft.sqlserver.jdbc;

import java.lang.Thread.State;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;


class IdleConnectionResiliency {
private static final java.util.logging.Logger loggerExternal = java.util.logging.Logger
.getLogger("com.microsoft.sqlserver.jdbc.IdleConnectionResiliency");
private boolean connectionRecoveryNegotiated;
private int connectRetryCount;
private SQLServerConnection connection;
private SessionStateTable sessionStateTable;
private ReconnectThread reconnectThread;
private AtomicInteger unprocessedResponseCount = new AtomicInteger();
private boolean connectionRecoveryPossible;
private SQLServerException reconnectErrorReceived = null;

/*
* Variables needed to perform a reconnect, these are not necessarily determined from just the connection string
Expand All @@ -27,7 +33,6 @@ class IdleConnectionResiliency {

IdleConnectionResiliency(SQLServerConnection connection) {
this.connection = connection;
reconnectThread = new ReconnectThread(connection);
}

boolean isConnectionRecoveryNegotiated() {
Expand All @@ -54,8 +59,8 @@ void setConnection(SQLServerConnection connection) {
this.connection = connection;
}

ReconnectThread getReconnectThread() {
return reconnectThread;
boolean isReconnectRunning() {
return reconnectThread != null && (reconnectThread.getState() != State.TERMINATED);
}

SessionStateTable getSessionStateTable() {
Expand Down Expand Up @@ -105,24 +110,34 @@ void parseInitialSessionStateData(byte[] data, byte[][] sessionStateInitial) thr
}

void incrementUnprocessedResponseCount() {
if (connection.getRetryCount() > 0 && !getReconnectThread().isAlive()) {
if (unprocessedResponseCount.incrementAndGet() < 0)
if (connection.getRetryCount() > 0 && !isReconnectRunning()) {
if (unprocessedResponseCount.incrementAndGet() < 0) {
/*
* When this number rolls over, connection recovery is disabled for the rest of the life of the
* connection.
*/
if (loggerExternal.isLoggable(Level.FINER)) {
loggerExternal.finer("unprocessedResponseCount < 0 on increment. Disabling connection resiliency.");
}

setConnectionRecoveryPossible(false);
}
}
}

void decrementUnprocessedResponseCount() {
if (connection.getRetryCount() > 0 && !getReconnectThread().isAlive()) {
if (unprocessedResponseCount.decrementAndGet() < 0)
if (connection.getRetryCount() > 0 && !isReconnectRunning()) {
if (unprocessedResponseCount.decrementAndGet() < 0) {
/*
* When this number rolls over, connection recovery is disabled for the rest of the life of the
* connection.
*/
if (loggerExternal.isLoggable(Level.FINER)) {
loggerExternal.finer("unprocessedResponseCount < 0 on decrement. Disabling connection resiliency.");
}

setConnectionRecoveryPossible(false);
}
}
}

Expand All @@ -148,6 +163,20 @@ FailoverInfo getFailoverInfo() {
int getLoginTimeoutSeconds() {
return loginLoginTimeoutSeconds;
}

void reconnect(TDSCommand cmd) throws InterruptedException {
reconnectErrorReceived = null;
reconnectThread = new ReconnectThread(this.connection, cmd);
reconnectThread.start();
reconnectThread.join();
reconnectErrorReceived = reconnectThread.getException();
// Remove reference so GC can clean it up
reconnectThread = null;
}

SQLServerException getReconnectException() {
return reconnectErrorReceived;
}
}


Expand Down Expand Up @@ -370,6 +399,8 @@ public void reset() {


final class ReconnectThread extends Thread {
static final java.util.logging.Logger loggerExternal = java.util.logging.Logger
.getLogger("com.microsoft.sqlserver.jdbc.ReconnectThread");
private SQLServerConnection con = null;
private SQLServerException eReceived = null;
private TDSCommand command = null;
Expand All @@ -384,19 +415,23 @@ final class ReconnectThread extends Thread {
@SuppressWarnings("unused")
private ReconnectThread() {};

ReconnectThread(SQLServerConnection sqlC) {
ReconnectThread(SQLServerConnection sqlC, TDSCommand cmd) {
this.con = sqlC;
}

// Resets the thread
void init(TDSCommand cmd) {
this.command = cmd;
connectRetryCount = con.getRetryCount();
eReceived = null;
stopRequested = false;
if (loggerExternal.isLoggable(Level.FINER)) {
loggerExternal.finer("ReconnectThread initialized. Connection retry count = " + connectRetryCount
+ "; Command = " + cmd.toString());
}

}

public void run() {
if (loggerExternal.isLoggable(Level.FINER)) {
loggerExternal.finer("Starting ReconnectThread for command: " + command.toString());
}
boolean interruptsEnabled = command.getInterruptsEnabled();
/*
* All TDSCommands are not interruptible before execution, and all the commands passed to here won't have been
Expand All @@ -405,10 +440,24 @@ public void run() {
*/
command.setInterruptsEnabled(true);
command.attachThread(this);
command.addToPoller();

// We need a reference to the SharedTimer outside of the context of the connection
SharedTimer timer = null;
ScheduledFuture<?> timeout = null;

if (command.getQueryTimeoutSeconds() > 0) {
timer = SharedTimer.getTimer();
timeout = timer.schedule(new TDSTimeoutTask(command, null),
command.getQueryTimeoutSeconds());
}

boolean keepRetrying = true;

while ((connectRetryCount != 0) && (!stopRequested) && keepRetrying) {
while ((connectRetryCount > 0) && (!stopRequested) && keepRetrying) {
if (loggerExternal.isLoggable(Level.FINER)) {
loggerExternal.finer("Running reconnect for command: " + command.toString() + " ; ConnectRetryCount = "
+ connectRetryCount);
}
try {
eReceived = null;
con.connect(null, con.getPooledConnectionParent());
Expand Down Expand Up @@ -451,10 +500,26 @@ public void run() {
}

command.setInterruptsEnabled(interruptsEnabled);
return;

if (loggerExternal.isLoggable(Level.FINER)) {
loggerExternal.finer("ReconnectThread exiting for command: " + command.toString());
}

if (timeout != null) {
timeout.cancel(false);
timeout = null;
}

if (timer != null) {
timer.removeRef();
timer = null;
}
}

void stop(boolean blocking) {
if (loggerExternal.isLoggable(Level.FINER)) {
loggerExternal.finer("ReconnectThread stop requested for command: " + command.toString());
}
stopRequested = true;
if (blocking && this.isAlive()) {
while (this.getState() != State.TERMINATED) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
final class SQLJdbcVersion {
static final int major = 10;
static final int minor = 2;
static final int patch = 0;
static final int patch = 1;
static final int build = 0;
/*
* Used to load mssql-jdbc_auth DLL.
Expand Down
Loading

0 comments on commit 11179a5

Please sign in to comment.