/**
* Copyright 2014 Duan Bingnan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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 org.pinus4j.cluster.config.loader.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.pinus4j.cluster.beans.DBClusterInfo;
import org.pinus4j.cluster.beans.DBInfo;
import org.pinus4j.cluster.beans.DBRegionInfo;
import org.pinus4j.cluster.beans.DBRegionInfo.Value;
import org.pinus4j.cluster.config.IClusterConfig;
import org.pinus4j.cluster.cp.IDBConnectionPool;
import org.pinus4j.cluster.enums.EnumDBMasterSlave;
import org.pinus4j.cluster.router.IClusterRouter;
import org.pinus4j.exceptions.LoadConfigException;
import org.pinus4j.utils.StringUtil;
import org.w3c.dom.Node;
import com.google.common.collect.Lists;
public class DBClusterInfoLoader extends AbstractXMLConfigLoader<List<DBClusterInfo>> {
private IDBConnectionPool dbConnectionPool;
public DBClusterInfoLoader(IDBConnectionPool dbConnectionPool) {
this.dbConnectionPool = dbConnectionPool;
}
@Override
public List<DBClusterInfo> load(Node xmlNode) throws LoadConfigException {
List<DBClusterInfo> dbClusterInfos = Lists.newArrayList();
List<Node> clusterNodeList = xmlUtil.getChildByName(xmlNode, "cluster");
for (Node clusterNode : clusterNodeList) {
String name = xmlUtil.getAttributeValue(clusterNode, "name");
dbClusterInfos.add(_getDBClusterInfo(name, clusterNode));
}
return dbClusterInfos;
}
@SuppressWarnings("unchecked")
private DBClusterInfo _getDBClusterInfo(String clusterName, Node clusterNode) throws LoadConfigException {
DBClusterInfo dbClusterInfo = new DBClusterInfo();
// set cluster name
dbClusterInfo.setClusterName(clusterName);
// set router class
try {
String classFullPath = xmlUtil.getAttributeValue(clusterNode, "router");
if (StringUtil.isBlank(classFullPath)) {
classFullPath = IClusterConfig.DEFAULT_CLUSTER_ROUTER_CLASS;
}
Class<IClusterRouter> clazz = (Class<IClusterRouter>) Class.forName(classFullPath);
dbClusterInfo.setRouterClass(clazz);
} catch (Exception e) {
throw new LoadConfigException(e);
}
//
// load global
//
Node global = xmlUtil.getFirstChildByName(clusterNode, "global");
if (global != null) {
// load master global
Node masterGlobal = xmlUtil.getFirstChildByName(global, "master");
String dbInfoId = masterGlobal.getTextContent().trim();
DBInfo masterGlobalDBInfo = dbConnectionPool.findDBInfo(dbInfoId).clone();
masterGlobalDBInfo.setClusterName(clusterName);
masterGlobalDBInfo.setMasterSlave(EnumDBMasterSlave.MASTER);
// set custom property
Map<String, String> propMap = xmlUtil.getAttributeAsMap(masterGlobal);
masterGlobalDBInfo.setCustomProperties(propMap);
masterGlobalDBInfo.check();
dbClusterInfo.setMasterGlobalDBInfo(masterGlobalDBInfo);
// load slave global
List<Node> slaveGlobalList = xmlUtil.getChildByName(global, "slave");
if (slaveGlobalList != null && !slaveGlobalList.isEmpty()) {
List<DBInfo> slaveGlobalConnection = new ArrayList<DBInfo>();
int slaveIndex = 0;
for (Node slaveGlobal : slaveGlobalList) {
dbInfoId = slaveGlobal.getTextContent().trim();
if (dbConnectionPool.findDBInfo(dbInfoId) == null) {
throw new LoadConfigException("配置错误,找不到datasource id=" + dbInfoId);
}
DBInfo slaveGlobalDBInfo = dbConnectionPool.findDBInfo(dbInfoId).clone();
slaveGlobalDBInfo.setClusterName(clusterName);
slaveGlobalDBInfo.setMasterSlave(EnumDBMasterSlave.getSlaveEnum(slaveIndex++));
// set custom property
propMap = xmlUtil.getAttributeAsMap(slaveGlobal);
slaveGlobalDBInfo.setCustomProperties(propMap);
slaveGlobalDBInfo.check();
slaveGlobalConnection.add(slaveGlobalDBInfo);
}
dbClusterInfo.setSlaveGlobalDBInfo(slaveGlobalConnection);
}
}
//
// load region
//
List<DBRegionInfo> dbRegions = new ArrayList<DBRegionInfo>();
List<Node> regionNodeList = xmlUtil.getChildByName(clusterNode, "region");
DBRegionInfo regionInfo = null;
for (Node regionNode : regionNodeList) {
regionInfo = new DBRegionInfo();
// load cluster capacity
String regionCapacity = xmlUtil.getAttributeValue(regionNode, "capacity");
if (regionCapacity == null) {
throw new LoadConfigException("<region>需要配置capacity属性");
}
List<Value> values = _parseCapacity(clusterName, regionCapacity);
regionInfo.setValues(values);
regionInfo.setCapacity(regionCapacity);
// load region master
List<DBInfo> regionMasterConnection = new ArrayList<DBInfo>();
Node master = xmlUtil.getFirstChildByName(regionNode, "master");
List<Node> shardingNodeList = xmlUtil.getChildByName(master, "sharding");
for (Node shardingNode : shardingNodeList) {
String dbInfoId = shardingNode.getTextContent().trim();
if (dbConnectionPool.findDBInfo(dbInfoId) == null) {
throw new LoadConfigException("配置错误,找不到datasource id=" + dbInfoId);
}
DBInfo masterShardingDBInfo = dbConnectionPool.findDBInfo(dbInfoId).clone();
masterShardingDBInfo.setClusterName(clusterName);
masterShardingDBInfo.setMasterSlave(EnumDBMasterSlave.MASTER);
// set custom property
Map<String, String> propMap = xmlUtil.getAttributeAsMap(shardingNode);
masterShardingDBInfo.setCustomProperties(propMap);
masterShardingDBInfo.check();
regionMasterConnection.add(masterShardingDBInfo);
}
regionInfo.setMasterDBInfos(regionMasterConnection);
// load region slave
List<List<DBInfo>> regionSlaveConnection = new ArrayList<List<DBInfo>>();
List<Node> slaveNodeList = xmlUtil.getChildByName(regionNode, "slave");
int slaveIndex = 0;
for (Node slaveNode : slaveNodeList) {
shardingNodeList = xmlUtil.getChildByName(slaveNode, "sharding");
List<DBInfo> slaveConnections = new ArrayList<DBInfo>();
for (Node shardingNode : shardingNodeList) {
String dbInfoId = shardingNode.getTextContent().trim();
if (dbConnectionPool.findDBInfo(dbInfoId) == null) {
throw new LoadConfigException("配置错误,找不到datasource id=" + dbInfoId);
}
DBInfo slaveShardingDBInfo = dbConnectionPool.findDBInfo(dbInfoId).clone();
slaveShardingDBInfo.setClusterName(clusterName);
slaveShardingDBInfo.setMasterSlave(EnumDBMasterSlave.getSlaveEnum(slaveIndex++));
// set custom property
Map<String, String> propMap = xmlUtil.getAttributeAsMap(shardingNode);
slaveShardingDBInfo.setCustomProperties(propMap);
slaveShardingDBInfo.check();
slaveConnections.add(slaveShardingDBInfo);
}
regionSlaveConnection.add(slaveConnections);
}
regionInfo.setSlaveDBInfos(regionSlaveConnection);
dbRegions.add(regionInfo);
}
dbClusterInfo.setDbRegions(dbRegions);
return dbClusterInfo;
}
private List<Value> _parseCapacity(String clusterName, String regionCapacity) throws LoadConfigException {
List<Value> values = new ArrayList<Value>();
String[] aa = regionCapacity.split("\\,");
Value value = null;
for (String bb : aa) {
String[] cc = bb.split("\\-");
if (cc.length != 2) {
throw new LoadConfigException("解析集群容量错误");
}
long start = -1, end = -1;
try {
start = Long.parseLong(cc[0]);
end = Long.parseLong(cc[1]);
} catch (Exception e) {
throw new LoadConfigException("解析集群容量错误, clusterName=" + clusterName, e);
}
if (start < 0 || end < 0 || end <= start) {
throw new LoadConfigException("集群容量参数有误, clusterName=" + clusterName + ", start=" + start + ", end="
+ end);
}
value = new Value();
value.start = start;
value.end = end;
values.add(value);
}
return values;
}
}