// notify new node @Override public void publishActiveState(NodeID nodeID) throws GroupException { debugInfo("Publishing active state to nodeId: " + nodeID); Assert.assertTrue(isActiveCoordinator()); GroupMessage msg = L2StateMessage.createElectionWonAlreadyMessage( EnrollmentFactory.createTrumpEnrollment(getLocalNodeID(), weightsFactory)); L2StateMessage response = (L2StateMessage) groupManager.sendToAndWaitForResponse(nodeID, msg); validateResponse(nodeID, response); }
@Override public void moveNodeToPassiveStandby(NodeID nodeID) { Assert.assertTrue(isActiveCoordinator()); logger.info("Requesting node " + nodeID + " to move to " + PASSIVE_STANDBY); GroupMessage msg = L2StateMessage.createMoveToPassiveStandbyMessage( EnrollmentFactory.createTrumpEnrollment(getLocalNodeID(), weightsFactory)); try { this.groupManager.sendTo(nodeID, msg); } catch (GroupException e) { logger.error(e); } }
private void handleStartElectionRequest(L2StateMessage msg) throws GroupException { if (state == ACTIVE_COORDINATOR) { // This is either a new L2 joining a cluster or a renegade L2. Force it to abort GroupMessage abortMsg = L2StateMessage.createAbortElectionMessage( msg, EnrollmentFactory.createTrumpEnrollment(getLocalNodeID(), weightsFactory)); info("Forcing Abort Election for " + msg + " with " + abortMsg); groupManager.sendTo(msg.messageFrom(), abortMsg); } else if (!electionMgr.handleStartElectionRequest(msg)) { // TODO::FIXME:: Commenting so that stage thread is not held up doing election. // startElectionIfNecessary(NodeID.NULL_ID); logger.warn("Not starting election as it was commented out"); } }
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; }
private synchronized void handleElectionResultMessage(L2StateMessage msg) throws GroupException { if (activeNode.equals(msg.getEnrollment().getNodeID())) { Assert.assertFalse(ServerID.NULL_ID.equals(activeNode)); // This wouldn't normally happen, but we agree - so ack GroupMessage resultAgreed = L2StateMessage.createResultAgreedMessage(msg, msg.getEnrollment()); logger.info("Agreed with Election Result from " + msg.messageFrom() + " : " + resultAgreed); groupManager.sendTo(msg.messageFrom(), resultAgreed); } else if (state == ACTIVE_COORDINATOR || !activeNode.isNull() || (msg.getEnrollment().isANewCandidate() && state != START_STATE)) { // Condition 1 : // Obviously an issue. // Condition 2 : // This shouldn't happen normally, but is possible when there is some weird network error // where A sees B, // B sees A/C and C sees B and A is active and C is trying to run election // Force other node to rerun election so that we can abort // Condition 3 : // We don't want new L2s to win an election when there are old L2s in PASSIVE states. GroupMessage resultConflict = L2StateMessage.createResultConflictMessage( msg, EnrollmentFactory.createTrumpEnrollment(getLocalNodeID(), weightsFactory)); warn( "WARNING :: Active Node = " + activeNode + " , " + state + " received ELECTION_RESULT message from another node : " + msg + " : Forcing re-election " + resultConflict); groupManager.sendTo(msg.messageFrom(), resultConflict); } else { debugInfo("ElectionMgr handling election result msg: " + msg); electionMgr.handleElectionResultMessage(msg); } }