
org.apache.solr.common.cloud.HashPartitioner Maven / Gradle / Ivy
package org.apache.solr.common.cloud;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.noggit.JSONWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Class to partition int range into n ranges.
*
*/
public class HashPartitioner {
// Hash ranges can't currently "wrap" - i.e. max must be greater or equal to min.
// TODO: ranges may not be all contiguous in the future (either that or we will
// need an extra class to model a collection of ranges)
public static class Range implements JSONWriter.Writable {
public int min; // inclusive
public int max; // inclusive
public Range(int min, int max) {
assert min <= max;
this.min = min;
this.max = max;
}
public boolean includes(int hash) {
return hash >= min && hash <= max;
}
public String toString() {
return Integer.toHexString(min) + '-' + Integer.toHexString(max);
}
@Override
public int hashCode() {
// difficult numbers to hash... only the highest bits will tend to differ.
// ranges will only overlap during a split, so we can just hash the lower range.
return (min>>28) + (min>>25) + (min>>21) + min;
}
@Override
public boolean equals(Object obj) {
if (obj.getClass() != getClass()) return false;
Range other = (Range)obj;
return this.min == other.min && this.max == other.max;
}
@Override
public void write(JSONWriter writer) {
writer.write(toString());
}
}
public Range fromString(String range) {
int middle = range.indexOf('-');
String minS = range.substring(0, middle);
String maxS = range.substring(middle+1);
long min = Long.parseLong(minS, 16); // use long to prevent the parsing routines from potentially worrying about overflow
long max = Long.parseLong(maxS, 16);
return new Range((int)min, (int)max);
}
public Range fullRange() {
return new Range(Integer.MIN_VALUE, Integer.MAX_VALUE);
}
public List partitionRange(int partitions, Range range) {
return partitionRange(partitions, range.min, range.max);
}
/**
* Returns the range for each partition
*/
public List partitionRange(int partitions, int min, int max) {
assert max >= min;
if (partitions == 0) return Collections.EMPTY_LIST;
long range = (long)max - (long)min;
long srange = Math.max(1, range / partitions);
List ranges = new ArrayList(partitions);
long start = min;
long end = start;
while (end < max) {
end = start + srange;
// make last range always end exactly on MAX_VALUE
if (ranges.size() == partitions - 1) {
end = max;
}
ranges.add(new Range((int)start, (int)end));
start = end + 1L;
}
return ranges;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy