Skip to content
Closed
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
8 changes: 7 additions & 1 deletion client/conf/db.properties.in
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ db.cloud.driver=@DBDRIVER@
db.cloud.port=3306
db.cloud.name=cloud

# Connection URI to the database "cloud". When this property is set, only the following properties will be used along with it: db.cloud.maxActive, db.cloud.maxIdle, db.cloud.maxWait, db.cloud.username, db.cloud.password, db.cloud.driver, db.cloud.validationQuery, db.cloud.isolation.level. Other properties will be ignored.
# Connection URI to the database "cloud". When this property is set, only the following properties will be used along with it: db.cloud.maxActive, db.cloud.maxIdle, db.cloud.maxWait, db.cloud.minIdleConnections, db.cloud.connectionTimeout, db.cloud.keepAliveTime, db.cloud.leakDetectionThreshold, db.cloud.registerMbeans, db.cloud.username, db.cloud.password, db.cloud.driver, db.cloud.validationQuery, db.cloud.isolation.level. Other properties will be ignored.
db.cloud.uri=


Expand All @@ -41,6 +41,12 @@ db.cloud.maxWait=600000
db.cloud.minIdleConnections=5
db.cloud.connectionTimeout=30000
db.cloud.keepAliveTime=600000
# HikariCP leak detection threshold in milliseconds.
# A value of 0 disables leak detection.
# Useful for debugging borrowed DB connections that are not returned to the pool.
# db.cloud.leakDetectionThreshold=0
# Enable HikariCP JMX MBeans for observing pool counters.
# db.cloud.registerMbeans=false
db.cloud.validationQuery=/* ping */ SELECT 1
db.cloud.testOnBorrow=true
db.cloud.testWhileIdle=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,10 @@ private static <T extends Number> T parseNumber(String value, Class<T> type) {
}
}

private static Boolean parseBoolean(String value) {
return value == null ? null : Boolean.parseBoolean(value);
}

@SuppressWarnings({"rawtypes", "unchecked"})
public static void initDataSource(Properties dbProps) {
try {
Expand All @@ -1065,6 +1069,8 @@ public static void initDataSource(Properties dbProps) {
final Integer cloudMinIdleConnections = parseNumber(dbProps.getProperty("db.cloud.minIdleConnections"), Integer.class);
final Long cloudConnectionTimeout = parseNumber(dbProps.getProperty("db.cloud.connectionTimeout"), Long.class);
final Long cloudKeepAliveTimeout = parseNumber(dbProps.getProperty("db.cloud.keepAliveTime"), Long.class);
final Long cloudLeakDetectionThreshold = parseNumber(dbProps.getProperty("db.cloud.leakDetectionThreshold"), Long.class);
final Boolean cloudRegisterMbeans = parseBoolean(dbProps.getProperty("db.cloud.registerMbeans"));
final String cloudUsername = dbProps.getProperty("db.cloud.username");
final String cloudPassword = dbProps.getProperty("db.cloud.password");
final String cloudValidationQuery = dbProps.getProperty("db.cloud.validationQuery");
Expand Down Expand Up @@ -1107,7 +1113,7 @@ public static void initDataSource(Properties dbProps) {
cloudUsername, cloudPassword, cloudMaxActive, cloudMaxIdle, cloudMaxWait,
cloudTimeBtwEvictionRunsMillis, cloudMinEvcitableIdleTimeMillis, cloudTestWhileIdle,
cloudTestOnBorrow, cloudValidationQuery, cloudMinIdleConnections, cloudConnectionTimeout,
cloudKeepAliveTimeout, isolationLevel, "cloud");
cloudKeepAliveTimeout, cloudLeakDetectionThreshold, cloudRegisterMbeans, isolationLevel, "cloud");

// Configure the usage db
final Integer usageMaxActive = parseNumber(dbProps.getProperty("db.usage.maxActive"), Integer.class);
Expand All @@ -1127,7 +1133,7 @@ public static void initDataSource(Properties dbProps) {
s_usageDS = createDataSource(dbProps.getProperty("db.usage.connectionPoolLib"), usageUriAndDriver.first(),
usageUsername, usagePassword, usageMaxActive, usageMaxIdle, usageMaxWait, null,
null, null, null, null,
usageMinIdleConnections, usageConnectionTimeout, usageKeepAliveTimeout, isolationLevel, "usage");
usageMinIdleConnections, usageConnectionTimeout, usageKeepAliveTimeout, null, null, isolationLevel, "usage");

try {
// Configure the simulator db
Expand Down Expand Up @@ -1167,7 +1173,7 @@ public static void initDataSource(Properties dbProps) {
simulatorConnectionUri, simulatorUsername, simulatorPassword, simulatorMaxActive,
simulatorMaxIdle, simulatorMaxWait, null, null, null, null,
cloudValidationQuery, simulatorMinIdleConnections, simulatorConnectionTimeout,
simulatorKeepAliveTimeout, isolationLevel, "simulator");
simulatorKeepAliveTimeout, null, null, isolationLevel, "simulator");
} catch (Exception e) {
LOGGER.debug("Simulator DB properties are not available. Not initializing simulator DS");
}
Expand Down Expand Up @@ -1269,21 +1275,21 @@ protected static String buildConnectionUri(String loadBalanceStrategy, String dr
private static DataSource createDataSource(String connectionPoolLib, String uri, String username, String password,
Integer maxActive, Integer maxIdle, Long maxWait, Long timeBtwnEvictionRuns, Long minEvictableIdleTime,
Boolean testWhileIdle, Boolean testOnBorrow, String validationQuery, Integer minIdleConnections,
Long connectionTimeout, Long keepAliveTime, Integer isolationLevel, String dsName) {
Long connectionTimeout, Long keepAliveTime, Long leakDetectionThreshold, Boolean registerMbeans, Integer isolationLevel, String dsName) {
LOGGER.debug("Creating datasource for database: {} with connection pool lib: {}", dsName,
connectionPoolLib);
if (CONNECTION_POOL_LIB_DBCP.equals(connectionPoolLib)) {
return createDbcpDataSource(uri, username, password, maxActive, maxIdle, maxWait, timeBtwnEvictionRuns,
minEvictableIdleTime, testWhileIdle, testOnBorrow, validationQuery, isolationLevel);
}
return createHikaricpDataSource(uri, username, password, maxActive, maxIdle, maxWait, minIdleConnections,
connectionTimeout, keepAliveTime, isolationLevel, dsName);
connectionTimeout, keepAliveTime, leakDetectionThreshold, registerMbeans, isolationLevel, dsName);
}

private static DataSource createHikaricpDataSource(String uri, String username, String password,
Integer maxActive, Integer maxIdle, Long maxWait,
Integer minIdleConnections, Long connectionTimeout, Long keepAliveTime,
Integer isolationLevel, String dsName) {
Integer maxActive, Integer maxIdle, Long maxWait,
Integer minIdleConnections, Long connectionTimeout, Long keepAliveTime,
Long leakDetectionThreshold, Boolean registerMbeans, Integer isolationLevel, String dsName) {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(uri);
config.setUsername(username);
Expand All @@ -1298,6 +1304,7 @@ private static DataSource createHikaricpDataSource(String uri, String username,
config.setMinimumIdle(ObjectUtils.defaultIfNull(minIdleConnections, 5));
config.setConnectionTimeout(ObjectUtils.defaultIfNull(connectionTimeout, 30000L));
config.setKeepaliveTime(ObjectUtils.defaultIfNull(keepAliveTime, 600000L));
applyHikariDebugSettings(config, leakDetectionThreshold, registerMbeans, dsName);

String isolationLevelString = "TRANSACTION_READ_COMMITTED";
if (isolationLevel == Connection.TRANSACTION_SERIALIZABLE) {
Expand Down Expand Up @@ -1326,6 +1333,17 @@ private static DataSource createHikaricpDataSource(String uri, String username,
return dataSource;
}

static void applyHikariDebugSettings(HikariConfig config, Long leakDetectionThreshold, Boolean registerMbeans, String dsName) {
long effectiveLeakDetectionThreshold = ObjectUtils.defaultIfNull(leakDetectionThreshold, 0L);
boolean effectiveRegisterMbeans = ObjectUtils.defaultIfNull(registerMbeans, false);

config.setLeakDetectionThreshold(effectiveLeakDetectionThreshold);
config.setRegisterMbeans(effectiveRegisterMbeans);

LOGGER.debug("HikariCP datasource {} leakDetectionThreshold={} ms, registerMbeans={}",
dsName, effectiveLeakDetectionThreshold, effectiveRegisterMbeans);
}

private static DataSource createDbcpDataSource(String uri, String username, String password,
Integer maxActive, Integer maxIdle, Long maxWait,
Long timeBtwnEvictionRuns, Long minEvictableIdleTime,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.cloud.utils.db;

import com.cloud.utils.Pair;
import com.zaxxer.hikari.HikariConfig;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
Expand All @@ -28,6 +29,8 @@
@RunWith(MockitoJUnitRunner.class)
public class TransactionLegacyTest {

private static final String CONNECTION_PARAMS = "&" + TransactionLegacy.CONNECTION_PARAMS;

Properties properties;

@Before
Expand All @@ -47,7 +50,7 @@ public void getConnectionUriAndDriverTestWithoutUri() {

Pair<String, String> result = TransactionLegacy.getConnectionUriAndDriver(properties, null, false, "cloud");

Assert.assertEquals("driver://host:5555/name?autoReconnect=false&someParams", result.first());
Assert.assertEquals("driver://host:5555/name?autoReconnect=false&someParams" + CONNECTION_PARAMS, result.first());
Assert.assertEquals("driver", result.second());
}

Expand All @@ -65,7 +68,7 @@ public void getConnectionUriAndDriverTestWithUri() {
public void getPropertiesAndBuildConnectionUriTestDbHaDisabled() {
String result = TransactionLegacy.getPropertiesAndBuildConnectionUri(properties, "strat", "driver", true, "cloud");

Assert.assertEquals("driver://host:5555/name?autoReconnect=false&someParams&useSSL=true", result);
Assert.assertEquals("driver://host:5555/name?autoReconnect=false&someParams&useSSL=true" + CONNECTION_PARAMS, result);
}

@Test
Expand All @@ -82,14 +85,14 @@ public void getPropertiesAndBuildConnectionUriTestDbHaEnabled() {
String result = TransactionLegacy.getPropertiesAndBuildConnectionUri(properties, "strat", "driver", true, "cloud");

Assert.assertEquals("driver://host,second_host:5555/name?autoReconnect=false&someParams&useSSL=true&failOverReadOnly=true&reconnectAtTxEnd=false&autoReconnectFor"
+ "Pools=true&secondsBeforeRetrySource=25&queriesBeforeRetrySource=105&initialTimeout=1000&loadBalanceStrategy=strat", result);
+ "Pools=true&secondsBeforeRetrySource=25&queriesBeforeRetrySource=105&initialTimeout=1000&loadBalanceStrategy=strat" + CONNECTION_PARAMS, result);
}

@Test
public void buildConnectionUriTestDbHaDisabled() {
String result = TransactionLegacy.buildConnectionUri(null, "driver", false, "host", null, 5555, "cloud", false, null, null);

Assert.assertEquals("driver://host:5555/cloud?autoReconnect=false", result);
Assert.assertEquals("driver://host:5555/cloud?autoReconnect=false" + CONNECTION_PARAMS, result);
}

@Test
Expand All @@ -98,20 +101,60 @@ public void buildConnectionUriTestDbHaEnabled() {

String result = TransactionLegacy.buildConnectionUri("strat", "driver", false, "host", "second_host", 5555, "cloud", false, null, "dbHaParams");

Assert.assertEquals("driver://host,second_host:5555/cloud?autoReconnect=false&dbHaParams&loadBalanceStrategy=strat", result);
Assert.assertEquals("driver://host,second_host:5555/cloud?autoReconnect=false&dbHaParams&loadBalanceStrategy=strat" + CONNECTION_PARAMS, result);
}

@Test
public void buildConnectionUriTestUrlParamsNotNull() {
String result = TransactionLegacy.buildConnectionUri(null, "driver", false, "host", null, 5555, "cloud", false, "urlParams", null);

Assert.assertEquals("driver://host:5555/cloud?autoReconnect=false&urlParams", result);
Assert.assertEquals("driver://host:5555/cloud?autoReconnect=false&urlParams" + CONNECTION_PARAMS, result);
}

@Test
public void buildConnectionUriTestUseSslTrue() {
String result = TransactionLegacy.buildConnectionUri(null, "driver", true, "host", null, 5555, "cloud", false, null, null);

Assert.assertEquals("driver://host:5555/cloud?autoReconnect=false&useSSL=true", result);
Assert.assertEquals("driver://host:5555/cloud?autoReconnect=false&useSSL=true" + CONNECTION_PARAMS, result);
}

@Test
public void applyHikariDebugSettingsDefaultsWhenUnset() {
HikariConfig config = new HikariConfig();

TransactionLegacy.applyHikariDebugSettings(config, null, null, "cloud");

Assert.assertEquals(0L, config.getLeakDetectionThreshold());
Assert.assertFalse(config.isRegisterMbeans());
}

@Test
public void applyHikariDebugSettingsKeepsZeroLeakDetectionDisabled() {
HikariConfig config = new HikariConfig();

TransactionLegacy.applyHikariDebugSettings(config, 0L, false, "cloud");

Assert.assertEquals(0L, config.getLeakDetectionThreshold());
Assert.assertFalse(config.isRegisterMbeans());
}

@Test
public void applyHikariDebugSettingsAppliesPositiveLeakDetectionThreshold() {
HikariConfig config = new HikariConfig();

TransactionLegacy.applyHikariDebugSettings(config, 60000L, false, "cloud");

Assert.assertEquals(60000L, config.getLeakDetectionThreshold());
Assert.assertFalse(config.isRegisterMbeans());
}

@Test
public void applyHikariDebugSettingsEnablesRegisterMbeans() {
HikariConfig config = new HikariConfig();

TransactionLegacy.applyHikariDebugSettings(config, null, true, "cloud");

Assert.assertEquals(0L, config.getLeakDetectionThreshold());
Assert.assertTrue(config.isRegisterMbeans());
}
}
Loading