diff options
author | David Heinemeier Hansson <david@loudthinking.com> | 2005-07-06 04:29:18 +0000 |
---|---|---|
committer | David Heinemeier Hansson <david@loudthinking.com> | 2005-07-06 04:29:18 +0000 |
commit | 707106f347fada1ac9a7c9e2da7e6d2342f8441d (patch) | |
tree | 41f972702ec8cd2e47983120618bbb9d89c420f8 /railties/bin | |
parent | 31702951365c26f930a5f39698cb51309e111e98 (diff) | |
download | rails-707106f347fada1ac9a7c9e2da7e6d2342f8441d.tar.gz rails-707106f347fada1ac9a7c9e2da7e6d2342f8441d.tar.bz2 rails-707106f347fada1ac9a7c9e2da7e6d2342f8441d.zip |
Added fixed gateway script [Nicholas Seckar]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1721 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'railties/bin')
-rw-r--r-- | railties/bin/listener | 147 | ||||
-rw-r--r-- | railties/bin/tracker | 149 |
2 files changed, 119 insertions, 177 deletions
diff --git a/railties/bin/listener b/railties/bin/listener index 493ac9dca4..421c453f23 100644 --- a/railties/bin/listener +++ b/railties/bin/listener @@ -1,103 +1,86 @@ -require "drb" -ENV["RAILS_ENV"] = 'production' -require "#{File.dirname(__FILE__)}/../config/environment.rb" +#!/usr/local/bin/ruby + +require 'stringio' +require 'fileutils' require 'fcgi_handler' -require 'rbconfig' -VERBOSE = false +def message(s) + $stderr.puts "listener: #{s}" if ENV && ENV["DEBUG_GATEWAY"] +end + +class RemoteCGI < CGI + attr_accessor :stdinput, :stdoutput, :env_table + def initialize(env_table, input = nil, output = nil) + self.env_table = env_table + self.stdinput = input || StringIO.new + self.stdoutput = output || StringIO.new + super() + end + + def out(stream) # Ignore the requested output stream + super(stdoutput) + end +end class Listener include DRbUndumped - attr_accessor :tracker - - def initialize(timeout = nil) - @timeout = timeout + + def initialize(timeout, socket_path) + @socket = File.expand_path(socket_path) @mutex = Mutex.new @active = false - + @timeout = timeout + @handler = RailsFCGIHandler.new @handler.extend DRbUndumped - @output = FakeOut.new - $stdout = @output - end - - def inform_up(tracker_uri) - return unless tracker_uri - tracker = DRbObject.new_with_uri(tracker_uri) - tracker.register_listener self - @tracker = tracker - end - def inform_down - @tracker.remove_listener(self) if @tracker - end - def run(on_uri, tracker_uri) - on_uri ||= "drbunix:" - DRb.start_service(on_uri, self) # Start a server for us - inform_up tracker_uri - @handler.process!(self) - end - - def die! - inform_down - Kernel.exit 0 - end - - def process(input) - $stderr.puts "listener: received request -- obtaining lock" if VERBOSE - @mutex.synchronize do - @active = true - - $stderr.puts "listener: obtained -- swaping stdin" if VERBOSE - $stdin = input - cgi = CGI.new - - $stderr.puts "listener: yielding to FCGI handler..." if VERBOSE - @cgi_block.call cgi - $stderr.puts "listener: handler finished, releasing control" if VERBOSE - - return @output.read! - end + message 'opening socket' + DRb.start_service("drbunix:#{@socket}", self) + + message 'entering process loop' + @handler.process! self end - - def each_cgi(&block) - @cgi_block = block + + def each_cgi(&cgi_block) + @cgi_block = cgi_block + message 'entering idle loop' loop do - @timeout ? sleep(@timeout) : sleep + sleep @timeout rescue nil die! unless @active @active = false end end -end -class FakeOut < Struct.new(:contents) - def initialize - super("") - end - def write(str) - contents << str + def process(env, input) + message 'received request' + @mutex.synchronize do + @active = true + + message 'creating input stream' + input_stream = StringIO.new(input) + message 'building CGI instance' + cgi = RemoteCGI.new(eval(env), input_stream) + + message 'yielding to fcgi handler' + @cgi_block.call cgi + message 'yield finished -- sending output' + + cgi.stdoutput.seek(0) + output = cgi.stdoutput.read + + return output + end end - def read! - c = contents - self.contents = '' - return c + + def die! + message 'shutting down' + DRb.stop_service + FileUtils.rm_f @socket + Kernel.exit 0 end end -if ARGV.shift == 'start-listeners' - tracker = ARGV.shift - number = (ARGV.shift || '1').to_i - exit(0) if number.zero? - - if number > 1 - fork do - exec( - File.join(Config::CONFIG['bin_dir'], Config::CONFIG['RUBY_SO_NAME']), - __FILE__, 'start-listeners', tracker, (number - 1).to_s - ) - end - end - - l = Listener.new(90) - l.run(nil, tracker) -end
\ No newline at end of file +socket_path = ARGV.shift +timeout = (ARGV.shift || 90).to_i + +Listener.new(timeout, socket_path)
\ No newline at end of file diff --git a/railties/bin/tracker b/railties/bin/tracker index 17fce67e54..859c9fa0e0 100644 --- a/railties/bin/tracker +++ b/railties/bin/tracker @@ -1,110 +1,69 @@ -require "drb" -require "rbconfig" +#!/usr/local/bin/ruby -VERBOSE = false +require 'drb' +require 'thread' + +def message(s) + $stderr.puts "tracker: #{s}" if ENV && ENV["DEBUG_GATEWAY"] +end class Tracker include DRbUndumped - - def initialize(timeout = 90, uri = nil) - @timeout = timeout - @waiting = [] - @working = [] - - @waiting_mutex = Mutex.new - - DRb.start_service(uri, self) - @uri = DRb.uri - end - def run - start_listener 3 - sleep 3 - - background - end - - def register_listener(listener) - @waiting.push listener - nil - end - def remove_listener(listener) - @waiting.delete listener - @working.delete listener - nil + + def initialize(instances, socket_path) + @instances = instances + @socket = File.expand_path(socket_path) + @active = false + + @listeners = [] + @instances.times { @listeners << Mutex.new } + + message "using #{@listeners.length} listeners" + message "opening socket at #{@socket}" + + @service = DRb.start_service("drbunix://#{@socket}", self) end - + def with_listener - listener = @waiting.shift - unless listener - start_listener(2) unless @waiting.length + @working.length > 6 - @waiting_mutex.synchronize do - 10.times do - sleep 0.5 - listener = @waiting.shift - break if listener - end - unless listener - ($stderr.puts "Dropping request due to lack of listeners!!!" unless listener) if VERBOSE - return - end + message "listener requested" + + mutex = has_lock = index = nil + 3.times do + @listeners.each_with_index do |mutex, index| + has_lock = mutex.try_lock + break if has_lock end + break if has_lock + sleep 0.05 end - - @working << listener - yield listener - ensure - if listener - @working.delete listener - @waiting << listener - end - end - - def background - loop do - @timeout ? sleep(@timeout) : sleep - unless @processed - $stderr.puts "Idle for #{@timeout} -- shutting down tracker." if VERBOSE - Kernel.exit 0 + + if has_lock + message "obtained listener #{index}" + @active = true + begin yield index + ensure + mutex.unlock + message "released listener #{index}" end - @processed = false + else + message "dropping request because no listeners are available!" end end - - def process(input) - output = nil - $stderr.puts "tracker: received request.. obtaining listener" if VERBOSE - with_listener do |listener| - $stderr.puts "tracker: obtained -- forwarding request to listener.." if VERBOSE - @processed = true - output = listener.process(input) - $stderr.puts "tracker: listener released control." if VERBOSE - end - return output - end - - def start_listener(n = 1) - tracker_uri = @uri - listener_path = File.join(File.dirname(__FILE__), 'listener') - fork do - exec( - File.join(Config::CONFIG['bin_dir'], Config::CONFIG['RUBY_SO_NAME']), - listener_path, 'start-listeners', tracker_uri, n.to_s - ) + + def background(check_interval = nil) + if check_interval + loop do + sleep check_interval + message "Idle for #{check_interval}, shutting down" unless @active + @active = false + Kernel.exit 0 + end + else DRb.thread.join end end - - def ping - true - end end -if ARGV.first == "start" - tracker = Tracker.new(90, ARGV[1]) - socket = (/druby:([^?]*)\?/ =~ ARGV[1]) ? $1 : nil - require 'fileutils' if socket - - begin tracker.run - ensure - FileUtils.rm_f(socket) if socket - end -end +socket_path = ARGV.shift +instances = ARGV.shift.to_i +t = Tracker.new(instances, socket_path) +t.background(ARGV.first ? ARGV.shift.to_i : 90)
\ No newline at end of file |