unicorn-fotopedia 0.99.1

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.
Files changed (163) hide show
  1. data/.CHANGELOG.old +25 -0
  2. data/.document +19 -0
  3. data/.gitignore +21 -0
  4. data/.mailmap +26 -0
  5. data/CONTRIBUTORS +32 -0
  6. data/COPYING +339 -0
  7. data/DESIGN +105 -0
  8. data/Documentation/.gitignore +5 -0
  9. data/Documentation/GNUmakefile +30 -0
  10. data/Documentation/unicorn.1.txt +171 -0
  11. data/Documentation/unicorn_rails.1.txt +172 -0
  12. data/FAQ +52 -0
  13. data/GIT-VERSION-GEN +40 -0
  14. data/GNUmakefile +292 -0
  15. data/HACKING +116 -0
  16. data/ISSUES +36 -0
  17. data/KNOWN_ISSUES +50 -0
  18. data/LICENSE +55 -0
  19. data/PHILOSOPHY +145 -0
  20. data/README +149 -0
  21. data/Rakefile +191 -0
  22. data/SIGNALS +109 -0
  23. data/Sandbox +78 -0
  24. data/TODO +5 -0
  25. data/TUNING +70 -0
  26. data/bin/unicorn +126 -0
  27. data/bin/unicorn_rails +203 -0
  28. data/examples/big_app_gc.rb +33 -0
  29. data/examples/echo.ru +27 -0
  30. data/examples/git.ru +13 -0
  31. data/examples/init.sh +58 -0
  32. data/examples/logger_mp_safe.rb +25 -0
  33. data/examples/nginx.conf +139 -0
  34. data/examples/unicorn.conf.rb +78 -0
  35. data/ext/unicorn_http/CFLAGS +13 -0
  36. data/ext/unicorn_http/c_util.h +124 -0
  37. data/ext/unicorn_http/common_field_optimization.h +111 -0
  38. data/ext/unicorn_http/ext_help.h +77 -0
  39. data/ext/unicorn_http/extconf.rb +14 -0
  40. data/ext/unicorn_http/global_variables.h +89 -0
  41. data/ext/unicorn_http/unicorn_http.rl +714 -0
  42. data/ext/unicorn_http/unicorn_http_common.rl +75 -0
  43. data/lib/unicorn.rb +847 -0
  44. data/lib/unicorn/app/exec_cgi.rb +150 -0
  45. data/lib/unicorn/app/inetd.rb +109 -0
  46. data/lib/unicorn/app/old_rails.rb +33 -0
  47. data/lib/unicorn/app/old_rails/static.rb +58 -0
  48. data/lib/unicorn/cgi_wrapper.rb +145 -0
  49. data/lib/unicorn/configurator.rb +421 -0
  50. data/lib/unicorn/const.rb +34 -0
  51. data/lib/unicorn/http_request.rb +72 -0
  52. data/lib/unicorn/http_response.rb +75 -0
  53. data/lib/unicorn/launcher.rb +65 -0
  54. data/lib/unicorn/oob_gc.rb +58 -0
  55. data/lib/unicorn/socket_helper.rb +152 -0
  56. data/lib/unicorn/tee_input.rb +217 -0
  57. data/lib/unicorn/util.rb +90 -0
  58. data/local.mk.sample +62 -0
  59. data/setup.rb +1586 -0
  60. data/t/.gitignore +2 -0
  61. data/t/GNUmakefile +67 -0
  62. data/t/README +42 -0
  63. data/t/bin/content-md5-put +36 -0
  64. data/t/bin/sha1sum.rb +23 -0
  65. data/t/bin/unused_listen +40 -0
  66. data/t/bin/utee +12 -0
  67. data/t/env.ru +3 -0
  68. data/t/my-tap-lib.sh +200 -0
  69. data/t/t0000-http-basic.sh +50 -0
  70. data/t/t0001-reload-bad-config.sh +52 -0
  71. data/t/t0002-config-conflict.sh +49 -0
  72. data/t/test-lib.sh +100 -0
  73. data/test/aggregate.rb +15 -0
  74. data/test/benchmark/README +50 -0
  75. data/test/benchmark/dd.ru +18 -0
  76. data/test/exec/README +5 -0
  77. data/test/exec/test_exec.rb +1038 -0
  78. data/test/rails/app-1.2.3/.gitignore +2 -0
  79. data/test/rails/app-1.2.3/Rakefile +7 -0
  80. data/test/rails/app-1.2.3/app/controllers/application.rb +6 -0
  81. data/test/rails/app-1.2.3/app/controllers/foo_controller.rb +36 -0
  82. data/test/rails/app-1.2.3/app/helpers/application_helper.rb +4 -0
  83. data/test/rails/app-1.2.3/config/boot.rb +11 -0
  84. data/test/rails/app-1.2.3/config/database.yml +12 -0
  85. data/test/rails/app-1.2.3/config/environment.rb +13 -0
  86. data/test/rails/app-1.2.3/config/environments/development.rb +9 -0
  87. data/test/rails/app-1.2.3/config/environments/production.rb +5 -0
  88. data/test/rails/app-1.2.3/config/routes.rb +6 -0
  89. data/test/rails/app-1.2.3/db/.gitignore +0 -0
  90. data/test/rails/app-1.2.3/public/404.html +1 -0
  91. data/test/rails/app-1.2.3/public/500.html +1 -0
  92. data/test/rails/app-2.0.2/.gitignore +2 -0
  93. data/test/rails/app-2.0.2/Rakefile +7 -0
  94. data/test/rails/app-2.0.2/app/controllers/application.rb +4 -0
  95. data/test/rails/app-2.0.2/app/controllers/foo_controller.rb +36 -0
  96. data/test/rails/app-2.0.2/app/helpers/application_helper.rb +4 -0
  97. data/test/rails/app-2.0.2/config/boot.rb +11 -0
  98. data/test/rails/app-2.0.2/config/database.yml +12 -0
  99. data/test/rails/app-2.0.2/config/environment.rb +17 -0
  100. data/test/rails/app-2.0.2/config/environments/development.rb +8 -0
  101. data/test/rails/app-2.0.2/config/environments/production.rb +5 -0
  102. data/test/rails/app-2.0.2/config/routes.rb +6 -0
  103. data/test/rails/app-2.0.2/db/.gitignore +0 -0
  104. data/test/rails/app-2.0.2/public/404.html +1 -0
  105. data/test/rails/app-2.0.2/public/500.html +1 -0
  106. data/test/rails/app-2.1.2/.gitignore +2 -0
  107. data/test/rails/app-2.1.2/Rakefile +7 -0
  108. data/test/rails/app-2.1.2/app/controllers/application.rb +4 -0
  109. data/test/rails/app-2.1.2/app/controllers/foo_controller.rb +36 -0
  110. data/test/rails/app-2.1.2/app/helpers/application_helper.rb +4 -0
  111. data/test/rails/app-2.1.2/config/boot.rb +111 -0
  112. data/test/rails/app-2.1.2/config/database.yml +12 -0
  113. data/test/rails/app-2.1.2/config/environment.rb +17 -0
  114. data/test/rails/app-2.1.2/config/environments/development.rb +7 -0
  115. data/test/rails/app-2.1.2/config/environments/production.rb +5 -0
  116. data/test/rails/app-2.1.2/config/routes.rb +6 -0
  117. data/test/rails/app-2.1.2/db/.gitignore +0 -0
  118. data/test/rails/app-2.1.2/public/404.html +1 -0
  119. data/test/rails/app-2.1.2/public/500.html +1 -0
  120. data/test/rails/app-2.2.2/.gitignore +2 -0
  121. data/test/rails/app-2.2.2/Rakefile +7 -0
  122. data/test/rails/app-2.2.2/app/controllers/application.rb +4 -0
  123. data/test/rails/app-2.2.2/app/controllers/foo_controller.rb +36 -0
  124. data/test/rails/app-2.2.2/app/helpers/application_helper.rb +4 -0
  125. data/test/rails/app-2.2.2/config/boot.rb +111 -0
  126. data/test/rails/app-2.2.2/config/database.yml +12 -0
  127. data/test/rails/app-2.2.2/config/environment.rb +17 -0
  128. data/test/rails/app-2.2.2/config/environments/development.rb +7 -0
  129. data/test/rails/app-2.2.2/config/environments/production.rb +5 -0
  130. data/test/rails/app-2.2.2/config/routes.rb +6 -0
  131. data/test/rails/app-2.2.2/db/.gitignore +0 -0
  132. data/test/rails/app-2.2.2/public/404.html +1 -0
  133. data/test/rails/app-2.2.2/public/500.html +1 -0
  134. data/test/rails/app-2.3.5/.gitignore +2 -0
  135. data/test/rails/app-2.3.5/Rakefile +7 -0
  136. data/test/rails/app-2.3.5/app/controllers/application_controller.rb +5 -0
  137. data/test/rails/app-2.3.5/app/controllers/foo_controller.rb +36 -0
  138. data/test/rails/app-2.3.5/app/helpers/application_helper.rb +4 -0
  139. data/test/rails/app-2.3.5/config/boot.rb +109 -0
  140. data/test/rails/app-2.3.5/config/database.yml +12 -0
  141. data/test/rails/app-2.3.5/config/environment.rb +17 -0
  142. data/test/rails/app-2.3.5/config/environments/development.rb +7 -0
  143. data/test/rails/app-2.3.5/config/environments/production.rb +6 -0
  144. data/test/rails/app-2.3.5/config/routes.rb +6 -0
  145. data/test/rails/app-2.3.5/db/.gitignore +0 -0
  146. data/test/rails/app-2.3.5/public/404.html +1 -0
  147. data/test/rails/app-2.3.5/public/500.html +1 -0
  148. data/test/rails/app-2.3.5/public/x.txt +1 -0
  149. data/test/rails/test_rails.rb +280 -0
  150. data/test/test_helper.rb +301 -0
  151. data/test/unit/test_configurator.rb +150 -0
  152. data/test/unit/test_http_parser.rb +555 -0
  153. data/test/unit/test_http_parser_ng.rb +443 -0
  154. data/test/unit/test_request.rb +184 -0
  155. data/test/unit/test_response.rb +110 -0
  156. data/test/unit/test_server.rb +291 -0
  157. data/test/unit/test_signals.rb +206 -0
  158. data/test/unit/test_socket_helper.rb +147 -0
  159. data/test/unit/test_tee_input.rb +257 -0
  160. data/test/unit/test_upload.rb +298 -0
  161. data/test/unit/test_util.rb +96 -0
  162. data/unicorn.gemspec +52 -0
  163. metadata +283 -0
@@ -0,0 +1,421 @@
1
+ # -*- encoding: binary -*-
2
+
3
+ require 'socket'
4
+ require 'logger'
5
+
6
+ module Unicorn
7
+
8
+ # Implements a simple DSL for configuring a Unicorn server.
9
+ #
10
+ # See http://unicorn.bogomips.org/examples/unicorn.conf.rb for an
11
+ # example config file. An example config file for use with nginx is
12
+ # also available at http://unicorn.bogomips.org/examples/nginx.conf
13
+ class Configurator < Struct.new(:set, :config_file, :after_reload)
14
+
15
+ # Default settings for Unicorn
16
+ DEFAULTS = {
17
+ # Backward compatibility soft timeout (disabled in default configuration)
18
+ :soft_timeout => 60,
19
+ :timeout => 60,
20
+ :logger => Logger.new($stderr),
21
+ :worker_processes => 1,
22
+ :after_fork => lambda { |server, worker|
23
+ server.logger.info("worker=#{worker.nr} spawned pid=#{$$}")
24
+ },
25
+ :before_fork => lambda { |server, worker|
26
+ server.logger.info("worker=#{worker.nr} spawning...")
27
+ },
28
+ :before_exec => lambda { |server|
29
+ server.logger.info("forked child re-executing...")
30
+ },
31
+ :pid => nil,
32
+ :preload_app => false,
33
+ }
34
+
35
+ def initialize(defaults = {}) #:nodoc:
36
+ self.set = Hash.new(:unset)
37
+ use_defaults = defaults.delete(:use_defaults)
38
+ self.config_file = defaults.delete(:config_file)
39
+
40
+ # after_reload is only used by unicorn_rails, unsupported otherwise
41
+ self.after_reload = defaults.delete(:after_reload)
42
+
43
+ set.merge!(DEFAULTS) if use_defaults
44
+ defaults.each { |key, value| self.send(key, value) }
45
+ Hash === set[:listener_opts] or
46
+ set[:listener_opts] = Hash.new { |hash,key| hash[key] = {} }
47
+ Array === set[:listeners] or set[:listeners] = []
48
+ reload
49
+ end
50
+
51
+ def reload #:nodoc:
52
+ instance_eval(File.read(config_file), config_file) if config_file
53
+
54
+ # working_directory binds immediately (easier error checking that way),
55
+ # now ensure any paths we changed are correctly set.
56
+ [ :pid, :stderr_path, :stdout_path ].each do |var|
57
+ String === (path = set[var]) or next
58
+ path = File.expand_path(path)
59
+ test(?w, path) || test(?w, File.dirname(path)) or \
60
+ raise ArgumentError, "directory for #{var}=#{path} not writable"
61
+ end
62
+
63
+ # unicorn_rails creates dirs here after working_directory is bound
64
+ after_reload.call if after_reload
65
+ end
66
+
67
+ def commit!(server, options = {}) #:nodoc:
68
+ skip = options[:skip] || []
69
+ set.each do |key, value|
70
+ value == :unset and next
71
+ skip.include?(key) and next
72
+ server.__send__("#{key}=", value)
73
+ end
74
+ end
75
+
76
+ def [](key) # :nodoc:
77
+ set[key]
78
+ end
79
+
80
+ # sets object to the +new+ Logger-like object. The new logger-like
81
+ # object must respond to the following methods:
82
+ # +debug+, +info+, +warn+, +error+, +fatal+, +close+
83
+ def logger(new)
84
+ %w(debug info warn error fatal close).each do |m|
85
+ new.respond_to?(m) and next
86
+ raise ArgumentError, "logger=#{new} does not respond to method=#{m}"
87
+ end
88
+
89
+ set[:logger] = new
90
+ end
91
+
92
+ # sets after_fork hook to a given block. This block will be called by
93
+ # the worker after forking. The following is an example hook which adds
94
+ # a per-process listener to every worker:
95
+ #
96
+ # after_fork do |server,worker|
97
+ # # per-process listener ports for debugging/admin:
98
+ # addr = "127.0.0.1:#{9293 + worker.nr}"
99
+ #
100
+ # # the negative :tries parameter indicates we will retry forever
101
+ # # waiting on the existing process to exit with a 5 second :delay
102
+ # # Existing options for Unicorn::Configurator#listen such as
103
+ # # :backlog, :rcvbuf, :sndbuf are available here as well.
104
+ # server.listen(addr, :tries => -1, :delay => 5, :backlog => 128)
105
+ #
106
+ # # drop permissions to "www-data" in the worker
107
+ # # generally there's no reason to start Unicorn as a priviledged user
108
+ # # as it is not recommended to expose Unicorn to public clients.
109
+ # worker.user('www-data', 'www-data') if Process.euid == 0
110
+ # end
111
+ def after_fork(*args, &block)
112
+ set_hook(:after_fork, block_given? ? block : args[0])
113
+ end
114
+
115
+ # sets before_fork got be a given Proc object. This Proc
116
+ # object will be called by the master process before forking
117
+ # each worker.
118
+ def before_fork(*args, &block)
119
+ set_hook(:before_fork, block_given? ? block : args[0])
120
+ end
121
+
122
+ # sets the before_exec hook to a given Proc object. This
123
+ # Proc object will be called by the master process right
124
+ # before exec()-ing the new unicorn binary. This is useful
125
+ # for freeing certain OS resources that you do NOT wish to
126
+ # share with the reexeced child process.
127
+ # There is no corresponding after_exec hook (for obvious reasons).
128
+ def before_exec(*args, &block)
129
+ set_hook(:before_exec, block_given? ? block : args[0], 1)
130
+ end
131
+
132
+ # sets the timeout of worker processes to +seconds+. Workers
133
+ # handling the request/app.call/response cycle taking longer than
134
+ # this time period will be softly killed (via SIGABRT). This
135
+ # timeout is enforced by the master process itself and not subject
136
+ # to the scheduling limitations by the worker process. Due the
137
+ # low-complexity, low-overhead implementation, timeouts of less
138
+ # than 3.0 seconds can be considered inaccurate and unsafe.
139
+ # ABORT is handled by the worker and raise an exception, offering a
140
+ # way to log the stack trace in your rails application.
141
+
142
+ def soft_timeout(seconds)
143
+ Numeric === seconds or raise ArgumentError,
144
+ "not numeric: timeout=#{seconds.inspect}"
145
+ seconds >= 3 or raise ArgumentError,
146
+ "too low: timeout=#{seconds.inspect}"
147
+ set[:soft_timeout] = seconds
148
+ end
149
+ # sets the timeout of worker processes to +seconds+. Workers
150
+ # handling the request/app.call/response cycle taking longer than
151
+ # this time period will be forcibly killed (via SIGKILL). This
152
+ # timeout is enforced by the master process itself and not subject
153
+ # to the scheduling limitations by the worker process. Due the
154
+ # low-complexity, low-overhead implementation, timeouts of less
155
+ # than 3.0 seconds can be considered inaccurate and unsafe.
156
+ #
157
+ # For running Unicorn behind nginx, it is recommended to set
158
+ # "fail_timeout=0" for in your nginx configuration like this
159
+ # to have nginx always retry backends that may have had workers
160
+ # SIGKILL-ed due to timeouts.
161
+ #
162
+ # # See http://wiki.nginx.org/NginxHttpUpstreamModule for more details
163
+ # # on nginx upstream configuration:
164
+ # upstream unicorn_backend {
165
+ # # for UNIX domain socket setups:
166
+ # server unix:/path/to/unicorn.sock fail_timeout=0;
167
+ #
168
+ # # for TCP setups
169
+ # server 192.168.0.7:8080 fail_timeout=0;
170
+ # server 192.168.0.8:8080 fail_timeout=0;
171
+ # server 192.168.0.9:8080 fail_timeout=0;
172
+ # }
173
+ def timeout(seconds)
174
+ Numeric === seconds or raise ArgumentError,
175
+ "not numeric: timeout=#{seconds.inspect}"
176
+ seconds >= 3 or raise ArgumentError,
177
+ "too low: timeout=#{seconds.inspect}"
178
+ set[:timeout] = seconds
179
+ end
180
+
181
+
182
+ # sets the current number of worker_processes to +nr+. Each worker
183
+ # process will serve exactly one client at a time. You can
184
+ # increment or decrement this value at runtime by sending SIGTTIN
185
+ # or SIGTTOU respectively to the master process without reloading
186
+ # the rest of your Unicorn configuration. See the SIGNALS document
187
+ # for more information.
188
+ def worker_processes(nr)
189
+ Integer === nr or raise ArgumentError,
190
+ "not an integer: worker_processes=#{nr.inspect}"
191
+ nr >= 0 or raise ArgumentError,
192
+ "not non-negative: worker_processes=#{nr.inspect}"
193
+ set[:worker_processes] = nr
194
+ end
195
+
196
+ # sets listeners to the given +addresses+, replacing or augmenting the
197
+ # current set. This is for the global listener pool shared by all
198
+ # worker processes. For per-worker listeners, see the after_fork example
199
+ # This is for internal API use only, do not use it in your Unicorn
200
+ # config file. Use listen instead.
201
+ def listeners(addresses) # :nodoc:
202
+ Array === addresses or addresses = Array(addresses)
203
+ addresses.map! { |addr| expand_addr(addr) }
204
+ set[:listeners] = addresses
205
+ end
206
+
207
+ # adds an +address+ to the existing listener set.
208
+ #
209
+ # The following options may be specified (but are generally not needed):
210
+ #
211
+ # +:backlog+: this is the backlog of the listen() syscall.
212
+ #
213
+ # Some operating systems allow negative values here to specify the
214
+ # maximum allowable value. In most cases, this number is only
215
+ # recommendation and there are other OS-specific tunables and
216
+ # variables that can affect this number. See the listen(2)
217
+ # syscall documentation of your OS for the exact semantics of
218
+ # this.
219
+ #
220
+ # If you are running unicorn on multiple machines, lowering this number
221
+ # can help your load balancer detect when a machine is overloaded
222
+ # and give requests to a different machine.
223
+ #
224
+ # Default: 1024
225
+ #
226
+ # +:rcvbuf+, +:sndbuf+: maximum receive and send buffer sizes of sockets
227
+ #
228
+ # These correspond to the SO_RCVBUF and SO_SNDBUF settings which
229
+ # can be set via the setsockopt(2) syscall. Some kernels
230
+ # (e.g. Linux 2.4+) have intelligent auto-tuning mechanisms and
231
+ # there is no need (and it is sometimes detrimental) to specify them.
232
+ #
233
+ # See the socket API documentation of your operating system
234
+ # to determine the exact semantics of these settings and
235
+ # other operating system-specific knobs where they can be
236
+ # specified.
237
+ #
238
+ # Defaults: operating system defaults
239
+ #
240
+ # +:tcp_nodelay+: disables Nagle's algorithm on TCP sockets
241
+ #
242
+ # This has no effect on UNIX sockets.
243
+ #
244
+ # Default: operating system defaults (usually Nagle's algorithm enabled)
245
+ #
246
+ # +:tcp_nopush+: enables TCP_CORK in Linux or TCP_NOPUSH in FreeBSD
247
+ #
248
+ # This will prevent partial TCP frames from being sent out.
249
+ # Enabling +tcp_nopush+ is generally not needed or recommended as
250
+ # controlling +tcp_nodelay+ already provides sufficient latency
251
+ # reduction whereas Unicorn does not know when the best times are
252
+ # for flushing corked sockets.
253
+ #
254
+ # This has no effect on UNIX sockets.
255
+ #
256
+ # +:tries+: times to retry binding a socket if it is already in use
257
+ #
258
+ # A negative number indicates we will retry indefinitely, this is
259
+ # useful for migrations and upgrades when individual workers
260
+ # are binding to different ports.
261
+ #
262
+ # Default: 5
263
+ #
264
+ # +:delay+: seconds to wait between successive +tries+
265
+ #
266
+ # Default: 0.5 seconds
267
+ #
268
+ # +:umask+: sets the file mode creation mask for UNIX sockets
269
+ #
270
+ # Typically UNIX domain sockets are created with more liberal
271
+ # file permissions than the rest of the application. By default,
272
+ # we create UNIX domain sockets to be readable and writable by
273
+ # all local users to give them the same accessibility as
274
+ # locally-bound TCP listeners.
275
+ #
276
+ # This has no effect on TCP listeners.
277
+ #
278
+ # Default: 0 (world read/writable)
279
+ def listen(address, opt = {})
280
+ address = expand_addr(address)
281
+ if String === address
282
+ [ :umask, :backlog, :sndbuf, :rcvbuf, :tries ].each do |key|
283
+ value = opt[key] or next
284
+ Integer === value or
285
+ raise ArgumentError, "not an integer: #{key}=#{value.inspect}"
286
+ end
287
+ [ :tcp_nodelay, :tcp_nopush ].each do |key|
288
+ (value = opt[key]).nil? and next
289
+ TrueClass === value || FalseClass === value or
290
+ raise ArgumentError, "not boolean: #{key}=#{value.inspect}"
291
+ end
292
+ unless (value = opt[:delay]).nil?
293
+ Numeric === value or
294
+ raise ArgumentError, "not numeric: delay=#{value.inspect}"
295
+ end
296
+ set[:listener_opts][address].merge!(opt)
297
+ end
298
+
299
+ set[:listeners] << address
300
+ end
301
+
302
+ # sets the +path+ for the PID file of the unicorn master process
303
+ def pid(path); set_path(:pid, path); end
304
+
305
+ # Enabling this preloads an application before forking worker
306
+ # processes. This allows memory savings when using a
307
+ # copy-on-write-friendly GC but can cause bad things to happen when
308
+ # resources like sockets are opened at load time by the master
309
+ # process and shared by multiple children. People enabling this are
310
+ # highly encouraged to look at the before_fork/after_fork hooks to
311
+ # properly close/reopen sockets. Files opened for logging do not
312
+ # have to be reopened as (unbuffered-in-userspace) files opened with
313
+ # the File::APPEND flag are written to atomically on UNIX.
314
+ #
315
+ # In addition to reloading the unicorn-specific config settings,
316
+ # SIGHUP will reload application code in the working
317
+ # directory/symlink when workers are gracefully restarted.
318
+ def preload_app(bool)
319
+ case bool
320
+ when TrueClass, FalseClass
321
+ set[:preload_app] = bool
322
+ else
323
+ raise ArgumentError, "preload_app=#{bool.inspect} not a boolean"
324
+ end
325
+ end
326
+
327
+ # Allow redirecting $stderr to a given path. Unlike doing this from
328
+ # the shell, this allows the unicorn process to know the path its
329
+ # writing to and rotate the file if it is used for logging. The
330
+ # file will be opened with the File::APPEND flag and writes
331
+ # synchronized to the kernel (but not necessarily to _disk_) so
332
+ # multiple processes can safely append to it.
333
+ def stderr_path(path)
334
+ set_path(:stderr_path, path)
335
+ end
336
+
337
+ # Same as stderr_path, except for $stdout
338
+ def stdout_path(path)
339
+ set_path(:stdout_path, path)
340
+ end
341
+
342
+ # sets the working directory for Unicorn. This ensures USR2 will
343
+ # start a new instance of Unicorn in this directory. This may be
344
+ # a symlink.
345
+ def working_directory(path)
346
+ # just let chdir raise errors
347
+ path = File.expand_path(path)
348
+ if config_file &&
349
+ config_file[0] != ?/ &&
350
+ ! test(?r, "#{path}/#{config_file}")
351
+ raise ArgumentError,
352
+ "config_file=#{config_file} would not be accessible in" \
353
+ " working_directory=#{path}"
354
+ end
355
+ Dir.chdir(path)
356
+ HttpServer::START_CTX[:cwd] = ENV["PWD"] = path
357
+ end
358
+
359
+ # Runs worker processes as the specified +user+ and +group+.
360
+ # The master process always stays running as the user who started it.
361
+ # This switch will occur after calling the after_fork hook, and only
362
+ # if the Worker#user method is not called in the after_fork hook
363
+ def user(user, group = nil)
364
+ # raises ArgumentError on invalid user/group
365
+ Etc.getpwnam(user)
366
+ Etc.getgrnam(group) if group
367
+ set[:user] = [ user, group ]
368
+ end
369
+
370
+ # expands "unix:path/to/foo" to a socket relative to the current path
371
+ # expands pathnames of sockets if relative to "~" or "~username"
372
+ # expands "*:port and ":port" to "0.0.0.0:port"
373
+ def expand_addr(address) #:nodoc
374
+ return "0.0.0.0:#{address}" if Integer === address
375
+ return address unless String === address
376
+
377
+ case address
378
+ when %r{\Aunix:(.*)\z}
379
+ File.expand_path($1)
380
+ when %r{\A~}
381
+ File.expand_path(address)
382
+ when %r{\A(?:\*:)?(\d+)\z}
383
+ "0.0.0.0:#$1"
384
+ when %r{\A(.*):(\d+)\z}
385
+ # canonicalize the name
386
+ packed = Socket.pack_sockaddr_in($2.to_i, $1)
387
+ Socket.unpack_sockaddr_in(packed).reverse!.join(':')
388
+ else
389
+ address
390
+ end
391
+ end
392
+
393
+ private
394
+
395
+ def set_path(var, path) #:nodoc:
396
+ case path
397
+ when NilClass, String
398
+ set[var] = path
399
+ else
400
+ raise ArgumentError
401
+ end
402
+ end
403
+
404
+ def set_hook(var, my_proc, req_arity = 2) #:nodoc:
405
+ case my_proc
406
+ when Proc
407
+ arity = my_proc.arity
408
+ (arity == req_arity) or \
409
+ raise ArgumentError,
410
+ "#{var}=#{my_proc.inspect} has invalid arity: " \
411
+ "#{arity} (need #{req_arity})"
412
+ when NilClass
413
+ my_proc = DEFAULTS[var]
414
+ else
415
+ raise ArgumentError, "invalid type: #{var}=#{my_proc.inspect}"
416
+ end
417
+ set[var] = my_proc
418
+ end
419
+
420
+ end
421
+ end
@@ -0,0 +1,34 @@
1
+ # -*- encoding: binary -*-
2
+
3
+ module Unicorn
4
+
5
+ # Frequently used constants when constructing requests or responses. Many times
6
+ # the constant just refers to a string with the same contents. Using these constants
7
+ # gave about a 3% to 10% performance improvement over using the strings directly.
8
+ # Symbols did not really improve things much compared to constants.
9
+ module Const
10
+ UNICORN_VERSION="0.99.0"
11
+
12
+ DEFAULT_HOST = "0.0.0.0" # default TCP listen host address
13
+ DEFAULT_PORT = 8080 # default TCP listen port
14
+ DEFAULT_LISTEN = "#{DEFAULT_HOST}:#{DEFAULT_PORT}"
15
+
16
+ # The basic max request size we'll try to read.
17
+ CHUNK_SIZE=(16 * 1024)
18
+
19
+ # Maximum request body size before it is moved out of memory and into a
20
+ # temporary file for reading (112 kilobytes).
21
+ MAX_BODY=1024 * 112
22
+
23
+ # common errors we'll send back
24
+ ERROR_400_RESPONSE = "HTTP/1.1 400 Bad Request\r\n\r\n"
25
+ ERROR_500_RESPONSE = "HTTP/1.1 500 Internal Server Error\r\n\r\n"
26
+ EXPECT_100_RESPONSE = "HTTP/1.1 100 Continue\r\n\r\n"
27
+
28
+ # A frozen format for this is about 15% faster
29
+ REMOTE_ADDR="REMOTE_ADDR".freeze
30
+ RACK_INPUT="rack.input".freeze
31
+ HTTP_EXPECT="HTTP_EXPECT"
32
+ end
33
+
34
+ end