Index: src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java
===================================================================
--- src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java (revision 1340192)
+++ src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java (working copy)
@@ -582,8 +582,12 @@
// So we will assign the ROOT and .META. region immediately.
processOpeningState(regionInfo);
break;
-
- }
+ } else if (deadServers.keySet().contains(sn)) {
+ // if the region is found on a dead server, we can assign
+ // it to a new RS. (HBASE-5882)
+ processOpeningState(regionInfo);
+ break;
+ }
regionsInTransition.put(encodedRegionName,
getRegionState(regionInfo, RegionState.State.OPENING, rt));
failoverProcessedRegions.put(encodedRegionName, regionInfo);
@@ -621,7 +625,6 @@
}
}
-
/**
* Put the region hri into an offline state up in zk.
* @param hri
Index: src/test/java/org/apache/hadoop/hbase/master/TestAssignmentManager.java
===================================================================
--- src/test/java/org/apache/hadoop/hbase/master/TestAssignmentManager.java (revision 1340192)
+++ src/test/java/org/apache/hadoop/hbase/master/TestAssignmentManager.java (working copy)
@@ -472,6 +472,7 @@
am.regionsInTransition.isEmpty());
}
} finally {
+ am.setEnabledTable(REGIONINFO.getTableNameAsString());
executor.shutdown();
am.shutdown();
// Clean up all znodes
@@ -677,6 +678,35 @@
}
/**
+ * Test the scenario when the master is in failover and trying to process a
+ * region which is in Opening state on a dead RS. Master should immediately
+ * assign the region and not wait for Timeout Monitor.(Hbase-5882).
+ */
+ @Test
+ public void testRegionInOpeningStateOnDeadRSWhileMasterFailover() throws IOException,
+ KeeperException, ServiceException, InterruptedException {
+ AssignmentManagerWithExtrasForTesting am = setUpMockedAssignmentManager(this.server,
+ this.serverManager);
+ ZKAssign.createNodeOffline(this.watcher, REGIONINFO, SERVERNAME_A);
+ int version = ZKAssign.getVersion(this.watcher, REGIONINFO);
+ ZKAssign.transitionNode(this.watcher, REGIONINFO, SERVERNAME_A, EventType.M_ZK_REGION_OFFLINE,
+ EventType.RS_ZK_REGION_OPENING, version);
+ RegionTransition rt = RegionTransition.createRegionTransition(EventType.RS_ZK_REGION_OPENING,
+ REGIONINFO.getRegionName(), SERVERNAME_A, HConstants.EMPTY_BYTE_ARRAY);
+ Map>> deadServers =
+ new HashMap>>();
+ deadServers.put(SERVERNAME_A, null);
+ version = ZKAssign.getVersion(this.watcher, REGIONINFO);
+ am.gate.set(false);
+ am.processRegionsInTransition(rt, REGIONINFO, deadServers, version);
+ // Waiting for the assignment to get completed.
+ while (!am.gate.get()) {
+ Thread.sleep(10);
+ }
+ assertTrue("The region should be assigned immediately.", null != am.regionPlans.get(REGIONINFO
+ .getEncodedName()));
+ }
+ /**
* Creates a new ephemeral node in the SPLITTING state for the specified region.
* Create it ephemeral in case regionserver dies mid-split.
*
@@ -810,7 +840,13 @@
while (this.gate.get()) Threads.sleep(1);
super.processRegionsInTransition(rt, regionInfo, deadServers, expectedVersion);
}
-
+
+ @Override
+ public void assign(HRegionInfo region, boolean setOfflineInZK, boolean forceNewPlan,
+ boolean hijack) {
+ super.assign(region, setOfflineInZK, forceNewPlan, hijack);
+ this.gate.set(true);
+ }
/** reset the watcher */
void setWatcher(ZooKeeperWatcher watcher) {
this.watcher = watcher;