aboutsummaryrefslogtreecommitdiffstats
path: root/railties/dispatches/gateway.cgi
blob: 0305b7f810fe966dd0ae557effbbf14ebb98687c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/usr/bin/env ruby

require 'drb'

# This file includes an experimental gateway CGI implementation. It will work
# only on platforms which support both fork and sockets.
#
# To enable it edit public/.htaccess and replace dispatch.cgi with gateway.cgi.
#
# Next, create the directory log/drb_gateway and grant the apache user rw access
# to said directory.
#
# On the next request to your server, the gateway tracker should start up, along
# with a few listener processes. This setup should provide you with much better
# speeds than dispatch.cgi.
#
# Keep in mind that the first request made to the server will be slow, as the
# tracker and listeners will have to load. Also, the tracker and listeners will
# shutdown after a period if inactivity. You can set this value below -- the
# default is 90 seconds.

TrackerSocket = File.expand_path(File.join(File.dirname(__FILE__), '../log/drb_gateway/tracker.sock'))
DieAfter = 90 # Seconds
Listeners = 3

def message(s)
  $stderr.puts "gateway.cgi: #{s}" if ENV && ENV["DEBUG_GATEWAY"]
end

def listener_socket(number)
  File.expand_path(File.join(File.dirname(__FILE__), "../log/drb_gateway/listener_#{number}.sock"))
end

unless File.exist? TrackerSocket
  message "Starting tracker and #{Listeners} listeners"
  fork do
    Process.setsid
    STDIN.reopen "/dev/null"
    STDOUT.reopen "/dev/null", "a"

    root = File.expand_path(File.dirname(__FILE__) + '/..')

    message "starting tracker"
    fork do
      ARGV.clear
      ARGV << TrackerSocket << Listeners.to_s << DieAfter.to_s
      load File.join(root, 'script', 'tracker')
    end

    message "starting listeners"
    require File.join(root, 'config/environment.rb')
    Listeners.times do |number|
      fork do
        ARGV.clear
        ARGV << listener_socket(number) << DieAfter.to_s
        load File.join(root, 'script', 'listener')
      end
    end
  end

  message "waiting for tracker and listener to arise..."
  ready = false
  10.times do
    sleep 0.5
    break if (ready = File.exist?(TrackerSocket) && File.exist?(listener_socket(0)))
  end

  if ready
    message "tracker and listener are ready"
  else
    message "Waited 5 seconds, listener and tracker not ready... dropping request"
    Kernel.exit 1
  end
end

DRb.start_service

message "connecting to tracker"
tracker = DRbObject.new_with_uri("drbunix:#{TrackerSocket}")

input = $stdin.read
$stdin.close

env = ENV.inspect

output = nil
tracker.with_listener do |number|
  message "connecting to listener #{number}"
  socket = listener_socket(number)
  listener = DRbObject.new_with_uri("drbunix:#{socket}")
  output = listener.process(env, input)
  message "listener #{number} has finished, writing output"
end

$stdout.write output
$stdout.flush
$stdout.close