HBASE-14824 HBaseAdmin.mergeRegions should recognize both full region names and encoded region names (Eungsop Yoo)

This commit is contained in:
tedyu 2015-11-18 14:24:47 -08:00
parent b2187c31ab
commit d738aade2e
4 changed files with 73 additions and 11 deletions

View File

@ -118,6 +118,9 @@ public class HRegionInfo implements Comparable<HRegionInfo> {
private static final int MAX_REPLICA_ID = 0xFFFF;
public static final int DEFAULT_REPLICA_ID = 0;
public static final String INVALID_REGION_NAME_FORMAT_MESSAGE = "Invalid regionName format";
/**
* Does region name contain its encoded name?
* @param regionName region name
@ -521,7 +524,8 @@ public class HRegionInfo implements Comparable<HRegionInfo> {
}
}
if (offset == -1) {
throw new IOException("Invalid regionName format: " + Bytes.toStringBinary(regionName));
throw new IOException(INVALID_REGION_NAME_FORMAT_MESSAGE
+ ": " + Bytes.toStringBinary(regionName));
}
byte[] tableName = new byte[offset];
System.arraycopy(regionName, 0, tableName, 0, offset);
@ -552,7 +556,8 @@ public class HRegionInfo implements Comparable<HRegionInfo> {
}
}
if (offset == -1) {
throw new IOException("Invalid regionName format: " + Bytes.toStringBinary(regionName));
throw new IOException(INVALID_REGION_NAME_FORMAT_MESSAGE
+ ": " + Bytes.toStringBinary(regionName));
}
byte [] startKey = HConstants.EMPTY_BYTE_ARRAY;
if(offset != tableName.length + 1) {

View File

@ -864,13 +864,13 @@ public interface Admin extends Abortable, Closeable {
/**
* Merge two regions. Asynchronous operation.
*
* @param encodedNameOfRegionA encoded name of region a
* @param encodedNameOfRegionB encoded name of region b
* @param nameOfRegionA encoded or full name of region a
* @param nameOfRegionB encoded or full name of region b
* @param forcible true if do a compulsory merge, otherwise we will only merge two adjacent
* regions
* @throws IOException
*/
void mergeRegions(final byte[] encodedNameOfRegionA, final byte[] encodedNameOfRegionB,
void mergeRegions(final byte[] nameOfRegionA, final byte[] nameOfRegionB,
final boolean forcible) throws IOException;
/**

View File

@ -2267,22 +2267,40 @@ public class HBaseAdmin implements Admin {
});
}
private boolean isEncodedRegionName(byte[] regionName) throws IOException {
try {
HRegionInfo.parseRegionName(regionName);
return false;
} catch (IOException e) {
if (StringUtils.stringifyException(e)
.contains(HRegionInfo.INVALID_REGION_NAME_FORMAT_MESSAGE)) {
return true;
}
throw e;
}
}
/**
* Merge two regions. Asynchronous operation.
* @param encodedNameOfRegionA encoded name of region a
* @param encodedNameOfRegionB encoded name of region b
* @param nameOfRegionA encoded or full name of region a
* @param nameOfRegionB encoded or full name of region b
* @param forcible true if do a compulsory merge, otherwise we will only merge
* two adjacent regions
* @throws IOException
*/
@Override
public void mergeRegions(final byte[] encodedNameOfRegionA,
final byte[] encodedNameOfRegionB, final boolean forcible)
public void mergeRegions(final byte[] nameOfRegionA,
final byte[] nameOfRegionB, final boolean forcible)
throws IOException {
Pair<HRegionInfo, ServerName> pair = getRegion(encodedNameOfRegionA);
final byte[] encodedNameOfRegionA = isEncodedRegionName(nameOfRegionA) ?
nameOfRegionA : HRegionInfo.encodeRegionName(nameOfRegionA).getBytes();
final byte[] encodedNameOfRegionB = isEncodedRegionName(nameOfRegionB) ?
nameOfRegionB : HRegionInfo.encodeRegionName(nameOfRegionB).getBytes();
Pair<HRegionInfo, ServerName> pair = getRegion(nameOfRegionA);
if (pair != null && pair.getFirst().getReplicaId() != HRegionInfo.DEFAULT_REPLICA_ID)
throw new IllegalArgumentException("Can't invoke merge on non-default regions directly");
pair = getRegion(encodedNameOfRegionB);
pair = getRegion(nameOfRegionB);
if (pair != null && pair.getFirst().getReplicaId() != HRegionInfo.DEFAULT_REPLICA_ID)
throw new IllegalArgumentException("Can't invoke merge on non-default regions directly");
executeCallable(new MasterCallable<Void>(getConnection()) {

View File

@ -1393,4 +1393,43 @@ public class TestAdmin1 {
}
}
}
@Test
public void testMergeRegions() throws Exception {
TableName tableName = TableName.valueOf("testMergeWithFullRegionName");
HColumnDescriptor cd = new HColumnDescriptor("d");
HTableDescriptor td = new HTableDescriptor(tableName);
td.addFamily(cd);
byte[][] splitRows = new byte[2][];
splitRows[0] = new byte[]{(byte)'3'};
splitRows[1] = new byte[]{(byte)'6'};
try {
TEST_UTIL.createTable(td, splitRows);
TEST_UTIL.waitTableAvailable(tableName);
List<HRegionInfo> tableRegions;
HRegionInfo regionA;
HRegionInfo regionB;
// merge with full name
tableRegions = admin.getTableRegions(tableName);
assertEquals(3, admin.getTableRegions(tableName).size());
regionA = tableRegions.get(0);
regionB = tableRegions.get(1);
admin.mergeRegions(regionA.getRegionName(), regionB.getRegionName(), false);
Thread.sleep(1000);
assertEquals(2, admin.getTableRegions(tableName).size());
// merge with encoded name
tableRegions = admin.getTableRegions(tableName);
regionA = tableRegions.get(0);
regionB = tableRegions.get(1);
admin.mergeRegions(regionA.getEncodedNameAsBytes(), regionB.getEncodedNameAsBytes(), false);
Thread.sleep(1000);
assertEquals(1, admin.getTableRegions(tableName).size());
} finally {
this.admin.disableTable(tableName);
this.admin.deleteTable(tableName);
}
}
}