/**
* Alipay.com Inc.
* Copyright (c) 2004-2013 All Rights Reserved.
*/
package com.alipay.zdal.client.jdbc;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.sql.DataSource;
import com.alipay.zdal.client.config.DataSourceParameter;
import com.alipay.zdal.client.config.ZdalConfig;
import com.alipay.zdal.client.config.ZdalConfigListener;
import com.alipay.zdal.client.config.ZdalDataSourceConfig;
import com.alipay.zdal.client.config.controller.ZdalSignalResource;
import com.alipay.zdal.client.controller.SpringBasedDispatcherImpl;
import com.alipay.zdal.client.datasource.keyweight.ZdalDataSourceKeyWeightRandom;
import com.alipay.zdal.client.datasource.keyweight.ZdalDataSourceKeyWeightRumtime;
import com.alipay.zdal.client.dispatcher.SqlDispatcher;
import com.alipay.zdal.client.exceptions.ZdalClientException;
import com.alipay.zdal.client.jdbc.dbselector.EquityDbManager;
import com.alipay.zdal.client.jdbc.dbselector.OneDBSelector;
import com.alipay.zdal.client.jdbc.dbselector.PriorityDbGroupSelector;
import com.alipay.zdal.common.Closable;
import com.alipay.zdal.common.Constants;
import com.alipay.zdal.common.DBType;
import com.alipay.zdal.common.RuntimeConfigHolder;
import com.alipay.zdal.common.jdbc.sorter.DB2ExceptionSorter;
import com.alipay.zdal.common.jdbc.sorter.MySQLExceptionSorter;
import com.alipay.zdal.common.jdbc.sorter.OracleExceptionSorter;
import com.alipay.zdal.common.lang.StringUtil;
import com.alipay.zdal.common.util.TableSuffixTypeEnum;
import com.alipay.zdal.datasource.LocalTxDataSourceDO;
import com.alipay.zdal.datasource.ZDataSource;
import com.alipay.zdal.parser.DefaultSQLParser;
import com.alipay.zdal.parser.SQLParser;
import com.alipay.zdal.rule.bean.GroovyTableDatabaseMapProvider;
import com.alipay.zdal.rule.bean.LogicTable;
import com.alipay.zdal.rule.bean.SimpleLogicTable;
import com.alipay.zdal.rule.bean.SimpleTableDatabaseMapProvider;
import com.alipay.zdal.rule.bean.SimpleTableMapProvider;
import com.alipay.zdal.rule.bean.SimpleTableTwoColumnsMapProvider;
import com.alipay.zdal.rule.bean.ZdalRoot;
import com.alipay.zdal.rule.config.beans.AppRule;
import com.alipay.zdal.rule.config.beans.ShardRule;
import com.alipay.zdal.rule.config.beans.Suffix;
import com.alipay.zdal.rule.config.beans.SuffixManager;
import com.alipay.zdal.rule.config.beans.TableRule;
import com.alipay.zdal.rule.config.beans.TableRule.ParseException;
import com.alipay.zdal.rule.ruleengine.entities.abstractentities.ListSharedElement.DEFAULT_LIST_RESULT_STRAGETY;
/**
*
* @author ����
* @version $Id: AbstractZdalDataSource.java, v 0.1 2013-1-30 ����09:56:01 Exp $
*/
public abstract class AbstractZdalDataSource extends ZdalDataSourceConfig implements DataSource,
Closable,
ZdalConfigListener {
private RuntimeConfigHolder<ZdalRuntime> runtimeConfigHolder = new RuntimeConfigHolder<ZdalRuntime>();
private SqlDispatcher writeDispatcher;
private SqlDispatcher readDispatcher;
private Map<String, ? extends Object> dataSourcePoolConfig;
/** rwRule */
private Map<String, ? extends Object> rwDataSourcePoolConfig;
private Map<String, ZdalDataSourceKeyWeightRandom> keyWeightMapConfig;
private Map<String, String> keyWeightConfig;
private int retryingTimes = 4;
private AppRule appRule;
/**
* ����Դ���ϣ�key������Դ��ʶ��value ��DataSource����Ŀǰ���õ��� ZdataSource
*/
protected Map<String, ZDataSource> dataSourcesMap = new HashMap<String, ZDataSource>();
private ZdalSignalResource zdalSignalResource = null;
/**
* Ȩ������rwp�ֱ�����Ȩ�ء�дȨ�ء�������3������ִ�С��˳������Ը�һ�����֡�
* ����ĸ�����֣���Ӧ���ֵĬ��Ϊ0������ĸ�������ֲ����֣���Ӧ���Ĭ��ֵ��return˵��
*
* @param weight
* ��ʽ
* @return int[0] R���������(Ĭ��10), int[1] W���������(Ĭ��10), int[2] P���������(Ĭ��0);
* R20W10 --> int[]{20,10,0} rp2w30 --> int[]{10,30,2}
*/
private static final Pattern weightPattern_r = Pattern
.compile("[Rr](\\d*)");
private static final Pattern weightPattern_w = Pattern
.compile("[Ww](\\d*)");
private static final Pattern weightPattern_p = Pattern
.compile("[Pp](\\d*)");
private static final Pattern weightPattern_q = Pattern
.compile("[Qq](\\d*)");
private static enum WeightRWPQEnum {
rWeight(0), wWeight(1), readPriority(2), writePriority(3);
private Integer value;
public Integer value() {
return value;
}
WeightRWPQEnum(Integer value) {
this.value = value;
}
}
/**
* ��������Դ.
*/
/**
* @see com.alipay.zdal.common.Closable#close()
*/
public final void close() throws Throwable {
if (!this.dataSourcesMap.isEmpty()) {
for (DataSource dataSource : this.dataSourcesMap.values()) {
try {
((ZDataSource) dataSource).destroy();
} catch (Throwable e) {
CONFIG_LOGGER
.error(
"##Error, ZdalDataSource tried to close datasource occured unexpected exception.",
e);
}
}
this.dataSourcesMap.clear();
}
if (zdalSignalResource != null) {
zdalSignalResource.close();
}
}
/*
* (non-Javadoc)
*
* @see
* com.alipay.zdal.client.config.ZdalConfigListener#resetWeight(java.util
* .Map)
*/
public void resetWeight(Map<String, String> keyWeights) {
this.resetZdalDataSource(keyWeights);
}
/**
* @see com.alipay.zdal.client.config.ZdalDataSourceConfig#initDataSources(com.alipay.zdal.client.config.ZdalConfig)
*/
protected final void initDataSources(ZdalConfig zdalConfig) {
if (zdalConfig.getDataSourceParameters() == null
|| zdalConfig.getDataSourceParameters().isEmpty()) {
throw new ZdalClientException("ERROR ## the datasource parameter is empty");
}
for (Entry<String, DataSourceParameter> entry : zdalConfig.getDataSourceParameters()
.entrySet()) {
try {
ZDataSource zDataSource = new ZDataSource(createDataSourceDO(entry.getValue(),
zdalConfig.getDbType(), appDsName + "." + entry.getKey()));
this.dataSourcesMap.put(entry.getKey(), zDataSource);
} catch (Exception e) {
throw new ZdalClientException("ERROR ## create dsName = " + entry.getKey()
+ " dataSource failured", e);
}
}
if (dbConfigType.isShard()) {
this.dataSourcePoolConfig = getFailoverDataSourcePoolConfig(zdalConfig
.getLogicPhysicsDsNames());//������������Ķ�Ӧ��ϵ.
this.appRule = zdalConfig.getAppRootRule();
this.appRule.init();
initForAppRule(appRule);
} else if (dbConfigType.isShardFailover()) {
this.dataSourcePoolConfig = getFailoverDataSourcePoolConfig(zdalConfig
.getLogicPhysicsDsNames());//������������Ķ�Ӧ��ϵ.
this.keyWeightConfig = zdalConfig.getFailoverRules();
this.appRule = zdalConfig.getAppRootRule();
this.appRule.init();
initForAppRule(appRule);
CONFIG_LOGGER.warn("WARN ## the shardFailoverWeight of " + appDsName + " is :"
+ getReceivDataStr(keyWeightConfig));
} else if (dbConfigType.isShardGroup()) {
this.rwDataSourcePoolConfig = zdalConfig.getGroupRules();
this.appRule = zdalConfig.getAppRootRule();
this.appRule.init();
initForAppRule(appRule);
CONFIG_LOGGER.warn("WARN ## the shardGroupWeight of " + appDsName + " is :"
+ getReceivDataStr(zdalConfig.getGroupRules()));
} else if (dbConfigType.isGroup()) {
this.rwDataSourcePoolConfig = zdalConfig.getGroupRules();
this.initForLoadBalance(zdalConfig.getDbType());
CONFIG_LOGGER.warn("WARN ## the GroupWeight of " + appDsName + " is :"
+ getReceivDataStr(zdalConfig.getGroupRules()));
}
this.initConfigListener();
}
/**
* ����failover��̬�л��Ĺ���,��Ҫ�ڷֲ�ʽ�����¿��Զ�̬��������zookeeper.
*/
private void initConfigListener() {
zdalSignalResource = new ZdalSignalResource(this);
}
private void initForLoadBalance(DBType dbType) {
Map<String, DBSelector> dsSelectors = this.buildRwDbSelectors(this.rwDataSourcePoolConfig);
this.runtimeConfigHolder.set(new ZdalRuntime(dsSelectors));
this.setDbTypeForDBSelector(dbType);
}
/**
* ����failover��������Դ����������Դ�Ķ�Ӧ��ϵ.
* @param logicPhysicsDsNames
* @return
*/
private Map<String, DataSource> getFailoverDataSourcePoolConfig(
Map<String, String> logicPhysicsDsNames) {
Map<String, DataSource> logicDataSourcesMap = new HashMap<String, DataSource>();
for (Map.Entry<String, String> mEntry : logicPhysicsDsNames.entrySet()) {
String key = mEntry.getKey().trim();
String value = mEntry.getValue().trim();
logicDataSourcesMap.put(key, dataSourcesMap.get(value));
}
return logicDataSourcesMap;
}
protected void initForAppRule(AppRule appRule) {
Map<String, DBSelector> dsSelectors = this.rwDataSourcePoolConfig == null ? buildDbSelectors(this.dataSourcePoolConfig)
: this.buildRwDbSelectors(this.rwDataSourcePoolConfig);
this.runtimeConfigHolder.set(new ZdalRuntime(dsSelectors));
// ��Ӱ�����Դkey�����Ȩ����������
if (keyWeightConfig != null && !keyWeightConfig.isEmpty()) {
// ������������������Դ��Ȩ����Ϣ
Map<String, ? extends Object> dataSourceKeyConfig = this.rwDataSourcePoolConfig == null ? this.dataSourcePoolConfig
: this.rwDataSourcePoolConfig;
keyWeightMapConfig = ZdalDataSourceKeyWeightRumtime.buildKeyWeightConfig(
keyWeightConfig, dataSourceKeyConfig);
if (keyWeightMapConfig == null) {
throw new IllegalStateException("����Դkey������Ȩ�����ô���,zdal��ʼ��ʧ�ܣ�");
}
}
this.initForDispatcher(appRule);
}
private void initForDispatcher(AppRule appRule) {
SQLParser parser = new DefaultSQLParser();
this.writeDispatcher = buildSqlDispatcher(appRule.getMasterRule(), parser);
this.readDispatcher = buildSqlDispatcher(appRule.getSlaveRule(), parser);
}
private SqlDispatcher buildSqlDispatcher(ShardRule shardRule, SQLParser parser) {
if (shardRule == null)
return null;
ZdalRoot zdalRoot = new ZdalRoot();
zdalRoot.setDBType(this.dbType);
Map<String/* key */, LogicTable> logicTableMap = new HashMap<String, LogicTable>();
if (shardRule.getTableRules() != null) {
for (Map.Entry<String/* ������ */, TableRule> e : shardRule.getTableRules().entrySet()) {
setDbTypeForDbIndex(this.dbType, e.getValue().getDbIndexArray());
LogicTable logicTable = toLogicTable(e.getValue());
logicTable.setLogicTableName(e.getKey());
logicTable.setDBType(this.dbType);
// logicTable.init(); //ZdalRoot.init()������logicTable.init()
logicTableMap.put(e.getKey(), logicTable);
}
}
zdalRoot.setLogicTableMap(logicTableMap);
if (shardRule.getDefaultDbIndex() != null) {
zdalRoot.setDefaultDBSelectorID(shardRule.getDefaultDbIndex());
}
zdalRoot.init(appDsName);
return buildSqlDispatcher(parser, zdalRoot);
}
private void setDbTypeForDbIndex(DBType dbType, String[] dbIndexes) {
Map<String, DBSelector> dbSelectors = this.runtimeConfigHolder.get().dbSelectors;
for (String dbIndex : dbIndexes) {
DBSelector dbs = dbSelectors.get(dbIndex);
if (dbs == null) {
throw new IllegalArgumentException("�������ô���[" + dbIndex + "]��dataSourcePool��û������");
}
dbs.setDbType(dbType);
// bug fixed by fanzeng. ��ΪzdalĬ�ϵ�dbType ��mysql������
// �����ȼ�����ѡ��db��ʱ���������db�����쳣��
// priorityDbGroupSelector�������ڲ���װ�ĶԵȿ�� dbtypeȥѡ��
// excetptionSorter,���db������oracle�ģ�
// bug fixed ֮ǰ����δ��ʼ��EquityDbManager��dbtype�����»���Ĭ�ϵ� mysql����ȥѡ��
if (dbs instanceof PriorityDbGroupSelector) {
EquityDbManager[] equityDbmanager = ((PriorityDbGroupSelector) dbs)
.getPriorityGroups();
if (equityDbmanager == null) {
throw new IllegalArgumentException("���ȼ��ĶԵȿⲢδ��ʼ�����������ã�");
}
for (int i = 0; i < equityDbmanager.length; i++) {
equityDbmanager[i].setDbType(dbType);
}
}
}
}
/**
* Ϊload balance ����dbType
*
* @param dbType
*/
private void setDbTypeForDBSelector(DBType dbType) {
Map<String, DBSelector> dbSelectors = this.runtimeConfigHolder.get().dbSelectors;
int i = 0;
String[] dbIndexes = new String[dbSelectors.size()];
for (Map.Entry<String, DBSelector> dbselector : dbSelectors.entrySet()) {
dbIndexes[i++] = dbselector.getKey().trim();
}
setDbTypeForDbIndex(dbType, dbIndexes);
}
/**
*
* @return
*/
private SimpleTableMapProvider getTableMapProvider(TableRule tableRule) {
SimpleTableMapProvider simpleTableMapProvider = null;
SuffixManager suffixManager = tableRule.getSuffixManager();
Suffix suf = suffixManager.getSuffix(0);
if (suf.getTbType().equals(TableSuffixTypeEnum.twoColumnForEachDB.getValue())) {
simpleTableMapProvider = new SimpleTableTwoColumnsMapProvider();
SimpleTableTwoColumnsMapProvider twoColumns = (SimpleTableTwoColumnsMapProvider) simpleTableMapProvider;
Suffix suf2 = suffixManager.getSuffix(1);
twoColumns.setFrom2(suf2.getTbSuffixFrom());
twoColumns.setTo2(suf2.getTbSuffixTo());
twoColumns.setWidth2(suf2.getTbSuffixWidth());
twoColumns.setPadding2(suf2.getTbSuffixPadding());
} else if (TableSuffixTypeEnum.dbIndexForEachDB.getValue().equals(suf.getTbType())) {
simpleTableMapProvider = new SimpleTableDatabaseMapProvider();
} else if (TableSuffixTypeEnum.groovyTableList.getValue().equals(suf.getTbType())
|| TableSuffixTypeEnum.groovyThroughAllDBTableList.getValue().equals(
suf.getTbType())
|| TableSuffixTypeEnum.groovyAdjustTableList.getValue().equals(suf.getTbType())) {
simpleTableMapProvider = new GroovyTableDatabaseMapProvider();
try {
GroovyTableDatabaseMapProvider groovyTableDatabaseMapProvider = (GroovyTableDatabaseMapProvider) simpleTableMapProvider;
groovyTableDatabaseMapProvider.setTbType(suf.getTbType());
groovyTableDatabaseMapProvider.setExpression(suffixManager.getExpression());
groovyTableDatabaseMapProvider.setTbPreffix(tableRule.getTbPreffix());
// �趨db�ĸ�������ʵ��groovy�ķֱ���ȷֲ���ʱ����õ���
groovyTableDatabaseMapProvider.setDbNumber(tableRule.getDbIndexCount());
} catch (ParseException e) {
throw new ZdalClientException("ERROR ## Tbsuffix�����������⣡������", e);
}
} else {
simpleTableMapProvider = new SimpleTableMapProvider();
}
return simpleTableMapProvider;
}
private LogicTable toLogicTable(TableRule tableRule) {
SimpleLogicTable st = new SimpleLogicTable();
st.setAllowReverseOutput(tableRule.isAllowReverseOutput());
st.setDatabases(tableRule.getDbIndexes());
if (tableRule.getDbRuleArray() != null) {
List<Object> dbRules = new ArrayList<Object>(tableRule.getDbRuleArray().length);
for (Object obj : tableRule.getDbRuleArray()) {
dbRules.add((String) obj);
}
st.setDatabaseRuleStringList(dbRules);
}
if (tableRule.getTbRuleArray() != null) {
List<Object> tbRules = new ArrayList<Object>(tableRule.getTbRuleArray().length);
for (Object obj : tableRule.getTbRuleArray()) {
tbRules.add((String) obj);
}
st.setTableRuleStringList(tbRules);
// �����2�е��������2�е��࣬������ǰ������
st.setSimpleTableMapProvider(getTableMapProvider(tableRule));
SuffixManager suffixManager = tableRule.getSuffixManager();
Suffix suf = suffixManager.getSuffix(0);
// �ֱ������ڣ������ñ�����ԣ��������κ�һ�����ԣ��ͱ�ʾ��simpleTableMapProvider
st.setFrom(suf.getTbSuffixFrom());
st.setTo(suf.getTbSuffixTo());
st.setWidth(suf.getTbSuffixWidth());
st.setPadding(suf.getTbSuffixPadding());
st.setTablesNumberForEachDatabases(suf.getTbNumForEachDb());
}
if (tableRule.getUniqueKeyArray() != null) {
st.setUniqueKeys(Arrays.asList(tableRule.getUniqueKeyArray()));
}
if (tableRule.isDisableFullTableScan()) {
st.setDefaultListResultStragety(DEFAULT_LIST_RESULT_STRAGETY.NONE);
} else {
st.setDefaultListResultStragety(DEFAULT_LIST_RESULT_STRAGETY.FULL_TABLE_SCAN);
}
return st;
}
private SpringBasedDispatcherImpl buildSqlDispatcher(SQLParser parser, ZdalRoot zdalRoot) {
if (zdalRoot != null) {
SpringBasedDispatcherImpl dispatcher = new SpringBasedDispatcherImpl();
dispatcher.setParser(parser);
dispatcher.setRoot(zdalRoot);
return dispatcher;
} else {
return null;
}
}
private DBSelector buildDbSelector(String dbIndex, DataSource[] dataSourceArray) {
Map<String, DataSource> map = new HashMap<String, DataSource>(dataSourceArray.length);
for (int i = 0; i < dataSourceArray.length; i++) {
map.put(dbIndex + Constants.DBINDEX_DSKEY_CONN_CHAR + i, dataSourceArray[i]);
}
EquityDbManager dbSelector = new EquityDbManager(dbIndex, map);
dbSelector.setAppDsName(appDsName);
return dbSelector;
}
private DBSelector buildDbSelector(String dbIndex, List<DataSource> dataSourceList) {
Map<String, DataSource> map = new HashMap<String, DataSource>(dataSourceList.size());
for (int i = 0, n = dataSourceList.size(); i < n; i++) {
map.put(dbIndex + Constants.DBINDEX_DSKEY_CONN_CHAR + i, dataSourceList.get(i));
}
EquityDbManager dbSelector = new EquityDbManager(dbIndex, map);
dbSelector.setAppDsName(appDsName);
return dbSelector;
}
@SuppressWarnings("unchecked")
private Map<String, DBSelector> buildDbSelectors(Map<String, ? extends Object> dataSourcePool) {
Map<String, DBSelector> dsSelectors = new HashMap<String, DBSelector>();
for (Map.Entry<String, ? extends Object> e : dataSourcePool.entrySet()) {
if (e.getValue() instanceof DataSource) {
OneDBSelector selector = new OneDBSelector(e.getKey(), (DataSource) e.getValue());
selector.setAppDsName(appDsName);
dsSelectors.put(e.getKey(), selector);
} else if (e.getValue() instanceof DataSource[]) {
dsSelectors.put(e.getKey(),
buildDbSelector(e.getKey(), (DataSource[]) e.getValue()));
} else if (e.getValue() instanceof List) {
dsSelectors.put(e.getKey(), buildDbSelector(e.getKey(), (List<DataSource>) e
.getValue()));
} else if (e.getValue() instanceof DBSelector) {
dsSelectors.put(e.getKey(), (DBSelector) e.getValue());
} else if (e.getValue() instanceof String) {
String[] dbs = ((String) e.getValue()).split(","); // ֧���Զ��ŷָ��Ķ������ԴID
if (dbs.length == 1) {
int index = dbs[0].indexOf(":");
String dsbeanId = index == -1 ? dbs[0] : dbs[0].substring(0, index);// ����DSȥ������Ҫ��Ȩ��
DataSource dataSource = getDataSourceObject(dsbeanId);
OneDBSelector selector = new OneDBSelector(e.getKey(), dataSource);
selector.setAppDsName(appDsName);
dsSelectors.put(e.getKey(), selector);
} else {
DataSource[] dsArray = new DataSource[dbs.length];
for (int i = 0; i < dbs.length; i++) {
dsArray[i] = getDataSourceObject(dbs[i]);
}
dsSelectors.put(e.getKey(), buildDbSelector(e.getKey(), dsArray));
}
}
dsSelectors.get(e.getKey()).setDbType(this.dbType);
}
return dsSelectors;
}
/**
* ��ȡ ����Դ
*
* @return
*/
private DataSource getDataSourceObject(String dsName) {
DataSource dataSource = null;
if (StringUtil.isBlank(dsName)) {
throw new IllegalArgumentException("The dsName can't be null!");
}
dataSource = this.dataSourcesMap.get(dsName.trim());
if (dataSource == null) {
throw new IllegalArgumentException("The dataSource can't be null,dsName=" + dsName);
}
return dataSource;
}
/**
* ����ʽ����ģʽ��֧�֣�
* �ֿ����λ������һ��dbgroup��dbgroup���ְ��������д�⣬��ʱ����masterRule��slaveRule
* ��ֻ��һ��oneRule
*
* ÿ��key��Ӧdbgroup�У�ÿ��������ж�д���Լ�Ȩ�أ���ʽ���� <entry key="slave_0"
* value="slaver_db1_a:RW ,slaver_db1_b:R" /> <entry key="slave_1"
* value="slaver_db2_a:R10W ,slaver_db2_b:R20" /> <entry key="slave_2"
* value="slaver_db3_a:R10W10,slaver_db3_b:R20W0" /> <entry key="slave_3"
* value="slaver_db4_a:R10W20,slaver_db3_b:R20W10" /> <!-- ���� --> <entry
* key="slave_4" value="slaver_db5_a,slaver_db5_b" /><!-- ���� --> <entry
* key="slave_5" value="slaver_db6" /> * ��Ӧ��Ȩ�أ� slave_0=R10W10,R10W0
* slave_1=R10W10,R20W0 slave_3=R10W20,R20W10 slave_4=R10W10,R10W10
* slave_5=RW
*
*
* ����������
* ��oneRule��ֳ�masterRule��slaveRule����oneRule�е�dbIndex�ֱ���masterRule�м�_w��
* ����slaveRule�м�_r�� tabaleA: <property name="dbIndexes"
* value="slave_0,slave_1,slave_2,slave_3" />
*
* master.tabaleA: <property name="dbIndexes"
* value="slave_0_w,slave_1_w,slave_2_w,slave_3_w" /> slaver.tabaleA:
* <property name="dbIndexes"
* value="slave_0_r,slave_1_r,slave_2_r,slave_3_r" />
* ��dbindex��ÿ������Դ�Ķ�д���ԣ���Ȩ�ز�ֵ�master_dbindex ��slave_dbindex
* master��slave�ľ�������Դ�г����еģ�ֻ�� <entry key="slave_0_w"
* value="slaver_db1_a:10,slaver_db1_b:0" /> <entry key="slave_0_r"
* value="slaver_db1_a:10,slaver_db1_b:10" /> <entry key="slave_1_w"
* value="slaver_db2_a:10,slaver_db2_b:0" /> <entry key="slave_1_r"
* value="slaver_db2_a:10,slaver_db2_b:20" /> <entry key="slave_2_w"
* value="slaver_db3_a:10,slaver_db3_b:0" /> <entry key="slave_2_r"
* value="slaver_db3_a:10,slaver_db3_b:20" /> <entry key="slave_3_w"
* value="slaver_db4_a:20,slaver_db3_b:10" /> <!-- ���� --> <entry
* key="slave_3_r" value="slaver_db4_a:10,slaver_db3_b:20" /> <!-- ���� -->
* <entry key="slave_4_w" value="slaver_db5_a:10,slaver_db5_b:10" /><!-- ����
* --> <entry key="slave_4_r" value="slaver_db5_a:10,slaver_db5_b:10" /><!--
* ���� --> <entry key="slave_5_w" value="slaver_db6" /> <entry
* key="slave_5_r" value="slaver_db6" />
*
* Ȩ�����ͣ� slave_1=R10W10,R20W0 |--> slave_1_w[10,0], slave_1_r[10,20] ��Ϊ��
* slave_1=R10W10,R0,W0 |--> slave_1_w[10,0], slave_1_r[10,0]
*
* @param dataSourcePool
* @return
*/
@SuppressWarnings("unchecked")
private Map<String, DBSelector> buildRwDbSelectors(Map<String, ? extends Object> dataSourcePool) {
Map<String, DBSelector> dsSelectors = new HashMap<String, DBSelector>();
for (Map.Entry<String, ? extends Object> e : dataSourcePool.entrySet()) {
String rdbIndex = e.getKey() + AppRule.DBINDEX_SUFFIX_READ; // "_r";
String wdbIndex = e.getKey() + AppRule.DBINDEX_SUFFIX_WRITE;// "_w";
if (e.getValue() instanceof DataSource) {
OneDBSelector rSelector = new OneDBSelector(rdbIndex, (DataSource) e.getValue());
rSelector.setAppDsName(appDsName);
dsSelectors.put(rdbIndex, rSelector);
OneDBSelector wSelector = new OneDBSelector(wdbIndex, (DataSource) e.getValue());
wSelector.setAppDsName(appDsName);
dsSelectors.put(wdbIndex, wSelector);
} else if (e.getValue() instanceof DataSource[]) {
dsSelectors.put(rdbIndex, buildDbSelector(rdbIndex, (DataSource[]) e.getValue()));
dsSelectors.put(wdbIndex, buildDbSelector(wdbIndex, (DataSource[]) e.getValue()));
} else if (e.getValue() instanceof List) {
dsSelectors.put(rdbIndex,
buildDbSelector(rdbIndex, (List<DataSource>) e.getValue()));
dsSelectors.put(wdbIndex,
buildDbSelector(wdbIndex, (List<DataSource>) e.getValue()));
} else if (e.getValue() instanceof DBSelector) {
dsSelectors.put(rdbIndex, (DBSelector) e.getValue());
dsSelectors.put(wdbIndex, (DBSelector) e.getValue());
} else if (e.getValue() instanceof String) {//ֻ�����String���͵���Ч.
parse(dsSelectors, e.getKey(), (String) e.getValue());
}
dsSelectors.get(rdbIndex).setDbType(this.dbType);
dsSelectors.get(wdbIndex).setDbType(this.dbType);
}
CONFIG_LOGGER.warn("warn ## \n" + showDbSelectors(dsSelectors, dataSourcePool));
return dsSelectors;
}
private String showDbSelectors(Map<String, DBSelector> dsSelectors,
Map<String, ? extends Object> dataSourcePool) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, ? extends Object> e : dataSourcePool.entrySet()) {
sb.append("[").append(e.getKey()).append("=").append(e.getValue()).append("]");
}
sb.append("\nconvert to:\n");
for (Map.Entry<String, DBSelector> e : dsSelectors.entrySet()) {
if (e.getValue() instanceof EquityDbManager) {
EquityDbManager db = (EquityDbManager) e.getValue();
sb.append(e.getKey()).append("=").append(db.getWeights()).append("\n");
} else if (e.getValue() instanceof PriorityDbGroupSelector) {
PriorityDbGroupSelector selector = (PriorityDbGroupSelector) e.getValue();
sb.append(selector.getId() + ": \n");
EquityDbManager[] dbs = selector.getPriorityGroups();
for (EquityDbManager db : dbs) {
sb.append(db.getId()).append(db.getWeights()).append("\n");
}
}
}
return sb.toString();
}
/**
* �������һ�飬�������ȶ������洢����Դ�� ͬһ�������ѡȡһ������ͬ���ϸ����ȼ�����ѡȡ��ֻ�и��������Ż�����ѡȡ�ͼ��������Դ
*
* ֻдrwʱ��pr=pw=0Ĭ��ֵ������Ҷ���ͬһ���ڣ�������ѡȡ,ֻдp ʱ��pr=pw=p dbs =
* slaver_db3_a:R10W10p10,slaver_db3_b:R20W0p5 �Զ���д���ֱ�ּ���pr pw dbs =
* slaver_db3_a:R10W10pr10pw2,slaver_db3_b:R20W0pr5pw10
*
* @param databaseSources
* @param dbIndex
* @param dsSelectors
*/
@SuppressWarnings("unchecked")
private void parseDbSelector(String[] databaseSources, String dbIndex,
Map<String, DBSelector> dsSelectors, WeightRWPQEnum rwPriority) {
Map<Integer, Map<String, DataSource>> initDataSourceGroups = new HashMap<Integer, Map<String, DataSource>>(
1);
Map<Integer, Map<String, Integer>> weightGroups = new HashMap<Integer, Map<String, Integer>>(
1);
for (int i = 0; i < databaseSources.length; i++) {
// ����ÿ��DataSource��Ȩ��
String dsKey = dbIndex + Constants.DBINDEX_DSKEY_CONN_CHAR + i;
String[] beanIdAndWeight = databaseSources[i].split(":"); // dbs[i]=slaver_db3_a:R10W10
DataSource dataSource = (DataSource) this.getDataSourceObject(super.getZdalConfig()
.getLogicPhysicsDsNames().get(beanIdAndWeight[0].trim()));//���������ӳ��
int[] weightRWPQ = parseWeightRW(beanIdAndWeight.length == 2 ? beanIdAndWeight[1]
: null);
// ��ñ���������ݿ��飬û����
Map<String, DataSource> initDataSources = initDataSourceGroups
.get(weightRWPQ[rwPriority.value()]);
if (initDataSources == null) {
initDataSources = new HashMap<String, DataSource>(databaseSources.length);
initDataSourceGroups.put(weightRWPQ[rwPriority.value()], initDataSources);
}
// ��ñ������Ȩ���飬û����
Map<String, Integer> weights = weightGroups.get(weightRWPQ[rwPriority.value()]);
if (weights == null) {
weights = new HashMap<String, Integer>(databaseSources.length);
weightGroups.put(weightRWPQ[rwPriority.value()], weights);
}
weights.put(dsKey, weightRWPQ[rwPriority.value() - 2]);
initDataSources.put(dsKey, dataSource);
}
if (initDataSourceGroups.size() == 1) {
Map<String, DataSource> rInitDataSources = initDataSourceGroups.values().toArray(
new Map[1])[0];
Map<String, Integer> rWeights = weightGroups.values().toArray(new Map[1])[0];
EquityDbManager equityDbManager = new EquityDbManager(dbIndex, rInitDataSources,
rWeights);
if (dbType != null) {
equityDbManager.setDbType(dbType);
}
equityDbManager.setAppDsName(appDsName);
dsSelectors.put(dbIndex, equityDbManager);
} else {
List<Integer> rpriorityKeys = new ArrayList<Integer>(initDataSourceGroups.size());
rpriorityKeys.addAll(initDataSourceGroups.keySet());
Collections.sort(rpriorityKeys);
EquityDbManager[] rpriorityGroups = new EquityDbManager[rpriorityKeys.size()];
for (int i = 0; i < rpriorityGroups.length; i++) {
Integer key = rpriorityKeys.get(i);
Map<String, DataSource> rInitDataSources = initDataSourceGroups.get(key);
Map<String, Integer> rWeights = weightGroups.get(key);
EquityDbManager equityDbManager = new EquityDbManager(dbIndex, rInitDataSources,
rWeights);
if (dbType != null)
equityDbManager.setDbType(dbType);
equityDbManager.setAppDsName(appDsName);
rpriorityGroups[i] = equityDbManager;
}
dsSelectors.put(dbIndex, new PriorityDbGroupSelector(dbIndex, rpriorityGroups));
}
}
// <entry key="slave_2" value="slaver_db3_a:R10W10,slaver_db3_b:R20W0" />
private void parse(Map<String, DBSelector> dsSelectors, String dbIndex, String commaDbs) {
String rdbIndex = dbIndex + AppRule.DBINDEX_SUFFIX_READ; // "_r";
String wdbIndex = dbIndex + AppRule.DBINDEX_SUFFIX_WRITE;// "_w";
String[] dbs = commaDbs.split(","); // ֧���Զ��ŷָ��Ķ������ԴID
// ���ֻ��һ��DataSource������OneDBSelector
if (dbs.length == 1) {
int index = dbs[0].indexOf(":");
String dsbeanId = index == -1 ? dbs[0] : dbs[0].substring(0, index);// ����DSȥ������Ҫ��Ȩ��
DataSource ds = this.getDataSourceObject(super.getZdalConfig().getLogicPhysicsDsNames()
.get(dsbeanId.trim()));//���������ӳ��
OneDBSelector selectorRead = new OneDBSelector(rdbIndex, ds);
selectorRead.setAppDsName(appDsName);
OneDBSelector selectorWrite = new OneDBSelector(wdbIndex, ds);
selectorWrite.setAppDsName(appDsName);
dsSelectors.put(rdbIndex, selectorRead);
dsSelectors.put(wdbIndex, selectorWrite);
} else {
// �ֱ����д������Դ
parseDbSelector(dbs, wdbIndex, dsSelectors, WeightRWPQEnum.writePriority);
parseDbSelector(dbs, rdbIndex, dsSelectors, WeightRWPQEnum.readPriority);
}
}
private int[] parseWeightRW(String weight) {
if (weight == null) {
return new int[] { 10, 10, 0, 0 }; // Ĭ�϶�д������д��ΪP0��
}
int r, w, p, q;
weight = weight.trim().toLowerCase(); // ͳ�Ƶ�Сд�����������
if (weight.indexOf('R') == -1 && weight.indexOf('r') == -1) {
r = 0;
} else {
r = parseNumber(weightPattern_r, weight, 10);
}
if (weight.indexOf('W') == -1 && weight.indexOf('w') == -1) {
w = 0;
} else {
w = parseNumber(weightPattern_w, weight, 10);
}
if (weight.indexOf('P') == -1 && weight.indexOf('p') == -1) {
p = 0;
} else {
p = parseNumber(weightPattern_p, weight, 0);
}
if (weight.indexOf('Q') == -1 && weight.indexOf('q') == -1) {
q = 0;
} else {
q = parseNumber(weightPattern_q, weight, 0);
}
return new int[] { r, w, p, q };
}
private int parseNumber(Pattern p, String weight, int defaultValue) {
Matcher m = p.matcher(weight);
if (!m.find()) {// ������matches()�Ͳ��У�
throw new IllegalArgumentException(
"Ȩ�����ò���������ʽ[Rr](\\d*)[Ww](\\d*)[Pp](\\d*)[Qq](\\d*)��" + weight);
}
if (m.group(1).length() == 0) {
return defaultValue;
} else {
return Integer.parseInt(m.group(1));
}
}
/**
* reset zdatasource��failoverRule��readWriteRule,Ŀǰtair����Դ��֧���ؽ�.
*
* @param zdalConfig
*/
public void resetZdalDataSource(Map<String, String> keyWeights) {
try {
long startReset = System.currentTimeMillis();
if (keyWeightConfig != null && !keyWeightConfig.isEmpty()) {
this.resetKeyWeightConfig(keyWeights);
String resetKeyWeightResults = getReceivDataStr(keyWeights);
// �����е�Ȩ�ص�����Ϻ��ٴ�ӡ����־
CONFIG_LOGGER.warn("WARN ## resetKeyWeightConfig[" + appDsName + "]:"
+ resetKeyWeightResults);
CONFIG_LOGGER.warn("WARN ## reset the config success,cost "
+ (System.currentTimeMillis() - startReset)
+ " ms,the appDsName = " + appDsName);
this.keyWeightConfig = keyWeights;
} else if (rwDataSourcePoolConfig != null && !rwDataSourcePoolConfig.isEmpty()) {
this.resetDbWeight(keyWeights);
String dbWeightConfigs = getReceivDataStr(keyWeights);
// �����е�Ȩ�ص�����Ϻ��ٴ�ӡ����־
CONFIG_LOGGER.warn("WARN ## resetRwDataSourceConfig[" + appDsName + "]:"
+ dbWeightConfigs);
CONFIG_LOGGER.warn("WARN ## reset the config success,cost "
+ (System.currentTimeMillis() - startReset)
+ " ms,the appDsName = " + appDsName);
this.rwDataSourcePoolConfig = keyWeights;
} else {
throw new ZdalClientException(
"ERROR ## only keyWeightConfig,rwDataSourcePoolConfig can reset weight");
}
} catch (Exception e) {
throw new ZdalClientException("ERROR ## appDsName = " + zdalConfig.getAppDsName()
+ " reset config failured ", e);
}
}
/**
* zdal reset rw weight
*
* @param p
*/
private void resetDbWeight(Map<String, String> p) {
Map<String, DBSelector> dbSelectors = this.runtimeConfigHolder.get().dbSelectors;
for (Map.Entry<String, String> entrySet : p.entrySet()) {
String dbIndex = ((String) entrySet.getKey()).trim();
String commaWeights = ((String) entrySet.getValue()).trim();
if (this.rwDataSourcePoolConfig != null
&& this.rwDataSourcePoolConfig.get(dbIndex) != null) {
// readwriteRule��ʽ��weight
resetRwDbWeight(dbIndex, dbSelectors, commaWeights);
} else if (this.dataSourcePoolConfig != null
&& dataSourcePoolConfig.get(dbIndex) != null) {
String[] rdwds = commaWeights.split(",");
int[] weights = new int[rdwds.length];
for (int i = 0; i < rdwds.length; i++) {
weights[i] = Integer.parseInt(rdwds[i]);
}
resetDbWeight(dbIndex, dbSelectors, weights);
}
}
}
/**
* @param commaWeights
* : R10W10,R10W0 ��ʽ��dskey0=r10w10,r10w0
*/
private void resetRwDbWeight(String dbIndex, Map<String, DBSelector> dbSelectors,
String commaWeights) {
String[] rdwds = commaWeights.split(",");
int[] rWeights = new int[rdwds.length];
int[] wWeights = new int[rdwds.length];
for (int i = 0; i < rdwds.length; i++) {
int[] weightRW = parseWeightRW(rdwds[i]);
rWeights[i] = weightRW[0];
wWeights[i] = weightRW[1];
}
resetDbWeight(dbIndex + AppRule.DBINDEX_SUFFIX_READ, dbSelectors, rWeights);
resetDbWeight(dbIndex + AppRule.DBINDEX_SUFFIX_WRITE, dbSelectors, wWeights);
}
private void resetDbWeight(String dbIndex, Map<String, DBSelector> dbSelectors, int[] weights) {
DBSelector dbSelector = dbSelectors.get(dbIndex);
if (dbSelector == null) {
throw new ZdalClientException(
"ERROR ## Couldn't find dbIndex in current datasoures. dbIndex:" + dbIndex);
}
Map<String, Integer> weightMap = new HashMap<String, Integer>(weights.length);
for (int i = 0; i < weights.length; i++) {
weightMap.put(dbIndex + Constants.DBINDEX_DSKEY_CONN_CHAR + i, weights[i]);
}
dbSelector.setWeight(weightMap);
}
/**
* added by fanzeng. changed by boya. ����p��ʽ���� group_00=ds0:10,ds1:0
* group_01=ds2:10,ds3:0 group_02=ds4:0,ds5:10 һ��ֻ��һ�����ʱ���õ�����Ȩ�أ�Ĭ��Ϊ10
*
* @param p
* ������������
*/
protected void resetKeyWeightConfig(Map<String, String> p) {
// Map<String, ZdalDataSourceKeyWeightRandom> keyWeightMapHolder =
// GetDataSourceSequenceRules
// .getKeyWeightRuntimeConfigHoder().get().getKeyWeightMapHolder();
Map<String, ZdalDataSourceKeyWeightRandom> keyWeightMapHolder = keyWeightMapConfig;
for (Entry<String, String> entrySet : p.entrySet()) {
String groupKey = entrySet.getKey();
String value = entrySet.getValue();
if (StringUtil.isBlank(groupKey) || StringUtil.isBlank(value)) {
throw new ZdalClientException("ERROR ## ����ԴgroupKey=" + groupKey
+ "����Ȩ��������Ϣ����Ϊ��,value=" + value);
}
String[] keyWeightStr = value.split(",");
String[] weightKeys = new String[keyWeightStr.length];
int[] weights = new int[keyWeightStr.length];
for (int i = 0; i < keyWeightStr.length; i++) {
if (StringUtil.isBlank(keyWeightStr[i])) {
throw new ZdalClientException("ERROR ## ����ԴkeyWeightStr[" + i
+ "]����Ȩ��������Ϣ����Ϊ��.");
}
String[] keyAndWeight = keyWeightStr[i].split(":");
if (keyAndWeight.length != 2) {
throw new ZdalClientException("ERROR ## ����Դkey��������Ȩ�ش���,keyWeightStr[" + i
+ "]=" + keyWeightStr[i] + ".");
}
String key = keyAndWeight[0];
String weightStr = keyAndWeight[1];
if (StringUtil.isBlank(key) || StringUtil.isBlank(weightStr)) {
CONFIG_LOGGER.error("ERROR ## ����Դ����Ȩ��������Ϣ����Ϊ��,key=" + key + ",weightStr="
+ weightStr);
return;
}
weightKeys[i] = key.trim();
weights[i] = Integer.parseInt(weightStr.trim());
}
// ���� groupKey�Լ���Ӧ��keyAndWeightMapȥ��ѯ
ZdalDataSourceKeyWeightRandom weightRandom = keyWeightMapHolder.get(groupKey);
if (weightRandom == null) {
throw new ZdalClientException("ERROR ## �����͵İ�����Դkey����Ȩ�������е�key����,�Ƿ���groupKey="
+ groupKey);
}
for (String newKey : weightKeys) {
if (weightRandom.getWeightConfig() == null
|| !weightRandom.getWeightConfig().containsKey(newKey)) {
throw new ZdalClientException("�����͵�����Դ����" + groupKey
+ "Ȩ�������а��������ڸ��������Դ��ʶ,key=" + newKey);
}
}
if (weightKeys.length != weightRandom.getDataSourceNumberInGroup()) {
throw new ZdalClientException("�����͵İ�����Դkey����Ȩ�������У�����groupKey=" + groupKey
+ "����������Դ�������� ,size=" + weightKeys.length
+ ",the size should be "
+ weightRandom.getDataSourceNumberInGroup());
}
// ���ݸ����groupKey�Լ���Ӧ��keyAndWeightMap����TDataSourceKeyWeightRandom
ZdalDataSourceKeyWeightRandom TDataSourceKeyWeightRandom = new ZdalDataSourceKeyWeightRandom(
weightKeys, weights);
keyWeightMapHolder.put(groupKey, TDataSourceKeyWeightRandom);
}
// ���ñ��ص�keyWeightMapCofig���ԣ�ȫ����Ի������ڸ�����
this.keyWeightMapConfig = keyWeightMapHolder;
}
/**
* added for zdal
*
* @param p
* @return
*/
private String getReceivDataStr(Map<String, String> p) {
String str = "";
if (p != null) {
StringBuilder sb = new StringBuilder();
for (Entry<String, String> entry : p.entrySet()) {
String key = entry.getKey().trim();
String value = entry.getValue().trim();
sb.append(key).append("=").append(value).append(";");
}
str = sb.toString();
}
return str;
}
/**
* zdataconsole�е�������Ϣת����ZdataSource��������Ϣ .
*
* @param parameter
* @return
*/
private LocalTxDataSourceDO createDataSourceDO(DataSourceParameter parameter, DBType dbType,
String dsName) throws Exception {
LocalTxDataSourceDO dsDo = new LocalTxDataSourceDO();
dsDo.setDsName(dsName);
dsDo.setConnectionURL(parameter.getJdbcUrl());
dsDo.setUserName(parameter.getUserName());
// dsDo.setEncPassword(parameter.getPassword());
dsDo.setPassWord(parameter.getPassword());//�������ĵ�����.
dsDo.setMinPoolSize(parameter.getMinConn());
dsDo.setMaxPoolSize(parameter.getMaxConn());
dsDo.setDriverClass(parameter.getDriverClass());
dsDo.setBlockingTimeoutMillis(parameter.getBlockingTimeoutMillis());
dsDo.setIdleTimeoutMinutes(parameter.getIdleTimeoutMinutes());
dsDo.setPreparedStatementCacheSize(parameter.getPreparedStatementCacheSize());
dsDo.setQueryTimeout(parameter.getQueryTimeout());
dsDo.getConnectionProperties().putAll(parameter.getConnectionProperties());
dsDo.setPrefill(parameter.getPrefill());
if (dbType.isMysql()) {
dsDo.setExceptionSorterClassName(MySQLExceptionSorter.class.getName());
} else if (dbType.isOracle()) {
dsDo.setExceptionSorterClassName(OracleExceptionSorter.class.getName());
} else if (dbType.isDB2()) {
dsDo.setExceptionSorterClassName(DB2ExceptionSorter.class.getName());
} else {
throw new ZdalClientException("ERROR ## the DbType must be mysql/oracle/db2.");
}
dsDo.setConnectionProperties(parameter.getConnectionProperties());
return dsDo;
}
/**
* ����Դ��connection�ķ�װ.
*
* @see javax.sql.DataSource#getConnection()
*/
public Connection getConnection() throws SQLException {
if (inited.get() == false) {
throw new ZdalClientException("ERROR ## the ZdalDataSource has not init");
}
ZdalConnection connection = new ZdalConnection();
this.buildTconnection(connection);
return connection;
}
/**
* @see javax.sql.DataSource#getConnection(java.lang.String,
* java.lang.String)
*/
public Connection getConnection(String username, String password) throws SQLException {
if (inited.get() == false) {
throw new ZdalClientException("ERROR ## the ZdalDataSource has not init");
}
ZdalConnection connection = new ZdalConnection(username, password);
this.buildTconnection(connection);
return connection;
}
/**
* �������ӣ�����Ҫ�IJ������õ�ZdalConnection��ȥ��Ȼ�����ø� ZdalStatement ����
*
* @param connection
*/
private void buildTconnection(ZdalConnection connection) {
ZdalRuntime rt = this.runtimeConfigHolder.get();
connection.setDataSourcePool(rt == null ? null : rt.dbSelectors);
connection.setWriteDispatcher(this.writeDispatcher);
connection.setReadDispatcher(this.readDispatcher);
connection.setRetryingTimes(this.retryingTimes);
connection.setDbConfigType(this.dbConfigType);
connection.setAppDsName(appDsName);
}
/**
* @see javax.sql.CommonDataSource#getLoginTimeout()
*/
public int getLoginTimeout() throws SQLException {
throw new UnsupportedOperationException("getLoginTimeout");
}
/**
* @see javax.sql.CommonDataSource#setLoginTimeout(int)
*/
public void setLoginTimeout(int seconds) throws SQLException {
throw new UnsupportedOperationException("setLoginTimeout");
}
/**
* @see javax.sql.CommonDataSource#getLogWriter()
*/
public PrintWriter getLogWriter() throws SQLException {
throw new UnsupportedOperationException("getLogWriter");
}
/**
* @see javax.sql.CommonDataSource#setLogWriter(java.io.PrintWriter)
*/
public void setLogWriter(PrintWriter out) throws SQLException {
throw new UnsupportedOperationException("setLogWriter");
}
/**
* @see java.sql.Wrapper#isWrapperFor(java.lang.Class)
*/
public boolean isWrapperFor(Class<?> iface) throws SQLException {
throw new UnsupportedOperationException("isWrapperFor");
}
/**
* @see java.sql.Wrapper#unwrap(java.lang.Class)
*/
public <T> T unwrap(Class<T> iface) throws SQLException {
throw new UnsupportedOperationException("unwrap");
}
public Map<String, ZdalDataSourceKeyWeightRandom> getKeyWeightMapConfig() {
return keyWeightMapConfig;
}
public RuntimeConfigHolder<ZdalRuntime> getRuntimeConfigHolder() {
return runtimeConfigHolder;
}
public SqlDispatcher getWriteDispatcher() {
return writeDispatcher;
}
public SqlDispatcher getReadDispatcher() {
return readDispatcher;
}
public AppRule getAppRule() {
return appRule;
}
public Map<String, String> getKeyWeightConfig() {
return keyWeightConfig;
}
public Map<String, ? extends Object> getRwDataSourcePoolConfig() {
return rwDataSourcePoolConfig;
}
public Map<String, ZDataSource> getDataSourcesMap() {
return dataSourcesMap;
}
public ZdalSignalResource getZdalSignalResource() {
return zdalSignalResource;
}
public int getRetryingTimes() {
return retryingTimes;
}
public void setRetryingTimes(int retryingTimes) {
this.retryingTimes = retryingTimes;
}
public Map<String, ? extends Object> getDataSourcePoolConfig() {
return dataSourcePoolConfig;
}
}