private void moveToPrevious() { if (!previous.isValid()) { throw new IllegalStateException( "Can move back only once and not in first key in the block."); } STATE tmp = previous; previous = current; current = tmp; // move after last key value currentBuffer.position(current.nextKvOffset); // Already decoded the tag bytes. We cache this tags into current state and also the total // compressed length of the tags bytes. For the next time decodeNext() we don't need to decode // the tags again. This might pollute the Data Dictionary what we use for the compression. // When current.uncompressTags is false, we will just reuse the current.tagsBuffer and skip // 'tagsCompressedLength' bytes of source stream. // See in decodeTags() current.tagsBuffer = previous.tagsBuffer; current.tagsCompressedLength = previous.tagsCompressedLength; current.uncompressTags = false; // The current key has to be reset with the previous Cell current.setKey(current.keyBuffer, current.memstoreTS); previous.invalidate(); }
@Override public boolean next() { if (!currentBuffer.hasRemaining()) { return false; } decodeNext(); current.setKey(current.keyBuffer, current.memstoreTS); previous.invalidate(); return true; }
@Override public void rewind() { currentBuffer.rewind(); if (tagCompressionContext != null) { tagCompressionContext.clear(); } decodeFirst(); current.setKey(current.keyBuffer, current.memstoreTS); previous.invalidate(); }
@Override public void setCurrentBuffer(ByteBuff buffer) { if (this.tagCompressionContext != null) { this.tagCompressionContext.clear(); } currentBuffer = buffer; current.currentBuffer = currentBuffer; if (tagCompressionContext != null) { current.tagCompressionContext = tagCompressionContext; } decodeFirst(); current.setKey(current.keyBuffer, current.memstoreTS); previous.invalidate(); }
@Override public int seekToKeyInBlock(Cell seekCell, boolean seekBefore) { int rowCommonPrefix = 0; int familyCommonPrefix = 0; int qualCommonPrefix = 0; previous.invalidate(); do { int comp; keyOnlyKV.setKey(current.keyBuffer, 0, current.keyLength); if (current.lastCommonPrefix != 0) { // The KV format has row key length also in the byte array. The // common prefix // includes it. So we need to subtract to find out the common prefix // in the // row part alone rowCommonPrefix = Math.min(rowCommonPrefix, current.lastCommonPrefix - 2); } if (current.lastCommonPrefix <= 2) { rowCommonPrefix = 0; } rowCommonPrefix += findCommonPrefixInRowPart(seekCell, keyOnlyKV, rowCommonPrefix); comp = compareCommonRowPrefix(seekCell, keyOnlyKV, rowCommonPrefix); if (comp == 0) { comp = compareTypeBytes(seekCell, keyOnlyKV); if (comp == 0) { // Subtract the fixed row key length and the family key fixed length familyCommonPrefix = Math.max( 0, Math.min( familyCommonPrefix, current.lastCommonPrefix - (3 + keyOnlyKV.getRowLength()))); familyCommonPrefix += findCommonPrefixInFamilyPart(seekCell, keyOnlyKV, familyCommonPrefix); comp = compareCommonFamilyPrefix(seekCell, keyOnlyKV, familyCommonPrefix); if (comp == 0) { // subtract the rowkey fixed length and the family key fixed // length qualCommonPrefix = Math.max( 0, Math.min( qualCommonPrefix, current.lastCommonPrefix - (3 + keyOnlyKV.getRowLength() + keyOnlyKV.getFamilyLength()))); qualCommonPrefix += findCommonPrefixInQualifierPart(seekCell, keyOnlyKV, qualCommonPrefix); comp = compareCommonQualifierPrefix(seekCell, keyOnlyKV, qualCommonPrefix); if (comp == 0) { comp = CellComparator.compareTimestamps(seekCell, keyOnlyKV); if (comp == 0) { // Compare types. Let the delete types sort ahead of puts; // i.e. types // of higher numbers sort before those of lesser numbers. // Maximum // (255) // appears ahead of everything, and minimum (0) appears // after // everything. comp = (0xff & keyOnlyKV.getTypeByte()) - (0xff & seekCell.getTypeByte()); } } } } } if (comp == 0) { // exact match if (seekBefore) { if (!previous.isValid()) { // The caller (seekBefore) has to ensure that we are not at the // first key in the block. throw new IllegalStateException( "Cannot seekBefore if " + "positioned at the first key in the block: key=" + Bytes.toStringBinary(seekCell.getRowArray())); } moveToPrevious(); return 1; } return 0; } if (comp < 0) { // already too large, check previous if (previous.isValid()) { moveToPrevious(); } else { return HConstants.INDEX_KEY_MAGIC; // using optimized index key } return 1; } // move to next, if more data is available if (currentBuffer.hasRemaining()) { previous.copyFromNext(current); decodeNext(); current.setKey(current.keyBuffer, current.memstoreTS); } else { break; } } while (true); // we hit the end of the block, not an exact match return 1; }