mongrel 0.3.11 → 0.3.12
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +4 -2
- data/bin/mongrel_rails +65 -101
- data/bin/mongrel_rails_service +1 -1
- data/bin/mongrel_rails_svc +131 -115
- data/doc/rdoc/classes/Class.html +197 -0
- data/doc/rdoc/classes/Class.src/M000001.html +24 -0
- data/doc/rdoc/classes/Class.src/M000002.html +62 -0
- data/doc/rdoc/classes/Class.src/M000003.html +21 -0
- data/doc/rdoc/classes/Class.src/M000004.html +20 -0
- data/doc/rdoc/classes/IO.html +170 -0
- data/doc/rdoc/classes/IO.src/M000005.html +19 -0
- data/doc/rdoc/classes/IO.src/M000006.html +19 -0
- data/doc/rdoc/classes/Kernel.html +159 -0
- data/doc/rdoc/classes/Kernel.src/M000025.html +19 -0
- data/doc/rdoc/classes/Kernel.src/M000026.html +25 -0
- data/doc/rdoc/classes/Mongrel.html +181 -0
- data/doc/rdoc/classes/Mongrel/CGIWrapper.html +383 -0
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000090.html +24 -0
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000091.html +47 -0
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000092.html +34 -0
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000093.html +27 -0
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000094.html +25 -0
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000095.html +18 -0
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000096.html +18 -0
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000097.html +18 -0
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000098.html +19 -0
- data/doc/rdoc/classes/Mongrel/Camping.html +177 -0
- data/doc/rdoc/classes/Mongrel/Camping.src/M000048.html +22 -0
- data/doc/rdoc/classes/Mongrel/Camping/CampingHandler.html +165 -0
- data/doc/rdoc/classes/Mongrel/Camping/CampingHandler.src/M000049.html +18 -0
- data/doc/rdoc/classes/Mongrel/Camping/CampingHandler.src/M000050.html +27 -0
- data/doc/rdoc/classes/Mongrel/Command.html +119 -0
- data/doc/rdoc/classes/Mongrel/Command/Base.html +337 -0
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000029.html +24 -0
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000030.html +41 -0
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000031.html +18 -0
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000032.html +18 -0
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000033.html +18 -0
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000034.html +22 -0
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000035.html +18 -0
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000036.html +18 -0
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000037.html +18 -0
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000038.html +18 -0
- data/doc/rdoc/classes/Mongrel/Command/Registry.html +192 -0
- data/doc/rdoc/classes/Mongrel/Command/Registry.src/M000039.html +20 -0
- data/doc/rdoc/classes/Mongrel/Command/Registry.src/M000040.html +25 -0
- data/doc/rdoc/classes/Mongrel/Command/Registry.src/M000041.html +46 -0
- data/doc/rdoc/classes/Mongrel/Configurator.html +563 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000099.html +24 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000100.html +23 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000101.html +18 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000102.html +32 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000103.html +19 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000104.html +31 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000105.html +33 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000106.html +18 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000107.html +25 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000108.html +19 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000109.html +22 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000110.html +21 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000111.html +18 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000112.html +27 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000113.html +46 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000114.html +18 -0
- data/doc/rdoc/classes/Mongrel/Const.html +286 -0
- data/doc/rdoc/classes/Mongrel/DirHandler.html +288 -0
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000058.html +20 -0
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000059.html +42 -0
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000060.html +40 -0
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000061.html +51 -0
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000062.html +40 -0
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000063.html +18 -0
- data/doc/rdoc/classes/Mongrel/Error404Handler.html +171 -0
- data/doc/rdoc/classes/Mongrel/Error404Handler.src/M000115.html +18 -0
- data/doc/rdoc/classes/Mongrel/Error404Handler.src/M000116.html +18 -0
- data/doc/rdoc/classes/Mongrel/HeaderOut.html +185 -0
- data/doc/rdoc/classes/Mongrel/HeaderOut.src/M000072.html +18 -0
- data/doc/rdoc/classes/Mongrel/HeaderOut.src/M000073.html +18 -0
- data/doc/rdoc/classes/Mongrel/HttpHandler.html +152 -0
- data/doc/rdoc/classes/Mongrel/HttpHandler.src/M000074.html +17 -0
- data/doc/rdoc/classes/Mongrel/HttpHandlerPlugin.html +169 -0
- data/doc/rdoc/classes/Mongrel/HttpHandlerPlugin.src/M000027.html +18 -0
- data/doc/rdoc/classes/Mongrel/HttpHandlerPlugin.src/M000028.html +17 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.html +271 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/M000051.html +28 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/M000052.html +29 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/M000053.html +29 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/M000054.html +41 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/M000055.html +27 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/M000056.html +27 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/M000057.html +28 -0
- data/doc/rdoc/classes/Mongrel/HttpRequest.html +222 -0
- data/doc/rdoc/classes/Mongrel/HttpRequest.src/M000117.html +28 -0
- data/doc/rdoc/classes/Mongrel/HttpRequest.src/M000118.html +20 -0
- data/doc/rdoc/classes/Mongrel/HttpRequest.src/M000119.html +20 -0
- data/doc/rdoc/classes/Mongrel/HttpRequest.src/M000120.html +32 -0
- data/doc/rdoc/classes/Mongrel/HttpResponse.html +371 -0
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000075.html +26 -0
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000076.html +20 -0
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000077.html +25 -0
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000078.html +22 -0
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000079.html +22 -0
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000080.html +23 -0
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000081.html +18 -0
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000082.html +20 -0
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000083.html +18 -0
- data/doc/rdoc/classes/Mongrel/HttpServer.html +360 -0
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000064.html +24 -0
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000065.html +65 -0
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000066.html +24 -0
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000067.html +60 -0
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000068.html +28 -0
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000069.html +18 -0
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000070.html +22 -0
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000071.html +18 -0
- data/doc/rdoc/classes/Mongrel/Rails.html +112 -0
- data/doc/rdoc/classes/Mongrel/Rails/RailsConfigurator.html +223 -0
- data/doc/rdoc/classes/Mongrel/Rails/RailsConfigurator.src/M000042.html +35 -0
- data/doc/rdoc/classes/Mongrel/Rails/RailsConfigurator.src/M000043.html +25 -0
- data/doc/rdoc/classes/Mongrel/Rails/RailsConfigurator.src/M000044.html +32 -0
- data/doc/rdoc/classes/Mongrel/Rails/RailsHandler.html +250 -0
- data/doc/rdoc/classes/Mongrel/Rails/RailsHandler.src/M000045.html +22 -0
- data/doc/rdoc/classes/Mongrel/Rails/RailsHandler.src/M000046.html +48 -0
- data/doc/rdoc/classes/Mongrel/Rails/RailsHandler.src/M000047.html +23 -0
- data/doc/rdoc/classes/Mongrel/StopServer.html +117 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.html +301 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000084.html +18 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000085.html +18 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000086.html +39 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000087.html +51 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000088.html +36 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000089.html +83 -0
- data/doc/rdoc/classes/MongrelDbg.html +209 -0
- data/doc/rdoc/classes/MongrelDbg.src/M000020.html +19 -0
- data/doc/rdoc/classes/MongrelDbg.src/M000021.html +20 -0
- data/doc/rdoc/classes/MongrelDbg.src/M000022.html +22 -0
- data/doc/rdoc/classes/MongrelDbg.src/M000023.html +21 -0
- data/doc/rdoc/classes/MongrelDbg.src/M000024.html +18 -0
- data/doc/rdoc/classes/ObjectTracker.html +176 -0
- data/doc/rdoc/classes/ObjectTracker.src/M000016.html +22 -0
- data/doc/rdoc/classes/ObjectTracker.src/M000017.html +18 -0
- data/doc/rdoc/classes/ObjectTracker.src/M000018.html +18 -0
- data/doc/rdoc/classes/ObjectTracker.src/M000019.html +46 -0
- data/doc/rdoc/classes/RequestLog.html +113 -0
- data/doc/rdoc/classes/RequestLog/Files.html +144 -0
- data/doc/rdoc/classes/RequestLog/Files.src/M000121.html +19 -0
- data/doc/rdoc/classes/RequestLog/Objects.html +144 -0
- data/doc/rdoc/classes/RequestLog/Objects.src/M000122.html +19 -0
- data/doc/rdoc/classes/RequestLog/Params.html +144 -0
- data/doc/rdoc/classes/RequestLog/Params.src/M000123.html +19 -0
- data/doc/rdoc/classes/Stats.html +306 -0
- data/doc/rdoc/classes/Stats.src/M000009.html +19 -0
- data/doc/rdoc/classes/Stats.src/M000010.html +23 -0
- data/doc/rdoc/classes/Stats.src/M000011.html +26 -0
- data/doc/rdoc/classes/Stats.src/M000012.html +18 -0
- data/doc/rdoc/classes/Stats.src/M000013.html +18 -0
- data/doc/rdoc/classes/Stats.src/M000014.html +19 -0
- data/doc/rdoc/classes/Stats.src/M000015.html +20 -0
- data/doc/rdoc/classes/TCPServer.html +173 -0
- data/doc/rdoc/classes/TCPServer.src/M000007.html +19 -0
- data/doc/rdoc/created.rid +1 -0
- data/doc/rdoc/files/COPYING.html +756 -0
- data/doc/rdoc/files/LICENSE.html +756 -0
- data/doc/rdoc/files/README.html +302 -0
- data/doc/rdoc/files/ext/http11/http11_c.html +101 -0
- data/doc/rdoc/files/lib/mongrel/camping_rb.html +108 -0
- data/doc/rdoc/files/lib/mongrel/cgi_rb.html +108 -0
- data/doc/rdoc/files/lib/mongrel/command_rb.html +111 -0
- data/doc/rdoc/files/lib/mongrel/debug_rb.html +110 -0
- data/doc/rdoc/files/lib/mongrel/handlers_rb.html +109 -0
- data/doc/rdoc/files/lib/mongrel/init_rb.html +109 -0
- data/doc/rdoc/files/lib/mongrel/rails_rb.html +111 -0
- data/doc/rdoc/files/lib/mongrel/stats_rb.html +117 -0
- data/doc/rdoc/files/lib/mongrel/tcphack_rb.html +109 -0
- data/doc/rdoc/files/lib/mongrel_rb.html +118 -0
- data/doc/rdoc/fr_class_index.html +60 -0
- data/doc/rdoc/fr_file_index.html +40 -0
- data/doc/rdoc/fr_method_index.html +149 -0
- data/doc/rdoc/index.html +24 -0
- data/doc/rdoc/rdoc-style.css +208 -0
- data/examples/builder.rb +29 -0
- data/examples/camping/blog.rb +11 -2
- data/examples/simpletest.rb +20 -7
- data/ext/http11/http11.c +71 -14
- data/ext/http11/http11_parser.c +27 -24
- data/ext/http11/http11_parser.h +2 -1
- data/lib/http11.bundle +0 -0
- data/lib/mongrel.rb +498 -135
- data/lib/mongrel/command.rb +1 -1
- data/lib/mongrel/debug.rb +259 -0
- data/lib/mongrel/handlers.rb +76 -22
- data/lib/mongrel/rails.rb +165 -72
- data/lib/mongrel/stats.rb +71 -0
- data/test/test_configurator.rb +67 -0
- data/test/test_debug.rb +31 -0
- data/test/test_http11.rb +16 -0
- data/test/test_response.rb +5 -0
- data/test/test_stats.rb +28 -0
- metadata +224 -2
data/lib/mongrel/command.rb
CHANGED
@@ -15,7 +15,7 @@ module Mongrel
|
|
15
15
|
# user's bidding.
|
16
16
|
module Base
|
17
17
|
|
18
|
-
attr_reader :valid, :done_validating
|
18
|
+
attr_reader :valid, :done_validating, :original_args
|
19
19
|
|
20
20
|
# Called by the implemented command to set the options for that command.
|
21
21
|
# Every option has a short and long version, a description, a variable to
|
@@ -0,0 +1,259 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'set'
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
$mongrel_debugging=true
|
6
|
+
|
7
|
+
module MongrelDbg
|
8
|
+
SETTINGS = { :tracing => {}}
|
9
|
+
LOGGING = { }
|
10
|
+
|
11
|
+
def MongrelDbg::configure(log_dir = "log/mongrel_debug")
|
12
|
+
Dir.mkdir(log_dir) if not File.exist?(log_dir)
|
13
|
+
@log_dir = log_dir
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def MongrelDbg::trace(target, message)
|
18
|
+
if SETTINGS[:tracing][target] and LOGGING[target]
|
19
|
+
LOGGING[target].log(Logger::DEBUG, message)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def MongrelDbg::begin_trace(target)
|
24
|
+
SETTINGS[:tracing][target] = true
|
25
|
+
if not LOGGING[target]
|
26
|
+
LOGGING[target] = Logger.new(File.join(@log_dir, "#{target.to_s}.log"))
|
27
|
+
end
|
28
|
+
MongrelDbg::trace(target, "TRACING ON #{Time.now}")
|
29
|
+
end
|
30
|
+
|
31
|
+
def MongrelDbg::end_trace(target)
|
32
|
+
SETTINGS[:tracing][target] = false
|
33
|
+
MongrelDbg::trace(target, "TRACING OFF #{Time.now}")
|
34
|
+
LOGGING[target].close
|
35
|
+
LOGGING[target] = nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def MongrelDbg::tracing?(target)
|
39
|
+
SETTINGS[:tracing][target]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
module ObjectTracker
|
45
|
+
@active_objects = nil
|
46
|
+
@live_object_tracking = true
|
47
|
+
|
48
|
+
def ObjectTracker.configure
|
49
|
+
@active_objects = Set.new
|
50
|
+
|
51
|
+
ObjectSpace.each_object do |obj|
|
52
|
+
@active_objects << obj.object_id
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def ObjectTracker.start
|
58
|
+
@live_object_tracking = true
|
59
|
+
end
|
60
|
+
|
61
|
+
def ObjectTracker.stop
|
62
|
+
@live_object_tracking = false
|
63
|
+
end
|
64
|
+
|
65
|
+
def ObjectTracker.sample
|
66
|
+
Class.stopit do
|
67
|
+
ospace = Set.new
|
68
|
+
counts = {}
|
69
|
+
|
70
|
+
# Strings can't be tracked easily and are so numerous that they drown out all else
|
71
|
+
# so we just ignore them in the counts.
|
72
|
+
ObjectSpace.each_object do |obj|
|
73
|
+
if not obj.kind_of? String
|
74
|
+
ospace << obj.object_id
|
75
|
+
counts[obj.class] ||= 0
|
76
|
+
counts[obj.class] += 1
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
dead_objects = @active_objects - ospace
|
81
|
+
new_objects = ospace - @active_objects
|
82
|
+
live_objects = ospace & @active_objects
|
83
|
+
|
84
|
+
MongrelDbg::trace(:objects, "COUNTS: #{dead_objects.length},#{new_objects.length},#{live_objects.length}")
|
85
|
+
|
86
|
+
if MongrelDbg::tracing? :objects
|
87
|
+
top_20 = counts.sort{|a,b| b[1] <=> a[1]}[0..20]
|
88
|
+
MongrelDbg::trace(:objects,"TOP 20: #{top_20.inspect}")
|
89
|
+
end
|
90
|
+
|
91
|
+
@active_objects = live_objects + new_objects
|
92
|
+
|
93
|
+
[@active_objects, top_20]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
$open_files = {}
|
100
|
+
|
101
|
+
class IO
|
102
|
+
alias_method :orig_open, :open
|
103
|
+
alias_method :orig_close, :close
|
104
|
+
|
105
|
+
def open(*arg, &blk)
|
106
|
+
$open_files[self] = args.inspect
|
107
|
+
orig_open(*arg,&blk)
|
108
|
+
end
|
109
|
+
|
110
|
+
def close(*arg,&blk)
|
111
|
+
$open_files.delete self
|
112
|
+
orig_close(*arg,&blk)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
module Kernel
|
118
|
+
alias_method :orig_open, :open
|
119
|
+
|
120
|
+
def open(*arg, &blk)
|
121
|
+
$open_files[self] = arg[0]
|
122
|
+
orig_open(*arg,&blk)
|
123
|
+
end
|
124
|
+
|
125
|
+
def log_open_files
|
126
|
+
Class.stopit do
|
127
|
+
open_counts = {}
|
128
|
+
$open_files.each do |f,args|
|
129
|
+
open_counts[args] ||= 0
|
130
|
+
open_counts[args] += 1
|
131
|
+
end
|
132
|
+
MongrelDbg::trace(:files, open_counts.to_yaml)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
|
139
|
+
class Class
|
140
|
+
alias_method :orig_new, :new
|
141
|
+
|
142
|
+
@@count = 0
|
143
|
+
@@stopit = false
|
144
|
+
@@class_caller_count = Hash.new{|hash,key| hash[key] = Hash.new(0)}
|
145
|
+
|
146
|
+
def new(*arg,&blk)
|
147
|
+
unless @@stopit
|
148
|
+
@@stopit = true
|
149
|
+
@@count += 1
|
150
|
+
@@class_caller_count[self][caller.join("\n\t")] += 1
|
151
|
+
@@stopit = false
|
152
|
+
end
|
153
|
+
orig_new(*arg,&blk)
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
def Class.report_object_creations(out=$stderr, more_than=20)
|
158
|
+
Class.stopit do
|
159
|
+
out.puts "Number of objects created = #{@@count}"
|
160
|
+
|
161
|
+
total = Hash.new(0)
|
162
|
+
|
163
|
+
@@class_caller_count.each_key do |klass|
|
164
|
+
caller_count = @@class_caller_count[klass]
|
165
|
+
caller_count.each_value do |count|
|
166
|
+
total[klass] += count
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
klass_list = total.keys.sort{|klass_a, klass_b|
|
171
|
+
a = total[klass_a]
|
172
|
+
b = total[klass_b]
|
173
|
+
if a != b
|
174
|
+
-1* (a <=> b)
|
175
|
+
else
|
176
|
+
klass_a.to_s <=> klass_b.to_s
|
177
|
+
end
|
178
|
+
}
|
179
|
+
|
180
|
+
below_count = 0
|
181
|
+
|
182
|
+
klass_list.each do |klass|
|
183
|
+
below_calls = 0
|
184
|
+
if total[klass] > more_than
|
185
|
+
out.puts "#{total[klass]}\t#{klass} objects created."
|
186
|
+
caller_count = @@class_caller_count[ klass]
|
187
|
+
caller_count.keys.sort_by{|call| -1*caller_count[call]}.each do |call|
|
188
|
+
if caller_count[call] > more_than
|
189
|
+
out.puts "\t** #{caller_count[call]} #{klass} objects AT:"
|
190
|
+
out.puts "\t#{call}\n\n"
|
191
|
+
else
|
192
|
+
below_calls += 1
|
193
|
+
end
|
194
|
+
end
|
195
|
+
out.puts "\t#{below_calls} more objects had calls less that #{more_than} limit.\n\n" if below_calls > 0
|
196
|
+
else
|
197
|
+
below_count += 1
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
out.puts "\t** #{below_count} More objects were created but the count was below the #{more_than} limit." if below_count > 0
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def Class.reset_object_creations
|
206
|
+
Class.stopit do
|
207
|
+
@@count = 0
|
208
|
+
@@class_caller_count = Hash.new{|hash,key| hash[key] = Hash.new(0)}
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def Class.stopit
|
213
|
+
@@stopit = true
|
214
|
+
yield
|
215
|
+
@@stopit = false
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
|
221
|
+
module RequestLog
|
222
|
+
class Files < GemPlugin::Plugin "/handlers"
|
223
|
+
include Mongrel::HttpHandlerPlugin
|
224
|
+
|
225
|
+
def process(request, response)
|
226
|
+
MongrelDbg::trace(:files, "#{Time.now} FILES OPEN BEFORE REQUEST #{request.params['PATH_INFO']}")
|
227
|
+
log_open_files
|
228
|
+
end
|
229
|
+
|
230
|
+
end
|
231
|
+
|
232
|
+
class Objects < GemPlugin::Plugin "/handlers"
|
233
|
+
include Mongrel::HttpHandlerPlugin
|
234
|
+
|
235
|
+
def process(request, response)
|
236
|
+
MongrelDbg::trace(:objects, "#{Time.now} OBJECT STATS BEFORE REQUEST #{request.params['PATH_INFO']}")
|
237
|
+
ObjectTracker.sample
|
238
|
+
end
|
239
|
+
|
240
|
+
end
|
241
|
+
|
242
|
+
|
243
|
+
class Params < GemPlugin::Plugin "/handlers"
|
244
|
+
include Mongrel::HttpHandlerPlugin
|
245
|
+
|
246
|
+
def process(request, response)
|
247
|
+
MongrelDbg::trace(:rails, "#{Time.now} REQUEST #{request.params['PATH_INFO']}")
|
248
|
+
MongrelDbg::trace(:rails, request.params.to_yaml)
|
249
|
+
end
|
250
|
+
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
|
255
|
+
END {
|
256
|
+
open("log/mongrel_debug/object_tracking.log", "w") {|f| Class.report_object_creations(f) }
|
257
|
+
MongrelDbg::trace(:files, "FILES OPEN AT EXIT")
|
258
|
+
log_open_files
|
259
|
+
}
|
data/lib/mongrel/handlers.rb
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
begin
|
3
|
+
require 'sendfile'
|
4
|
+
$mongrel_has_sendfile = true
|
5
|
+
STDERR.puts "** You have sendfile installed, will use that to serve files."
|
6
|
+
rescue Object
|
7
|
+
$mongrel_has_sendfile = false
|
8
|
+
end
|
1
9
|
|
2
10
|
module Mongrel
|
3
11
|
|
@@ -5,12 +13,35 @@ module Mongrel
|
|
5
13
|
# just the minimum necessary for you to handle a request and shoot back
|
6
14
|
# a response. Look at the HttpRequest and HttpResponse objects for how
|
7
15
|
# to use them.
|
16
|
+
#
|
17
|
+
# This is used for very simple handlers that don't require much to operate.
|
18
|
+
# More extensive plugins or those you intend to distribute as GemPlugins
|
19
|
+
# should be implemented using the HttpHandlerPlugin mixin.
|
20
|
+
#
|
8
21
|
class HttpHandler
|
22
|
+
|
9
23
|
def process(request, response)
|
10
24
|
end
|
11
25
|
end
|
12
26
|
|
13
27
|
|
28
|
+
# This is used when your handler is implemented as a GemPlugin.
|
29
|
+
# The plugin always takes an options hash which you can modify
|
30
|
+
# and then access later. They are stored by default for
|
31
|
+
# the process method later.
|
32
|
+
module HttpHandlerPlugin
|
33
|
+
attr_reader :options
|
34
|
+
|
35
|
+
def initialize(options={})
|
36
|
+
@options = options
|
37
|
+
end
|
38
|
+
|
39
|
+
def process(request, response)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
|
14
45
|
# The server normally returns a 404 response if an unknown URI is requested, but it
|
15
46
|
# also returns a lame empty message. This lets you do a 404 response
|
16
47
|
# with a custom message for special URIs.
|
@@ -53,6 +84,7 @@ module Mongrel
|
|
53
84
|
".txt" => "text/plain"
|
54
85
|
}
|
55
86
|
|
87
|
+
ONLY_HEAD_GET="Only HEAD and GET allowed.".freeze
|
56
88
|
|
57
89
|
attr_reader :path
|
58
90
|
|
@@ -103,7 +135,7 @@ module Mongrel
|
|
103
135
|
|
104
136
|
if @listing_allowed
|
105
137
|
response.start(200) do |head,out|
|
106
|
-
head[
|
138
|
+
head[Const::CONTENT_TYPE] = "text/html"
|
107
139
|
out << "<html><head><title>Directory Listing</title></head><body>"
|
108
140
|
Dir.entries(dir).each do |child|
|
109
141
|
next if child == "."
|
@@ -126,20 +158,40 @@ module Mongrel
|
|
126
158
|
|
127
159
|
# Sends the contents of a file back to the user. Not terribly efficient since it's
|
128
160
|
# opening and closing the file for each read.
|
129
|
-
def send_file(req, response)
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
161
|
+
def send_file(req, response, header_only=false)
|
162
|
+
|
163
|
+
# first we setup the headers and status then we do a very fast send on the socket directly
|
164
|
+
response.status = 200
|
165
|
+
|
166
|
+
# set the mime type from our map based on the ending
|
167
|
+
dot_at = req.rindex(".")
|
168
|
+
if dot_at
|
169
|
+
ext = req[dot_at .. -1]
|
170
|
+
if MIME_TYPES[ext]
|
171
|
+
stat = File.stat(req)
|
172
|
+
response.header[Const::CONTENT_TYPE] = MIME_TYPES[ext]
|
173
|
+
# TODO: Confirm this works for rfc 1123
|
174
|
+
response.header[Const::LAST_MODIFIED] = HttpServer.httpdate(stat.mtime)
|
175
|
+
# TODO that this is a valid way to calculate an etag
|
176
|
+
response.header[Const::ETAG] = Const::ETAG_FORMAT % [stat.mtime.to_i, stat.size, stat.ino]
|
138
177
|
end
|
178
|
+
end
|
139
179
|
|
140
|
-
|
141
|
-
|
142
|
-
|
180
|
+
response.send_status(File.size(req))
|
181
|
+
response.send_header
|
182
|
+
|
183
|
+
if not header_only
|
184
|
+
begin
|
185
|
+
if $mongrel_has_sendfile
|
186
|
+
File.open(req, "rb") { |f| response.socket.sendfile(f) }
|
187
|
+
else
|
188
|
+
File.open(req, "rb") { |f| response.socket.write(f.read) }
|
189
|
+
end
|
190
|
+
rescue EOFError,Errno::ECONNRESET,Errno::EPIPE
|
191
|
+
# ignore these since it means the client closed off early
|
192
|
+
end
|
193
|
+
else
|
194
|
+
response.send_body # should send nothing
|
143
195
|
end
|
144
196
|
end
|
145
197
|
|
@@ -147,7 +199,8 @@ module Mongrel
|
|
147
199
|
# Process the request to either serve a file or a directory listing
|
148
200
|
# if allowed (based on the listing_allowed paramter to the constructor).
|
149
201
|
def process(request, response)
|
150
|
-
|
202
|
+
req_method = request.params[Const::REQUEST_METHOD] || Const::GET
|
203
|
+
req = can_serve request.params[Const::PATH_INFO]
|
151
204
|
if not req
|
152
205
|
# not found, return a 404
|
153
206
|
response.start(404) do |head,out|
|
@@ -156,16 +209,17 @@ module Mongrel
|
|
156
209
|
else
|
157
210
|
begin
|
158
211
|
if File.directory? req
|
159
|
-
send_dir_listing(request.params[
|
160
|
-
|
161
|
-
send_file(req, response)
|
212
|
+
send_dir_listing(request.params[Const::REQUEST_URI],req, response)
|
213
|
+
elsif req_method == Const::HEAD
|
214
|
+
send_file(req, response, true)
|
215
|
+
elsif req_method == Const::GET
|
216
|
+
send_file(req, response, false)
|
217
|
+
else
|
218
|
+
response.start(403) {|head,out| out.write(ONLY_HEAD_GET) }
|
162
219
|
end
|
163
220
|
rescue => details
|
164
|
-
|
165
|
-
|
166
|
-
out << "Error accessing file: #{details}"
|
167
|
-
out << details.backtrace.join("\n")
|
168
|
-
end
|
221
|
+
STDERR.puts "Error accessing file #{req}: #{details}"
|
222
|
+
STDERR.puts details.backtrace.join("\n")
|
169
223
|
end
|
170
224
|
end
|
171
225
|
end
|
data/lib/mongrel/rails.rb
CHANGED
@@ -1,85 +1,178 @@
|
|
1
1
|
require 'mongrel'
|
2
2
|
require 'cgi'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
# application with Mongrel during development and testing, then use it
|
7
|
-
# also in production behind a server that's better at serving the
|
8
|
-
# static files.
|
9
|
-
#
|
10
|
-
# The RailsHandler takes a mime_map parameter which is a simple suffix=mimetype
|
11
|
-
# mapping that it should add to the list of valid mime types.
|
12
|
-
#
|
13
|
-
# It also supports page caching directly and will try to resolve a request
|
14
|
-
# in the following order:
|
15
|
-
#
|
16
|
-
# * If the requested exact PATH_INFO exists as a file then serve it.
|
17
|
-
# * If it exists at PATH_INFO+".html" exists then serve that.
|
18
|
-
# * Finally, construct a Mongrel::CGIWrapper and run Dispatcher.dispath to have Rails go.
|
19
|
-
#
|
20
|
-
# This means that if you are using page caching it will actually work with Mongrel
|
21
|
-
# and you should see a decent speed boost (but not as fast as if you use lighttpd).
|
22
|
-
#
|
23
|
-
# An additional feature you can use is
|
24
|
-
class RailsHandler < Mongrel::HttpHandler
|
25
|
-
attr_reader :files
|
26
|
-
attr_reader :guard
|
27
|
-
|
28
|
-
def initialize(dir, mime_map = {})
|
29
|
-
@files = Mongrel::DirHandler.new(dir,false)
|
30
|
-
@guard = Mutex.new
|
4
|
+
module Mongrel
|
5
|
+
module Rails
|
31
6
|
|
32
|
-
# register the requested mime types
|
33
|
-
mime_map.each {|k,v| Mongrel::DirHandler::add_mime_type(k,v) }
|
34
|
-
end
|
35
|
-
|
36
|
-
# Attempts to resolve the request as follows:
|
37
|
-
#
|
38
|
-
#
|
39
|
-
# * If the requested exact PATH_INFO exists as a file then serve it.
|
40
|
-
# * If it exists at PATH_INFO+".html" exists then serve that.
|
41
|
-
# * Finally, construct a Mongrel::CGIWrapper and run Dispatcher.dispath to have Rails go.
|
42
|
-
def process(request, response)
|
43
|
-
return if response.socket.closed?
|
44
|
-
|
45
|
-
path_info = request.params[Mongrel::Const::PATH_INFO]
|
46
|
-
page_cached = request.params[Mongrel::Const::PATH_INFO] + ".html"
|
47
|
-
|
48
|
-
if @files.can_serve(path_info)
|
49
|
-
# File exists as-is so serve it up
|
50
|
-
@files.process(request,response)
|
51
|
-
elsif @files.can_serve(page_cached)
|
52
|
-
# possible cached page, serve it up
|
53
|
-
request.params[Mongrel::Const::PATH_INFO] = page_cached
|
54
|
-
@files.process(request,response)
|
55
|
-
else
|
56
|
-
begin
|
57
|
-
cgi = Mongrel::CGIWrapper.new(request, response)
|
58
|
-
cgi.handler = self
|
59
7
|
|
8
|
+
# Implements a handler that can run Rails and serve files out of the
|
9
|
+
# Rails application's public directory. This lets you run your Rails
|
10
|
+
# application with Mongrel during development and testing, then use it
|
11
|
+
# also in production behind a server that's better at serving the
|
12
|
+
# static files.
|
13
|
+
#
|
14
|
+
# The RailsHandler takes a mime_map parameter which is a simple suffix=mimetype
|
15
|
+
# mapping that it should add to the list of valid mime types.
|
16
|
+
#
|
17
|
+
# It also supports page caching directly and will try to resolve a request
|
18
|
+
# in the following order:
|
19
|
+
#
|
20
|
+
# * If the requested exact PATH_INFO exists as a file then serve it.
|
21
|
+
# * If it exists at PATH_INFO+".html" exists then serve that.
|
22
|
+
# * Finally, construct a Mongrel::CGIWrapper and run Dispatcher.dispath to have Rails go.
|
23
|
+
#
|
24
|
+
# This means that if you are using page caching it will actually work with Mongrel
|
25
|
+
# and you should see a decent speed boost (but not as fast as if you use lighttpd).
|
26
|
+
#
|
27
|
+
# An additional feature you can use is
|
28
|
+
class RailsHandler < Mongrel::HttpHandler
|
29
|
+
attr_reader :files
|
30
|
+
attr_reader :guard
|
31
|
+
|
32
|
+
def initialize(dir, mime_map = {})
|
33
|
+
@files = Mongrel::DirHandler.new(dir,false)
|
34
|
+
@guard = Mutex.new
|
35
|
+
|
36
|
+
# register the requested mime types
|
37
|
+
mime_map.each {|k,v| Mongrel::DirHandler::add_mime_type(k,v) }
|
38
|
+
end
|
39
|
+
|
40
|
+
# Attempts to resolve the request as follows:
|
41
|
+
#
|
42
|
+
#
|
43
|
+
# * If the requested exact PATH_INFO exists as a file then serve it.
|
44
|
+
# * If it exists at PATH_INFO+".html" exists then serve that.
|
45
|
+
# * Finally, construct a Mongrel::CGIWrapper and run Dispatcher.dispath to have Rails go.
|
46
|
+
def process(request, response)
|
47
|
+
return if response.socket.closed?
|
48
|
+
|
49
|
+
path_info = request.params[Mongrel::Const::PATH_INFO]
|
50
|
+
page_cached = request.params[Mongrel::Const::PATH_INFO] + ".html"
|
51
|
+
|
52
|
+
if @files.can_serve(path_info)
|
53
|
+
# File exists as-is so serve it up
|
54
|
+
@files.process(request,response)
|
55
|
+
elsif @files.can_serve(page_cached)
|
56
|
+
# possible cached page, serve it up
|
57
|
+
request.params[Mongrel::Const::PATH_INFO] = page_cached
|
58
|
+
@files.process(request,response)
|
59
|
+
else
|
60
|
+
begin
|
61
|
+
cgi = Mongrel::CGIWrapper.new(request, response)
|
62
|
+
cgi.handler = self
|
63
|
+
|
64
|
+
@guard.synchronize do
|
65
|
+
# Rails is not thread safe so must be run entirely within synchronize
|
66
|
+
Dispatcher.dispatch(cgi, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, response.body)
|
67
|
+
end
|
68
|
+
|
69
|
+
# This finalizes the output using the proper HttpResponse way
|
70
|
+
cgi.out {""}
|
71
|
+
rescue Errno::EPIPE
|
72
|
+
# ignored
|
73
|
+
rescue Object => rails_error
|
74
|
+
STDERR.puts "Error calling Dispatcher.dispatch #{rails_error.inspect}"
|
75
|
+
STDERR.puts rails_error.backtrace.join("\n")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
# Does the internal reload for Rails. It might work for most cases, but
|
82
|
+
# sometimes you get exceptions. In that case just do a real restart.
|
83
|
+
def reload!
|
60
84
|
@guard.synchronize do
|
61
|
-
|
62
|
-
|
85
|
+
$".replace $orig_dollar_quote
|
86
|
+
GC.start
|
87
|
+
Dispatcher.reset_application!
|
88
|
+
ActionController::Routing::Routes.reload
|
63
89
|
end
|
64
|
-
|
65
|
-
# This finalizes the output using the proper HttpResponse way
|
66
|
-
cgi.out {""}
|
67
|
-
rescue Errno::EPIPE
|
68
|
-
# ignored
|
69
|
-
rescue Object => rails_error
|
70
|
-
STDERR.puts "Error calling Dispatcher.dispatch #{rails_error.inspect}"
|
71
|
-
STDERR.puts rails_error.backtrace.join("\n")
|
72
90
|
end
|
73
91
|
end
|
74
|
-
end
|
75
|
-
|
76
92
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
93
|
+
# Creates Rails specific configuration options for people to use
|
94
|
+
# instead of the base Configurator.
|
95
|
+
class RailsConfigurator < Mongrel::Configurator
|
96
|
+
|
97
|
+
# Creates a single rails handler and returns it so you
|
98
|
+
# can add it to a uri. You can actually attach it to
|
99
|
+
# as many URIs as you want, but this returns the
|
100
|
+
# same RailsHandler for each call.
|
101
|
+
#
|
102
|
+
# Requires the following options:
|
103
|
+
#
|
104
|
+
# * :docroot => The public dir to serve from.
|
105
|
+
# * :environment => Rails environment to use.
|
106
|
+
# * :cwd => The change to working directory
|
107
|
+
#
|
108
|
+
# And understands the following optional settings:
|
109
|
+
#
|
110
|
+
# * :mime => A map of mime types.
|
111
|
+
#
|
112
|
+
# Because of how Rails is designed you can only have
|
113
|
+
# one installed per Ruby interpreter (talk to them
|
114
|
+
# about thread safety). Because of this the first
|
115
|
+
# time you call this function it does all the config
|
116
|
+
# needed to get your rails working. After that
|
117
|
+
# it returns the one handler you've configured.
|
118
|
+
# This lets you attach Rails to any URI (and mulitple)
|
119
|
+
# you want, but still protects you from threads destroying
|
120
|
+
# your handler.
|
121
|
+
def rails(options={})
|
122
|
+
|
123
|
+
return @rails_handler if @rails_handler
|
124
|
+
|
125
|
+
ops = resolve_defaults(options)
|
126
|
+
|
127
|
+
# fix up some defaults
|
128
|
+
ops[:environment] ||= "development"
|
129
|
+
ops[:docroot] ||= "public"
|
130
|
+
ops[:mime] ||= {}
|
131
|
+
|
132
|
+
|
133
|
+
$orig_dollar_quote = $".clone
|
134
|
+
ENV['RAILS_ENV'] = ops[:environment]
|
135
|
+
require "#{ops[:cwd]}/config/environment"
|
136
|
+
require 'dispatcher'
|
137
|
+
require 'mongrel/rails'
|
138
|
+
|
139
|
+
@rails_handler = RailsHandler.new(ops[:docroot], ops[:mime])
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
# Reloads rails. This isn't too reliable really, but
|
144
|
+
# should work for most minimal reload purposes. Only reliable
|
145
|
+
# way it so stop then start the process.
|
146
|
+
def reload!
|
147
|
+
if not @rails_handler
|
148
|
+
raise "Rails was not configured. Read the docs for RailsConfigurator."
|
149
|
+
end
|
150
|
+
|
151
|
+
log "Reloading rails..."
|
152
|
+
@rails_handler.reload!
|
153
|
+
log "Done reloading rails."
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
# Takes the exact same configuration as Mongrel::Configurator (and actually calls that)
|
158
|
+
# but sets up the additional HUP handler to call reload!.
|
159
|
+
def setup_rails_signals(options={})
|
160
|
+
ops = resolve_defaults(options)
|
161
|
+
|
162
|
+
if RUBY_PLATFORM !~ /mswin/
|
163
|
+
setup_signals(options)
|
164
|
+
|
165
|
+
# rails reload
|
166
|
+
trap("HUP") {
|
167
|
+
log "HUP signal received."
|
168
|
+
reload!
|
169
|
+
}
|
170
|
+
|
171
|
+
log "Rails signals registered. HUP => reload (without restart). It might not work well."
|
172
|
+
else
|
173
|
+
log "WARNING: Rails does not support signals on Win32."
|
174
|
+
end
|
175
|
+
end
|
83
176
|
end
|
84
177
|
end
|
85
178
|
end
|