1 use crate::{ 2 error::parse_error::{ParseError, ParseErrorType}, 3 unit::UnitType, 4 }; 5 6 use std::io::BufRead; 7 use std::string::{String, ToString}; 8 use std::vec::Vec; 9 10 use super::UnitParser; 11 12 pub struct GraphNode { 13 value: String, 14 edges: Vec<usize>, 15 incoming_edges: Vec<usize>, 16 } 17 18 pub struct Graph { 19 total_edge: u32, 20 max_edge: u32, 21 nodes: Vec<GraphNode>, 22 value: Vec<String>, 23 } 24 25 impl Graph { 26 fn new() -> Self { 27 return Graph { 28 max_edge: 0, 29 total_edge: 0, 30 nodes: Vec::new(), 31 value: Vec::new(), 32 }; 33 } 34 35 pub fn add_node(&mut self, value: &String) -> usize { 36 let index = self.nodes.len(); 37 //如果nodes中已经有了这个value则无需重复添加,直接返回nodes中的value对应的index 38 if let Some(idx) = self.value.iter().position(|x| *x == *value) { 39 return idx; 40 } 41 //如果value在nodes中不存在,则添加value 42 self.nodes.push(GraphNode { 43 value: value.to_string(), 44 edges: Vec::new(), 45 incoming_edges: Vec::new(), 46 }); 47 self.value.push(value.to_string()); 48 return index; 49 } 50 pub fn add_edge(&mut self, from: usize, to: usize) { 51 self.total_edge += 1; 52 self.nodes[from].edges.push(to); 53 self.nodes[to].incoming_edges.push(from); 54 } 55 pub fn topological_sort(&mut self) -> Result<Vec<String>, ParseError> { 56 let mut result = Vec::new(); 57 let mut visited = Vec::new(); 58 let mut stack = Vec::new(); 59 for (i, node) in self.nodes.iter().enumerate() { 60 if node.incoming_edges.len() == 0 { 61 stack.push(i); 62 } 63 } 64 while stack.len() > 0 { 65 let index = stack.pop().unwrap(); 66 if visited.contains(&index) { 67 continue; 68 } 69 visited.push(index); 70 result.push(self.nodes[index].value.clone()); 71 let len = self.nodes[index].edges.len(); 72 for i in 0..len { 73 let edge = self.nodes[index].edges[i]; 74 self.nodes[edge].incoming_edges.retain(|&x| x != index); 75 if self.nodes[edge].incoming_edges.len() == 0 { 76 stack.push(edge); 77 } 78 } 79 } 80 if result.len() != self.nodes.len() { 81 return Err(ParseError::new( 82 ParseErrorType::ECircularDependency, 83 "".to_string(), 84 0, 85 )); 86 } 87 result.reverse(); 88 return Ok(result); 89 } 90 91 fn add_edges(&mut self, path: &String, after: Vec<String>) { 92 //因为service的依赖关系规模不会很大,故先使用递归实现 93 //TODO:改递归 94 for target in after { 95 let s = self.add_node(&path); 96 let t = self.add_node(&target); 97 self.add_edge(s, t); 98 if self.total_edge > self.max_edge { 99 return; 100 } 101 self.add_edges(&target, Self::parse_after(&target)); 102 } 103 } 104 105 // TODO: 完善这里,目前还是可能会有循环依赖的问题,因为目前只判断了After字段,其他字段也有可能导致循环依赖问题 106 pub fn construct_graph(unit: String) -> Result<Graph, ParseError> { 107 //计算整个依赖图中的节点数 108 let mut node_num = 1; 109 let mut dep = Vec::new(); 110 Self::get_node_num(&unit, &mut dep, &mut node_num)?; 111 112 let mut graph: Graph = Graph::new(); 113 graph.max_edge = node_num * (node_num - 1); 114 115 graph.add_node(&unit); 116 let after = Self::parse_after(&unit); 117 //递归添加边来构建图 118 graph.add_edges(&unit, after); 119 120 if graph.max_edge < graph.total_edge { 121 return Err(ParseError::new( 122 ParseErrorType::ECircularDependency, 123 unit, 124 0, 125 )); 126 } 127 128 return Ok(graph); 129 } 130 131 pub fn parse_after(path: &String) -> Vec<String> { 132 let mut ret = Vec::new(); 133 134 let reader = UnitParser::get_reader(path, UnitType::Unknown).unwrap(); 135 136 let mut lines_with_after = Vec::new(); 137 138 for line_result in reader.lines() { 139 if let Ok(line) = line_result { 140 if line.starts_with("After") { 141 lines_with_after.push(line); 142 } 143 } 144 } 145 146 for line in lines_with_after { 147 let after = &line.split('=').collect::<Vec<&str>>()[1]; 148 let units = after.split_whitespace().collect::<Vec<&str>>(); 149 150 for unit in units { 151 ret.push(String::from(unit)); 152 } 153 } 154 155 ret 156 } 157 158 /// ## 获取到unit文件依赖图节点数 159 /// 160 /// ### param file_path unit文件路径 161 /// 162 /// ### dependencies 缓存after依赖的容器 163 /// 164 /// ### total_after_count 返回节点数 165 /// 166 /// ### return 167 fn get_node_num( 168 file_path: &str, 169 dependencies: &mut Vec<String>, 170 total_after_count: &mut u32, 171 ) -> Result<(), ParseError> { 172 let reader = UnitParser::get_reader(file_path, UnitType::Unknown)?; 173 174 let mut current_after_count = 0; 175 176 for line_result in reader.lines() { 177 if let Ok(line) = line_result { 178 if line.starts_with("After=") { 179 let dependencies_str = &line[6..]; 180 let dependency_list: Vec<&str> = dependencies_str.split_whitespace().collect(); 181 182 for dependency in dependency_list { 183 if dependencies.contains(&dependency.to_string()) { 184 // 循环依赖检查 185 continue; 186 } 187 188 dependencies.push(dependency.to_string()); 189 190 // 递归解析依赖链 191 Self::get_node_num(dependency, dependencies, total_after_count)?; 192 } 193 194 current_after_count += 1; 195 } 196 } 197 } 198 199 *total_after_count += current_after_count; 200 201 Ok(()) 202 } 203 } 204