package com.taobao.tddl.group.dbselector; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import javax.sql.DataSource; import com.taobao.tddl.group.config.GroupConfigManager; import com.taobao.tddl.group.config.GroupExtraConfig; import com.taobao.tddl.group.jdbc.DataSourceWrapper; /** * <pre> * 用于运行期间主备切换的场景,DBA通常在做完主备切换后才会去修改每个TAtomDataSource的配置。 * 假设有d0,d1,d2三个库,完成一次切换时对应每个TAtomDataSource的状态快照如下: * ===================== * d0 d1 d2 * (1) rw r r * (2) na r r * (3) na rw r * (4) r rw r * ===================== * (1)是切换前正常的状态快照,(4)是切换完成后的状态快照,(2)、(3)是中间过程的状态快照。 * 如果业务系统在状态(1)、(3)、(4)下要求进行更新操作,则更新操作被允许,因为在这三个状态中都能找到一个含有"w"的db, * 如果业务系统在状态(2)下要求进行更新操作,则更新操作被拒绝,抛出异常,因为在这个状态中找不到含有"w"的db, * </pre> * * @author yangzhu */ public class RuntimeWritableAtomDBSelector extends AbstractDBSelector { private Map<String, DataSourceWrapper> dataSourceWrapperMap = new HashMap<String, DataSourceWrapper>(); private EquityDbManager equityDbManager; public RuntimeWritableAtomDBSelector(Map<String, DataSourceWrapper> dataSourceWrapperMap, GroupExtraConfig groupExtraConfig){ Map<String, Integer> dummyWeightMap = new HashMap<String, Integer>(dataSourceWrapperMap.size()); for (String dsKey : dataSourceWrapperMap.keySet()) dummyWeightMap.put(dsKey, 10); this.equityDbManager = new EquityDbManager(dataSourceWrapperMap, dummyWeightMap, groupExtraConfig); this.readable = false; // 只用于写 this.dataSourceWrapperMap = dataSourceWrapperMap; } public DataSource select() { for (Map.Entry<String, DataSourceWrapper> e : dataSourceWrapperMap.entrySet()) { if (GroupConfigManager.isDataSourceAvailable(e.getValue(), false)) { return e.getValue(); } } return null; } @SuppressWarnings({ "unchecked", "rawtypes" }) public Map getDataSources() { return dataSourceWrapperMap; } @Override protected <T> T tryExecuteInternal(Map<DataSource, SQLException> failedDataSources, DataSourceTryer<T> tryer, int times, Object... args) throws SQLException { return equityDbManager.tryExecuteInternal(failedDataSources, tryer, times, args); } public DataSourceWrapper get(String dsKey) { return dataSourceWrapperMap.get(dsKey); } protected DataSourceHolder findDataSourceWrapperByIndex(int dataSourceIndex) { return equityDbManager.findDataSourceWrapperByIndex(dataSourceIndex); } }