rainbows 3.2.0 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|