@Override
 public synchronized boolean handleStartElectionRequest(L2StateMessage msg) {
   Assert.assertEquals(L2StateMessage.START_ELECTION, msg.getType());
   if (state == ELECTION_IN_PROGRESS
       && (myVote.isANewCandidate() || !msg.getEnrollment().isANewCandidate())) {
     // Another node is also joining in the election process, Cast its vote and notify my vote
     // Note : WE dont want to do this for new candidates when we are not new.
     Enrollment vote = msg.getEnrollment();
     Enrollment old = votes.put(vote.getNodeID(), vote);
     boolean sendResponse = msg.inResponseTo().isNull();
     if (old != null && !vote.equals(old)) {
       logger.warn(
           "Received duplicate vote : Replacing with new one : " + vote + " old one : " + old);
       sendResponse = true;
     }
     if (sendResponse) {
       // This is either not a response to this node initiating election or a duplicate vote.
       // Either case notify this
       // nodes vote
       L2StateMessage response = createElectionStartedMessage(msg, myVote);
       logger.info("Casted vote from " + msg + " My Response : " + response);
       try {
         groupManager.sendTo(msg.messageFrom(), response);
       } catch (GroupException e) {
         logger.error("Error sending Votes to : " + msg.messageFrom(), e);
       }
     } else {
       logger.info("Casted vote from " + msg);
     }
     return true;
   } else {
     logger.info("Ignoring Start Election Request  : " + msg + " My state = " + state);
     return false;
   }
 }
 /** This method is called by the winner of the election to announce to the world */
 @Override
 public synchronized void declareWinner(NodeID myNodeId) {
   Assert.assertEquals(winner.getNodeID(), myNodeId);
   L2StateMessage msg = createElectionWonMessage(this.winner);
   debugInfo("Announcing as winner: " + myNodeId);
   this.groupManager.sendAll(msg);
   logger.info("Declared as Winner: Winner is : " + this.winner);
   reset(winner);
 }
 private synchronized void handleElectionWonMessage(L2StateMessage clusterMsg) {
   debugInfo("Received election_won or election_already_won msg: " + clusterMsg);
   Enrollment winningEnrollment = clusterMsg.getEnrollment();
   if (state == ACTIVE_COORDINATOR) {
     // Can't get Election Won from another node : Split brain
     String error =
         state
             + " Received Election Won Msg : "
             + clusterMsg
             + ". A Terracotta server tried to join the mirror group as a second ACTIVE";
     logger.error(error);
     if (clusterMsg.getType() == L2StateMessage.ELECTION_WON_ALREADY) {
       sendNGResponse(clusterMsg.messageFrom(), clusterMsg);
     }
     groupManager.zapNode(
         winningEnrollment.getNodeID(), L2HAZapNodeRequestProcessor.SPLIT_BRAIN, error);
   } else if (activeNode.isNull()
       || activeNode.equals(winningEnrollment.getNodeID())
       || clusterMsg.getType() == L2StateMessage.ELECTION_WON) {
     // There is no active server for this node or the other node just detected a failure of ACTIVE
     // server and ran an
     // election and is sending the results. This can happen if this node for some reason is not
     // able to detect that
     // the active is down but the other node did. Go with the new active.
     setActiveNodeID(winningEnrollment.getNodeID());
     moveToPassiveState(winningEnrollment);
     if (clusterMsg.getType() == L2StateMessage.ELECTION_WON_ALREADY) {
       sendOKResponse(clusterMsg.messageFrom(), clusterMsg);
     }
   } else {
     // This is done to solve DEV-1532. Node sent ELECTION_WON_ALREADY message but our ACTIVE is
     // intact.
     logger.warn(
         "Conflicting Election Won  Msg : "
             + clusterMsg
             + " since I already have a ACTIVE Node : "
             + activeNode
             + ". Sending NG response");
     // The reason we send a response for ELECTION_WON_ALREADY message is that if we don't agree we
     // don't want the
     // other server to send us cluster state messages.
     sendNGResponse(clusterMsg.messageFrom(), clusterMsg);
   }
 }
 private synchronized void electionStarted(Enrollment e) {
   if (this.state == ELECTION_IN_PROGRESS) {
     throw new AssertionError("Election Already in Progress");
   }
   this.state = ELECTION_IN_PROGRESS;
   this.myVote = e;
   this.winner = null;
   this.votes.clear();
   this.votes.put(e.getNodeID(), e); // Cast my vote
   logger.info("Election Started : " + e);
 }
  private NodeID doElection(NodeID myNodeId, boolean isNew, WeightGeneratorFactory weightsFactory)
      throws GroupException, InterruptedException {

    // Step 1: publish to cluster NodeID, weight and election start
    Enrollment e = EnrollmentFactory.createEnrollment(myNodeId, isNew, weightsFactory);
    electionStarted(e);

    L2StateMessage msg = createElectionStartedMessage(e);
    debugInfo("Sending my election vote to all members");
    groupManager.sendAll(msg);

    // Step 2: Wait for election completion
    waitTillElectionComplete();

    // Step 3: Compute Winner
    Enrollment lWinner = computeResult();
    if (lWinner != e) {
      logger.info("Election lost : Winner is : " + lWinner);
      Assert.assertNotNull(lWinner);
      return lWinner.getNodeID();
    }
    // Step 4 : local host won the election, so notify world for acceptance
    msg = createElectionResultMessage(e);
    debugInfo("Won election, announcing to world and waiting for response...");
    GroupResponse<L2StateMessage> responses = groupManager.sendAllAndWaitForResponse(msg);
    for (L2StateMessage response : responses.getResponses()) {
      Assert.assertEquals(msg.getMessageID(), response.inResponseTo());
      if (response.getType() == L2StateMessage.RESULT_AGREED) {
        Assert.assertEquals(e, response.getEnrollment());
      } else if (response.getType() == L2StateMessage.RESULT_CONFLICT) {
        logger.info(
            "Result Conflict: Local Result : "
                + e
                + " From : "
                + response.messageFrom()
                + " Result : "
                + response.getEnrollment());
        return ServerID.NULL_ID;
      } else {
        throw new AssertionError(
            "Node : "
                + response.messageFrom()
                + " responded neither with RESULT_AGREED or RESULT_CONFLICT :"
                + response);
      }
    }

    // Step 5 : result agreed - I am the winner
    return myNodeId;
  }