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:
parent
683c005fca
commit
2cac550467
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue