/** * @param searcherIsAfterInputKey <0: input key is before the searcher's position<br> * >0: input key is after the searcher's position */ protected CellScannerPosition fixRowTokenMissReverse(int searcherIsAfterInputKey) { if (searcherIsAfterInputKey < 0) {//searcher position is after the input key, so back up boolean foundPreviousRow = previousRow(true); if(foundPreviousRow){ populateLastNonRowFields(); return CellScannerPosition.BEFORE; }else{ return CellScannerPosition.BEFORE_FIRST; } }else{//searcher position is before the input key if(currentRowNode.hasOccurrences()){ populateFirstNonRowFields(); return CellScannerPosition.BEFORE; } boolean foundNextRow = nextRow(); if(foundNextRow){ return CellScannerPosition.AFTER; }else{ return CellScannerPosition.AFTER_LAST; } } }
/****************** complete seek when fan mismatch ******************/ protected CellScannerPosition fixRowFanMissReverse(int fanInsertionPoint){ if(fanInsertionPoint == 0){//we need to back up a row if (currentRowNode.hasOccurrences()) { populateLastNonRowFields(); return CellScannerPosition.BEFORE; } boolean foundPreviousRow = previousRow(true);//true -> position on last cell in row if(foundPreviousRow){ populateLastNonRowFields(); return CellScannerPosition.BEFORE; } return CellScannerPosition.BEFORE_FIRST; } //follow the previous fan, but then descend recursively forward followFan(fanInsertionPoint - 1); followLastFansUntilExhausted(); populateLastNonRowFields(); return CellScannerPosition.BEFORE; }
protected CellScannerPosition fixRowFanMissForward(int fanInsertionPoint){ if(fanInsertionPoint >= currentRowNode.getFanOut()){ discardCurrentRowNode(true); if (!nextRow()) { return CellScannerPosition.AFTER_LAST; } else { return CellScannerPosition.AFTER; } } followFan(fanInsertionPoint); if(hasOccurrences()){ populateFirstNonRowFields(); return CellScannerPosition.AFTER; } if(nextRowInternal()){ populateFirstNonRowFields(); return CellScannerPosition.AFTER; }else{ return CellScannerPosition.AFTER_LAST; } }
@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); } }
private void testBetween1and2(CellSearcher searcher){ CellScannerPosition p;//reuse Cell betweenAAndAAA = new KeyValue(AA, cf, cq, ts-2, v); //test exact Assert.assertFalse(searcher.positionAt(betweenAAndAAA)); //test atOrBefore p = searcher.positionAtOrBefore(betweenAAndAAA); Assert.assertEquals(CellScannerPosition.BEFORE, p); Assert.assertTrue(CellComparator.equals(searcher.current(), d.get(1))); //test atOrAfter p = searcher.positionAtOrAfter(betweenAAndAAA); Assert.assertEquals(CellScannerPosition.AFTER, p); Assert.assertTrue(CellComparator.equals(searcher.current(), d.get(2))); }
private void testBetween2and3(CellSearcher searcher){ CellScannerPosition p;//reuse Cell betweenAAAndB = new KeyValue(AAA, cf, cq, ts-2, v); //test exact Assert.assertFalse(searcher.positionAt(betweenAAAndB)); //test atOrBefore p = searcher.positionAtOrBefore(betweenAAAndB); Assert.assertEquals(CellScannerPosition.BEFORE, p); Assert.assertTrue(CellComparator.equals(searcher.current(), d.get(2))); //test atOrAfter p = searcher.positionAtOrAfter(betweenAAAndB); Assert.assertEquals(CellScannerPosition.AFTER, p); Assert.assertTrue(CellComparator.equals(searcher.current(), d.get(3))); }
/** * @param searcherIsAfterInputKey <0: input key is before the searcher's position<br/> * >0: input key is after the searcher's position */ protected CellScannerPosition fixRowTokenMissReverse(int searcherIsAfterInputKey) { if (searcherIsAfterInputKey < 0) {//searcher position is after the input key, so back up boolean foundPreviousRow = previousRow(true); if(foundPreviousRow){ populateLastNonRowFields(); return CellScannerPosition.BEFORE; }else{ return CellScannerPosition.BEFORE_FIRST; } }else{//searcher position is before the input key if(currentRowNode.hasOccurrences()){ populateFirstNonRowFields(); return CellScannerPosition.BEFORE; } boolean foundNextRow = nextRow(); if(foundNextRow){ return CellScannerPosition.AFTER; }else{ return CellScannerPosition.AFTER_LAST; } } }
/****************** complete seek when fan mismatch ******************/ protected CellScannerPosition fixRowFanMissReverse(int fanInsertionPoint){ if(fanInsertionPoint == 0){//we need to back up a row boolean foundPreviousRow = previousRow(true);//true -> position on last cell in row if(foundPreviousRow){ populateLastNonRowFields(); return CellScannerPosition.BEFORE; } return CellScannerPosition.BEFORE_FIRST; } //follow the previous fan, but then descend recursively forward followFan(fanInsertionPoint - 1); followLastFansUntilExhausted(); populateLastNonRowFields(); return CellScannerPosition.BEFORE; }
protected int seekToOrBeforeUsingPositionAtOrBefore(byte[] keyOnlyBytes, int offset, int length, boolean seekBefore){ // this does a deep copy of the key byte[] because the CellSearcher interface wants a Cell KeyValue kv = KeyValue.createKeyValueFromKey(keyOnlyBytes, offset, length); CellScannerPosition position = ptSearcher.seekForwardToOrBefore(kv); if(CellScannerPosition.AT == position){ if (seekBefore) { ptSearcher.previous(); return 1; } return 0; } return 1; }
@Override public CellScannerPosition positionAtOrBefore(Cell key) { reInitFirstNode(); int fanIndex = -1; while(true){ //detect row mismatch. break loop if mismatch int currentNodeDepth = rowLength; int rowTokenComparison = compareToCurrentToken(key); if(rowTokenComparison != 0){ return fixRowTokenMissReverse(rowTokenComparison); } //exact row found, move on to qualifier & ts if(rowMatchesAfterCurrentPosition(key)){ return positionAtQualifierTimestamp(key, true); } //detect dead end (no fan to descend into) if(!currentRowNode.hasFan()){ if(hasOccurrences()){//must be leaf or nub populateLastNonRowFields(); return CellScannerPosition.BEFORE; }else{ //TODO i don't think this case is exercised by any tests return fixRowFanMissReverse(0); } } //keep hunting for the rest of the row byte searchForByte = CellUtil.getRowByte(key, currentNodeDepth); fanIndex = currentRowNode.whichFanNode(searchForByte); if(fanIndex < 0){//no matching row. return early int insertionPoint = -fanIndex - 1; return fixRowFanMissReverse(insertionPoint); } //found a match, so dig deeper into the tree followFan(fanIndex); } }
@Override public CellScannerPosition seekForwardToOrBefore(Cell key) { //Do we even need this check or should upper layers avoid this situation. It's relatively //expensive compared to the rest of the seek operation. if(currentPositionIsAfter(key)){ //our position is after the requested key, so can't do anything return CellScannerPosition.AFTER; } return positionAtOrBefore(key); }
@Override public CellScannerPosition seekForwardToOrAfter(Cell key) { //Do we even need this check or should upper layers avoid this situation. It's relatively //expensive compared to the rest of the seek operation. if(currentPositionIsAfter(key)){ //our position is after the requested key, so can't do anything return CellScannerPosition.AFTER; } return positionAtOrAfter(key); }
protected int seekToOrBeforeUsingPositionAtOrBefore(Cell kv, boolean seekBefore) { // this does a deep copy of the key byte[] because the CellSearcher // interface wants a Cell CellScannerPosition position = ptSearcher.seekForwardToOrBefore(kv); if (CellScannerPosition.AT == position) { if (seekBefore) { ptSearcher.previous(); return 1; } return 0; } return 1; }
protected int seekToOrBeforeUsingPositionAtOrAfter(Cell kv, boolean seekBefore) { // should probably switch this to use the seekForwardToOrBefore method CellScannerPosition position = ptSearcher.seekForwardToOrAfter(kv); if (CellScannerPosition.AT == position) { if (seekBefore) { ptSearcher.previous(); return 1; } return 0; } if (CellScannerPosition.AFTER == position) { if (!ptSearcher.isBeforeFirst()) { ptSearcher.previous(); } return 1; } if (position == CellScannerPosition.AFTER_LAST) { if (seekBefore) { ptSearcher.previous(); } return 1; } throw new RuntimeException("unexpected CellScannerPosition:" + position); }
@Override public void individualSearcherAssertions(CellSearcher searcher) { /** * The searcher should get a token mismatch on the "r" branch. Assert that it skips not only rA, * but rB as well. */ KeyValue afterLast = KeyValueUtil.createFirstOnRow(Bytes.toBytes("zzz")); CellScannerPosition position = searcher.positionAtOrAfter(afterLast); Assert.assertEquals(CellScannerPosition.AFTER_LAST, position); Assert.assertNull(searcher.current()); }
@Override public void individualSearcherAssertions(CellSearcher searcher) { /** * The searcher should get a token mismatch on the "r" branch. Assert that it skips not only * rA, but rB as well. */ KeyValue cfcRow = KeyValueUtil.createFirstOnRow(Bytes.toBytes("cfc")); CellScannerPosition position = searcher.positionAtOrAfter(cfcRow); Assert.assertEquals(CellScannerPosition.AFTER, position); Assert.assertEquals(d.get(2), searcher.current()); searcher.previous(); Assert.assertEquals(d.get(1), searcher.current()); }
@Override public void individualSearcherAssertions(CellSearcher searcher) { /** * The searcher should get a token mismatch on the "r" branch. Assert that * it skips not only rA, but rB as well. */ KeyValue afterLast = KeyValueUtil.createFirstOnRow(Bytes.toBytes("zzz")); CellScannerPosition position = searcher.positionAtOrAfter(afterLast); Assert.assertEquals(CellScannerPosition.AFTER_LAST, position); Assert.assertNull(searcher.current()); }