HBASE-5882 Prcoess RIT on master restart can try assigning the region if the region is found on a dead server instead of waiting for Timeout Monitor (Ashutosh)

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1341110 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
ramkrishna 2012-05-21 17:07:33 +00:00
parent 683c005fca
commit 2cac550467
2 changed files with 101 additions and 44 deletions

View File

@ -582,8 +582,12 @@ public class AssignmentManager extends ZooKeeperListener {
// 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 @@ public class AssignmentManager extends ZooKeeperListener {
}
}
/**
* Put the region <code>hri</code> into an offline state up in zk.
* @param hri

View File

@ -472,6 +472,7 @@ public class TestAssignmentManager {
am.regionsInTransition.isEmpty());
}
} finally {
am.setEnabledTable(REGIONINFO.getTableNameAsString());
executor.shutdown();
am.shutdown();
// Clean up all znodes
@ -614,47 +615,65 @@ public class TestAssignmentManager {
@Test
public void testRegionPlanIsUpdatedWhenRegionFailsToOpen() throws IOException, KeeperException,
ServiceException, InterruptedException {
this.server.getConfiguration().setClass(HConstants.HBASE_MASTER_LOADBALANCER_CLASS,
MockedLoadBalancer.class, LoadBalancer.class);
AssignmentManagerWithExtrasForTesting am = setUpMockedAssignmentManager(this.server,
this.serverManager);
// Boolean variable used for waiting until randomAssignment is called and new
// plan is generated.
AtomicBoolean gate = new AtomicBoolean(false);
if (balancer instanceof MockedLoadBalancer) {
((MockedLoadBalancer) balancer).setGateVariable(gate);
try {
this.server.getConfiguration().setClass(
HConstants.HBASE_MASTER_LOADBALANCER_CLASS, MockedLoadBalancer.class,
LoadBalancer.class);
AssignmentManagerWithExtrasForTesting am = setUpMockedAssignmentManager(
this.server, this.serverManager);
// Boolean variable used for waiting until randomAssignment is called and
// new
// plan is generated.
AtomicBoolean gate = new AtomicBoolean(false);
if (balancer instanceof MockedLoadBalancer) {
((MockedLoadBalancer) balancer).setGateVariable(gate);
}
ZKAssign.createNodeOffline(this.watcher, REGIONINFO, SERVERNAME_A);
int v = ZKAssign.getVersion(this.watcher, REGIONINFO);
ZKAssign.transitionNode(this.watcher, REGIONINFO, SERVERNAME_A,
EventType.M_ZK_REGION_OFFLINE, EventType.RS_ZK_REGION_FAILED_OPEN, v);
String path = ZKAssign.getNodeName(this.watcher, REGIONINFO
.getEncodedName());
RegionState state = new RegionState(REGIONINFO, State.OPENING, System
.currentTimeMillis(), SERVERNAME_A);
am.regionsInTransition.put(REGIONINFO.getEncodedName(), state);
// a dummy plan inserted into the regionPlans. This plan is cleared and
// new one is formed
am.regionPlans.put(REGIONINFO.getEncodedName(), new RegionPlan(
REGIONINFO, null, SERVERNAME_A));
RegionPlan regionPlan = am.regionPlans.get(REGIONINFO.getEncodedName());
List<ServerName> serverList = new ArrayList<ServerName>(2);
serverList.add(SERVERNAME_B);
Mockito.when(
this.serverManager.createDestinationServersList(SERVERNAME_A))
.thenReturn(serverList);
am.nodeDataChanged(path);
// here we are waiting until the random assignment in the load balancer is
// called.
while (!gate.get()) {
Thread.sleep(10);
}
// new region plan may take some time to get updated after random
// assignment is called and
// gate is set to true.
RegionPlan newRegionPlan = am.regionPlans
.get(REGIONINFO.getEncodedName());
while (newRegionPlan == null) {
Thread.sleep(10);
newRegionPlan = am.regionPlans.get(REGIONINFO.getEncodedName());
}
// the new region plan created may contain the same RS as destination but
// it should
// be new plan.
assertNotSame("Same region plan should not come", regionPlan,
newRegionPlan);
assertTrue("Destnation servers should be different.", !(regionPlan
.getDestination().equals(newRegionPlan.getDestination())));
} finally {
this.server.getConfiguration().setClass(
HConstants.HBASE_MASTER_LOADBALANCER_CLASS, DefaultLoadBalancer.class,
LoadBalancer.class);
}
ZKAssign.createNodeOffline(this.watcher, REGIONINFO, SERVERNAME_A);
int v = ZKAssign.getVersion(this.watcher, REGIONINFO);
ZKAssign.transitionNode(this.watcher, REGIONINFO, SERVERNAME_A, EventType.M_ZK_REGION_OFFLINE,
EventType.RS_ZK_REGION_FAILED_OPEN, v);
String path = ZKAssign.getNodeName(this.watcher, REGIONINFO.getEncodedName());
RegionState state = new RegionState(REGIONINFO, State.OPENING, System.currentTimeMillis(),
SERVERNAME_A);
am.regionsInTransition.put(REGIONINFO.getEncodedName(), state);
// a dummy plan inserted into the regionPlans. This plan is cleared and new one is formed
am.regionPlans.put(REGIONINFO.getEncodedName(), new RegionPlan(REGIONINFO, null, SERVERNAME_A));
RegionPlan regionPlan = am.regionPlans.get(REGIONINFO.getEncodedName());
List<ServerName> serverList = new ArrayList<ServerName>(2);
serverList.add(SERVERNAME_B);
Mockito.when(this.serverManager.createDestinationServersList(SERVERNAME_A)).thenReturn(serverList);
am.nodeDataChanged(path);
// here we are waiting until the random assignment in the load balancer is called.
while (!gate.get()) {
Thread.sleep(10);
}
// new region plan may take some time to get updated after random assignment is called and
// gate is set to true.
RegionPlan newRegionPlan = am.regionPlans.get(REGIONINFO.getEncodedName());
while (newRegionPlan == null) {
Thread.sleep(10);
newRegionPlan = am.regionPlans.get(REGIONINFO.getEncodedName());
}
// the new region plan created may contain the same RS as destination but it should
// be new plan.
assertNotSame("Same region plan should not come", regionPlan, newRegionPlan);
assertTrue("Destnation servers should be different.", !(regionPlan.getDestination().equals(
newRegionPlan.getDestination())));
}
/**
@ -676,6 +695,35 @@ public class TestAssignmentManager {
}
}
/**
* 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<ServerName, List<Pair<HRegionInfo, Result>>> deadServers =
new HashMap<ServerName, List<Pair<HRegionInfo, Result>>>();
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 +858,13 @@ public class TestAssignmentManager {
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;