github.com/ves/terraform@v0.8.0-beta2/dag/dag.go (about) 1 package dag 2 3 import ( 4 "fmt" 5 "log" 6 "sort" 7 "strings" 8 "sync" 9 "time" 10 11 "github.com/hashicorp/go-multierror" 12 ) 13 14 // AcyclicGraph is a specialization of Graph that cannot have cycles. With 15 // this property, we get the property of sane graph traversal. 16 type AcyclicGraph struct { 17 Graph 18 } 19 20 // WalkFunc is the callback used for walking the graph. 21 type WalkFunc func(Vertex) error 22 23 // DepthWalkFunc is a walk function that also receives the current depth of the 24 // walk as an argument 25 type DepthWalkFunc func(Vertex, int) error 26 27 func (g *AcyclicGraph) DirectedGraph() Grapher { 28 return g 29 } 30 31 // Returns a Set that includes every Vertex yielded by walking down from the 32 // provided starting Vertex v. 33 func (g *AcyclicGraph) Ancestors(v Vertex) (*Set, error) { 34 s := new(Set) 35 start := AsVertexList(g.DownEdges(v)) 36 memoFunc := func(v Vertex, d int) error { 37 s.Add(v) 38 return nil 39 } 40 41 if err := g.DepthFirstWalk(start, memoFunc); err != nil { 42 return nil, err 43 } 44 45 return s, nil 46 } 47 48 // Returns a Set that includes every Vertex yielded by walking up from the 49 // provided starting Vertex v. 50 func (g *AcyclicGraph) Descendents(v Vertex) (*Set, error) { 51 s := new(Set) 52 start := AsVertexList(g.UpEdges(v)) 53 memoFunc := func(v Vertex, d int) error { 54 s.Add(v) 55 return nil 56 } 57 58 if err := g.ReverseDepthFirstWalk(start, memoFunc); err != nil { 59 return nil, err 60 } 61 62 return s, nil 63 } 64 65 // Root returns the root of the DAG, or an error. 66 // 67 // Complexity: O(V) 68 func (g *AcyclicGraph) Root() (Vertex, error) { 69 roots := make([]Vertex, 0, 1) 70 for _, v := range g.Vertices() { 71 if g.UpEdges(v).Len() == 0 { 72 roots = append(roots, v) 73 } 74 } 75 76 if len(roots) > 1 { 77 // TODO(mitchellh): make this error message a lot better 78 return nil, fmt.Errorf("multiple roots: %#v", roots) 79 } 80 81 if len(roots) == 0 { 82 return nil, fmt.Errorf("no roots found") 83 } 84 85 return roots[0], nil 86 } 87 88 // TransitiveReduction performs the transitive reduction of graph g in place. 89 // The transitive reduction of a graph is a graph with as few edges as 90 // possible with the same reachability as the original graph. This means 91 // that if there are three nodes A => B => C, and A connects to both 92 // B and C, and B connects to C, then the transitive reduction is the 93 // same graph with only a single edge between A and B, and a single edge 94 // between B and C. 95 // 96 // The graph must be valid for this operation to behave properly. If 97 // Validate() returns an error, the behavior is undefined and the results 98 // will likely be unexpected. 99 // 100 // Complexity: O(V(V+E)), or asymptotically O(VE) 101 func (g *AcyclicGraph) TransitiveReduction() { 102 // For each vertex u in graph g, do a DFS starting from each vertex 103 // v such that the edge (u,v) exists (v is a direct descendant of u). 104 // 105 // For each v-prime reachable from v, remove the edge (u, v-prime). 106 defer g.debug.BeginOperation("TransitiveReduction", "").End("") 107 108 for _, u := range g.Vertices() { 109 uTargets := g.DownEdges(u) 110 vs := AsVertexList(g.DownEdges(u)) 111 112 g.DepthFirstWalk(vs, func(v Vertex, d int) error { 113 shared := uTargets.Intersection(g.DownEdges(v)) 114 for _, vPrime := range AsVertexList(shared) { 115 g.RemoveEdge(BasicEdge(u, vPrime)) 116 } 117 118 return nil 119 }) 120 } 121 } 122 123 // Validate validates the DAG. A DAG is valid if it has a single root 124 // with no cycles. 125 func (g *AcyclicGraph) Validate() error { 126 if _, err := g.Root(); err != nil { 127 return err 128 } 129 130 // Look for cycles of more than 1 component 131 var err error 132 cycles := g.Cycles() 133 if len(cycles) > 0 { 134 for _, cycle := range cycles { 135 cycleStr := make([]string, len(cycle)) 136 for j, vertex := range cycle { 137 cycleStr[j] = VertexName(vertex) 138 } 139 140 err = multierror.Append(err, fmt.Errorf( 141 "Cycle: %s", strings.Join(cycleStr, ", "))) 142 } 143 } 144 145 // Look for cycles to self 146 for _, e := range g.Edges() { 147 if e.Source() == e.Target() { 148 err = multierror.Append(err, fmt.Errorf( 149 "Self reference: %s", VertexName(e.Source()))) 150 } 151 } 152 153 return err 154 } 155 156 func (g *AcyclicGraph) Cycles() [][]Vertex { 157 var cycles [][]Vertex 158 for _, cycle := range StronglyConnected(&g.Graph) { 159 if len(cycle) > 1 { 160 cycles = append(cycles, cycle) 161 } 162 } 163 return cycles 164 } 165 166 // Walk walks the graph, calling your callback as each node is visited. 167 // This will walk nodes in parallel if it can. Because the walk is done 168 // in parallel, the error returned will be a multierror. 169 func (g *AcyclicGraph) Walk(cb WalkFunc) error { 170 defer g.debug.BeginOperation("Walk", "").End("") 171 172 // Cache the vertices since we use it multiple times 173 vertices := g.Vertices() 174 175 // Build the waitgroup that signals when we're done 176 var wg sync.WaitGroup 177 wg.Add(len(vertices)) 178 doneCh := make(chan struct{}) 179 go func() { 180 defer close(doneCh) 181 wg.Wait() 182 }() 183 184 // The map of channels to watch to wait for vertices to finish 185 vertMap := make(map[Vertex]chan struct{}) 186 for _, v := range vertices { 187 vertMap[v] = make(chan struct{}) 188 } 189 190 // The map of whether a vertex errored or not during the walk 191 var errLock sync.Mutex 192 var errs error 193 errMap := make(map[Vertex]bool) 194 for _, v := range vertices { 195 // Build our list of dependencies and the list of channels to 196 // wait on until we start executing for this vertex. 197 deps := AsVertexList(g.DownEdges(v)) 198 depChs := make([]<-chan struct{}, len(deps)) 199 for i, dep := range deps { 200 depChs[i] = vertMap[dep] 201 } 202 203 // Get our channel so that we can close it when we're done 204 ourCh := vertMap[v] 205 206 // Start the goroutine to wait for our dependencies 207 readyCh := make(chan bool) 208 go func(v Vertex, deps []Vertex, chs []<-chan struct{}, readyCh chan<- bool) { 209 // First wait for all the dependencies 210 for i, ch := range chs { 211 DepSatisfied: 212 for { 213 select { 214 case <-ch: 215 break DepSatisfied 216 case <-time.After(time.Second * 5): 217 log.Printf("[DEBUG] vertex %q, waiting for: %q", 218 VertexName(v), VertexName(deps[i])) 219 } 220 } 221 log.Printf("[DEBUG] vertex %q, got dep: %q", 222 VertexName(v), VertexName(deps[i])) 223 } 224 225 // Then, check the map to see if any of our dependencies failed 226 errLock.Lock() 227 defer errLock.Unlock() 228 for _, dep := range deps { 229 if errMap[dep] { 230 errMap[v] = true 231 readyCh <- false 232 return 233 } 234 } 235 236 readyCh <- true 237 }(v, deps, depChs, readyCh) 238 239 // Start the goroutine that executes 240 go func(v Vertex, doneCh chan<- struct{}, readyCh <-chan bool) { 241 defer close(doneCh) 242 defer wg.Done() 243 244 var err error 245 if ready := <-readyCh; ready { 246 err = cb(v) 247 } 248 249 errLock.Lock() 250 defer errLock.Unlock() 251 if err != nil { 252 errMap[v] = true 253 errs = multierror.Append(errs, err) 254 } 255 }(v, ourCh, readyCh) 256 } 257 258 <-doneCh 259 return errs 260 } 261 262 // simple convenience helper for converting a dag.Set to a []Vertex 263 func AsVertexList(s *Set) []Vertex { 264 rawList := s.List() 265 vertexList := make([]Vertex, len(rawList)) 266 for i, raw := range rawList { 267 vertexList[i] = raw.(Vertex) 268 } 269 return vertexList 270 } 271 272 type vertexAtDepth struct { 273 Vertex Vertex 274 Depth int 275 } 276 277 // depthFirstWalk does a depth-first walk of the graph starting from 278 // the vertices in start. This is not exported now but it would make sense 279 // to export this publicly at some point. 280 func (g *AcyclicGraph) DepthFirstWalk(start []Vertex, f DepthWalkFunc) error { 281 defer g.debug.BeginOperation("DepthFirstWalk", "").End("") 282 283 seen := make(map[Vertex]struct{}) 284 frontier := make([]*vertexAtDepth, len(start)) 285 for i, v := range start { 286 frontier[i] = &vertexAtDepth{ 287 Vertex: v, 288 Depth: 0, 289 } 290 } 291 for len(frontier) > 0 { 292 // Pop the current vertex 293 n := len(frontier) 294 current := frontier[n-1] 295 frontier = frontier[:n-1] 296 297 // Check if we've seen this already and return... 298 if _, ok := seen[current.Vertex]; ok { 299 continue 300 } 301 seen[current.Vertex] = struct{}{} 302 303 // Visit the current node 304 if err := f(current.Vertex, current.Depth); err != nil { 305 return err 306 } 307 308 // Visit targets of this in a consistent order. 309 targets := AsVertexList(g.DownEdges(current.Vertex)) 310 sort.Sort(byVertexName(targets)) 311 for _, t := range targets { 312 frontier = append(frontier, &vertexAtDepth{ 313 Vertex: t, 314 Depth: current.Depth + 1, 315 }) 316 } 317 } 318 319 return nil 320 } 321 322 // reverseDepthFirstWalk does a depth-first walk _up_ the graph starting from 323 // the vertices in start. 324 func (g *AcyclicGraph) ReverseDepthFirstWalk(start []Vertex, f DepthWalkFunc) error { 325 defer g.debug.BeginOperation("ReverseDepthFirstWalk", "").End("") 326 327 seen := make(map[Vertex]struct{}) 328 frontier := make([]*vertexAtDepth, len(start)) 329 for i, v := range start { 330 frontier[i] = &vertexAtDepth{ 331 Vertex: v, 332 Depth: 0, 333 } 334 } 335 for len(frontier) > 0 { 336 // Pop the current vertex 337 n := len(frontier) 338 current := frontier[n-1] 339 frontier = frontier[:n-1] 340 341 // Check if we've seen this already and return... 342 if _, ok := seen[current.Vertex]; ok { 343 continue 344 } 345 seen[current.Vertex] = struct{}{} 346 347 // Add next set of targets in a consistent order. 348 targets := AsVertexList(g.UpEdges(current.Vertex)) 349 sort.Sort(byVertexName(targets)) 350 for _, t := range targets { 351 frontier = append(frontier, &vertexAtDepth{ 352 Vertex: t, 353 Depth: current.Depth + 1, 354 }) 355 } 356 357 // Visit the current node 358 if err := f(current.Vertex, current.Depth); err != nil { 359 return err 360 } 361 } 362 363 return nil 364 } 365 366 // byVertexName implements sort.Interface so a list of Vertices can be sorted 367 // consistently by their VertexName 368 type byVertexName []Vertex 369 370 func (b byVertexName) Len() int { return len(b) } 371 func (b byVertexName) Swap(i, j int) { b[i], b[j] = b[j], b[i] } 372 func (b byVertexName) Less(i, j int) bool { 373 return VertexName(b[i]) < VertexName(b[j]) 374 }