package com.taobao.tddl.rule.virtualnode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Maps;
/**
* 构造table的一致性hash的slot
*
* @author <a href="junyu@taobao.com">junyu</a>
* @version 1.0
* @since 1.6
* @date 2011-6-2 03:13:08
*/
public class TableSlotMap extends WrappedLogic implements VirtualNodeMap {
private String logicTable;
protected Map<String/* slot number */, String/* table suffix */> tableContext = Maps.newConcurrentMap();
private Map<String/* table suffix */, String/* slot string */> tableSlotMap = Maps.newHashMap();
private PartitionFunction keyPartitionFunction;
private PartitionFunction valuePartitionFunction;
public void init() {
this.initTableSlotMap(tableSlotMap);
if (null != tableSlotMap && tableSlotMap.size() > 0) {
tableContext = extraReverseMap(tableSlotMap);
} else {
throw new IllegalArgumentException("no tableSlotMap config at all");
}
}
private void initTableSlotMap(Map<String, String> tableSlotMap) {
if (this.keyPartitionFunction == null || this.valuePartitionFunction == null) {
return;
}
List<String> keys = this.buildTableSlotMapKeys();
List<String> values = this.buildTableSlotMapValues();
for (int i = 0; i < keys.size(); i++) {
tableSlotMap.put(keys.get(i), values.get(i));
}
}
public String getValue(String key) {
String suffix = tableContext.get(key);
// TODO 增加虚拟节点使用统计
// TotalStatMonitor.virtualSlotIncrement(buildLogKey(key));
if (super.tableSlotKeyFormat != null) {
return super.wrapValue(suffix);
} else if (logicTable != null) {
StringBuilder sb = new StringBuilder();
sb.append(logicTable);
sb.append(tableSplitor);
sb.append(suffix);
return sb.toString();
} else {
// throw new
// RuntimeException("TableRule no tableSlotKeyFormat property and logicTable is null");
return suffix;
}
}
// ======================== helper method ======================
private List<String> buildTableSlotMapKeys() {
List<String> result = new ArrayList<String>();
int[] partitionCount = this.keyPartitionFunction.getCount();
int[] partitionLength = this.keyPartitionFunction.getLength();
int firstValue = this.keyPartitionFunction.getFirstValue();
for (int i = 0; i < partitionCount.length; i++) {
for (int j = 0; j < partitionCount[i]; j++) {
int key = firstValue + partitionLength[i];
firstValue = key;
result.add(String.valueOf(key));
}
}
return result;
}
private List<String> buildTableSlotMapValues() {
List<String> result = new ArrayList<String>();
int[] partitionCount = this.valuePartitionFunction.getCount();
int[] partitionLength = this.valuePartitionFunction.getLength();
int firstValue = this.valuePartitionFunction.getFirstValue();
for (int i = 0; i < partitionCount.length; i++) {
for (int j = 0; j < partitionCount[i]; j++) {
int startValue = firstValue;
int endValue = startValue + partitionLength[i] - 1;
firstValue += partitionLength[i];
result.add(String.valueOf(startValue) + "-" + String.valueOf(endValue));
}
}
return result;
}
public String buildLogKey(String key) {
if (logicTable != null) {
StringBuilder sb = new StringBuilder(logicTable);
sb.append("_slot_");
sb.append(key);
return sb.toString();
} else {
throw new RuntimeException("TableRule no logicTable at all,can not happen!!");
}
}
// ===================== setter / getter ====================
public void setTableSlotMap(Map<String, String> tableSlotMap) {
this.tableSlotMap = tableSlotMap;
}
public void setLogicTable(String logicTable) {
this.logicTable = logicTable;
}
public void setKeyPartitionFunction(PartitionFunction keyPartitionFunction) {
this.keyPartitionFunction = keyPartitionFunction;
}
public void setValuePartitionFunction(PartitionFunction valuePartitionFunction) {
this.valuePartitionFunction = valuePartitionFunction;
}
}