package com.easyooo.framework.sharding.routing;
import java.util.List;
import com.easyooo.framework.sharding.DataSourceKey;
import com.easyooo.framework.sharding.DsRoutingException;
import com.easyooo.framework.sharding.Module;
import com.easyooo.framework.sharding.NumberRange;
import com.easyooo.framework.sharding.RoutingConfigHolder;
import com.easyooo.framework.sharding.RoutingContext;
import com.easyooo.framework.sharding.RoutingGroup;
import com.easyooo.framework.sharding.RoutingRule;
/**
* 根据分组进行取模数。
* 将分组按照区间进行匹配,匹配上了在根据节点数量进行取模数
*
* @author Killer
*/
public class RangeRoutingRule implements RoutingRule {
@Override
public DataSourceKey routing(Module module, RoutingContext context) throws DsRoutingException {
Long keyword = context.getKeyword();
// 查找对应的路由组
RoutingGroup group = findRoutingGroup(module, keyword);
if(group == null){
DsRoutingException dre = new DsRoutingException(module
+ " can't locate the datasource, Because there is no group");
dre.setKeyword(keyword);
dre.setModule(module);
throw dre;
}
List<DataSourceKey> dsk = group.getDataSourceKeys();
if(dsk.size() == 1){
return dsk.get(0);
}
// 存在多个数据源,检查Keyword
checkKeyword(module, keyword);
long modulus = keyword % dsk.size();
return dsk.get(new Long(modulus).intValue());
}
private void checkKeyword(Module module, Long keyword){
if(keyword == null){
DsRoutingException dre = new DsRoutingException(
module + " is configured with multiple groups, But the keyword is null.");
dre.setModule(module);
throw dre;
}
}
protected List<RoutingGroup> getRoutingGroups(Module module){
RoutingConfigHolder holder = RoutingConfigHolder.getInstance();
return holder.getRoutingGroup(module);
}
/**
* 如果只有一个Group,则直接返回,
* 否则按照NumberRange区间与Keyword进行匹配,如果在属于Group的区间值则匹配成功
*
* @param groups
* @param keyword
* @return
*/
protected RoutingGroup findRoutingGroup(Module module, Long keyword){
List<RoutingGroup> groups = getRoutingGroups(module);
if(groups.size() == 1){
return groups.get(0);
}
// 多个Group,检查keyword
checkKeyword(module, keyword);
for (RoutingGroup group : groups) {
NumberRange range = group.getRange();
if(keyword >= range.getMin().longValue()
&& keyword <= range.getMax().longValue()){
return group;
}
}
return null;
}
}