package lsr.paxos.recovery; import static lsr.common.ProcessDescriptor.processDescriptor; import java.util.BitSet; import lsr.paxos.core.Paxos; import lsr.paxos.core.Proposer; import lsr.paxos.core.Proposer.ProposerState; import lsr.paxos.messages.Message; import lsr.paxos.messages.Recovery; import lsr.paxos.messages.RecoveryAnswer; import lsr.paxos.network.MessageHandler; import lsr.paxos.storage.Storage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class EpochRecoveryRequestHandler implements MessageHandler { private final Paxos paxos; public EpochRecoveryRequestHandler(Paxos paxos) { this.paxos = paxos; } public void onMessageReceived(Message message, final int sender) { final Recovery recovery = (Recovery) message; paxos.getDispatcher().submit(new Runnable() { public void run() { Storage storage = paxos.getStorage(); if (storage.getEpoch()[sender] > recovery.getEpoch()) { logger.info("Got stale recovery message from {} ({})", sender, recovery); return; } if (paxos.getLeaderId() == sender) { // if current leader is recovering, we cannot respond // and we should change a leader logger.info(processDescriptor.logMark_Benchmark, "Delaying receive {} (view change forced)", recovery); paxos.getProposer().prepareNextView(); onMessageReceived(recovery, sender); return; } logger.info(processDescriptor.logMark_Benchmark, "Received {}", recovery); if (paxos.isLeader() && paxos.getProposer().getState() == ProposerState.PREPARING) { paxos.getProposer().executeOnPrepared(new Proposer.Task() { public void onPrepared() { onMessageReceived(recovery, sender); } public void onFailedToPrepare() { onMessageReceived(recovery, sender); } }); return; } storage.updateEpoch(recovery.getEpoch(), sender); RecoveryAnswer answer = new RecoveryAnswer(storage.getView(), storage.getEpoch(), storage.getLog().getNextId()); paxos.getNetwork().sendMessage(answer, sender); } }); } public void onMessageSent(Message message, BitSet destinations) { } private final static Logger logger = LoggerFactory.getLogger(EpochRecoveryRequestHandler.class); }