summaryrefslogtreecommitdiff
path: root/lib/chef/node
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2016-10-07 15:04:47 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2016-10-25 09:29:29 -0700
commit6536f15dcb53938fe9c77e7438b20fe6ac3cdffb (patch)
treee6f6a3b0f28914582e4be97c5ecb9e3b20a0e9c1 /lib/chef/node
parent10904d6cf42a2a0ed69757aca3e80f512bb89379 (diff)
downloadchef-6536f15dcb53938fe9c77e7438b20fe6ac3cdffb.tar.gz
remove breadcrumb state
Signed-off-by: Lamont Granquist <lamont@scriptkiddie.org>
Diffstat (limited to 'lib/chef/node')
-rw-r--r--lib/chef/node/attribute_collections.rb22
-rw-r--r--lib/chef/node/common_api.rb6
-rw-r--r--lib/chef/node/immutable_collections.rb6
-rw-r--r--lib/chef/node/mixin/deep_merge_cache.rb11
-rw-r--r--lib/chef/node/mixin/state_tracking.rb18
5 files changed, 28 insertions, 35 deletions
diff --git a/lib/chef/node/attribute_collections.rb b/lib/chef/node/attribute_collections.rb
index be87c028cb..412fb52a48 100644
--- a/lib/chef/node/attribute_collections.rb
+++ b/lib/chef/node/attribute_collections.rb
@@ -64,13 +64,12 @@ class Chef
MUTATOR_METHODS.each do |mutator|
define_method(mutator) do |*args, &block|
ret = super(*args, &block)
- __root.reset_cache(__root.top_level_breadcrumb)
+ send_reset_cache
ret
end
end
- def initialize(data = [], root = self)
- @__root ||= root
+ def initialize(data = [])
super(data)
map! { |e| convert_value(e) }
end
@@ -129,7 +128,6 @@ class Chef
# object.
MUTATOR_METHODS = [
:clear,
- :delete,
:delete_if,
:keep_if,
:merge!,
@@ -143,21 +141,24 @@ class Chef
# For all of the mutating methods on Mash, override them so that they
# also invalidate the cached `merged_attributes` on the root Attribute
# object.
+
+ def delete(key, &block)
+ send_reset_cache(__path + [ key ])
+ super
+ end
+
MUTATOR_METHODS.each do |mutator|
define_method(mutator) do |*args, &block|
- __root.reset_cache(__root.top_level_breadcrumb)
+ send_reset_cache
super(*args, &block)
end
end
- def initialize(data = {}, root = self)
- puts caller unless root.class == Chef::Node::Attribute
- @__root ||= root
+ def initialize(data = {})
super(data)
end
def [](key)
- __root.top_level_breadcrumb ||= key
value = super
if !key?(key)
value = self.class.new({}, __root)
@@ -168,9 +169,8 @@ class Chef
end
def []=(key, value)
- __root.top_level_breadcrumb ||= key
ret = super
- __root.reset_cache(__root.top_level_breadcrumb)
+ send_reset_cache(__path + [ key ])
ret
end
diff --git a/lib/chef/node/common_api.rb b/lib/chef/node/common_api.rb
index 6aae880667..9bb83a5178 100644
--- a/lib/chef/node/common_api.rb
+++ b/lib/chef/node/common_api.rb
@@ -32,7 +32,6 @@ class Chef
# - autovivifying / autoreplacing writer
# - non-container-ey intermediate objects are replaced with hashes
def write(*args, &block)
- __root.top_level_breadcrumb = nil if respond_to?(:__root)
value = block_given? ? yield : args.pop
last = args.pop
prev_memo = prev_key = nil
@@ -56,7 +55,6 @@ class Chef
# something that is not a container ("schema violation" issues).
#
def write!(*args, &block)
- __root.top_level_breadcrumb = nil if respond_to?(:__root)
value = block_given? ? yield : args.pop
last = args.pop
obj = args.inject(self) do |memo, key|
@@ -71,7 +69,6 @@ class Chef
# return true or false based on if the attribute exists
def exist?(*path)
- __root.top_level_breadcrumb = nil if respond_to?(:__root)
path.inject(self) do |memo, key|
return false unless valid_container?(memo, key)
if memo.is_a?(Hash)
@@ -103,7 +100,6 @@ class Chef
# non-autovivifying reader that throws an exception if the attribute does not exist
def read!(*path)
raise Chef::Exceptions::NoSuchAttribute unless exist?(*path)
- __root.top_level_breadcrumb = nil if respond_to?(:__root)
path.inject(self) do |memo, key|
memo[key]
end
@@ -112,10 +108,8 @@ class Chef
# FIXME:(?) does anyone really like the autovivifying reader that we have and wants the same behavior? readers that write? ugh...
def unlink(*path, last)
- __root.top_level_breadcrumb = nil if respond_to?(:__root)
hash = path.empty? ? self : read(*path)
return nil unless hash.is_a?(Hash) || hash.is_a?(Array)
- __root.top_level_breadcrumb ||= last
hash.delete(last)
end
diff --git a/lib/chef/node/immutable_collections.rb b/lib/chef/node/immutable_collections.rb
index 50ac8daf93..623290f287 100644
--- a/lib/chef/node/immutable_collections.rb
+++ b/lib/chef/node/immutable_collections.rb
@@ -52,8 +52,7 @@ class Chef
alias :internal_push :<<
private :internal_push
- def initialize(array_data = [], root = self)
- @__root = root
+ def initialize(array_data = [])
array_data.each do |value|
internal_push(immutablize(value))
end
@@ -114,8 +113,7 @@ class Chef
alias :internal_set :[]=
private :internal_set
- def initialize(mash_data = {}, root = self)
- @__root = root
+ def initialize(mash_data = {})
mash_data.each do |key, value|
internal_set(key, immutablize(value))
end
diff --git a/lib/chef/node/mixin/deep_merge_cache.rb b/lib/chef/node/mixin/deep_merge_cache.rb
index d6a2149c52..b18d6b10cb 100644
--- a/lib/chef/node/mixin/deep_merge_cache.rb
+++ b/lib/chef/node/mixin/deep_merge_cache.rb
@@ -19,14 +19,6 @@ class Chef
class Node
module Mixin
module DeepMergeCache
- # This is used to track the top level key as we descend through method chaining into
- # a precedence level (e.g. node.default['foo']['bar']['baz']= results in 'foo' here). We
- # need this so that when we hit the end of a method chain which results in a mutator method
- # that we can invalidate the whole top-level deep merge cache for the top-level key. It is
- # the responsibility of the accessor on the Chef::Node object to reset this to nil, and then
- # the first VividMash#[] call can ||= and set this to the first key we encounter.
- attr_accessor :top_level_breadcrumb
-
# Cache of deep merged values by top-level key. This is a simple hash which has keys that are the
# top-level keys of the node object, and we save the computed deep-merge for that key here. There is
# no cache of subtrees.
@@ -36,7 +28,6 @@ class Chef
@merged_attributes = nil
@combined_override = nil
@combined_default = nil
- @top_level_breadcrumb = nil
@deep_merge_cache = {}
end
@@ -46,7 +37,7 @@ class Chef
# must invalidate the entire cache and re-deep-merge the entire node object.
def reset_cache(path = nil)
if path.nil?
- @deep_merge_cache = {}
+ deep_merge_cache.clear
else
deep_merge_cache.delete(path.to_s)
end
diff --git a/lib/chef/node/mixin/state_tracking.rb b/lib/chef/node/mixin/state_tracking.rb
index 7472d2a67d..2447de1c16 100644
--- a/lib/chef/node/mixin/state_tracking.rb
+++ b/lib/chef/node/mixin/state_tracking.rb
@@ -22,10 +22,14 @@ class Chef
attr_reader :__path
attr_reader :__root
- def initialize(*args)
- super(*args)
- @__path ||= []
- @__root ||= self
+ NULL = Object.new
+
+ def initialize(data = NULL, root = self)
+ # __path and __root must be nil when we call super so it knows
+ # to avoid resetting the cache on construction
+ data == NULL ? super() : super(data)
+ @__path = []
+ @__root = root
end
def [](key)
@@ -55,6 +59,12 @@ class Chef
def __root=(root)
@__root = root
end
+
+ private
+
+ def send_reset_cache(path = __path)
+ __root.reset_cache(path.first) if !__root.nil? && __root.respond_to?(:reset_cache) && !path.nil?
+ end
end
end
end