blob: 17fce67e5448c4734bd8fc46465ea23d24d0ac7b (
plain) (
tree)
|
|
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
|