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  }