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