Skip to main content

pijul_core/alive/
debug.rs

1use super::{Graph, VertexId};
2use crate::changestore::*;
3use crate::pristine::{Base32, GraphTxnT, Position};
4use crate::{HashMap, HashSet};
5use std::io::Write;
6
7impl Graph {
8    /// Write a graph to an `std::io::Write` in GraphViz (dot) format.
9    #[allow(dead_code)]
10    pub fn debug<W: Write, T: GraphTxnT, P: ChangeStore>(
11        &self,
12        changes: &P,
13        txn: &T,
14        channel: &T::Graph,
15        add_others: bool,
16        introduced_by: bool,
17        mut w: W,
18    ) -> Result<(), std::io::Error> {
19        writeln!(w, "digraph {{")?;
20        let mut buf = Vec::new();
21        let mut cache = HashMap::default();
22        if add_others {
23            for (line, i) in self.lines.iter().zip(0..) {
24                cache.insert(
25                    Position {
26                        change: line.vertex.change,
27                        pos: line.vertex.start,
28                    },
29                    i,
30                );
31            }
32        }
33        let mut others = HashSet::default();
34        for (line, i) in self.lines.iter().zip(0..) {
35            buf.resize(line.vertex.end - line.vertex.start, 0);
36            changes
37                .get_contents(
38                    |h| txn.get_external(&h).ok().map(|x| x.into()),
39                    line.vertex,
40                    &mut buf,
41                )
42                .unwrap();
43            let contents = &buf;
44            // Produce an escaped string.
45            let contents = format!(
46                "{:?}",
47                if let Ok(contents) = std::str::from_utf8(contents) {
48                    contents.chars().take(100).collect()
49                } else {
50                    "<INVALID UTF8>".to_string()
51                }
52            );
53            // Remove the quotes around the escaped string.
54            let contents = contents.split_at(contents.len() - 1).0.split_at(1).1;
55            writeln!(
56                w,
57                "n_{}[label=\"{}({}): {}.[{};{}[: {}\"];",
58                i,
59                i,
60                line.scc,
61                line.vertex.change.to_base32(),
62                line.vertex.start.0,
63                line.vertex.end.0,
64                contents
65            )?;
66
67            if add_others && !line.vertex.is_root() {
68                for v in crate::pristine::iter_adj_all(txn, channel, line.vertex).unwrap() {
69                    let v = v.unwrap();
70                    if let Some(dest) = cache.get(&v.dest()) {
71                        writeln!(
72                            w,
73                            "n_{} -> n_{}[color=red,label=\"{:?}{}{}\"];",
74                            i,
75                            dest,
76                            v.flag().bits(),
77                            if introduced_by { " " } else { "" },
78                            if introduced_by {
79                                v.introduced_by().to_base32()
80                            } else {
81                                String::new()
82                            }
83                        )?;
84                    } else {
85                        if !others.contains(&v.dest()) {
86                            others.insert(v.dest());
87                            writeln!(
88                                w,
89                                "n_{}_{}[label=\"{}.{}\",color=red];",
90                                v.dest().change.to_base32(),
91                                v.dest().pos.0,
92                                v.dest().change.to_base32(),
93                                v.dest().pos.0
94                            )?;
95                        }
96                        writeln!(
97                            w,
98                            "n_{} -> n_{}_{}[color=red,label=\"{:?}{}{}\"];",
99                            i,
100                            v.dest().change.to_base32(),
101                            v.dest().pos.0,
102                            v.flag().bits(),
103                            if introduced_by { " " } else { "" },
104                            if introduced_by {
105                                v.introduced_by().to_base32()
106                            } else {
107                                String::new()
108                            }
109                        )?;
110                    }
111                }
112            }
113            for &(edge, VertexId(j)) in (self.children
114                [line.children..line.children + line.n_children])
115                .iter()
116                .chain(line.extra.iter())
117            {
118                if let Some(ref edge) = edge {
119                    writeln!(
120                        w,
121                        "n_{}->n_{}[label=\"{:?}{}{}\"];",
122                        i,
123                        j,
124                        edge.flag().bits(),
125                        if introduced_by { " " } else { "" },
126                        if introduced_by {
127                            edge.introduced_by().to_base32()
128                        } else {
129                            String::new()
130                        }
131                    )?
132                } else {
133                    writeln!(w, "n_{}->n_{}[label=\"none\"];", i, j)?
134                }
135            }
136        }
137        writeln!(w, "}}")?;
138        Ok(())
139    }
140
141    #[allow(dead_code)]
142    pub fn debug_raw<W: Write>(&self, mut w: W) -> Result<(), std::io::Error> {
143        writeln!(w, "digraph {{")?;
144        for (line, i) in self.lines.iter().zip(0..) {
145            // Remove the quotes around the escaped string.
146            writeln!(
147                w,
148                "n_{}[label=\"{}(scc {}): {}.[{};{}[\"];",
149                i,
150                i,
151                line.scc,
152                line.vertex.change.to_base32(),
153                line.vertex.start.0,
154                line.vertex.end.0,
155            )?;
156
157            for &(edge, VertexId(j)) in self.children
158                [line.children..line.children + line.n_children]
159                .iter()
160                .chain(line.extra.iter())
161            {
162                if let Some(ref edge) = edge {
163                    writeln!(
164                        w,
165                        "n_{}->n_{}[label=\"{:?} {}\"];",
166                        i,
167                        j,
168                        edge.flag().bits(),
169                        edge.introduced_by().to_base32()
170                    )?
171                } else {
172                    writeln!(w, "n_{}->n_{}[label=\"none\"];", i, j)?
173                }
174            }
175        }
176        writeln!(w, "}}")?;
177        Ok(())
178    }
179}