diff --git src/test/java/org/apache/hadoop/hbase/master/Mocking.java src/test/java/org/apache/hadoop/hbase/master/Mocking.java new file mode 100644 index 0000000..187e07d --- /dev/null +++ src/test/java/org/apache/hadoop/hbase/master/Mocking.java @@ -0,0 +1,46 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hbase.master; + +import org.apache.hadoop.hbase.master.AssignmentManager.RegionState; + +/** + * Package scoped mocking utility. + */ +public class Mocking { + + static void waitForRegionPendingOpenInRIT(AssignmentManager am, String encodedName) + throws InterruptedException { + // We used to do a check like this: + //!Mocking.verifyRegionState(this.watcher, REGIONINFO, EventType.M_ZK_REGION_OFFLINE)) { + // There is a race condition with this: because we may do the transition to + // RS_ZK_REGION_OPENING before the RIT is internally updated. We need to wait for the + // RIT to be as we need it to be instead. This cannot happen in a real cluster as we + // update the RIT before sending the openRegion request. + + boolean wait = true; + while (wait) { + RegionState state = am.getRegionsInTransition().get(encodedName); + if (state != null && state.isPendingOpen()){ + wait = false; + } else { + Thread.sleep(1); + } + } + } +} diff --git src/test/java/org/apache/hadoop/hbase/master/TestAssignmentManager.java src/test/java/org/apache/hadoop/hbase/master/TestAssignmentManager.java index ba46069..19e7dfa 100644 --- src/test/java/org/apache/hadoop/hbase/master/TestAssignmentManager.java +++ src/test/java/org/apache/hadoop/hbase/master/TestAssignmentManager.java @@ -36,9 +36,9 @@ import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.HServerLoad; import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.MediumTests; import org.apache.hadoop.hbase.Server; import org.apache.hadoop.hbase.ServerName; -import org.apache.hadoop.hbase.SmallTests; import org.apache.hadoop.hbase.ZooKeeperConnectionException; import org.apache.hadoop.hbase.catalog.CatalogTracker; import org.apache.hadoop.hbase.client.Get; @@ -61,12 +61,12 @@ import org.apache.hadoop.hbase.util.Threads; import org.apache.hadoop.hbase.util.Writables; import org.apache.hadoop.hbase.zookeeper.RecoverableZooKeeper; import org.apache.hadoop.hbase.zookeeper.ZKAssign; +import org.apache.hadoop.hbase.zookeeper.ZKTable.TableState; import org.apache.hadoop.hbase.zookeeper.ZKUtil; import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher; -import org.apache.hadoop.hbase.zookeeper.ZKTable.TableState; import org.apache.zookeeper.KeeperException; -import org.apache.zookeeper.Watcher; import org.apache.zookeeper.KeeperException.NodeExistsException; +import org.apache.zookeeper.Watcher; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; @@ -82,7 +82,7 @@ import com.google.protobuf.ServiceException; /** * Test {@link AssignmentManager} */ -@Category(SmallTests.class) +@Category(MediumTests.class) public class TestAssignmentManager { private static final HBaseTestingUtility HTU = new HBaseTestingUtility(); private static final ServerName SERVERNAME_A = @@ -162,7 +162,7 @@ public class TestAssignmentManager { /** * Test a balance going on at same time as a master failover - * + * * @throws IOException * @throws KeeperException * @throws InterruptedException @@ -313,10 +313,11 @@ public class TestAssignmentManager { * from one server to another mocking regionserver responding over zk. * @throws IOException * @throws KeeperException + * @throws InterruptedException */ - @Test + @Test(timeout = 10000) public void testBalance() - throws IOException, KeeperException { + throws IOException, KeeperException, InterruptedException { // Create and startup an executor. This is used by AssignmentManager // handling zk callbacks. ExecutorService executor = startupMasterExecutor("testBalanceExecutor"); @@ -350,11 +351,9 @@ public class TestAssignmentManager { // AM is going to notice above CLOSED and queue up a new assign. The // assign will go to open the region in the new location set by the // balancer. The zk node will be OFFLINE waiting for regionserver to - // transition it through OPENING, OPENED. Wait till we see the OFFLINE - // zk node before we proceed. - while (!ZKAssign.verifyRegionState(this.watcher, REGIONINFO, EventType.M_ZK_REGION_OFFLINE)) { - Threads.sleep(1); - } + // transition it through OPENING, OPENED. Wait till we see the RIT + // before we proceed. + Mocking.waitForRegionPendingOpenInRIT(am, REGIONINFO.getEncodedName()); // Get current versionid else will fail on transition from OFFLINE to OPENING below versionid = ZKAssign.getVersion(this.watcher, REGIONINFO); assertNotSame(-1, versionid); @@ -407,7 +406,7 @@ public class TestAssignmentManager { /** * To test closed region handler to remove rit and delete corresponding znode if region in pending - * close or closing while processing shutdown of a region server.(HBASE-5927). + * close or closing while processing shutdown of a region server.(HBASE-5927). * @throws KeeperException * @throws IOException */ @@ -417,7 +416,7 @@ public class TestAssignmentManager { testCaseWithPartiallyDisabledState(TableState.DISABLING); testCaseWithPartiallyDisabledState(TableState.DISABLED); } - + /** * To test if the split region is removed from RIT if the region was in SPLITTING state * but the RS has actually completed the splitting in META but went down. See HBASE-6070 @@ -451,7 +450,7 @@ public class TestAssignmentManager { am.regionsInTransition.put(REGIONINFO.getEncodedName(), new RegionState(REGIONINFO, State.SPLITTING, System.currentTimeMillis(), SERVERNAME_A)); am.getZKTable().setEnabledTable(REGIONINFO.getTableNameAsString()); - + RegionTransitionData data = new RegionTransitionData(EventType.RS_ZK_REGION_SPLITTING, REGIONINFO.getRegionName(), SERVERNAME_A); String node = ZKAssign.getNodeName(this.watcher, REGIONINFO.getEncodedName()); @@ -459,11 +458,11 @@ public class TestAssignmentManager { ZKUtil.createAndWatch(this.watcher, node, data.getBytes()); try { - + processServerShutdownHandler(ct, am, regionSplitDone); // check znode deleted or not. // In both cases the znode should be deleted. - + if(regionSplitDone){ assertTrue("Region state of region in SPLITTING should be removed from rit.", am.regionsInTransition.isEmpty()); @@ -506,7 +505,7 @@ public class TestAssignmentManager { } else { am.getZKTable().setDisabledTable(REGIONINFO.getTableNameAsString()); } - + RegionTransitionData data = new RegionTransitionData(EventType.M_ZK_REGION_CLOSING, REGIONINFO.getRegionName(), SERVERNAME_A); String node = ZKAssign.getNodeName(this.watcher, REGIONINFO.getEncodedName()); @@ -581,7 +580,7 @@ public class TestAssignmentManager { * @param hri Region to serialize into HRegionInfo * @return A mocked up Result that fakes a Get on a row in the * .META. table. - * @throws IOException + * @throws IOException */ private Result getMetaTableRowResult(final HRegionInfo hri, final ServerName sn) @@ -600,13 +599,13 @@ public class TestAssignmentManager { Bytes.toBytes(sn.getStartcode()))); return new Result(kvs); } - + /** * @param sn ServerName to use making startcode and server in meta * @param hri Region to serialize into HRegionInfo * @return A mocked up Result that fakes a Get on a row in the * .META. table. - * @throws IOException + * @throws IOException */ private Result getMetaTableRowResultAsSplitRegion(final HRegionInfo hri, final ServerName sn) throws IOException { @@ -668,12 +667,12 @@ public class TestAssignmentManager { am.shutdown(); } } - + /** * Tests the processDeadServersAndRegionsInTransition should not fail with NPE * when it failed to get the children. Let's abort the system in this * situation - * @throws ServiceException + * @throws ServiceException */ @Test(timeout = 5000) public void testProcessDeadServersAndRegionsInTransitionShouldNotFailWithNPE() @@ -713,8 +712,8 @@ public class TestAssignmentManager { * @param region region to be created as offline * @param serverName server event originates from * @return Version of znode created. - * @throws KeeperException - * @throws IOException + * @throws KeeperException + * @throws IOException */ // Copied from SplitTransaction rather than open the method over there in // the regionserver package. @@ -807,9 +806,9 @@ public class TestAssignmentManager { server, manager, ct, balancer, executor); return am; } - + /** - * TestCase verifies that the regionPlan is updated whenever a region fails to open + * TestCase verifies that the regionPlan is updated whenever a region fails to open * and the master tries to process RS_ZK_FAILED_OPEN state.(HBASE-5546). */ @Test @@ -863,11 +862,11 @@ public class TestAssignmentManager { am.shutdown(); } } - + /** * Test verifies whether assignment is skipped for regions of tables in DISABLING state during * clean cluster startup. See HBASE-6281. - * + * * @throws KeeperException * @throws IOException * @throws Exception @@ -973,7 +972,7 @@ public class TestAssignmentManager { this.gate.set(true); return randomServerName; } - + @Override public Map> retainAssignment( Map regions, List servers) {