/** This tests offlining a entityGroup */
  @Test(timeout = 120000)
  public void testOfflineEntityGroup() throws Exception {
    String table = "testOfflineEntityGroup";
    try {
      EntityGroupInfo egInfo = createTableAndGetOneEntityGroup(table);

      EntityGroupStates entityGroupStates =
          TEST_UTIL.getWaspCluster().getMaster().getAssignmentManager().getEntityGroupStates();
      ServerName serverName = entityGroupStates.getFServerOfEntityGroup(egInfo);
      TEST_UTIL.assertEntityGroupOnServer(egInfo, serverName, 200);
      admin.offline(egInfo.getEntityGroupName());

      long timeoutTime = System.currentTimeMillis() + 800;
      while (true) {
        List<EntityGroupInfo> entityGroups =
            entityGroupStates.getEntityGroupsOfTable(Bytes.toBytes(table));
        if (!entityGroups.contains(egInfo)) break;
        long now = System.currentTimeMillis();
        if (now > timeoutTime) {
          fail("Failed to offline the entityGroup in time");
          break;
        }
        Thread.sleep(10);
      }
      EntityGroupState entityGroupState = entityGroupStates.getEntityGroupState(egInfo);
      assertTrue(entityGroupState.isOffline());
    } finally {
      TEST_UTIL.deleteTable(Bytes.toBytes(table));
    }
  }
  @Test
  public void testOpenedEntityGroupHandlerOnMasterRestart() throws Exception {
    // Start the cluster
    log("Starting cluster");
    TEST_UTIL.getConfiguration().setInt("wasp.master.assignment.timeoutmonitor.period", 2000);
    TEST_UTIL.getConfiguration().setInt("wasp.master.assignment.timeoutmonitor.timeout", 5000);
    TEST_UTIL.startMiniCluster(NUM_MASTERS, NUM_FServer);
    String tableName = "testOpenedEntityGroupHandlerOnMasterRestart";
    MiniWaspCluster cluster = createEntityGroups(tableName);
    abortMaster(cluster);

    FServer entityGroupServer = cluster.getFServer(0);
    EntityGroup entityGroup = getEntityGroupBeingServed(cluster, entityGroupServer);

    // forcefully move a entityGroup to OPENED state in zk
    // Create a ZKW to use in the test
    zkw =
        WaspTestingUtility.createAndForceNodeToOpenedState(
            TEST_UTIL, entityGroup, entityGroupServer.getServerName());

    // Start up a new master
    log("Starting up a new master");
    cluster.startMaster().getMaster();
    log("Waiting for master to be ready");
    cluster.waitForActiveAndReadyMaster();
    log("Master is ready");

    // Failover should be completed, now wait for no RIT
    log("Waiting for no more RIT");
    ZKAssign.blockUntilNoRIT(zkw);
  }
  private MiniWaspCluster createEntityGroups(String tableName)
      throws InterruptedException, ZooKeeperConnectionException, IOException, KeeperException {
    MiniWaspCluster cluster = TEST_UTIL.getWaspCluster();
    log("Waiting for active/ready master");
    cluster.waitForActiveAndReadyMaster();
    zkw = new ZooKeeperWatcher(TEST_UTIL.getConfiguration(), "testOpenedEntityGroupHandler", null);

    // Create a table with entityGroups
    byte[] table = Bytes.toBytes(tableName);
    byte[] family = Bytes.toBytes("family");
    TEST_UTIL.createTable(table);

    // wait till the entityGroups are online
    log("Waiting for no more RIT");
    ZKAssign.blockUntilNoRIT(zkw);

    return cluster;
  }
 /** This tests entityGroup assignment */
 @Test(timeout = 120000)
 public void testAssignEntityGroup() throws Exception {
   String table = "testAssignEntityGroup";
   try {
     FTable desc = FMetaTestUtil.makeTable(table);
     admin.createTable(desc);
     EntityGroupInfo egInfo =
         new EntityGroupInfo(
             Bytes.toBytes(desc.getTableName()), Bytes.toBytes("A"), Bytes.toBytes("Z"));
     FMetaEditor.addEntityGroupToMeta(conf, egInfo);
     FMaster master = TEST_UTIL.getWaspCluster().getMaster();
     master.assignEntityGroup(egInfo);
     master.getAssignmentManager().waitForAssignment(egInfo);
     ServerName serverName =
         master.getAssignmentManager().getEntityGroupStates().getFServerOfEntityGroup(egInfo);
     TEST_UTIL.assertEntityGroupOnServer(egInfo, serverName, 200);
   } finally {
     TEST_UTIL.deleteTable(Bytes.toBytes(table));
   }
 }
  /** This tests moving a entityGroup */
  @Test(timeout = 120000)
  public void testMoveEntityGroup() throws Exception {
    String table = "testMoveEntityGroup";
    try {
      EntityGroupInfo egInfo = createTableAndGetOneEntityGroup(table);

      EntityGroupStates entityGroupStates =
          TEST_UTIL.getWaspCluster().getMaster().getAssignmentManager().getEntityGroupStates();
      ServerName serverName = entityGroupStates.getFServerOfEntityGroup(egInfo);
      ServerName destServerName = null;
      for (int i = 0; i < 3; i++) {
        FServer destServer = TEST_UTIL.getWaspCluster().getFServer(i);
        if (!destServer.getServerName().equals(serverName)) {
          destServerName = destServer.getServerName();
          break;
        }
      }
      assertTrue(destServerName != null && !destServerName.equals(serverName));
      TEST_UTIL
          .getWaspAdmin()
          .move(egInfo.getEncodedNameAsBytes(), Bytes.toBytes(destServerName.getServerName()));

      long timeoutTime = System.currentTimeMillis() + 5000;
      while (true) {
        ServerName sn = entityGroupStates.getFServerOfEntityGroup(egInfo);
        if (sn != null && sn.equals(destServerName)) {
          TEST_UTIL.assertEntityGroupOnServer(egInfo, sn, 2000);
          break;
        }
        long now = System.currentTimeMillis();
        if (now > timeoutTime) {
          fail("Failed to move the entityGroup in time");
        }
        entityGroupStates.waitForUpdate(50);
      }

    } finally {
      TEST_UTIL.deleteTable(Bytes.toBytes(table));
    }
  }
  EntityGroupInfo createTableAndGetOneEntityGroup(final String tableName)
      throws IOException, InterruptedException {
    FTable desc = FMetaTestUtil.makeTable(tableName);
    admin.createTable(desc, Bytes.toBytes("A"), Bytes.toBytes("Z"), 5);

    // wait till the table is assigned
    FMaster master = TEST_UTIL.getWaspCluster().getMaster();
    long timeoutTime = System.currentTimeMillis() + 100;
    while (true) {
      List<EntityGroupInfo> entityGroups =
          master
              .getAssignmentManager()
              .getEntityGroupStates()
              .getEntityGroupsOfTable(Bytes.toBytes(tableName));
      if (entityGroups.size() > 3) {
        return entityGroups.get(2);
      }
      long now = System.currentTimeMillis();
      if (now > timeoutTime) {
        fail("Could not find an online entityGroup");
      }
      Thread.sleep(10);
    }
  }
 @AfterClass
 public static void tearDownAfterClass() throws Exception {
   TEST_UTIL.shutdownMiniCluster();
 }
 @BeforeClass
 public static void setUpBeforeClass() throws Exception {
   TEST_UTIL.getConfiguration().setClass(FConstants.REDO_IMPL, MemRedoLog.class, Redo.class);
   TEST_UTIL.startMiniCluster(3);
   admin = TEST_UTIL.getWaspAdmin();
 }
public class TestAssignmentManagerOnCluster {
  private static final WaspTestingUtility TEST_UTIL = new WaspTestingUtility();
  private static final Configuration conf = TEST_UTIL.getConfiguration();
  private static WaspAdmin admin;

  @BeforeClass
  public static void setUpBeforeClass() throws Exception {
    TEST_UTIL.getConfiguration().setClass(FConstants.REDO_IMPL, MemRedoLog.class, Redo.class);
    TEST_UTIL.startMiniCluster(3);
    admin = TEST_UTIL.getWaspAdmin();
  }

  @AfterClass
  public static void tearDownAfterClass() throws Exception {
    TEST_UTIL.shutdownMiniCluster();
  }

  /** This tests entityGroup assignment */
  @Test(timeout = 120000)
  public void testAssignEntityGroup() throws Exception {
    String table = "testAssignEntityGroup";
    try {
      FTable desc = FMetaTestUtil.makeTable(table);
      admin.createTable(desc);
      EntityGroupInfo egInfo =
          new EntityGroupInfo(
              Bytes.toBytes(desc.getTableName()), Bytes.toBytes("A"), Bytes.toBytes("Z"));
      FMetaEditor.addEntityGroupToMeta(conf, egInfo);
      FMaster master = TEST_UTIL.getWaspCluster().getMaster();
      master.assignEntityGroup(egInfo);
      master.getAssignmentManager().waitForAssignment(egInfo);
      ServerName serverName =
          master.getAssignmentManager().getEntityGroupStates().getFServerOfEntityGroup(egInfo);
      TEST_UTIL.assertEntityGroupOnServer(egInfo, serverName, 200);
    } finally {
      TEST_UTIL.deleteTable(Bytes.toBytes(table));
    }
  }

  /** This tests offlining a entityGroup */
  @Test(timeout = 120000)
  public void testOfflineEntityGroup() throws Exception {
    String table = "testOfflineEntityGroup";
    try {
      EntityGroupInfo egInfo = createTableAndGetOneEntityGroup(table);

      EntityGroupStates entityGroupStates =
          TEST_UTIL.getWaspCluster().getMaster().getAssignmentManager().getEntityGroupStates();
      ServerName serverName = entityGroupStates.getFServerOfEntityGroup(egInfo);
      TEST_UTIL.assertEntityGroupOnServer(egInfo, serverName, 200);
      admin.offline(egInfo.getEntityGroupName());

      long timeoutTime = System.currentTimeMillis() + 800;
      while (true) {
        List<EntityGroupInfo> entityGroups =
            entityGroupStates.getEntityGroupsOfTable(Bytes.toBytes(table));
        if (!entityGroups.contains(egInfo)) break;
        long now = System.currentTimeMillis();
        if (now > timeoutTime) {
          fail("Failed to offline the entityGroup in time");
          break;
        }
        Thread.sleep(10);
      }
      EntityGroupState entityGroupState = entityGroupStates.getEntityGroupState(egInfo);
      assertTrue(entityGroupState.isOffline());
    } finally {
      TEST_UTIL.deleteTable(Bytes.toBytes(table));
    }
  }

  /** This tests moving a entityGroup */
  @Test(timeout = 120000)
  public void testMoveEntityGroup() throws Exception {
    String table = "testMoveEntityGroup";
    try {
      EntityGroupInfo egInfo = createTableAndGetOneEntityGroup(table);

      EntityGroupStates entityGroupStates =
          TEST_UTIL.getWaspCluster().getMaster().getAssignmentManager().getEntityGroupStates();
      ServerName serverName = entityGroupStates.getFServerOfEntityGroup(egInfo);
      ServerName destServerName = null;
      for (int i = 0; i < 3; i++) {
        FServer destServer = TEST_UTIL.getWaspCluster().getFServer(i);
        if (!destServer.getServerName().equals(serverName)) {
          destServerName = destServer.getServerName();
          break;
        }
      }
      assertTrue(destServerName != null && !destServerName.equals(serverName));
      TEST_UTIL
          .getWaspAdmin()
          .move(egInfo.getEncodedNameAsBytes(), Bytes.toBytes(destServerName.getServerName()));

      long timeoutTime = System.currentTimeMillis() + 5000;
      while (true) {
        ServerName sn = entityGroupStates.getFServerOfEntityGroup(egInfo);
        if (sn != null && sn.equals(destServerName)) {
          TEST_UTIL.assertEntityGroupOnServer(egInfo, sn, 2000);
          break;
        }
        long now = System.currentTimeMillis();
        if (now > timeoutTime) {
          fail("Failed to move the entityGroup in time");
        }
        entityGroupStates.waitForUpdate(50);
      }

    } finally {
      TEST_UTIL.deleteTable(Bytes.toBytes(table));
    }
  }

  EntityGroupInfo createTableAndGetOneEntityGroup(final String tableName)
      throws IOException, InterruptedException {
    FTable desc = FMetaTestUtil.makeTable(tableName);
    admin.createTable(desc, Bytes.toBytes("A"), Bytes.toBytes("Z"), 5);

    // wait till the table is assigned
    FMaster master = TEST_UTIL.getWaspCluster().getMaster();
    long timeoutTime = System.currentTimeMillis() + 100;
    while (true) {
      List<EntityGroupInfo> entityGroups =
          master
              .getAssignmentManager()
              .getEntityGroupStates()
              .getEntityGroupsOfTable(Bytes.toBytes(tableName));
      if (entityGroups.size() > 3) {
        return entityGroups.get(2);
      }
      long now = System.currentTimeMillis();
      if (now > timeoutTime) {
        fail("Could not find an online entityGroup");
      }
      Thread.sleep(10);
    }
  }
}
 @After
 public void tearDown() throws Exception {
   // Stop the cluster
   TEST_UTIL.shutdownMiniCluster();
   TEST_UTIL = new WaspTestingUtility();
 }
 @Before
 public void setUp() throws Exception {
   TEST_UTIL = new WaspTestingUtility();
   TEST_UTIL.getConfiguration().setClass(FConstants.REDO_IMPL, MemRedoLog.class, Redo.class);
 }
  @Test
  public void testShouldNotCompeleteOpenedEntityGroupSuccessfullyIfVersionMismatches()
      throws Exception {
    EntityGroup entityGroup = null;
    try {
      int testIndex = 0;
      TEST_UTIL.getHBaseTestingUtility().startMiniZKCluster();
      TEST_UTIL
          .getConfiguration()
          .set(
              FConstants.ZOOKEEPER_QUORUM,
              TEST_UTIL.getConfiguration().get(HConstants.ZOOKEEPER_QUORUM));
      TEST_UTIL
          .getConfiguration()
          .set(
              FConstants.ZOOKEEPER_CLIENT_PORT,
              TEST_UTIL.getConfiguration().get(HConstants.ZOOKEEPER_CLIENT_PORT));
      final Server server = new MockServer(TEST_UTIL);
      FTable htd =
          FMetaTestUtil.makeTable(
              "testShouldNotCompeleteOpenedEntityGroupSuccessfullyIfVersionMismatches");
      EntityGroupInfo egi =
          new EntityGroupInfo(
              Bytes.toBytes(htd.getTableName()),
              Bytes.toBytes(testIndex),
              Bytes.toBytes(testIndex + 1));
      entityGroup = EntityGroup.createEntityGroup(egi, TEST_UTIL.getConfiguration(), htd, null);
      assertNotNull(entityGroup);
      AssignmentManager am = Mockito.mock(AssignmentManager.class);
      EntityGroupStates rsm = Mockito.mock(EntityGroupStates.class);
      Mockito.doReturn(rsm).when(am).getEntityGroupStates();
      when(rsm.isEntityGroupInTransition(egi)).thenReturn(false);
      when(rsm.getEntityGroupState(egi))
          .thenReturn(
              new EntityGroupState(
                  entityGroup.getEntityGroupInfo(),
                  EntityGroupState.State.OPEN,
                  System.currentTimeMillis(),
                  server.getServerName()));
      // create a node with OPENED state
      zkw =
          WaspTestingUtility.createAndForceNodeToOpenedState(
              TEST_UTIL, entityGroup, server.getServerName());
      when(am.getZKTable()).thenReturn(new ZKTable(zkw));
      Stat stat = new Stat();
      String nodeName =
          ZKAssign.getNodeName(zkw, entityGroup.getEntityGroupInfo().getEncodedName());
      ZKUtil.getDataAndWatch(zkw, nodeName, stat);

      // use the version for the OpenedEntityGroupHandler
      OpenedEntityGroupHandler handler =
          new OpenedEntityGroupHandler(
              server,
              am,
              entityGroup.getEntityGroupInfo(),
              server.getServerName(),
              stat.getVersion());
      // Once again overwrite the same znode so that the version changes.
      ZKAssign.transitionNode(
          zkw,
          entityGroup.getEntityGroupInfo(),
          server.getServerName(),
          EventType.FSERVER_ZK_ENTITYGROUP_OPENED,
          EventType.FSERVER_ZK_ENTITYGROUP_OPENED,
          stat.getVersion());

      // Should not invoke assignmentmanager.entityGroupOnline. If it is
      // invoked as per current mocking it will throw null pointer exception.
      boolean expectedException = false;
      try {
        handler.process();
      } catch (Exception e) {
        expectedException = true;
      }
      assertFalse("The process method should not throw any exception.", expectedException);
      List<String> znodes = ZKUtil.listChildrenAndWatchForNewChildren(zkw, zkw.assignmentZNode);
      String entityGroupName = znodes.get(0);
      assertEquals(
          "The entityGroup should not be opened successfully.",
          entityGroupName,
          entityGroup.getEntityGroupInfo().getEncodedName());
    } finally {
      EntityGroup.closeEntityGroup(entityGroup);
      TEST_UTIL.getHBaseTestingUtility().shutdownMiniZKCluster();
    }
  }