Class: Puppet::Transaction::Relationship_graph_wrapper
- Defined in:
- lib/vendor/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
-
#enqueue_roots ⇒ Object
Enqueue the initial set of resources, those with no dependencies.
- #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.
312 313 314 315 316 317 318 319 320 321 |
# File 'lib/vendor/puppet/transaction.rb', line 312 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 = [] end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(*args, &block) ⇒ Object
322 323 324 |
# File 'lib/vendor/puppet/transaction.rb', line 322 def method_missing(*args,&block) real_graph.send(*args,&block) end |
Instance Attribute Details
#blockers ⇒ Object (readonly)
Returns the value of attribute blockers.
311 312 313 |
# File 'lib/vendor/puppet/transaction.rb', line 311 def blockers @blockers end |
#done ⇒ Object (readonly)
Returns the value of attribute done.
311 312 313 |
# File 'lib/vendor/puppet/transaction.rb', line 311 def done @done end |
#generated ⇒ Object (readonly)
Returns the value of attribute generated.
311 312 313 |
# File 'lib/vendor/puppet/transaction.rb', line 311 def generated @generated end |
#ready ⇒ Object (readonly)
Returns the value of attribute ready.
311 312 313 |
# File 'lib/vendor/puppet/transaction.rb', line 311 def ready @ready end |
#real_graph ⇒ Object (readonly)
Returns the value of attribute real_graph.
311 312 313 |
# File 'lib/vendor/puppet/transaction.rb', line 311 def real_graph @real_graph end |
#transaction ⇒ Object (readonly)
Returns the value of attribute transaction.
311 312 313 |
# File 'lib/vendor/puppet/transaction.rb', line 311 def transaction @transaction end |
#unguessable_deterministic_key ⇒ Object (readonly)
Returns the value of attribute unguessable_deterministic_key.
311 312 313 |
# File 'lib/vendor/puppet/transaction.rb', line 311 def unguessable_deterministic_key @unguessable_deterministic_key end |
Instance Method Details
#add_edge(f, t, label = nil) ⇒ Object
328 329 330 331 332 333 334 |
# File 'lib/vendor/puppet/transaction.rb', line 328 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
325 326 327 |
# File 'lib/vendor/puppet/transaction.rb', line 325 def add_vertex(v) real_graph.add_vertex(v) end |
#enqueue(*resources) ⇒ Object
353 354 355 356 357 358 |
# File 'lib/vendor/puppet/transaction.rb', line 353 def enqueue(*resources) resources.each do |resource| key = unguessable_deterministic_key[resource] ready[key] = resource end end |
#enqueue_roots ⇒ Object
Enqueue the initial set of resources, those with no dependencies.
336 337 338 339 340 341 |
# File 'lib/vendor/puppet/transaction.rb', line 336 def enqueue_roots vertices.each do |v| blockers[v] = direct_dependencies_of(v).length enqueue(v) if blockers[v] == 0 end end |
#fail_unsuitable_resources(resources) ⇒ Object
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 |
# File 'lib/vendor/puppet/transaction.rb', line 411 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
359 360 361 362 363 364 |
# File 'lib/vendor/puppet/transaction.rb', line 359 def finish(resource) direct_dependents_of(resource).each do |v| enqueue(v) if unblock(v) end done[resource] = true end |
#next_resource ⇒ Object
365 366 367 |
# File 'lib/vendor/puppet/transaction.rb', line 365 def next_resource ready.delete_min end |
#traverse(&block) ⇒ Object
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 404 405 406 407 408 409 |
# File 'lib/vendor/puppet/transaction.rb', line 368 def traverse(&block) real_graph.report_cycles_in_graph enqueue_roots 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.
344 345 346 347 348 349 350 351 352 |
# File 'lib/vendor/puppet/transaction.rb', line 344 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 |