diff options
-rw-r--r-- | lib/puppet/pgraph.rb | 19 | ||||
-rw-r--r-- | lib/puppet/transaction.rb | 5 | ||||
-rwxr-xr-x | test/other/pgraph.rb | 97 | ||||
-rwxr-xr-x | test/other/transactions.rb | 2 |
4 files changed, 96 insertions, 27 deletions
diff --git a/lib/puppet/pgraph.rb b/lib/puppet/pgraph.rb index af8e720cb..fe55533d9 100644 --- a/lib/puppet/pgraph.rb +++ b/lib/puppet/pgraph.rb @@ -1,5 +1,3 @@ -#!/usr/bin/env ruby -# # Created by Luke A. Kanies on 2006-11-24. # Copyright (c) 2006. All rights reserved. @@ -51,8 +49,7 @@ class Puppet::PGraph < GRATR::Digraph end # Fail in a somewhat informative way if the graph has become cyclic. - def check_cycle - sorted = topsort() + def check_cycle(sorted) return true if sorted.size == size() bad = [] @@ -120,20 +117,19 @@ class Puppet::PGraph < GRATR::Digraph # This creates direct relationships where there were previously # indirect relationships through the containers. def splice!(other, type) - vertices.find_all { |v| v.is_a?(type) }.each do |vertex| + vertices.find_all { |v| v.is_a?(type) }.each do |container| # Get the list of children from the other graph. - #children = other.adjacent(vertex, :direction => :out) - children = other.leaves(vertex) + children = other.adjacent(container, :direction => :out) # Just remove the container if it's empty. if children.empty? - remove_vertex!(vertex) + remove_vertex!(container) next end # First create new edges for each of the :in edges [:in, :out].each do |dir| - adjacent(vertex, :direction => dir, :type => :edges).each do |edge| + adjacent(container, :direction => dir, :type => :edges).each do |edge| children.each do |child| if dir == :in s = edge.source @@ -160,9 +156,12 @@ class Puppet::PGraph < GRATR::Digraph [s, t] end end + + # Now get rid of the edge, so remove_vertex! works correctly. + remove_edge!(edge) end end - remove_vertex!(vertex) + remove_vertex!(container) end end diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb index 43ee135a6..2a83ea630 100644 --- a/lib/puppet/transaction.rb +++ b/lib/puppet/transaction.rb @@ -474,6 +474,9 @@ class Transaction @relgraph = relationship_graph @sorted_resources = @relgraph.topsort + + # Now make sure no cycles crept into our graph. + @relgraph.check_cycle(@sorted_resources) end # Create a graph of all of the relationships in our resource graph. @@ -507,8 +510,6 @@ class Transaction # Then splice in the container information graph.splice!(@resources, Puppet::Type::Component) - graph.check_cycle - graph(graph, :expanded_relationships) return graph diff --git a/test/other/pgraph.rb b/test/other/pgraph.rb index e28decebb..b61241087 100755 --- a/test/other/pgraph.rb +++ b/test/other/pgraph.rb @@ -75,37 +75,33 @@ class TestPGraph < Test::Unit::TestCase empty = Container.new("empty", []) # Also, add an empty container to top top.push empty - + contgraph = top.to_graph - + # Now add a couple of child files, so that we can test whether all # containers get spliced, rather than just components. - + # Now make a dependency graph deps = Puppet::PGraph.new - + contgraph.vertices.each do |v| deps.add_vertex(v) end - + # We have to specify a relationship to our empty container, else it # never makes it into the dep graph in the first place. - #{one => two, three => [middle, two, "c"], "f" => "c", "h" => middle, "c" => empty}.each do |source, targets| {one => two, "f" => "c", "h" => middle, "c" => empty}.each do |source, target| deps.add_edge!(source, target, :callback => :refresh) end - - #num = 6 - #contgraph.to_jpg(File.expand_path("~/tmp/graphs"), "containers#{num}") - #contgraph.reversal.to_jpg(File.expand_path("~/tmp/graphs"), "reversal#{num}") - #deps.to_jpg(File.expand_path("~/tmp/graphs"), "relationships#{num}") + #contgraph.to_jpg(File.expand_path("~/Desktop/pics"), "main") + #deps.to_jpg(File.expand_path("~/Desktop/pics"), "before") assert_nothing_raised { deps.splice!(contgraph, Container) } - #deps.to_jpg(File.expand_path("~/tmp/graphs"), "after_relationships#{num}") assert(! deps.cyclic?, "Created a cyclic graph") # Make sure there are no container objects remaining + #deps.to_jpg(File.expand_path("~/Desktop/pics"), "after") c = deps.vertices.find_all { |v| v.is_a?(Container) } assert(c.empty?, "Still have containers %s" % c.inspect) @@ -206,15 +202,88 @@ class TestPGraph < Test::Unit::TestCase if result assert_raise(Puppet::Error, "%s did not fail" % hash.inspect) do - graph.check_cycle + graph.check_cycle(graph.topsort) end else assert_nothing_raised("%s failed" % hash.inspect) do - graph.check_cycle + graph.check_cycle(graph.topsort) end end end end + + # This isn't really a unit test, it's just a way to do some graphing with + # tons of relationships so we can see how it performs. + def disabled_test_lots_of_relationships + containers = Puppet::PGraph.new + relationships = Puppet::PGraph.new + labels = %w{a b c d e} + conts = {} + vertices = {} + labels.each do |label| + vertices[label] = [] + end + num = 100 + num.times do |i| + labels.each do |label| + vertices[label] << ("%s%s" % [label, i]) + end + end + labels.each do |label| + conts[label] = Container.new(label, vertices[label]) + end + + conts.each do |label, cont| + cont.each do |child| + containers.add_edge!(cont, child) + end + end + prev = nil + labels.inject(nil) do |prev, label| + if prev + containers.add_edge!(conts[prev], conts[label]) + end + label + end + + containers.to_jpg(File.expand_path("~/Desktop/pics/lots"), "start") + + # Now create the relationship graph + + # Make everything in both b and c require d1 + %w{b c}.each do |label| + conts[label].each do |v| + relationships.add_edge!(v, "d1") + #relationships.add_edge!(v, conts["d"]) + end + end + + # Make most in b also require the appropriate thing in c + conts["b"].each do |v| + i = v.split('')[1] + + relationships.add_edge!(v, "c%s" % i) + end + + # And make d1 require most of e + num.times do |i| + relationships.add_edge!("d1", "e%s" % i) + end + + containers.vertices.each do |v| + relationships.add_vertex!(v) + end + relationships.to_jpg(File.expand_path("~/Desktop/pics/lots"), "relationships") + + time = Benchmark.realtime do + relationships.splice!(containers, Container) + end + relationships.to_jpg(File.expand_path("~/Desktop/pics/lots"), "final") + puts time + time = Benchmark.realtime do + relationships.topsort + end + end end # $Id$ diff --git a/test/other/transactions.rb b/test/other/transactions.rb index e90952a70..3129116e7 100755 --- a/test/other/transactions.rb +++ b/test/other/transactions.rb @@ -1000,7 +1000,7 @@ class TestTransactions < Test::Unit::TestCase trans = newcomp(one, two).evaluate assert_raise(Puppet::Error) do - trans.relationship_graph + trans.prepare end end |