ruby-style 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +54 -52
- data/lib/style/adapter/rails.rb +37 -0
- data/lib/style/adapter/ramaze.rb +14 -0
- data/lib/style/handler/evented_mongrel.rb +3 -0
- data/lib/style/handler/eventmachine.rb +43 -0
- data/lib/style/handler/mongrel.rb +20 -0
- data/lib/{RailsSCGIStyle.rb → style/handler/scgi.rb} +26 -5
- data/lib/style.rb +78 -33
- metadata +8 -4
- data/lib/RailsMongrelStyle.rb +0 -61
data/README
CHANGED
@@ -28,7 +28,8 @@ Subversion access is available at svn://code.jeremyevans.net/ruby-style/.
|
|
28
28
|
the fly
|
29
29
|
* Supports both command line and yaml config file configuration
|
30
30
|
* Is easily extensible to support running other frameworks and protocols other
|
31
|
-
than the included ones (
|
31
|
+
than the included ones (Rails and Ramaze; SCGI, Mongrel, and Evented
|
32
|
+
Mongrel)
|
32
33
|
|
33
34
|
== Running and configuration
|
34
35
|
|
@@ -37,16 +38,18 @@ just run the program without any arguments:
|
|
37
38
|
|
38
39
|
style [option value, ...] (decrement|halt|increment|restart|start|stop)
|
39
40
|
Options:
|
41
|
+
-a, --adapter Adapter/Framework to use [rails]
|
40
42
|
-b, --bind IP address to bind to [127.0.0.1]
|
41
43
|
-c, --config Location of config file [config/style.yaml]
|
42
44
|
-d, --directory Working directory [.]
|
45
|
+
-D, --debug Run the program in the foreground without forking [No]
|
43
46
|
-f, --fork Number of listners on each port [1]
|
47
|
+
-h, --handler Handler/Server to use [mongrel]
|
44
48
|
-k, --killtime Number of seconds to wait when killing each child [2]
|
45
49
|
-l, --logfile Where to redirect STDOUT and STDERR [log/style.log]
|
46
50
|
-n, --number Number of ports to which to bind [1]
|
47
51
|
-p, --port Starting port to which to bind [9999]
|
48
52
|
-P, --pidfile Location of pid file [log/style.pid]
|
49
|
-
-s, --style Type of style to use [RailsMongrel]
|
50
53
|
-u, --unsupervised Whether to run unsupervised [No]
|
51
54
|
|
52
55
|
Here's what the various commands do:
|
@@ -66,9 +69,15 @@ process, so the -c, -l, and -P options are relative to that.
|
|
66
69
|
|
67
70
|
Here's a longer explanation of the options:
|
68
71
|
|
72
|
+
-a, --adapter Adapter/Framework to use [rails]
|
73
|
+
|
74
|
+
This is the adapter/framework to use. Support for Rails and Ramaze is
|
75
|
+
included in the distribution, support for other frameworks should be fairly
|
76
|
+
easy to add.
|
77
|
+
|
69
78
|
-b, --bind IP address to bind to [127.0.0.1]
|
70
79
|
|
71
|
-
This is the TCP/IP networking
|
80
|
+
This is the TCP/IP networking socket to bind to. It defaults to the
|
72
81
|
loopback address because generally the web application runs on the same
|
73
82
|
physical server as the web server. If this is not the case, change it to an
|
74
83
|
externally available IP, and make sure to lock down access to the port via a
|
@@ -89,6 +98,11 @@ Here's a longer explanation of the options:
|
|
89
98
|
root of the application before hand and then not use this option. This option
|
90
99
|
is not configurable from the configuration file.
|
91
100
|
|
101
|
+
-D, --debug Run the program in the foreground without forking [No]
|
102
|
+
|
103
|
+
This runs the program in the program without forking, aiding in debugging a
|
104
|
+
problematic configuration.
|
105
|
+
|
92
106
|
-f, --fork Number of listners on each port [1]
|
93
107
|
|
94
108
|
This enables multiple child processes listening on each port. It is
|
@@ -100,6 +114,13 @@ Here's a longer explanation of the options:
|
|
100
114
|
are killed, so it is possibly to have multiple processes listening on a port
|
101
115
|
even if this is left at one.
|
102
116
|
|
117
|
+
-h, --handler Handler/Server to use [mongrel]
|
118
|
+
|
119
|
+
This is the handler/server to use. Support for Mongrel, Evented Mongrel,
|
120
|
+
and SCGI is included in the distribution. Support for other servers is
|
121
|
+
easy to add as long as the servers can be modified to use the socket
|
122
|
+
created by style ($STYLE_SOCKET).
|
123
|
+
|
103
124
|
-k, --killtime Number of seconds to wait when killing each child [2]
|
104
125
|
|
105
126
|
This sets the time that style between sending shutdown signals to child
|
@@ -134,15 +155,6 @@ Here's a longer explanation of the options:
|
|
134
155
|
they should be, and you will probably won't be able to start new processes
|
135
156
|
(because the ports will still be in use).
|
136
157
|
|
137
|
-
-s, --style Type of style to use [RailsMongrel]
|
138
|
-
|
139
|
-
This is the type of style to use. It defaults to RailsMongrel, as that is
|
140
|
-
most common configuration these days. The other style included with style is
|
141
|
-
RailsSCGI. Adding other styles is fairly easy, just make the style is in a
|
142
|
-
file named XXXXXStyle.rb (where XXXXX is in the name of the style), and that
|
143
|
-
file is located in ruby's library path ($:, e.g. via the RUBYLIB environment
|
144
|
-
variable). See the included styles for an example.
|
145
|
-
|
146
158
|
-u, --unsupervised Whether to run unsupervised [No]
|
147
159
|
|
148
160
|
This starts child processes without using a supervisor process. It is not
|
@@ -152,24 +164,15 @@ Here's a longer explanation of the options:
|
|
152
164
|
restarted when they die, and you may lose connections during restarts.
|
153
165
|
|
154
166
|
Every one of the long options can also be specified in the config file. Also,
|
155
|
-
the
|
156
|
-
being used (such as modifying the Rails environment setting).
|
157
|
-
|
158
|
-
== Included styles and config files
|
159
|
-
|
160
|
-
style current comes with support for the following styles: RailsMongrelStyle
|
161
|
-
(the default, which requires rails and mongrel), and RailsSCGIStyle (which
|
162
|
-
requires rails and ruby-scgi).
|
167
|
+
the config file must be used if you want to specify any settings specific to
|
168
|
+
adapter being used (such as modifying the Rails environment setting). See
|
169
|
+
below for information on the adapter_config config file variable.
|
163
170
|
|
164
|
-
The
|
165
|
-
be deployed behind a front end webserver, such as Apache, Lighttpd, or Nginx.
|
166
|
-
The RailsSCGI style supports running Rails over SCGI, which is supported by
|
167
|
-
both Apache and Lighttpd. Both default to running Rails in production mode,
|
168
|
-
as style is designed as a production tool.
|
171
|
+
== The config file
|
169
172
|
|
170
|
-
Example
|
171
|
-
interface, with three listeners per port. Note how the :
|
172
|
-
used to set up settings specific to the
|
173
|
+
Example Rails+Mongrel style.yaml that listens on ports 8912 and 8193 on any
|
174
|
+
interface, with three listeners per port. Note how the :adapter_config entry
|
175
|
+
is used to set up settings specific to the Rails adapter, such as placing
|
173
176
|
Rails in development mode.
|
174
177
|
|
175
178
|
---
|
@@ -178,32 +181,36 @@ Rails in development mode.
|
|
178
181
|
:fork: 3
|
179
182
|
:number: 2
|
180
183
|
:killtime: 1
|
181
|
-
:
|
182
|
-
:
|
184
|
+
:adapter: rails
|
185
|
+
:handler: mongrel
|
186
|
+
:adapter_config:
|
183
187
|
:environment: development
|
184
188
|
:log_file: log/rails-mongrel.log
|
185
189
|
:docroot: public
|
186
190
|
:num_processors: 99
|
187
191
|
:timeout: 100
|
188
192
|
|
189
|
-
Example
|
193
|
+
Example Rails+SCGI style.yaml that has four listeners on port 8912:
|
190
194
|
|
191
195
|
---
|
192
196
|
:port: 8912
|
193
197
|
:fork: 4
|
194
198
|
:number: 1
|
195
|
-
:
|
196
|
-
:
|
199
|
+
:adapter: rails
|
200
|
+
:handler: scgi
|
201
|
+
:adapter_config:
|
197
202
|
:logfile: log/railsscgi.log
|
198
203
|
:maxconns: 10
|
199
204
|
:environment: production
|
200
205
|
|
201
|
-
Very simple configuration that runs
|
202
|
-
port 3000.
|
206
|
+
Very simple configuration that runs Ramaze+Evented Mongrel in unsupervised
|
207
|
+
mode on port 3000.
|
203
208
|
|
204
209
|
---
|
205
210
|
:port: 3000
|
206
211
|
:unsupervised: 1
|
212
|
+
:adapter: ramaze
|
213
|
+
:handler: evented_mongrel
|
207
214
|
|
208
215
|
== How restarting works
|
209
216
|
|
@@ -261,25 +268,20 @@ Thu Sep 6 12:01:59 PDT 2007
|
|
261
268
|
Result, three brand new listening processes, total time to restart is about 12
|
262
269
|
seconds (2 * (2 killtime * 1 number * 3 fork)).
|
263
270
|
|
264
|
-
== Other
|
271
|
+
== Other handlers and adapter
|
265
272
|
|
266
|
-
|
267
|
-
|
273
|
+
To add support for another handler, make sure the instead of creating a socket,
|
274
|
+
it uses the socket provided by style, available in the global variable
|
275
|
+
$STYLE_SOCKET. See existing handler code to see how Mongrel, SCGI, and Event
|
276
|
+
Machine were modified to support this.
|
268
277
|
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
def initialize(options)
|
273
|
-
#options is a Hash
|
274
|
-
end
|
275
|
-
|
276
|
-
def listen(socket)
|
277
|
-
# socket is a TCPServer
|
278
|
-
end
|
279
|
-
end
|
278
|
+
Support for other adapters is easily added by adding the run method to the
|
279
|
+
Style class. This can be easy (as it is with Ramaze), or more difficult (as it
|
280
|
+
is with Rails). If the adapter uses Rack, it should be fairly simple.
|
280
281
|
|
281
|
-
|
282
|
-
|
282
|
+
Style loads adapters and handlers from style/{adapter,handler} relative to the
|
283
|
+
load path, so you can add your own adapters and handlers without modifying the
|
284
|
+
program, as long as you place the files somewhere in the load path.
|
283
285
|
|
284
286
|
== FAQ
|
285
287
|
|
@@ -289,4 +291,4 @@ A: No. Among other things, style uses fork, which is not available on Windows.
|
|
289
291
|
|
290
292
|
Q: Does it work with Capistrano yet?
|
291
293
|
|
292
|
-
A: I haven't tried.
|
294
|
+
A: I haven't tried. It probably can, but it will take a little custom work.
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
# This hooks the HTTP request into Ruby on Rails and Mongrel.
|
4
|
+
class Style
|
5
|
+
# Initialzes Rails and Mongrel with the appropriate environment and settings.
|
6
|
+
def run
|
7
|
+
config[:handler] == 'scgi' ? run_rails_scgi : run_rails_mongrel
|
8
|
+
end
|
9
|
+
|
10
|
+
def run_rails_scgi
|
11
|
+
RailsSCGIProcessor.new(config[:adapter_config]).listen
|
12
|
+
end
|
13
|
+
|
14
|
+
def run_rails_mongrel
|
15
|
+
require 'mongrel/rails'
|
16
|
+
settings = {:cwd => Dir.pwd, :log_file => 'log/rails-mongrel.log',
|
17
|
+
:environment => 'production', :docroot => 'public',
|
18
|
+
:mime_map => nil, :debug => false, :includes => ["mongrel"],
|
19
|
+
:config_script => nil, :num_processors => 1024, :timeout => 0,
|
20
|
+
:user => nil, :group => nil, :prefix => nil}.merge(config[:adapter_config])
|
21
|
+
ENV['RAILS_ENV'] = settings[:environment]
|
22
|
+
$0 += " environment:#{ENV['RAILS_ENV']}"
|
23
|
+
mongrel = Mongrel::Rails::RailsConfigurator.new(settings) do
|
24
|
+
listener do
|
25
|
+
mime = defaults[:mime_map] ? load_mime_map(defaults[:mime_map], mime) : {}
|
26
|
+
debug "/" if defaults[:debug]
|
27
|
+
uri defaults[:prefix] || "/", :handler => rails(:mime => mime, :prefix => defaults[:prefix])
|
28
|
+
load_plugins
|
29
|
+
run_config(defaults[:config_script]) if defaults[:config_script]
|
30
|
+
trap("INT") { @log.info("SIGTERM, forced shutdown."); shutdown(force=true) }
|
31
|
+
setup_rails_signals
|
32
|
+
end
|
33
|
+
end
|
34
|
+
mongrel.run
|
35
|
+
mongrel.join
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ramaze'
|
3
|
+
|
4
|
+
class Style
|
5
|
+
# Run Ramaze with the mongrel adapter and start.rb runner
|
6
|
+
def run
|
7
|
+
settings = {:adapter=>config[:handler].to_sym, :test_connections=>false,
|
8
|
+
:force=>true, :runner =>'start.rb', :host=>config[:bind],
|
9
|
+
:port=>config[:sockets][$STYLE_SOCKET]}.merge(config[:adapter_config])
|
10
|
+
require settings[:runner].to_s
|
11
|
+
Ramaze.start(settings)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
$eventmachine_library = :pure_ruby
|
3
|
+
require 'eventmachine'
|
4
|
+
|
5
|
+
module EventMachine
|
6
|
+
class StreamObject < Selectable
|
7
|
+
# Delete this when EventMachine fixes typo bug (Rubyforge bug #17461), see
|
8
|
+
# https://rubyforge.org/tracker/index.php?func=detail&aid=17461&group_id=1555&atid=6060
|
9
|
+
def eventable_write
|
10
|
+
# coalesce the outbound array here, perhaps
|
11
|
+
@last_activity = Reactor.instance.current_loop_time
|
12
|
+
while data = @outbound_q.shift do
|
13
|
+
begin
|
14
|
+
data = data.to_s
|
15
|
+
w = if io.respond_to?(:write_nonblock)
|
16
|
+
io.write_nonblock data
|
17
|
+
else
|
18
|
+
io.syswrite data
|
19
|
+
end
|
20
|
+
|
21
|
+
if w < data.length
|
22
|
+
@outbound_q.unshift data[w..-1]
|
23
|
+
break
|
24
|
+
end
|
25
|
+
rescue Errno::EAGAIN
|
26
|
+
@outbound_q.unshift data
|
27
|
+
rescue EOFError, Errno::ECONNRESET, Errno::ECONNREFUSED
|
28
|
+
@close_scheduled = true
|
29
|
+
@outbound_q.clear
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class EvmaTCPServer < Selectable
|
36
|
+
class << self
|
37
|
+
# Use $STYLE_SOCKET instead of creating a socket with the host and port
|
38
|
+
def start_server(host, port)
|
39
|
+
EvmaTCPServer.new $STYLE_SOCKET
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'mongrel'
|
3
|
+
|
4
|
+
module Mongrel
|
5
|
+
class HttpServer
|
6
|
+
# Keep the interface the same, but ignore the host and port and use the
|
7
|
+
# socket provided by style
|
8
|
+
def initialize(host, port, num_processors=950, throttle=0, timeout=60)
|
9
|
+
tries = 0
|
10
|
+
@socket = $STYLE_SOCKET
|
11
|
+
@classifier = URIClassifier.new
|
12
|
+
@host = host
|
13
|
+
@port = port
|
14
|
+
@workers = ThreadGroup.new
|
15
|
+
@throttle = throttle
|
16
|
+
@num_processors = num_processors
|
17
|
+
@timeout = timeout
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,13 +1,34 @@
|
|
1
|
-
|
1
|
+
require 'rubygems'
|
2
2
|
require 'scgi'
|
3
3
|
|
4
|
+
class SCGI::Processor
|
5
|
+
# Use the standard error as the output logger, and use $STYLE_SOCKET as the
|
6
|
+
# socket on which to listen
|
7
|
+
def initialize(settings = {})
|
8
|
+
@socket ||= $STYLE_SOCKET
|
9
|
+
@total_conns ||= 0
|
10
|
+
@shutdown ||= false
|
11
|
+
@dead ||= false
|
12
|
+
@threads ||= Queue.new
|
13
|
+
@log = Object.new
|
14
|
+
def @log.info(msg)
|
15
|
+
STDERR.puts("[INF][#{@pid ||= Process.pid}] #{msg}")
|
16
|
+
end
|
17
|
+
def @log.error(msg, exc=nil)
|
18
|
+
STDERR.puts("[ERR][#{@pid ||= Process.pid}] #{msg}#{": #{exc}\n#{exc.backtrace.join("\n")}" if exc}")
|
19
|
+
end
|
20
|
+
@maxconns ||= settings[:maxconns] || 2**30-1
|
21
|
+
super()
|
22
|
+
setup_signals
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
4
26
|
# This SCGI::Processor subclass hooks the SCGI request into Ruby on Rails.
|
5
|
-
class
|
27
|
+
class RailsSCGIProcessor < SCGI::Processor
|
6
28
|
# Initialzes Rails with the appropriate environment and settings
|
7
29
|
def initialize(settings)
|
8
|
-
ENV['RAILS_ENV'] = settings[:environment] || 'production'
|
9
|
-
|
10
|
-
require "config/environment"
|
30
|
+
$0 += " environment:#{ENV['RAILS_ENV'] = settings[:environment] || 'production'}"
|
31
|
+
require 'config/environment'
|
11
32
|
ActiveRecord::Base.allow_concurrency = false
|
12
33
|
require 'dispatcher'
|
13
34
|
super(settings)
|
data/lib/style.rb
CHANGED
@@ -16,16 +16,15 @@ require 'yaml'
|
|
16
16
|
# trees.
|
17
17
|
class Style
|
18
18
|
attr_reader :config, :mutex
|
19
|
-
VALID_STYLE_RE = /\A[A-Z][A-ZA-z0-9]*\z/
|
20
19
|
|
21
20
|
# Configure style
|
22
21
|
def initialize
|
23
|
-
super
|
24
22
|
@config = {:pidfile=>'log/style.pid', :number=>1, :port=>9999,
|
25
23
|
:style=>'RailsMongrel', :fork=>1, :bind=>'127.0.0.1',
|
26
24
|
:cliconfig=>{}, :killtime=>2, :config=>'config/style.yaml',
|
27
25
|
:logfile=>'log/style.log', :children=>{},:sockets=>{},
|
28
|
-
:
|
26
|
+
:adapter_config=>{}, :directory=>'.', :debug=>false,
|
27
|
+
:unsupervised=> false, :adapter=>'rails', :handler=>'mongrel'}
|
29
28
|
@mutex = Mutex.new
|
30
29
|
begin
|
31
30
|
parse_options
|
@@ -58,6 +57,12 @@ class Style
|
|
58
57
|
conf
|
59
58
|
end
|
60
59
|
|
60
|
+
def create_socket(bind, port)
|
61
|
+
socket = TCPServer.new(bind, port)
|
62
|
+
socket.listen(50)
|
63
|
+
socket
|
64
|
+
end
|
65
|
+
|
61
66
|
# Detach the process from the controlling terminal, exit otherwise
|
62
67
|
def detach
|
63
68
|
unless Process.setsid
|
@@ -66,13 +71,12 @@ class Style
|
|
66
71
|
end
|
67
72
|
trap(:HUP, 'IGNORE')
|
68
73
|
end
|
69
|
-
|
70
|
-
#
|
71
|
-
def
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
eval(style)
|
74
|
+
|
75
|
+
# Print the error message and the usage, then exit
|
76
|
+
def exit_with_error(error_message)
|
77
|
+
puts error_message
|
78
|
+
puts usage
|
79
|
+
exit(1)
|
76
80
|
end
|
77
81
|
|
78
82
|
# Kill each of the given pids in order
|
@@ -92,6 +96,16 @@ class Style
|
|
92
96
|
return nil
|
93
97
|
end
|
94
98
|
end
|
99
|
+
|
100
|
+
# Load the revelent style adapter/framework
|
101
|
+
def load_adapter
|
102
|
+
require "style/adapter/#{config[:adapter]}"
|
103
|
+
end
|
104
|
+
|
105
|
+
# Load the revelent style handler/server
|
106
|
+
def load_handler
|
107
|
+
require "style/handler/#{config[:handler]}"
|
108
|
+
end
|
95
109
|
|
96
110
|
# Parse the command line options, and merge them with the default options and
|
97
111
|
# the config file options. Config file options take precendence over the
|
@@ -99,27 +113,35 @@ class Style
|
|
99
113
|
def parse_options
|
100
114
|
cliconfig = config[:cliconfig]
|
101
115
|
GetoptLong.new(
|
116
|
+
[ '--adapter', '-a', GetoptLong::REQUIRED_ARGUMENT ],
|
102
117
|
[ '--bind', '-b', GetoptLong::REQUIRED_ARGUMENT ],
|
103
118
|
[ '--config', '-c', GetoptLong::REQUIRED_ARGUMENT ],
|
104
119
|
[ '--directory', '-d', GetoptLong::REQUIRED_ARGUMENT ],
|
120
|
+
[ '--debug', '-D', GetoptLong::NO_ARGUMENT],
|
105
121
|
[ '--fork', '-f', GetoptLong::REQUIRED_ARGUMENT ],
|
122
|
+
[ '--handler', '-h', GetoptLong::REQUIRED_ARGUMENT ],
|
106
123
|
[ '--killtime', '-k', GetoptLong::REQUIRED_ARGUMENT ],
|
107
124
|
[ '--logfile', '-l', GetoptLong::REQUIRED_ARGUMENT ],
|
108
125
|
[ '--number', '-n', GetoptLong::REQUIRED_ARGUMENT ],
|
109
126
|
[ '--port', '-p', GetoptLong::REQUIRED_ARGUMENT ],
|
110
127
|
[ '--pidfile', '-P', GetoptLong::REQUIRED_ARGUMENT ],
|
111
|
-
[ '--style', '-s', GetoptLong::REQUIRED_ARGUMENT ],
|
112
128
|
[ '--unsupervised', '-u', GetoptLong::NO_ARGUMENT]
|
113
129
|
).each do |opt, arg|
|
114
130
|
case opt
|
131
|
+
when '--adapter'
|
132
|
+
cliconfig[:adapter] = arg
|
115
133
|
when '--bind'
|
116
134
|
cliconfig[:bind] = arg
|
117
135
|
when '--config'
|
118
136
|
config[:config] = cliconfig[:config] = arg
|
119
137
|
when '--directory'
|
120
138
|
config[:directory] = arg
|
139
|
+
when '--debug'
|
140
|
+
cliconfig[:debug] = true
|
121
141
|
when '--fork'
|
122
142
|
cliconfig[:fork] = arg.to_i
|
143
|
+
when '--handler'
|
144
|
+
cliconfig[:handler] = arg
|
123
145
|
when '--killtime'
|
124
146
|
cliconfig[:killtime] = arg.to_i
|
125
147
|
when '--logfile'
|
@@ -130,8 +152,6 @@ class Style
|
|
130
152
|
cliconfig[:port] = arg.to_i
|
131
153
|
when '--pidfile'
|
132
154
|
cliconfig[:pidfile] = arg
|
133
|
-
when '--style'
|
134
|
-
cliconfig[:style] = arg
|
135
155
|
when '--unsupervised'
|
136
156
|
cliconfig[:unsupervised] = true
|
137
157
|
end
|
@@ -144,24 +164,24 @@ class Style
|
|
144
164
|
config[:config] = File.expand_path(config[:config])
|
145
165
|
reload_config
|
146
166
|
|
147
|
-
[:
|
148
|
-
|
149
|
-
|
150
|
-
|
167
|
+
unless config[:debug]
|
168
|
+
[:logfile, :pidfile].each do |opt|
|
169
|
+
cliconfig[opt] = File.expand_path(cliconfig[opt]) if cliconfig[opt]
|
170
|
+
config[opt] = File.expand_path(config[opt])
|
171
|
+
config[opt] = check_dir(config[opt])
|
172
|
+
end
|
151
173
|
end
|
152
|
-
exit_with_error("#{config[:style]} is not a valid style!") unless VALID_STYLE_RE.match(config[:style])
|
153
|
-
end
|
154
|
-
|
155
|
-
# Print the error message and the usage, then exit
|
156
|
-
def exit_with_error(error_message)
|
157
|
-
puts error_message
|
158
|
-
puts usage
|
159
|
-
exit(1)
|
160
174
|
end
|
161
175
|
|
162
176
|
# Process the command given
|
163
177
|
def process(command)
|
164
|
-
config[:
|
178
|
+
if config[:debug]
|
179
|
+
run_in_foreground
|
180
|
+
elsif config[:unsupervised]
|
181
|
+
process_unsupervised_command(command)
|
182
|
+
else
|
183
|
+
process_supervised_command(command)
|
184
|
+
end
|
165
185
|
end
|
166
186
|
|
167
187
|
# Process the command given in supervised mode. All commands except start just send
|
@@ -220,7 +240,8 @@ class Style
|
|
220
240
|
end
|
221
241
|
|
222
242
|
# Reload the configuration, used when restarting. Only the following options
|
223
|
-
# take effect when reloading: config, killtime, pidfile,
|
243
|
+
# take effect when reloading: config, killtime, pidfile, adapter, handler,
|
244
|
+
# and adapter_config.
|
224
245
|
def reload_config
|
225
246
|
config.merge!(config_file_options(config[:config]))
|
226
247
|
config.merge!(config[:cliconfig])
|
@@ -241,6 +262,21 @@ class Style
|
|
241
262
|
end rescue nil
|
242
263
|
end
|
243
264
|
|
265
|
+
# Load the relevant handler and adapter and run the server
|
266
|
+
def run_child
|
267
|
+
load_handler
|
268
|
+
load_adapter
|
269
|
+
run
|
270
|
+
end
|
271
|
+
|
272
|
+
# Run the program in the foreground instead of daemonizing. Only runs on one
|
273
|
+
# port, and obviously doesn't fork.
|
274
|
+
def run_in_foreground
|
275
|
+
$STYLE_SOCKET = create_socket(config[:bind], config[:port])
|
276
|
+
config[:sockets][$STYLE_SOCKET] = config[:port]
|
277
|
+
run_child
|
278
|
+
end
|
279
|
+
|
244
280
|
# Setup the necessary signals used in supervisory mode:
|
245
281
|
#
|
246
282
|
# * CLD - Restart any dead children
|
@@ -318,10 +354,11 @@ class Style
|
|
318
354
|
def start_child(socket)
|
319
355
|
return if config[:shutdown]
|
320
356
|
pid = fork do
|
357
|
+
$STYLE_SOCKET = socket
|
321
358
|
[:HUP, :INT, :TERM, :USR1, :USR2].each{|signal| trap(signal, 'DEFAULT')}
|
322
359
|
config[:sockets].keys.each{|sock| sock.close unless sock == socket}
|
323
|
-
$0 = "#{
|
324
|
-
|
360
|
+
$0 = "#{process_name} port:#{config[:sockets][socket]}"
|
361
|
+
run_child
|
325
362
|
end
|
326
363
|
#puts "started pid #{pid}"
|
327
364
|
config[:children][pid] = socket
|
@@ -334,7 +371,7 @@ class Style
|
|
334
371
|
redirect_io
|
335
372
|
config[:number].times do |i|
|
336
373
|
port = config[:port]+i
|
337
|
-
socket =
|
374
|
+
socket = create_socket(config[:bind], port)
|
338
375
|
config[:sockets][socket] = port
|
339
376
|
config[:fork].times{start_child(socket)}
|
340
377
|
end
|
@@ -354,11 +391,17 @@ class Style
|
|
354
391
|
end
|
355
392
|
end
|
356
393
|
|
394
|
+
# Name of the Style
|
395
|
+
def process_name
|
396
|
+
"style-#{config[:adapter]}-#{config[:handler]} #{Dir.pwd}"
|
397
|
+
end
|
398
|
+
|
399
|
+
|
357
400
|
# Start all necessary children of the supervisor process (number * fork)
|
358
401
|
def supervisor_children_start
|
359
402
|
config[:number].times do |i|
|
360
403
|
port = config[:port]+i
|
361
|
-
socket =
|
404
|
+
socket = create_socket(config[:bind], port)
|
362
405
|
config[:sockets][socket] = port
|
363
406
|
config[:fork].times{start_child(socket)}
|
364
407
|
end
|
@@ -372,7 +415,7 @@ class Style
|
|
372
415
|
|
373
416
|
# Do the final setup of the supervisor process, and then loop indefinitely
|
374
417
|
def supervisor_loop
|
375
|
-
$0 = "#{
|
418
|
+
$0 = "#{process_name} supervisor"
|
376
419
|
redirect_io
|
377
420
|
supervisor_children_start
|
378
421
|
setup_supervisor_signals
|
@@ -407,16 +450,18 @@ class Style
|
|
407
450
|
<<-END
|
408
451
|
style [option value, ...] (decrement|halt|increment|restart|start|stop)
|
409
452
|
Options:
|
453
|
+
-a, --adapter Adapter/Framework to use [rails]
|
410
454
|
-b, --bind IP address to bind to [127.0.0.1]
|
411
455
|
-c, --config Location of config file [config/style.yaml]
|
412
456
|
-d, --directory Working directory [.]
|
457
|
+
-D, --debug Run the program in the foreground without forking [No]
|
413
458
|
-f, --fork Number of listners on each port [1]
|
459
|
+
-h, --handler Handler/Server to use [mongrel]
|
414
460
|
-k, --killtime Number of seconds to wait when killing each child [2]
|
415
461
|
-l, --logfile Where to redirect STDOUT and STDERR [log/style.log]
|
416
462
|
-n, --number Number of ports to which to bind [1]
|
417
463
|
-p, --port Starting port to which to bind [9999]
|
418
464
|
-P, --pidfile Location of pid file [log/style.pid]
|
419
|
-
-s, --style Type of style to use [RailsMongrel]
|
420
465
|
-u, --unsupervised Whether to run unsupervised [No]
|
421
466
|
END
|
422
467
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: ruby-style
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.0
|
7
|
-
date: 2008-01-
|
6
|
+
version: 1.1.0
|
7
|
+
date: 2008-01-27 00:00:00 -08:00
|
8
8
|
summary: Supervised TCPServer, Yielding Listeners Easily
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -32,8 +32,12 @@ files:
|
|
32
32
|
- LICENSE
|
33
33
|
- README
|
34
34
|
- lib/style.rb
|
35
|
-
- lib/
|
36
|
-
- lib/
|
35
|
+
- lib/style/handler/mongrel.rb
|
36
|
+
- lib/style/handler/scgi.rb
|
37
|
+
- lib/style/handler/eventmachine.rb
|
38
|
+
- lib/style/handler/evented_mongrel.rb
|
39
|
+
- lib/style/adapter/ramaze.rb
|
40
|
+
- lib/style/adapter/rails.rb
|
37
41
|
test_files: []
|
38
42
|
|
39
43
|
rdoc_options:
|
data/lib/RailsMongrelStyle.rb
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'yaml'
|
3
|
-
require 'mongrel'
|
4
|
-
require 'mongrel/rails'
|
5
|
-
require 'etc'
|
6
|
-
require 'cgi_multipart_eof_fix' rescue nil
|
7
|
-
|
8
|
-
module Mongrel
|
9
|
-
# Patch the Mongrel HttpServer to add a socket= method
|
10
|
-
class HttpServer
|
11
|
-
attr_writer :socket
|
12
|
-
|
13
|
-
# Keep the interface the same, but ignore the host and port and don't
|
14
|
-
# create a socket (one will be provided later)
|
15
|
-
def initialize(host, port, num_processors=950, throttle=0, timeout=60)
|
16
|
-
tries = 0
|
17
|
-
@classifier = URIClassifier.new
|
18
|
-
@host = host
|
19
|
-
@port = port
|
20
|
-
@workers = ThreadGroup.new
|
21
|
-
@throttle = throttle
|
22
|
-
@num_processors = num_processors
|
23
|
-
@timeout = timeout
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# This hooks the HTTP request into Ruby on Rails and Mongrel.
|
29
|
-
class RailsMongrelStyle
|
30
|
-
attr_reader :mongrel
|
31
|
-
|
32
|
-
# Initialzes Rails and Mongrel with the appropriate environment and settings.
|
33
|
-
def initialize(settings)
|
34
|
-
settings = {:cwd => Dir.pwd, :log_file => 'log/rails-mongrel.log',
|
35
|
-
:environment => 'production', :docroot => 'public',
|
36
|
-
:mime_map => nil, :debug => false, :includes => ["mongrel"],
|
37
|
-
:config_script => nil, :num_processors => 1024, :timeout => 0,
|
38
|
-
:user => nil, :group => nil, :prefix => nil}.merge(settings)
|
39
|
-
ENV['RAILS_ENV'] = settings[:environment]
|
40
|
-
$0 += " environment:#{ENV['RAILS_ENV']}"
|
41
|
-
@mongrel = Mongrel::Rails::RailsConfigurator.new(settings) do
|
42
|
-
listener do
|
43
|
-
mime = defaults[:mime_map] ? load_mime_map(defaults[:mime_map], mime) : {}
|
44
|
-
debug "/" if defaults[:debug]
|
45
|
-
uri defaults[:prefix] || "/", :handler => rails(:mime => mime, :prefix => defaults[:prefix])
|
46
|
-
load_plugins
|
47
|
-
run_config(defaults[:config_script]) if defaults[:config_script]
|
48
|
-
setup_rails_signals
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# Set the HttpServer to the correct socket and start running the mongrel event loop.
|
54
|
-
def listen(socket)
|
55
|
-
mongrel.instance_variable_get('@rails_handler').instance_variable_get('@listener').socket = socket
|
56
|
-
mongrel.run
|
57
|
-
mongrel.join
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
GemPlugin::Manager.instance.load "mongrel" => GemPlugin::INCLUDE, "rails" => GemPlugin::EXCLUDE
|