package lsr.paxos;
import static lsr.common.ProcessDescriptor.processDescriptor;
import java.util.BitSet;
import lsr.paxos.messages.Prepare;
import lsr.paxos.messages.PrepareOK;
import lsr.paxos.storage.Storage;
public class EpochPrepareRetransmitter implements PrepareRetransmitter {
private final ActiveRetransmitter retransmitter;
private RetransmittedMessage prepareRetransmitter;
// keeps epochs of received prepareOk messages.
private long[] prepareEpoch;
private BitSet prepared = new BitSet();
private final Storage storage;
private final int numReplicas;
public EpochPrepareRetransmitter(ActiveRetransmitter retransmitter, Storage storage) {
this.retransmitter = retransmitter;
this.storage = storage;
numReplicas = processDescriptor.numReplicas;
prepareEpoch = new long[numReplicas];
}
public void startTransmitting(Prepare prepare, BitSet acceptor) {
for (int i = 0; i < numReplicas; i++) {
prepareEpoch[i] = -1;
}
prepared.clear();
prepareRetransmitter = retransmitter.startTransmitting(prepare, acceptor);
}
public void stop() {
prepareRetransmitter.stop();
}
public void update(PrepareOK message, int sender) {
if (sender == processDescriptor.localId) {
prepareEpoch[sender] = storage.getEpoch()[sender];
prepared.set(sender);
return;
}
// update storage - storage has greatest seen epochs.
storage.updateEpoch(message.getEpoch());
// Mark that we got prepareOk; overwrite received epoch only if we got
// now newer
prepareEpoch[sender] = Math.max(prepareEpoch[sender], message.getEpoch()[sender]);
for (int i = 0; i < numReplicas; i++) {
// Here, if we detected stale message, we discard it and reduce
// prepared set
if (prepareEpoch[i] == storage.getEpoch()[i]) {
stop(i);
} else {
start(i);
}
}
}
public boolean isMajority() {
return prepared.cardinality() >= processDescriptor.majority;
}
private void stop(int i) {
if (!prepared.get(i)) {
prepared.set(i);
prepareRetransmitter.stop(i);
}
}
private void start(int i) {
if (prepared.get(i)) {
prepared.clear(i);
prepareRetransmitter.start(i);
}
}
}