use futures::{Async, Future};
use std::collections::HashSet;
use super::{Common, NextState};
use election::Role;
use message::{Message, RequestVoteReply};
use node::NodeId;
use {Io, Result};
pub struct Candidate<IO: Io> {
followers: HashSet<NodeId>,
init: Option<IO::SaveBallot>,
}
impl<IO: Io> Candidate<IO> {
pub fn new(common: &mut Common<IO>) -> Self {
common.set_timeout(Role::Candidate);
let future = common.save_ballot();
Candidate {
init: Some(future),
followers: HashSet::new(),
}
}
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::RequestVoteReply(RequestVoteReply { voted: true, .. }) = message {
self.followers.insert(message.header().sender.clone());
let is_elected = common
.config()
.consensus_value(|n| self.followers.contains(n));
if is_elected {
return Ok(Some(common.transit_to_leader()));
}
}
Ok(None)
}
pub fn run_once(&mut self, common: &mut Common<IO>) -> Result<NextState<IO>> {
if let Async::Ready(Some(())) = track!(self.init.poll())? {
self.init = None;
common.rpc_caller().broadcast_request_vote();
}
Ok(None)
}
}