Skip to content

Commit

Permalink
Refactor: add noop_log_id to Leading
Browse files Browse the repository at this point in the history
When a leader established, store the first log id in struct `Leading`,
i.e., the noop log id.

This log id can be used for linearizable read.
  • Loading branch information
drmingdrmer committed Apr 8, 2024
1 parent b73a64f commit 10d441f
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 2 deletions.
12 changes: 12 additions & 0 deletions openraft/src/engine/engine_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,18 @@ where C: RaftTypeConfig
debug_assert!(_res.is_ok(), "commit vote can not fail but: {:?}", _res);
}

// Update the noop log index
{
let vote = *self.state.vote_ref();
let index = self.state.last_log_id().next_index();

let leading = self.internal_server_state.leading_mut().unwrap();

// TODO: in future the leader will be able to start another new election without quit leader.
debug_assert!(leading.noop_log_id.is_none());
leading.noop_log_id = Some(LogId::new(vote.committed_leader_id().unwrap(), index));
}

let mut rh = self.replication_handler();

// It has to setup replication stream first because append_blank_log() may update the
Expand Down
4 changes: 2 additions & 2 deletions openraft/src/engine/handler/vote_handler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ where C: RaftTypeConfig
// Re-create a new Leader instance.

let em = &self.state.membership_state.effective();
let leader = Leading::new(
let leading = Leading::new(
*self.state.vote_ref(),
em.membership().to_quorum_set(),
em.learner_ids(),
Expand All @@ -162,7 +162,7 @@ where C: RaftTypeConfig

// Do not update clock_progress, until the first blank log is committed.

*self.internal_server_state = InternalServerState::Leading(Box::new(leader));
*self.internal_server_state = InternalServerState::Leading(Box::new(leading));

self.server_state_handler().update_server_state_if_changed();
}
Expand Down
11 changes: 11 additions & 0 deletions openraft/src/engine/tests/elect_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ fn test_elect() -> anyhow::Result<()> {
eng.elect();

assert_eq!(Vote::new_committed(1, 1), *eng.state.vote_ref());
assert_eq!(
Some(log_id(1, 1, 1)),
eng.internal_server_state.leading().unwrap().noop_log_id
);
assert!(
eng.internal_server_state.voting_mut().is_none(),
"voting state is removed when becoming leader"
Expand Down Expand Up @@ -102,6 +106,11 @@ fn test_elect() -> anyhow::Result<()> {
eng.elect();

assert_eq!(Vote::new_committed(2, 1), *eng.state.vote_ref());
assert_eq!(
Some(log_id(2, 1, 1)),
eng.internal_server_state.leading().unwrap().noop_log_id
);

assert!(
eng.internal_server_state.voting_mut().is_none(),
"voting state is removed when becoming leader"
Expand Down Expand Up @@ -151,6 +160,8 @@ fn test_elect() -> anyhow::Result<()> {
eng.elect();

assert_eq!(Vote::new(1, 1), *eng.state.vote_ref());
assert_eq!(None, eng.internal_server_state.leading().unwrap().noop_log_id);

assert_eq!(
Some(btreeset! {1},),
eng.internal_server_state.leading().map(|x| x.voting().unwrap().granters().collect::<BTreeSet<_>>())
Expand Down
7 changes: 7 additions & 0 deletions openraft/src/engine/tests/handle_vote_resp_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ fn test_handle_vote_resp() -> anyhow::Result<()> {
});

assert_eq!(Vote::new(2, 1), *eng.state.vote_ref());
assert_eq!(None, eng.internal_server_state.leading().unwrap().noop_log_id);
assert_eq!(
Some(btreeset! {1},),
eng.internal_server_state.leading().map(|x| x.voting().unwrap().granters().collect::<BTreeSet<_>>())
Expand Down Expand Up @@ -163,6 +164,7 @@ fn test_handle_vote_resp() -> anyhow::Result<()> {
});

assert_eq!(Vote::new(2, 1), *eng.state.vote_ref());
assert_eq!(None, eng.internal_server_state.leading().unwrap().noop_log_id);
assert_eq!(
Some(btreeset! {1},),
eng.internal_server_state.leading().map(|x| x.voting().unwrap().granters().collect::<BTreeSet<_>>())
Expand Down Expand Up @@ -199,6 +201,7 @@ fn test_handle_vote_resp() -> anyhow::Result<()> {
});

assert_eq!(Vote::new(2, 1), *eng.state.vote_ref());
assert_eq!(None, eng.internal_server_state.leading().unwrap().noop_log_id);
assert_eq!(
Some(btreeset! {1,2},),
eng.internal_server_state.leading().map(|x| x.voting().unwrap().granters().collect::<BTreeSet<_>>())
Expand Down Expand Up @@ -235,6 +238,10 @@ fn test_handle_vote_resp() -> anyhow::Result<()> {
});

assert_eq!(Vote::new_committed(2, 1), *eng.state.vote_ref());
assert_eq!(
Some(log_id(2, 1, 1)),
eng.internal_server_state.leading().unwrap().noop_log_id
);
assert!(
eng.internal_server_state.voting_mut().is_none(),
"voting state is removed when becoming leader"
Expand Down
7 changes: 7 additions & 0 deletions openraft/src/leader/leader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ pub(crate) struct Leading<NID: NodeId, QS: QuorumSet<NID>, I: Instant> {
/// The vote this leader works in.
pub(crate) vote: Vote<NID>,

/// The log id of the first log entry proposed by this leader,
/// i.e., the `noop` log(AKA blank log) after leader established.
///
/// It is set when leader established.
pub(crate) noop_log_id: Option<LogId<NID>>,

quorum_set: QS,

/// Voting state, i.e., there is a Candidate running.
Expand Down Expand Up @@ -63,6 +69,7 @@ where

Self {
vote,
noop_log_id: None,
quorum_set: quorum_set.clone(),
voting: None,
progress: VecProgress::new(
Expand Down

0 comments on commit 10d441f

Please sign in to comment.