rainbows 3.2.0 → 3.3.0
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/.document +1 -0
- data/COPYING +617 -282
- data/Documentation/comparison.haml +81 -24
- data/FAQ +3 -0
- data/GIT-VERSION-GEN +1 -1
- data/LICENSE +14 -5
- data/README +10 -9
- data/Sandbox +25 -0
- data/TODO +2 -22
- data/lib/rainbows.rb +50 -49
- data/lib/rainbows/client.rb +6 -5
- data/lib/rainbows/configurator.rb +191 -37
- data/lib/rainbows/const.rb +1 -1
- data/lib/rainbows/coolio.rb +4 -1
- data/lib/rainbows/coolio/client.rb +2 -2
- data/lib/rainbows/coolio/heartbeat.rb +2 -1
- data/lib/rainbows/coolio_fiber_spawn.rb +12 -7
- data/lib/rainbows/coolio_thread_pool.rb +19 -10
- data/lib/rainbows/coolio_thread_spawn.rb +3 -0
- data/lib/rainbows/epoll.rb +27 -5
- data/lib/rainbows/epoll/client.rb +3 -3
- data/lib/rainbows/ev_core.rb +2 -1
- data/lib/rainbows/event_machine.rb +4 -0
- data/lib/rainbows/event_machine/client.rb +2 -1
- data/lib/rainbows/fiber.rb +5 -0
- data/lib/rainbows/fiber/base.rb +1 -0
- data/lib/rainbows/fiber/coolio/methods.rb +0 -1
- data/lib/rainbows/fiber/io.rb +10 -6
- data/lib/rainbows/fiber/io/pipe.rb +6 -1
- data/lib/rainbows/fiber/io/socket.rb +6 -1
- data/lib/rainbows/fiber_pool.rb +12 -7
- data/lib/rainbows/fiber_spawn.rb +11 -6
- data/lib/rainbows/http_server.rb +55 -59
- data/lib/rainbows/join_threads.rb +4 -0
- data/lib/rainbows/max_body.rb +29 -10
- data/lib/rainbows/never_block.rb +7 -10
- data/lib/rainbows/pool_size.rb +14 -0
- data/lib/rainbows/process_client.rb +23 -1
- data/lib/rainbows/queue_pool.rb +8 -6
- data/lib/rainbows/response.rb +12 -11
- data/lib/rainbows/revactor.rb +14 -7
- data/lib/rainbows/revactor/client.rb +2 -2
- data/lib/rainbows/stream_file.rb +11 -4
- data/lib/rainbows/thread_pool.rb +12 -28
- data/lib/rainbows/thread_spawn.rb +14 -13
- data/lib/rainbows/thread_timeout.rb +118 -30
- data/lib/rainbows/writer_thread_pool/client.rb +1 -1
- data/lib/rainbows/writer_thread_spawn/client.rb +2 -2
- data/lib/rainbows/xepoll.rb +13 -5
- data/lib/rainbows/xepoll/client.rb +19 -17
- data/lib/rainbows/xepoll_thread_pool.rb +82 -0
- data/lib/rainbows/xepoll_thread_pool/client.rb +129 -0
- data/lib/rainbows/xepoll_thread_spawn.rb +58 -0
- data/lib/rainbows/xepoll_thread_spawn/client.rb +121 -0
- data/pkg.mk +4 -0
- data/rainbows.gemspec +4 -1
- data/t/GNUmakefile +5 -1
- data/t/client_header_buffer_size.ru +5 -0
- data/t/simple-http_XEpollThreadPool.ru +10 -0
- data/t/simple-http_XEpollThreadSpawn.ru +10 -0
- data/t/t0022-copy_stream-byte-range.sh +1 -15
- data/t/t0026-splice-copy_stream-byte-range.sh +25 -0
- data/t/t0027-nil-copy_stream.sh +60 -0
- data/t/t0041-optional-pool-size.sh +2 -2
- data/t/t0042-client_header_buffer_size.sh +65 -0
- data/t/t9100-thread-timeout.sh +1 -6
- data/t/t9101-thread-timeout-threshold.sh +1 -6
- data/t/test-lib.sh +58 -0
- data/t/test_isolate.rb +9 -3
- metadata +47 -16
data/lib/rainbows/client.rb
CHANGED
@@ -4,19 +4,22 @@ require "io/wait"
|
|
4
4
|
|
5
5
|
# this class is used for most synchronous concurrency models
|
6
6
|
class Rainbows::Client < Kgio::Socket
|
7
|
+
include Rainbows::ProcessClient
|
8
|
+
Rainbows.config!(self, :keepalive_timeout)
|
9
|
+
|
7
10
|
def read_expire
|
8
|
-
Time.now +
|
11
|
+
Time.now + KEEPALIVE_TIMEOUT
|
9
12
|
end
|
10
13
|
|
11
14
|
def kgio_wait_readable
|
12
|
-
wait
|
15
|
+
wait KEEPALIVE_TIMEOUT
|
13
16
|
end
|
14
17
|
|
15
18
|
# used for reading headers (respecting keepalive_timeout)
|
16
19
|
def timed_read(buf)
|
17
20
|
expire = nil
|
18
21
|
begin
|
19
|
-
case rv = kgio_tryread(
|
22
|
+
case rv = kgio_tryread(CLIENT_HEADER_BUFFER_SIZE, buf)
|
20
23
|
when :wait_readable
|
21
24
|
return if expire && expire < Time.now
|
22
25
|
expire ||= read_expire
|
@@ -26,6 +29,4 @@ class Rainbows::Client < Kgio::Socket
|
|
26
29
|
end
|
27
30
|
end while true
|
28
31
|
end
|
29
|
-
|
30
|
-
include Rainbows::ProcessClient
|
31
32
|
end
|
@@ -2,49 +2,203 @@
|
|
2
2
|
|
3
3
|
# This module adds \Rainbows! to the
|
4
4
|
# {Unicorn::Configurator}[http://unicorn.bogomips.org/Unicorn/Configurator.html]
|
5
|
+
# \Rainbows!-specific configuration options must be inside a the Rainbows!
|
6
|
+
# block, otherwise Unicorn::Configurator directives may be used anwwhere
|
7
|
+
# in the file.
|
8
|
+
#
|
9
|
+
# Rainbows! do
|
10
|
+
# use :ThreadSpawn # concurrency model to use
|
11
|
+
# worker_connections 400
|
12
|
+
# keepalive_timeout 0 # zero disables keepalives entirely
|
13
|
+
# client_max_body_size 5*1024*1024 # 5 megabytes
|
14
|
+
# keepalive_requests 666 # default:100
|
15
|
+
# client_header_buffer_size 2 * 1024 # 2 kilobytes
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # the rest of the Unicorn configuration...
|
19
|
+
# worker_processes 8
|
20
|
+
# stderr_path "/path/to/error.log"
|
21
|
+
# stdout_path "/path/to/output.log"
|
5
22
|
module Rainbows::Configurator
|
23
|
+
Unicorn::Configurator::DEFAULTS.merge!({
|
24
|
+
:use => Rainbows::Base,
|
25
|
+
:worker_connections => 50,
|
26
|
+
:keepalive_timeout => 5,
|
27
|
+
:keepalive_requests => 100,
|
28
|
+
:client_max_body_size => 1024 * 1024,
|
29
|
+
:client_header_buffer_size => 1024,
|
30
|
+
:copy_stream => IO.respond_to?(:copy_stream) ? IO : false,
|
31
|
+
})
|
6
32
|
|
7
|
-
#
|
8
|
-
# a +worker_connections+ upper-bound. This method
|
9
|
-
# inside a Unicorn/\Rainbows! configuration file
|
33
|
+
# Configures \Rainbows! with a given concurrency model to +use+ and
|
34
|
+
# a +worker_connections+ upper-bound. This method should be called
|
35
|
+
# inside a Unicorn/\Rainbows! configuration file.
|
36
|
+
#
|
37
|
+
# All other methods in Rainbows::Configurator must be called
|
38
|
+
# inside this block.
|
39
|
+
def Rainbows!(&block)
|
40
|
+
block_given? or raise ArgumentError, "Rainbows! requires a block"
|
41
|
+
@block = true
|
42
|
+
instance_eval(&block)
|
43
|
+
ensure
|
44
|
+
@block = false
|
45
|
+
end
|
46
|
+
|
47
|
+
def check! # :nodoc:
|
48
|
+
@block or abort "must be inside a Rainbows! block"
|
49
|
+
end
|
50
|
+
|
51
|
+
# This limits the number of connected clients per-process. The total
|
52
|
+
# number of clients on a server is +worker_processes+ * +worker_connections+.
|
53
|
+
#
|
54
|
+
# This option has no effect with the Base concurrency model, which is
|
55
|
+
# limited to +1+.
|
56
|
+
#
|
57
|
+
# Default: 50
|
58
|
+
def worker_connections(clients)
|
59
|
+
check!
|
60
|
+
set_int(:worker_connections, clients, 1)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Select a concurrency model for use with \Rainbows!. You must select
|
64
|
+
# this with a Symbol (prefixed with ":"). Thus if you wish to select
|
65
|
+
# the Rainbows::ThreadSpawn concurrency model, you would use:
|
10
66
|
#
|
11
67
|
# Rainbows! do
|
12
|
-
# use :ThreadSpawn
|
13
|
-
# worker_connections 400
|
14
|
-
# keepalive_timeout 0 # zero disables keepalives entirely
|
15
|
-
# client_max_body_size 5*1024*1024 # 5 megabytes
|
16
|
-
# keepalive_requests 666 # default:100
|
68
|
+
# use :ThreadSpawn
|
17
69
|
# end
|
18
70
|
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
71
|
+
# See the {Summary}[link:Summary.html] document for a summary of
|
72
|
+
# supported concurrency models. +options+ may be specified for some
|
73
|
+
# concurrency models, but the majority do not support them.
|
74
|
+
#
|
75
|
+
# Default: :Base (no concurrency)
|
76
|
+
def use(model, *options)
|
77
|
+
check!
|
78
|
+
mod = begin
|
79
|
+
Rainbows.const_get(model)
|
80
|
+
rescue NameError => e
|
81
|
+
warn "error loading #{model.inspect}: #{e}"
|
82
|
+
e.backtrace.each { |l| warn l }
|
83
|
+
abort "concurrency model #{model.inspect} not supported"
|
84
|
+
end
|
85
|
+
Module === mod or abort "concurrency model #{model.inspect} not supported"
|
86
|
+
options.each do |opt|
|
87
|
+
case opt
|
88
|
+
when Hash
|
89
|
+
Rainbows::O.merge!(opt)
|
90
|
+
when Symbol
|
91
|
+
Rainbows::O[opt] = true
|
92
|
+
else
|
93
|
+
abort "cannot handle option: #{opt.inspect} in #{options.inspect}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
mod.setup if mod.respond_to?(:setup)
|
97
|
+
set[:use] = mod
|
98
|
+
end
|
99
|
+
|
100
|
+
# Sets the value (in seconds) the server will wait for a client in
|
101
|
+
# between requests. The default value should be enough under most
|
102
|
+
# conditions for browsers to render the page and start retrieving
|
103
|
+
# extra elements.
|
104
|
+
#
|
105
|
+
# Setting this value to +0+ disables keepalive entirely
|
106
|
+
#
|
107
|
+
# Default: 5 seconds
|
108
|
+
def keepalive_timeout(seconds)
|
109
|
+
check!
|
110
|
+
set_int(:keepalive_timeout, seconds, 0)
|
111
|
+
end
|
112
|
+
|
113
|
+
# This limits the number of requests which can be made over a keep-alive
|
114
|
+
# connection. This is used to prevent single client from monopolizing
|
115
|
+
# the server and to improve fairness when load-balancing across multiple
|
116
|
+
# machines by forcing a client to reconnect. This may be helpful
|
117
|
+
# in mitigating some denial-of-service attacks.
|
118
|
+
#
|
119
|
+
# Default: 100 requests
|
120
|
+
def keepalive_requests(count)
|
121
|
+
check!
|
122
|
+
case count
|
123
|
+
when nil, Integer
|
124
|
+
set[:keepalive_requests] = count
|
125
|
+
else
|
126
|
+
abort "not an integer or nil: keepalive_requests=#{count.inspect}"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Limits the maximum size of a request body for all requests.
|
131
|
+
# Setting this to +nil+ disables the maximum size check.
|
132
|
+
#
|
133
|
+
# Default: 1 megabyte (1048576 bytes)
|
134
|
+
#
|
135
|
+
# If you want endpoint-specific upload limits and use a
|
136
|
+
# "rack.input"-streaming concurrency model, see the Rainbows::MaxBody
|
137
|
+
def client_max_body_size(bytes)
|
138
|
+
check!
|
139
|
+
err = "client_max_body_size must be nil or a non-negative Integer"
|
140
|
+
case bytes
|
141
|
+
when nil
|
142
|
+
when Integer
|
143
|
+
bytes >= 0 or abort err
|
144
|
+
else
|
145
|
+
abort err
|
146
|
+
end
|
147
|
+
set[:client_max_body_size] = bytes
|
148
|
+
end
|
149
|
+
|
150
|
+
# This governs the amount of memory allocated for an individual read(2) or
|
151
|
+
# recv(2) system call when reading headers. Applications that make minimal
|
152
|
+
# use of cookies should not increase this from the default.
|
153
|
+
#
|
154
|
+
# Rails applications using session cookies may want to increase this to
|
155
|
+
# 2048 bytes or more depending on expected request sizes.
|
156
|
+
#
|
157
|
+
# Increasing this will increase overall memory usage to your application,
|
158
|
+
# as you will need at least this amount of memory for every connected client.
|
159
|
+
#
|
160
|
+
# Default: 1024 bytes
|
161
|
+
def client_header_buffer_size(bytes)
|
162
|
+
check!
|
163
|
+
set_int(:client_header_buffer_size, bytes, 1)
|
164
|
+
end
|
165
|
+
|
166
|
+
# Allows overriding the +klass+ where the +copy_stream+ method is
|
167
|
+
# used to do efficient copying of regular files, pipes, and sockets.
|
168
|
+
#
|
169
|
+
# This is only used with multi-threaded concurrency models:
|
170
|
+
#
|
171
|
+
# * ThreadSpawn
|
172
|
+
# * ThreadPool
|
173
|
+
# * WriterThreadSpawn
|
174
|
+
# * WriterThreadPool
|
175
|
+
# * XEpollThreadSpawn
|
176
|
+
# * XEpollThreadPool
|
177
|
+
#
|
178
|
+
# Due to existing {bugs}[http://redmine.ruby-lang.org/search?q=copy_stream]
|
179
|
+
# in the Ruby IO.copy_stream implementation, \Rainbows! uses the
|
180
|
+
# "sendfile" RubyGem that instead of copy_stream to transfer regular files
|
181
|
+
# to clients. The "sendfile" RubyGem also supports more operating systems,
|
182
|
+
# and works with more concurrency models.
|
183
|
+
#
|
184
|
+
# Recent Linux 2.6 users may override this with "IO::Splice" from the
|
185
|
+
# "io_splice" RubyGem:
|
186
|
+
#
|
187
|
+
# require "io/splice"
|
188
|
+
# Rainbows! do
|
189
|
+
# copy_stream IO::Splice
|
190
|
+
# end
|
191
|
+
#
|
192
|
+
# Keep in mind that splice(2) itself is a relatively new system call
|
193
|
+
# and has been buggy in many older Linux kernels.
|
194
|
+
#
|
195
|
+
# Default: IO on Ruby 1.9+, false otherwise
|
196
|
+
def copy_stream(klass)
|
197
|
+
check!
|
198
|
+
if klass && ! klass.respond_to?(:copy_stream)
|
199
|
+
abort "#{klass} must respond to `copy_stream' or be `false'"
|
200
|
+
end
|
201
|
+
set[:copy_stream] = klass
|
48
202
|
end
|
49
203
|
end
|
50
204
|
|
data/lib/rainbows/const.rb
CHANGED
data/lib/rainbows/coolio.rb
CHANGED
@@ -21,6 +21,9 @@ require 'rainbows/coolio_support'
|
|
21
21
|
#
|
22
22
|
# This model is mostly compatible with users of "async.callback" in
|
23
23
|
# the Rack environment as long as they do not depend on EventMachine.
|
24
|
+
#
|
25
|
+
# === RubyGem Requirements
|
26
|
+
# * cool.io 1.0.0 or later
|
24
27
|
module Rainbows::Coolio
|
25
28
|
# :stopdoc:
|
26
29
|
# keep-alive timeout scoreboard
|
@@ -39,10 +42,10 @@ module Rainbows::Coolio
|
|
39
42
|
autoload :ThreadClient, 'rainbows/coolio/thread_client'
|
40
43
|
autoload :ResponsePipe, 'rainbows/coolio/response_pipe'
|
41
44
|
autoload :ResponseChunkPipe, 'rainbows/coolio/response_chunk_pipe'
|
45
|
+
autoload :Heartbeat, 'rainbows/coolio/heartbeat'
|
42
46
|
# :startdoc:
|
43
47
|
end
|
44
48
|
# :enddoc:
|
45
|
-
require 'rainbows/coolio/heartbeat'
|
46
49
|
require 'rainbows/coolio/server'
|
47
50
|
require 'rainbows/coolio/core'
|
48
51
|
Rainbows::Coolio.__send__ :include, Rainbows::Coolio::Core
|
@@ -45,7 +45,7 @@ class Rainbows::Coolio::Client < Coolio::IO
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def on_readable
|
48
|
-
buf = @_io.kgio_tryread(
|
48
|
+
buf = @_io.kgio_tryread(CLIENT_HEADER_BUFFER_SIZE, RBUF)
|
49
49
|
case buf
|
50
50
|
when :wait_readable
|
51
51
|
when nil # eof
|
@@ -134,7 +134,7 @@ class Rainbows::Coolio::Client < Coolio::IO
|
|
134
134
|
close if @_write_buffer.empty?
|
135
135
|
when :headers
|
136
136
|
if @buf.empty?
|
137
|
-
buf = @_io.kgio_tryread(
|
137
|
+
buf = @_io.kgio_tryread(CLIENT_HEADER_BUFFER_SIZE, RBUF) or return close
|
138
138
|
String === buf and return on_read(buf)
|
139
139
|
# buf == :wait_readable
|
140
140
|
unless enabled?
|
@@ -8,9 +8,10 @@
|
|
8
8
|
class Rainbows::Coolio::Heartbeat < Coolio::TimerWatcher
|
9
9
|
KATO = Rainbows::Coolio::KATO
|
10
10
|
CONN = Rainbows::Coolio::CONN
|
11
|
+
Rainbows.config!(self, :keepalive_timeout)
|
11
12
|
|
12
13
|
def on_timer
|
13
|
-
if (ot =
|
14
|
+
if (ot = KEEPALIVE_TIMEOUT) >= 0
|
14
15
|
ot = Time.now - ot
|
15
16
|
KATO.delete_if { |client, time| time < ot and client.timeout? }
|
16
17
|
end
|
@@ -1,13 +1,17 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
require 'rainbows/fiber/coolio'
|
3
3
|
|
4
|
-
# A combination of the Coolio and FiberSpawn models.
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
4
|
+
# A combination of the Coolio and FiberSpawn models.
|
5
|
+
#
|
6
|
+
# This concurrency model is difficult to use with existing applications,
|
7
|
+
# lacks third-party support, and is thus NOT recommended.
|
8
|
+
#
|
9
|
+
# This allows Ruby 1.9 Fiber-based concurrency for application
|
10
|
+
# processing while exposing a synchronous execution model and using
|
11
|
+
# scalable network concurrency provided by Cool.io. A streaming
|
12
|
+
# "rack.input" is exposed. Applications are strongly advised to wrap
|
13
|
+
# all slow IO objects (sockets, pipes) using the Rainbows::Fiber::IO or
|
14
|
+
# a Cool.io-compatible class whenever possible.
|
11
15
|
module Rainbows::CoolioFiberSpawn
|
12
16
|
|
13
17
|
include Rainbows::Base
|
@@ -21,6 +25,7 @@ module Rainbows::CoolioFiberSpawn
|
|
21
25
|
Server.const_set(:APP, Rainbows.server.app)
|
22
26
|
Heartbeat.new(1, true).attach(Coolio::Loop.default)
|
23
27
|
LISTENERS.map! { |s| Server.new(s).attach(Coolio::Loop.default) }
|
28
|
+
Rainbows::Client.__send__ :include, Rainbows::Fiber::Coolio::Methods
|
24
29
|
Coolio::Loop.default.run
|
25
30
|
end
|
26
31
|
end
|
@@ -14,20 +14,29 @@
|
|
14
14
|
#
|
15
15
|
# This concurrency model is designed for Ruby 1.9, and Ruby 1.8
|
16
16
|
# users are NOT advised to use this due to high CPU usage.
|
17
|
+
#
|
18
|
+
# === :pool_size vs worker_connections
|
19
|
+
#
|
20
|
+
# In your Rainbows! config block, you may specify a Thread pool size
|
21
|
+
# to limit your application concurrency independently of
|
22
|
+
# worker_connections.
|
23
|
+
#
|
24
|
+
# Rainbows! do
|
25
|
+
# use :CoolioThreadPool, :pool_size => 50
|
26
|
+
# worker_connections 100
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# In extremely rare cases, this may be combined with Rainbows::AppPool
|
30
|
+
# if you have different concurrency capabilities for different parts of
|
31
|
+
# your Rack application.
|
32
|
+
#
|
33
|
+
# === RubyGem Requirements
|
34
|
+
# * cool.io 1.0.0 or later
|
17
35
|
module Rainbows::CoolioThreadPool
|
18
36
|
# :stopdoc:
|
19
37
|
autoload :Client, 'rainbows/coolio_thread_pool/client'
|
20
|
-
|
21
|
-
:pool_size => 20, # same default size as ThreadPool (w/o Coolio)
|
22
|
-
}
|
38
|
+
extend Rainbows::PoolSize
|
23
39
|
#:startdoc:
|
24
|
-
|
25
|
-
def self.setup # :nodoc:
|
26
|
-
o = Rainbows::O
|
27
|
-
DEFAULTS.each { |k,v| o[k] ||= v }
|
28
|
-
Integer === o[:pool_size] && o[:pool_size] > 0 or
|
29
|
-
raise ArgumentError, "pool_size must a be an Integer > 0"
|
30
|
-
end
|
31
40
|
include Rainbows::Coolio::Core
|
32
41
|
|
33
42
|
def init_worker_threads(master, queue) # :nodoc:
|
@@ -13,6 +13,9 @@
|
|
13
13
|
#
|
14
14
|
# This concurrency model is designed for Ruby 1.9, and Ruby 1.8
|
15
15
|
# users are NOT advised to use this due to high CPU usage.
|
16
|
+
#
|
17
|
+
# === RubyGem Requirements
|
18
|
+
# * cool.io 1.0.0 or later
|
16
19
|
module Rainbows::CoolioThreadSpawn
|
17
20
|
include Rainbows::Coolio::Core
|
18
21
|
autoload :Client, 'rainbows/coolio_thread_spawn/client'
|
data/lib/rainbows/epoll.rb
CHANGED
@@ -1,11 +1,32 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
|
-
# :enddoc:
|
3
2
|
require 'sleepy_penguin'
|
4
3
|
require 'sendfile'
|
5
4
|
|
6
|
-
# Edge-triggered epoll concurrency model
|
7
|
-
#
|
5
|
+
# Edge-triggered epoll concurrency model using
|
6
|
+
# {sleepy_penguin}[http://bogomips.org/sleepy_penguin/] for epoll.
|
7
|
+
#
|
8
|
+
# Unlike more portable options like Coolio and EventMachine, this
|
9
|
+
# is Linux-only, but uses edge-triggering instead of level-triggering,
|
10
|
+
# so it may perform better in some cases. Coolio and EventMachine have
|
11
|
+
# better library support and may be widely-used, however.
|
12
|
+
#
|
13
|
+
# Consider using XEpoll instead of this if you are using Ruby 1.9,
|
14
|
+
# it will avoid accept()-scalability issues with many worker processes.
|
15
|
+
#
|
16
|
+
# When serving static files, this is extremely unfair and optimized
|
17
|
+
# for throughput at the expense of fairness. This is not an issue
|
18
|
+
# if you're not serving static files, or if your working set is
|
19
|
+
# small enough to aways be in your kernel page cache. This concurrency
|
20
|
+
# model may starve clients if you have slow disks and large static files.
|
21
|
+
#
|
22
|
+
# === RubyGem Requirements
|
23
|
+
#
|
24
|
+
# * raindrops 0.6.0 or later
|
25
|
+
# * sleepy_penguin 2.0.0 or later
|
26
|
+
# * sendfile 1.1.0 or later
|
27
|
+
#
|
8
28
|
module Rainbows::Epoll
|
29
|
+
# :stopdoc:
|
9
30
|
include Rainbows::Base
|
10
31
|
ReRun = []
|
11
32
|
autoload :Server, 'rainbows/epoll/server'
|
@@ -17,9 +38,8 @@ module Rainbows::Epoll
|
|
17
38
|
end
|
18
39
|
|
19
40
|
def self.loop
|
20
|
-
timeout = Rainbows.server.timeout
|
21
41
|
begin
|
22
|
-
EP.wait(nil,
|
42
|
+
EP.wait(nil, 1000) { |_, obj| obj.epoll_run }
|
23
43
|
while obj = ReRun.shift
|
24
44
|
obj.epoll_run
|
25
45
|
end
|
@@ -33,6 +53,7 @@ module Rainbows::Epoll
|
|
33
53
|
def init_worker_process(worker)
|
34
54
|
super
|
35
55
|
Rainbows::Epoll.const_set :EP, SleepyPenguin::Epoll.new
|
56
|
+
Rainbows.at_quit { Rainbows::Epoll::EP.close }
|
36
57
|
Rainbows::Client.__send__ :include, Client
|
37
58
|
end
|
38
59
|
|
@@ -40,4 +61,5 @@ module Rainbows::Epoll
|
|
40
61
|
init_worker_process(worker)
|
41
62
|
Server.run
|
42
63
|
end
|
64
|
+
# :startdoc:
|
43
65
|
end
|