package org.goldenorb.server; import static org.junit.Assert.*; import java.util.List; import java.util.concurrent.CountDownLatch; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.ZooKeeper; import org.goldenorb.client.NodeDoesNotExistException; import org.goldenorb.client.OrbTrackerMemberData; import org.goldenorb.client.WatcherException; import org.goldenorb.client.ZooKeeperConnectionException; import org.goldenorb.conf.OrbConfiguration; import org.goldenorb.jet.OrbTrackerMember; import org.goldenorb.zookeeper.OrbZKFailure; import org.goldenorb.zookeeper.ZookeeperUtils; import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; public class TestOrbTrackerMemberDataServiceImpl { private static ZooKeeper zk; private static String jobQueuePath; private static String jobsInProgressPath; private static String leaderGroupPath; @BeforeClass public static void setUpBeforeClass() throws Exception { OrbConfiguration orbConf = new OrbConfiguration(true); orbConf.setOrbZooKeeperQuorum("localhost:21810"); zk = ZookeeperUtils.connect(orbConf.getOrbZooKeeperQuorum()); ZookeeperUtils.tryToCreateNode(zk, "/GoldenOrb"); ZookeeperUtils.tryToCreateNode(zk, "/GoldenOrb/" + orbConf.getOrbClusterName()); ZookeeperUtils.tryToCreateNode(zk, "/GoldenOrb/" + orbConf.getOrbClusterName() + "/JobsInProgress"); ZookeeperUtils.tryToCreateNode(zk, "/GoldenOrb/" + orbConf.getOrbClusterName() + "/JobQueue"); ZookeeperUtils .tryToCreateNode(zk, "/GoldenOrb/" + orbConf.getOrbClusterName() + "/OrbTrackerLeaderGroup"); jobsInProgressPath = "/GoldenOrb/" + orbConf.getOrbClusterName() + "/JobsInProgress"; jobQueuePath = "/GoldenOrb/" + orbConf.getOrbClusterName() + "/JobQueue"; leaderGroupPath = "/GoldenOrb/" + orbConf.getOrbClusterName() + "/OrbTrackerLeaderGroup"; } @AfterClass public static void tearDownAfterClass() throws Exception { ZookeeperUtils.recursiveDelete(zk, "/GoldenOrb"); ZookeeperUtils.deleteNodeIfEmpty(zk, "/GoldenOrb"); } @After public void tearDown() throws Exception { ZookeeperUtils.recursiveDelete(zk, jobsInProgressPath); ZookeeperUtils.recursiveDelete(zk, jobQueuePath); ZookeeperUtils.recursiveDelete(zk, leaderGroupPath); } @Test public void testGetOrbTrackerMemberData() throws OrbZKFailure, ZooKeeperConnectionException, WatcherException, NodeDoesNotExistException, InterruptedException, KeeperException { int num_nodes = 10; OrbTrackerMember[] members = new OrbTrackerMember[num_nodes]; for (int i = 0; i < num_nodes; i++) { members[i] = new OrbTrackerMember(); members[i].setAvailablePartitions(i); members[i].setHostname("host"); members[i].setInUsePartitions(i); members[i].setLeader(false); members[i].setPartitionCapacity(i); members[i].setPort(i); members[i].setReservedPartitions(i); ZookeeperUtils.tryToCreateNode(zk, leaderGroupPath + "/member", members[i], CreateMode.EPHEMERAL_SEQUENTIAL); } OrbTrackerMemberDataServiceImpl server = new OrbTrackerMemberDataServiceImpl(); CountDownLatch jobs = new CountDownLatch(1); CountDownLatch update = new CountDownLatch(num_nodes); CountDownLatch remove = new CountDownLatch(3); server.enterTestingMode(jobs, remove, update); OrbTrackerMemberData[] memberData = server.getOrbTrackerMemberData(); update.await(); List<String> nodes = zk.getChildren(leaderGroupPath, false); assertEquals(nodes.size(), memberData.length); update = new CountDownLatch(2); server.setUpdateLatch(update); for (int i = 0; i < 2; i++) { members[i] = new OrbTrackerMember(); members[i].setAvailablePartitions(i); members[i].setHostname("host"); members[i].setInUsePartitions(i); members[i].setLeader(false); members[i].setPartitionCapacity(i); members[i].setPort(i); members[i].setReservedPartitions(i); ZookeeperUtils.tryToCreateNode(zk, leaderGroupPath + "/member", members[i], CreateMode.EPHEMERAL_SEQUENTIAL); } update.await(); memberData = server.getOrbTrackerMemberData(); nodes = zk.getChildren(leaderGroupPath, false); assertEquals(nodes.size(), memberData.length); remove = new CountDownLatch(4); server.setRemoveLatch(remove); int i = 0; for (String node : nodes) { if (i < 4) { ZookeeperUtils.deleteNodeIfEmpty(zk, leaderGroupPath + "/" + node); } i++; } remove.await(); memberData = server.getOrbTrackerMemberData(); nodes = zk.getChildren(leaderGroupPath, false); assertEquals(nodes.size(), memberData.length); } @Test public void testGetJobsInQueue() throws OrbZKFailure, NodeDoesNotExistException, ZooKeeperConnectionException, WatcherException, InterruptedException, KeeperException { OrbTrackerMemberDataServiceImpl server = new OrbTrackerMemberDataServiceImpl(); int num_jobs = 10; CountDownLatch jobsLatch = new CountDownLatch(1); CountDownLatch updateLatch = new CountDownLatch(1); CountDownLatch removeLatch = new CountDownLatch(1); server.enterTestingMode(jobsLatch, removeLatch, updateLatch); for (int i = 0; i < num_jobs; i++) { ZookeeperUtils.tryToCreateNode(zk, jobQueuePath + "/job", CreateMode.EPHEMERAL_SEQUENTIAL); } String[] job = server.getJobsInQueue(); // initialize watcher jobsLatch.await(); List<String> nodes = zk.getChildren(jobQueuePath, false); job = server.getJobsInQueue(); assertEquals(nodes.size(), job.length); jobsLatch = new CountDownLatch(3); server.setJobsLatch(jobsLatch); for (int i = 0; i < 3; i++) { ZookeeperUtils.tryToCreateNode(zk, jobQueuePath + "/job", CreateMode.EPHEMERAL_SEQUENTIAL); Thread.sleep(5); // Need to make the number of watcher events deterministic } jobsLatch.await(); nodes = zk.getChildren(jobQueuePath, false); job = server.getJobsInQueue(); assertEquals(nodes.size(), job.length); jobsLatch = new CountDownLatch(5); server.setJobsLatch(jobsLatch); for (int i = 0; i < 5; i++) { ZookeeperUtils.deleteNodeIfEmpty(zk, jobQueuePath + "/" + nodes.get(i)); Thread.sleep(5); // Need to make the number of watcher events deterministic } jobsLatch.await(); nodes = zk.getChildren(jobQueuePath, false); job = server.getJobsInQueue(); assertEquals(nodes.size(), job.length); } @Test public void testGetJobsInProgress() throws OrbZKFailure, NodeDoesNotExistException, ZooKeeperConnectionException, WatcherException, InterruptedException, KeeperException { OrbTrackerMemberDataServiceImpl server = new OrbTrackerMemberDataServiceImpl(); int num_jobs = 10; CountDownLatch jobsLatch = new CountDownLatch(1); CountDownLatch updateLatch = new CountDownLatch(1); CountDownLatch removeLatch = new CountDownLatch(1); server.enterTestingMode(jobsLatch, removeLatch, updateLatch); for (int i = 0; i < num_jobs; i++) { ZookeeperUtils.tryToCreateNode(zk, jobsInProgressPath + "/job", CreateMode.EPHEMERAL_SEQUENTIAL); } String[] job = server.getJobsInProgress(); // initialize watcher jobsLatch.await(); List<String> nodes = zk.getChildren(jobsInProgressPath, false); job = server.getJobsInProgress(); assertEquals(nodes.size(), job.length); jobsLatch = new CountDownLatch(3); server.setJobsLatch(jobsLatch); for (int i = 0; i < 3; i++) { ZookeeperUtils.tryToCreateNode(zk, jobsInProgressPath + "/job", CreateMode.EPHEMERAL_SEQUENTIAL); Thread.sleep(5); // Need to make the number of watcher events deterministic } jobsLatch.await(); nodes = zk.getChildren(jobsInProgressPath, false); job = server.getJobsInProgress(); assertEquals(nodes.size(), job.length); jobsLatch = new CountDownLatch(5); server.setJobsLatch(jobsLatch); for (int i = 0; i < 5; i++) { ZookeeperUtils.deleteNodeIfEmpty(zk, jobsInProgressPath + "/" + nodes.get(i)); Thread.sleep(5); // Need to make the number of watcher events deterministic } jobsLatch.await(); nodes = zk.getChildren(jobsInProgressPath, false); job = server.getJobsInProgress(); assertEquals(nodes.size(), job.length); } @Test public void testEveryThingChangingAtOnce() throws NodeDoesNotExistException, ZooKeeperConnectionException, WatcherException, InterruptedException, KeeperException { CountDownLatch start = new CountDownLatch(1); CountDownLatch allDone = new CountDownLatch(3); int cycles = 10; MemberThread[] threads = new MemberThread[3]; for (int i = 0; i < 3; i++) { threads[i] = new MemberThread(i, cycles, start, allDone); threads[i].start(); } OrbTrackerMemberDataServiceImpl server = new OrbTrackerMemberDataServiceImpl(); // initialize watchers CountDownLatch notUsed = new CountDownLatch(1); server.enterTestingMode(notUsed, notUsed, notUsed); String[] jobQueue = server.getJobsInQueue(); String[] jobsInProgress = server.getJobsInProgress(); OrbTrackerMemberData[] members = server.getOrbTrackerMemberData(); System.out.println("Start"); start.countDown(); allDone.await(); List<String> mem = zk.getChildren(leaderGroupPath, false); List<String> jq = zk.getChildren(jobQueuePath, false); List<String> jip = zk.getChildren(jobsInProgressPath, false); jobQueue = server.getJobsInQueue(); jobsInProgress = server.getJobsInProgress(); members = server.getOrbTrackerMemberData(); assertEquals(mem.size(), members.length); assertEquals(jq.size(), jobQueue.length); assertEquals(jip.size(), jobsInProgress.length); } public void createMember(int i) throws OrbZKFailure { OrbTrackerMember otm = new OrbTrackerMember(); otm.setAvailablePartitions(i); otm.setHostname("host"); otm.setInUsePartitions(i); otm.setLeader(false); otm.setPartitionCapacity(i); otm.setPort(i); otm.setReservedPartitions(i); ZookeeperUtils.tryToCreateNode(zk, leaderGroupPath, otm, CreateMode.EPHEMERAL_SEQUENTIAL); } public void createJob(String path) throws OrbZKFailure { ZookeeperUtils.tryToCreateNode(zk, path + "/job", CreateMode.EPHEMERAL_SEQUENTIAL); } public void deleteNode(String path) throws KeeperException, InterruptedException, OrbZKFailure { List<String> nodes = zk.getChildren(path, false); int num = (int) (nodes.size() * Math.random()); int counter = 0; for (String node : nodes) { if (counter < num) { ZookeeperUtils.deleteNodeIfEmpty(zk, path + "/" + node); } } } public class MemberThread extends Thread { private int cycles; private CountDownLatch start; private CountDownLatch complete; private int type; public MemberThread(int type, int cycles, CountDownLatch start, CountDownLatch complete) { this.cycles = cycles; this.start = start; this.complete = complete; this.type = type; } public void run() { try { start.await(); int num = 0; for (int i = 0; i < cycles; i++) { if (i % 2 == 0) { if (i == 0) { num = 10; } else { num = (int) (Math.random() * 10); } for (int j = 0; j < num; j++) { if (type == 0) { createMember(i); } if (type == 1) { createJob(jobsInProgressPath); } else { createJob(jobQueuePath); } } } else { if (type == 0) { deleteNode(leaderGroupPath); } else if (type == 1) { deleteNode(jobsInProgressPath); } else { deleteNode(jobQueuePath); } } } complete.countDown(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (OrbZKFailure e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (KeeperException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }