@Test public void testScanForwards() throws IOException { CellSearcher searcher = null; try { searcher = DecoderFactory.checkOut(block, true); int i = -1; while (searcher.advance()) { ++i; KeyValue inputCell = rows.getInputs().get(i); Cell outputCell = searcher.current(); // check all 3 permutations of equals() Assert.assertEquals(inputCell, outputCell); Assert.assertEquals(outputCell, inputCell); Assert.assertTrue(CellComparator.equals(inputCell, outputCell)); } Assert.assertEquals(rows.getInputs().size(), i + 1); } finally { DecoderFactory.checkIn(searcher); } }
@Test public void testScanBackwards() throws IOException { CellSearcher searcher = null; try { searcher = DecoderFactory.checkOut(block, true); searcher.positionAfterLastCell(); int i = -1; while (searcher.previous()) { ++i; int oppositeIndex = rows.getInputs().size() - i - 1; KeyValue inputKv = rows.getInputs().get(oppositeIndex); KeyValue outputKv = KeyValueUtil.copyToNewKeyValue(searcher.current()); Assert.assertEquals(inputKv, outputKv); } Assert.assertEquals(rows.getInputs().size(), i + 1); } finally { DecoderFactory.checkIn(searcher); } }
@Test public void testSeekWithPrefix() throws IOException { if (!(rows instanceof TestRowDataSearchWithPrefix)) { return; } CellSearcher searcher = null; try { searcher = DecoderFactory.checkOut(block, true); // seek with half bytes of second row key, should return second row KeyValue kv = rows.getInputs().get(1); KeyValue firstKVOnRow = KeyValueUtil.createFirstOnRow(Arrays.copyOfRange( kv.getRowArray(), kv.getRowOffset(), kv.getRowOffset() + kv.getRowLength() / 2)); CellScannerPosition position = searcher.positionAtOrAfter(firstKVOnRow); Assert.assertEquals(CellScannerPosition.AFTER, position); Assert.assertEquals(kv, searcher.current()); } finally { DecoderFactory.checkIn(searcher); } }
/** * I don't think this method is called during normal HBase operation, so efficiency is not * important. */ public ByteBuffer decodeKeyValues(DataInputStream source, int allocateHeaderLength, int skipLastBytes, HFileBlockDecodingContext decodingCtx) throws IOException { ByteBuffer sourceAsBuffer = ByteBufferUtils.drainInputStreamToBuffer(source);// waste sourceAsBuffer.mark(); PrefixTreeBlockMeta blockMeta = new PrefixTreeBlockMeta(sourceAsBuffer); sourceAsBuffer.rewind(); int numV1BytesWithHeader = allocateHeaderLength + blockMeta.getNumKeyValueBytes(); byte[] keyValueBytesWithHeader = new byte[numV1BytesWithHeader]; ByteBuffer result = ByteBuffer.wrap(keyValueBytesWithHeader); result.rewind(); CellSearcher searcher = null; try { boolean includesMvcc = decodingCtx.getHFileContext().isIncludesMvcc(); searcher = DecoderFactory.checkOut(sourceAsBuffer, includesMvcc); while (searcher.advance()) { KeyValue currentCell = KeyValueUtil.copyToNewKeyValue(searcher.current()); // needs to be modified for DirectByteBuffers. no existing methods to // write VLongs to byte[] int offset = result.arrayOffset() + result.position(); System.arraycopy(currentCell.getBuffer(), currentCell.getOffset(), result.array(), offset, currentCell.getLength()); int keyValueLength = KeyValueUtil.length(currentCell); ByteBufferUtils.skip(result, keyValueLength); offset += keyValueLength; if (includesMvcc) { ByteBufferUtils.writeVLong(result, currentCell.getMvccVersion()); } } result.position(result.limit());//make it appear as if we were appending return result; } finally { DecoderFactory.checkIn(searcher); } }
@Override public ByteBuffer getFirstKeyInBlock(ByteBuffer block) { block.rewind(); PrefixTreeArraySearcher searcher = null; try { // should i includeMemstoreTS (second argument)? i think PrefixKeyDeltaEncoder is, so i will searcher = DecoderFactory.checkOut(block, true); if (!searcher.positionAtFirstCell()) { return null; } return KeyValueUtil.copyKeyToNewByteBuffer(searcher.current()); } finally { DecoderFactory.checkIn(searcher); } }
@Test public void testRandomSeekHits() throws IOException { CellSearcher searcher = null; try { searcher = DecoderFactory.checkOut(block, true); for (KeyValue kv : rows.getInputs()) { boolean hit = searcher.positionAt(kv); Assert.assertTrue(hit); Cell foundKv = searcher.current(); Assert.assertTrue(CellComparator.equals(kv, foundKv)); } } finally { DecoderFactory.checkIn(searcher); } }
@Test public void testRandomSeekIndividualAssertions() throws IOException { CellSearcher searcher = null; try { searcher = DecoderFactory.checkOut(block, true); rows.individualSearcherAssertions(searcher); } finally { DecoderFactory.checkIn(searcher); } }
/** * I don't think this method is called during normal HBase operation, so efficiency is not * important. */ @Override public ByteBuffer decodeKeyValues(DataInputStream source, int allocateHeaderLength, int skipLastBytes, boolean includesMvccVersion) throws IOException { ByteBuffer sourceAsBuffer = ByteBufferUtils.drainInputStreamToBuffer(source);// waste sourceAsBuffer.mark(); PrefixTreeBlockMeta blockMeta = new PrefixTreeBlockMeta(sourceAsBuffer); sourceAsBuffer.rewind(); int numV1BytesWithHeader = allocateHeaderLength + blockMeta.getNumKeyValueBytes(); byte[] keyValueBytesWithHeader = new byte[numV1BytesWithHeader]; ByteBuffer result = ByteBuffer.wrap(keyValueBytesWithHeader); result.rewind(); CellSearcher searcher = null; try { searcher = DecoderFactory.checkOut(sourceAsBuffer, includesMvccVersion); while (searcher.advance()) { KeyValue currentCell = KeyValueUtil.copyToNewKeyValue(searcher.current()); // needs to be modified for DirectByteBuffers. no existing methods to // write VLongs to byte[] int offset = result.arrayOffset() + result.position(); KeyValueUtil.appendToByteArray(currentCell, result.array(), offset); int keyValueLength = KeyValueUtil.length(currentCell); ByteBufferUtils.skip(result, keyValueLength); offset += keyValueLength; if (includesMvccVersion) { ByteBufferUtils.writeVLong(result, currentCell.getMvccVersion()); } } result.position(result.limit());//make it appear as if we were appending return result; } finally { DecoderFactory.checkIn(searcher); } }
@Override public ByteBuffer getFirstKeyInBlock(ByteBuffer block) { block.rewind(); PrefixTreeArraySearcher searcher = null; try { //should i includeMemstoreTS (second argument)? i think PrefixKeyDeltaEncoder is, so i will searcher = DecoderFactory.checkOut(block, true); if (!searcher.positionAtFirstCell()) { return null; } return KeyValueUtil.copyKeyToNewByteBuffer(searcher.current()); } finally { DecoderFactory.checkIn(searcher); } }
@Override public void setCurrentBuffer(ByteBuffer fullBlockBuffer) { block = fullBlockBuffer; ptSearcher = DecoderFactory.checkOut(block, includeMvccVersion); rewind(); }
@Test public void testRandomSeekMisses() throws IOException { CellSearcher searcher = null; List<Integer> rowStartIndexes = rows.getRowStartIndexes(); try { searcher = DecoderFactory.checkOut(block, true); //test both the positionAtOrBefore and positionAtOrAfter methods for(boolean beforeVsAfterOnMiss : new boolean[]{true, false}){ for (int i=0; i < rows.getInputs().size(); ++i) { KeyValue kv = rows.getInputs().get(i); //nextRow KeyValue inputNextRow = KeyValueUtil.createFirstKeyInNextRow(kv); CellScannerPosition position = beforeVsAfterOnMiss ? searcher.positionAtOrBefore(inputNextRow) : searcher.positionAtOrAfter(inputNextRow); boolean isFirstInRow = rowStartIndexes.contains(i); if(isFirstInRow){ int rowIndex = rowStartIndexes.indexOf(i); if(rowIndex < rowStartIndexes.size() - 1){ if(beforeVsAfterOnMiss){ Assert.assertEquals(CellScannerPosition.BEFORE, position); }else{ Assert.assertEquals(CellScannerPosition.AFTER, position); } int expectedInputIndex = beforeVsAfterOnMiss ? rowStartIndexes.get(rowIndex + 1) - 1 : rowStartIndexes.get(rowIndex + 1); Assert.assertEquals(rows.getInputs().get(expectedInputIndex), searcher.current()); } } //previous KV KeyValue inputPreviousKv = KeyValueUtil.previousKey(kv); boolean hit = searcher.positionAt(inputPreviousKv); Assert.assertFalse(hit); position = searcher.positionAtOrAfter(inputPreviousKv); if(CollectionUtils.isLastIndex(rows.getInputs(), i)){ Assert.assertTrue(CellScannerPosition.AFTER_LAST == position); }else{ Assert.assertTrue(CellScannerPosition.AFTER == position); /* * TODO: why i+1 instead of i? */ Assert.assertEquals(rows.getInputs().get(i+1), searcher.current()); } } } } finally { DecoderFactory.checkIn(searcher); } }