in core/src/main/java/org/apache/accumulo/core/file/rfile/RFile.java [948:1107]
private void _seek(Range range) throws IOException {
this.range = range;
this.checkRange = true;
if (blockCount == 0) {
// its an empty file
rk = null;
return;
}
Key startKey = range.getStartKey();
if (startKey == null) {
startKey = new Key();
}
boolean reseek = true;
if (range.afterEndKey(firstKey)) {
// range is before first key in rfile, so there is nothing to do
reset(false);
reseek = false;
}
if (rk != null) {
if (range.beforeStartKey(prevKey) && range.afterEndKey(getTopKey())) {
// range is between the two keys in the file where the last range seeked to stopped, so
// there is
// nothing to do
reseek = false;
}
if (startKey.compareTo(getTopKey()) <= 0 && startKey.compareTo(prevKey) > 0) {
// current location in file can satisfy this request, no need to seek
reseek = false;
}
if (entriesLeft > 0 && startKey.compareTo(getTopKey()) >= 0
&& startKey.compareTo(iiter.peekPrevious().getKey()) <= 0) {
// start key is within the unconsumed portion of the current block
// this code intentionally does not use the index associated with a cached block
// because if only forward seeks are being done, then there is no benefit to building
// and index for the block... could consider using the index if it exist but not
// causing the build of an index... doing this could slow down some use cases and
// and speed up others.
final var valbs = new ArrayByteSequence(new byte[64], 0, 0);
SkippR skippr =
RelativeKey.fastSkip(currBlock, startKey, valbs, prevKey, getTopKey(), entriesLeft);
if (skippr.skipped > 0) {
entriesLeft -= skippr.skipped;
val = new Value(valbs.toArray());
prevKey = skippr.prevKey;
rk = skippr.rk;
}
reseek = false;
}
if (entriesLeft == 0 && startKey.compareTo(getTopKey()) > 0
&& startKey.compareTo(iiter.peekPrevious().getKey()) <= 0) {
// In the empty space at the end of a block. This can occur when keys are shortened in the
// index creating index entries that do not exist in the
// block. These shortened index entries fall between the last key in a block and first key
// in the next block, but may not exist in the data.
// Just proceed to the next block.
reseek = false;
}
if (iiter.previousIndex() == 0 && getTopKey().equals(firstKey)
&& startKey.compareTo(firstKey) <= 0) {
// seeking before the beginning of the file, and already positioned at the first key in
// the file
// so there is nothing to do
reseek = false;
}
}
if (reseek) {
iiter = index.lookup(startKey);
reset(false);
if (iiter.hasNext()) {
// if the index contains the same key multiple times, then go to the
// earliest index entry containing the key
while (iiter.hasPrevious()
&& iiter.peekPrevious().getKey().equals(iiter.peek().getKey())) {
iiter.previous();
}
if (iiter.hasPrevious()) {
prevKey = new Key(iiter.peekPrevious().getKey()); // initially prevKey is the last key
// of the prev block
} else {
prevKey = new Key(); // first block in the file, so set prev key to minimal key
}
IndexEntry indexEntry = iiter.next();
entriesLeft = indexEntry.getNumEntries();
currBlock = getDataBlock(indexEntry);
checkRange = range.afterEndKey(indexEntry.getKey());
if (!checkRange) {
hasTop = true;
}
final var valbs = new ArrayByteSequence(new byte[64], 0, 0);
Key currKey = null;
if (currBlock.isIndexable()) {
BlockIndex blockIndex = BlockIndex.getIndex(currBlock, indexEntry);
if (blockIndex != null) {
BlockIndexEntry bie = blockIndex.seekBlock(startKey, currBlock);
if (bie != null) {
// we are seeked to the current position of the key in the index
// need to prime the read process and read this key from the block
RelativeKey tmpRk = new RelativeKey();
tmpRk.setPrevKey(bie.getPrevKey());
tmpRk.readFields(currBlock);
val = new Value();
val.readFields(currBlock);
valbs.reset(val.get(), 0, val.getSize());
// just consumed one key from the input stream, so subtract one from entries left
entriesLeft = bie.getEntriesLeft() - 1;
prevKey = new Key(bie.getPrevKey());
currKey = tmpRk.getKey();
}
}
}
SkippR skippr =
RelativeKey.fastSkip(currBlock, startKey, valbs, prevKey, currKey, entriesLeft);
prevKey = skippr.prevKey;
entriesLeft -= skippr.skipped;
val = new Value(valbs.toArray());
// set rk when everything above is successful, if exception
// occurs rk will not be set
rk = skippr.rk;
} else {
// past the last key
}
}
hasTop = rk != null && !range.afterEndKey(rk.getKey());
while (hasTop() && range.beforeStartKey(getTopKey())) {
next();
}
if (metricsGatherer != null) {
metricsGatherer.startLocalityGroup(rk.getKey().getColumnFamily());
metricsGatherer.addMetric(rk.getKey(), val);
}
}