rainbows 0.94.0 → 0.95.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/.manifest +18 -0
- data/ChangeLog +394 -226
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +6 -4
- data/NEWS +18 -0
- data/README +13 -5
- data/Static_Files +71 -0
- data/TODO +12 -0
- data/Test_Suite +1 -1
- data/bin/rainbows +1 -4
- data/lib/rainbows/actor_spawn.rb +1 -1
- data/lib/rainbows/app_pool.rb +1 -1
- data/lib/rainbows/base.rb +79 -89
- data/lib/rainbows/byte_slice.rb +17 -0
- data/lib/rainbows/configurator.rb +46 -0
- data/lib/rainbows/const.rb +2 -2
- data/lib/rainbows/dev_fd_response.rb +52 -44
- data/lib/rainbows/error.rb +1 -0
- data/lib/rainbows/ev_core.rb +3 -2
- data/lib/rainbows/event_machine.rb +26 -24
- data/lib/rainbows/fiber/base.rb +30 -40
- data/lib/rainbows/fiber/body.rb +34 -0
- data/lib/rainbows/fiber/io.rb +28 -8
- data/lib/rainbows/fiber/queue.rb +1 -0
- data/lib/rainbows/fiber/rev.rb +4 -2
- data/lib/rainbows/fiber.rb +1 -0
- data/lib/rainbows/fiber_pool.rb +2 -2
- data/lib/rainbows/fiber_spawn.rb +2 -2
- data/lib/rainbows/http_response.rb +20 -31
- data/lib/rainbows/http_server.rb +3 -4
- data/lib/rainbows/max_body.rb +1 -0
- data/lib/rainbows/never_block/event_machine.rb +2 -0
- data/lib/rainbows/never_block.rb +5 -4
- data/lib/rainbows/queue_pool.rb +1 -0
- data/lib/rainbows/response/body.rb +119 -0
- data/lib/rainbows/response.rb +43 -0
- data/lib/rainbows/rev/client.rb +79 -9
- data/lib/rainbows/rev/core.rb +4 -0
- data/lib/rainbows/rev/deferred_response.rb +1 -44
- data/lib/rainbows/rev/heartbeat.rb +1 -0
- data/lib/rainbows/rev/master.rb +1 -0
- data/lib/rainbows/rev/sendfile.rb +26 -0
- data/lib/rainbows/rev/thread.rb +2 -1
- data/lib/rainbows/rev.rb +2 -0
- data/lib/rainbows/rev_fiber_spawn.rb +3 -1
- data/lib/rainbows/rev_thread_pool.rb +7 -5
- data/lib/rainbows/rev_thread_spawn.rb +2 -2
- data/lib/rainbows/revactor.rb +146 -146
- data/lib/rainbows/sendfile.rb +10 -21
- data/lib/rainbows/server_token.rb +39 -0
- data/lib/rainbows/stream_file.rb +14 -0
- data/lib/rainbows/tee_input.rb +1 -0
- data/lib/rainbows/thread_pool.rb +12 -7
- data/lib/rainbows/thread_spawn.rb +2 -3
- data/lib/rainbows/writer_thread_pool.rb +13 -7
- data/lib/rainbows/writer_thread_spawn.rb +12 -9
- data/lib/rainbows.rb +16 -45
- data/rainbows.gemspec +8 -8
- data/t/.gitignore +1 -1
- data/t/GNUmakefile +26 -16
- data/t/README +1 -1
- data/t/async-response-no-autochunk.ru +0 -1
- data/t/async-response.ru +0 -1
- data/t/cramp/rainsocket.ru +26 -0
- data/t/fork-sleep.ru +0 -1
- data/t/my-tap-lib.sh +3 -2
- data/t/simple-http_ActorSpawn.ru +9 -0
- data/t/t0009-broken-app.sh +1 -1
- data/t/t0009.ru +0 -1
- data/t/t0011-close-on-exec-set.sh +1 -1
- data/t/t0015-working_directory.sh +56 -0
- data/t/t0016-onenine-encoding-is-tricky.sh +28 -0
- data/t/t0016.rb +15 -0
- data/t/t0020-large-sendfile-response.sh +141 -0
- data/t/t0300-async_sinatra.sh +0 -6
- data/t/t0501-cramp-rainsocket.sh +38 -0
- data/t/t9001-sendfile-to-path.sh +5 -4
- data/t/t9002-server-token.sh +37 -0
- data/t/t9002.ru +4 -0
- data/t/test-lib.sh +1 -1
- data/t/test_isolate.rb +14 -11
- metadata +87 -18
@@ -0,0 +1,119 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# :enddoc:
|
3
|
+
# non-portable body response stuff goes here
|
4
|
+
#
|
5
|
+
# The sendfile 1.0.0 RubyGem includes IO#sendfile and
|
6
|
+
# IO#sendfile_nonblock. Previous versions of "sendfile" didn't have
|
7
|
+
# IO#sendfile_nonblock, and IO#sendfile in previous versions could
|
8
|
+
# block other threads under 1.8 with large files
|
9
|
+
#
|
10
|
+
# IO#sendfile currently (June 2010) beats 1.9 IO.copy_stream with
|
11
|
+
# non-Linux support and large files on 32-bit. We still fall back to
|
12
|
+
# IO.copy_stream (if available) if we're dealing with DevFdResponse
|
13
|
+
# objects, though.
|
14
|
+
#
|
15
|
+
# Linux-only splice(2) support via the "io_splice" gem will eventually
|
16
|
+
# be added for streaming sockets/pipes, too.
|
17
|
+
#
|
18
|
+
# * write_body_file - regular files (sendfile or pread+write)
|
19
|
+
# * write_body_stream - socket/pipes (read+write, splice later)
|
20
|
+
# * write_body_each - generic fallback
|
21
|
+
#
|
22
|
+
# callgraph is as follows:
|
23
|
+
#
|
24
|
+
# write_body
|
25
|
+
# `- write_body_each
|
26
|
+
# `- write_body_path
|
27
|
+
# `- write_body_file
|
28
|
+
# `- write_body_stream
|
29
|
+
#
|
30
|
+
module Rainbows::Response::Body # :nodoc:
|
31
|
+
ALIASES = {}
|
32
|
+
|
33
|
+
# to_io is not part of the Rack spec, but make an exception here
|
34
|
+
# since we can conserve path lookups and file descriptors.
|
35
|
+
# \Rainbows! will never get here without checking for the existence
|
36
|
+
# of body.to_path first.
|
37
|
+
def body_to_io(body)
|
38
|
+
if body.respond_to?(:to_io)
|
39
|
+
body.to_io
|
40
|
+
else
|
41
|
+
# try to take advantage of Rainbows::DevFdResponse, calling File.open
|
42
|
+
# is a last resort
|
43
|
+
path = body.to_path
|
44
|
+
path =~ %r{\A/dev/fd/(\d+)\z} ? IO.new($1.to_i) : File.open(path, 'rb')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
if IO.method_defined?(:sendfile_nonblock)
|
49
|
+
def write_body_file(sock, body)
|
50
|
+
sock.sendfile(body, 0)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
if IO.respond_to?(:copy_stream)
|
55
|
+
unless method_defined?(:write_body_file)
|
56
|
+
# try to use sendfile() via IO.copy_stream, otherwise pread()+write()
|
57
|
+
def write_body_file(sock, body)
|
58
|
+
IO.copy_stream(body, sock, nil, 0)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# only used when body is a pipe or socket that can't handle
|
63
|
+
# pread() semantics
|
64
|
+
def write_body_stream(sock, body)
|
65
|
+
IO.copy_stream(body, sock)
|
66
|
+
ensure
|
67
|
+
body.respond_to?(:close) and body.close
|
68
|
+
end
|
69
|
+
else
|
70
|
+
# fall back to body#each, which is a Rack standard
|
71
|
+
ALIASES[:write_body_stream] = :write_body_each
|
72
|
+
end
|
73
|
+
|
74
|
+
if method_defined?(:write_body_file)
|
75
|
+
|
76
|
+
# middlewares/apps may return with a body that responds to +to_path+
|
77
|
+
def write_body_path(sock, body)
|
78
|
+
inp = body_to_io(body)
|
79
|
+
if inp.stat.file?
|
80
|
+
begin
|
81
|
+
write_body_file(sock, inp)
|
82
|
+
ensure
|
83
|
+
inp.close if inp != body
|
84
|
+
end
|
85
|
+
else
|
86
|
+
write_body_stream(sock, inp)
|
87
|
+
end
|
88
|
+
ensure
|
89
|
+
body.respond_to?(:close) && inp != body and body.close
|
90
|
+
end
|
91
|
+
else
|
92
|
+
def write_body_path(sock, body)
|
93
|
+
write_body_stream(sock, body_to_io(body))
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
if method_defined?(:write_body_path)
|
98
|
+
def write_body(client, body)
|
99
|
+
body.respond_to?(:to_path) ?
|
100
|
+
write_body_path(client, body) :
|
101
|
+
write_body_each(client, body)
|
102
|
+
end
|
103
|
+
else
|
104
|
+
ALIASES[:write_body] = :write_body_each
|
105
|
+
end
|
106
|
+
|
107
|
+
# generic body writer, used for most dynamically generated responses
|
108
|
+
def write_body_each(socket, body)
|
109
|
+
body.each { |chunk| socket.write(chunk) }
|
110
|
+
ensure
|
111
|
+
body.respond_to?(:close) and body.close
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.included(klass)
|
115
|
+
ALIASES.each do |new_method, orig_method|
|
116
|
+
klass.__send__(:alias_method, new_method, orig_method)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# :enddoc:
|
3
|
+
require 'time' # for Time#httpdate
|
4
|
+
|
5
|
+
module Rainbows::Response
|
6
|
+
|
7
|
+
CODES = Unicorn::HttpResponse::CODES
|
8
|
+
|
9
|
+
def response_header(response, out)
|
10
|
+
status, headers = response
|
11
|
+
status = CODES[status.to_i] || status
|
12
|
+
|
13
|
+
headers.each do |key, value|
|
14
|
+
next if %r{\A(?:X-Rainbows-|Connection\z|Date\z|Status\z)}i =~ key
|
15
|
+
if value =~ /\n/
|
16
|
+
# avoiding blank, key-only cookies with /\n+/
|
17
|
+
out.concat(value.split(/\n+/).map! { |v| "#{key}: #{v}\r\n" })
|
18
|
+
else
|
19
|
+
out << "#{key}: #{value}\r\n"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
"HTTP/1.1 #{status}\r\n" \
|
24
|
+
"Date: #{Time.now.httpdate}\r\n" \
|
25
|
+
"Status: #{status}\r\n" \
|
26
|
+
"#{out.join('')}\r\n"
|
27
|
+
end
|
28
|
+
|
29
|
+
def write_header(socket, response, out)
|
30
|
+
out and socket.write(response_header(response, out))
|
31
|
+
end
|
32
|
+
|
33
|
+
def write_response(socket, response, out)
|
34
|
+
write_header(socket, response, out)
|
35
|
+
write_body(socket, response[2])
|
36
|
+
end
|
37
|
+
|
38
|
+
# called after forking
|
39
|
+
def self.setup(klass)
|
40
|
+
require('rainbows/response/body') and
|
41
|
+
klass.__send__(:include, Rainbows::Response::Body)
|
42
|
+
end
|
43
|
+
end
|
data/lib/rainbows/rev/client.rb
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
|
+
# :enddoc:
|
2
3
|
require 'rainbows/ev_core'
|
3
4
|
module Rainbows
|
4
5
|
module Rev
|
5
6
|
|
6
7
|
class Client < ::Rev::IO
|
8
|
+
include Rainbows::ByteSlice
|
7
9
|
include Rainbows::EvCore
|
10
|
+
include Rainbows::Response
|
8
11
|
G = Rainbows::G
|
12
|
+
HH = Rack::Utils::HeaderHash
|
9
13
|
|
10
14
|
def initialize(io)
|
11
15
|
CONN[self] = false
|
@@ -14,6 +18,33 @@ module Rainbows
|
|
14
18
|
@deferred_bodies = [] # for (fast) regular files only
|
15
19
|
end
|
16
20
|
|
21
|
+
def quit
|
22
|
+
super
|
23
|
+
close if @deferred_bodies.empty? && @_write_buffer.empty?
|
24
|
+
end
|
25
|
+
|
26
|
+
# override the ::Rev::IO#write method try to write directly to the
|
27
|
+
# kernel socket buffers to avoid an extra userspace copy if
|
28
|
+
# possible.
|
29
|
+
def write(buf)
|
30
|
+
if @_write_buffer.empty?
|
31
|
+
begin
|
32
|
+
w = @_io.write_nonblock(buf)
|
33
|
+
if w == Rack::Utils.bytesize(buf)
|
34
|
+
return on_write_complete
|
35
|
+
end
|
36
|
+
# we never care for the return value, but yes, we may return
|
37
|
+
# a "fake" short write from super(buf) if anybody cares.
|
38
|
+
buf = byte_slice(buf, w..-1)
|
39
|
+
rescue Errno::EAGAIN
|
40
|
+
break # fall through to super(buf)
|
41
|
+
rescue
|
42
|
+
return close
|
43
|
+
end while true
|
44
|
+
end
|
45
|
+
super(buf)
|
46
|
+
end
|
47
|
+
|
17
48
|
# queued, optional response bodies, it should only be unpollable "fast"
|
18
49
|
# devices where read(2) is uninterruptable. Unfortunately, NFS and ilk
|
19
50
|
# are also part of this. We'll also stick DeferredResponse bodies in
|
@@ -27,6 +58,42 @@ module Rainbows
|
|
27
58
|
@_write_buffer.empty? && @deferred_bodies.empty? and close.nil?
|
28
59
|
end
|
29
60
|
|
61
|
+
def rev_write_response(response, out)
|
62
|
+
status, headers, body = response
|
63
|
+
|
64
|
+
body.respond_to?(:to_path) or
|
65
|
+
return write_response(self, response, out)
|
66
|
+
|
67
|
+
headers = HH.new(headers)
|
68
|
+
io = body_to_io(body)
|
69
|
+
st = io.stat
|
70
|
+
|
71
|
+
if st.socket? || st.pipe?
|
72
|
+
do_chunk = !!(headers['Transfer-Encoding'] =~ %r{\Achunked\z}i)
|
73
|
+
do_chunk = false if headers.delete('X-Rainbows-Autochunk') == 'no'
|
74
|
+
# too tricky to support keepalive/pipelining when a response can
|
75
|
+
# take an indeterminate amount of time here.
|
76
|
+
if out.nil?
|
77
|
+
do_chunk = false
|
78
|
+
else
|
79
|
+
out[0] = CONN_CLOSE
|
80
|
+
end
|
81
|
+
|
82
|
+
# we only want to attach to the Rev::Loop belonging to the
|
83
|
+
# main thread in Ruby 1.9
|
84
|
+
io = DeferredResponse.new(io, self, do_chunk, body).
|
85
|
+
attach(Server::LOOP)
|
86
|
+
elsif st.file?
|
87
|
+
headers.delete('Transfer-Encoding')
|
88
|
+
headers['Content-Length'] ||= st.size.to_s
|
89
|
+
io = to_sendfile(io)
|
90
|
+
else # char/block device, directory, whatever... nobody cares
|
91
|
+
return write_response(self, response, out)
|
92
|
+
end
|
93
|
+
defer_body(io, out)
|
94
|
+
write_header(self, response, out)
|
95
|
+
end
|
96
|
+
|
30
97
|
def app_call
|
31
98
|
begin
|
32
99
|
KATO.delete(self)
|
@@ -36,7 +103,7 @@ module Rainbows
|
|
36
103
|
alive = @hp.keepalive? && G.alive
|
37
104
|
out = [ alive ? CONN_ALIVE : CONN_CLOSE ] if @hp.headers?
|
38
105
|
|
39
|
-
|
106
|
+
rev_write_response(response, out)
|
40
107
|
if alive
|
41
108
|
@env.clear
|
42
109
|
@hp.reset
|
@@ -52,16 +119,16 @@ module Rainbows
|
|
52
119
|
end
|
53
120
|
|
54
121
|
def on_write_complete
|
55
|
-
if body = @deferred_bodies
|
122
|
+
if body = @deferred_bodies[0]
|
123
|
+
# no socket or pipes, body must be a regular file to continue here
|
56
124
|
return if DeferredResponse === body
|
125
|
+
|
57
126
|
begin
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
close if :close == @state && @deferred_bodies.empty?
|
64
|
-
end
|
127
|
+
rev_sendfile(body)
|
128
|
+
rescue EOFError # expected at file EOF
|
129
|
+
@deferred_bodies.shift
|
130
|
+
body.close
|
131
|
+
close if :close == @state && @deferred_bodies.empty?
|
65
132
|
rescue => e
|
66
133
|
handle_error(e)
|
67
134
|
end
|
@@ -71,6 +138,9 @@ module Rainbows
|
|
71
138
|
end
|
72
139
|
|
73
140
|
def on_close
|
141
|
+
while f = @deferred_bodies.shift
|
142
|
+
DeferredResponse === f or f.close
|
143
|
+
end
|
74
144
|
CONN.delete(self)
|
75
145
|
end
|
76
146
|
|
data/lib/rainbows/rev/core.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
|
+
# :enddoc:
|
2
3
|
require 'rev'
|
3
4
|
Rev::VERSION >= '0.3.0' or abort 'rev >= 0.3.0 is required'
|
4
5
|
require 'rainbows/rev/heartbeat'
|
@@ -22,6 +23,9 @@ module Rainbows
|
|
22
23
|
# for connections and doesn't die until the parent dies (or is
|
23
24
|
# given a INT, QUIT, or TERM signal)
|
24
25
|
def worker_loop(worker)
|
26
|
+
Rainbows::Response.setup(Rainbows::Rev::Client)
|
27
|
+
require 'rainbows/rev/sendfile'
|
28
|
+
Rainbows::Rev::Client.__send__(:include, Rainbows::Rev::Sendfile)
|
25
29
|
init_worker_process(worker)
|
26
30
|
mod = self.class.const_get(@use)
|
27
31
|
rloop = Server.const_set(:LOOP, ::Rev::Loop.default)
|
@@ -1,55 +1,12 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
|
+
# :enddoc:
|
2
3
|
module Rainbows
|
3
4
|
module Rev
|
4
5
|
|
5
6
|
# this is class is specific to Rev for writing large static files
|
6
7
|
# or proxying IO-derived objects
|
7
8
|
class DeferredResponse < ::Rev::IO
|
8
|
-
include Unicorn
|
9
9
|
include Rainbows::Const
|
10
|
-
G = Rainbows::G
|
11
|
-
HH = Rack::Utils::HeaderHash
|
12
|
-
|
13
|
-
def self.write(client, response, out)
|
14
|
-
status, headers, body = response
|
15
|
-
|
16
|
-
body.respond_to?(:to_path) or
|
17
|
-
return HttpResponse.write(client, response, out)
|
18
|
-
|
19
|
-
headers = HH.new(headers)
|
20
|
-
|
21
|
-
# to_io is not part of the Rack spec, but make an exception
|
22
|
-
# here since we can't get here without checking to_path first
|
23
|
-
io = body.to_io if body.respond_to?(:to_io)
|
24
|
-
io ||= ::IO.new($1.to_i) if body.to_path =~ %r{\A/dev/fd/(\d+)\z}
|
25
|
-
io ||= File.open(body.to_path, 'rb')
|
26
|
-
st = io.stat
|
27
|
-
|
28
|
-
if st.socket? || st.pipe?
|
29
|
-
do_chunk = !!(headers['Transfer-Encoding'] =~ %r{\Achunked\z}i)
|
30
|
-
do_chunk = false if headers.delete('X-Rainbows-Autochunk') == 'no'
|
31
|
-
# too tricky to support keepalive/pipelining when a response can
|
32
|
-
# take an indeterminate amount of time here.
|
33
|
-
if out.nil?
|
34
|
-
do_chunk = false
|
35
|
-
else
|
36
|
-
out[0] = CONN_CLOSE
|
37
|
-
end
|
38
|
-
|
39
|
-
# we only want to attach to the Rev::Loop belonging to the
|
40
|
-
# main thread in Ruby 1.9
|
41
|
-
io = new(io, client, do_chunk, body).attach(Server::LOOP)
|
42
|
-
elsif st.file?
|
43
|
-
headers.delete('Transfer-Encoding')
|
44
|
-
headers['Content-Length'] ||= st.size.to_s
|
45
|
-
else # char/block device, directory, whatever... nobody cares
|
46
|
-
return HttpResponse.write(client, response, out)
|
47
|
-
end
|
48
|
-
client.defer_body(io, out)
|
49
|
-
out.nil? or
|
50
|
-
client.write(HttpResponse.header_string(status, headers.to_hash, out))
|
51
|
-
end
|
52
|
-
|
53
10
|
def initialize(io, client, do_chunk, body)
|
54
11
|
super(io)
|
55
12
|
@client, @do_chunk, @body = client, do_chunk, body
|
data/lib/rainbows/rev/master.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# :enddoc:
|
3
|
+
module Rainbows::Rev::Sendfile
|
4
|
+
if IO.method_defined?(:sendfile_nonblock)
|
5
|
+
F = Rainbows::StreamFile
|
6
|
+
|
7
|
+
def to_sendfile(io)
|
8
|
+
F[0, io]
|
9
|
+
end
|
10
|
+
|
11
|
+
def rev_sendfile(body)
|
12
|
+
body.offset += @_io.sendfile_nonblock(body, body.offset, 0x10000)
|
13
|
+
enable_write_watcher
|
14
|
+
rescue Errno::EAGAIN
|
15
|
+
enable_write_watcher
|
16
|
+
end
|
17
|
+
else
|
18
|
+
def to_sendfile(io)
|
19
|
+
io
|
20
|
+
end
|
21
|
+
|
22
|
+
def rev_sendfile(body)
|
23
|
+
write(body.sysread(0x4000))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/rainbows/rev/thread.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
|
+
# :enddoc:
|
2
3
|
require 'thread'
|
3
4
|
require 'rainbows/rev/master'
|
4
5
|
|
@@ -22,7 +23,7 @@ module Rainbows
|
|
22
23
|
enable
|
23
24
|
alive = @hp.keepalive? && G.alive
|
24
25
|
out = [ alive ? CONN_ALIVE : CONN_CLOSE ] if @hp.headers?
|
25
|
-
|
26
|
+
rev_write_response(response, out)
|
26
27
|
return quit unless alive && G.alive
|
27
28
|
|
28
29
|
@env.clear
|
data/lib/rainbows/rev.rb
CHANGED
@@ -15,9 +15,11 @@ module Rainbows
|
|
15
15
|
include Base
|
16
16
|
include Fiber::Rev
|
17
17
|
|
18
|
-
def worker_loop(worker)
|
18
|
+
def worker_loop(worker) # :nodoc:
|
19
|
+
Rainbows::Response.setup(Rainbows::Fiber::Rev::Server)
|
19
20
|
init_worker_process(worker)
|
20
21
|
Server.const_set(:MAX, @worker_connections)
|
22
|
+
Rainbows::Fiber::Base.setup(Rainbows::Fiber::Rev::Server, nil)
|
21
23
|
Server.const_set(:APP, G.server.app)
|
22
24
|
Heartbeat.new(1, true).attach(::Rev::Loop.default)
|
23
25
|
kato = Kato.new.attach(::Rev::Loop.default)
|
@@ -20,17 +20,19 @@ module Rainbows
|
|
20
20
|
|
21
21
|
module RevThreadPool
|
22
22
|
|
23
|
+
# :stopdoc:
|
23
24
|
DEFAULTS = {
|
24
25
|
:pool_size => 20, # same default size as ThreadPool (w/o Rev)
|
25
26
|
}
|
27
|
+
#:startdoc:
|
26
28
|
|
27
|
-
def self.setup
|
29
|
+
def self.setup # :nodoc:
|
28
30
|
DEFAULTS.each { |k,v| O[k] ||= v }
|
29
31
|
Integer === O[:pool_size] && O[:pool_size] > 0 or
|
30
32
|
raise ArgumentError, "pool_size must a be an Integer > 0"
|
31
33
|
end
|
32
34
|
|
33
|
-
class PoolWatcher < ::Rev::TimerWatcher
|
35
|
+
class PoolWatcher < ::Rev::TimerWatcher # :nodoc: all
|
34
36
|
def initialize(threads)
|
35
37
|
@threads = threads
|
36
38
|
super(G.server.timeout, true)
|
@@ -41,7 +43,7 @@ module Rainbows
|
|
41
43
|
end
|
42
44
|
end
|
43
45
|
|
44
|
-
class Client < Rainbows::Rev::ThreadClient
|
46
|
+
class Client < Rainbows::Rev::ThreadClient # :nodoc:
|
45
47
|
def app_dispatch
|
46
48
|
QUEUE << self
|
47
49
|
end
|
@@ -49,7 +51,7 @@ module Rainbows
|
|
49
51
|
|
50
52
|
include Rainbows::Rev::Core
|
51
53
|
|
52
|
-
def init_worker_threads(master, queue)
|
54
|
+
def init_worker_threads(master, queue) # :nodoc:
|
53
55
|
O[:pool_size].times.map do
|
54
56
|
Thread.new do
|
55
57
|
begin
|
@@ -62,7 +64,7 @@ module Rainbows
|
|
62
64
|
end
|
63
65
|
end
|
64
66
|
|
65
|
-
def init_worker_process(worker)
|
67
|
+
def init_worker_process(worker) # :nodoc:
|
66
68
|
super
|
67
69
|
master = Rev::Master.new(Queue.new).attach(::Rev::Loop.default)
|
68
70
|
queue = Client.const_set(:QUEUE, Queue.new)
|
@@ -20,7 +20,7 @@ module Rainbows
|
|
20
20
|
|
21
21
|
module RevThreadSpawn
|
22
22
|
|
23
|
-
class Client < Rainbows::Rev::ThreadClient
|
23
|
+
class Client < Rainbows::Rev::ThreadClient # :nodoc: all
|
24
24
|
def app_dispatch
|
25
25
|
Thread.new(self) { |client| MASTER << [ client, app_response ] }
|
26
26
|
end
|
@@ -28,7 +28,7 @@ module Rainbows
|
|
28
28
|
|
29
29
|
include Rainbows::Rev::Core
|
30
30
|
|
31
|
-
def init_worker_process(worker)
|
31
|
+
def init_worker_process(worker) # :nodoc:
|
32
32
|
super
|
33
33
|
master = Rev::Master.new(Queue.new).attach(::Rev::Loop.default)
|
34
34
|
Client.const_set(:MASTER, master)
|