use of bftsmart.tom.leaderchange.ElectionResult in project bftsmart by blockchain-jd-com.
the class Synchronizer method process_LC_STOPDATA.
/**
* 处理从其它节点发来的 STOPDATA 消息;
* <p>
*
* @param msg
*/
private synchronized void process_LC_STOPDATA(LCMessage msg) {
log_debug("process_LC_STOPDATA", "start processing STOPDATA message...", msg.getType(), msg.getSender());
// 检查执政期是否过期;
if (msg.getReg() < lcManager.getLastReg()) {
// 执政期过期的消息,直接抛弃 ;
log_error("process_LC_STOPDATA", "receive an outdated STOPDATA message with wrong view!", msg.getType(), msg.getSender());
return;
}
// 检查消息的视图;
if (!msg.matchesView(this.controller.getCurrentView())) {
// STOPDATA 消息的视图与当前视图不一致;
// 由于执政期未过期,或者当前正处于选举进程中,尽管视图不一致,但也可以先放到超前消息列表里,暂时不做处理;
log_info("process_LC_STOPDATA", "Keep STOPDATA message as out of context for regency[" + msg.getReg() + "]!", msg.getType(), msg.getSender());
outOfContextLC.add(msg);
return;
}
// STOPDATA 消息是由新的一轮执政期中的非领导者节点向领导者节点发送的选举结果的信息;
// 当前节点需要确认如果自己是新领导者节点
final int newRegency = msg.getReg();
final int newLeader = msg.getLeader();
LeaderRegency currentRegency = this.lcManager.getCurrentRegency();
if (newRegency == currentRegency.getId()) {
// 新的执政期与当前执政期相同;
if (newLeader != currentRegency.getLeaderId()) {
// 相同的执政期,但是领导者不相同,属于无效消息;
log_error("process_LC_STOPDATA", "Discard STOPDATA message due to different leader[curr=" + currentRegency.getId() + ", new=" + newLeader + "] in the same regency[" + newRegency + "]!", msg.getType(), msg.getSender());
return;
}
if (newLeader != getCurrentId()) {
log_error("process_LC_STOPDATA", "Discarding STOPDATA message", msg.getType(), msg.getSender());
return;
}
// 当前节点是领导者;
log_info("process_LC_STOPDATA", "This is new leader of regency[" + newRegency + "]!", msg.getType(), msg.getSender());
processSTOPDATA(msg, new LeaderRegency(newLeader, newRegency));
return;
}
// 综合来看,除了 2.3 这种情况之外,其它都是需要当做超前消息来处理;
if (lcManager.isInProgress()) {
ElectionResult result = lcManager.generateElectionResult(lcManager.getNextReg());
int nextRegency = lcManager.getNextReg();
if (result != null && (newRegency < nextRegency || (newRegency == nextRegency && newLeader != result.getRegency().getLeaderId()))) {
// 执政期过期的消息,直接抛弃 ;
String errorMessage = String.format("Discard the STOPDATA message that will expire soon! --[nextRegency=%s][msgRegency=%s]", nextRegency, msg.getReg());
log_warn("process_LC_STOPDATA", errorMessage, msg.getType(), msg.getSender());
return;
}
}
log_info("process_LC_STOPDATA", "Keep STOPDATA message as out of context for regency[" + msg.getReg() + "]!", msg.getType(), msg.getSender());
outOfContextLC.add(msg);
// 原来的处理;
// // Am I the new leader, and am I expecting this messages?
// if (newRegency == lcManager.getLastReg() && this.controller.getStaticConf().getProcessId() == execManager
// .getCurrentLeader()/* (regency % this.reconfManager.getCurrentViewN()) */) {
//
// LOGGER.info(
// "(Synchronizer.deliverTimeoutRequest) [{}] -> I am proc {} I'm the new leader and I received a STOPDATA, from proc {}, from port {}",
// this.execManager.getTOMLayer().getRealName(), controller.getStaticConf().getProcessId(),
// msg.getSender(), controller.getStaticConf().getRemoteAddress(msg.getSender()).getConsensusPort());
// processSTOPDATA(msg, newRegency);
// } else if (msg.getReg() > lcManager.getLastReg()) { // send STOPDATA to out of context if
// // it is for a future regency
// LOGGER.info(
// "(Synchronizer.process_LC_STOPDATA) [{}] -> I am proc {} Keeping STOPDATA message as out of context for regency {}, from proc {}, from port {}",
// this.execManager.getTOMLayer().getRealName(), controller.getStaticConf().getProcessId(),
// msg.getReg(), msg.getSender(),
// controller.getStaticConf().getRemoteAddress(msg.getSender()).getConsensusPort());
// outOfContextLC.add(msg);
//
// } else {
// log_error("process_LC_STOPDATA", "Discarding STOPDATA message", msg.getType(), msg.getSender());
// }
}
use of bftsmart.tom.leaderchange.ElectionResult in project bftsmart by blockchain-jd-com.
the class Synchronizer method commitElection.
private synchronized void commitElection(final int proposedRegencyId) {
ElectionResult electionResult;
if (!execManager.stopped()) {
// stop consensus execution if more than f replicas sent a STOP message
execManager.stop();
}
electionResult = lcManager.commitElection(proposedRegencyId);
LOGGER.info("(Synchronizer.startSynchronization) [{}] -> I am proc {} installing regency {}", this.execManager.getTOMLayer().getRealName(), controller.getStaticConf().getProcessId(), lcManager.getNextReg());
// avoid memory leaks
lcManager.clearCurrentRequestTimedOut();
lcManager.clearRequestsFromSTOP();
// 此时开启太快,会触发反反复复的超时,应该等leaderchange流程结束再开启
// requestsTimer.Enabled(true);
requestsTimer.setShortTimeout(-1);
// requestsTimer.startTimer();
// int leader = regency % this.reconfManager.getCurrentViewN(); // new leader
// cid to execute
int inExec = tom.getInExec();
// last cid decided
int lastExec = tom.getLastExec();
execManager.setNewLeader(electionResult.getRegency().getLeaderId());
// 重启心跳
tom.heartBeatTimer.restartformlc();
// 重启业务消息超时定时器
requestsTimer.startTimer(controller.getStaticConf().getRequestTimeout());
lcManager.setLcTimestampStatePair(new LCTimestampStatePair(System.currentTimeMillis(), LCState.LC_SYNC));
LOGGER.info("I am proc {}, node lc state become sync!", this.controller.getStaticConf().getProcessId());
// leader
if (electionResult.getRegency().getLeaderId() != this.controller.getStaticConf().getProcessId()) {
sendStopDataInFollower(electionResult, inExec, lastExec);
} else {
processStopDataInLeader(electionResult, inExec, lastExec);
}
}
use of bftsmart.tom.leaderchange.ElectionResult 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());
}
Aggregations