Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loom friendly synchronization. #1931

Merged
merged 6 commits into from
Oct 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 31 additions & 20 deletions src/main/java/com/microsoft/sqlserver/jdbc/FailOverInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
package com.microsoft.sqlserver.jdbc;

import java.text.MessageFormat;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;


Expand All @@ -19,6 +21,7 @@ final class FailoverInfo {
private int portNumber;
private String failoverInstance;
private boolean setUpInfocalled;
private final Lock lock = new ReentrantLock();

// This member is exposed outside for reading, we need to know in advance if the
// failover partner is the currently active server before making a DNS resolution and a connect attempt.
Expand Down Expand Up @@ -80,29 +83,37 @@ private void setupInfo(SQLServerConnection con) throws SQLServerException {
setUpInfocalled = true;
}

synchronized ServerPortPlaceHolder failoverPermissionCheck(SQLServerConnection con,
boolean link) throws SQLServerException {
setupInfo(con);
return new ServerPortPlaceHolder(failoverPartner, portNumber, failoverInstance, link);
ServerPortPlaceHolder failoverPermissionCheck(SQLServerConnection con, boolean link) throws SQLServerException {
lock.lock();
try {
setupInfo(con);
return new ServerPortPlaceHolder(failoverPartner, portNumber, failoverInstance, link);
} finally {
lock.unlock();
}
}

// Add/replace the failover server,
synchronized void failoverAdd(SQLServerConnection connection, boolean actualUseFailoverPartner,
String actualFailoverPartner) throws SQLServerException {
if (useFailoverPartner != actualUseFailoverPartner) {
if (connection.getConnectionLogger().isLoggable(Level.FINE))
connection.getConnectionLogger()
.fine(connection.toString() + " Failover detected. failover partner=" + actualFailoverPartner);
useFailoverPartner = actualUseFailoverPartner;
}
// The checking for actualUseFailoverPartner may look weird but this is required
// We only change the failoverpartner info when we connect to the primary
// if we connect to the secondary and it sends a failover partner
// we wont store that information.
if (!actualUseFailoverPartner && !failoverPartner.equals(actualFailoverPartner)) {
failoverPartner = actualFailoverPartner;
// new FO partner need to setup again.
setUpInfocalled = false;
void failoverAdd(SQLServerConnection connection, boolean actualUseFailoverPartner, String actualFailoverPartner) {
lock.lock();
try {
if (useFailoverPartner != actualUseFailoverPartner) {
if (connection.getConnectionLogger().isLoggable(Level.FINE))
connection.getConnectionLogger()
.fine(connection.toString() + " Failover detected. failover partner=" + actualFailoverPartner);
useFailoverPartner = actualUseFailoverPartner;
}
// The checking for actualUseFailoverPartner may look weird but this is required
// We only change the failoverpartner info when we connect to the primary
// if we connect to the secondary and it sends a failover partner
// we wont store that information.
if (!actualUseFailoverPartner && !failoverPartner.equals(actualFailoverPartner)) {
failoverPartner = actualFailoverPartner;
// new FO partner need to setup again.
setUpInfocalled = false;
}
} finally {
lock.unlock();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
package com.microsoft.sqlserver.jdbc;

import java.util.HashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;


final class FailoverMapSingleton {
private static int initialHashmapSize = 5;
private static HashMap<String, FailoverInfo> failoverMap = new HashMap<>(initialHashmapSize);
private static final Lock LOCK = new ReentrantLock();

private FailoverMapSingleton() {
/* hide the constructor to stop the instantiation of this class. */}
Expand All @@ -30,7 +33,8 @@ private static String concatPrimaryDatabase(String primary, String instance, Str

static FailoverInfo getFailoverInfo(SQLServerConnection connection, String primaryServer, String instance,
String database) {
synchronized (FailoverMapSingleton.class) {
LOCK.lock();
try {
if (failoverMap.isEmpty()) {
return null;
} else {
Expand All @@ -43,6 +47,8 @@ static FailoverInfo getFailoverInfo(SQLServerConnection connection, String prima
fo.log(connection);
return fo;
}
} finally {
LOCK.unlock();
}
}

Expand All @@ -54,7 +60,8 @@ static void putFailoverInfo(SQLServerConnection connection, String primaryServer
String failoverPartner) throws SQLServerException {
FailoverInfo fo;

synchronized (FailoverMapSingleton.class) {
LOCK.lock();
try {
// one more check to make sure someone already did not do this
if (null == (fo = getFailoverInfo(connection, primaryServer, instance, database))) {
if (connection.getConnectionLogger().isLoggable(Level.FINE))
Expand All @@ -64,6 +71,8 @@ static void putFailoverInfo(SQLServerConnection connection, String primaryServer
} else
// if the class exists make sure the latest info is updated
fo.failoverAdd(connection, actualuseFailover, failoverPartner);
} finally {
LOCK.unlock();
}
}
}
Loading