HBASE-19364, Truncate_preserve fails with table when replica region > 1
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/0d8fee21 Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/0d8fee21 Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/0d8fee21 Branch: refs/heads/branch-1.4 Commit: 0d8fee2158e08bc6d0907d4abbe1215eaded6ce3 Parents: 1b0b8d9 Author: Pankaj Kumar <pankaj...@huawei.com> Authored: Thu Dec 7 22:51:01 2017 +0530 Committer: Andrew Purtell <apurt...@apache.org> Committed: Fri Feb 23 17:03:03 2018 -0800 ---------------------------------------------------------------------- .../apache/hadoop/hbase/MetaTableAccessor.java | 45 +++++++++++++++++--- .../master/procedure/ProcedureSyncWait.java | 24 ++++++----- .../procedure/TruncateTableProcedure.java | 2 +- .../MasterProcedureTestingUtility.java | 5 +++ .../procedure/TestTruncateTableProcedure.java | 44 +++++++++++++------ 5 files changed, 90 insertions(+), 30 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hbase/blob/0d8fee21/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java ---------------------------------------------------------------------- diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java index 3f11558..440f8c6 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java @@ -392,12 +392,27 @@ public class MetaTableAccessor { * @return Ordered list of {@link HRegionInfo}. * @throws IOException */ - public static List<HRegionInfo> getTableRegions(ZooKeeperWatcher zkw, - Connection connection, TableName tableName, final boolean excludeOfflinedSplitParents) - throws IOException { + public static List<HRegionInfo> 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<HRegionInfo> getTableRegions(ZooKeeperWatcher zkw, Connection connection, + TableName tableName, final boolean excludeOfflinedSplitParents, + final boolean excludeReplicaRegions) throws IOException { List<Pair<HRegionInfo, ServerName>> result = null; - result = getTableRegionsAndLocations(zkw, connection, tableName, - excludeOfflinedSplitParents); + result = getTableRegionsAndLocations(zkw, connection, tableName, excludeOfflinedSplitParents, + excludeReplicaRegions); return getListOfHRegionInfos(result); } @@ -478,7 +493,22 @@ public class MetaTableAccessor { public static List<Pair<HRegionInfo, ServerName>> 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 List of regioninfos and server addresses. + */ + public static List<Pair<HRegionInfo, ServerName>> 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); @@ -514,6 +544,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<HRegionInfo, ServerName>( loc.getRegionInfo(), loc.getServerName())); } http://git-wip-us.apache.org/repos/asf/hbase/blob/0d8fee21/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java index d0dea0a..1846cef 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java @@ -149,22 +149,24 @@ public final class ProcedureSyncWait { protected static List<HRegionInfo> getRegionsFromMeta(final MasterProcedureEnv env, final TableName tableName) throws IOException { - return getRegionsFromMeta(env, tableName, false); + return getRegionsFromMeta(env, tableName, false, false); } protected static List<HRegionInfo> 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<List<HRegionInfo>>() { - @Override - public List<HRegionInfo> 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<List<HRegionInfo>>() { + @Override + public List<HRegionInfo> 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, http://git-wip-us.apache.org/repos/asf/hbase/blob/0d8fee21/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TruncateTableProcedure.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TruncateTableProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TruncateTableProcedure.java index 735e94f..120ae4f 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TruncateTableProcedure.java +++ b/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); http://git-wip-us.apache.org/repos/asf/hbase/blob/0d8fee21/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.java index fa57b12..ff479d4 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.java +++ b/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<MasterProcedureEnv> 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<MasterProcedureEnv> 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)); http://git-wip-us.apache.org/repos/asf/hbase/blob/0d8fee21/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestTruncateTableProcedure.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestTruncateTableProcedure.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestTruncateTableProcedure.java index 8797a4f..47460af 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestTruncateTableProcedure.java +++ b/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<MasterProcedureEnv> 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); - } }