111 lines
2.3 KiB
Plaintext
111 lines
2.3 KiB
Plaintext
require "drb"
|
|
require "rbconfig"
|
|
|
|
VERBOSE = false
|
|
|
|
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
|
|
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
|
|
end
|
|
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
|
|
end
|
|
@processed = false
|
|
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
|
|
)
|
|
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
|