summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2005-05-29 20:41:53 +0000
committerLuke Kanies <luke@madstop.com>2005-05-29 20:41:53 +0000
commitc0d86a4ae6c00910a44f392f0076a5785ee85791 (patch)
treef3c66cd9fcabe6328828c68689558b148ff60efa /lib
parentd86e4796432a61aa89330f5bf19c68609bda1e0b (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.rb4
-rw-r--r--lib/blink/statechange.rb7
-rw-r--r--lib/blink/transaction.rb60
-rw-r--r--lib/blink/transportable.rb34
-rw-r--r--lib/blink/type.rb116
-rw-r--r--lib/blink/type/file.rb5
-rw-r--r--lib/blink/type/state.rb7
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