diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java index 34a37f1..f68350d 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java @@ -340,6 +340,11 @@ private final AtomicInteger majorInProgress = new AtomicInteger(0); private final AtomicInteger minorInProgress = new AtomicInteger(0); + /** + * use only for test to create dirty HRegion. + */ + private boolean skipRowChecking = false; + // // Context: During replay we want to ensure that we do not lose any data. So, we // have to be conservative in how we replay wals. For each store, we calculate @@ -361,6 +366,14 @@ private volatile Optional configurationManager; + /** + * set this flag to true,then the put/delete operation will skip row range check and used for test only. + * @param skipRowChecking true:skip row checking false:default not + */ + public void setSkipRowChecking(boolean skipRowChecking) { + this.skipRowChecking = skipRowChecking; + } + /** * @return The smallest mvcc readPoint across all the scanners in this * region. Writes older than this readPoint, are included in every @@ -5567,8 +5580,22 @@ defaultScannerContext = ScannerContext.newBuilder() .setBatchLimit(scan.getBatch()).build(); - if (Bytes.equals(scan.getStopRow(), HConstants.EMPTY_END_ROW) && !scan.isGetScan()) { - this.stopRow = null; + // To resolve HBASE-15097,we should set the 'stopRow' exactly for the current region scan. + if (!scan.isReversed()) { + if (Bytes.equals(this.region.getRegionInfo().getEndKey(), HConstants.EMPTY_END_ROW)) { + if (Bytes.equals(scan.getStopRow(), HConstants.EMPTY_END_ROW)) { + this.stopRow = null; + } else { + this.stopRow = scan.getStopRow(); + } + } else { + if (Bytes.equals(scan.getStopRow(), HConstants.EMPTY_END_ROW) + || Bytes.compareTo(scan.getStopRow(), this.getRegionInfo().getEndKey()) >= 0) { + this.stopRow = this.region.getRegionInfo().getEndKey(); + } else { + this.stopRow = scan.getStopRow(); + } + } } else { this.stopRow = scan.getStopRow(); } 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 cef92a6..04f4ba8 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 @@ -3184,6 +3184,88 @@ } @Test + public void testScanner_StopRow() throws IOException { + InternalScanner s = null; + + byte[] row1 = Bytes.toBytes("row111"); + byte[] row2 = Bytes.toBytes("row222"); + byte[] row3 = Bytes.toBytes("row333"); + byte[] row4 = Bytes.toBytes("row444"); + byte[] row5 = Bytes.toBytes("row555"); + byte[] row6 = Bytes.toBytes("row666"); + byte[] row7 = Bytes.toBytes("row777"); + + byte[] col1 = Bytes.toBytes("Pub111"); + + byte[] family = Bytes.toBytes("testFamily"); + this.region = initHRegion(tableName, row1, row6, getName(), CONF, false, family); + this.region.setSkipRowChecking(true); + try { + + Put put = new Put(row1); + put.addColumn(family, col1, Bytes.toBytes(10L)); + region.put(put); + + put = new Put(row2); + put.addColumn(family, col1, Bytes.toBytes(15L)); + region.put(put); + + put = new Put(row3); + put.addColumn(family, col1, Bytes.toBytes(20L)); + region.put(put); + + put = new Put(row4); + put.addColumn(family, col1, Bytes.toBytes(30L)); + region.put(put); + + put = new Put(row5); + put.addColumn(family, col1, Bytes.toBytes(40L)); + region.put(put); + + Scan scan = new Scan(row1, row5); + scan.setMaxVersions(); + scan.addColumn(family, col1); + s = region.getScanner(scan); + List results = new ArrayList(); + boolean hasMore = s.next(results); + while (hasMore) { + hasMore = s.next(results); + } + s.close(); + + assertEquals(4, results.size()); + + //Put row6 and row7 to make the region has data out of its boundary. + put = new Put(row6); + put.addColumn(family, col1, Bytes.toBytes(40L)); + region.put(put); + + put = new Put(row7); + put.addColumn(family, col1, Bytes.toBytes(40L)); + region.put(put); + + scan = new Scan(row1); + scan.setMaxVersions(); + scan.addColumn(family, col1); + s = region.getScanner(scan); + results.clear(); + hasMore = s.next(results); + while (hasMore) { + hasMore = s.next(results); + } + s.close(); + + assertEquals(5, results.size()); + } finally { + if (s != null) { + s.close(); + } + HBaseTestingUtility.closeRegionAndWAL(this.region); + this.region = null; + } + } + + @Test public void testScanner_StopRow1542() throws IOException { byte[] family = Bytes.toBytes("testFamily"); this.region = initHRegion(tableName, getName(), CONF, family);