diff options
| author | Luke Kanies <luke@madstop.com> | 2005-06-27 21:44:46 +0000 |
|---|---|---|
| committer | Luke Kanies <luke@madstop.com> | 2005-06-27 21:44:46 +0000 |
| commit | 8f95084cd854aef4e3493854e58cefd352cdc68d (patch) | |
| tree | f31288d1cbbd60c0fdc7c04bbd6960516a6893be /lib/puppet/transaction.rb | |
| parent | 6f074138779e558fd7017880f606dcf3527233f9 (diff) | |
| download | puppet-8f95084cd854aef4e3493854e58cefd352cdc68d.tar.gz puppet-8f95084cd854aef4e3493854e58cefd352cdc68d.tar.xz puppet-8f95084cd854aef4e3493854e58cefd352cdc68d.zip | |
renaming blink to puppet
git-svn-id: https://reductivelabs.com/svn/puppet/library/trunk@302 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib/puppet/transaction.rb')
| -rw-r--r-- | lib/puppet/transaction.rb | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb new file mode 100644 index 000000000..87b2f950c --- /dev/null +++ b/lib/puppet/transaction.rb @@ -0,0 +1,162 @@ +#!/usr/local/bin/ruby -w + +# $Id$ + +# the class that actually walks our object/state tree, collects the changes, +# and performs them + +# there are two directions of walking: +# - first we recurse down the tree and collect changes +# - then we walk back up the tree through 'refresh' after the changes + +require 'blink' +require 'blink/statechange' + +#--------------------------------------------------------------- +module Blink +class Transaction + attr_accessor :toplevel, :component + + #--------------------------------------------------------------- + # a bit of a gross hack; a global list of objects that have failed to sync, + # so that we can verify during later syncs that our dependencies haven't + # failed + def Transaction.init + @@failures = Hash.new(0) + @@changed = [] + end + #--------------------------------------------------------------- + + #--------------------------------------------------------------- + # for now, just store the changes for executing linearly + # later, we might execute them as we receive them + def change(change) + @changes.push change + end + #--------------------------------------------------------------- + + #--------------------------------------------------------------- + # i don't need to worry about ordering, because it's not possible to specify + # an object as a dependency unless it's already been mentioned within the language + # thus, an object gets defined, then mentioned as a dependency, and the objects + # are synced in that order automatically + def evaluate + Blink.notice "executing %s changes or transactions" % @changes.length + + return @changes.collect { |change| + if change.is_a?(Blink::StateChange) + change.transaction = self + events = nil + begin + events = [change.forward].flatten + #@@changed.push change.state.parent + rescue => detail + Blink.error("%s failed: %s" % [change,detail]) + raise + # at this point, we would normally do error handling + # but i haven't decided what to do for that yet + # so just record that a sync failed for a given object + #@@failures[change.state.parent] += 1 + # this still could get hairy; what if file contents changed, + # but a chmod failed? how would i handle that error? dern + end + + if events.nil? + Blink.verbose "No events returned?" + else + # first handle the subscriptions on individual objects + events.each { |event| + change.state.parent.subscribers?(event).each { |sub| + sub.trigger(self) + } + } + end + events + elsif change.is_a?(Blink::Transaction) + change.evaluate + else + raise "Transactions cannot handle objects of type %s" % child.class + end + }.flatten.reject { |event| + event.nil? + }.each { |event| + # this handles subscriptions on the components, rather than + # on idividual objects + self.component.subscribers?(event).each { |sub| + sub.trigger(self) + } + } + end + #--------------------------------------------------------------- + + #--------------------------------------------------------------- + # this should only be called by a Blink::Container object now + # and it should only receive an array + def initialize(tree) + @tree = tree + @toplevel = false + + @triggered = Hash.new(0) + + # of course, this won't work on the second run + unless defined? @@failures + @toplevel = true + self.class.init + end + # change collection is in-band, and message generation is out-of-band + # of course, exception raising is also out-of-band + @changes = @tree.collect { |child| + # these children are all Blink::Type instances + # not all of the children will return a change, and Containers + # return transactions + child.evaluate + }.flatten.reject { |child| + child.nil? # remove empties + } + end + #--------------------------------------------------------------- + + #--------------------------------------------------------------- + def rollback + @changes.each { |change| + if change.is_a?(Blink::StateChange) + next unless change.run + #change.transaction = self + begin + change.backward + #@@changed.push change.state.parent + rescue => detail + Blink.error("%s rollback failed: %s" % [change,detail]) + # at this point, we would normally do error handling + # but i haven't decided what to do for that yet + # so just record that a sync failed for a given object + #@@failures[change.state.parent] += 1 + # this still could get hairy; what if file contents changed, + # but a chmod failed? how would i handle that error? dern + end + elsif change.is_a?(Blink::Transaction) + # yay, recursion + change.rollback + else + raise "Transactions cannot handle objects of type %s" % child.class + end + } + end + #--------------------------------------------------------------- + + #--------------------------------------------------------------- + def triggercount(sub) + Blink.notice "Triggercount on %s is %s" % [sub,@triggered[sub]] + return @triggered[sub] + end + #--------------------------------------------------------------- + + #--------------------------------------------------------------- + def triggered(sub) + @triggered[sub] += 1 + Blink.notice "%s was triggered; count is %s" % [sub,@triggered[sub]] + end + #--------------------------------------------------------------- +end +end +#--------------------------------------------------------------- |
