HBASE-26881 Backport HBASE-25368 to branch-2 (#4267)

Signed-off-by: Andrew Purtell <apurtell@apache.org>
This commit is contained in:
Wellington Ramos Chevreuil 2022-03-25 10:04:13 +00:00 committed by Andrew Purtell
parent 6a4b2428df
commit 2bbddfee1e
4 changed files with 86 additions and 48 deletions

View File

@ -2394,51 +2394,55 @@ 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 = AsyncMetaTableAccessor.getRegionLocationWithEncodedName(metaTable,
regionNameOrEncodedRegionName);
}
} else { } else {
RegionInfo regionInfo = future = AsyncMetaTableAccessor.getRegionLocationWithEncodedName(metaTable,
MetaTableAccessor.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 = MetaTableAccessor.parseRegionInfoFromRegionName(regionNameOrEncodedRegionName);
AsyncMetaTableAccessor.getRegionLocation(metaTable, 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( AsyncMetaTableAccessor.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;
} }
/** /**

View File

@ -362,9 +362,25 @@ public interface RegionInfo extends Comparable<RegionInfo> {
* @return True if <code>regionName</code> represents an encoded name. * @return True if <code>regionName</code> represents an encoded name.
*/ */
@InterfaceAudience.Private // For use by internals only. @InterfaceAudience.Private // For use by internals only.
public static boolean isEncodedRegionName(byte[] regionName) { 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;
} }
/** /**

View File

@ -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;
@ -130,6 +131,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());

View File

@ -19,6 +19,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.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;
@ -316,11 +317,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
}
} }
} }
} }