diff --git hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java index 2bc98be..26cd849 100644 --- hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java +++ hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java @@ -411,12 +411,27 @@ public class MetaTableAccessor { * @return Ordered list of {@link HRegionInfo}. * @throws IOException */ - public static List getTableRegions(ZooKeeperWatcher zkw, - Connection connection, TableName tableName, final boolean excludeOfflinedSplitParents) - throws IOException { + public static List getTableRegions(ZooKeeperWatcher zkw, Connection connection, + TableName tableName, final boolean excludeOfflinedSplitParents) throws IOException { + return getTableRegions(zkw, connection, tableName, excludeOfflinedSplitParents, false); + } + + /** + * Gets all of the regions of the specified table. + * @param zkw zookeeper connection to access meta table + * @param connection connection we're using + * @param tableName table we're looking for + * @param excludeOfflinedSplitParents If true, do not include offlined split parents in the + * return. + * @param excludeReplicaRegions If true, do not include replica regions in the result. + * @return Ordered list of {@link HRegionInfo}. + */ + public static List getTableRegions(ZooKeeperWatcher zkw, Connection connection, + TableName tableName, final boolean excludeOfflinedSplitParents, + final boolean excludeReplicaRegions) throws IOException { List> result = null; - result = getTableRegionsAndLocations(zkw, connection, tableName, - excludeOfflinedSplitParents); + result = getTableRegionsAndLocations(zkw, connection, tableName, excludeOfflinedSplitParents, + excludeReplicaRegions); return getListOfHRegionInfos(result); } @@ -497,7 +512,22 @@ public class MetaTableAccessor { public static List> getTableRegionsAndLocations( ZooKeeperWatcher zkw, Connection connection, final TableName tableName, final boolean excludeOfflinedSplitParents) throws IOException { + return getTableRegionsAndLocations(zkw, connection, tableName, excludeOfflinedSplitParents, + false); + } + /** + * @param zkw ZooKeeperWatcher instance we're using to get hbase:meta location + * @param connection connection we're using + * @param tableName table to work with + * @param excludeOfflinedSplitParents Exclude offline regions + * @param excludeReplicaRegions If true, do not include replica regions in the result. + * @return Return list of regioninfos and server addresses. + */ + public static List> getTableRegionsAndLocations( + ZooKeeperWatcher zkw, Connection connection, final TableName tableName, + final boolean excludeOfflinedSplitParents, final boolean excludeReplicaRegions) + throws IOException { if (tableName.equals(TableName.META_TABLE_NAME)) { // If meta, do a bit of special handling. ServerName serverName = new MetaTableLocator().getMetaRegionLocation(zkw); @@ -533,6 +563,11 @@ public class MetaTableAccessor { } for (HRegionLocation loc : current.getRegionLocations()) { if (loc != null) { + // Exclude replica region from the result + if (excludeReplicaRegions + && !RegionReplicaUtil.isDefaultReplica(loc.getRegionInfo())) { + continue; + } this.results.add(new Pair( loc.getRegionInfo(), loc.getServerName())); } diff --git hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java index d0dea0a..1846cef 100644 --- hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java +++ hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java @@ -149,22 +149,24 @@ public final class ProcedureSyncWait { protected static List getRegionsFromMeta(final MasterProcedureEnv env, final TableName tableName) throws IOException { - return getRegionsFromMeta(env, tableName, false); + return getRegionsFromMeta(env, tableName, false, false); } protected static List getRegionsFromMeta(final MasterProcedureEnv env, - final TableName tableName, final boolean excludeOfflinedSplitParents) throws IOException { + final TableName tableName, final boolean excludeOfflinedSplitParents, + final boolean excludeReplicaRegions) throws IOException { return ProcedureSyncWait.waitFor(env, "regions of table=" + tableName + " from meta", - new ProcedureSyncWait.Predicate>() { - @Override - public List evaluate() throws IOException { - if (TableName.META_TABLE_NAME.equals(tableName)) { - return new MetaTableLocator().getMetaRegions(env.getMasterServices().getZooKeeper()); - } - return MetaTableAccessor.getTableRegions(env.getMasterServices().getZooKeeper(), - env.getMasterServices().getConnection(), tableName, excludeOfflinedSplitParents); + new ProcedureSyncWait.Predicate>() { + @Override + public List evaluate() throws IOException { + if (TableName.META_TABLE_NAME.equals(tableName)) { + return new MetaTableLocator().getMetaRegions(env.getMasterServices().getZooKeeper()); } - }); + return MetaTableAccessor.getTableRegions(env.getMasterServices().getZooKeeper(), + env.getMasterServices().getConnection(), tableName, excludeOfflinedSplitParents, + excludeReplicaRegions); + } + }); } protected static void waitRegionInTransition(final MasterProcedureEnv env, diff --git hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TruncateTableProcedure.java hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TruncateTableProcedure.java index 735e94f..120ae4f 100644 --- hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TruncateTableProcedure.java +++ hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TruncateTableProcedure.java @@ -85,7 +85,7 @@ public class TruncateTableProcedure // TODO: Move out... in the acquireLock() LOG.debug("waiting for '" + getTableName() + "' regions in transition"); - regions = ProcedureSyncWait.getRegionsFromMeta(env, getTableName(), true); + regions = ProcedureSyncWait.getRegionsFromMeta(env, getTableName(), true, true); assert regions != null && !regions.isEmpty() : "unexpected 0 regions"; ProcedureSyncWait.waitRegionInTransition(env, regions); diff --git hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.java hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.java index fa57b12..ff479d4 100644 --- hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.java +++ hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.java @@ -74,6 +74,11 @@ public class MasterProcedureTestingUtility { public static HRegionInfo[] createTable(final ProcedureExecutor procExec, final TableName tableName, final byte[][] splitKeys, String... family) throws IOException { HTableDescriptor htd = createHTD(tableName, family); + return createTable(procExec, htd, splitKeys); + } + + public static HRegionInfo[] createTable(final ProcedureExecutor procExec, + HTableDescriptor htd, final byte[][] splitKeys) throws IOException { HRegionInfo[] regions = ModifyRegionUtils.createHRegionInfos(htd, splitKeys); long procId = ProcedureTestingUtility.submitAndWait(procExec, new CreateTableProcedure(procExec.getEnvironment(), htd, regions)); diff --git hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestTruncateTableProcedure.java hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestTruncateTableProcedure.java index 8797a4f..47460af 100644 --- hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestTruncateTableProcedure.java +++ hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestTruncateTableProcedure.java @@ -43,6 +43,8 @@ import org.junit.experimental.categories.Category; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import java.io.IOException; + @Category(MediumTests.class) public class TestTruncateTableProcedure { private static final Log LOG = LogFactory.getLog(TestTruncateTableProcedure.class); @@ -241,23 +243,40 @@ public class TestTruncateTableProcedure { return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor(); } - @Test(timeout=60000) - public void testTruncateWithPreserveAfterSplit() throws Exception{ + @Test(timeout = 60000) + public void testTruncateWithPreserveAfterSplit() throws Exception { final String[] families = new String[] { "f1", "f2" }; - final byte[][] splitKeys = new byte[][] { - Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c") - }; + final byte[][] splitKeys = + new byte[][] { Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c") }; TableName tableName = TableName.valueOf("testTruncateWithPreserveAfterSplit"); - HRegionInfo[] regions = MasterProcedureTestingUtility.createTable( - getMasterProcedureExecutor(), tableName, splitKeys, families); + HRegionInfo[] regions = MasterProcedureTestingUtility.createTable(getMasterProcedureExecutor(), + tableName, splitKeys, families); + splitAndTruncate(families, splitKeys, tableName, regions); + } + + @Test(timeout = 60000) + public void testTruncatePreserveWithReplicaRegionAfterSplit() throws Exception { + final String[] families = new String[] { "f1", "f2" }; + final byte[][] splitKeys = + new byte[][] { Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c") }; + TableName tableName = TableName.valueOf("testTruncateWithPreserveAfterSplit"); + HTableDescriptor htd = MasterProcedureTestingUtility.createHTD(tableName, families); + htd.setRegionReplication(3); + HRegionInfo[] regions = + MasterProcedureTestingUtility.createTable(getMasterProcedureExecutor(), htd, splitKeys); + splitAndTruncate(families, splitKeys, tableName, regions); + } + + private void splitAndTruncate(final String[] families, final byte[][] splitKeys, + TableName tableName, HRegionInfo[] regions) throws IOException, InterruptedException { // load enough data so the table can split - MasterProcedureTestingUtility.loadData( - UTIL.getConnection(), tableName, 5000, splitKeys, families); + MasterProcedureTestingUtility.loadData(UTIL.getConnection(), tableName, 5000, splitKeys, + families); assertEquals(5000, UTIL.countRows(tableName)); UTIL.getHBaseAdmin().split(tableName); UTIL.waitUntilAllRegionsAssigned(tableName); - //wait until split really happens - while(UTIL.getHBaseAdmin().getTableRegions(tableName).size() <= regions.length) { + // wait until split really happens + while (UTIL.getHBaseAdmin().getTableRegions(tableName).size() <= regions.length) { Thread.sleep(50); } // disable the table @@ -265,10 +284,9 @@ public class TestTruncateTableProcedure { // truncate the table final ProcedureExecutor procExec = getMasterProcedureExecutor(); long procId = ProcedureTestingUtility.submitAndWait(procExec, - new TruncateTableProcedure(procExec.getEnvironment(), tableName, true)); + new TruncateTableProcedure(procExec.getEnvironment(), tableName, true)); ProcedureTestingUtility.assertProcNotFailed(procExec, procId); UTIL.waitUntilAllRegionsAssigned(tableName); - } }