use log::info;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet, VecDeque};
use crate::event_label::{AsEventLabel, LabelEnum};
use crate::must::MustState;
use crate::{event::*, Config, ThreadId};
#[derive(Clone, Serialize, Deserialize)]
pub(crate) struct TopologicallySortedExecutionGraph {
label_order: VecDeque<LabelEnum>,
labels: HashSet<Event>,
}
impl TopologicallySortedExecutionGraph {
pub(crate) fn new() -> Self {
TopologicallySortedExecutionGraph {
label_order: VecDeque::new(),
labels: HashSet::new(),
}
}
pub(crate) fn insert_label(&mut self, label: LabelEnum) {
if !self.labels.contains(&label.pos()) {
info!("Adding {} to graph", label);
self.labels.insert(label.pos());
self.label_order.push_back(label);
}
}
pub(crate) fn next_task(&mut self, current_event: Option<LabelEnum>) -> Option<LabelEnum> {
if current_event.is_some() {
return current_event;
}
let event = self.label_order.pop_front();
match event {
None => {
info!("End of trace!");
None
}
Some(label) => match label {
LabelEnum::Begin(b) => {
info!("Skipping: {}", b);
self.next_task(current_event)
}
LabelEnum::End(e) => {
info!("Skipping: {}", e);
self.next_task(current_event)
}
_ => {
info!("Replaying: {}", label);
Some(label)
}
},
}
}
pub(crate) fn filter(&self) -> TurmoilExecutionTrace {
let mut v = Vec::new();
let mut event_to_msg = HashMap::new();
for e in self.label_order.iter() {
if let LabelEnum::SendMsg(s) = e {
let event_id = s.pos();
let msg_string = format!("{:?}", s.val());
event_to_msg.insert(event_id, msg_string);
}
if let LabelEnum::RecvMsg(r) = e {
let sender = r.sender().to_number() as usize;
let receiver = r.receiver().to_number() as usize;
let sender_event = r.rf().unwrap();
let msg = event_to_msg
.remove(&sender_event)
.expect("Could not find corresponding sender event");
v.push((sender, receiver, msg));
}
}
TurmoilExecutionTrace(v)
}
}
#[derive(Serialize, Deserialize)]
pub(crate) struct TurmoilExecutionTrace(Vec<(usize, usize, String)>);
impl std::fmt::Display for TopologicallySortedExecutionGraph {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut out_string = String::new();
for label in self.label_order.iter() {
let str = format!("{}", label);
out_string.push_str(&str);
out_string.push('\n');
}
write!(f, "{}", out_string)
}
}
#[derive(Clone, Serialize, Deserialize)]
pub struct ReplayInformation {
sorted_error_graph: Option<TopologicallySortedExecutionGraph>,
error_state: Option<MustState>,
error_found: bool,
current_event: Option<LabelEnum>,
replay_mode: bool,
config: Config,
}
impl ReplayInformation {
pub(crate) fn new(config: Config, replay_mode: bool) -> Self {
ReplayInformation {
sorted_error_graph: None,
error_state: None,
error_found: false,
current_event: None,
replay_mode,
config,
}
}
pub(crate) fn create(
sorted_error_graph: TopologicallySortedExecutionGraph,
error_state: MustState,
config: Config,
) -> Self {
ReplayInformation {
sorted_error_graph: Some(sorted_error_graph),
error_state: Some(error_state),
error_found: true,
current_event: None,
replay_mode: true,
config,
}
}
pub(crate) fn extract_error_state(&mut self) -> MustState {
assert!(self.error_state.is_some());
self.error_state.take().unwrap()
}
pub(crate) fn error_found(&self) -> bool {
self.error_found
}
pub(crate) fn current_event(&self) -> Option<LabelEnum> {
self.current_event.clone()
}
pub(crate) fn reset_current_event(&mut self) {
self.current_event = None;
}
pub(crate) fn sorted_error_graph(&self) -> &TopologicallySortedExecutionGraph {
self.sorted_error_graph.as_ref().unwrap()
}
pub(crate) fn replay_mode(&self) -> bool {
self.replay_mode
}
pub(crate) fn next_task(&mut self) -> Option<ThreadId> {
assert!(self.sorted_error_graph.is_some());
let next_label = self
.sorted_error_graph
.as_mut()
.unwrap()
.next_task(self.current_event.clone());
match next_label {
None => {
self.current_event = None;
None
}
Some(label) => {
let task = label.thread();
self.current_event = Some(label);
Some(task)
}
}
}
pub(crate) fn config(&self) -> Config {
self.config.clone()
}
}