@Test
public void testBalance() throws IOException, KeeperException,
DeserializationException, InterruptedException {
// Create and startup an executor. This is used by AssignmentManager
// handling zk callbacks.
ExecutorService executor = startupMasterExecutor("testBalanceExecutor");
// We need a mocked catalog tracker.
LoadBalancer balancer = LoadBalancerFactory.getLoadBalancer(server
.getConfiguration());
// Create an AM.
AssignmentManager am = new AssignmentManager(this.server,
this.serverManager, balancer, executor, null);
am.failoverCleanupDone.set(true);
try {
// Make sure our new AM gets callbacks; once registered, can't unregister.
// Thats ok because we make a new zk watcher for each test.
this.watcher.registerListenerFirst(am);
// Call the balance function but fake the entityGroup being online first
// at
// SERVERNAME_A. Create a balance plan.
am.entityGroupOnline(ENTITYGROUPINFO, SERVERNAME_A);
// Balance entityGroup from A to B.
EntityGroupPlan plan = new EntityGroupPlan(ENTITYGROUPINFO, SERVERNAME_A,
SERVERNAME_B);
am.balance(plan);
// Now fake the entityGroup closing successfully over on the fserver; the
// fserver will have set the entityGroup in CLOSED state. This will
// trigger callback into AM. The below zk close call is from the FSERVER
// close
// entityGroup handler duplicated here because its down deep in a private
// method hard to expose.
int versionid = ZKAssign.transitionNodeClosed(this.watcher,
ENTITYGROUPINFO, SERVERNAME_A, -1);
assertNotSame(versionid, -1);
// AM is going to notice above CLOSED and queue up a new assign. The
// assign will go to open the entityGroup in the new location set by the
// balancer. The zk node will be OFFLINE waiting for fserver to
// transition it through OPENING, OPENED. Wait till we see the OFFLINE
// zk node before we proceed.
Mocking.waitForEntityGroupPendingOpenInRIT(am,
ENTITYGROUPINFO.getEncodedName());
// Get current versionid else will fail on transition from OFFLINE to
// OPENING below
versionid = ZKAssign.getVersion(this.watcher, ENTITYGROUPINFO);
assertNotSame(-1, versionid);
// This uglyness below is what the openentityGrouphandler on FSERVER side
// does.
versionid = ZKAssign.transitionNode(server.getZooKeeper(),
ENTITYGROUPINFO, SERVERNAME_A, EventHandler.EventType.M_ZK_ENTITYGROUP_OFFLINE,
EventHandler.EventType.FSERVER_ZK_ENTITYGROUP_OPENING, versionid);
assertNotSame(-1, versionid);
// Move znode from OPENING to OPENED as FSERVER does on successful open.
versionid = ZKAssign.transitionNodeOpened(this.watcher, ENTITYGROUPINFO,
SERVERNAME_B, versionid);
assertNotSame(-1, versionid);
// Wait on the handler removing the OPENED znode.
while (am.getEntityGroupStates().isEntityGroupInTransition(
ENTITYGROUPINFO))
Threads.sleep(1);
} finally {
executor.shutdown();
am.shutdown();
// Clean up all znodes
ZKAssign.deleteAllNodes(this.watcher);
}
}