From 9e27de6aed43bfcf9230272f1979122a8da4a08e Mon Sep 17 00:00:00 2001 From: meiyi Date: Thu, 22 Jul 2021 16:07:52 +0800 Subject: [PATCH] HBASE-24734 RegionInfo#containsRange should support check meta table (#3496) Signed-off-by: zhangduo --- .../hbase/client/MutableRegionInfo.java | 14 +++++--- .../hbase/client/TestRegionInfoBuilder.java | 34 +++++++++++++++++++ .../apache/hadoop/hbase/CellComparator.java | 12 +++++++ .../hadoop/hbase/MetaCellComparator.java | 5 +++ .../hbase/regionserver/TestRegionInfo.java | 34 +++++++++++++++++++ 5 files changed, 94 insertions(+), 5 deletions(-) diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/MutableRegionInfo.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/MutableRegionInfo.java index 028608db614..0aa301c4c8c 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/MutableRegionInfo.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/MutableRegionInfo.java @@ -17,6 +17,8 @@ */ package org.apache.hadoop.hbase.client; import java.util.Arrays; +import org.apache.hadoop.hbase.CellComparator; +import org.apache.hadoop.hbase.CellComparatorImpl; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.util.Bytes; @@ -206,15 +208,16 @@ class MutableRegionInfo implements RegionInfo { */ @Override public boolean containsRange(byte[] rangeStartKey, byte[] rangeEndKey) { - if (Bytes.compareTo(rangeStartKey, rangeEndKey) > 0) { + CellComparator cellComparator = CellComparatorImpl.getCellComparator(tableName); + if (cellComparator.compareRows(rangeStartKey, rangeEndKey) > 0) { throw new IllegalArgumentException( "Invalid range: " + Bytes.toStringBinary(rangeStartKey) + " > " + Bytes.toStringBinary(rangeEndKey)); } - boolean firstKeyInRange = Bytes.compareTo(rangeStartKey, startKey) >= 0; + boolean firstKeyInRange = cellComparator.compareRows(rangeStartKey, startKey) >= 0; boolean lastKeyInRange = - Bytes.compareTo(rangeEndKey, endKey) < 0 || + cellComparator.compareRows(rangeEndKey, endKey) < 0 || Bytes.equals(endKey, HConstants.EMPTY_BYTE_ARRAY); return firstKeyInRange && lastKeyInRange; } @@ -224,8 +227,9 @@ class MutableRegionInfo implements RegionInfo { */ @Override public boolean containsRow(byte[] row) { - return Bytes.compareTo(row, startKey) >= 0 && - (Bytes.compareTo(row, endKey) < 0 || + CellComparator cellComparator = CellComparatorImpl.getCellComparator(tableName); + return cellComparator.compareRows(row, startKey) >= 0 && + (cellComparator.compareRows(row, endKey) < 0 || Bytes.equals(endKey, HConstants.EMPTY_BYTE_ARRAY)); } diff --git a/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestRegionInfoBuilder.java b/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestRegionInfoBuilder.java index d7b375b4f7c..3b66f7eb2e6 100644 --- a/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestRegionInfoBuilder.java +++ b/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestRegionInfoBuilder.java @@ -26,6 +26,7 @@ import static org.junit.Assert.fail; import java.io.IOException; import org.apache.hadoop.hbase.HBaseClassTestRule; +import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.TableNameTestRule; import org.apache.hadoop.hbase.exceptions.DeserializationException; @@ -137,6 +138,39 @@ public class TestRegionInfoBuilder { } } + @Test + public void testContainsRangeForMetaTable() { + TableDescriptor tableDesc = + TableDescriptorBuilder.newBuilder(TableName.META_TABLE_NAME).build(); + RegionInfo hri = RegionInfoBuilder.newBuilder(tableDesc.getTableName()).build(); + byte[] startRow = HConstants.EMPTY_START_ROW; + byte[] row1 = Bytes.toBytes("a,a,0"); + byte[] row2 = Bytes.toBytes("aaaaa,,1"); + byte[] row3 = Bytes.toBytes("aaaaa,\u0000\u0000,2"); + byte[] row4 = Bytes.toBytes("aaaaa,\u0001,3"); + byte[] row5 = Bytes.toBytes("aaaaa,a,4"); + byte[] row6 = Bytes.toBytes("aaaaa,\u1000,5"); + + // Single row range at start of region + assertTrue(hri.containsRange(startRow, startRow)); + // Fully contained range + assertTrue(hri.containsRange(row1, row2)); + assertTrue(hri.containsRange(row2, row3)); + assertTrue(hri.containsRange(row3, row4)); + assertTrue(hri.containsRange(row4, row5)); + assertTrue(hri.containsRange(row5, row6)); + // Range overlapping start of region + assertTrue(hri.containsRange(startRow, row2)); + // Fully contained single-row range + assertTrue(hri.containsRange(row1, row1)); + // Degenerate range + try { + hri.containsRange(row3, row2); + fail("Invalid range did not throw IAE"); + } catch (IllegalArgumentException iae) { + } + } + @Test public void testLastRegionCompare() { TableDescriptor tableDesc = TableDescriptorBuilder.newBuilder(name.getTableName()).build(); diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/CellComparator.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/CellComparator.java index 474f77215a1..286498615a4 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/CellComparator.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/CellComparator.java @@ -20,6 +20,7 @@ package org.apache.hadoop.hbase; import java.nio.ByteBuffer; import java.util.Comparator; import org.apache.hadoop.hbase.util.ByteBufferUtils; +import org.apache.hadoop.hbase.util.Bytes; import org.apache.yetus.audience.InterfaceAudience; import org.apache.yetus.audience.InterfaceStability; @@ -82,6 +83,17 @@ public interface CellComparator extends Comparator { */ int compareRows(Cell cell, byte[] bytes, int offset, int length); + /** + * Compares two row bytes + * @param leftRow the byte array of the left row + * @param rightRow the byte array of the right row + * @return greater than 0 if leftRow is bigger, less than 0 if rightRow is bigger, 0 if both + * rows are equal + */ + default int compareRows(byte[] leftRow, byte[] rightRow) { + return Bytes.compareTo(leftRow, rightRow); + } + /** * @param row ByteBuffer that wraps a row; will read from current position and will reading all * remaining; will not disturb the ByteBuffer internal state. diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/MetaCellComparator.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/MetaCellComparator.java index 4c18cfe79d2..5adb1e8bd77 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/MetaCellComparator.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/MetaCellComparator.java @@ -55,6 +55,11 @@ public class MetaCellComparator extends CellComparatorImpl { rlength); } + @Override + public int compareRows(byte[] leftRow, byte[] rightRow) { + return compareRows(leftRow, 0, leftRow.length, rightRow, 0, rightRow.length); + } + @Override public int compare(final Cell a, final Cell b, boolean ignoreSequenceid) { int diff = compareRows(a, b); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionInfo.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionInfo.java index 2874206241a..56a8ea061e0 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionInfo.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionInfo.java @@ -30,6 +30,7 @@ import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hbase.HBaseClassTestRule; import org.apache.hadoop.hbase.HBaseTestingUtil; +import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.RegionInfoBuilder; @@ -262,6 +263,39 @@ public class TestRegionInfo { } } + @Test + public void testContainsRangeForMetaTable() { + TableDescriptor tableDesc = + TableDescriptorBuilder.newBuilder(TableName.META_TABLE_NAME).build(); + RegionInfo hri = RegionInfoBuilder.newBuilder(tableDesc.getTableName()).build(); + byte[] startRow = HConstants.EMPTY_START_ROW; + byte[] row1 = Bytes.toBytes("a,a,0"); + byte[] row2 = Bytes.toBytes("aaaaa,,1"); + byte[] row3 = Bytes.toBytes("aaaaa,\u0000\u0000,2"); + byte[] row4 = Bytes.toBytes("aaaaa,\u0001,3"); + byte[] row5 = Bytes.toBytes("aaaaa,a,4"); + byte[] row6 = Bytes.toBytes("aaaaa,\u1000,5"); + + // Single row range at start of region + assertTrue(hri.containsRange(startRow, startRow)); + // Fully contained range + assertTrue(hri.containsRange(row1, row2)); + assertTrue(hri.containsRange(row2, row3)); + assertTrue(hri.containsRange(row3, row4)); + assertTrue(hri.containsRange(row4, row5)); + assertTrue(hri.containsRange(row5, row6)); + // Range overlapping start of region + assertTrue(hri.containsRange(startRow, row2)); + // Fully contained single-row range + assertTrue(hri.containsRange(row1, row1)); + // Degenerate range + try { + hri.containsRange(row3, row2); + fail("Invalid range did not throw IAE"); + } catch (IllegalArgumentException iae) { + } + } + @Test public void testLastRegionCompare() { TableDescriptor tableDesc =