use of bftsmart.tom.leaderchange.LeaderRegencyPropose in project bftsmart by blockchain-jd-com.
the class Synchronizer method processOutOfContextSTOPs.
// Processes STOP messages that were not process upon reception, because they
// were
// ahead of the replica's expected regency
private void processOutOfContextSTOPs(int regency) {
// Logger.println("(Synchronizer.processOutOfContextSTOPs) Checking if there are out of context STOPs for regency " + regency);
Set<LCMessage> stops = getOutOfContextLC(LCType.STOP, regency);
if (stops.size() > 0) {
LOGGER.info("(Synchronizer.processOutOfContextSTOPs) [{}] -> I am proc {} Processing {} out of context STOPs for regency {}", this.execManager.getTOMLayer().getRealName(), controller.getStaticConf().getProcessId(), stops.size(), regency);
} else {
LOGGER.info("(Synchronizer.processOutOfContextSTOPs) [{}] -> I am proc {} No out of context STOPs for regency {}", this.execManager.getTOMLayer().getRealName(), controller.getStaticConf().getProcessId(), regency);
}
for (LCMessage m : stops) {
TOMMessage[] requests = deserializeTOMMessages(m.getPayload());
// store requests that came with the STOP message
lcManager.addRequestsFromSTOP(requests);
// store information about the STOP message
LeaderRegencyPropose propose = LeaderRegencyPropose.copy(m.getLeader(), m.getReg(), m.getViewId(), m.getViewProcessIds(), m.getSender());
lcManager.addStop(propose);
}
}
use of bftsmart.tom.leaderchange.LeaderRegencyPropose in project bftsmart by blockchain-jd-com.
the class Synchronizer method process_LC_STOP.
private synchronized void process_LC_STOP(LCMessage msg) {
// message STOP
log_debug("process_LC_STOP", "begin...", msg.getType(), msg.getSender());
// TODO: 收到 STOP 消息;
// this message is for the next leader change?
LeaderRegencyPropose regencyPropose = copyPropose(msg);
final int proposedRegencyId = regencyPropose.getRegency().getId();
if (lcManager.canPropose(proposedRegencyId)) {
if (lcManager.isFutureAfterNextRegency(proposedRegencyId)) {
// send STOP to out of context
// 处于选举进程中,但是提议的执政期Id 大于当前选举中的执政期 Id,说明这是一个执政期Id超前的提议;
// it is for a future regency
log_debug("process_LC_STOP", "Keeping STOP message as out of context for regency[" + msg.getReg() + "]!", msg.getType(), msg.getSender());
outOfContextLC.add(msg);
// 解决节点处于选举中,新一轮选举的消息放入缓存没有机会处理的问题
LeaderRegency maxRegency = getMaxRegencyFromOutofContextLC();
// 对超出预期的,且个数满足f+1条件的最大regency进行处理
for (int outofregency = maxRegency.getId(); outofregency > lcManager.getNextReg(); outofregency--) {
if (maxRegencyOutOfContextSTOPs(outofregency) == lcManager.getBeginQuorum()) {
LOGGER.info("I am proc {}, process out of context msg for regency {}", this.controller.getStaticConf().getProcessId(), outofregency);
processOutOfContextSTOPs(outofregency);
lcManager.updateNextReg(outofregency);
// 生成本地的附议Stop消息
LeaderRegencyPropose leaderRegencyPropose = LeaderRegencyPropose.copy(maxRegency.getLeaderId(), maxRegency.getId(), this.controller.getCurrentView().getId(), this.controller.getCurrentView().getProcesses(), getCurrentId());
lcManager.addStop(leaderRegencyPropose);
try {
byte[] payload = makeTomMessageReplyBatch(maxRegency.getId());
LCMessage msgSTOP_APPEND = LCMessage.createSTOP_APPEND(this.controller.getStaticConf().getProcessId(), leaderRegencyPropose.getRegency(), controller.getCurrentView(), payload);
// make replica re-transmit the stop
requestsTimer.setSTOP(maxRegency.getId(), msgSTOP_APPEND);
communication.send(this.controller.getCurrentViewOtherAcceptors(), msgSTOP_APPEND);
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
} else {
// 未开始选举进程,或者已经开始选举进程并且提议的执政期等于正在选举中的执政期;
// 等同于表达式:(!lcManager.isInProgress()) || proposedRegencyId ==
// lcManager.getNextReg()
log_debug("process_LC_STOP", "received regency change request.", msg.getType(), msg.getSender());
TOMMessage[] requests = deserializeTOMMessages(msg.getPayload());
// store requests that came with the STOP message
lcManager.addRequestsFromSTOP(requests);
// 当前的领导者;
// store information about the message STOP
lcManager.addStop(regencyPropose);
// the replica might have received STOPs
processOutOfContextSTOPs(msg.getReg());
// that were out of context at the time they
// were received, but now can be processed
// evaluate STOP messages
startSynchronization(regencyPropose);
}
} else {
log_warn("process_LC_STOP", "Discard the outdated STOP message with regency[" + proposedRegencyId + "]!", msg.getType(), msg.getSender());
}
}
use of bftsmart.tom.leaderchange.LeaderRegencyPropose in project bftsmart by blockchain-jd-com.
the class Synchronizer method startSynchronization.
// this method is called when a timeout occurs or when a STOP message is
// recevied
private synchronized void startSynchronization(LeaderRegencyPropose regencyPropose) {
LOGGER.info("(Synchronizer.startSynchronization) [{}] -> I am proc {}, initialize synchr phase", this.execManager.getTOMLayer().getRealName(), controller.getStaticConf().getProcessId());
// Ask to start the synchronizations phase if enough messages have been received
// already
final int proposedRegencyId = regencyPropose.getRegency().getId();
// 如果此时已经处于选举进程,则不作后续处理;
if (!lcManager.isInProgress()) {
// 对非领导者而言,如果请求是有当前执政期的领导者节点主动触发的,并计入自己的一票;
LeaderRegency currentRegency = lcManager.getCurrentRegency();
if ((!tom.isLeader()) && regencyPropose.getSender() == currentRegency.getLeaderId() && regencyPropose.getRegency().getId() == currentRegency.getId() + 1) {
// 这是来自当前执政期领导者的主动选举提议;
// 进一步校验视图的一致性;
// 基于当前视图预测下一个执政期(即:当前执政期Id + 1),校验预测结果与来自远程的领导者的提议是否一致;
// 如果一致,则直接投赞成票,并主动发出 STOP_APPEND 消息;
View currentView = controller.getCurrentView();
LeaderRegencyPropose nextRegencyPropose = LeaderRegencyPropose.chooseFromView(currentRegency.getId() + 1, currentView, this.getCurrentId());
if (regencyPropose.isViewEquals(currentView) && nextRegencyPropose.getRegency().getLeaderId() == regencyPropose.getRegency().getLeaderId()) {
lcManager.addStop(nextRegencyPropose);
// 发送 STOP_APPEND 消息;
sendSTOP_APPEND(nextRegencyPropose);
}
}
if (lcManager.isUpToBeginQuorum(proposedRegencyId)) {
beginElection(regencyPropose);
}
}
// Did the synchronization phase really started?
// LCManager有两种状态:
// 1: 进入“选举中”状态;
// 2:在本次“选举周期”下并发地收到其它节点的 STOPDATA 消息,完成了本次轮选举;
ElectionResult electionResult = lcManager.generateQuorumElectionResult(proposedRegencyId);
if (lcManager.isInProgress(proposedRegencyId) && electionResult != null) {
commitElection(proposedRegencyId);
}
// End of: if (canSendStopData && lcManager.getNextReg() >
// lcManager.getLastReg());
}
use of bftsmart.tom.leaderchange.LeaderRegencyPropose in project bftsmart by blockchain-jd-com.
the class Synchronizer method beginElection.
/**
* 由于收到其它节点报告的 STOP 消息数量达到了满足开始选举的数量条件,调用此方法将开始一轮新的选举;
*
* <p>
*
* 1. 调用此方法时,如果当前节点尚未开启新选举,则此方法将开启新一轮选举,并向其它节点广播 STOP / STOP_APPEND 消息;<br>
* 1.1. 如果开启选举的提议( {@link LeaderRegencyPropose} )来自当前节点,则向其它节点广播 STOP 消息; <br>
* 1.2. 如果开启选举的提议( {@link LeaderRegencyPropose} )来自其它节点,则向其它节点广播 STOP_APPEND 消息;
* <p>
*
* 2. 调用此方法时,如果当前节点已经开启新选举,则不做任何操作;
*/
private void beginElection(LeaderRegencyPropose regencyPropose) {
if (!lcManager.tryBeginElection(regencyPropose.getRegency())) {
return;
}
final boolean FROM_REMOTE = regencyPropose.getSender() != getCurrentId();
final int PROPOSED_NEXT_REGENCY_ID = regencyPropose.getRegency().getId();
heartBeatTimer.stopAll();
requestsTimer.stopTimer();
this.getLCManager().setLcTimestampStatePair(new LCTimestampStatePair(System.currentTimeMillis(), LCState.LC_SELECTING));
// 加入当前节点的领导者执政期提议;
// store information about message I am going to send
lcManager.addStop(regencyPropose);
// 对于已经收到满足f+1条件stop的情形,本身会发送stop_append, 定时器停止,不会再触发超时,此时需要把自己的投票
LeaderRegencyPropose leaderRegencyPropose = LeaderRegencyPropose.copy(regencyPropose.getRegency().getLeaderId(), regencyPropose.getRegency().getId(), this.controller.getCurrentView().getId(), this.controller.getCurrentView().getProcesses(), getCurrentId());
lcManager.addStop(leaderRegencyPropose);
// Get requests that timed out and the requests received in STOP messages
// and add those STOPed requests to the client manager
addSTOPedRequestsToClientManager();
try {
// serialize conent to send in the STOP message
byte[] payload = makeTomMessageReplyBatch(PROPOSED_NEXT_REGENCY_ID);
if (FROM_REMOTE) {
View currentView = this.controller.getCurrentView();
if (!regencyPropose.isViewEquals(currentView)) {
throw new IllegalStateException(String.format("The view of regency propose from node[%s] is not equal the the current view of node[%s]!", regencyPropose.getSender(), controller.getStaticConf().getProcessId()));
}
LCMessage msgSTOP_APPEND = LCMessage.createSTOP_APPEND(this.controller.getStaticConf().getProcessId(), regencyPropose.getRegency(), currentView, payload);
// make replica re-transmit the stop
requestsTimer.setSTOP(PROPOSED_NEXT_REGENCY_ID, msgSTOP_APPEND);
// message
// until a
// new
// regency is installed
communication.send(this.controller.getCurrentViewOtherAcceptors(), msgSTOP_APPEND);
} else {
LCMessage msgSTOP = LCMessage.createSTOP(this.controller.getStaticConf().getProcessId(), regencyPropose.getRegency(), this.controller.getCurrentView(), payload);
// TODO: ???
// make replica re-transmit the stop message
requestsTimer.setSTOP(PROPOSED_NEXT_REGENCY_ID, msgSTOP);
// until a
// new
// regency is installed
communication.send(this.controller.getCurrentViewOtherAcceptors(), msgSTOP);
}
} catch (Exception ex) {
ex.printStackTrace();
java.util.logging.Logger.getLogger(TOMLayer.class.getName()).log(Level.SEVERE, null, ex);
}
}
use of bftsmart.tom.leaderchange.LeaderRegencyPropose in project bftsmart by blockchain-jd-com.
the class Synchronizer method maxRegencyOutOfContextSTOPs.
// get stops count with max regency from out of context
//
//
private int maxRegencyOutOfContextSTOPs(int regency) {
Map<Integer, Map<Integer, LeaderRegencyPropose>> stops = new ConcurrentHashMap<Integer, Map<Integer, LeaderRegencyPropose>>();
for (LCMessage m : outOfContextLC) {
if (m.getType() == LCType.STOP && m.getReg() == regency) {
LeaderRegencyPropose propose = LeaderRegencyPropose.copy(m.getLeader(), m.getReg(), m.getViewId(), m.getViewProcessIds(), m.getSender());
Map<Integer, LeaderRegencyPropose> peerProposes = stops.get(regency);
if (peerProposes == null) {
peerProposes = new ConcurrentHashMap<Integer, LeaderRegencyPropose>();
stops.put(regency, peerProposes);
}
peerProposes.put(m.getSender(), propose);
}
}
return stops.get(regency) == null ? 0 : stops.get(regency).size();
}
Aggregations