diff options
| author | Luke Kanies <luke@madstop.com> | 2005-05-29 20:41:53 +0000 |
|---|---|---|
| committer | Luke Kanies <luke@madstop.com> | 2005-05-29 20:41:53 +0000 |
| commit | c0d86a4ae6c00910a44f392f0076a5785ee85791 (patch) | |
| tree | f3c66cd9fcabe6328828c68689558b148ff60efa /lib | |
| parent | d86e4796432a61aa89330f5bf19c68609bda1e0b (diff) | |
intermediate; no extra functionality yet, but moving away from discussing namevars outside of a given class
git-svn-id: https://reductivelabs.com/svn/puppet/library/trunk@277 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/blink/client.rb | 4 | ||||
| -rw-r--r-- | lib/blink/statechange.rb | 7 | ||||
| -rw-r--r-- | lib/blink/transaction.rb | 60 | ||||
| -rw-r--r-- | lib/blink/transportable.rb | 34 | ||||
| -rw-r--r-- | lib/blink/type.rb | 116 | ||||
| -rw-r--r-- | lib/blink/type/file.rb | 5 | ||||
| -rw-r--r-- | lib/blink/type/state.rb | 7 |
7 files changed, 185 insertions, 48 deletions
diff --git a/lib/blink/client.rb b/lib/blink/client.rb index 3f64c37ba..f266d2dfb 100644 --- a/lib/blink/client.rb +++ b/lib/blink/client.rb @@ -70,11 +70,15 @@ module Blink Blink.notice("Calling config") container = Marshal::load(tree).to_type + # this is a gross hack... but i don't see a good way around it + # set all of the variables to empty + Blink::Transaction.init # for now we just evaluate the top-level container, but eventually # there will be schedules and such associated with each object, # and probably with the container itself transaction = container.evaluate #transaction = Blink::Transaction.new(objects) + transaction.toplevel = true transaction.evaluate self.shutdown end diff --git a/lib/blink/statechange.rb b/lib/blink/statechange.rb index 49b6484bb..0f2987fb9 100644 --- a/lib/blink/statechange.rb +++ b/lib/blink/statechange.rb @@ -13,6 +13,7 @@ module Blink #--------------------------------------------------------------- def initialize(state) @state = state + #@state.parent.newchange @path = state.fqpath @is = state.is @should = state.should @@ -27,7 +28,11 @@ module Blink Blink.notice "change noop is %s" % @state.noop else Blink.notice "Calling sync on %s" % @state - @state.sync + begin + @state.sync + rescue => detail + Blink.error "%s failed: %s" % [self.to_s,detail] + end end end #--------------------------------------------------------------- diff --git a/lib/blink/transaction.rb b/lib/blink/transaction.rb index 9535cd712..0da2ae766 100644 --- a/lib/blink/transaction.rb +++ b/lib/blink/transaction.rb @@ -13,34 +13,67 @@ require 'blink' require 'blink/statechange' #--------------------------------------------------------------- -class Blink::Transaction +module Blink +class Transaction + attr_accessor :toplevel + + #--------------------------------------------------------------- + # 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) - @children.push 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" % @children.length + Blink.notice "executing %s changes or transactions" % @changes.length - @children.each { |change| + @changes.each { |change| if change.is_a?(Blink::StateChange) begin change.forward + @@changed.push change.state.parent rescue => detail Blink.error("%s failed: %s" % [change,detail]) - # at this point, we would normally roll back the transaction - # but, um, i don't know how to do that yet + # 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) - change.evaluate + # nothing...? else raise "Transactions cannot handle objects of type %s" % child.class end } + + if @toplevel # if we're the top transaction, perform the refreshes + notifies = @@changed.uniq.collect { |object| + object.notify + }.flatten.uniq + + # now we have the entire list of objects to notify + else + # these are the objects that need to be refreshed + #return @refresh.uniq + end end #--------------------------------------------------------------- @@ -49,11 +82,19 @@ class Blink::Transaction # and it should only receive an array def initialize(tree) @tree = tree + @toplevel = false + # 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 - @children = @tree.collect { |child| - # not all of the children will return a change + @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 @@ -61,4 +102,5 @@ class Blink::Transaction end #--------------------------------------------------------------- end +end #--------------------------------------------------------------- diff --git a/lib/blink/transportable.rb b/lib/blink/transportable.rb index afb6f8061..3df5229cc 100644 --- a/lib/blink/transportable.rb +++ b/lib/blink/transportable.rb @@ -2,14 +2,8 @@ # $Id$ -# the interpreter -# -# this builds our virtual pinball machine, into which we'll place our host-specific -# information and out of which we'll receive our host-specific configuration - require 'blink' - module Blink #------------------------------------------------------------ class TransObject < Hash @@ -18,6 +12,16 @@ module Blink @@ohash = {} @@oarray = [] + def TransObject.add(object) + @@oarray.push object + + # this is just so we can check, at parse time, whether a required + # object has already been mentioned when it is listed as required + # because we're ordered, as long as an object gets made before its + # dependent objects will get synced later + @@ohash[object.longname] = object + end + def TransObject.clear @@oarray.clear end @@ -29,13 +33,11 @@ module Blink def initialize(name,type) self[:name] = name @type = type - #if @@ohash.include?(name) - # raise "%s already exists" % name - #else - # @@ohash[name] = self - # @@oarray.push(self) - #end - @@oarray.push self + self.class.add(self) + end + + def longname + return [object.type,object[:name]].join('--') end def name @@ -49,12 +51,6 @@ module Blink def to_type retobj = nil if type = Blink::Type.type(self.type) - namevar = type.namevar - if namevar != :name - self[namevar] = self[:name] - self.delete(:name) - end - p self #begin # this will fail if the type already exists # which may or may not be a good thing... diff --git a/lib/blink/type.rb b/lib/blink/type.rb index e697e0a15..15f54aa7b 100644 --- a/lib/blink/type.rb +++ b/lib/blink/type.rb @@ -43,6 +43,12 @@ class Blink::Type < Blink::Element @allowedmethods = [:noop,:debug] + @@metaparams = [ + :onerror, + :schedule, + :require + ] + #--------------------------------------------------------------- #--------------------------------------------------------------- # class methods dealing with Type management @@ -308,6 +314,13 @@ class Blink::Type < Blink::Element #--------------------------------------------------------------- #--------------------------------------------------------------- + # Is the parameter in question a meta-parameter? + def Type.metaparam(param) + @@metaparams.include?(param) + end + #--------------------------------------------------------------- + + #--------------------------------------------------------------- # this is probably only used by FileRecord objects def Type.parameters=(params) Blink.notice "setting parameters to [%s]" % params.join(" ") @@ -382,7 +395,10 @@ class Blink::Type < Blink::Element mname = name.intern end - if stateklass = self.class.validstate(mname) + if Blink::Type.metaparam(mname) + # call the metaparam method + self.send(("meta" + mname.id2name),value) + elsif stateklass = self.class.validstate(mname) if value.is_a?(Blink::State) @states[mname] = value else @@ -436,14 +452,35 @@ class Blink::Type < Blink::Element @children = [] @evalcount = 0 - @parent = nil @noop = false - # these are not currently used + # which objects to notify when we change + @notify = [] + + # keeping stats for the total number of changes, and how many were + # completely sync'ed + # this isn't really sufficient either, because it adds lots of special cases + # such as failed changes + # it also doesn't distinguish between changes from the current transaction + # vs. changes over the process lifetime + @totalchanges = 0 + @syncedchanges = 0 + @failedchanges = 0 + + # which attributes we care about even though they don't have + # values + # this isn't used right now, and isn't likely to be until we support + # querying @monitor = Array.new - @notify = Hash.new - @actions = Hash.new + #namevar = self.class.namevar + #if namevar != :name + # unless hash.include?(namevar) + # raise "Objects of %s type must be passed %s" % [self.class,namevar] + # end + # hash[namevar] = hash[:name] + # hash.delete(:name) + #end # convert all strings to symbols hash.each { |var,value| unless var.is_a? Symbol @@ -573,6 +610,12 @@ class Blink::Type < Blink::Element #--------------------------------------------------------------- #--------------------------------------------------------------- + def newchange + @totalchanges += 1 + end + #--------------------------------------------------------------- + + #--------------------------------------------------------------- # this method is responsible for collecting state changes # we always descend into the children before we evaluate our current # states @@ -588,8 +631,9 @@ class Blink::Type < Blink::Element return end @evalcount += 1 - # these might return messages, but the main action is through - # setting changes in the transactions + + # collect changes and return them + # these changes could be from child objects or from contained states self.collect { |child| child.evaluate } @@ -623,16 +667,50 @@ class Blink::Type < Blink::Element #--------------------------------------------------------------- #--------------------------------------------------------------- - # this method is responsible for handling changes in dependencies - # for instance, restarting a service if a config file is changed - # in general, we just hand the method up to our parent, but for - # objects that might need to refresh, they'll override this method - # XXX at this point, if all dependent objects change, then this method - # might get called for each change - def refresh(transaction) - unless @parent.nil? - @parent.refresh(transaction) + #--------------------------------------------------------------- + # Meta-parameter methods: These methods deal with the results + # of specifying metaparameters + #--------------------------------------------------------------- + #--------------------------------------------------------------- + + #--------------------------------------------------------------- + def metaonerror(response) + Blink.debug("Would have called metaonerror") + @onerror = response + end + #--------------------------------------------------------------- + + #--------------------------------------------------------------- + # this is a tad weird, because we specify the requirements on the + # "parent" object, but it's the child object that needs to know + # which objects to notify; i.e., object A requires object B, so if + # object B gets modified it needs to notify object A. + def metarequire(requires) + unless requires.is_a?(Array) + requires = [requires] end + requires.each { |object| + Blink.debug("%s requires %s" % [self.name,object.name]) + object.addnotify(self) + } + end + #--------------------------------------------------------------- + + #--------------------------------------------------------------- + def addnotify(object) + @notify.push object + end + #--------------------------------------------------------------- + + #--------------------------------------------------------------- + def notify + @notify + end + #--------------------------------------------------------------- + + #--------------------------------------------------------------- + def metaschedule(schedule) + @schedule = schedule end #--------------------------------------------------------------- @@ -656,6 +734,6 @@ require 'blink/type/symlink' require 'blink/type/package' require 'blink/type/component' require 'blink/statechange' -require 'blink/type/typegen' -require 'blink/type/typegen/filetype' -require 'blink/type/typegen/filerecord' +#require 'blink/type/typegen' +#require 'blink/type/typegen/filetype' +#require 'blink/type/typegen/filerecord' diff --git a/lib/blink/type/file.rb b/lib/blink/type/file.rb index b3866a78f..176b2e672 100644 --- a/lib/blink/type/file.rb +++ b/lib/blink/type/file.rb @@ -15,6 +15,7 @@ module Blink require 'etc' attr_accessor :file @name = :create + @event = :file_created def retrieve stat = nil @@ -39,6 +40,7 @@ module Blink require 'etc' attr_accessor :file @name = :owner + @event = :inode_changed def retrieve stat = nil @@ -96,6 +98,7 @@ module Blink require 'etc' @name = :mode + @event = :inode_changed def initialize(should) # this is pretty hackish, but i need to make sure the number is in @@ -152,6 +155,7 @@ module Blink @parent = Blink::State::FileMode @name = :setuid + @event = :inode_changed def <=>(other) self.is <=> @parent.value[11] @@ -176,6 +180,7 @@ module Blink require 'etc' @name = :group + @event = :inode_changed def retrieve stat = nil diff --git a/lib/blink/type/state.rb b/lib/blink/type/state.rb index 4518fdd9a..209095065 100644 --- a/lib/blink/type/state.rb +++ b/lib/blink/type/state.rb @@ -31,6 +31,13 @@ class Blink::State < Blink::Element #--------------------------------------------------------------- #--------------------------------------------------------------- + # which event gets generated if this state change happens + def State.generates + return @event + end + #--------------------------------------------------------------- + + #--------------------------------------------------------------- # if we're not in sync, return a statechange capable of putting us # in sync def evaluate |
