Skip to content

Commit

Permalink
raft: add Log.append() validation
Browse files Browse the repository at this point in the history
  • Loading branch information
erikgrinaker committed May 31, 2024
1 parent cc61d74 commit ad1bb41
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 12 deletions.
9 changes: 8 additions & 1 deletion src/raft/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,15 @@ impl Log {
}

/// Appends a command to the log, returning its index. None implies a noop
/// command, typically after Raft leader changes.
/// command, typically after Raft leader changes. The term must be equal to
/// or greater than the previous entry.
pub fn append(&mut self, term: Term, command: Option<Vec<u8>>) -> Result<Index> {
match self.get(self.last_index)? {
Some(e) if term < e.term => return errassert!("term regression {} → {term}", e.term),
None if self.last_index > 0 => return errassert!("log gap at {}", self.last_index),
None if term == 0 => return errassert!("can't append entry with term 0"),
Some(_) | None => {}
}
let index = self.last_index + 1;
self.engine.set(&Key::Entry(index).encode()?, bincode::serialize(&(term, command))?)?;
self.engine.flush()?;
Expand Down
24 changes: 13 additions & 11 deletions src/raft/testscripts/log/append
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# Appending an entry with term 0 fails, even on an empty log.
!append 0 foo
status
---
Error: assertion failed: can't append entry with term 0
last=0@0 commit=0@0

# Appending to an empty log works. The term doesn't have to be 1, and doesn't
# have to match get_term().
#
Expand Down Expand Up @@ -35,29 +42,24 @@ append 5
append → 3@3 command
append → 4@5 None

# A term regression is allowed, as is a 0 term.
# TODO: it shouldn't be.
append 1 old
append 0
# A term regression fails, as does a 0 term.
!append 4 old
!append 0
---
append → 5@1 old
append → 6@0 None
Error: assertion failed: term regression 5 → 4
Error: assertion failed: term regression 5 → 0

# Dump the final status and data.
status
scan
raw
---
last=6@0 commit=0@0
last=4@5 commit=0@0
1@2 foo
2@2 None
3@3 command
4@5 None
5@1 old
6@0 None
Entry(1) 0x000000000000000001 = 0x020103666f6f
Entry(2) 0x000000000000000002 = 0x0200
Entry(3) 0x000000000000000003 = 0x030107636f6d6d616e64
Entry(4) 0x000000000000000004 = 0x0500
Entry(5) 0x000000000000000005 = 0x0101036f6c64
Entry(6) 0x000000000000000006 = 0x0000

0 comments on commit ad1bb41

Please sign in to comment.