diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/DefaultMemStore.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/DefaultMemStore.java index edc651131e8..299c9989b2f 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/DefaultMemStore.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/DefaultMemStore.java @@ -719,6 +719,8 @@ public class DefaultMemStore implements MemStore { // A flag represents whether could stop skipping Cells for MVCC // if have encountered the next row. Only used for reversed scan private boolean stopSkippingCellsIfNextRow = false; + // Stop skipping KeyValues for MVCC if finish this row. Only used for reversed scan + private Cell stopSkippingKVsRow; private final long readPoint; private final KeyValue.KVComparator comparator; @@ -765,7 +767,6 @@ public class DefaultMemStore implements MemStore { * @return Next Cell */ private Cell getNext(Iterator it) { - Cell startCell = theNext; Cell v = null; try { while (it.hasNext()) { @@ -773,8 +774,8 @@ public class DefaultMemStore implements MemStore { if (v.getSequenceId() <= this.readPoint) { return v; } - if (stopSkippingCellsIfNextRow && startCell != null - && comparator.compareRows(v, startCell) > 0) { + if (stopSkippingCellsIfNextRow && stopSkippingKVsRow != null + && comparator.compareRows(v, stopSkippingKVsRow) > 0) { return null; } } @@ -994,6 +995,7 @@ public class DefaultMemStore implements MemStore { Cell firstKeyOnPreviousRow = KeyValueUtil.createFirstOnRow(lastCellBeforeRow.getRowArray(), lastCellBeforeRow.getRowOffset(), lastCellBeforeRow.getRowLength()); this.stopSkippingCellsIfNextRow = true; + this.stopSkippingKVsRow = firstKeyOnPreviousRow; seek(firstKeyOnPreviousRow); this.stopSkippingCellsIfNextRow = false; if (peek() == null diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java index 48ee82545ca..0d2e35cacd3 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java @@ -6538,4 +6538,44 @@ public class TestHRegion { assertEquals("19995", Bytes.toString(currRow.get(1).getRowArray(), currRow.get(1).getRowOffset(), currRow.get(1).getRowLength())); } + + @Test + public void testReverseScanWhenPutCellsAfterOpenReverseScan() throws Exception { + byte[] cf1 = Bytes.toBytes("CF1"); + byte[][] families = { cf1 }; + byte[] col = Bytes.toBytes("C"); + + HBaseConfiguration conf = new HBaseConfiguration(); + this.region = initHRegion(tableName, method, conf, families); + + Put put = new Put(Bytes.toBytes("199996")); + put.addColumn(cf1, col, Bytes.toBytes("val")); + region.put(put); + Put put2 = new Put(Bytes.toBytes("199995")); + put2.addColumn(cf1, col, Bytes.toBytes("val")); + region.put(put2); + + // Create a reverse scan + Scan scan = new Scan(Bytes.toBytes("199996")); + scan.setReversed(true); + RegionScanner scanner = region.getScanner(scan); + + // Put a lot of cells that have sequenceIDs grater than the readPt of the reverse scan + for (int i = 100000; i < 200000; i++) { + Put p = new Put(Bytes.toBytes("" + i)); + p.addColumn(cf1, col, Bytes.toBytes("" + i)); + region.put(p); + } + List currRow = new ArrayList<>(); + boolean hasNext; + do { + hasNext = scanner.next(currRow); + } while (hasNext); + + assertEquals(2, currRow.size()); + assertEquals("199996", Bytes.toString(currRow.get(0).getRowArray(), + currRow.get(0).getRowOffset(), currRow.get(0).getRowLength())); + assertEquals("199995", Bytes.toString(currRow.get(1).getRowArray(), + currRow.get(1).getRowOffset(), currRow.get(1).getRowLength())); + } }