HBASE-24734 RegionInfo#containsRange should support check meta table (#3496) (#3517)

Signed-off-by: zhangduo <zhangduo@apache.org>
This commit is contained in:
meiyi 2021-07-22 18:04:24 +08:00 committed by GitHub
parent 8bc180c773
commit 729da5a6d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 93 additions and 5 deletions

View File

@ -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));
}

View File

@ -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();

View File

@ -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<Cell> {
*/
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.

View File

@ -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);

View File

@ -30,6 +30,7 @@ import org.apache.hadoop.hbase.HBaseClassTestRule;
import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.HTableDescriptor;
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;
@ -251,6 +252,38 @@ public class TestHRegionInfo {
}
}
@Test
public void testContainsRangeForMetaTable() {
HTableDescriptor tableDesc = new HTableDescriptor(TableName.META_TABLE_NAME);
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() {
HTableDescriptor tableDesc = new HTableDescriptor(TableName.valueOf(name.getMethodName()));