com.taobao.tddl.jdbc.group.dbselector.EquityDbManager.java Source code

Java tutorial

Introduction

Here is the source code for com.taobao.tddl.jdbc.group.dbselector.EquityDbManager.java

Source

/*(C) 2007-2012 Alibaba Group Holding Limited.   
 *This program is free software; you can redistribute it and/or modify   
*it under the terms of the GNU General Public License version 2 as   
* published by the Free Software Foundation.   
* Authors:   
*   junyu <junyu@taobao.com> , shenxun <shenxun@taobao.com>,   
*   linxuan <linxuan@taobao.com> ,qihao <qihao@taobao.com>    
*/
package com.taobao.tddl.jdbc.group.dbselector;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.taobao.tddl.common.WeightRandom;
import com.taobao.tddl.common.util.NagiosUtils;
import com.taobao.tddl.jdbc.group.DataSourceWrapper;
import com.taobao.tddl.jdbc.group.config.ConfigManager;
import com.taobao.tddl.jdbc.group.config.GroupExtraConfig;

/**
 * 
 * 
 * 
 *
 * 
 *
 * @author linxuan
 * @author yangzhu
 *
 */

//EquityDbManager
//""EquityDbManager
public class EquityDbManager extends AbstractDBSelector {
    private static final Log logger = LogFactory.getLog(EquityDbManager.class);

    private Map<String /* dsKey */, DataSourceHolder> dataSourceMap;
    private WeightRandom weightRandom;

    public EquityDbManager(Map<String, DataSourceWrapper> dataSourceWrapperMap, Map<String, Integer> weightMap) {
        this.dataSourceMap = new HashMap<String, DataSourceHolder>(dataSourceWrapperMap.size());
        for (Map.Entry<String, DataSourceWrapper> e : dataSourceWrapperMap.entrySet()) {
            this.dataSourceMap.put(e.getKey(), new DataSourceHolder(e.getValue()));
        }
        this.weightRandom = new WeightRandom(weightMap);
    }

    public EquityDbManager(Map<String, DataSourceWrapper> dataSourceWrapperMap, Map<String, Integer> weightMap,
            GroupExtraConfig groupExtraConfig) {
        super.groupExtraConfig = groupExtraConfig;
        this.dataSourceMap = new HashMap<String, DataSourceHolder>(dataSourceWrapperMap.size());
        for (Map.Entry<String, DataSourceWrapper> e : dataSourceWrapperMap.entrySet()) {
            this.dataSourceMap.put(e.getKey(), new DataSourceHolder(e.getValue()));
        }
        this.weightRandom = new WeightRandom(weightMap);
    }

    private static String selectAliveKey(WeightRandom weightRandom, List<String> excludeKeys) {
        if (null == excludeKeys) {
            excludeKeys = new ArrayList<String>();
        }
        return weightRandom.select(excludeKeys);
    }

    /**
     * @return DataSource
     */
    public DataSource select() {
        String key = selectAliveKey(weightRandom, null);
        if (null != key) {
            return this.get(key);
        } else {
            return null;
        }
    }

    /**
     * dsKey0null
     * @param dsKey DataSourcekey, dbSelector
     * @return dsKey
     */
    public DataSourceWrapper get(String dsKey) {
        DataSourceHolder holder = dataSourceMap.get(dsKey);
        Integer weigthValue = this.weightRandom.getWeightConfig().get(dsKey);
        if (weigthValue == null || weigthValue.equals(0))
            return null;
        return holder == null ? null : holder.dsw;
    }

    //TODO DataSource[]
    public Map<String, DataSource> getDataSources() {
        Map<String, DataSource> dsMap = new HashMap<String, DataSource>(dataSourceMap.size());
        for (Map.Entry<String, DataSourceHolder> e : dataSourceMap.entrySet()) {
            dsMap.put(e.getKey(), e.getValue().dsw);
        }
        return dsMap;
    }

    public Map<String, Integer> getWeights() {
        return weightRandom.getWeightConfig();
    }

    /**
     * 
     * DataSourceargsDataSourceTryertryOnDataSource
     * @param failedDataSources DS
     * @param args DataSourceTryertryOnDataSource
     * @return nullSQLException
     */
    protected <T> T tryExecuteInternal(Map<DataSource, SQLException> failedDataSources, DataSourceTryer<T> tryer,
            int times, Object... args) throws SQLException {
        //times1
        if (!this.isSupportRetry) {
            times = 1;
        }
        WeightRandom wr = this.weightRandom;
        List<SQLException> exceptions = new ArrayList<SQLException>(0);
        List<String> excludeKeys = new ArrayList<String>(0);
        if (failedDataSources != null) {
            exceptions.addAll(failedDataSources.values());
            times = times - failedDataSources.size(); //
            for (SQLException e : failedDataSources.values()) {
                if (!exceptionSorter.isExceptionFatal(e)) {
                    //map
                    //fatalfailedDataSourcesmap?(guangxia)
                    return tryer.onSQLException(exceptions, exceptionSorter, args);
                }
            }
        }
        for (int i = 0; i < times; i++) {
            String name = selectAliveKey(wr, excludeKeys);
            if (name == null) {
                // 
                exceptions.add(new NoMoreDataSourceException("tryTime:" + i + ", excludeKeys:" + excludeKeys
                        + ", weightConfig:" + wr.getWeightConfig()));
                break;
            }

            DataSourceHolder dsHolder = dataSourceMap.get(name);
            if (dsHolder == null) {
                //(null)dataSourceMap
                throw new IllegalStateException("Can't find DataSource for name:" + name);
            }
            if (failedDataSources != null && failedDataSources.containsKey(dsHolder.dsw)) {
                excludeKeys.add(name);
                i--; //
                continue;
            }
            //TODO DataSource NA
            if (!ConfigManager.isDataSourceAvailable(dsHolder.dsw, this.readable)) {
                excludeKeys.add(name);
                i--; //
                continue;
            }

            try {
                if (dsHolder.isNotAvailable) {
                    boolean toTry = System.currentTimeMillis() - dsHolder.lastRetryTime > retryBadDbInterval;
                    if (toTry && dsHolder.lock.tryLock()) {
                        try {
                            T t = tryer.tryOnDataSource(dsHolder.dsw, args); //
                            dsHolder.isNotAvailable = false; //
                            return t;
                        } finally {
                            dsHolder.lastRetryTime = System.currentTimeMillis();
                            dsHolder.lock.unlock();
                        }
                    } else {
                        excludeKeys.add(name); //notAvailable
                        i--; //
                        continue;
                    }
                } else {
                    return tryer.tryOnDataSource(dsHolder.dsw, args); //
                }
            } catch (SQLException e) {
                exceptions.add(e);
                boolean isFatal = exceptionSorter.isExceptionFatal(e);
                if (isFatal) {
                    NagiosUtils.addNagiosLog(NagiosUtils.KEY_DB_NOT_AVAILABLE + "|" + name, e.getMessage());
                    dsHolder.isNotAvailable = true;
                }
                if (!isFatal || failedDataSources == null) {
                    //throw e; //
                    break;
                }
                logger.warn(new StringBuilder().append(i + 1).append("th try locate on [").append(name)
                        .append("] failed:").append(e.getMessage()).toString()); //,
                excludeKeys.add(name);
            }
        }
        return tryer.onSQLException(exceptions, exceptionSorter, args);
    }

    private final Random random = new Random();

    /**
     * dataSourceIndexi
     * i/IdataSourceIndexgroup
     *
      * dbidbi= db0:rwi0i2, db1:ri1, db2:ri1, db3:ri2 
      *     dataSourceIndex=0db0db0i0
      *     dataSourceIndex=1db1db2db1db2i1
      *     dataSourceIndex=2db0db3db0db3i2
      * idb0:rw, db1:r; dataSourceIndex=1db1
     */
    protected DataSourceHolder findDataSourceWrapperByIndex(int dataSourceIndex) {
        List<DataSourceHolder> holders = new ArrayList<DataSourceHolder>();
        for (DataSourceHolder dsh : dataSourceMap.values()) {
            if (dsh.dsw.isMatchDataSourceIndex(dataSourceIndex))
                holders.add(dsh);
        }

        if (!holders.isEmpty()) {
            return holders.get(random.nextInt(holders.size()));
        } else {
            return null;
        }
    }
}