Skip to content

Commit

Permalink
Failover handling
Browse files Browse the repository at this point in the history
  • Loading branch information
rusher committed May 17, 2015
1 parent ccd0a21 commit 9376624
Show file tree
Hide file tree
Showing 25 changed files with 1,852 additions and 329 deletions.
21 changes: 14 additions & 7 deletions src/main/java/org/mariadb/jdbc/Driver.java
Expand Up @@ -52,8 +52,9 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS
import org.mariadb.jdbc.internal.SQLExceptionMapper;
import org.mariadb.jdbc.internal.common.QueryException;
import org.mariadb.jdbc.internal.common.Utils;
import org.mariadb.jdbc.internal.mysql.MySQLProtocol;
import org.mariadb.jdbc.internal.mysql.*;

import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
Expand Down Expand Up @@ -87,7 +88,7 @@ public final class Driver implements java.sql.Driver {
* @return a connection
* @throws SQLException if it is not possible to connect
*/
public Connection connect(final String url, final Properties info) throws SQLException {
public Connection connect(final String url, final Properties props) throws SQLException {
// TODO: handle the properties!
// TODO: define what props we support!

Expand All @@ -96,7 +97,7 @@ public Connection connect(final String url, final Properties info) throws SQLExc
if(idx > 0) {
baseUrl = url.substring(0,idx);
String urlParams = url.substring(idx+1);
setURLParameters(urlParams, info);
setURLParameters(urlParams, props);
}

log.finest("Connecting to: " + url);
Expand All @@ -105,12 +106,18 @@ public Connection connect(final String url, final Properties info) throws SQLExc
if(jdbcUrl == null) {
return null;
}
String userName = info.getProperty("user",jdbcUrl.getUsername());
String password = info.getProperty("password",jdbcUrl.getPassword());
String username = props.getProperty("user",jdbcUrl.getUsername());
String password = props.getProperty("password",jdbcUrl.getPassword());

MySQLProtocol protocol = new MySQLProtocol(jdbcUrl, userName, password, info);
if (jdbcUrl.getHostAddresses() == null) {
log.info("MariaDB connector : missing Host address");
return null;
} else {
Protocol proxyfiedProtocol = ConnectorUtils.retrieveProxy(jdbcUrl, username, password, props);
proxyfiedProtocol.initializeConnection();
return MySQLConnection.newConnection(proxyfiedProtocol);
}

return MySQLConnection.newConnection(protocol);
} catch (QueryException e) {
SQLExceptionMapper.throwException(e, null, null);
return null;
Expand Down
42 changes: 41 additions & 1 deletion src/main/java/org/mariadb/jdbc/HostAddress.java
@@ -1,5 +1,7 @@
package org.mariadb.jdbc;

import java.util.List;

public class HostAddress {
public String host;
public int port;
Expand All @@ -12,7 +14,8 @@ public class HostAddress {
* @return parsed endpoints
*/
public static HostAddress[] parse(String spec) {
String[] tokens = spec.split(",");
if (spec == null) return null;
String[] tokens = spec.trim().split(",");
HostAddress[] arr = new HostAddress[tokens.length];

for (int i=0; i < tokens.length; i++) {
Expand Down Expand Up @@ -53,6 +56,19 @@ else if (s.contains(":")) {
}
return result;
}

public static String toString(List<HostAddress> addrs) {
String s="";
for(int i=0; i < addrs.size(); i++) {
boolean isIPv6 = addrs.get(i).host != null && addrs.get(i).host.contains(":");
String host = (isIPv6)?("[" + addrs.get(i).host + "]"):addrs.get(i).host;
s += host + ":" + addrs.get(i).port;
if (i < addrs.size() -1)
s += ",";
}
return s;
}

public static String toString(HostAddress[] addrs) {
String s="";
for(int i=0; i < addrs.length; i++) {
Expand All @@ -64,5 +80,29 @@ public static String toString(HostAddress[] addrs) {
}
return s;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof HostAddress)) return false;

HostAddress that = (HostAddress) o;

if (port != that.port) return false;
return !(host != null ? !host.equals(that.host) : that.host != null);

}

@Override
public int hashCode() {
int result = host != null ? host.hashCode() : 0;
result = 31 * result + port;
return result;
}

@Override
public String toString() {
return "HostAddress{" + host + ":" + port + "}";
}
}

30 changes: 20 additions & 10 deletions src/main/java/org/mariadb/jdbc/JDBCUrl.java
Expand Up @@ -49,18 +49,22 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS

package org.mariadb.jdbc;

import java.util.Properties;

public class JDBCUrl {
private String username;
private String password;
private String database;
private Properties properties;
private HostAddress addresses[];


private JDBCUrl( String username, String password, String database, HostAddress addresses[]) {
private JDBCUrl( String username, String password, String database, HostAddress addresses[], Properties properties) {
this.username = username;
this.password = password;
this.database = database;
this.addresses = addresses;
this.properties = properties;
}

/*
Expand All @@ -83,28 +87,30 @@ private static JDBCUrl parseConnectorJUrl(String url) {

hostname = tokens[0];
database = (tokens.length > 1) ? tokens[1] : null;

Properties properties = new Properties();

if (database == null) {
return new JDBCUrl("", "", database, HostAddress.parse(hostname));
return new JDBCUrl("", "", database, HostAddress.parse(hostname), properties);
}

//check if there are parameters
if (database.indexOf('?') > -1)
{
if (database.indexOf('?') > -1) {

String[] credentials = database.substring(database.indexOf('?') + 1, database.length()).split("&");

database = database.substring(0, database.indexOf('?'));

for (int i = 0; i < credentials.length; i++)
{
for (int i = 0; i < credentials.length; i++){
String[] parameter = credentials[i].split("=");
properties.put(parameter[0], (parameter.length>1)?parameter[1]:"");
if (credentials[i].startsWith("user="))
user=credentials[i].substring(5);
else if (credentials[i].startsWith("password="))
password = credentials[i].substring(9);
}
}

return new JDBCUrl(user, password, database, HostAddress.parse(hostname));
return new JDBCUrl(user, password, database, HostAddress.parse(hostname), properties);
}

static boolean acceptsURL(String url) {
Expand All @@ -127,6 +133,7 @@ public static JDBCUrl parse(final String url) {
}
return null;
}

public String getUsername() {
return username;
}
Expand All @@ -147,9 +154,12 @@ public String getDatabase() {
return database;
}


public HostAddress[] getHostAddresses() {
return this.addresses;
return this.addresses;
}

public Properties getProperties() {
return properties;
}

public String toString() {
Expand Down
18 changes: 7 additions & 11 deletions src/main/java/org/mariadb/jdbc/MySQLConnection.java
Expand Up @@ -53,6 +53,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS
import org.mariadb.jdbc.internal.common.QueryException;
import org.mariadb.jdbc.internal.common.Utils;
import org.mariadb.jdbc.internal.mysql.MySQLProtocol;
import org.mariadb.jdbc.internal.mysql.Protocol;

import java.net.SocketException;
import java.sql.*;
Expand All @@ -64,7 +65,7 @@ public final class MySQLConnection implements Connection {
/**
* the protocol to communicate with.
*/
private final MySQLProtocol protocol;
private final Protocol protocol;
/**
* save point count - to generate good names for the savepoints.
*/
Expand All @@ -88,12 +89,12 @@ public final class MySQLConnection implements Connection {
*
* @param protocol the protocol to use.
*/
private MySQLConnection(MySQLProtocol protocol) {
private MySQLConnection(Protocol protocol) {
this.protocol = protocol;
clientInfoProperties = protocol.getInfo();
}

MySQLProtocol getProtocol() {
Protocol getProtocol() {
return protocol;
}

Expand All @@ -107,7 +108,7 @@ static TimeZone getTimeZone(String id) throws SQLException {
return tz;
}

public static MySQLConnection newConnection(MySQLProtocol protocol) throws SQLException {
public static MySQLConnection newConnection(Protocol protocol) throws SQLException {
MySQLConnection connection = new MySQLConnection(protocol);

Properties info = protocol.getInfo();
Expand Down Expand Up @@ -298,7 +299,7 @@ public void setReadOnly(final boolean readOnly) throws SQLException {
* connection
*/
public boolean isReadOnly() throws SQLException {
return false;
return !protocol.checkIfMaster();
}

public static String quoteIdentifier(String s) {
Expand Down Expand Up @@ -459,7 +460,7 @@ public int getTransactionIsolation() throws SQLException {
* @see java.sql.SQLWarning
*/
public SQLWarning getWarnings() throws SQLException {
if (warningsCleared || isClosed() || !protocol.hasWarnings) {
if (warningsCleared || isClosed() || !protocol.hasWarnings()) {
return null;
}
Statement st = null;
Expand Down Expand Up @@ -1287,11 +1288,6 @@ public String getPinGlobalTxToPhysicalConnection() {
return protocol.getPinGlobalTxToPhysicalConnection();
}


public void setHostFailed() {
protocol.setHostFailed();
}

volatile int lowercaseTableNames = -1;
public int getLowercaseTableNames() throws SQLException {
if (lowercaseTableNames == -1) {
Expand Down
15 changes: 12 additions & 3 deletions src/main/java/org/mariadb/jdbc/MySQLDataSource.java
Expand Up @@ -53,11 +53,12 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS
import org.mariadb.jdbc.internal.SQLExceptionMapper;
import org.mariadb.jdbc.internal.common.QueryException;
import org.mariadb.jdbc.internal.common.Utils;
import org.mariadb.jdbc.internal.mysql.MySQLProtocol;
import org.mariadb.jdbc.internal.mysql.*;

import javax.sql.*;

import java.io.PrintWriter;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
Expand Down Expand Up @@ -297,7 +298,13 @@ private void resetUrl() {
public Connection getConnection() throws SQLException {
createUrl();
try {
return MySQLConnection.newConnection(new MySQLProtocol(url, username, password, info));
Protocol proxyfiedProtocol = (Protocol) Proxy.newProxyInstance(
MySQLProtocol.class.getClassLoader(),
new Class[]{Protocol.class},
new FailoverProxy(new MySQLProtocol(url, username, password, info), new SingleHostListener())
);
proxyfiedProtocol.initializeConnection();
return MySQLConnection.newConnection(proxyfiedProtocol);
} catch (QueryException e) {
SQLExceptionMapper.throwException(e, null, null);
return null;
Expand All @@ -317,7 +324,9 @@ public Connection getConnection(final String username, final String password) th
createUrl();
try {
Properties props = info == null ? new Properties() : info;
return MySQLConnection.newConnection(new MySQLProtocol(url, username, password, props));
Protocol proxyfiedProtocol = ConnectorUtils.retrieveProxy(url, username, password, props);
proxyfiedProtocol.initializeConnection();
return MySQLConnection.newConnection(proxyfiedProtocol);
} catch (QueryException e) {
SQLExceptionMapper.throwException(e, null, null);
return null;
Expand Down
5 changes: 2 additions & 3 deletions src/main/java/org/mariadb/jdbc/MySQLDatabaseMetaData.java
Expand Up @@ -96,8 +96,8 @@ private String dataTypeClause (String fullTypeColumnName){
" WHEN 'binary' THEN " + Types.BINARY +
" WHEN 'time' THEN " + Types.TIME +
" WHEN 'timestamp' THEN " + Types.TIMESTAMP +
" WHEN 'tinyint' THEN " + (((connection.getProtocol().datatypeMappingFlags & MySQLValueObject.TINYINT1_IS_BIT)== 0)? Types.TINYINT : "IF(" + fullTypeColumnName + "='tinyint(1)'," + Types.BIT + "," + Types.TINYINT + ") ") +
" WHEN 'year' THEN " + (((connection.getProtocol().datatypeMappingFlags & MySQLValueObject.YEAR_IS_DATE_TYPE)== 0)? Types.SMALLINT :Types.DATE) +
" WHEN 'tinyint' THEN " + (((connection.getProtocol().getDatatypeMappingFlags() & MySQLValueObject.TINYINT1_IS_BIT)== 0)? Types.TINYINT : "IF(" + fullTypeColumnName + "='tinyint(1)'," + Types.BIT + "," + Types.TINYINT + ") ") +
" WHEN 'year' THEN " + (((connection.getProtocol().getDatatypeMappingFlags() & MySQLValueObject.YEAR_IS_DATE_TYPE)== 0)? Types.SMALLINT :Types.DATE) +
" ELSE " + Types.OTHER +
" END ";
}
Expand Down Expand Up @@ -1729,7 +1729,6 @@ public static ResultSet getImportedKeys(String tableDef, String tableName, Strin
List<String[]> data = new ArrayList<String[]>();

for (String p:parts) {
//System.out.println("--" + p);
p = p.trim();
if (!p.startsWith("CONSTRAINT") && !p.contains("FOREIGN KEY"))
continue;
Expand Down

0 comments on commit 9376624

Please sign in to comment.