Class: Puppet::Transaction::Relationship_graph_wrapper
- Defined in:
- lib/puppet/transaction.rb
Overview
We want to monitor changes in the relationship graph of our catalog but this is complicated by the fact that the catalog both is_a graph and has_a graph, by the fact that changes to the structure of the object can have adverse serialization effects, by threading issues, by order-of-initialization issues, etc.
Since the proper lifetime/scope of the monitoring is a transaction and the transaction is already commiting a mild law-of-demeter transgression, we cut the Gordian knot here by simply wrapping the transaction’s view of the resource graph to capture and maintain the information we need. Nothing outside the transaction needs this information, and nothing outside the transaction can see it except via the Transaction#relationship_graph
Instance Attribute Summary collapse
-
#blockers ⇒ Object
readonly
Returns the value of attribute blockers.
-
#done ⇒ Object
readonly
Returns the value of attribute done.
-
#generated ⇒ Object
readonly
Returns the value of attribute generated.
-
#ready ⇒ Object
readonly
Returns the value of attribute ready.
-
#real_graph ⇒ Object
readonly
Returns the value of attribute real_graph.
-
#transaction ⇒ Object
readonly
Returns the value of attribute transaction.
-
#unguessable_deterministic_key ⇒ Object
readonly
Returns the value of attribute unguessable_deterministic_key.
Instance Method Summary collapse
- #add_edge(f, t, label = nil) ⇒ Object
- #add_vertex(v) ⇒ Object
- #enqueue(*resources) ⇒ Object
- #fail_unsuitable_resources(resources) ⇒ Object
- #finish(resource) ⇒ Object
-
#initialize(real_graph, transaction) ⇒ Relationship_graph_wrapper
constructor
A new instance of Relationship_graph_wrapper.
- #method_missing(*args, &block) ⇒ Object
- #next_resource ⇒ Object
- #traverse(&block) ⇒ Object
-
#unblock(resource) ⇒ Object
Decrement the blocker count for the resource by 1.
Constructor Details
#initialize(real_graph, transaction) ⇒ Relationship_graph_wrapper
Returns a new instance of Relationship_graph_wrapper.
311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
# File 'lib/puppet/transaction.rb', line 311 def initialize(real_graph,transaction) @real_graph = real_graph @transaction = transaction @ready = Puppet::RbTreeMap.new @generated = {} @done = {} @blockers = {} @unguessable_deterministic_key = Hash.new { |h,k| h[k] = Digest::SHA1.hexdigest("NaCl, MgSO4 (salts) and then #{k.ref}") } @providerless_types = [] vertices.each do |v| blockers[v] = direct_dependencies_of(v).length enqueue(v) if blockers[v] == 0 end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(*args, &block) ⇒ Object
325 326 327 |
# File 'lib/puppet/transaction.rb', line 325 def method_missing(*args,&block) real_graph.send(*args,&block) end |
Instance Attribute Details
#blockers ⇒ Object (readonly)
Returns the value of attribute blockers.
310 311 312 |
# File 'lib/puppet/transaction.rb', line 310 def blockers @blockers end |
#done ⇒ Object (readonly)
Returns the value of attribute done.
310 311 312 |
# File 'lib/puppet/transaction.rb', line 310 def done @done end |
#generated ⇒ Object (readonly)
Returns the value of attribute generated.
310 311 312 |
# File 'lib/puppet/transaction.rb', line 310 def generated @generated end |
#ready ⇒ Object (readonly)
Returns the value of attribute ready.
310 311 312 |
# File 'lib/puppet/transaction.rb', line 310 def ready @ready end |
#real_graph ⇒ Object (readonly)
Returns the value of attribute real_graph.
310 311 312 |
# File 'lib/puppet/transaction.rb', line 310 def real_graph @real_graph end |
#transaction ⇒ Object (readonly)
Returns the value of attribute transaction.
310 311 312 |
# File 'lib/puppet/transaction.rb', line 310 def transaction @transaction end |
#unguessable_deterministic_key ⇒ Object (readonly)
Returns the value of attribute unguessable_deterministic_key.
310 311 312 |
# File 'lib/puppet/transaction.rb', line 310 def unguessable_deterministic_key @unguessable_deterministic_key end |
Instance Method Details
#add_edge(f, t, label = nil) ⇒ Object
331 332 333 334 335 336 337 |
# File 'lib/puppet/transaction.rb', line 331 def add_edge(f,t,label=nil) key = unguessable_deterministic_key[t] ready.delete(key) real_graph.add_edge(f,t,label) end |
#add_vertex(v) ⇒ Object
328 329 330 |
# File 'lib/puppet/transaction.rb', line 328 def add_vertex(v) real_graph.add_vertex(v) end |
#enqueue(*resources) ⇒ Object
349 350 351 352 353 354 |
# File 'lib/puppet/transaction.rb', line 349 def enqueue(*resources) resources.each do |resource| key = unguessable_deterministic_key[resource] ready[key] = resource end end |
#fail_unsuitable_resources(resources) ⇒ Object
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 |
# File 'lib/puppet/transaction.rb', line 405 def fail_unsuitable_resources(resources) resources.each do |resource| # We don't automatically assign unsuitable providers, so if there # is one, it must have been selected by the user. if resource.provider resource.err "Provider #{resource.provider.class.name} is not functional on this host" else @providerless_types << resource.type end transaction.resource_status(resource).failed = true finish(resource) end end |
#finish(resource) ⇒ Object
355 356 357 358 359 360 |
# File 'lib/puppet/transaction.rb', line 355 def finish(resource) direct_dependents_of(resource).each do |v| enqueue(v) if unblock(v) end done[resource] = true end |
#next_resource ⇒ Object
361 362 363 |
# File 'lib/puppet/transaction.rb', line 361 def next_resource ready.delete_min end |
#traverse(&block) ⇒ Object
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 |
# File 'lib/puppet/transaction.rb', line 364 def traverse(&block) real_graph.report_cycles_in_graph deferred_resources = [] while (resource = next_resource) && !transaction.stop_processing? if resource.suitable? made_progress = true transaction.prefetch_if_necessary(resource) # If we generated resources, we don't know what they are now # blocking, so we opt to recompute it, rather than try to track every # change that would affect the number. blockers.clear if transaction.eval_generate(resource) yield resource finish(resource) else deferred_resources << resource end if ready.empty? and deferred_resources.any? if made_progress enqueue(*deferred_resources) else fail_unsuitable_resources(deferred_resources) end made_progress = false deferred_resources = [] end end # Just once per type. No need to punish the user. @providerless_types.uniq.each do |type| Puppet.err "Could not find a suitable provider for #{type}" end end |
#unblock(resource) ⇒ Object
Decrement the blocker count for the resource by 1. If the number of blockers is unknown, count them and THEN decrement by 1.
340 341 342 343 344 345 346 347 348 |
# File 'lib/puppet/transaction.rb', line 340 def unblock(resource) blockers[resource] ||= direct_dependencies_of(resource).select { |r2| !done[r2] }.length if blockers[resource] > 0 blockers[resource] -= 1 else resource.warning "appears to have a negative number of dependencies" end blockers[resource] <= 0 end |