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

replace synchronised with RetrantLock - so that its JDK 21 Virtual thread Project loom friendly. #110

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
92 changes: 49 additions & 43 deletions src/main/java/com/amazon/redshift/Driver.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,9 @@

package com.amazon.redshift;

import com.amazon.redshift.jdbc.RedshiftConnectionImpl;
import com.amazon.redshift.logger.LogLevel;
import com.amazon.redshift.logger.RedshiftLogger;
import com.amazon.redshift.util.DriverInfo;
import com.amazon.redshift.util.ExpressionProperties;
import com.amazon.redshift.util.GT;
import com.amazon.redshift.util.HostSpec;
import com.amazon.redshift.util.IniFile;
import com.amazon.redshift.util.RedshiftException;
import com.amazon.redshift.util.RedshiftState;
import com.amazon.redshift.util.SharedTimer;
import com.amazon.redshift.util.URLCoder;
import com.amazon.redshift.util.RedshiftProperties;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.InitialDirContext;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedActionException;
Expand All @@ -41,11 +21,31 @@
import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.naming.Context;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.InitialDirContext;

import com.amazon.redshift.jdbc.RedshiftConnectionImpl;
import com.amazon.redshift.jdbc.ResourceLock;
import com.amazon.redshift.logger.LogLevel;
import com.amazon.redshift.logger.RedshiftLogger;
import com.amazon.redshift.util.DriverInfo;
import com.amazon.redshift.util.ExpressionProperties;
import com.amazon.redshift.util.GT;
import com.amazon.redshift.util.HostSpec;
import com.amazon.redshift.util.IniFile;
import com.amazon.redshift.util.RedshiftException;
import com.amazon.redshift.util.RedshiftProperties;
import com.amazon.redshift.util.RedshiftState;
import com.amazon.redshift.util.SharedTimer;
import com.amazon.redshift.util.URLCoder;

/**
* <p>The Java SQL framework allows for multiple database drivers. Each driver should supply a class
* that implements the Driver interface</p>
Expand Down Expand Up @@ -97,29 +97,32 @@ public class Driver implements java.sql.Driver {
throw new ExceptionInInitializerError(e);
}
}
private final ResourceLock lock = new ResourceLock();

// Helper to retrieve default properties from classloader resource
// properties files.
private Properties defaultProperties;

private synchronized Properties getDefaultProperties() throws IOException {
if (defaultProperties != null) {
return defaultProperties;
}

// Make sure we load properties with the maximum possible privileges.
try {
defaultProperties =
AccessController.doPrivileged(new PrivilegedExceptionAction<Properties>() {
public Properties run() throws IOException {
return loadDefaultProperties();
}
});
} catch (PrivilegedActionException e) {
throw (IOException) e.getException();
}

return defaultProperties;
private Properties getDefaultProperties() throws IOException {
try(ResourceLock ignore = lock.obtain()){
if (defaultProperties != null) {
return defaultProperties;
}

// Make sure we load properties with the maximum possible privileges.
try {
defaultProperties =
AccessController.doPrivileged(new PrivilegedExceptionAction<Properties>() {
public Properties run() throws IOException {
return loadDefaultProperties();
}
});
} catch (PrivilegedActionException e) {
throw (IOException) e.getException();
}

return defaultProperties;
}
}

private Properties loadDefaultProperties() throws IOException {
Expand Down Expand Up @@ -376,6 +379,9 @@ private RedshiftLogger getLogger(final Properties props) {
* while enforcing a login timeout.
*/
private static class ConnectThread implements Runnable {
private final ResourceLock lock = new ResourceLock();
private final Condition lockCondition = lock.newCondition();

ConnectThread(String url, RedshiftProperties props, RedshiftLogger connLogger) {
this.url = url;
this.props = props;
Expand All @@ -394,7 +400,7 @@ public void run() {
error = t;
}

synchronized (this) {
try (ResourceLock ignore = lock.obtain()) {
if (abandoned) {
if (conn != null) {
try {
Expand All @@ -405,7 +411,7 @@ public void run() {
} else {
result = conn;
resultException = error;
notify();
lockCondition.signal();
}
}
}
Expand All @@ -420,7 +426,7 @@ public void run() {
*/
public Connection getResult(long timeout) throws SQLException {
long expiry = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) + timeout;
synchronized (this) {
try (ResourceLock ignore = lock.obtain()) {
while (true) {
if (result != null) {
return result;
Expand All @@ -446,7 +452,7 @@ public Connection getResult(long timeout) throws SQLException {
}

try {
wait(delay);
lockCondition.await(delay, TimeUnit.MILLISECONDS);
} catch (InterruptedException ie) {

// reset the interrupt flag
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import java.io.IOException;
import java.nio.charset.Charset;

import com.amazon.redshift.jdbc.ResourceLock;

/**
* UTF-8 encoder which validates input and is optimized for jdk 9+ where {@code String} objects are backed by
* {@code byte[]}.
Expand Down Expand Up @@ -40,12 +42,15 @@ public String decode(byte[] encodedString, int offset, int length) throws IOExce
* Decodes to {@code char[]} in presence of non-ascii values after first copying all known ascii chars directly
* from {@code byte[]} to {@code char[]}.
*/
private synchronized String slowDecode(byte[] encodedString, int offset, int length, int curIdx) throws IOException {
final char[] chars = getCharArray(length);
int out = 0;
for (int i = offset; i < curIdx; ++i) {
chars[out++] = (char) encodedString[i];
}
return decodeToChars(encodedString, curIdx, length - (curIdx - offset), chars, out);
}
private String slowDecode(byte[] encodedString, int offset, int length, int curIdx) throws IOException {
try (ResourceLock lock = new ResourceLock()) {
lock.obtain();
final char[] chars = getCharArray(length);
int out = 0;
for (int i = offset; i < curIdx; ++i) {
chars[out++] = (char) encodedString[i];
}
return decodeToChars(encodedString, curIdx, length - (curIdx - offset), chars, out);
}
}
}
Loading