mongrel 0.3.6 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +28 -1
- data/Rakefile +2 -2
- data/bin/mongrel_rails +102 -65
- data/bin/mongrel_rails_service +16 -7
- data/bin/mongrel_rails_svc +184 -87
- data/doc/rdoc/classes/Mongrel.html +1 -0
- data/doc/rdoc/classes/Mongrel/Const.html +3 -3
- data/doc/rdoc/classes/Mongrel/HeaderOut.html +10 -10
- data/doc/rdoc/classes/Mongrel/HeaderOut.src/{M000028.html → M000014.html} +4 -4
- data/doc/rdoc/classes/Mongrel/HeaderOut.src/{M000029.html → M000015.html} +7 -7
- data/doc/rdoc/classes/Mongrel/HttpParser.html +35 -35
- data/doc/rdoc/classes/Mongrel/HttpParser.src/{M000015.html → M000001.html} +0 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/{M000016.html → M000002.html} +0 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/{M000017.html → M000003.html} +0 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/{M000018.html → M000004.html} +0 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/{M000019.html → M000005.html} +0 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/{M000020.html → M000006.html} +0 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/{M000021.html → M000007.html} +0 -0
- data/doc/rdoc/classes/Mongrel/HttpRequest.html +5 -5
- data/doc/rdoc/classes/Mongrel/HttpRequest.src/{M000041.html → M000029.html} +25 -25
- data/doc/rdoc/classes/Mongrel/HttpResponse.html +36 -36
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000034.html → M000016.html} +7 -7
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000035.html → M000017.html} +6 -6
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000036.html → M000018.html} +5 -5
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000037.html → M000019.html} +5 -5
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000038.html → M000020.html} +6 -6
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000039.html → M000021.html} +6 -6
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000040.html → M000022.html} +6 -6
- data/doc/rdoc/classes/Mongrel/HttpServer.html +34 -35
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000008.html +36 -0
- data/doc/rdoc/classes/Mongrel/HttpServer.src/{M000023.html → M000009.html} +43 -43
- data/doc/rdoc/classes/Mongrel/HttpServer.src/{M000024.html → M000010.html} +31 -31
- data/doc/rdoc/classes/Mongrel/HttpServer.src/{M000025.html → M000011.html} +4 -4
- data/doc/rdoc/classes/Mongrel/HttpServer.src/{M000026.html → M000012.html} +4 -4
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000013.html +23 -0
- data/doc/rdoc/classes/{FactoryError.html → Mongrel/TimeoutWorker.html} +7 -34
- data/doc/rdoc/classes/Mongrel/URIClassifier.html +63 -20
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000023.html +18 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000024.html +18 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000030.html → M000025.html} +0 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000031.html → M000026.html} +0 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000032.html → M000027.html} +0 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000033.html → M000028.html} +0 -0
- data/doc/rdoc/created.rid +1 -1
- data/doc/rdoc/files/README.html +35 -2
- data/doc/rdoc/files/lib/mongrel_rb.html +4 -1
- data/doc/rdoc/fr_class_index.html +1 -2
- data/doc/rdoc/fr_file_index.html +0 -1
- data/doc/rdoc/fr_method_index.html +29 -41
- data/lib/mongrel.rb +37 -9
- data/lib/mongrel/command.rb +13 -34
- data/lib/mongrel/plugins.rb +156 -0
- data/lib/mongrel/rails.rb +70 -0
- data/test/plugins/commands/test1.rb +19 -0
- data/test/test_plugins.rb +45 -0
- data/test/test_uriclassifier.rb +5 -1
- metadata +38 -49
- data/doc/rdoc/classes/FactoryError.src/M000001.html +0 -23
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000022.html +0 -33
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000027.html +0 -19
- data/doc/rdoc/classes/PluginFactory.html +0 -409
- data/doc/rdoc/classes/PluginFactory.src/M000002.html +0 -18
- data/doc/rdoc/classes/PluginFactory.src/M000003.html +0 -18
- data/doc/rdoc/classes/PluginFactory.src/M000004.html +0 -22
- data/doc/rdoc/classes/PluginFactory.src/M000005.html +0 -22
- data/doc/rdoc/classes/PluginFactory.src/M000006.html +0 -33
- data/doc/rdoc/classes/PluginFactory.src/M000007.html +0 -32
- data/doc/rdoc/classes/PluginFactory.src/M000008.html +0 -18
- data/doc/rdoc/classes/PluginFactory.src/M000009.html +0 -24
- data/doc/rdoc/classes/PluginFactory.src/M000010.html +0 -40
- data/doc/rdoc/classes/PluginFactory.src/M000011.html +0 -39
- data/doc/rdoc/classes/PluginFactory.src/M000012.html +0 -24
- data/doc/rdoc/classes/PluginFactory.src/M000013.html +0 -70
- data/doc/rdoc/classes/PluginFactory.src/M000014.html +0 -34
- data/doc/rdoc/files/lib/pluginfactory_rb.html +0 -132
- data/lib/pluginfactory.rb +0 -384
data/README
CHANGED
|
@@ -14,7 +14,8 @@ scream without too many portability issues.
|
|
|
14
14
|
The 0.3.6 release supports Ruby On Rails much better than previously, and also
|
|
15
15
|
sports the beginning of a command and plugin infrastructure. There is now a more
|
|
16
16
|
complete CGIWrapper that handles most of the CGI usage, but still doesn't do the
|
|
17
|
-
MIME decoding or file upload/send (it leaves that to CGI).
|
|
17
|
+
MIME decoding or file upload/send (it leaves that to CGI). Finally, there's a
|
|
18
|
+
great mongrel_rails_service script for running under Win32 as a service.
|
|
18
19
|
|
|
19
20
|
After you've installed (either with gem install mongrel or via source) you should
|
|
20
21
|
have the mongrel_rails command available in your PATH. Then you just do the following:
|
|
@@ -42,6 +43,32 @@ There are also many more new options for configuring the rails runner including
|
|
|
42
43
|
changing to a different directory, adding more MIME types, and setting processor
|
|
43
44
|
threads and timeouts.
|
|
44
45
|
|
|
46
|
+
|
|
47
|
+
=== Win32 Service Support
|
|
48
|
+
|
|
49
|
+
Mongrel now has support for running as a Win32 service right out of the
|
|
50
|
+
box. The support is still rough but works well enough that we decided
|
|
51
|
+
to release it. You can thank Luis Lavena for working on this and making
|
|
52
|
+
it so nice.
|
|
53
|
+
|
|
54
|
+
After you do the gem install, find a Rails application you want to run
|
|
55
|
+
and do:
|
|
56
|
+
|
|
57
|
+
$ mongrel_rails_service install -n myapp \
|
|
58
|
+
-r c:\my\path\to\myapp -p 4000 -e production
|
|
59
|
+
$ mongrel_rails_service start -n myapp
|
|
60
|
+
|
|
61
|
+
Now hit the port and poof, works. *Stopping the service is a little problematic right now.*
|
|
62
|
+
|
|
63
|
+
If you run into an app that's not running right, my suggestion is to run it with
|
|
64
|
+
the regular mongrel_rails runner:
|
|
65
|
+
|
|
66
|
+
$ cd c:\my\path\to\myapp
|
|
67
|
+
$ mongrel_rails start -p 4500
|
|
68
|
+
|
|
69
|
+
Since that will spit out error messages and stuff to the console. *Use CTRL-Pause/Break to stop.*
|
|
70
|
+
|
|
71
|
+
|
|
45
72
|
== Install
|
|
46
73
|
|
|
47
74
|
It doesn't explicitly require Camping, but if you want to run the examples/camping/
|
data/Rakefile
CHANGED
|
@@ -30,7 +30,7 @@ end
|
|
|
30
30
|
|
|
31
31
|
setup_extension("http11", "http11")
|
|
32
32
|
|
|
33
|
-
version="0.3.
|
|
33
|
+
version="0.3.7"
|
|
34
34
|
summary = "A small fast HTTP library and server that runs Rails, Camping, and Nitro apps."
|
|
35
35
|
test_file = "test/test_ws.rb"
|
|
36
36
|
author="Zed A. Shaw"
|
|
@@ -44,7 +44,7 @@ end
|
|
|
44
44
|
desc "Build a binary gem for Win32"
|
|
45
45
|
task :win32_gem => [:clean, :compile, :test, :rerdoc, :package_win32]
|
|
46
46
|
|
|
47
|
-
scripts_win32 = scripts + ['mongrel_rails_service'
|
|
47
|
+
scripts_win32 = scripts + ['mongrel_rails_service']
|
|
48
48
|
task :package_win32 do
|
|
49
49
|
setup_win32_gem(name, version, version, summary, scripts_win32, test_file) do |spec|
|
|
50
50
|
spec.add_dependency('win32-service', '>= 0.5.0')
|
data/bin/mongrel_rails
CHANGED
|
@@ -1,61 +1,24 @@
|
|
|
1
1
|
require 'rubygems'
|
|
2
|
-
require 'mongrel'
|
|
3
|
-
require 'mongrel/command'
|
|
2
|
+
require 'mongrel/rails'
|
|
4
3
|
|
|
5
4
|
|
|
6
|
-
class
|
|
7
|
-
|
|
8
|
-
def initialize(dir, mime_map = {})
|
|
9
|
-
@files = Mongrel::DirHandler.new(dir,false)
|
|
10
|
-
@guard = Mutex.new
|
|
11
|
-
|
|
12
|
-
# register the requested mime types
|
|
13
|
-
mime_map.each {|k,v| Mongrel::DirHandler::add_mime_type(k,v) }
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def process(request, response)
|
|
17
|
-
# not static, need to talk to rails
|
|
18
|
-
return if response.socket.closed?
|
|
19
|
-
|
|
20
|
-
if @files.can_serve(request.params["PATH_INFO"])
|
|
21
|
-
@files.process(request,response)
|
|
22
|
-
else
|
|
23
|
-
cgi = Mongrel::CGIWrapper.new(request, response)
|
|
24
|
-
|
|
25
|
-
begin
|
|
26
|
-
@guard.synchronize do
|
|
27
|
-
# Rails is not thread safe so must be run entirely within synchronize
|
|
28
|
-
Dispatcher.dispatch(cgi, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, response.body)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# This finalizes the output using the proper HttpResponse way
|
|
32
|
-
cgi.out {""}
|
|
33
|
-
rescue Object => rails_error
|
|
34
|
-
STDERR.puts "calling Dispatcher.dispatch #{rails_error}"
|
|
35
|
-
STDERR.puts rails_error.backtrace.join("\n")
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
class StartCommand < Mongrel::Command::Command
|
|
5
|
+
class Start < Mongrel::Plugin "/commands"
|
|
6
|
+
include Mongrel::Command::Base
|
|
45
7
|
|
|
46
8
|
def configure
|
|
47
9
|
options [
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
10
|
+
["-e", "--environment ENV", "Rails environment to run as", :@environment, ENV['RAILS_ENV'] || "development"],
|
|
11
|
+
["-d", "--daemonize", "Whether to run in the background or not", :@daemon, false],
|
|
12
|
+
['-p', '--port PORT', "Which port to bind to", :@port, 3000],
|
|
13
|
+
['-a', '--address ADDR', "Address to bind to", :@address, "0.0.0.0"],
|
|
14
|
+
['-l', '--log FILE', "Where to write log messages", :@log_file, "log/mongrel.log"],
|
|
15
|
+
['-P', '--pid FILE', "Where to write the PID", :@pid_file, "log/mongrel.pid"],
|
|
16
|
+
['-n', '--num-procs INT', "Number of processor threads to use", :@num_procs, 20],
|
|
17
|
+
['-t', '--timeout SECONDS', "Timeout all requests after SECONDS time", :@timeout, 120],
|
|
18
|
+
['-m', '--mime PATH', "A YAML file that lists additional MIME types", :@mime_map, nil],
|
|
19
|
+
['-c', '--chdir PATH', "Change to dir before starting (will be expanded)", :@cwd, Dir.pwd],
|
|
20
|
+
['-r', '--root PATH', "Set the document root (default 'public')", :@docroot, "public"],
|
|
21
|
+
['-L', '--load PATH', "Loads plugins from the given directory", :@load_from, nil],
|
|
59
22
|
]
|
|
60
23
|
end
|
|
61
24
|
|
|
@@ -71,9 +34,12 @@ class StartCommand < Mongrel::Command::Command
|
|
|
71
34
|
valid_dir? @docroot, "Path to docroot not valid: #@docroot"
|
|
72
35
|
valid_exists? @mime_map, "MIME mapping file does not exist: #@mime_map" if @mime_map
|
|
73
36
|
|
|
37
|
+
valid_dir? @load_from, "Plugin directory path does not exist" if @load_from
|
|
38
|
+
|
|
74
39
|
return @valid
|
|
75
40
|
end
|
|
76
41
|
|
|
42
|
+
|
|
77
43
|
def daemonize
|
|
78
44
|
# save this for later since daemonize will hose it
|
|
79
45
|
if @daemon and RUBY_PLATFORM !~ /mswin/
|
|
@@ -117,22 +83,47 @@ class StartCommand < Mongrel::Command::Command
|
|
|
117
83
|
end
|
|
118
84
|
|
|
119
85
|
def start_mongrel(rails)
|
|
120
|
-
|
|
86
|
+
@restart = false
|
|
87
|
+
|
|
121
88
|
server = Mongrel::HttpServer.new(@address, @port, @num_procs.to_i, @timeout.to_i)
|
|
122
89
|
server.register("/", rails)
|
|
123
90
|
server.run
|
|
124
|
-
|
|
91
|
+
|
|
92
|
+
# signal trapping just applies to posix systems
|
|
93
|
+
# TERM is a valid signal, but still doesn't gracefuly shutdown on win32.
|
|
94
|
+
if RUBY_PLATFORM !~ /mswin/
|
|
95
|
+
# graceful shutdown
|
|
96
|
+
trap("TERM") {
|
|
97
|
+
server.stop
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# rails reload
|
|
101
|
+
trap("HUP") {
|
|
102
|
+
server.stop
|
|
103
|
+
@restart = true
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
# restart
|
|
107
|
+
trap("USR2") {
|
|
108
|
+
server.stop
|
|
109
|
+
@restart = true
|
|
110
|
+
}
|
|
111
|
+
end
|
|
125
112
|
|
|
126
113
|
begin
|
|
127
|
-
puts "Server ready."
|
|
114
|
+
STDERR.puts "Server ready."
|
|
128
115
|
server.acceptor.join
|
|
129
116
|
rescue Interrupt
|
|
130
|
-
puts "Interrupted."
|
|
117
|
+
STDERR.puts "Interrupted."
|
|
131
118
|
raise
|
|
132
119
|
end
|
|
120
|
+
|
|
121
|
+
# daemonize makes restart easy
|
|
122
|
+
run if @restart
|
|
133
123
|
end
|
|
134
124
|
|
|
135
125
|
def run
|
|
126
|
+
Mongrel::PluginManager.instance.load(@load_from) if @load_from
|
|
136
127
|
daemonize
|
|
137
128
|
rails = configure_rails
|
|
138
129
|
start_mongrel(rails)
|
|
@@ -140,12 +131,26 @@ class StartCommand < Mongrel::Command::Command
|
|
|
140
131
|
end
|
|
141
132
|
|
|
142
133
|
|
|
134
|
+
def send_signal(signal, pid_file)
|
|
135
|
+
pid = open(pid_file).read.to_i
|
|
136
|
+
print "Sending #{signal} to Mongrel at PID #{pid}..."
|
|
137
|
+
begin
|
|
138
|
+
Process.kill(signal, pid)
|
|
139
|
+
rescue Errno::ESRCH
|
|
140
|
+
puts "Process does not exist. Not running."
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
puts "Done."
|
|
144
|
+
end
|
|
145
|
+
|
|
143
146
|
|
|
144
|
-
class
|
|
147
|
+
class Stop < Mongrel::Plugin "/commands"
|
|
148
|
+
include Mongrel::Command::Base
|
|
145
149
|
|
|
146
150
|
def configure
|
|
147
|
-
options [
|
|
151
|
+
options [
|
|
148
152
|
['-c', '--chdir PATH', "Change to dir before starting (will be expanded)", :@cwd, Dir.pwd],
|
|
153
|
+
['-f', '--force', "Force the shutdown.", :@force, false],
|
|
149
154
|
['-P', '--pid FILE', "Where to write the PID", :@pid_file, "log/mongrel.pid"]
|
|
150
155
|
]
|
|
151
156
|
end
|
|
@@ -162,16 +167,48 @@ class StopCommand < Mongrel::Command::Command
|
|
|
162
167
|
|
|
163
168
|
|
|
164
169
|
def run
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
170
|
+
if @force
|
|
171
|
+
send_signal("KILL", @pid_file)
|
|
172
|
+
else
|
|
173
|
+
send_signal("TERM", @pid_file)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
File.unlink(@pid_file)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
class Restart < Mongrel::Plugin "/commands"
|
|
183
|
+
include Mongrel::Command::Base
|
|
184
|
+
|
|
185
|
+
def configure
|
|
186
|
+
options [
|
|
187
|
+
['-c', '--chdir PATH', "Change to dir before starting (will be expanded)", :@cwd, Dir.pwd],
|
|
188
|
+
['-s', '--soft', "Do a soft restart rather than a process exit restart", :@soft, false],
|
|
189
|
+
['-P', '--pid FILE', "Where to write the PID", :@pid_file, "log/mongrel.pid"]
|
|
190
|
+
]
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def validate
|
|
194
|
+
@cwd = File.expand_path(@cwd)
|
|
195
|
+
valid_dir? @cwd, "Invalid path to change to during daemon mode: #@cwd"
|
|
196
|
+
|
|
197
|
+
@pid_file = File.join(@cwd,@pid_file)
|
|
198
|
+
valid_exists? @pid_file, "PID file #@pid_file does not exist. Not running?"
|
|
199
|
+
|
|
200
|
+
return @valid
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def run
|
|
205
|
+
if @soft
|
|
206
|
+
send_signal("HUP", @pid_file)
|
|
207
|
+
else
|
|
208
|
+
send_signal("USR2", @pid_file)
|
|
171
209
|
end
|
|
172
210
|
|
|
173
211
|
File.unlink(@pid_file)
|
|
174
|
-
puts "Done."
|
|
175
212
|
end
|
|
176
213
|
end
|
|
177
214
|
|
data/bin/mongrel_rails_service
CHANGED
|
@@ -7,8 +7,6 @@
|
|
|
7
7
|
###############################################
|
|
8
8
|
require 'rubygems'
|
|
9
9
|
require 'mongrel'
|
|
10
|
-
require 'mongrel/command'
|
|
11
|
-
|
|
12
10
|
require 'win32/service'
|
|
13
11
|
include Win32
|
|
14
12
|
|
|
@@ -32,7 +30,8 @@ module GenericCommand
|
|
|
32
30
|
end
|
|
33
31
|
end
|
|
34
32
|
|
|
35
|
-
class
|
|
33
|
+
class Install < Mongrel::Plugin "/commands"
|
|
34
|
+
include Mongrel::Command::Base
|
|
36
35
|
|
|
37
36
|
# Default every option to nil so only the defined ones get passed to service
|
|
38
37
|
# (which will override ServiceCommand defaults).
|
|
@@ -41,12 +40,13 @@ class InstallCommand < Mongrel::Command::Command
|
|
|
41
40
|
['-n', '--name SVC_NAME', "Required name for the service to be registered/installed.", :@svc_name, nil],
|
|
42
41
|
['-d', '--display SVC_DISPLAY', "Adjust the display name of the service.", :@svc_display, nil],
|
|
43
42
|
['-r', '--root PATH', "Set the root path where your rails app resides.", :@rails_root, Dir.pwd],
|
|
44
|
-
['-e', '--environment ENV', "Rails environment to run as", :@environment, 'production'],
|
|
43
|
+
['-e', '--environment ENV', "Rails environment to run as. (default: production)", :@environment, 'production'],
|
|
45
44
|
['-b', '--binding ADDR', "Address to bind to", :@ip, nil],
|
|
46
45
|
['-p', '--port PORT', "Which port to bind to", :@port, 3000],
|
|
47
46
|
['-m', '--mime PATH', "A YAML file that lists additional MIME types", :@mime_map, nil],
|
|
48
47
|
['-P', '--num-procs INT', "Number of processor threads to use", :@num_procs, nil],
|
|
49
48
|
['-t', '--timeout SECONDS', "Timeout all requests after SECONDS time", :@timeout, nil],
|
|
49
|
+
['-c', '--cpu CPU', "Bind the process to specific cpu, starting from 1.", :@cpu, nil]
|
|
50
50
|
]
|
|
51
51
|
end
|
|
52
52
|
|
|
@@ -70,6 +70,9 @@ class InstallCommand < Mongrel::Command::Command
|
|
|
70
70
|
valid? app_exist == true, "The root of rails app isn't valid, please verify."
|
|
71
71
|
valid_exists? @mime_map, "MIME mapping file does not exist: #@mime_map" if @mime_map
|
|
72
72
|
|
|
73
|
+
# Validate the number of cpu to bind to.
|
|
74
|
+
valid? @cpu.to_i > 0, "You must specify a numeric value for cpu. (1..8)" if @cpu
|
|
75
|
+
|
|
73
76
|
# We should validate service existance here, right Zed?
|
|
74
77
|
begin
|
|
75
78
|
valid? !Service.exists?(@svc_name), "The service already exist, please uninstall it first."
|
|
@@ -112,6 +115,9 @@ class InstallCommand < Mongrel::Command::Command
|
|
|
112
115
|
|
|
113
116
|
# timeout
|
|
114
117
|
@params << "-t #{@timeout.to_i} " if @timeout
|
|
118
|
+
|
|
119
|
+
# cpu
|
|
120
|
+
@params << "-c #{@cpu.to_i} " if @cpu
|
|
115
121
|
end
|
|
116
122
|
|
|
117
123
|
def install_service
|
|
@@ -168,7 +174,8 @@ class InstallCommand < Mongrel::Command::Command
|
|
|
168
174
|
end
|
|
169
175
|
end
|
|
170
176
|
|
|
171
|
-
class
|
|
177
|
+
class Delete < Mongrel::Plugin "/commands"
|
|
178
|
+
include Mongrel::Command::Base
|
|
172
179
|
include GenericCommand
|
|
173
180
|
|
|
174
181
|
def run
|
|
@@ -186,7 +193,8 @@ class DeleteCommand < Mongrel::Command::Command
|
|
|
186
193
|
end
|
|
187
194
|
end
|
|
188
195
|
|
|
189
|
-
class
|
|
196
|
+
class Start < Mongrel::Plugin "/commands"
|
|
197
|
+
include Mongrel::Command::Base
|
|
190
198
|
include GenericCommand
|
|
191
199
|
|
|
192
200
|
def run
|
|
@@ -210,7 +218,8 @@ class StartCommand < Mongrel::Command::Command
|
|
|
210
218
|
end
|
|
211
219
|
end
|
|
212
220
|
|
|
213
|
-
class
|
|
221
|
+
class Stop < Mongrel::Plugin "/commands"
|
|
222
|
+
include Mongrel::Command::Base
|
|
214
223
|
include GenericCommand
|
|
215
224
|
|
|
216
225
|
def run
|
data/bin/mongrel_rails_svc
CHANGED
|
@@ -4,75 +4,57 @@
|
|
|
4
4
|
# This is where Win32::Daemon resides.
|
|
5
5
|
###############################################
|
|
6
6
|
require 'rubygems'
|
|
7
|
-
require 'mongrel'
|
|
8
|
-
|
|
7
|
+
require 'mongrel/rails'
|
|
9
8
|
require 'optparse'
|
|
10
|
-
|
|
11
9
|
require 'win32/service'
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
#
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
@guard = Mutex.new
|
|
25
|
-
|
|
26
|
-
# register the requested mime types
|
|
27
|
-
mime_map.each {|k,v| Mongrel::DirHandler::add_mime_type(k,v) }
|
|
11
|
+
# We need to use OpenProcess and SetProcessAffinityMask on WinNT/2K/XP for
|
|
12
|
+
# binding the process to each cpu.
|
|
13
|
+
# Kernel32 Module Just for Win32 :D
|
|
14
|
+
require 'dl/win32'
|
|
15
|
+
|
|
16
|
+
module Kernel32
|
|
17
|
+
[
|
|
18
|
+
%w/OpenProcess LLL L/,
|
|
19
|
+
%w/SetProcessAffinityMask LL L/,
|
|
20
|
+
].each do |fn|
|
|
21
|
+
const_set fn[0].intern, Win32API.new('kernel32.dll', *fn)
|
|
28
22
|
end
|
|
29
23
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if @files.can_serve(request.params["PATH_INFO"])
|
|
35
|
-
@files.process(request,response)
|
|
36
|
-
else
|
|
37
|
-
cgi = Mongrel::CGIWrapper.new(request, response)
|
|
38
|
-
|
|
39
|
-
begin
|
|
40
|
-
@guard.synchronize do
|
|
41
|
-
# Rails is not thread safe so must be run entirely within synchronize
|
|
42
|
-
Dispatcher.dispatch(cgi, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, response.body)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# This finalizes the output using the proper HttpResponse way
|
|
46
|
-
cgi.out {""}
|
|
47
|
-
rescue Object => rails_error
|
|
48
|
-
STDERR.puts "calling Dispatcher.dispatch #{rails_error}"
|
|
49
|
-
STDERR.puts rails_error.backtrace.join("\n")
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
24
|
+
PROCESS_ALL_ACCESS = 0x1f0fff
|
|
25
|
+
|
|
26
|
+
module_function
|
|
53
27
|
|
|
28
|
+
def set_affinity(pid, cpu)
|
|
29
|
+
handle = OpenProcess.call(PROCESS_ALL_ACCESS, 0, pid)
|
|
30
|
+
|
|
31
|
+
# CPU mask is a bit weird, hehehe :)
|
|
32
|
+
# default mask for CPU 1
|
|
33
|
+
mask = 1
|
|
34
|
+
mask = %w{1 2 4 8 16 32 64 128}[cpu.to_i - 1] if cpu.to_i.between?(1, 8)
|
|
35
|
+
|
|
36
|
+
SetProcessAffinityMask.call(handle, mask.to_i)
|
|
37
|
+
end
|
|
54
38
|
end
|
|
39
|
+
# End Kernel32 Module
|
|
55
40
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
else
|
|
66
|
-
# no gzip supported, send it back normal
|
|
67
|
-
out << results
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|
|
41
|
+
DEBUG_LOG_FILE = File.expand_path(File.dirname(__FILE__) + '/debug.log')
|
|
42
|
+
DEBUG_THREAD_LOG_FILE = File.expand_path(File.dirname(__FILE__) + '/debug_thread.log')
|
|
43
|
+
|
|
44
|
+
def dbg(msg)
|
|
45
|
+
File.open(DEBUG_LOG_FILE,"a+") { |f| f.puts("#{Time.now} - #{msg}") }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def dbg_th(msg)
|
|
49
|
+
File.open(DEBUG_THREAD_LOG_FILE,"a+") { |f| f.puts("#{Time.now} - #{msg}") }
|
|
71
50
|
end
|
|
72
51
|
|
|
73
|
-
class
|
|
52
|
+
# This class encapsulate the handler registering, http_server and working thread
|
|
53
|
+
# Is standalone, so using MongrelRails in your app get everything runnig
|
|
54
|
+
# (in case you don't want use mongrel_rails script)
|
|
55
|
+
class MongrelRails
|
|
74
56
|
def initialize(ip, port, rails_root, docroot, environment, mime_map, num_procs, timeout)
|
|
75
|
-
|
|
57
|
+
dbg "mongrelrails_initialize entered"
|
|
76
58
|
|
|
77
59
|
@ip = ip
|
|
78
60
|
@port = port
|
|
@@ -83,11 +65,23 @@ class RailsDaemon < Win32::Daemon
|
|
|
83
65
|
@num_procs = num_procs
|
|
84
66
|
@timeout = timeout
|
|
85
67
|
|
|
86
|
-
|
|
68
|
+
dbg "mongrelrails_initialize left"
|
|
87
69
|
end
|
|
70
|
+
|
|
71
|
+
def delayed_initialize
|
|
72
|
+
dbg "delayed_initialize entered"
|
|
73
|
+
|
|
74
|
+
@rails = configure_rails
|
|
75
|
+
|
|
76
|
+
# start up mongrel with the right configurations
|
|
77
|
+
@server = Mongrel::HttpServer.new(@ip, @port, @num_procs.to_i, @timeout.to_i)
|
|
78
|
+
@server.register("/", @rails)
|
|
88
79
|
|
|
80
|
+
dbg "delayed_initialize left"
|
|
81
|
+
end
|
|
82
|
+
|
|
89
83
|
def load_mime_map
|
|
90
|
-
|
|
84
|
+
dbg "load_mime_map entered"
|
|
91
85
|
|
|
92
86
|
mime = {}
|
|
93
87
|
|
|
@@ -100,13 +94,13 @@ class RailsDaemon < Win32::Daemon
|
|
|
100
94
|
mime.each {|k,v| puts "WARNING: MIME type #{k} must start with '.'" if k.index(".") != 0 }
|
|
101
95
|
end
|
|
102
96
|
|
|
103
|
-
|
|
97
|
+
dbg "load_mime_map left"
|
|
104
98
|
|
|
105
99
|
return mime
|
|
106
100
|
end
|
|
107
101
|
|
|
108
102
|
def configure_rails
|
|
109
|
-
|
|
103
|
+
dbg "configure_rails entered"
|
|
110
104
|
|
|
111
105
|
Dir.chdir(@rails_root)
|
|
112
106
|
|
|
@@ -116,45 +110,85 @@ class RailsDaemon < Win32::Daemon
|
|
|
116
110
|
# configure the rails handler
|
|
117
111
|
rails = RailsHandler.new(@docroot, load_mime_map)
|
|
118
112
|
|
|
119
|
-
|
|
113
|
+
dbg "configure_rails left"
|
|
120
114
|
|
|
121
115
|
return rails
|
|
122
116
|
end
|
|
123
117
|
|
|
124
|
-
def
|
|
125
|
-
|
|
118
|
+
def start_serve
|
|
119
|
+
dbg "start_serve entered"
|
|
126
120
|
|
|
127
|
-
@
|
|
128
|
-
|
|
121
|
+
@runner = Thread.new do
|
|
122
|
+
dbg_th "runner_thread suspended"
|
|
123
|
+
Thread.stop
|
|
124
|
+
|
|
125
|
+
dbg_th "runner_thread resumed"
|
|
126
|
+
dbg_th "runner_thread acceptor.join"
|
|
127
|
+
@server.acceptor.join
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
dbg "server.run"
|
|
131
|
+
@server.run
|
|
132
|
+
|
|
133
|
+
dbg "runner.run"
|
|
134
|
+
@runner.run
|
|
129
135
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
136
|
+
dbg "start_serve left"
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def stop_serve
|
|
140
|
+
dbg "stop_serve entered"
|
|
141
|
+
|
|
142
|
+
if @runner.alive?
|
|
143
|
+
dbg "killing thread"
|
|
144
|
+
@runner.kill
|
|
145
|
+
end
|
|
133
146
|
|
|
134
|
-
|
|
147
|
+
@server.stop
|
|
148
|
+
|
|
149
|
+
dbg "stop_serve left"
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
class RailsDaemon < Win32::Daemon
|
|
154
|
+
def initialize(rails)
|
|
155
|
+
dbg "daemon_initialize entered"
|
|
156
|
+
|
|
157
|
+
@rails = rails
|
|
158
|
+
|
|
159
|
+
dbg "daemon_initialize left"
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def service_init
|
|
163
|
+
dbg "service_init entered"
|
|
164
|
+
|
|
165
|
+
@rails.delayed_initialize
|
|
166
|
+
|
|
167
|
+
dbg "service_init left"
|
|
135
168
|
end
|
|
136
169
|
|
|
137
170
|
def service_main
|
|
138
|
-
|
|
171
|
+
dbg "service_main entered"
|
|
139
172
|
|
|
140
|
-
|
|
141
|
-
@
|
|
173
|
+
dbg "rails.start_serve"
|
|
174
|
+
@rails.start_serve
|
|
142
175
|
|
|
143
|
-
|
|
176
|
+
dbg "while RUNNING"
|
|
144
177
|
while state == RUNNING
|
|
145
178
|
sleep 1
|
|
146
179
|
end
|
|
180
|
+
dbg "state !RUNNING"
|
|
147
181
|
|
|
148
|
-
|
|
182
|
+
dbg "rails.stop_serve"
|
|
183
|
+
@rails.stop_serve
|
|
184
|
+
|
|
185
|
+
dbg "service_main left"
|
|
149
186
|
end
|
|
150
187
|
|
|
151
188
|
def service_stop
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
#@server.stop
|
|
156
|
-
|
|
157
|
-
File.open(DEBUG_LOG_FILE,"a+") { |f| f.puts("#{Time.now} - service_stop left") }
|
|
189
|
+
dbg "service_stop entered"
|
|
190
|
+
|
|
191
|
+
dbg "service_stop left"
|
|
158
192
|
end
|
|
159
193
|
end
|
|
160
194
|
|
|
@@ -170,25 +204,88 @@ if ARGV[0] == 'service'
|
|
|
170
204
|
:port => 3000,
|
|
171
205
|
:mime_map => nil,
|
|
172
206
|
:num_procs => 20,
|
|
173
|
-
:timeout => 120
|
|
207
|
+
:timeout => 120,
|
|
208
|
+
:cpu => nil
|
|
174
209
|
}
|
|
175
210
|
|
|
176
211
|
ARGV.options do |opts|
|
|
177
212
|
opts.on('-r', '--root PATH', "Set the root path where your rails app resides.") { |OPTIONS[:rails_root]| }
|
|
178
|
-
opts.on('-e', '--environment ENV', "Rails environment to run as.") { |OPTIONS[:environment]| }
|
|
213
|
+
opts.on('-e', '--environment ENV', "Rails environment to run as. (default: production)") { |OPTIONS[:environment]| }
|
|
179
214
|
opts.on('-b', '--binding ADDR', "Address to bind to") { |OPTIONS[:ip]| }
|
|
180
215
|
opts.on('-p', '--port PORT', "Which port to bind to") { |OPTIONS[:port]| }
|
|
181
216
|
opts.on('-m', '--mime PATH', "A YAML file that lists additional MIME types") { |OPTIONS[:mime_map]| }
|
|
182
217
|
opts.on('-P', '--num-procs INT', "Number of processor threads to use") { |OPTIONS[:num_procs]| }
|
|
183
218
|
opts.on('-t', '--timeout SECONDS', "Timeout all requests after SECONDS time") { |OPTIONS[:timeout]| }
|
|
184
|
-
|
|
219
|
+
opts.on('-c', '--cpu CPU', "Bind the process to specific cpu") { |OPTIONS[:cpu]| }
|
|
220
|
+
|
|
185
221
|
opts.parse!
|
|
186
222
|
end
|
|
187
223
|
|
|
224
|
+
#expand RAILS_ROOT
|
|
225
|
+
OPTIONS[:rails_root] = File.expand_path(OPTIONS[:rails_root])
|
|
226
|
+
|
|
188
227
|
OPTIONS[:docroot] = File.expand_path(OPTIONS[:rails_root] + '/public')
|
|
189
228
|
|
|
190
|
-
|
|
229
|
+
# We must bind to a specific cpu?
|
|
230
|
+
if OPTIONS[:cpu]
|
|
231
|
+
Kernel32.set_affinity(Process.pid, OPTIONS[:cpu])
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
rails = MongrelRails.new(OPTIONS[:ip], OPTIONS[:port], OPTIONS[:rails_root], OPTIONS[:docroot], OPTIONS[:environment], OPTIONS[:mime_map], OPTIONS[:num_procs].to_i, OPTIONS[:timeout].to_i)
|
|
235
|
+
rails_svc = RailsDaemon.new(rails)
|
|
191
236
|
rails_svc.mainloop
|
|
192
237
|
|
|
193
|
-
|
|
238
|
+
elsif ARGV[0] == 'debug'
|
|
239
|
+
ARGV.shift
|
|
194
240
|
|
|
241
|
+
# default options
|
|
242
|
+
OPTIONS = {
|
|
243
|
+
:rails_root => Dir.pwd,
|
|
244
|
+
:environment => 'production',
|
|
245
|
+
:ip => '0.0.0.0',
|
|
246
|
+
:port => 3000,
|
|
247
|
+
:mime_map => nil,
|
|
248
|
+
:num_procs => 20,
|
|
249
|
+
:timeout => 120,
|
|
250
|
+
:cpu => nil
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
ARGV.options do |opts|
|
|
254
|
+
opts.on('-r', '--root PATH', "Set the root path where your rails app resides.") { |OPTIONS[:rails_root]| }
|
|
255
|
+
opts.on('-e', '--environment ENV', "Rails environment to run as.") { |OPTIONS[:environment]| }
|
|
256
|
+
opts.on('-b', '--binding ADDR', "Address to bind to") { |OPTIONS[:ip]| }
|
|
257
|
+
opts.on('-p', '--port PORT', "Which port to bind to") { |OPTIONS[:port]| }
|
|
258
|
+
opts.on('-m', '--mime PATH', "A YAML file that lists additional MIME types") { |OPTIONS[:mime_map]| }
|
|
259
|
+
opts.on('-P', '--num-procs INT', "Number of processor threads to use") { |OPTIONS[:num_procs]| }
|
|
260
|
+
opts.on('-t', '--timeout SECONDS', "Timeout all requests after SECONDS time") { |OPTIONS[:timeout]| }
|
|
261
|
+
opts.on('-c', '--cpu CPU', "Bind the process to specific cpu") { |OPTIONS[:cpu]| }
|
|
262
|
+
|
|
263
|
+
opts.parse!
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
#expand RAILS_ROOT
|
|
267
|
+
OPTIONS[:rails_root] = File.expand_path(OPTIONS[:rails_root])
|
|
268
|
+
|
|
269
|
+
OPTIONS[:docroot] = File.expand_path(OPTIONS[:rails_root] + '/public')
|
|
270
|
+
|
|
271
|
+
# We must bind to a specific cpu?
|
|
272
|
+
if OPTIONS[:cpu]
|
|
273
|
+
Kernel32.set_affinity(Process.pid, OPTIONS[:cpu])
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
rails = MongrelRails.new(OPTIONS[:ip], OPTIONS[:port], OPTIONS[:rails_root], OPTIONS[:docroot], OPTIONS[:environment], OPTIONS[:mime_map], OPTIONS[:num_procs].to_i, OPTIONS[:timeout].to_i)
|
|
277
|
+
rails.delayed_initialize
|
|
278
|
+
rails.start_serve
|
|
279
|
+
|
|
280
|
+
begin
|
|
281
|
+
sleep
|
|
282
|
+
rescue Interrupt
|
|
283
|
+
puts "graceful shutdown?"
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
begin
|
|
287
|
+
rails.stop_serve
|
|
288
|
+
rescue
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
end
|