use self::append::FollowerAppend;
use self::idle::FollowerIdle;
use self::init::FollowerInit;
use self::snapshot::FollowerSnapshot;
use super::{Common, NextState};
use election::Role;
use message::{Message, MessageHeader};
use {Io, Result};
mod append;
mod idle;
mod init;
mod snapshot;
pub enum Follower<IO: Io> {
Init(FollowerInit<IO>),
Idle(FollowerIdle<IO>),
Append(FollowerAppend<IO>),
Snapshot(FollowerSnapshot<IO>),
}
impl<IO: Io> Follower<IO> {
pub fn new(common: &mut Common<IO>, pending_vote: Option<MessageHeader>) -> Self {
common.set_timeout(Role::Follower);
let follower = FollowerInit::new(common, pending_vote);
Follower::Init(follower)
}
pub fn handle_timeout(&mut self, common: &mut Common<IO>) -> Result<NextState<IO>> {
Ok(Some(common.transit_to_candidate()))
}
pub fn handle_message(
&mut self,
common: &mut Common<IO>,
message: Message,
) -> Result<NextState<IO>> {
if let Message::AppendEntriesCall { .. } = message {
common.set_timeout(Role::Follower);
if unsafe { common.io_mut().is_busy() } {
common.rpc_callee(message.header()).reply_busy();
return Ok(None);
}
}
match *self {
Follower::Init(ref mut t) => track!(t.handle_message(common, message)),
Follower::Idle(ref mut t) => track!(t.handle_message(common, message)),
Follower::Append(ref mut t) => track!(t.handle_message(common, message)),
Follower::Snapshot(ref mut t) => track!(t.handle_message(common, message)),
}
}
pub fn run_once(&mut self, common: &mut Common<IO>) -> Result<NextState<IO>> {
match *self {
Follower::Init(ref mut t) => track!(t.run_once(common)),
Follower::Idle(_) => Ok(None),
Follower::Append(ref mut t) => track!(t.run_once(common)),
Follower::Snapshot(ref mut t) => track!(t.run_once(common)),
}
}
}