@Override public void handleAccepted(PaxosMessage proposal) { ensureSize(chosen, proposal.getInstanceNum() + 1); // Prevent NPE if (chosen.get(proposal.getInstanceNum()) != null) return; // Something has already been chosen so I dont care anymore. List<PaxosMessage> acceptedVotes = proposalAcceptedVotes.get(proposal.getInstanceNum()); if (acceptedVotes == null) { acceptedVotes = new ArrayList<PaxosMessage>(); acceptedVotes.add(proposal); proposalAcceptedVotes.put(proposal.getInstanceNum(), acceptedVotes); } else { for (PaxosMessage acceptedVote : acceptedVotes) { if (proposal.getProposerId() == acceptedVote.getProposerId()) return; // This person is reaffirming their acceptance of this instances proposal. } acceptedVotes.add(proposal); proposalAcceptedVotes.put(proposal.getInstanceNum(), acceptedVotes); } // handle being chosen if (proposalAcceptedVotes.get(proposal.getInstanceNum()).size() >= serverSet.getQuorumSize()) { onChosen(proposal); } }
public void messageReceived(IoSession ioSession, Object message) throws Exception { if (message instanceof DefaultPaxosMessage) { PaxosMessage paxosMessage = (DefaultPaxosMessage) message; switch (paxosMessage.getType()) { case PROPOSE: handlePropose(paxosMessage); break; case ACCEPTED: handleAccepted(paxosMessage); break; case PREPARE: handlePrepare( (Integer) paxosMessage.getValue(), paxosMessage.getProposerId()); // PSN and consensus instance dont matter break; case PREPARE_RESP: handlePrepareResponse(paxosMessage); break; case RECOVERY: handleRecovery(paxosMessage); break; case RECOVERY_RESP: handleRecoveryResponse(paxosMessage); break; case PING: if (paxosMessage.getProposerId() == getLeader()) // Leaders HeartBeat leaderLastHeard = new Date(); else if (((Integer) paxosMessage.getValue()) > preparedFor) { // I came alive and the leader is not who I thought. preparedFor = ((Integer) paxosMessage.getValue()); handlePrepare(preparedFor, getLeader()); sendRecovery(); } break; default: throw new Exception( "received PaxosMessage of unknown type" + paxosMessage.getType().name()); } } else if (message instanceof ChatMessage) { // Some client sent or some server forwarded. if (nodeIsLeader()) { propose( new DefaultPaxosMessage( nextInstance, nextPropose, id, PaxosMessageType.PROPOSE, (ChatMessage) message)); nextInstance++; } else { sendToLeader((ChatMessage) message); } } else { throw new Exception("Unknown message type:" + message.getClass().getSimpleName()); } }
@Override public void handlePrepareResponse(PaxosMessage response) { if (!prepareResponseFrom.contains(response.getProposerId())) prepareResponseFrom.add( response.getProposerId()); // This is a new server accepted our prepare request. List<ChatMessage> remoteAccepted = (List<ChatMessage>) response.getValue(); for (int i = 0; i < remoteAccepted.size(); i++) { if (chosen.size() > i && chosen.get(i) != null) continue; if (remoteAccepted.get(i) != null) { propose( new DefaultPaxosMessage( i, nextPropose, id, PaxosMessageType.PROPOSE, remoteAccepted.get(i))); if (i > nextInstance) nextInstance = i; } } }
private void handleRecovery(PaxosMessage recoveryRequest) { PaxosMessage recoveryResponse = new DefaultPaxosMessage(-1, -1, id, PaxosMessageType.RECOVERY_RESP, chosen); sendMessage(recoveryResponse, recoveryRequest.getProposerId()); }