summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2008-04-07 23:47:01 -0500
committerLuke Kanies <luke@madstop.com>2008-04-08 11:33:49 -0500
commitc6729d134b6b0479e091928ee68abb9008d0f71d (patch)
tree0fc97c75dbd946d18d8c72d3006b10bf38054ee8 /lib
parent8e1e06ff1c65bc5d8162fce41776e31b9f00d1bf (diff)
downloadpuppet-c6729d134b6b0479e091928ee68abb9008d0f71d.tar.gz
puppet-c6729d134b6b0479e091928ee68abb9008d0f71d.tar.xz
puppet-c6729d134b6b0479e091928ee68abb9008d0f71d.zip
Reworking the caching layer to use TTLs instead of versions
based on timestamps. This just modifies the indirection class itself, there is still some work to do to remove version code from other classes.
Diffstat (limited to 'lib')
-rw-r--r--lib/puppet/indirector/indirection.rb96
1 files changed, 77 insertions, 19 deletions
diff --git a/lib/puppet/indirector/indirection.rb b/lib/puppet/indirector/indirection.rb
index d47433c60..91cc42b17 100644
--- a/lib/puppet/indirector/indirection.rb
+++ b/lib/puppet/indirector/indirection.rb
@@ -1,4 +1,5 @@
require 'puppet/util/docs'
+require 'puppet/indirector/envelope'
# The class that connects functional classes with their different collection
# back-ends. Each indirection has a set of associated terminus classes,
@@ -28,8 +29,7 @@ class Puppet::Indirector::Indirection
# Find an indirected model by name. This is provided so that Terminus classes
# can specifically hook up with the indirections they are associated with.
def self.model(name)
- match = @@indirections.find { |i| i.name == name }
- return nil unless match
+ return nil unless match = @@indirections.find { |i| i.name == name }
match.model
end
@@ -65,6 +65,25 @@ class Puppet::Indirector::Indirection
@@indirections.delete(self) if @@indirections.include?(self)
end
+ # Set the time-to-live for instances created through this indirection.
+ def ttl=(value)
+ raise ArgumentError, "Indirection TTL must be an integer" unless value.is_a?(Fixnum)
+ @ttl = value
+ end
+
+ # Default to the runinterval for the ttl.
+ def ttl
+ unless defined?(@ttl)
+ @ttl = Puppet[:runinterval].to_i
+ end
+ @ttl
+ end
+
+ # Calculate the expiration date for a returned instance.
+ def expiration
+ Time.now + ttl
+ end
+
# Generate the full doc string.
def doc
text = ""
@@ -106,6 +125,12 @@ class Puppet::Indirector::Indirection
end
end
+ # Set the options that can be passed on to the terminus instances.
+ attr_reader :option_struct
+ def options=(options)
+ @option_struct = Struct.new(*options)
+ end
+
# Return the singleton terminus for this indirection.
def terminus(terminus_name = nil)
# Get the name of the terminus.
@@ -161,29 +186,41 @@ class Puppet::Indirector::Indirection
check_authorization(:find, terminus_name, ([key] + args))
# See if our instance is in the cache and up to date.
- if cache? and cache.has_most_recent?(key, terminus(terminus_name).version(key))
- Puppet.debug "Using cached %s %s" % [self.name, key]
- return cache.find(key, *args)
+ if cache? and cached = cache.find(key, *args)
+ if cached.expired?
+ Puppet.info "Cached %s %s expired at %s; not using" % [self.name, key, cached.expiration]
+ else
+ Puppet.debug "Using cached %s %s" % [self.name, key]
+ return cached
+ end
end
# Otherwise, return the result from the terminus, caching if appropriate.
if result = terminus(terminus_name).find(key, *args)
- result.version ||= Time.now.utc
+ # Include the envelope module, so we can set the expiration.
+ result.extend(Puppet::Indirector::Envelope)
+ result.expiration ||= self.expiration
if cache?
Puppet.info "Caching %s %s" % [self.name, key]
cache.save(result, *args)
end
- terminus(terminus_name).post_find(result) if terminus(terminus_name).respond_to?(:post_find)
-
return result
end
+
+ return nil
end
- def destroy(*args)
- check_authorization(:destroy, terminus_class, args)
+ def destroy(key, *args)
+ check_authorization(:destroy, terminus_class, ([key] + args))
+
+ terminus.destroy(key, *args)
+
+ if cache? and cached = cache.find(key, *args)
+ cache.destroy(key, *args)
+ end
- terminus.destroy(*args)
+ nil
end
def search(*args)
@@ -191,21 +228,22 @@ class Puppet::Indirector::Indirection
result = terminus.search(*args)
- terminus().post_search(result) if terminus().respond_to?(:post_search)
-
result
end
# these become instance methods
def save(instance, *args)
- check_authorization(:save, terminus_class, ([instance] + args))
+ if respond_to?(:select_terminus)
+ terminus_name = select_terminus(instance.name, *args)
+ else
+ terminus_name = terminus_class
+ end
- instance.version ||= Time.now.utc
- dest = cache? ? cache : terminus
- return if dest.has_most_recent?(instance.name, instance.version)
- Puppet.info "Caching %s %s" % [self.name, instance.name] if cache?
+ check_authorization(:save, terminus_name, ([instance] + args))
+
+ # If caching is enabled, save our document there, do
cache.save(instance, *args) if cache?
- terminus.save(instance, *args)
+ terminus(terminus_class).save(instance, *args)
end
def version(*args)
@@ -226,6 +264,20 @@ class Puppet::Indirector::Indirection
end
end
+ # Handle a given indirected call.
+ def prepare_call(method, arguments)
+ raise ArgumentError, "Options must be a hash" unless arguments.is_a?(Hash)
+
+ # Set any terminus options.
+ options = option_struct ? set_options(option_struct, arguments) : nil
+
+ tclass = choose_terminus(options)
+
+ check_authorization(method, tclass, options)
+
+ return terminus(tclass), options
+ end
+
# Create a new terminus instance.
def make_terminus(terminus_class)
# Load our terminus class.
@@ -234,4 +286,10 @@ class Puppet::Indirector::Indirection
end
return klass.new
end
+
+ # Create a struct instance with all of the appropriate options set
+ # from the provided hash.
+ def set_options(struct, arguments)
+ struct.new(struct.members.inject([]) { |array, param| arguments[param.to_sym]; array } )
+ end
end