HBASE-25368 Filter out more invalid encoded name in isEncodedRegionNa… (#2868)
HBASE-25368 Filter out more invalid encoded name in isEncodedRegionName(byte[] regionName) Signed-off-by: Duo Zhang <zhangduo@apache.org>
This commit is contained in:
parent
a37e727990
commit
5c13c68494
|
@ -2388,51 +2388,56 @@ class RawAsyncHBaseAdmin implements AsyncAdmin {
|
||||||
if (regionNameOrEncodedRegionName == null) {
|
if (regionNameOrEncodedRegionName == null) {
|
||||||
return failedFuture(new IllegalArgumentException("Passed region name can't be null"));
|
return failedFuture(new IllegalArgumentException("Passed region name can't be null"));
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
CompletableFuture<Optional<HRegionLocation>> future;
|
CompletableFuture<Optional<HRegionLocation>> future;
|
||||||
if (RegionInfo.isEncodedRegionName(regionNameOrEncodedRegionName)) {
|
if (RegionInfo.isEncodedRegionName(regionNameOrEncodedRegionName)) {
|
||||||
String encodedName = Bytes.toString(regionNameOrEncodedRegionName);
|
String encodedName = Bytes.toString(regionNameOrEncodedRegionName);
|
||||||
if (encodedName.length() < RegionInfo.MD5_HEX_LENGTH) {
|
if (encodedName.length() < RegionInfo.MD5_HEX_LENGTH) {
|
||||||
// old format encodedName, should be meta region
|
// old format encodedName, should be meta region
|
||||||
future = connection.registry.getMetaRegionLocations()
|
future = connection.registry.getMetaRegionLocations()
|
||||||
.thenApply(locs -> Stream.of(locs.getRegionLocations())
|
.thenApply(locs -> Stream.of(locs.getRegionLocations())
|
||||||
.filter(loc -> loc.getRegion().getEncodedName().equals(encodedName)).findFirst());
|
.filter(loc -> loc.getRegion().getEncodedName().equals(encodedName)).findFirst());
|
||||||
} else {
|
|
||||||
future = ClientMetaTableAccessor.getRegionLocationWithEncodedName(metaTable,
|
|
||||||
regionNameOrEncodedRegionName);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
RegionInfo regionInfo =
|
future = ClientMetaTableAccessor.getRegionLocationWithEncodedName(metaTable,
|
||||||
CatalogFamilyFormat.parseRegionInfoFromRegionName(regionNameOrEncodedRegionName);
|
regionNameOrEncodedRegionName);
|
||||||
if (regionInfo.isMetaRegion()) {
|
}
|
||||||
future = connection.registry.getMetaRegionLocations()
|
} else {
|
||||||
.thenApply(locs -> Stream.of(locs.getRegionLocations())
|
// Not all regionNameOrEncodedRegionName here is going to be a valid region name,
|
||||||
.filter(loc -> loc.getRegion().getReplicaId() == regionInfo.getReplicaId())
|
// it needs to throw out IllegalArgumentException in case tableName is passed in.
|
||||||
.findFirst());
|
RegionInfo regionInfo;
|
||||||
} else {
|
try {
|
||||||
future =
|
regionInfo = CatalogFamilyFormat.parseRegionInfoFromRegionName(
|
||||||
ClientMetaTableAccessor.getRegionLocation(metaTable, regionNameOrEncodedRegionName);
|
regionNameOrEncodedRegionName);
|
||||||
}
|
} catch (IOException ioe) {
|
||||||
|
return failedFuture(new IllegalArgumentException(ioe.getMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
CompletableFuture<HRegionLocation> returnedFuture = new CompletableFuture<>();
|
if (regionInfo.isMetaRegion()) {
|
||||||
addListener(future, (location, err) -> {
|
future = connection.registry.getMetaRegionLocations()
|
||||||
if (err != null) {
|
.thenApply(locs -> Stream.of(locs.getRegionLocations())
|
||||||
returnedFuture.completeExceptionally(err);
|
.filter(loc -> loc.getRegion().getReplicaId() == regionInfo.getReplicaId())
|
||||||
return;
|
.findFirst());
|
||||||
}
|
} else {
|
||||||
if (!location.isPresent() || location.get().getRegion() == null) {
|
future =
|
||||||
returnedFuture.completeExceptionally(
|
ClientMetaTableAccessor.getRegionLocation(metaTable, regionNameOrEncodedRegionName);
|
||||||
new UnknownRegionException("Invalid region name or encoded region name: " +
|
}
|
||||||
Bytes.toStringBinary(regionNameOrEncodedRegionName)));
|
|
||||||
} else {
|
|
||||||
returnedFuture.complete(location.get());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return returnedFuture;
|
|
||||||
} catch (IOException e) {
|
|
||||||
return failedFuture(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CompletableFuture<HRegionLocation> returnedFuture = new CompletableFuture<>();
|
||||||
|
addListener(future, (location, err) -> {
|
||||||
|
if (err != null) {
|
||||||
|
returnedFuture.completeExceptionally(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!location.isPresent() || location.get().getRegion() == null) {
|
||||||
|
returnedFuture.completeExceptionally(
|
||||||
|
new UnknownRegionException("Invalid region name or encoded region name: " +
|
||||||
|
Bytes.toStringBinary(regionNameOrEncodedRegionName)));
|
||||||
|
} else {
|
||||||
|
returnedFuture.complete(location.get());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return returnedFuture;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -363,7 +363,23 @@ public interface RegionInfo extends Comparable<RegionInfo> {
|
||||||
@InterfaceAudience.Private // For use by internals only.
|
@InterfaceAudience.Private // For use by internals only.
|
||||||
public static boolean isEncodedRegionName(byte[] regionName) {
|
public static boolean isEncodedRegionName(byte[] regionName) {
|
||||||
// If not parseable as region name, presume encoded. TODO: add stringency; e.g. if hex.
|
// If not parseable as region name, presume encoded. TODO: add stringency; e.g. if hex.
|
||||||
return parseRegionNameOrReturnNull(regionName) == null && regionName.length <= MD5_HEX_LENGTH;
|
if (parseRegionNameOrReturnNull(regionName) == null) {
|
||||||
|
if (regionName.length > MD5_HEX_LENGTH) {
|
||||||
|
return false;
|
||||||
|
} else if (regionName.length == MD5_HEX_LENGTH) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
String encodedName = Bytes.toString(regionName);
|
||||||
|
try {
|
||||||
|
Integer.parseInt(encodedName);
|
||||||
|
// If this is a valid integer, it could be hbase:meta's encoded region name.
|
||||||
|
return true;
|
||||||
|
} catch(NumberFormatException er) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.apache.hadoop.hbase.client;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertThrows;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
@ -99,6 +100,24 @@ public class TestAdmin1 extends TestAdminBase {
|
||||||
assertTrue(exception instanceof TableNotFoundException);
|
assertTrue(exception instanceof TableNotFoundException);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCompactATableWithSuperLongTableName() throws Exception {
|
||||||
|
TableName tableName = TableName.valueOf(name.getMethodName());
|
||||||
|
TableDescriptor htd = TableDescriptorBuilder.newBuilder(tableName)
|
||||||
|
.setColumnFamily(ColumnFamilyDescriptorBuilder.of("fam1")).build();
|
||||||
|
try {
|
||||||
|
ADMIN.createTable(htd);
|
||||||
|
assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> ADMIN.majorCompactRegion(tableName.getName()));
|
||||||
|
|
||||||
|
assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> ADMIN.majorCompactRegion(Bytes.toBytes("abcd")));
|
||||||
|
} finally {
|
||||||
|
ADMIN.disableTable(tableName);
|
||||||
|
ADMIN.deleteTable(tableName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCompactionTimestamps() throws Exception {
|
public void testCompactionTimestamps() throws Exception {
|
||||||
TableName tableName = TableName.valueOf(name.getMethodName());
|
TableName tableName = TableName.valueOf(name.getMethodName());
|
||||||
|
|
|
@ -298,11 +298,9 @@ public class TestAdmin2 extends TestAdminBase {
|
||||||
if (!regionInfo.isMetaRegion()) {
|
if (!regionInfo.isMetaRegion()) {
|
||||||
if (regionInfo.getRegionNameAsString().contains(name)) {
|
if (regionInfo.getRegionNameAsString().contains(name)) {
|
||||||
info = regionInfo;
|
info = regionInfo;
|
||||||
try {
|
assertThrows(UnknownRegionException.class,
|
||||||
ADMIN.unassign(Bytes.toBytes("sample"), true);
|
() -> ADMIN.unassign(Bytes.toBytes(
|
||||||
} catch (UnknownRegionException nsre) {
|
"test,,1358563771069.acc1ad1b7962564fc3a43e5907e8db33."), true));
|
||||||
// expected, ignore it
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue