diff options
author | Jesse Wolfe <jes5199@gmail.com> | 2010-10-01 11:35:35 -0700 |
---|---|---|
committer | Jesse Wolfe <jes5199@gmail.com> | 2010-10-01 11:35:35 -0700 |
commit | da84c03a7d1fe33c660c3e4c3a069ef1aed23bae (patch) | |
tree | a75697d977d90b7754e0a14dcfc13b33aff893d1 /lib/puppet/parser | |
parent | 0077379e528037d875a92575a994d01ca5233cc0 (diff) | |
parent | 917c520f1abc0c72d7065531cffcef88259e32e0 (diff) | |
download | puppet-da84c03a7d1fe33c660c3e4c3a069ef1aed23bae.tar.gz puppet-da84c03a7d1fe33c660c3e4c3a069ef1aed23bae.tar.xz puppet-da84c03a7d1fe33c660c3e4c3a069ef1aed23bae.zip |
Merge commit '2.6.2rc1'
Diffstat (limited to 'lib/puppet/parser')
-rw-r--r-- | lib/puppet/parser/ast/function.rb | 2 | ||||
-rw-r--r-- | lib/puppet/parser/ast/resource.rb | 6 | ||||
-rw-r--r-- | lib/puppet/parser/functions/extlookup.rb | 2 | ||||
-rw-r--r-- | lib/puppet/parser/functions/versioncmp.rb | 6 | ||||
-rw-r--r-- | lib/puppet/parser/lexer.rb | 2 | ||||
-rw-r--r-- | lib/puppet/parser/parser_support.rb | 6 | ||||
-rw-r--r-- | lib/puppet/parser/resource.rb | 8 | ||||
-rw-r--r-- | lib/puppet/parser/type_loader.rb | 98 |
8 files changed, 69 insertions, 61 deletions
diff --git a/lib/puppet/parser/ast/function.rb b/lib/puppet/parser/ast/function.rb index 74023f631..80e6e6512 100644 --- a/lib/puppet/parser/ast/function.rb +++ b/lib/puppet/parser/ast/function.rb @@ -28,7 +28,7 @@ class Puppet::Parser::AST end # We don't need to evaluate the name, because it's plaintext - args = @arguments.safeevaluate(scope) + args = @arguments.safeevaluate(scope).map { |x| x == :undef ? '' : x } scope.send("function_#{@name}", args) end diff --git a/lib/puppet/parser/ast/resource.rb b/lib/puppet/parser/ast/resource.rb index 0c58538d5..6909c85c2 100644 --- a/lib/puppet/parser/ast/resource.rb +++ b/lib/puppet/parser/ast/resource.rb @@ -46,7 +46,6 @@ class Resource < AST::ResourceReference :virtual => virt, :source => scope.source, :scope => scope, - :strict => true ) @@ -64,12 +63,9 @@ class Resource < AST::ResourceReference if params.is_a?(AST::ASTArray) @parameters = params else - - @parameters = AST::ASTArray.new( - + @parameters = AST::ASTArray.new( :line => params.line, :file => params.file, - :children => [params] ) end diff --git a/lib/puppet/parser/functions/extlookup.rb b/lib/puppet/parser/functions/extlookup.rb index 63d49e563..bc55410b9 100644 --- a/lib/puppet/parser/functions/extlookup.rb +++ b/lib/puppet/parser/functions/extlookup.rb @@ -52,7 +52,7 @@ the exact same outcome: $snmp_contact = extlookup(\"snmp_contact\") -The obove code shows some other features, you can use any fact or variable that +The above code shows some other features, you can use any fact or variable that is in scope by simply using %{varname} in your data files, you can return arrays by just having multiple values in the csv after the initial variable name. diff --git a/lib/puppet/parser/functions/versioncmp.rb b/lib/puppet/parser/functions/versioncmp.rb index 94ba3886f..6091e0923 100644 --- a/lib/puppet/parser/functions/versioncmp.rb +++ b/lib/puppet/parser/functions/versioncmp.rb @@ -14,9 +14,9 @@ Where a and b are arbitrary version strings This functions returns a number: -* > 0 if version a is greater than version b -* == 0 if both version are equals -* < 0 if version a is less than version b +* Greater than 0 if version a is greater than version b +* Equal to 0 if both version are equals +* Less than 0 if version a is less than version b Example: diff --git a/lib/puppet/parser/lexer.rb b/lib/puppet/parser/lexer.rb index a25a17e3f..9036d652e 100644 --- a/lib/puppet/parser/lexer.rb +++ b/lib/puppet/parser/lexer.rb @@ -520,7 +520,7 @@ class Puppet::Parser::Lexer def slurpstring(terminators,escapes=%w{ \\ $ ' " n t s }+["\n"],ignore_invalid_escapes=false) # we search for the next quote that isn't preceded by a # backslash; the caret is there to match empty strings - str = @scanner.scan_until(/([^\\]|^)[#{terminators}]/) or lex_error "Unclosed quote after '#{last}' in '#{rest}'" + str = @scanner.scan_until(/([^\\]|^|[^\\])([\\]{2})*[#{terminators}]/) or lex_error "Unclosed quote after '#{last}' in '#{rest}'" @line += str.count("\n") # literal carriage returns add to the line count. str.gsub!(/\\(.)/) { ch = $1 diff --git a/lib/puppet/parser/parser_support.rb b/lib/puppet/parser/parser_support.rb index c0fd37178..c90c1978f 100644 --- a/lib/puppet/parser/parser_support.rb +++ b/lib/puppet/parser/parser_support.rb @@ -111,7 +111,7 @@ class Puppet::Parser::Parser end def import(file) - known_resource_types.loader.import_if_possible(file, @lexer.file) + known_resource_types.loader.import(file, @lexer.file) end def initialize(env) @@ -215,7 +215,9 @@ class Puppet::Parser::Parser end def parse_ruby_file - require self.file + # Execute the contents of the file inside its own "main" object so + # that it can call methods in the resource type API. + Puppet::DSL::ResourceTypeAPI.new.instance_eval(File.read(self.file)) end def string=(string) diff --git a/lib/puppet/parser/resource.rb b/lib/puppet/parser/resource.rb index 8a5ae886c..c007d4dbe 100644 --- a/lib/puppet/parser/resource.rb +++ b/lib/puppet/parser/resource.rb @@ -64,6 +64,7 @@ class Puppet::Parser::Resource < Puppet::Resource # Retrieve the associated definition and evaluate it. def evaluate + return if evaluated? @evaluated = true if klass = resource_type and ! builtin_type? finish @@ -93,6 +94,7 @@ class Puppet::Parser::Resource < Puppet::Resource @finished = true add_defaults add_metaparams + add_scope_tags validate end @@ -259,6 +261,12 @@ class Puppet::Parser::Resource < Puppet::Resource end end + def add_scope_tags + if scope_resource = scope.resource + tag(*scope_resource.tags) + end + end + # Accept a parameter from an override. def override_parameter(param) # This can happen if the override is defining a new parameter, rather diff --git a/lib/puppet/parser/type_loader.rb b/lib/puppet/parser/type_loader.rb index 09aa636e1..bae560381 100644 --- a/lib/puppet/parser/type_loader.rb +++ b/lib/puppet/parser/type_loader.rb @@ -3,25 +3,56 @@ require 'puppet/node/environment' class Puppet::Parser::TypeLoader include Puppet::Node::Environment::Helper - class Helper < Hash + # Helper class that makes sure we don't try to import the same file + # more than once from either the same thread or different threads. + class Helper include MonitorMixin - def done_with(item) - synchronize do - delete(item)[:busy].signal if self.has_key?(item) and self[item][:loader] == Thread.current - end + def initialize + super + # These hashes are indexed by filename + @state = {} # :doing or :done + @thread = {} # if :doing, thread that's doing the parsing + @cond_var = {} # if :doing, condition var that will be signaled when done. end - def owner_of(item) - synchronize do - if !self.has_key? item - self[item] = { :loader => Thread.current, :busy => self.new_cond} - :nobody - elsif self[item][:loader] == Thread.current - :this_thread + + # Execute the supplied block exactly once per file, no matter how + # many threads have asked for it to run. If another thread is + # already executing it, wait for it to finish. If this thread is + # already executing it, return immediately without executing the + # block. + # + # Note: the reason for returning immediately if this thread is + # already executing the block is to handle the case of a circular + # import--when this happens, we attempt to recursively re-parse a + # file that we are already in the process of parsing. To prevent + # an infinite regress we need to simply do nothing when the + # recursive import is attempted. + def do_once(file) + need_to_execute = synchronize do + case @state[file] + when :doing + if @thread[file] != Thread.current + @cond_var[file].wait + end + false + when :done + false else - flag = self[item][:busy] - flag.wait - flag.signal - :another_thread + @state[file] = :doing + @thread[file] = Thread.current + @cond_var[file] = new_cond + true + end + end + if need_to_execute + begin + yield + ensure + synchronize do + @state[file] = :done + @thread.delete(file) + @cond_var.delete(file).broadcast + end end end end @@ -51,8 +82,7 @@ class Puppet::Parser::TypeLoader unless file =~ /^#{File::SEPARATOR}/ file = File.join(dir, file) end - unless imported? file - @imported[file] = true + @loading_helper.do_once(file) do parse_file(file) end end @@ -60,27 +90,20 @@ class Puppet::Parser::TypeLoader modname end - def imported?(file) - @imported.has_key?(file) - end - def known_resource_types environment.known_resource_types end def initialize(env) self.environment = env - @loaded = {} - @loading = Helper.new - - @imported = {} + @loading_helper = Helper.new end def load_until(namespaces, name) return nil if name == "" # special-case main. name2files(namespaces, name).each do |filename| modname = begin - import_if_possible(filename) + import(filename) rescue Puppet::ImportError => detail # We couldn't load the item # I'm not convienced we should just drop these errors, but this @@ -96,10 +119,6 @@ class Puppet::Parser::TypeLoader nil end - def loaded?(name) - @loaded.include?(name) - end - def name2files(namespaces, name) return [name.sub(/^::/, '').gsub("::", File::SEPARATOR)] if name =~ /^::/ @@ -126,21 +145,4 @@ class Puppet::Parser::TypeLoader parser.file = file parser.parse end - - # Utility method factored out of load for handling thread-safety. - # This isn't tested in the specs, because that's basically impossible. - def import_if_possible(file, current_file = nil) - @loaded[file] || begin - case @loading.owner_of(file) - when :this_thread - nil - when :another_thread - import_if_possible(file,current_file) - when :nobody - @loaded[file] = import(file,current_file) - end - ensure - @loading.done_with(file) - end - end end |