All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.javaclub.cdl.client.group.DefaultDBSelector Maven / Gradle / Ivy

There is a newer version: 2.3.9
Show newest version
package com.github.javaclub.cdl.client.group;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import javax.sql.DataSource;

import com.github.javaclub.cdl.client.common.DataSourceHolder;
import com.github.javaclub.cdl.client.common.DataSourceWrapper;
import com.github.javaclub.cdl.client.util.SQLMonitors;

public class DefaultDBSelector extends AbstractDBSelector {
	private List dataSourceHolderList = new ArrayList();
	private AtomicInteger rid = new AtomicInteger();
	private boolean isMaster;

	@Override
	protected DataSourceHolder findDataSourceWrapperByIndex(int dataSourceIndex) {
		boolean result = true;
		try{
			SQLMonitors.entry(isMaster ? "write":"read");
			for (DataSourceHolder holder : dataSourceHolderList) {
				if (holder.getDsw().getDataSourceIndex() == dataSourceIndex) {
					return holder;
				}
			}
			result = false;
			return null;
		}finally{
			SQLMonitors.exit(isMaster ? "write":"read", result);
		}
	}

	@Override
	protected  T tryExecuteInternal(Map failedDataSources, DataSourceTryer tryer, int times, Object... args)
			throws SQLException {
		List exceptions = new ArrayList(0);
		if (failedDataSources != null) {
			exceptions.addAll(failedDataSources.values());
			times = times - failedDataSources.size();
			for (SQLException e : failedDataSources.values()) {
				if (!exceptionSorter.isExceptionFatal(e)) {
					return tryer.onSQLException(exceptions, exceptionSorter, args);
				}
			}
		}

		// 默认重试一次
		times = 2;

		DataSourceHolder lastDsHolder = null;
		DataSourceHolder dsHolder;
		while ((dsHolder = getRandomDataSourceHolder(lastDsHolder)) != null && --times >= 0) {
			boolean result = true;
			try {
				SQLMonitors.entry(isMaster ? "write":"read");
				lastDsHolder = dsHolder;
				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 { // 此库暂不能使用
						continue;
					}
				} else {
					return tryer.tryOnDataSource(dsHolder.dsw, args);
				}
			} catch (SQLException e) {
				result = false;
				exceptions.add(e);
				boolean isFatal = exceptionSorter.isExceptionFatal(e);
				if (isFatal) {
					dsHolder.isNotAvailable = true;
				}
				if (!isFatal) {
					// 如果不是数据库不可用异常,或者不要求重试,直接抛出
					break;
				}
			}finally{
				SQLMonitors.exit(isMaster ? "write":"read", result);
			}
		}
		if (exceptions.isEmpty()) { // 所有的数据库都不能使用
			exceptions.add(new SQLException("not found available dataSource"));
		}
		return tryer.onSQLException(exceptions, exceptionSorter, args);
	}

	public DataSourceHolder getRandomDataSourceHolder(DataSourceHolder curDataSourceHolder) {
		if (dataSourceHolderList.isEmpty()) {
			return null;
		}
		if (dataSourceHolderList.size() == 1) {
			if (curDataSourceHolder == null) {
				return dataSourceHolderList.get(0);
			} else { // 避免重复使用相同ds
				return null;
			}
		}
		
		if (rid.get() > Integer.MAX_VALUE - 10000) {
			rid.set(0);
		}
		
		for (int i = 0; i < dataSourceHolderList.size(); i++) {
			int index = rid.incrementAndGet() % dataSourceHolderList.size();
			
			// 避免重复使用相同ds
			if (curDataSourceHolder == null || !curDataSourceHolder.equals(dataSourceHolderList.get(index))) {
				return dataSourceHolderList.get(index);
			}
		}
		return null;
	}

	public void addDataSourceHolder(DataSourceHolder dataSourceHolder) {
		if (isMaster) { // 写库,只有一个
			dataSourceHolderList.add(dataSourceHolder);
		} else {
			if (dataSourceHolder.getDsw().getReadWeight().r > 0) { // 读库
				for (int i = 0; i < dataSourceHolder.getDsw().getReadWeight().r; i++) { // 按照权重添加
					dataSourceHolderList.add(dataSourceHolder);
				}
				if (dataSourceHolderList.size() > 2) { // 随机打散
					Collections.shuffle(dataSourceHolderList);
				}
			}
		}
	}

	public void setMaster(boolean isMaster) {
		this.isMaster = isMaster;
	}

	@Override
	public DataSourceWrapper getDataSourceWrapperForMeta() {
		if(!dataSourceHolderList.isEmpty()){
			return dataSourceHolderList.get(0).getDsw();
		}
		return null;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy