Skip to content

Commit

Permalink
rename property; move RefreshableVTGateConnection
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Charis committed Nov 16, 2017
1 parent 3996539 commit fbd1485
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 73 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package io.vitess.client;

import java.io.File;

public class RefreshableVTGateConnection extends VTGateConnection {
private final File keystoreFile;
private final File truststoreFile;
private volatile long keystoreMtime;
private volatile long truststoreMtime;

public RefreshableVTGateConnection(RpcClient client,
String keystorePath,
String truststorePath) {
super(client);
this.keystoreFile = new File(keystorePath);
this.truststoreFile = new File(truststorePath);
this.keystoreMtime = this.keystoreFile.exists() ? this.keystoreFile.lastModified() : 0;
this.truststoreMtime = this.truststoreFile.exists() ? this.truststoreFile.lastModified() : 0;
}

public boolean checkKeystoreUpdates() {
long keystoreMtime = keystoreFile.exists() ? keystoreFile.lastModified() : 0;
long truststoreMtime = truststoreFile.exists() ? truststoreFile.lastModified() : 0;
boolean modified = false;
if (keystoreMtime > this.keystoreMtime) {
modified = true;
this.keystoreMtime = keystoreMtime;
}
if (truststoreMtime > this.truststoreMtime) {
modified = true;
this.truststoreMtime = truststoreMtime;
}
return modified;
}
}
26 changes: 19 additions & 7 deletions java/jdbc/src/main/java/io/vitess/jdbc/ConnectionProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,14 @@ public class ConnectionProperties {
Constants.Property.USE_SSL,
"Whether this connection should use transport-layer security",
false);
private BooleanConnectionProperty refreshSSLConnectionsOnCertFileModification = new BooleanConnectionProperty(
"refreshSSLConnectionsOnKeystoreUpdate",
private BooleanConnectionProperty refreshConnection = new BooleanConnectionProperty(
"refreshConnection",
"When enabled, the driver will monitor for changes to the keystore and truststore files. If any are detected, SSL-enabled connections will be recreated.",
true);
false);
private LongConnectionProperty refreshSeconds = new LongConnectionProperty(
"refreshSeconds",
"How often in seconds the driver will monitor for changes to the keystore and truststore files, when refreshConnection is enabled.",
60);
private StringConnectionProperty keyStore = new StringConnectionProperty(
Constants.Property.KEYSTORE,
"The Java .JKS keystore file to use when TLS is enabled",
Expand Down Expand Up @@ -480,12 +484,20 @@ public boolean getUseSSL() {
return useSSL.getValueAsBoolean();
}

public boolean getRefreshSSLConnectionsOnCertFileModification() {
return refreshSSLConnectionsOnCertFileModification.getValueAsBoolean();
public boolean getRefreshConnection() {
return refreshConnection.getValueAsBoolean();
}

public void setRefreshConnection(boolean refreshConnection) {
this.refreshConnection.setValue(refreshConnection);
}

public long getRefreshSeconds() {
return refreshSeconds.getValueAsLong();
}

public void setRefreshSSLConnectionsOnCertFileModification(boolean refreshSSLConnectionsOnCertFileModification) {
this.refreshSSLConnectionsOnCertFileModification.setValue(refreshSSLConnectionsOnCertFileModification);
public void setRefreshSeconds(long refreshSeconds) {
this.refreshSeconds.setValue(refreshSeconds);
}

public String getKeyStore() {
Expand Down
80 changes: 16 additions & 64 deletions java/jdbc/src/main/java/io/vitess/jdbc/VitessVTGateManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import java.util.logging.Level;

import com.google.common.io.Closeables;

import io.vitess.client.Context;
import io.vitess.client.RpcClient;
import io.vitess.client.VTGateConnection;
import io.vitess.client.RefreshableVTGateConnection;
import io.vitess.client.grpc.GrpcClientFactory;
import io.vitess.client.grpc.RetryingInterceptorConfig;
import io.vitess.client.grpc.tls.TlsOptions;
Expand Down Expand Up @@ -63,25 +65,25 @@ public static class VTGateConnections {
*
* @param connection
*/
public VTGateConnections(VitessConnection connection) {
for (VitessJDBCUrl.HostInfo hostInfo : connection.getUrl().getHostInfos()) {
public VTGateConnections(final VitessConnection connection) {
for (final VitessJDBCUrl.HostInfo hostInfo : connection.getUrl().getHostInfos()) {
String identifier = getIdentifer(hostInfo.getHostname(), hostInfo.getPort(), connection.getUsername(), connection.getTarget());
synchronized (VitessVTGateManager.class) {
if (!vtGateConnHashMap.containsKey(identifier)) {
updateVtGateConnHashMap(identifier, hostInfo, connection);
}
if (connection.getUseSSL() && connection.getRefreshSSLConnectionsOnCertFileModification() && vtgateConnRefreshTimer == null) {
if (connection.getUseSSL() && connection.getRefreshConnection() && vtgateConnRefreshTimer == null) {
logger.info("ssl vtgate connection detected -- installing connection refresh based on ssl keystore modification");
vtgateConnRefreshTimer = new Timer("ssl-refresh-vtgate-conn", true);
vtgateConnRefreshTimer.scheduleAtFixedRate(
new TimerTask() {
@Override
public void run() {
refreshUpdatedSSLConnections();
refreshUpdatedSSLConnections(hostInfo, connection);
}
},
TimeUnit.SECONDS.toMillis(60),
TimeUnit.SECONDS.toMillis(60));
TimeUnit.SECONDS.toMillis(connection.getRefreshSeconds()),
TimeUnit.SECONDS.toMillis(connection.getRefreshSeconds()));
}
}
vtGateIdentifiers.add(identifier);
Expand All @@ -107,54 +109,6 @@ private static String getIdentifer(String hostname, int port, String userIdentif
return (hostname + port + userIdentifer + keyspace);
}

public static class RefreshableVTGateConn extends VTGateConnection {
private final VitessJDBCUrl.HostInfo hostInfo;
private final VitessConnection conn;
private final File keystoreFile;
private final File truststoreFile;
private volatile long keystoreMtime;
private volatile long truststoreMtime;

RefreshableVTGateConn(RpcClient client,
VitessJDBCUrl.HostInfo hostInfo,
VitessConnection conn,
String keystorePath,
String truststorePath) {
super(client);
this.hostInfo = hostInfo;
this.conn = conn;
this.keystoreFile = new File(keystorePath);
this.truststoreFile = new File(truststorePath);
// initial check ensures the mtimes are up-to-date
checkKeystoreUpdates();
}

VitessJDBCUrl.HostInfo getHostInfo() {
return hostInfo;
}

VitessConnection getConn() {
return conn;
}

boolean checkKeystoreUpdates() {
long keystoreMtime = keystoreFile.exists() ? keystoreFile.lastModified() : 0;
long truststoreMtime = truststoreFile.exists() ? truststoreFile.lastModified() : 0;

boolean modified = false;
if (keystoreMtime > this.keystoreMtime) {
modified = true;
this.keystoreMtime = keystoreMtime;
}
if (truststoreMtime > this.truststoreMtime) {
modified = true;
this.truststoreMtime = truststoreMtime;
}

return modified;
}
}

/**
* Create VTGateConn and update vtGateConnHashMap.
*
Expand All @@ -167,19 +121,19 @@ private static void updateVtGateConnHashMap(String identifier, VitessJDBCUrl.Hos
vtGateConnHashMap.put(identifier, getVtGateConn(hostInfo, connection));
}

private static void refreshUpdatedSSLConnections() {
private static void refreshUpdatedSSLConnections(VitessJDBCUrl.HostInfo hostInfo, VitessConnection connection) {
synchronized (VitessVTGateManager.class) {
int updatedCount = 0;
for (Map.Entry<String, VTGateConnection> entry : vtGateConnHashMap.entrySet()) {
if (entry.getValue() instanceof RefreshableVTGateConn) {
RefreshableVTGateConn existing = (RefreshableVTGateConn) entry.getValue();
if (entry.getValue() instanceof RefreshableVTGateConnection) {
RefreshableVTGateConnection existing = (RefreshableVTGateConnection) entry.getValue();
if (existing.checkKeystoreUpdates()) {
updatedCount++;
VTGateConnection old = vtGateConnHashMap.replace(entry.getKey(), getVtGateConn(existing.getHostInfo(), existing.getConn()));
VTGateConnection old = vtGateConnHashMap.replace(entry.getKey(), getVtGateConn(hostInfo, connection));
try {
Closeables.close(old, true);
} catch (IOException e) {
// exception will be logged by Closeables.close
old.close();
} catch (IOException ioe) {
logger.log(Level.WARNING, "Error closing VTGateConnection", ioe);
}
}
}
Expand Down Expand Up @@ -225,10 +179,8 @@ private static VTGateConnection getVtGateConn(VitessJDBCUrl.HostInfo hostInfo, V
.trustStorePassword(trustStorePassword)
.trustAlias(trustAlias);

return new RefreshableVTGateConn(
return new RefreshableVTGateConnection(
new GrpcClientFactory(retryingConfig).createTls(context, hostInfo.toString(), tlsOptions),
hostInfo,
connection,
keyStorePath,
trustStorePath);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

public class ConnectionPropertiesTest {

private static final int NUM_PROPS = 35;
private static final int NUM_PROPS = 36;

@Test
public void testReflection() throws Exception {
Expand Down Expand Up @@ -67,7 +67,8 @@ public void testDefaults() throws SQLException {
Assert.assertEquals("tabletType", Constants.DEFAULT_TABLET_TYPE, props.getTabletType());
Assert.assertEquals("useSSL", false, props.getUseSSL());
Assert.assertEquals("useAffectedRows", true, props.getUseAffectedRows());
Assert.assertEquals("refreshSSLConnectionsOnCertFileModification", true, props.getRefreshSSLConnectionsOnCertFileModification());
Assert.assertEquals("refreshConnection", false, props.getRefreshConnection());
Assert.assertEquals("refreshSeconds", 60, props.getRefreshSeconds());
}

@Test
Expand Down

0 comments on commit fbd1485

Please sign in to comment.