rainbows 2.1.0 → 3.0.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/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +2 -3
- data/Rakefile +5 -2
- data/lib/rainbows.rb +72 -54
- data/lib/rainbows/base.rb +7 -9
- data/lib/rainbows/client.rb +25 -4
- data/lib/rainbows/const.rb +1 -1
- data/lib/rainbows/coolio.rb +6 -3
- data/lib/rainbows/coolio/client.rb +78 -57
- data/lib/rainbows/coolio/core.rb +1 -4
- data/lib/rainbows/coolio/heartbeat.rb +2 -3
- data/lib/rainbows/coolio/master.rb +3 -2
- data/lib/rainbows/coolio/{deferred_chunk_response.rb → response_chunk_pipe.rb} +1 -2
- data/lib/rainbows/coolio/{deferred_response.rb → response_pipe.rb} +1 -1
- data/lib/rainbows/coolio/thread_client.rb +4 -6
- data/lib/rainbows/coolio_fiber_spawn.rb +1 -1
- data/lib/rainbows/coolio_thread_pool.rb +1 -1
- data/lib/rainbows/coolio_thread_pool/watcher.rb +2 -4
- data/lib/rainbows/coolio_thread_spawn.rb +1 -1
- data/lib/rainbows/dev_fd_response.rb +2 -2
- data/lib/rainbows/error.rb +5 -7
- data/lib/rainbows/ev_core.rb +20 -7
- data/lib/rainbows/event_machine.rb +6 -5
- data/lib/rainbows/event_machine/client.rb +46 -53
- data/lib/rainbows/event_machine/response_pipe.rb +2 -3
- data/lib/rainbows/fiber/base.rb +5 -5
- data/lib/rainbows/fiber/body.rb +4 -13
- data/lib/rainbows/fiber/coolio/heartbeat.rb +1 -3
- data/lib/rainbows/fiber/coolio/server.rb +4 -7
- data/lib/rainbows/fiber_pool.rb +1 -1
- data/lib/rainbows/fiber_spawn.rb +2 -2
- data/lib/rainbows/http_parser.rb +12 -0
- data/lib/rainbows/http_server.rb +5 -7
- data/lib/rainbows/max_body.rb +2 -2
- data/lib/rainbows/never_block/core.rb +1 -1
- data/lib/rainbows/process_client.rb +15 -29
- data/lib/rainbows/queue_pool.rb +1 -3
- data/lib/rainbows/rack_input.rb +3 -3
- data/lib/rainbows/response.rb +164 -38
- data/lib/rainbows/revactor.rb +5 -65
- data/lib/rainbows/revactor/client.rb +60 -0
- data/lib/rainbows/revactor/{body.rb → client/methods.rb} +14 -14
- data/lib/rainbows/revactor/{tee_socket.rb → client/tee_socket.rb} +1 -1
- data/lib/rainbows/sendfile.rb +1 -2
- data/lib/rainbows/server_token.rb +1 -1
- data/lib/rainbows/thread_pool.rb +9 -9
- data/lib/rainbows/thread_spawn.rb +7 -6
- data/lib/rainbows/thread_timeout.rb +1 -1
- data/lib/rainbows/writer_thread_pool.rb +9 -25
- data/lib/rainbows/writer_thread_pool/client.rb +44 -1
- data/lib/rainbows/writer_thread_spawn.rb +2 -11
- data/lib/rainbows/writer_thread_spawn/client.rb +53 -13
- data/rainbows.gemspec +3 -12
- data/t/async_chunk_app.ru +62 -0
- data/t/byte-range-common.sh +142 -0
- data/t/t0022-copy_stream-byte-range.sh +2 -111
- data/t/t0023-sendfile-byte-range.sh +2 -32
- data/t/t0025-write-on-close.sh +23 -0
- data/t/t0040-keepalive_requests-setting.sh +0 -5
- data/t/t0402-async-keepalive.sh +146 -0
- data/t/t0500-cramp-streaming.sh +2 -0
- data/t/t0501-cramp-rainsocket.sh +2 -0
- data/t/t9000-rack-app-pool.sh +1 -1
- data/t/test_isolate.rb +5 -10
- data/t/test_isolate_cramp.rb +26 -0
- data/t/write-on-close.ru +11 -0
- metadata +33 -30
- data/lib/rainbows/coolio/sendfile.rb +0 -17
- data/lib/rainbows/response/body.rb +0 -127
- data/lib/rainbows/response/range.rb +0 -34
- data/lib/rainbows/timed_read.rb +0 -28
@@ -1,17 +0,0 @@
|
|
1
|
-
# -*- encoding: binary -*-
|
2
|
-
# :enddoc:
|
3
|
-
module Rainbows::Coolio::Sendfile
|
4
|
-
if IO.method_defined?(:sendfile_nonblock)
|
5
|
-
def rev_sendfile(sf) # +sf+ is a Rainbows::StreamFile object
|
6
|
-
sf.offset += (n = @_io.sendfile_nonblock(sf, sf.offset, sf.count))
|
7
|
-
0 == (sf.count -= n) and raise EOFError
|
8
|
-
enable_write_watcher
|
9
|
-
rescue Errno::EAGAIN
|
10
|
-
enable_write_watcher
|
11
|
-
end
|
12
|
-
else
|
13
|
-
def rev_sendfile(body)
|
14
|
-
write(body.to_io.sysread(0x4000))
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,127 +0,0 @@
|
|
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
|
-
FD_MAP = Rainbows::FD_MAP
|
34
|
-
|
35
|
-
class F < File; end
|
36
|
-
|
37
|
-
def close_if_private(io)
|
38
|
-
io.close if F === io
|
39
|
-
end
|
40
|
-
|
41
|
-
def io_for_fd(fd)
|
42
|
-
FD_MAP.delete(fd) || F.for_fd(fd)
|
43
|
-
end
|
44
|
-
|
45
|
-
# to_io is not part of the Rack spec, but make an exception here
|
46
|
-
# since we can conserve path lookups and file descriptors.
|
47
|
-
# \Rainbows! will never get here without checking for the existence
|
48
|
-
# of body.to_path first.
|
49
|
-
def body_to_io(body)
|
50
|
-
if body.respond_to?(:to_io)
|
51
|
-
body.to_io
|
52
|
-
else
|
53
|
-
# try to take advantage of Rainbows::DevFdResponse, calling File.open
|
54
|
-
# is a last resort
|
55
|
-
path = body.to_path
|
56
|
-
path =~ %r{\A/dev/fd/(\d+)\z} ? io_for_fd($1.to_i) : F.open(path)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
if IO.method_defined?(:sendfile_nonblock)
|
61
|
-
def write_body_file(sock, body, range)
|
62
|
-
io = body_to_io(body)
|
63
|
-
range ? sock.sendfile(io, range[0], range[1]) : sock.sendfile(io, 0)
|
64
|
-
ensure
|
65
|
-
close_if_private(io)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
if IO.respond_to?(:copy_stream)
|
70
|
-
unless method_defined?(:write_body_file)
|
71
|
-
# try to use sendfile() via IO.copy_stream, otherwise pread()+write()
|
72
|
-
def write_body_file(sock, body, range)
|
73
|
-
range ? IO.copy_stream(body, sock, range[1], range[0]) :
|
74
|
-
IO.copy_stream(body, sock, nil, 0)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
# only used when body is a pipe or socket that can't handle
|
79
|
-
# pread() semantics
|
80
|
-
def write_body_stream(sock, body, range)
|
81
|
-
IO.copy_stream(body, sock)
|
82
|
-
end
|
83
|
-
else
|
84
|
-
# fall back to body#each, which is a Rack standard
|
85
|
-
ALIASES[:write_body_stream] = :write_body_each
|
86
|
-
end
|
87
|
-
|
88
|
-
if method_defined?(:write_body_file)
|
89
|
-
# middlewares/apps may return with a body that responds to +to_path+
|
90
|
-
def write_body_path(sock, body, range)
|
91
|
-
stat = File.stat(body.to_path)
|
92
|
-
stat.file? ? write_body_file(sock, body, range) :
|
93
|
-
write_body_stream(sock, body, range)
|
94
|
-
ensure
|
95
|
-
body.respond_to?(:close) and body.close
|
96
|
-
end
|
97
|
-
elsif method_defined?(:write_body_stream)
|
98
|
-
def write_body_path(sock, body, range)
|
99
|
-
write_body_stream(sock, body, range)
|
100
|
-
ensure
|
101
|
-
body.respond_to?(:close) and body.close
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
if method_defined?(:write_body_path)
|
106
|
-
def write_body(client, body, range)
|
107
|
-
body.respond_to?(:to_path) ?
|
108
|
-
write_body_path(client, body, range) :
|
109
|
-
write_body_each(client, body, range)
|
110
|
-
end
|
111
|
-
else
|
112
|
-
ALIASES[:write_body] = :write_body_each
|
113
|
-
end
|
114
|
-
|
115
|
-
# generic body writer, used for most dynamically generated responses
|
116
|
-
def write_body_each(socket, body, range = nil)
|
117
|
-
body.each { |chunk| socket.write(chunk) }
|
118
|
-
ensure
|
119
|
-
body.respond_to?(:close) and body.close
|
120
|
-
end
|
121
|
-
|
122
|
-
def self.included(klass)
|
123
|
-
ALIASES.each do |new_method, orig_method|
|
124
|
-
klass.__send__(:alias_method, new_method, orig_method)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# -*- encoding: binary -*-
|
2
|
-
# :enddoc:
|
3
|
-
module Rainbows::Response::Range
|
4
|
-
HTTP_RANGE = 'HTTP_RANGE'
|
5
|
-
Content_Range = 'Content-Range'.freeze
|
6
|
-
Content_Length = 'Content-Length'.freeze
|
7
|
-
|
8
|
-
# This does not support multipart responses (does anybody actually
|
9
|
-
# use those?) +headers+ is always a Rack::Utils::HeaderHash
|
10
|
-
def make_range!(env, status, headers)
|
11
|
-
if 200 == status.to_i &&
|
12
|
-
(clen = headers[Content_Length]) &&
|
13
|
-
/\Abytes=(\d+-\d*|\d*-\d+)\z/ =~ env[HTTP_RANGE]
|
14
|
-
a, b = $1.split(/-/)
|
15
|
-
clen = clen.to_i
|
16
|
-
if b.nil? # bytes=M-
|
17
|
-
offset = a.to_i
|
18
|
-
count = clen - offset
|
19
|
-
elsif a.empty? # bytes=-N
|
20
|
-
offset = clen - b.to_i
|
21
|
-
count = clen - offset
|
22
|
-
else # bytes=M-N
|
23
|
-
offset = a.to_i
|
24
|
-
count = b.to_i + 1 - offset
|
25
|
-
end
|
26
|
-
raise Rainbows::Response416 if count <= 0 || offset >= clen
|
27
|
-
count = clen if count > clen
|
28
|
-
headers[Content_Length] = count.to_s
|
29
|
-
headers[Content_Range] = "bytes #{offset}-#{offset+count-1}/#{clen}"
|
30
|
-
[ status, offset, count ]
|
31
|
-
end
|
32
|
-
# nil if no status
|
33
|
-
end
|
34
|
-
end
|
data/lib/rainbows/timed_read.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
# -*- encoding: binary -*-
|
2
|
-
# :enddoc:
|
3
|
-
module Rainbows::TimedRead
|
4
|
-
G = Rainbows::G # :nodoc:
|
5
|
-
|
6
|
-
def read_expire
|
7
|
-
Time.now + G.kato
|
8
|
-
end
|
9
|
-
|
10
|
-
def kgio_wait_readable
|
11
|
-
IO.select([self], nil, nil, G.kato)
|
12
|
-
end
|
13
|
-
|
14
|
-
# used for reading headers (respecting keepalive_timeout)
|
15
|
-
def timed_read(buf)
|
16
|
-
expire = nil
|
17
|
-
begin
|
18
|
-
case rv = kgio_tryread(16384, buf)
|
19
|
-
when :wait_readable
|
20
|
-
return if expire && expire < Time.now
|
21
|
-
expire ||= read_expire
|
22
|
-
kgio_wait_readable
|
23
|
-
else
|
24
|
-
return rv
|
25
|
-
end
|
26
|
-
end while true
|
27
|
-
end
|
28
|
-
end
|