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