mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-02 20:02:29 +01:00
Merge pull request #1574 from nlivens/mysql_driver_issue
Make sure that the DB drivers are loaded before creating connectionsI've digged deeper, and found out that Tomcat is really specific in how it loads the JDBC drivers apparently. If we would be using the standard JDBC connection pooling of Tomcat (tomcat-jdbc) instead of commons-dbcp, we would have the option to specify a "driverClassName" when creating our connection. This is not the case for commons-dbcp, which we are using within ACS. If you check an official example of Tomcat : https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#Plain_Ol'_Java or https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#As_a_Resource As you can see in the above examples, both of them specify the driverClassName. In the underlying implementation of Tomcat, Tomcat will do ```Class.forName(driverClassName)``` which will trigger the auto-registration of the Driver. Tomcat code : ```java if (driver==null) { if (log.isDebugEnabled()) { log.debug("Instantiating driver using class: "+poolProperties.getDriverClassName()+" [url="+poolProperties.getUrl()+"]"); } driver = (java.sql.Driver) Class.forName(poolProperties.getDriverClassName(), true, PooledConnection.class.getClassLoader() ).newInstance(); } ``` * pr/1574: Make sure that the DB drivers are loaded before initiating connections Signed-off-by: Will Stevens <williamstevens@gmail.com>
This commit is contained in:
commit
971c8a74e4
69
framework/db/src/com/cloud/utils/db/DriverLoader.java
Normal file
69
framework/db/src/com/cloud/utils/db/DriverLoader.java
Normal file
@ -0,0 +1,69 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package com.cloud.utils.db;
|
||||
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class DriverLoader {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(DriverLoader.class.getName());
|
||||
private static final List<String> LOADED_DRIVERS;
|
||||
private static final Map<String, String> DRIVERS;
|
||||
|
||||
static {
|
||||
DRIVERS = new HashMap<String, String>();
|
||||
DRIVERS.put("jdbc:mysql", "com.mysql.jdbc.Driver");
|
||||
DRIVERS.put("jdbc:postgresql", "org.postgresql.Driver");
|
||||
DRIVERS.put("jdbc:h2", "org.h2.Driver");
|
||||
|
||||
LOADED_DRIVERS = new ArrayList<String>();
|
||||
}
|
||||
|
||||
|
||||
public static void loadDriver(String dbDriver) {
|
||||
String driverClass = DRIVERS.get(dbDriver);
|
||||
if (driverClass == null) {
|
||||
LOGGER.error("DB driver type " + dbDriver + " is not supported!");
|
||||
throw new CloudRuntimeException("DB driver type " + dbDriver + " is not supported!");
|
||||
}
|
||||
|
||||
if (LOADED_DRIVERS.contains(dbDriver)) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("DB driver " + driverClass + " was already loaded.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Class.forName(driverClass).newInstance();
|
||||
LOADED_DRIVERS.add(dbDriver);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Successfully loaded DB driver " + driverClass);
|
||||
}
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
|
||||
LOGGER.error("Failed to load DB driver " + driverClass);
|
||||
throw new CloudRuntimeException("Failed to load DB driver " + driverClass, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -20,8 +20,6 @@ import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Driver;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
@ -1078,7 +1076,7 @@ public class TransactionLegacy implements Closeable {
|
||||
final String cloudConnectionUri = cloudDriver + "://" + cloudHost + (s_dbHAEnabled ? "," + cloudSlaves : "") + ":" + cloudPort + "/" + cloudDbName +
|
||||
"?autoReconnect=" + cloudAutoReconnect + (url != null ? "&" + url : "") + (useSSL ? "&useSSL=true" : "") +
|
||||
(s_dbHAEnabled ? "&" + cloudDbHAParams : "") + (s_dbHAEnabled ? "&loadBalanceStrategy=" + loadBalanceStrategy : "");
|
||||
loadDbDriver(cloudConnectionUri);
|
||||
DriverLoader.loadDriver(cloudDriver);
|
||||
|
||||
final ConnectionFactory cloudConnectionFactory = new DriverManagerConnectionFactory(cloudConnectionUri, cloudUsername, cloudPassword);
|
||||
|
||||
@ -1109,7 +1107,7 @@ public class TransactionLegacy implements Closeable {
|
||||
final String usageConnectionUri = usageDriver + "://" + usageHost + (s_dbHAEnabled ? "," + dbProps.getProperty("db.cloud.slaves") : "") + ":" + usagePort +
|
||||
"/" + usageDbName + "?autoReconnect=" + usageAutoReconnect + (usageUrl != null ? "&" + usageUrl : "") +
|
||||
(s_dbHAEnabled ? "&" + getDBHAParams("usage", dbProps) : "") + (s_dbHAEnabled ? "&loadBalanceStrategy=" + loadBalanceStrategy : "");
|
||||
loadDbDriver(usageConnectionUri);
|
||||
DriverLoader.loadDriver(usageDriver);
|
||||
|
||||
final ConnectionFactory usageConnectionFactory = new DriverManagerConnectionFactory(usageConnectionUri, usageUsername, usagePassword);
|
||||
|
||||
@ -1137,7 +1135,7 @@ public class TransactionLegacy implements Closeable {
|
||||
|
||||
final String simulatorConnectionUri = simulatorDriver + "://" + simulatorHost + ":" + simulatorPort + "/" + simulatorDbName + "?autoReconnect=" +
|
||||
simulatorAutoReconnect;
|
||||
loadDbDriver(simulatorConnectionUri);
|
||||
DriverLoader.loadDriver(simulatorDriver);
|
||||
|
||||
final ConnectionFactory simulatorConnectionFactory = new DriverManagerConnectionFactory(simulatorConnectionUri, simulatorUsername, simulatorPassword);
|
||||
|
||||
@ -1157,16 +1155,6 @@ public class TransactionLegacy implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadDbDriver(String dbConnectionUri) {
|
||||
try {
|
||||
Driver driver = DriverManager.getDriver(dbConnectionUri);
|
||||
s_logger.debug("Successfully loaded DB driver " + driver.getClass().getName() + " for connection " + dbConnectionUri);
|
||||
} catch (SQLException e) {
|
||||
s_logger.error("Failed to load DB driver for connection " + dbConnectionUri, e);
|
||||
throw new CloudRuntimeException("Failed to load DB driver for connection " + dbConnectionUri, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getDBHAParams(String dbName, Properties dbProps) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("failOverReadOnly=" + dbProps.getProperty("db." + dbName + ".failOverReadOnly"));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user