/**
* Alipay.com Inc.
* Copyright (c) 2004-2012 All Rights Reserved.
*/
package com.alipay.zdal.client.jdbc.dbselector;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.apache.log4j.Logger;
import com.alipay.zdal.client.jdbc.ZdalStatement.DB_OPERATION_TYPE;
import com.alipay.zdal.common.OperationDBType;
import com.alipay.zdal.common.WeightRandom;
import com.alipay.zdal.common.jdbc.sorter.ExceptionSorter;
/**
* �����ȼ�ѡ���selector
*
* ÿ��ѡ��ֻ�����ȼ���ߵ�һ��DB��ѡ�����������ã��ż�������һ�����ȼ���DB����ѡ��
*
* ���ȼ���ͬ��DB�������ѡ��
*
* ԭʼ����TCҪ����ÿ��dbgroup�����ȶ����⣬�����ⲻ����ʱ���Զ�������
* ��չ����һ���౸��������������⡣�����ⶼ������ʱ���Ŷ�����
*
* Ϊ�˷��㴦��ͽӿ�һ�£�������Ҫ��
* 1. Ŀǰֻ֧�ֶ������ȼ���
* 2. һ��Ȩ�����͵���Ϣ�У�������
* 3. һ������Դֻ����һ�����ȼ����У�
*
*
*/
public class PriorityDbGroupSelector extends AbstractDBSelector {
private static final Logger logger = Logger.getLogger(PriorityDbGroupSelector.class);
/**
* �����ȼ�˳�������ݿ��顣Ԫ��0���ȼ���ߡ�ÿ��EquityDbManagerԪ�ش��������ͬ���ȼ���һ�����ݿ�
*/
//private EquityDbManager[] priorityGroups;
private PriorityGroupsDataSources[] priorityGroupsDataSourceHolder;
public PriorityDbGroupSelector(String id, EquityDbManager[] priorityGroups) {
super(id);
// this.priorityGroups = priorityGroups;
if (priorityGroupsDataSourceHolder == null) {
priorityGroupsDataSourceHolder = new PriorityGroupsDataSources[priorityGroups.length];
}
for (int i = 0; i < priorityGroups.length; i++) {
this.priorityGroupsDataSourceHolder[i] = new PriorityGroupsDataSources(
priorityGroups[i]);
}
if (priorityGroupsDataSourceHolder == null || priorityGroupsDataSourceHolder.length == 0) {
throw new IllegalArgumentException("PriorityGroupsDataSourceHolder is null or empty!");
}
}
public DataSource select() {
for (int i = 0; i < priorityGroupsDataSourceHolder.length; i++) {
DataSource ds = getEquityDbManager(i).select();
if (ds != null) {
return ds;
}
}
return null;
}
/**
* ȡÿ�������weightKey���ܵ�weightKey�Ľ�������������
*/
public void setWeight(Map<String, Integer> weightMap) {
for (int i = 0; i < priorityGroupsDataSourceHolder.length; i++) {
Map<String, Integer> oldWeights = getEquityDbManager(i).getWeights();
Map<String, Integer> newWeights = new HashMap<String, Integer>(oldWeights.size());
for (Map.Entry<String, Integer> e : weightMap.entrySet()) {
if (oldWeights.containsKey(e.getKey())) {
newWeights.put(e.getKey(), e.getValue());
}
}
getEquityDbManager(i).setWeightRandom(new WeightRandom(newWeights));
}
}
private static class DataSourceTryerWrapper<T> implements DataSourceTryer<T> {
private final List<SQLException> historyExceptions;
private final DataSourceTryer<T> tryer;
public DataSourceTryerWrapper(DataSourceTryer<T> tryer, List<SQLException> historyExceptions) {
this.tryer = tryer;
this.historyExceptions = historyExceptions;
}
public T onSQLException(List<SQLException> exceptions, ExceptionSorter exceptionSorter,
Object... args) throws SQLException {
Exception last = exceptions.get(exceptions.size() - 1);
if (last instanceof NoMoreDataSourceException) {
if (exceptions.size() > 1) {
exceptions.remove(exceptions.size() - 1);
}
historyExceptions.addAll(exceptions);
throw (NoMoreDataSourceException) last;
} else {
return tryer.onSQLException(exceptions, exceptionSorter, args);
}
}
public T tryOnDataSource(DataSource ds, String name, Object... args) throws SQLException {
return tryer.tryOnDataSource(ds, name, args);
}
};
/**
* ����EquityDbManager��tryExecuteʵ�֣����û���tryer��һ����װ����wrapperTryer.onSQLException��
* �����һ��e��NoMoreDataSourceExceptionʱ������ԭtryer��onSQLException, ת�������������ȼ���
*/
public <T> T tryExecute(Map<DataSource, SQLException> failedDataSources,
DataSourceTryer<T> tryer, int times, DB_OPERATION_TYPE operationType,
Object... args) throws SQLException {
final List<SQLException> historyExceptions = new ArrayList<SQLException>(0);
DataSourceTryer<T> wrapperTryer = new DataSourceTryerWrapper<T>(tryer, historyExceptions);
for (int i = 0; i < priorityGroupsDataSourceHolder.length; i++) {
try {
return priorityGroupsDataSourceHolder[i].tryExecute(failedDataSources,
wrapperTryer, times, operationType, i, args);
} catch (NoMoreDataSourceException e) {
logger.warn("NoMoreDataSource for retry for priority group " + i);
}
}
//���е����ȼ��鶼�����ã����׳��쳣
return tryer.onSQLException(historyExceptions, exceptionSorter, args);
}
//Ĭ�϶�д�ⶼ���Խ�������
public boolean isSupportRetry(OperationDBType type) {
return true;
}
public EquityDbManager[] getPriorityGroups() {
EquityDbManager[] priorityGroups = new EquityDbManager[priorityGroupsDataSourceHolder.length];
for (int i = 0; i < priorityGroupsDataSourceHolder.length; i++) {
priorityGroups[i] = getEquityDbManager(i);
}
return priorityGroups;
}
private EquityDbManager getEquityDbManager(int i) {
if (priorityGroupsDataSourceHolder[i] == null
|| priorityGroupsDataSourceHolder[i].getEquityDbManager() == null) {
throw new IllegalArgumentException(
"The priorityGroupsDataSourceHolder or equityDbManager can't be null!");
}
return priorityGroupsDataSourceHolder[i].getEquityDbManager();
}
}