|
|
@@ -1,14 +1,19 @@
|
|
|
use std::sync::atomic::Ordering;
|
|
|
use std::time::Duration;
|
|
|
|
|
|
-use crate::{Index, Raft, HEARTBEAT_INTERVAL_MILLIS};
|
|
|
+use crate::{Index, Raft, Snapshot, HEARTBEAT_INTERVAL_MILLIS};
|
|
|
+
|
|
|
+pub enum ApplyCommandMessage<Command> {
|
|
|
+ Snapshot(Snapshot),
|
|
|
+ Command(Index, Command),
|
|
|
+}
|
|
|
|
|
|
pub trait ApplyCommandFnMut<Command>:
|
|
|
- 'static + Send + FnMut(Index, Command)
|
|
|
+ 'static + Send + FnMut(ApplyCommandMessage<Command>)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
-impl<Command, T: 'static + Send + FnMut(Index, Command)>
|
|
|
+impl<Command, T: 'static + Send + FnMut(ApplyCommandMessage<Command>)>
|
|
|
ApplyCommandFnMut<Command> for T
|
|
|
{
|
|
|
}
|
|
|
@@ -28,7 +33,7 @@ where
|
|
|
let stop_wait_group = self.stop_wait_group.clone();
|
|
|
std::thread::spawn(move || {
|
|
|
while keep_running.load(Ordering::SeqCst) {
|
|
|
- let (mut index, commands) = {
|
|
|
+ let messages = {
|
|
|
let mut rf = rf.lock();
|
|
|
if rf.last_applied >= rf.commit_index {
|
|
|
condvar.wait_for(
|
|
|
@@ -36,27 +41,37 @@ where
|
|
|
Duration::from_millis(HEARTBEAT_INTERVAL_MILLIS),
|
|
|
);
|
|
|
}
|
|
|
- if rf.last_applied < rf.commit_index {
|
|
|
+ if rf.last_applied < rf.log.start() {
|
|
|
+ let (index_term, data) = rf.log.snapshot();
|
|
|
+ vec![ApplyCommandMessage::Snapshot(Snapshot {
|
|
|
+ last_included_index: index_term.index,
|
|
|
+ data: data.to_vec(),
|
|
|
+ })]
|
|
|
+ } else if rf.last_applied < rf.commit_index {
|
|
|
let index = rf.last_applied + 1;
|
|
|
let last_one = rf.commit_index + 1;
|
|
|
- let commands: Vec<Command> = rf
|
|
|
+ let messages: Vec<ApplyCommandMessage<Command>> = rf
|
|
|
.log
|
|
|
.between(index, last_one)
|
|
|
.iter()
|
|
|
- .map(|entry| entry.command.clone())
|
|
|
+ .map(|entry| {
|
|
|
+ ApplyCommandMessage::Command(
|
|
|
+ entry.index,
|
|
|
+ entry.command.clone(),
|
|
|
+ )
|
|
|
+ })
|
|
|
.collect();
|
|
|
rf.last_applied = rf.commit_index;
|
|
|
- (index, commands)
|
|
|
+ messages
|
|
|
} else {
|
|
|
continue;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// Release the lock while calling external functions.
|
|
|
- for command in commands {
|
|
|
- apply_command(index, command);
|
|
|
+ for message in messages {
|
|
|
+ apply_command(message);
|
|
|
snapshot_daemon.trigger();
|
|
|
- index += 1;
|
|
|
}
|
|
|
}
|
|
|
|