aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib/commands/ncgi
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2005-09-29 12:18:51 +0000
committerDavid Heinemeier Hansson <david@loudthinking.com>2005-09-29 12:18:51 +0000
commit0a0ac868453e9d8d9ee1dac6a7eb274772235b05 (patch)
tree1db7e1fce4d2c62f97c204ef72e7898c5263c82a /railties/lib/commands/ncgi
parent070d218c479c8cbb41e78f599110f0ea1cf0343a (diff)
downloadrails-0a0ac868453e9d8d9ee1dac6a7eb274772235b05.tar.gz
rails-0a0ac868453e9d8d9ee1dac6a7eb274772235b05.tar.bz2
rails-0a0ac868453e9d8d9ee1dac6a7eb274772235b05.zip
Removed all the scripts in script/* and replaced it with one generic portal: script/run
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@2411 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'railties/lib/commands/ncgi')
-rw-r--r--railties/lib/commands/ncgi/listener86
-rw-r--r--railties/lib/commands/ncgi/tracker69
2 files changed, 155 insertions, 0 deletions
diff --git a/railties/lib/commands/ncgi/listener b/railties/lib/commands/ncgi/listener
new file mode 100644
index 0000000000..421c453f23
--- /dev/null
+++ b/railties/lib/commands/ncgi/listener
@@ -0,0 +1,86 @@
+#!/usr/local/bin/ruby
+
+require 'stringio'
+require 'fileutils'
+require 'fcgi_handler'
+
+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
+
+ def initialize(timeout, socket_path)
+ @socket = File.expand_path(socket_path)
+ @mutex = Mutex.new
+ @active = false
+ @timeout = timeout
+
+ @handler = RailsFCGIHandler.new
+ @handler.extend DRbUndumped
+
+ message 'opening socket'
+ DRb.start_service("drbunix:#{@socket}", self)
+
+ message 'entering process loop'
+ @handler.process! self
+ end
+
+ def each_cgi(&cgi_block)
+ @cgi_block = cgi_block
+ message 'entering idle loop'
+ loop do
+ sleep @timeout rescue nil
+ die! unless @active
+ @active = false
+ end
+ end
+
+ 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 die!
+ message 'shutting down'
+ DRb.stop_service
+ FileUtils.rm_f @socket
+ Kernel.exit 0
+ end
+end
+
+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/lib/commands/ncgi/tracker b/railties/lib/commands/ncgi/tracker
new file mode 100644
index 0000000000..859c9fa0e0
--- /dev/null
+++ b/railties/lib/commands/ncgi/tracker
@@ -0,0 +1,69 @@
+#!/usr/local/bin/ruby
+
+require 'drb'
+require 'thread'
+
+def message(s)
+ $stderr.puts "tracker: #{s}" if ENV && ENV["DEBUG_GATEWAY"]
+end
+
+class Tracker
+ include DRbUndumped
+
+ 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
+ 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
+
+ if has_lock
+ message "obtained listener #{index}"
+ @active = true
+ begin yield index
+ ensure
+ mutex.unlock
+ message "released listener #{index}"
+ end
+ else
+ message "dropping request because no listeners are available!"
+ end
+ end
+
+ 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
+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