From 7d9e970e348b37e2a9902a2e738026e643700988 Mon Sep 17 00:00:00 2001 From: Toshihiro Suzuki Date: Fri, 28 Sep 2018 01:29:07 +0900 Subject: [PATCH] HBASE-21200 Memstore flush doesn't finish because of seekToPreviousRow() in memstore scanner. --- .../hadoop/hbase/regionserver/SegmentScanner.java | 21 ++++++++++++ .../hadoop/hbase/regionserver/TestHRegion.java | 40 ++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/SegmentScanner.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/SegmentScanner.java index 8a867b6..8a90685 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/SegmentScanner.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/SegmentScanner.java @@ -202,6 +202,27 @@ public class SegmentScanner implements KeyValueScanner { return false; } Cell firstKeyOnPreviousRow = PrivateCellUtil.createFirstOnRow(lastCellBeforeRow); + + // Optimization: We can skip seeking when the sequenceId of the cells whose row is equal + // to firstKeyOnPreviousRow is grater than readPoint. + boolean skipSeeking = true; + Iterator iterator = getIterator(firstKeyOnPreviousRow); + while (iterator.hasNext()) { + Cell next = iterator.next(); + if (segment.compareRows(next, firstKeyOnPreviousRow) > 0) { + break; + } + if (next.getSequenceId() <= this.readPoint) { + skipSeeking = false; + break; + } + } + if (skipSeeking) { + keepSeeking = true; + key = firstKeyOnPreviousRow; + continue; + } + this.stopSkippingKVsIfNextRow = true; seek(firstKeyOnPreviousRow); this.stopSkippingKVsIfNextRow = false; 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 fcaad62..b2d9a1b 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 @@ -5534,6 +5534,46 @@ public class TestHRegion { } @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); + RegionScannerImpl 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())); + } + + @Test public void testWriteRequestsCounter() throws IOException { byte[] fam = Bytes.toBytes("info"); byte[][] families = { fam }; -- 2.10.1 (Apple Git-78)