HBASE-14824 HBaseAdmin.mergeRegions should recognize both full region names and encoded region names (Eungsop Yoo)
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/d738aade Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/d738aade Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/d738aade Branch: refs/heads/hbase-12439 Commit: d738aade2ec9a837f71cdb37792e3eb516cc53a3 Parents: b2187c3 Author: tedyu <[email protected]> Authored: Wed Nov 18 14:24:47 2015 -0800 Committer: tedyu <[email protected]> Committed: Wed Nov 18 14:24:47 2015 -0800 ---------------------------------------------------------------------- .../org/apache/hadoop/hbase/HRegionInfo.java | 9 ++++- .../org/apache/hadoop/hbase/client/Admin.java | 6 +-- .../apache/hadoop/hbase/client/HBaseAdmin.java | 30 ++++++++++++--- .../apache/hadoop/hbase/client/TestAdmin1.java | 39 ++++++++++++++++++++ 4 files changed, 73 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hbase/blob/d738aade/hbase-client/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java ---------------------------------------------------------------------- diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java index 59c698f..13ba23d 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java @@ -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) { http://git-wip-us.apache.org/repos/asf/hbase/blob/d738aade/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java ---------------------------------------------------------------------- diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java index 972939e..290ecb5 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java @@ -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; /** http://git-wip-us.apache.org/repos/asf/hbase/blob/d738aade/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java ---------------------------------------------------------------------- diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java index ba369c0..66079dd 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java @@ -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()) { http://git-wip-us.apache.org/repos/asf/hbase/blob/d738aade/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin1.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin1.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin1.java index eabff98..6730e0a 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin1.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin1.java @@ -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); + } + } }
