summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/puppet/gratr/adjacency_graph.rb41
-rw-r--r--lib/puppet/pgraph.rb17
-rw-r--r--lib/puppet/transaction.rb97
-rwxr-xr-xtest/other/transactions.rb10
4 files changed, 114 insertions, 51 deletions
diff --git a/lib/puppet/gratr/adjacency_graph.rb b/lib/puppet/gratr/adjacency_graph.rb
index bea50e8c8..a02ed0b2f 100644
--- a/lib/puppet/gratr/adjacency_graph.rb
+++ b/lib/puppet/gratr/adjacency_graph.rb
@@ -107,18 +107,43 @@ module GRATR
# * add_edge!(Edge[source,target], "Label")
# * add_edge!(source,target, "Label")
def add_edge!(u, v=nil, l=nil, n=nil)
- n = u.number if u.class.include? EdgeNumber and n.nil?
- u, v, l = u.source, u.target, u.label if u.kind_of? GRATR::Edge
- return self if not @allow_loops and u == v
- n = (@next_edge_number+=1) unless n if @parallel_edges
- add_vertex!(u); add_vertex!(v)
+ if u.class.include? EdgeNumber and n.nil?
+ n = u.number
+ end
+ if u.kind_of? GRATR::Edge
+ edge = u
+ u, v, l = u.source, u.target, u.label
+ end
+ if not @allow_loops and u == v
+ return self
+ end
+ if @parallel_edges and ! n
+ n = (@next_edge_number+=1)
+ end
+ add_vertex!(u);
+ add_vertex!(v)
@vertex_dict[u].add(v)
- (@edge_number[u] ||= @edgelist_class.new).add(n) if @parallel_edges
+
+ if @parallel_edges
+ (@edge_number[u] ||= @edgelist_class.new).add(n)
+ end
unless directed?
@vertex_dict[v].add(u)
- (@edge_number[v] ||= @edgelist_class.new).add(n) if @parallel_edges
+ if @parallel_edges
+ (@edge_number[v] ||= @edgelist_class.new).add(n)
+ end
end
- self[n ? edge_class[u,v,n] : edge_class[u,v]] = l if l
+
+ if l
+ unless edge
+ if n
+ edge = edge_class[u,v,n]
+ else
+ edge = edge_class[u,v]
+ end
+ end
+ self[edge] = l
+ end
self
end
diff --git a/lib/puppet/pgraph.rb b/lib/puppet/pgraph.rb
index 56363f9a9..ce7bc52b8 100644
--- a/lib/puppet/pgraph.rb
+++ b/lib/puppet/pgraph.rb
@@ -60,8 +60,8 @@ class Puppet::PGraph < GRATR::Digraph
# Determine all of the leaf nodes below a given vertex.
def leaves(vertex, type = :dfs)
tree = tree_from_vertex(vertex, type)
- leaves = tree.keys.find_all { |c| adjacent(c, :direction => :out).empty? }
- return leaves
+ l = tree.keys.find_all { |c| adjacent(c, :direction => :out).empty? }
+ return l
end
# Collect all of the edges that the passed events match. Returns
@@ -100,32 +100,33 @@ class Puppet::PGraph < GRATR::Digraph
# to the leaves instead
next unless vertex.is_a?(type)
- leaves = other.leaves(vertex)
- if leaves.empty?
+ #oleaves = other.leaves(vertex)
+ oleaves = other.adjacent(vertex, :direction => :out)
+ if oleaves.empty?
remove_vertex!(vertex)
next
end
# First create new edges for each of the :in edges
adjacent(vertex, :direction => :in, :type => :edges).each do |edge|
- leaves.each do |leaf|
+ oleaves.each do |leaf|
add_edge!(edge.source, leaf, edge.label)
if cyclic?
raise ArgumentError,
"%s => %s results in a loop" %
- [up, leaf]
+ [edge.source, leaf]
end
end
end
# Then for each of the out edges
adjacent(vertex, :direction => :out, :type => :edges).each do |edge|
- leaves.each do |leaf|
+ oleaves.each do |leaf|
add_edge!(leaf, edge.target, edge.label)
if cyclic?
raise ArgumentError,
"%s => %s results in a loop" %
- [leaf, down]
+ [leaf, edge.target]
end
end
end
diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb
index 67d016c15..ff78281ad 100644
--- a/lib/puppet/transaction.rb
+++ b/lib/puppet/transaction.rb
@@ -16,7 +16,10 @@ class Transaction
Puppet.config.setdefaults(:transaction,
:tags => ["", "Tags to use to find resources. If this is set, then
only resources tagged with the specified tags will be applied.
- Values must be comma-separated."]
+ Values must be comma-separated."],
+ :evaltrace => [false, "Whether each resource should log when it is
+ being evaluated. This allows you to interactively see exactly
+ what is being done."]
)
# Add some additional times for reporting
@@ -47,12 +50,12 @@ class Transaction
# If a resource is going to be deleted but it still has dependencies, then
# don't delete it unless it's implicit.
- if ! resource.implicit? and deps = @relgraph.dependents(resource) and ! deps.empty? and changes.detect { |change|
- change.state.name == :ensure and change.should == :absent
- }
- resource.warning "%s still depend%s on me -- not deleting" %
- [deps.collect { |r| r.ref }.join(","), if deps.length > 1; ""; else "s"; end]
- return []
+ if ! resource.implicit? and deleting?(changes)
+ if deps = @relgraph.dependents(resource) and ! deps.empty?
+ resource.warning "%s still depend%s on me -- not deleting" %
+ [deps.collect { |r| r.ref }.join(","), if deps.length > 1; ""; else "s"; end]
+ return []
+ end
end
unless changes.is_a? Array
@@ -126,42 +129,62 @@ class Transaction
end
@resources.clear
end
-
+
+ # Copy an important relationships from the parent to the newly-generated
+ # child resource.
+ def copy_relationships(resource, children)
+ depthfirst = resource.depthfirst?
+
+ # We only have to worry about dependents, because any dependencies
+ # already missed their chance to register an event for us.
+ dependents = @relgraph.adjacent(resource,
+ :direction => :out, :type => :edges).reject { |e| ! e.callback }
+
+ #sources = @relgraph.adjacent(resource,
+ # :direction => :in, :type => :edges).reject { |e| ! e.callback }
+
+ children.each do |gen_child|
+ if depthfirst
+ @relgraph.add_edge!(gen_child, resource)
+ else
+ @relgraph.add_edge!(resource, gen_child)
+ end
+ dependents.each do |edge|
+ @relgraph.add_edge!(gen_child, edge.target, edge.label)
+ end
+ #sources.each do |edge|
+ # @relgraph.add_edge!(edge.source, gen_child, edge.label)
+ #end
+ end
+ end
+
+ # Are we deleting this resource?
+ def deleting?(changes)
+ changes.detect { |change|
+ change.state.name == :ensure and change.should == :absent
+ }
+ end
+
# See if the resource generates new resources at evaluation time.
def eval_generate(resource)
if resource.respond_to?(:eval_generate)
if children = resource.eval_generate
- depthfirst = resource.depthfirst?
- dependents = @relgraph.adjacent(resource, :direction => :out, :type => :edges)
- targets = @relgraph.adjacent(resource, :direction => :in, :type => :edges)
- children.each do |gen_child|
- if depthfirst
- @relgraph.add_edge!(gen_child, resource)
- else
- @relgraph.add_edge!(resource, gen_child)
- end
- dependents.each do |edge|
- @relgraph.add_edge!(gen_child, edge.target, edge.label)
- end
- targets.each do |edge|
- @relgraph.add_edge!(edge.source, gen_child, edge.label)
- end
- @generated << gen_child
- end
+ copy_relationships(resource, children)
+ @generated += children
return children
end
end
end
# Evaluate a single resource.
- def eval_resource(resource)
+ def eval_resource(resource, checkskip = true)
events = []
if resource.is_a?(Puppet::Type::Component)
raise Puppet::DevError, "Got a component to evaluate"
end
- if skip?(resource)
+ if checkskip and skip?(resource)
@resourcemetrics[:skipped] += 1
else
@resourcemetrics[:scheduled] += 1
@@ -172,7 +195,8 @@ class Transaction
if resource.depthfirst? and children
children.each do |child|
- events += eval_resource(child)
+ # The child will never be skipped when the parent isn't
+ events += eval_resource(child, false)
end
end
@@ -180,7 +204,7 @@ class Transaction
seconds = thinmark do
events += apply(resource)
end
-
+
if ! resource.depthfirst? and children
children.each do |child|
events += eval_resource(child)
@@ -218,13 +242,23 @@ class Transaction
begin
allevents = @sorted_resources.collect { |resource|
- eval_resource(resource)
+ ret = nil
+ seconds = thinmark do
+ ret = eval_resource(resource)
+ end
+
+ if Puppet[:evaltrace]
+ resource.info "Evaluated in %0.2f seconds" % seconds
+ end
+ ret
}.flatten.reject { |e| e.nil? }
ensure
# And then close the transaction log.
Puppet::Log.close(@report)
end
+ @relgraph.to_jpg(File.expand_path("~/tmp/graphs"), "simple_relgraph")
+
Puppet.debug "Finishing transaction %s with %s changes" %
[self.object_id, @count]
@@ -247,7 +281,8 @@ class Transaction
# enough to check the immediate dependencies, which is why we use
# a tree from the reversed graph.
skip = false
- @relgraph.dependencies(resource).each do |dep|
+ deps = @relgraph.dependencies(resource)
+ deps.each do |dep|
if fails = failed?(dep)
resource.notice "Dependency %s[%s] has %s failures" %
[dep.class.name, dep.name, @failures[dep]]
diff --git a/test/other/transactions.rb b/test/other/transactions.rb
index d9a173986..2ae4b1b13 100755
--- a/test/other/transactions.rb
+++ b/test/other/transactions.rb
@@ -677,10 +677,12 @@ class TestTransactions < Test::Unit::TestCase
assert(trans.relgraph.vertex?(ra),
"Did not add ra to rel_graph" % name)
- # Now make sure this generated resource has the same relationships as the generating
- # resource
- assert(trans.relgraph.edge?(yay, ra),
- "yay is not required by ra")
+ # Now make sure this generated resource has the same relationships as
+ # the generating resource
+ #assert(trans.relgraph.edge?(yay, ra),
+ # "yay is not required by ra")
+ assert(trans.relgraph.edge?(ya, rah),
+ "rah is not subscribed to ya")
assert(trans.relgraph.edge?(ya, ra),
"ra is not subscribed to ya")