d_engine/core/
mod.rs

1mod commit_handler;
2mod election;
3mod event;
4mod purge;
5mod raft;
6mod raft_context;
7mod raft_role;
8mod replication;
9mod state_machine_handler;
10mod timer;
11
12pub(crate) use commit_handler::*;
13pub(crate) use election::*;
14pub(crate) use event::*;
15pub(crate) use purge::*;
16pub(crate) use raft::*;
17pub(crate) use raft_context::*;
18#[doc(hidden)]
19pub use raft_role::*;
20pub(crate) use replication::*;
21pub(crate) use state_machine_handler::*;
22pub(crate) use timer::*;
23use tracing::instrument;
24
25use crate::proto::common::entry_payload::Payload;
26use crate::proto::common::membership_change::Change;
27use crate::proto::common::EntryPayload;
28use crate::proto::common::MembershipChange;
29use crate::proto::common::Noop;
30
31#[cfg(test)]
32mod raft_oneshot_test;
33#[cfg(test)]
34mod raft_test;
35
36/// In raft, during any Leader to Peer communication,
37///     if received response term is bigger than Leader's,
38///     the current Leader need downgrade to follower
39///     and update its term to higher one.
40///
41/// e.g. Append Entries RPC
42/// e.g. Election: receive VoteResponse
43/// e.g. Sync cluster membership configure
44/// @return: true - found higher term;
45pub(crate) fn if_higher_term_found(
46    my_current_term: u64,
47    term: u64,
48    is_learner: bool,
49) -> bool {
50    //means I am fake leader or we should ignore learner's response
51    if !is_learner && my_current_term < term {
52        tracing::warn!("my_current_term: {} < term: {} ?", my_current_term, term);
53        return true;
54    }
55
56    false
57}
58
59/// Raft paper: 5.4.1 Election restriction
60///
61/// Raft determines which of two logs is more up-to-date by comparing the index and term of the last
62/// entries in the  logs. If the logs have last entries with different terms, then the log with the
63/// later term is more up-to-date. If the logs end with the same term, then whichever log is longer
64/// is more up-to-date.
65#[instrument]
66pub(crate) fn is_target_log_more_recent(
67    my_last_log_index: u64,
68    my_last_log_term: u64,
69    target_last_log_index: u64,
70    target_last_log_term: u64,
71) -> bool {
72    (target_last_log_term > my_last_log_term)
73        || (target_last_log_term == my_last_log_term && target_last_log_index >= my_last_log_index)
74}
75
76#[derive(Debug, Clone, Copy)]
77pub enum QuorumStatus {
78    Confirmed,    // Confirmed by the majority of nodes
79    LostQuorum,   // Unable to obtain majority
80    NetworkError, // Network problem (can be retried)
81}
82
83impl EntryPayload {
84    pub fn command(command: Vec<u8>) -> Self {
85        Self {
86            payload: Some(Payload::Command(command)),
87        }
88    }
89    pub fn noop() -> Self {
90        Self {
91            payload: Some(Payload::Noop(Noop {})),
92        }
93    }
94
95    pub fn config(change: Change) -> Self {
96        Self {
97            payload: Some(Payload::Config(MembershipChange {
98                change: Some(change),
99            })),
100        }
101    }
102}