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 ViewRecoveryRequestHandler implements MessageHandler {
private final Paxos paxos;
public ViewRecoveryRequestHandler(Paxos paxos) {
this.paxos = paxos;
}
public void onMessageReceived(Message msg, final int sender) {
final Recovery recovery = (Recovery) msg;
paxos.getDispatcher().submit(new Runnable() {
public void run() {
Storage storage = paxos.getStorage();
Proposer proposer = paxos.getProposer();
if (paxos.getLeaderId() == sender ||
recovery.getView() >= storage.getView()) {
/*
* if current leader is recovering, we cannot respond and we
* should change a leader
*/
// OR
/*
* The recovering process notified me that it crashed in
* view recovery.getView()
*
* This view is not less then current. View change must be
* performed.
*/
logger.info(processDescriptor.logMark_Benchmark,
"Delaying receive {} (view change forced)", recovery);
if (proposer.getState() != ProposerState.INACTIVE)
proposer.stopProposer();
proposer.prepareNextView();
// reschedule receiving msg
onMessageReceived(recovery, sender);
return;
}
if (paxos.isLeader() &&
proposer.getState() == ProposerState.PREPARING) {
logger.info(processDescriptor.logMark_Benchmark,
"Delaying receive {} (view change forced)", recovery);
// wait until we prepare the view
proposer.executeOnPrepared(new Proposer.Task() {
public void onPrepared() {
onMessageReceived(recovery, sender);
}
public void onFailedToPrepare() {
onMessageReceived(recovery, sender);
}
});
return;
}
logger.info(processDescriptor.logMark_Benchmark, "Received {}", recovery);
RecoveryAnswer answer = new RecoveryAnswer(storage.getView(),
storage.getLog().getNextId());
paxos.getNetwork().sendMessage(answer, sender);
}
});
}
public void onMessageSent(Message message, BitSet destinations) {
}
private static final Logger logger = LoggerFactory.getLogger(ViewRecoveryRequestHandler.class);
}