summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2017-10-16 13:08:19 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2017-12-06 12:44:06 -0800
commit5b17173847fe3e6d2a976fecad065952c801522e (patch)
tree4aebe6f3151a1d6519b92e1d150c2cc6b2e7086e
parent0c29acc106ca774e230c8ef45694c8bffd166b69 (diff)
downloadchef-5b17173847fe3e6d2a976fecad065952c801522e.tar.gz
turbo attribute merging
Signed-off-by: Lamont Granquist <lamont@scriptkiddie.org>
-rw-r--r--lib/chef/node/immutable_collections.rb17
1 files changed, 16 insertions, 1 deletions
diff --git a/lib/chef/node/immutable_collections.rb b/lib/chef/node/immutable_collections.rb
index 13cb321890..3378bee2b5 100644
--- a/lib/chef/node/immutable_collections.rb
+++ b/lib/chef/node/immutable_collections.rb
@@ -198,6 +198,7 @@ class Chef
class ImmutableMash < Mash
alias_method :internal_clear, :clear
alias_method :internal_key?, :key? # FIXME: could bypass convert_key in Mash for perf
+ alias_method :internal_each, :each
include Immutablize
include CommonAPI
@@ -264,6 +265,7 @@ class Chef
def reset
@generated_cache = false
+ @short_circuit_attr_level = nil
internal_clear # redundant?
end
@@ -273,13 +275,20 @@ class Chef
@generated_cache = true
end
+ # @api private
+ attr_accessor :short_circuit_attr_levels
+
private
def generate_cache
internal_clear
- Attribute::COMPONENTS.reverse.each do |component|
+ components = short_circuit_attr_levels ? short_circuit_attr_levels : Attribute::COMPONENTS.reverse
+ # merged_components is not entirely accurate due to the short-circuit
+ merged_components = []
+ components.each do |component|
subhash = __node__.attributes.instance_variable_get(component).read(*__path__)
unless subhash.nil? # FIXME: nil is used for not present
+ merged_components << component
if subhash.kind_of?(Hash)
subhash.keys.each do |key|
next if internal_key?(key)
@@ -290,6 +299,12 @@ class Chef
end
end
end
+ if merged_components.size == 1
+ # merged_components is accurate enough to tell us if we're not really merging
+ internal_each do |key, value|
+ value.short_circuit_attr_levels = merged_components if value.respond_to?(:short_circuit_attr_levels)
+ end
+ end
end
prepend Chef::Node::Mixin::StateTracking