in merkledb/src/merkledb_debug.rs [180:234]
fn every_root_is_cas_and_file_reachable_invariant(&self) -> bool {
let mut ret = true;
for i in 0..self.get_sequence_number() {
if let Some(node) = self.find_node_by_id(i as MerkleNodeId) {
let nodeattr = self.node_attributes(node.id()).unwrap();
// we only check roots. i.e. nodes with no parents.
if nodeattr.cas_parent() > 0 || nodeattr.file_parent() > 0 {
continue;
}
// every node must be cas to file or file to cas solvable
let cas_to_file = self.reconstruct_from_file(&[node.clone()]).unwrap();
let file_to_cas = self.reconstruct_from_cas(&[node.clone()]).unwrap();
if cas_to_file.is_empty() && file_to_cas.is_empty() {
let attr = self.node_attributes(node.id()).unwrap();
eprintln!(
"CAS File relation invariant broken for node {node:?}\n\
\tattr: {attr:?}\n\
\tcas_to_file: {cas_to_file:?}\n\
\tfile_to_cas: {file_to_cas:?}\n"
);
ret = false;
}
// check that the lengths match up for each cas_to_file,
// file_to_cas entry
//
for (h, range) in cas_to_file {
let total_len: usize = range.iter().map(|x| x.end - x.start).sum();
let n = self.find_node(&h).unwrap();
if n.len() != total_len {
let attr = self.node_attributes(n.id()).unwrap();
eprintln!(
"When querying {node:?}, attr {nodeattr:?},\n\
\tCAS To file length mismatch for node {n:?}. attr: {attr:?}, \n\
\tranges acquired is {range:?}\n"
);
ret = false;
}
}
for (h, range) in file_to_cas {
let total_len: usize = range.iter().map(|x| x.end - x.start).sum();
let n = self.find_node(&h).unwrap();
if n.len() != total_len {
let attr = self.node_attributes(n.id()).unwrap();
eprintln!(
"When querying {node:?}, attr {nodeattr:?}, \n\
\tFile To CAS length mismatch for node {n:?}. \n\
\tattr: {attr:?}, ranges acquired is {range:?}\n"
);
ret = false;
}
}
}
}
ret
}