package voldemort.store.readonly;
import java.nio.ByteBuffer;
import voldemort.utils.ByteUtils;
/**
* A search strategy that uses interpolation to jump to approximately the
* correct location in the index with as few comparisons as possible. This
* strategy depends entirely on the uniform distribution of the keys that is
* guaranteed by the md5 hash.
*
*
*/
public class InterpolationSearchStrategy implements SearchStrategy {
public int indexOf(ByteBuffer index, byte[] key, int indexFileSize) {
int guess;
int lowIdx = 0;
int indexSize = ReadOnlyUtils.POSITION_SIZE + key.length;
int highIdx = indexFileSize / indexSize - 1;
long lastIdx = highIdx;
long lowValue = 0;
long highValue = 0xFFFFFFFFL;
long keyInt = ByteUtils.readUnsignedInt(key, 0);
byte[] found = new byte[key.length];
while(true) {
if(lowIdx > highIdx || keyInt < lowValue || keyInt > highValue)
return -1;
if(highIdx == lowIdx) {
guess = highIdx;
} else {
long size = highIdx - lowIdx;
long offset = (size - 1) * (keyInt - lowValue) / (highValue - lowValue);
guess = lowIdx + (int) offset;
}
index.position(guess * indexSize);
index.get(found);
int compare = ByteUtils.compare(key, found);
// did we find it?
if(compare == 0)
return index.getInt();
// okay we didn't find it this time, update the min and max
long foundInt = ByteUtils.readUnsignedInt(found, 0);
if(compare == -1) {
// key is less than found
if(guess == 0)
return -1;
highIdx = guess - 1;
highValue = foundInt;
} else {
// key is greater than found
if(guess == lastIdx)
return -1;
lowIdx = guess + 1;
lowValue = foundInt;
}
}
}
}