2018-07-08 09:41:50 -07:00
|
|
|
//! Functionality for logging faulty node behavior encountered by each
|
|
|
|
//! algorithm.
|
|
|
|
//!
|
2018-12-18 07:17:46 -08:00
|
|
|
//! Each algorithm can propogate their faulty node logs upwards to a calling algorithm via
|
|
|
|
//! `DistAlgorihm`'s `.handle_input()` and `.handle_message()` trait methods.
|
|
|
|
|
|
|
|
pub use failure::Fail;
|
2018-07-08 09:41:50 -07:00
|
|
|
|
|
|
|
/// A structure representing the context of a faulty node. This structure
|
|
|
|
/// describes which node is faulty (`node_id`) and which faulty behavior
|
2018-12-11 00:12:38 -08:00
|
|
|
/// that the node exhibited ('kind').
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
2018-12-18 07:17:46 -08:00
|
|
|
pub struct Fault<N, F: Fail> {
|
2018-11-26 06:35:24 -08:00
|
|
|
/// The faulty node's ID.
|
2018-08-02 14:27:55 -07:00
|
|
|
pub node_id: N,
|
2018-11-26 06:35:24 -08:00
|
|
|
/// The kind of fault the node is blamed for.
|
2018-12-18 07:17:46 -08:00
|
|
|
pub kind: F,
|
2018-07-08 09:41:50 -07:00
|
|
|
}
|
|
|
|
|
2018-12-18 07:17:46 -08:00
|
|
|
impl<N, F> Fault<N, F>
|
|
|
|
where
|
|
|
|
F: Fail,
|
|
|
|
{
|
2018-11-26 06:35:24 -08:00
|
|
|
/// Creates a new fault, blaming `node_id` for the `kind`.
|
2018-12-18 07:17:46 -08:00
|
|
|
pub fn new(node_id: N, kind: F) -> Self {
|
2018-07-08 09:41:50 -07:00
|
|
|
Fault { node_id, kind }
|
|
|
|
}
|
2018-12-18 07:17:46 -08:00
|
|
|
|
|
|
|
/// Applies `f_fault` to `kind`, leaves `node_id` unchanged
|
|
|
|
pub fn map<F2, FF>(self, f_fault: FF) -> Fault<N, F2>
|
|
|
|
where
|
|
|
|
F2: Fail,
|
|
|
|
FF: Fn(F) -> F2,
|
|
|
|
{
|
|
|
|
Fault {
|
|
|
|
node_id: self.node_id,
|
|
|
|
kind: f_fault(self.kind),
|
|
|
|
}
|
|
|
|
}
|
2018-07-08 09:41:50 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Creates a new `FaultLog` where `self` is the first element in the log
|
|
|
|
/// vector.
|
2018-12-18 07:17:46 -08:00
|
|
|
impl<N, F> Into<FaultLog<N, F>> for Fault<N, F>
|
|
|
|
where
|
|
|
|
F: Fail,
|
|
|
|
{
|
|
|
|
fn into(self) -> FaultLog<N, F> {
|
2018-07-08 09:41:50 -07:00
|
|
|
FaultLog(vec![self])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A structure used to contain reports of faulty node behavior.
|
2018-07-16 06:31:21 -07:00
|
|
|
#[derive(Debug, PartialEq)]
|
2018-12-18 07:17:46 -08:00
|
|
|
pub struct FaultLog<N, F: Fail>(pub Vec<Fault<N, F>>);
|
2018-07-08 09:41:50 -07:00
|
|
|
|
2018-12-18 07:17:46 -08:00
|
|
|
impl<N, F> FaultLog<N, F>
|
|
|
|
where
|
|
|
|
F: Fail,
|
|
|
|
{
|
2018-07-08 09:41:50 -07:00
|
|
|
/// Creates an empty `FaultLog`.
|
|
|
|
pub fn new() -> Self {
|
|
|
|
FaultLog::default()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Creates a new `FaultLog` initialized with a single log.
|
2018-12-18 07:17:46 -08:00
|
|
|
pub fn init(node_id: N, kind: F) -> Self {
|
2018-07-08 09:41:50 -07:00
|
|
|
Fault::new(node_id, kind).into()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Creates a new `Fault` and pushes it onto the fault log.
|
2018-12-18 07:17:46 -08:00
|
|
|
pub fn append(&mut self, node_id: N, kind: F) {
|
2018-07-08 09:41:50 -07:00
|
|
|
self.0.push(Fault::new(node_id, kind));
|
|
|
|
}
|
|
|
|
|
2018-12-18 07:17:46 -08:00
|
|
|
/// Consumes a `Fault` and pushes it onto the fault log.
|
|
|
|
pub fn append_fault(&mut self, fault: Fault<N, F>) {
|
|
|
|
self.0.push(fault);
|
|
|
|
}
|
|
|
|
|
2018-07-08 09:41:50 -07:00
|
|
|
/// Consumes `new_logs`, appending its logs onto the end of `self`.
|
2018-12-18 07:17:46 -08:00
|
|
|
pub fn extend(&mut self, new_logs: FaultLog<N, F>) {
|
2018-07-08 09:41:50 -07:00
|
|
|
self.0.extend(new_logs.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Consumes `self`, appending its logs onto the end of `logs`.
|
2018-12-18 07:17:46 -08:00
|
|
|
pub fn merge_into(self, logs: &mut FaultLog<N, F>) {
|
2018-07-08 09:41:50 -07:00
|
|
|
logs.extend(self);
|
|
|
|
}
|
2018-07-11 23:52:38 -07:00
|
|
|
|
|
|
|
/// Returns `true` if there are no fault entries in the log.
|
|
|
|
pub fn is_empty(&self) -> bool {
|
|
|
|
self.0.is_empty()
|
|
|
|
}
|
2018-12-18 07:17:46 -08:00
|
|
|
|
|
|
|
/// Applies `f_fault` to each element in log, modifying its `kind` only
|
|
|
|
pub fn map<F2, FF>(self, f_fault: FF) -> FaultLog<N, F2>
|
|
|
|
where
|
|
|
|
F2: Fail,
|
|
|
|
FF: Fn(F) -> F2,
|
|
|
|
{
|
|
|
|
FaultLog(self.into_iter().map(|f| f.map(&f_fault)).collect())
|
|
|
|
}
|
2018-07-08 09:41:50 -07:00
|
|
|
}
|
|
|
|
|
2018-12-18 07:17:46 -08:00
|
|
|
impl<N, F> Default for FaultLog<N, F>
|
|
|
|
where
|
|
|
|
F: Fail,
|
|
|
|
{
|
2018-07-08 09:41:50 -07:00
|
|
|
fn default() -> Self {
|
|
|
|
FaultLog(vec![])
|
|
|
|
}
|
|
|
|
}
|
2018-12-18 07:17:46 -08:00
|
|
|
|
|
|
|
impl<N, F> IntoIterator for FaultLog<N, F>
|
|
|
|
where
|
|
|
|
F: Fail,
|
|
|
|
{
|
|
|
|
type Item = Fault<N, F>;
|
|
|
|
type IntoIter = std::vec::IntoIter<Fault<N, F>>;
|
|
|
|
|
|
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
|
|
self.0.into_iter()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<N, F> std::iter::FromIterator<Fault<N, F>> for FaultLog<N, F>
|
|
|
|
where
|
|
|
|
F: Fail,
|
|
|
|
{
|
|
|
|
fn from_iter<I: IntoIterator<Item = Fault<N, F>>>(iter: I) -> Self {
|
|
|
|
let mut log = FaultLog::new();
|
|
|
|
for i in iter {
|
|
|
|
log.append_fault(i);
|
|
|
|
}
|
|
|
|
log
|
|
|
|
}
|
|
|
|
}
|