/*
* Copyright (c) 2013, OpenCloudDB/MyCAT and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software;Designed and Developed mainly by many Chinese
* opensource volunteers. you can redistribute it and/or modify it under the
* terms of the GNU General Public License version 2 only, as published by the
* Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Any questions about this component can be directed to it's project Web address
* https://code.google.com/p/opencloudb/.
*
*/
package org.opencloudb.route.function;
import org.opencloudb.config.model.rule.RuleAlgorithm;
import org.opencloudb.parser.util.Pair;
import org.opencloudb.route.util.PartitionUtil;
import org.opencloudb.util.StringUtil;
/**
* @author <a href="mailto:daasadmin@hp.com">yangwenx</a>
*/
public final class PartitionByString extends AbstractPartionAlgorithm implements RuleAlgorithm {
private int hashSliceStart = 0;
/** 0 means str.length(), -1 means str.length()-1 */
private int hashSliceEnd = 8;
protected int[] count;
protected int[] length;
protected PartitionUtil partitionUtil;
public void setPartitionCount(String partitionCount) {
this.count = toIntArray(partitionCount);
}
public void setPartitionLength(String partitionLength) {
this.length = toIntArray(partitionLength);
}
public void setHashLength(int hashLength) {
setHashSlice(String.valueOf(hashLength));
}
public void setHashSlice(String hashSlice) {
Pair<Integer, Integer> p = sequenceSlicing(hashSlice);
hashSliceStart = p.getKey();
hashSliceEnd = p.getValue();
}
/**
* "2" -> (0,2)<br/>
* "1:2" -> (1,2)<br/>
* "1:" -> (1,0)<br/>
* "-1:" -> (-1,0)<br/>
* ":-1" -> (0,-1)<br/>
* ":" -> (0,0)<br/>
*/
public static Pair<Integer, Integer> sequenceSlicing(String slice) {
int ind = slice.indexOf(':');
if (ind < 0) {
int i = Integer.parseInt(slice.trim());
if (i >= 0) {
return new Pair<Integer, Integer>(0, i);
} else {
return new Pair<Integer, Integer>(i, 0);
}
}
String left = slice.substring(0, ind).trim();
String right = slice.substring(1 + ind).trim();
int start, end;
if (left.length() <= 0) {
start = 0;
} else {
start = Integer.parseInt(left);
}
if (right.length() <= 0) {
end = 0;
} else {
end = Integer.parseInt(right);
}
return new Pair<Integer, Integer>(start, end);
}
@Override
public void init() {
partitionUtil = new PartitionUtil(count,length);
}
private static int[] toIntArray(String string) {
String[] strs = org.opencloudb.util.SplitUtil.split(string, ',', true);
int[] ints = new int[strs.length];
for (int i = 0; i < strs.length; ++i) {
ints[i] = Integer.parseInt(strs[i]);
}
return ints;
}
@Override
public Integer calculate(String key) {
int start = hashSliceStart >= 0 ? hashSliceStart : key.length() + hashSliceStart;
int end = hashSliceEnd > 0 ? hashSliceEnd : key.length() + hashSliceEnd;
long hash = StringUtil.hash(key, start, end);
return partitionUtil.partition(hash);
}
}