You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by wi...@apache.org on 2013/11/20 15:50:35 UTC
[05/50] [abbrv] git commit: updated refs/heads/disk-cache to 6f3e4d3
CLOUDSTACK-4916: Fixing the issue with DB HA when there are more than 2 db nodes (Issue was mysql DriverManager was returning salve db nodes on random basis which was causing issue)
Signed-off-by: Abhinandan Prateek <ap...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/67fc2f53
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/67fc2f53
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/67fc2f53
Branch: refs/heads/disk-cache
Commit: 67fc2f53e2e197f2a8da3b7fc367de9dbe54bb93
Parents: 74153e4
Author: Damodar Reddy <da...@citrix.com>
Authored: Thu Nov 14 10:45:54 2013 +0530
Committer: Abhinandan Prateek <ap...@apache.org>
Committed: Thu Nov 14 11:10:48 2013 +0530
----------------------------------------------------------------------
client/tomcatconf/db.properties.in | 1 +
framework/db/pom.xml | 5 +
.../src/com/cloud/utils/db/StaticStrategy.java | 130 +++++++++++++++++++
.../com/cloud/utils/db/TransactionLegacy.java | 8 +-
4 files changed, 140 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/67fc2f53/client/tomcatconf/db.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/db.properties.in b/client/tomcatconf/db.properties.in
index 31e0803..b224cec 100644
--- a/client/tomcatconf/db.properties.in
+++ b/client/tomcatconf/db.properties.in
@@ -85,6 +85,7 @@ db.simulator.autoReconnect=true
# High Availability And Cluster Properties
db.ha.enabled=false
+db.ha.loadBalanceStrategy=com.cloud.utils.db.StaticStrategy
# cloud stack Database
db.cloud.slaves=localhost,localhost
db.cloud.autoReconnect=true
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/67fc2f53/framework/db/pom.xml
----------------------------------------------------------------------
diff --git a/framework/db/pom.xml b/framework/db/pom.xml
index 5af00a0..e28628e 100644
--- a/framework/db/pom.xml
+++ b/framework/db/pom.xml
@@ -44,6 +44,11 @@
<artifactId>cloud-utils</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
<build>
<plugins>
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/67fc2f53/framework/db/src/com/cloud/utils/db/StaticStrategy.java
----------------------------------------------------------------------
diff --git a/framework/db/src/com/cloud/utils/db/StaticStrategy.java b/framework/db/src/com/cloud/utils/db/StaticStrategy.java
new file mode 100644
index 0000000..29e96df
--- /dev/null
+++ b/framework/db/src/com/cloud/utils/db/StaticStrategy.java
@@ -0,0 +1,130 @@
+// 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 java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import com.mysql.jdbc.BalanceStrategy;
+import com.mysql.jdbc.Connection;
+import com.mysql.jdbc.ConnectionImpl;
+import com.mysql.jdbc.LoadBalancingConnectionProxy;
+import com.mysql.jdbc.SQLError;
+
+public class StaticStrategy implements BalanceStrategy {
+
+ public StaticStrategy() {
+ }
+
+ public void destroy() {
+ // we don't have anything to clean up
+ }
+
+ public void init(Connection conn, Properties props) throws SQLException {
+ // we don't have anything to initialize
+ }
+
+ public ConnectionImpl pickConnection(LoadBalancingConnectionProxy proxy,
+ List<String> configuredHosts, Map<String, ConnectionImpl> liveConnections, long[] responseTimes,
+ int numRetries) throws SQLException {
+ int numHosts = configuredHosts.size();
+
+ SQLException ex = null;
+
+ List<String> whiteList = new ArrayList<String>(numHosts);
+ whiteList.addAll(configuredHosts);
+
+ Map<String, Long> blackList = proxy.getGlobalBlacklist();
+
+ whiteList.removeAll(blackList.keySet());
+
+ Map<String, Integer> whiteListMap = this.getArrayIndexMap(whiteList);
+
+
+ for (int attempts = 0; attempts < numRetries;) {
+ if(whiteList.size() == 0){
+ throw SQLError.createSQLException("No hosts configured", null);
+ }
+
+ String hostPortSpec = whiteList.get(0); //Always take the first host
+
+ ConnectionImpl conn = liveConnections.get(hostPortSpec);
+
+ if (conn == null) {
+ try {
+ conn = proxy.createConnectionForHost(hostPortSpec);
+ } catch (SQLException sqlEx) {
+ ex = sqlEx;
+
+ if (proxy.shouldExceptionTriggerFailover(sqlEx)) {
+
+ Integer whiteListIndex = whiteListMap.get(hostPortSpec);
+
+ // exclude this host from being picked again
+ if (whiteListIndex != null) {
+ whiteList.remove(whiteListIndex.intValue());
+ whiteListMap = this.getArrayIndexMap(whiteList);
+ }
+ proxy.addToGlobalBlacklist( hostPortSpec );
+
+ if (whiteList.size() == 0) {
+ attempts++;
+ try {
+ Thread.sleep(250);
+ } catch (InterruptedException e) {
+ }
+
+ // start fresh
+ whiteListMap = new HashMap<String, Integer>(numHosts);
+ whiteList.addAll(configuredHosts);
+ blackList = proxy.getGlobalBlacklist();
+
+ whiteList.removeAll(blackList.keySet());
+ whiteListMap = this.getArrayIndexMap(whiteList);
+ }
+
+ continue;
+ }
+
+ throw sqlEx;
+ }
+ }
+
+ return conn;
+ }
+
+ if (ex != null) {
+ throw ex;
+ }
+
+ return null; // we won't get here, compiler can't tell
+ }
+
+ private Map<String, Integer> getArrayIndexMap(List<String> l) {
+ Map<String, Integer> m = new HashMap<String, Integer>(l.size());
+ for (int i = 0; i < l.size(); i++) {
+ m.put(l.get(i), Integer.valueOf(i));
+ }
+ return m;
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/67fc2f53/framework/db/src/com/cloud/utils/db/TransactionLegacy.java
----------------------------------------------------------------------
diff --git a/framework/db/src/com/cloud/utils/db/TransactionLegacy.java b/framework/db/src/com/cloud/utils/db/TransactionLegacy.java
index 39893bd..d50118b 100755
--- a/framework/db/src/com/cloud/utils/db/TransactionLegacy.java
+++ b/framework/db/src/com/cloud/utils/db/TransactionLegacy.java
@@ -1034,7 +1034,7 @@ public class TransactionLegacy {
s_dbHAEnabled = Boolean.valueOf(dbProps.getProperty("db.ha.enabled"));
s_logger.info("Is Data Base High Availiability enabled? Ans : " + s_dbHAEnabled);
-
+ String loadBalanceStrategy = dbProps.getProperty("db.ha.loadBalanceStrategy");
// FIXME: If params are missing...default them????
final int cloudMaxActive = Integer.parseInt(dbProps.getProperty("db.cloud.maxActive"));
final int cloudMaxIdle = Integer.parseInt(dbProps.getProperty("db.cloud.maxIdle"));
@@ -1090,7 +1090,7 @@ public class TransactionLegacy {
cloudMaxWait, cloudMaxIdle, cloudTestOnBorrow, false, cloudTimeBtwEvictionRunsMillis, 1, cloudMinEvcitableIdleTimeMillis, cloudTestWhileIdle);
final ConnectionFactory cloudConnectionFactory = new DriverManagerConnectionFactory("jdbc:mysql://" + cloudHost + (s_dbHAEnabled ? "," + cloudSlaves : "") + ":" + cloudPort + "/" + cloudDbName +
- "?autoReconnect=" + cloudAutoReconnect + (url != null ? "&" + url : "") + (useSSL ? "&useSSL=true" : "") + (s_dbHAEnabled ? "&" + cloudDbHAParams : ""), cloudUsername, cloudPassword);
+ "?autoReconnect=" + cloudAutoReconnect + (url != null ? "&" + url : "") + (useSSL ? "&useSSL=true" : "") + (s_dbHAEnabled ? "&" + cloudDbHAParams : "") + (s_dbHAEnabled ? "&loadBalanceStrategy=" + loadBalanceStrategy : ""), cloudUsername, cloudPassword);
final KeyedObjectPoolFactory poolableObjFactory = (cloudPoolPreparedStatements ? new StackKeyedObjectPoolFactory() : null);
@@ -1116,7 +1116,7 @@ public class TransactionLegacy {
usageMaxWait, usageMaxIdle);
final ConnectionFactory usageConnectionFactory = new DriverManagerConnectionFactory("jdbc:mysql://" + usageHost + (s_dbHAEnabled ? "," + dbProps.getProperty("db.cloud.slaves") : "") + ":" + usagePort + "/" + usageDbName +
- "?autoReconnect=" + usageAutoReconnect + (usageUrl != null ? "&" + usageUrl : "") + (s_dbHAEnabled ? "&" + getDBHAParams("usage", dbProps) : ""), usageUsername, usagePassword);
+ "?autoReconnect=" + usageAutoReconnect + (usageUrl != null ? "&" + usageUrl : "") + (s_dbHAEnabled ? "&" + getDBHAParams("usage", dbProps) : "") + (s_dbHAEnabled ? "&loadBalanceStrategy=" + loadBalanceStrategy : ""), usageUsername, usagePassword);
final PoolableConnectionFactory usagePoolableConnectionFactory = new PoolableConnectionFactory(usageConnectionFactory, usageConnectionPool,
new StackKeyedObjectPoolFactory(), null, false, false);
@@ -1129,7 +1129,7 @@ public class TransactionLegacy {
final GenericObjectPool awsapiConnectionPool = new GenericObjectPool(null, usageMaxActive, GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION,
usageMaxWait, usageMaxIdle);
final ConnectionFactory awsapiConnectionFactory = new DriverManagerConnectionFactory("jdbc:mysql://" + cloudHost + (s_dbHAEnabled ? "," + cloudSlaves : "") + ":" + cloudPort + "/" + awsapiDbName +
- "?autoReconnect=" + cloudAutoReconnect + (s_dbHAEnabled ? "&" + cloudDbHAParams : ""), cloudUsername, cloudPassword);
+ "?autoReconnect=" + cloudAutoReconnect + (s_dbHAEnabled ? "&" + cloudDbHAParams : "") + (s_dbHAEnabled ? "&loadBalanceStrategy=" + loadBalanceStrategy : ""), cloudUsername, cloudPassword);
final PoolableConnectionFactory awsapiPoolableConnectionFactory = new PoolableConnectionFactory(awsapiConnectionFactory, awsapiConnectionPool,
new StackKeyedObjectPoolFactory(), null, false, false);