Changeset 284
- Timestamp:
- 04/21/06 14:29:42 (3 years ago)
- Location:
- branches/broker-rewrite
- Files:
-
- 4 added
- 23 modified
-
default.cfg (modified) (1 diff)
-
demo.cfg (modified) (1 diff)
-
docs/manual/config.html (modified) (2 diffs)
-
experiments/safelevel.rb (added)
-
lib/arrow.rb (modified) (1 diff)
-
lib/arrow/appletregistry.rb (modified) (3 diffs)
-
lib/arrow/broker.rb (modified) (6 diffs)
-
lib/arrow/cache.rb (modified) (1 diff)
-
lib/arrow/config-loaders/yaml.rb (modified) (2 diffs)
-
lib/arrow/config.rb (modified) (7 diffs)
-
lib/arrow/dispatcher.rb (modified) (5 diffs)
-
lib/arrow/formvalidator.rb (modified) (6 diffs)
-
lib/arrow/object.rb (modified) (2 diffs)
-
lib/arrow/template.rb (modified) (3 diffs)
-
lib/arrow/template/escape.rb (modified) (1 diff)
-
lib/arrow/template/prettyprint.rb (added)
-
lib/arrow/templatefactory.rb (modified) (1 diff)
-
lib/arrow/transaction.rb (modified) (3 diffs)
-
templates/inspect/display.tmpl (modified) (2 diffs)
-
tests/applet.tests.rb (modified) (2 diffs)
-
tests/appletregistry.tests.rb (modified) (1 diff)
-
tests/broker.tests.rb (modified) (2 diffs)
-
tests/data/test.cfg (added)
-
tests/dispatcher.tests.rb (added)
-
tests/formvalidator.tests.rb (modified) (10 diffs)
-
tests/lib/apacheconstants.rb (modified) (1 diff)
-
tests/template.tests.rb (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/broker-rewrite/default.cfg
r85 r284 4 4 templateLogLevel: notice 5 5 applets: 6 defaultApplet: "/status"7 6 missingApplet: "/missing" 8 7 errorApplet: "/error" -
branches/broker-rewrite/demo.cfg
r214 r284 4 4 templateLogLevel: notice 5 5 applets: 6 defaultApplet: "/status"7 6 missingApplet: "/missing" 8 7 errorApplet: "/error" -
branches/broker-rewrite/docs/manual/config.html
r277 r284 96 96 templateLogLevel: info 97 97 applets: 98 defaultApplet: "/status"99 98 missingApplet: "/missing" 100 99 errorApplet: "/error" … … 168 167 <dd> 169 168 <dl class="linelist config-subitems"> 170 <dt>defaultApplet</dt>171 <dd>This specifies the URI of the applet which is executed when172 none is specified by a request's URI. If this value is not173 specified or set to <tt>(builtin)</tt>, a very simple status174 handler is called instead (<a175 href="http://dev.rubycrafters.com/html/classes/Arrow/Broker.html#M000086"176 >Arrow::Broker#runDefaultApplet</a>).</dd>177 178 169 <dt>missingApplet</dt> 179 170 <dd>Specifies the URI of an applet which should be executed when -
branches/broker-rewrite/lib/arrow.rb
r277 r284 65 65 ### this. 66 66 def self.load_dispatchers( hosts_file ) 67 $deferr.puts "Loading dispatchers; $SAFE is #$SAFE" 67 68 hosts_file.untaint 68 69 configs = YAML.load( File.read(hosts_file) ) -
branches/broker-rewrite/lib/arrow/appletregistry.rb
r280 r284 205 205 end 206 206 207 # Output the applet chain to the debugging log.208 self.log.debug "Found %d applets in %p: %p" % [209 appletchain.nitems,210 uri_parts.join("/"),211 describe_appletchain( appletchain )212 ]213 214 207 return appletchain 215 208 end … … 301 294 def load_applets_from_file( path ) 302 295 296 # Reload mode -- don't do anything unless the file's been updated 303 297 if @filemap.key?( path ) 304 # Reload mode -- don't do anything unless the file's been updated298 if @filemap[ path ].has_changed? 305 299 self.log.info "File %p has changed since loaded. Reloading." % [path] 306 if @filemap[ path ].has_changed?300 self.purge_deleted_applets( path ) 307 301 else 308 self. purge_deleted_applets( path )302 self.log.debug "File %p has not changed." % [path] 309 303 return nil 310 self.log.debug "File %p has not changed." % [path]311 end312 304 end 305 end 313 306 314 307 self.log.debug "Attempting to load applet objects from %p" % path … … 428 421 end 429 422 430 431 ### Return a string which describes the given +appletchain+.432 def describe_appletchain( appletchain )433 appletchain.collect {|item|434 applet = item[0]435 "%s (%s): '%s': %p" % [436 applet.class.signature.name,437 applet.class,438 item[1],439 item[2]440 ]441 }.join("\n\t")442 end443 444 445 423 end # class Arrow::AppletRegistry 446 424 -
branches/broker-rewrite/lib/arrow/broker.rb
r282 r284 76 76 @registry.check_for_updates 77 77 78 # Run the default applet if no path info was given, or 79 if path.empty? 80 rval = self.run_default_applet( txn ) 81 else 82 83 # Get the chain of applets to execute for the request 84 appletchain = @registry.find_applet_chain( path ) 85 86 # If the pathinfo doesn't correspond to at least one applet, run 87 # the no-such-applet handler. 88 if appletchain.empty? 89 rval = self.run_missing_applet_handler( txn, path ) 90 else 91 rval = self.run_applet_chain( txn, appletchain ) 92 end 78 # Get the chain of applets to execute for the request 79 appletchain = @registry.find_applet_chain( path ) 80 81 # If the pathinfo doesn't correspond to at least one applet, run 82 # the no-such-applet handler. 83 if appletchain.empty? 84 rval = self.run_missing_applet_handler( txn, path ) 85 else 86 rval = self.run_applet_chain( txn, appletchain ) 93 87 end 94 88 … … 118 112 chain.empty? || !chain.first.is_a?( Array ) 119 113 114 res = nil 120 115 applet, txn.applet_path, args = self.unwrap_chain_link( chain.first ) 121 116 … … 123 118 if chain.nitems == 1 124 119 self.log.debug "Running final applet in chain" 125 re turnself.run_applet( applet, txn, args )120 res = self.run_applet( applet, txn, args ) 126 121 else 127 122 dchain = chain[ 1..-1 ] … … 129 124 [ applet.signature.name, chain.nitems, dchain ] 130 125 131 return applet.delegate( txn, dchain, *args ) {|subchain| 132 subchain = dchain if subchain.nil? 133 self.log.debug "Delegated call to appletchain %p" % [ subchain ] 134 self.run_applet_chain( txn, subchain ) 135 } 136 end 137 rescue ::Exception => err 138 self.log.error "Error while executing applet chain: %p (/%s): %s:\n\t%s" % [ 139 applet, 140 chain.first[1], 141 err.message, 142 err.backtrace.join("\n\t"), 143 ] 144 return self.run_error_handler( applet, txn, err ) 126 begin 127 res = applet.delegate( txn, dchain, *args ) do |subchain| 128 subchain = dchain if subchain.nil? 129 self.log.debug "Delegated call to appletchain %p" % [ subchain ] 130 self.run_applet_chain( txn, subchain ) 131 end 132 rescue ::Exception => err 133 self.log.error "Error while executing applet chain: %p (/%s): %s:\n\t%s" % [ 134 applet, 135 chain.first[1], 136 err.message, 137 err.backtrace.join("\n\t"), 138 ] 139 res = self.run_error_handler( applet, txn, err ) 140 end 141 end 142 143 return res 145 144 end 146 145 … … 150 149 ### sensible errors if a delegating app screws up a chain somehow. 151 150 def unwrap_chain_link( link ) 152 applet = link[0] or raise AppletChainError, "Null applet" 153 154 unless applet.is_a?( Arrow::Applet ) 155 emsg = "cannot convert %s into an Arrow::Applet" % 156 applet.class.name 157 raise AppletChainError, emsg 158 end 159 160 path = link[1] or raise AppletChainError, "Null path" 161 args = link[2] or raise AppletChainError, "Null argument list" 151 applet = link[0] or raise Arrow::AppletChainError, "Null applet" 152 153 path = link[1] or raise Arrow::AppletChainError, "Null path" 154 args = link[2] or raise Arrow::AppletChainError, "Null argument list" 162 155 unless args.is_a?( Array ) 163 156 emsg = "Argument list is a %s: expected an Array" % 164 157 args.class.name 165 raise A ppletChainError, emsg158 raise Arrow::AppletChainError, emsg 166 159 end 167 160 … … 187 180 188 181 189 ### Handle requests that don't target a specific applet (i.e.,190 ### their path_info is empty). This will attempt to run whatever applet is191 ### configured as the default one (:defaultApplet), or run a builtin status192 ### applet if no default is configured or if the configured one isn't193 ### loaded.194 def run_default_applet( txn, *args )195 rval = appletchain = nil196 handlerUri = @config.applets.defaultApplet197 198 if handlerUri != "(builtin)"199 appletchain = @registry.find_applet_chain( handlerUri, true )200 self.log.debug "Found appletchain %p for default applet" % [ appletchain ]201 202 if appletchain.empty?203 rval = self.run_missing_applet_handler( txn, handlerUri )204 else205 rval = self.run_applet_chain( txn, appletchain )206 end207 else208 rval = self.builtin_default_handler( txn )209 end210 211 return rval212 end213 214 215 ### The builtin default handler routine. Outputs a plain-text status216 ### message.217 def builtin_default_handler( txn )218 self.log.notice "Using builtin default handler."219 220 txn.request.content_type = "text/plain"221 return "Arrow Status: Running %s (%d applets loaded)" %222 [ Time.now, @registry.length ]223 end224 225 226 182 ### Handle requests that target an applet that doesn't exist. 227 183 def run_missing_applet_handler( txn, uri ) -
branches/broker-rewrite/lib/arrow/cache.rb
r277 r284 25 25 require 'arrow/logger' 26 26 27 module Arrow 27 ### Instances of this class are LRU caches for disk-based objects which keep 28 ### track of the cached object's modification time, expiring the cached 29 ### version when the disk-based version changes.. 30 class Arrow::Cache < ::Cache 28 31 29 ### Instances of this class are LRU caches for disk-based objects which keep 30 ### track of the cached object's modification time, expiring the cached 31 ### version when the disk-based version changes.. 32 class Cache < ::Cache 32 # Default configuration values 33 DefaultConfig = { 34 :maxNum => 10, 35 :maxObjSize => nil, 36 :maxSize => nil, 37 :expiration => 3600, 38 } 33 39 34 # Default configuration values 35 DefaultConfig = { 36 :maxNum => 10, 37 :maxObjSize => nil, 38 :maxSize => nil, 39 :expiration => 3600, 40 41 ############################################################# 42 ### C L A S S M E T H O D S 43 ############################################################# 44 45 @extent = [] 46 class << self 47 attr_reader :extent 48 end 49 50 51 ############################################################# 52 ### I N S T A N C E M E T H O D S 53 ############################################################# 54 55 ### Create a new cache. This merges the DefaultConfig with the specified 56 ### values and transforms camelCased keys into under_barred ones. 57 def initialize( name, config={}, &cleanup ) 58 @name = name 59 60 # Merge defaults and specified values 61 merged = nil 62 if config.is_a?( Arrow::Config::ConfigStruct ) 63 merged = DefaultConfig.merge( config.to_h ) 64 else 65 merged = DefaultConfig.merge( config ) 66 end 67 68 # Transform the config hash into the form the superclass expects 69 merged.each_key {|key| 70 lckey = key.to_s.gsub( /(.)([A-Z])/ ) {|match| 71 match[0,1] + "_" + match[1,1].downcase 72 }.intern 73 74 next if key == lckey 75 merged[ lckey ] = merged.delete( key ) 40 76 } 41 77 78 # Register this instance with the class for introspection (costs 79 # much less than ObjectSpace.each_object). 80 obj = super( merged, &cleanup ) 81 self.class.extent << obj 82 83 return obj 84 end 85 86 87 ###### 88 public 89 ###### 90 91 # The name of the cache; used in introspection 92 attr_reader :name 93 94 95 ### Overridden from the superclass to prevent .to_s from being called on 96 ### objects to determine their size if the object supports a #memsize 97 ### method. This is mostly to stop templates from being rendered every 98 ### time they're cached. 99 def []=( key, obj ) 100 self.expire 42 101 43 ############################################################# 44 ### C L A S S M E T H O D S 45 ############################################################# 102 self.invalidate( key ) if self.cached?( key ) 46 103 47 @extent = [] 48 class << self 49 attr_reader :extent 104 if obj.respond_to?( :memsize ) 105 size = obj.memsize 106 else 107 size = obj.to_s.size 50 108 end 51 109 52 53 ############################################################# 54 ### I N S T A N C E M E T H O D S 55 ############################################################# 56 57 ### Create a new cache. This merges the DefaultConfig with the specified 58 ### values and transforms camelCased keys into under_barred ones. 59 def initialize( name, config={}, &cleanup ) 60 @name = name 61 62 # Merge defaults and specified values 63 merged = nil 64 if config.is_a?( Arrow::Config::ConfigStruct ) 65 merged = DefaultConfig.merge( config.to_h ) 66 else 67 merged = DefaultConfig.merge( config ) 68 end 69 70 # Transform the config hash into the form the superclass expects 71 merged.each_key {|key| 72 lckey = key.to_s.gsub( /(.)([A-Z])/ ) {|match| 73 match[0,1] + "_" + match[1,1].downcase 74 }.intern 75 76 next if key == lckey 77 merged[ lckey ] = merged.delete( key ) 78 } 79 80 # Register this instance with the class for introspection (costs 81 # much less than ObjectSpace.each_object). 82 obj = super( merged, &cleanup ) 83 self.class.extent << obj 84 110 # Test against size threshold 111 if @max_obj_size && size > @max_obj_size 112 Arrow::Logger[self.class].debug \ 113 "%p not cached: size exceeds maxObjSize: %d" % 114 [ obj, @max_obj_size ] 85 115 return obj 86 116 end 117 if @max_obj_size.nil? && @max_size && size > @max_size 118 Arrow::Logger[self.class].debug \ 119 "%p not cached: size exceeds maxSize: %d" % 120 [ obj, @max_size ] 121 return obj 122 end 123 124 if @max_num && @list.size >= @max_num 125 Arrow::Logger[self.class].debug \ 126 "Dropping %p from the cache: count exceeds maxNum: %d" % 127 [ @list.first, @max_num ] 128 self.invalidate( @list.first ) 129 end 130 131 @size += size 132 if @max_size 133 while @size > @max_size 134 Arrow::Logger[self.class].debug \ 135 "Dropping %p from the cache: size exceeds maxSize: %d" % 136 [ @list.first, @max_size ] 137 self.invalidate( @list.first ) 138 end 139 end 140 141 @objs[ key ] = Cache::CACHE_OBJECT.new( obj, size, Time.now.to_i ) 142 @list.push( key ) 143 144 return obj 145 end 87 146 88 147 89 ###### 90 public 91 ###### 92 93 # The name of the cache; used in introspection 94 attr_reader :name 95 96 97 ### Overridden from the superclass to prevent .to_s from being called on 98 ### objects to determine their size if the object supports a #memsize 99 ### method. This is mostly to stop templates from being rendered every 100 ### time they're cached. 101 def []=( key, obj ) 102 self.expire 103 104 self.invalidate( key ) if self.cached?( key ) 105 106 if obj.respond_to?( :memsize ) 107 size = obj.memsize 108 else 109 size = obj.to_s.size 110 end 111 112 # Test against size threshold 113 if @max_obj_size && size > @max_obj_size 114 Arrow::Logger[self.class].debug \ 115 "%p not cached: size exceeds maxObjSize: %d" % 116 [ obj, @max_obj_size ] 117 return obj 118 end 119 if @max_obj_size.nil? && @max_size && size > @max_size 120 Arrow::Logger[self.class].debug \ 121 "%p not cached: size exceeds maxSize: %d" % 122 [ obj, @max_size ] 123 return obj 124 end 125 126 if @max_num && @list.size >= @max_num 127 Arrow::Logger[self.class].debug \ 128 "Dropping %p from the cache: count exceeds maxNum: %d" % 129 [ @list.first, @max_num ] 130 self.invalidate( @list.first ) 131 end 132 133 @size += size 134 if @max_size 135 while @size > @max_size 136 Arrow::Logger[self.class].debug \ 137 "Dropping %p from the cache: size exceeds maxSize: %d" % 138 [ @list.first, @max_size ] 139 self.invalidate( @list.first ) 140 end 141 end 142 143 @objs[ key ] = Cache::CACHE_OBJECT.new( obj, size, Time.now.to_i ) 144 @list.push( key ) 145 146 return obj 147 end 148 149 150 end # class Cache 151 152 end # module Arrow 153 154 148 end # class Arrow::Cache -
branches/broker-rewrite/lib/arrow/config-loaders/yaml.rb
r277 r284 38 38 # Add YAML domain types for Arrow classes 39 39 40 YAML.add_domain_type( Arrow::YamlDomain, "arrowPath" ) {|type, val|40 YAML.add_domain_type( Arrow::YamlDomain, "arrowPath" ) do |type, val| 41 41 obj = nil 42 42 case val … … 49 49 50 50 obj 51 }51 end 52 52 53 53 -
branches/broker-rewrite/lib/arrow/config.rb
r277 r284 9 9 # [<b>startMonitor</b>] 10 10 # Start the monitoring subsystem. Defaults to +false+. 11 # [<b>defaultApplet</b>]12 # The URI of the default applet to run when the Arrow appserver root URI13 # is requested. A value of '(builtin)' (the default) will cause a default14 # status method to be invoked.15 11 # [<b>noSuchAppletHandler</b>] 16 12 # The URI of the applet which should handle requests for applets that don't … … 153 149 :missingApplet => '/missing', 154 150 :errorApplet => '/error', 155 :defaultApplet => '/',156 151 }, 157 152 … … 358 353 ### from which it was loaded. 359 354 def changed? 360 return true if @struct.modified? 355 if @struct.modified? 356 self.log.debug "Struct was modified" 357 return true 358 end 361 359 return false unless self.name 362 self.loader.isNewer?( self.name, self.createTime ) 360 if self.loader.isNewer?( self.name, self.createTime ) 361 self.log.debug "Config source (%s) has been updated since %s" % 362 [ self.name, self.createTime ] 363 return true 364 end 363 365 end 364 366 … … 422 424 def initialize( hash ) 423 425 @hash = hash.dup 424 @ modified= false426 @dirty = false 425 427 end 426 428 … … 438 440 ### have changed since it was created. 439 441 def modified? 440 return @modified|| @hash.values.find do |obj|442 @dirty || @hash.values.find do |obj| 441 443 obj.is_a?( ConfigStruct ) && obj.modified? 442 444 end … … 518 520 519 521 # :TODO: Actually check to see if anything has changed? 520 @ modified= true522 @dirty = true 521 523 522 524 return self … … 551 553 define_method( "#{key}?" ) {@hash[key] ? true : false} 552 554 define_method( "#{key}=" ) {|val| 553 @ modified= @hash[key] != val555 @dirty = @hash[key] != val 554 556 @hash[key] = val 555 557 } -
branches/broker-rewrite/lib/arrow/dispatcher.rb
