(RaftLog heart)
| 594 | } |
| 595 | |
| 596 | void setLeaderReady(RaftLog heart) throws Exception { |
| 597 | if (isLeader()) { |
| 598 | // 是否过期First-Heartbeat。 |
| 599 | // 使用 LeaderReadyFuture 可以更加精确的识别。 |
| 600 | // 但是,由于RaftLog不是常驻内存的,保存不了进程级别的变量。 |
| 601 | if (heart.getTerm() != leaderWaitReadyTerm || heart.getIndex() != leaderWaitReadyIndex) |
| 602 | return; |
| 603 | |
| 604 | leaderWaitReadyIndex = 0; |
| 605 | leaderWaitReadyTerm = 0; |
| 606 | |
| 607 | logger.info("{} {} LastIndex={} Count={}", getName(), raftConfig.getDbHome(), |
| 608 | logSequence.getLastIndex(), logSequence.getTestStateMachineCount()); |
| 609 | |
| 610 | leaderReadyFuture.setResult(true); |
| 611 | signalAll(); // has under lock(this) |
| 612 | |
| 613 | server.foreach(allSocket -> { |
| 614 | // 本来这个通告发给Agent(client)即可, |
| 615 | // 但是现在没有区分是来自Raft的连接还是来自Agent, |
| 616 | // 全部发送。 |
| 617 | // 另外Raft之间有两个连接,会收到多次,Raft不处理这个通告。 |
| 618 | // 由于Raft数量不多,不会造成大的浪费,不做处理了。 |
| 619 | if (allSocket.isHandshakeDone()) { |
| 620 | var r = new LeaderIs(); |
| 621 | r.Argument.setTerm(logSequence.getTerm()); |
| 622 | r.Argument.setLeaderId(leaderId); |
| 623 | r.Argument.setLeader(isLeader()); |
| 624 | r.Send(allSocket); // skip response. |
| 625 | } |
| 626 | }); |
| 627 | if (onLeaderReady != null) |
| 628 | onLeaderReady.run(); |
| 629 | } |
| 630 | } |
| 631 | |
| 632 | private boolean isLastLogUpToDate(BRequestVoteArgument candidate) throws RocksDBException { |
| 633 | // NodeReady local candidate |
no test coverage detected