use crate::graph::middleware::dag::ArrayMap;
use crate::graph::middleware::dot::Dot;
use crate::vv::structs::version_vector::VersionVector;
use smallvec::SmallVec;
use std::collections::HashMap;
use std::fmt;
use std::fs::File;
use std::io::prelude::Write;
use std::io::BufWriter;
#[derive(Debug)]
pub enum CausalCheck {
Send { sent_dot: Dot, context: Vec<Dot> },
Delivery { dev_dot: Dot },
Stable { stb_dot: Dot },
}
impl CausalCheck {
pub fn get_dot(entry: &CausalCheck) -> Dot {
match entry {
CausalCheck::Send { sent_dot, .. } => sent_dot.clone(),
CausalCheck::Delivery { dev_dot } => dev_dot.clone(),
CausalCheck::Stable { stb_dot } => stb_dot.clone(),
}
}
}
#[derive(Debug)]
pub enum CausalityChecker {
Ok(ArrayMap<CheckNode>),
Error(CausalityCheckerError),
}
#[derive(Debug)]
pub enum CausalityCheckerErrorEnum {
Send,
Delivery,
Stability,
}
impl fmt::Display for CausalityCheckerErrorEnum {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CausalityCheckerErrorEnum::Send => write!(f, "Send"),
CausalityCheckerErrorEnum::Delivery => write!(f, "Delivery"),
CausalityCheckerErrorEnum::Stability => write!(f, "Stability"),
}
}
}
#[derive(Debug)]
pub struct CausalityCheckerError {
error_type: CausalityCheckerErrorEnum,
message: String,
global_causal_dag: ArrayMap<CheckNode>,
peer_dot_sequences: Vec<Vec<CausalCheck>>,
dot_to_index_map: HashMap<Dot, usize>,
peer_version_vectors: Vec<VersionVector>,
dot_version_vector_map: HashMap<Dot, VersionVector>,
peer_dot_sequence_indexes: Vec<usize>,
peer_dot_sequence_prev_indexes: Vec<usize>,
current_dot: Dot,
current_peer: usize,
current_peer_dot_sequence_index: usize,
}
impl CausalityCheckerError {
pub fn new(
error_type: CausalityCheckerErrorEnum,
message: String,
global_causal_dag: ArrayMap<CheckNode>,
peer_dot_sequences: Vec<Vec<CausalCheck>>,
dot_to_index_map: HashMap<Dot, usize>,
peer_version_vectors: Vec<VersionVector>,
dot_version_vector_map: HashMap<Dot, VersionVector>,
peer_dot_sequence_indexes: Vec<usize>,
peer_dot_sequence_prev_indexes: Vec<usize>,
current_dot: Dot,
current_peer: usize,
current_peer_dot_sequence_index: usize,
) -> Self {
Self {
error_type,
message,
global_causal_dag,
peer_dot_sequences,
dot_to_index_map,
peer_version_vectors,
dot_version_vector_map,
peer_dot_sequence_indexes,
peer_dot_sequence_prev_indexes,
current_dot,
current_peer,
current_peer_dot_sequence_index,
}
}
pub fn log_causal_check_error(self, output_base_file_path: String) {
println!("Message {}\n\n", self.message);
println!("Error type {}\n\n", self.error_type);
let file = File::create(output_base_file_path).unwrap();
let mut file_buffer = BufWriter::new(file);
file_buffer
.write(
format!(
"{:?} | Peer {} | Seq Index {} | Error Type {}\n",
self.current_dot,
self.current_peer,
self.current_peer_dot_sequence_index,
self.error_type
)
.as_bytes(),
)
.unwrap();
file_buffer
.write(format!("--------------------------\n").as_bytes())
.unwrap();
file_buffer
.write(format!("Sequence Indexes\n\t{:?}\n", self.peer_dot_sequence_indexes).as_bytes())
.unwrap();
file_buffer
.write(format!("--------------------------\n").as_bytes())
.unwrap();
file_buffer
.write(
format!(
"Sequence Prev Indexes\n\t{:?}\n",
self.peer_dot_sequence_prev_indexes
)
.as_bytes(),
)
.unwrap();
file_buffer
.write(format!("--------------------------\n").as_bytes())
.unwrap();
for i in 0..self.peer_version_vectors.len() {
file_buffer
.write(format!("Peer {} VV:\n\t{:?}\n", i, self.peer_version_vectors[i]).as_bytes())
.unwrap();
}
file_buffer
.write(format!("--------------------------\n").as_bytes())
.unwrap();
for i in 0..self.peer_dot_sequences.len() {
let sequence_file =
File::create(format!("tcb_output/causal_error_peer_sequence{}.txt", i)).unwrap();
let mut sequence_file_buffer = BufWriter::new(sequence_file);
sequence_file_buffer
.write(format!("Peer Dot Seq {}\n", i).as_bytes())
.unwrap();
for j in 0..self.peer_dot_sequences[i].len() {
sequence_file_buffer
.write(format!("\n\t{} - {:?}\n", j, self.peer_dot_sequences[i][j]).as_bytes())
.unwrap();
}
sequence_file_buffer.flush().unwrap();
}
file_buffer
.write(format!("--------------------------\n").as_bytes())
.unwrap();
file_buffer
.write(format!("\t Dot Version Vector\n").as_bytes())
.unwrap();
for (dot, version_vector) in self.dot_version_vector_map.iter() {
let line = format!("\t{:?} - {:?}\n", dot, version_vector);
file_buffer.write_all(line.as_bytes()).unwrap();
}
file_buffer
.write(format!("--------------------------\n").as_bytes())
.unwrap();
file_buffer
.write(format!("\t Dot to Index Map\n").as_bytes())
.unwrap();
for (dot, index) in self.dot_to_index_map.iter() {
let line = format!("\t{:?} - {}\n", dot, index);
file_buffer.write_all(line.as_bytes()).unwrap();
}
file_buffer
.write(format!("--------------------------\n").as_bytes())
.unwrap();
file_buffer
.write(format!("\t Causal Graph\n").as_bytes())
.unwrap();
for i in 0..self.global_causal_dag.len() {
let temp_node = &self.global_causal_dag[i];
let line = format!(
"{} - Dot({}, {})\n\tPred - {:?}\n\tSucc - {:?}\n",
i,
temp_node.dot.id,
temp_node.dot.counter,
temp_node.predecessors,
temp_node.successors
);
file_buffer.write_all(line.as_bytes()).unwrap();
}
file_buffer.flush().unwrap();
}
}
pub enum HandlePeerDotCausalError {
Ok,
CausalDeliveryError {
message: String,
current_dot: Dot,
current_peer: usize,
current_peer_dot_sequence_index: usize,
},
CausalStabilityError {
message: String,
current_dot: Dot,
current_peer: usize,
current_peer_dot_sequence_index: usize,
},
}
#[derive(Debug)]
pub struct VersionMatrix {
pub matrix: Vec<VersionVector>,
}
impl VersionMatrix {
pub fn new(peer_number: usize) -> VersionMatrix {
let mut matrix: Vec<VersionVector> = Vec::with_capacity(peer_number);
for _ in 0..peer_number {
matrix.push(VersionVector::new(peer_number));
}
VersionMatrix { matrix: matrix }
}
pub fn check_stability(&self, dot_version_vector: &VersionVector) -> bool {
for i in 0..self.matrix.len() {
if !VersionVector::cmp(&self.matrix[i], dot_version_vector) {
return false;
}
}
true
}
pub fn update_peer_entry(&mut self, peer_id: usize, dot_version_vector: VersionVector) {
self.matrix[peer_id] = dot_version_vector;
}
}
#[derive(Debug)]
pub struct CheckNode {
pub dot: Dot,
pub predecessors: SmallVec<[usize; 4]>,
pub successors: SmallVec<[usize; 4]>,
}
impl CheckNode {
pub fn new(dot: Dot) -> CheckNode {
let predecessors = SmallVec::<[usize; 4]>::new();
let successors = SmallVec::<[usize; 4]>::new();
CheckNode {
dot: dot,
predecessors: predecessors,
successors: successors,
}
}
}