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.
Files changed (71) hide show
  1. data/GIT-VERSION-GEN +1 -1
  2. data/GNUmakefile +2 -3
  3. data/Rakefile +5 -2
  4. data/lib/rainbows.rb +72 -54
  5. data/lib/rainbows/base.rb +7 -9
  6. data/lib/rainbows/client.rb +25 -4
  7. data/lib/rainbows/const.rb +1 -1
  8. data/lib/rainbows/coolio.rb +6 -3
  9. data/lib/rainbows/coolio/client.rb +78 -57
  10. data/lib/rainbows/coolio/core.rb +1 -4
  11. data/lib/rainbows/coolio/heartbeat.rb +2 -3
  12. data/lib/rainbows/coolio/master.rb +3 -2
  13. data/lib/rainbows/coolio/{deferred_chunk_response.rb → response_chunk_pipe.rb} +1 -2
  14. data/lib/rainbows/coolio/{deferred_response.rb → response_pipe.rb} +1 -1
  15. data/lib/rainbows/coolio/thread_client.rb +4 -6
  16. data/lib/rainbows/coolio_fiber_spawn.rb +1 -1
  17. data/lib/rainbows/coolio_thread_pool.rb +1 -1
  18. data/lib/rainbows/coolio_thread_pool/watcher.rb +2 -4
  19. data/lib/rainbows/coolio_thread_spawn.rb +1 -1
  20. data/lib/rainbows/dev_fd_response.rb +2 -2
  21. data/lib/rainbows/error.rb +5 -7
  22. data/lib/rainbows/ev_core.rb +20 -7
  23. data/lib/rainbows/event_machine.rb +6 -5
  24. data/lib/rainbows/event_machine/client.rb +46 -53
  25. data/lib/rainbows/event_machine/response_pipe.rb +2 -3
  26. data/lib/rainbows/fiber/base.rb +5 -5
  27. data/lib/rainbows/fiber/body.rb +4 -13
  28. data/lib/rainbows/fiber/coolio/heartbeat.rb +1 -3
  29. data/lib/rainbows/fiber/coolio/server.rb +4 -7
  30. data/lib/rainbows/fiber_pool.rb +1 -1
  31. data/lib/rainbows/fiber_spawn.rb +2 -2
  32. data/lib/rainbows/http_parser.rb +12 -0
  33. data/lib/rainbows/http_server.rb +5 -7
  34. data/lib/rainbows/max_body.rb +2 -2
  35. data/lib/rainbows/never_block/core.rb +1 -1
  36. data/lib/rainbows/process_client.rb +15 -29
  37. data/lib/rainbows/queue_pool.rb +1 -3
  38. data/lib/rainbows/rack_input.rb +3 -3
  39. data/lib/rainbows/response.rb +164 -38
  40. data/lib/rainbows/revactor.rb +5 -65
  41. data/lib/rainbows/revactor/client.rb +60 -0
  42. data/lib/rainbows/revactor/{body.rb → client/methods.rb} +14 -14
  43. data/lib/rainbows/revactor/{tee_socket.rb → client/tee_socket.rb} +1 -1
  44. data/lib/rainbows/sendfile.rb +1 -2
  45. data/lib/rainbows/server_token.rb +1 -1
  46. data/lib/rainbows/thread_pool.rb +9 -9
  47. data/lib/rainbows/thread_spawn.rb +7 -6
  48. data/lib/rainbows/thread_timeout.rb +1 -1
  49. data/lib/rainbows/writer_thread_pool.rb +9 -25
  50. data/lib/rainbows/writer_thread_pool/client.rb +44 -1
  51. data/lib/rainbows/writer_thread_spawn.rb +2 -11
  52. data/lib/rainbows/writer_thread_spawn/client.rb +53 -13
  53. data/rainbows.gemspec +3 -12
  54. data/t/async_chunk_app.ru +62 -0
  55. data/t/byte-range-common.sh +142 -0
  56. data/t/t0022-copy_stream-byte-range.sh +2 -111
  57. data/t/t0023-sendfile-byte-range.sh +2 -32
  58. data/t/t0025-write-on-close.sh +23 -0
  59. data/t/t0040-keepalive_requests-setting.sh +0 -5
  60. data/t/t0402-async-keepalive.sh +146 -0
  61. data/t/t0500-cramp-streaming.sh +2 -0
  62. data/t/t0501-cramp-rainsocket.sh +2 -0
  63. data/t/t9000-rack-app-pool.sh +1 -1
  64. data/t/test_isolate.rb +5 -10
  65. data/t/test_isolate_cramp.rb +26 -0
  66. data/t/write-on-close.ru +11 -0
  67. metadata +33 -30
  68. data/lib/rainbows/coolio/sendfile.rb +0 -17
  69. data/lib/rainbows/response/body.rb +0 -127
  70. data/lib/rainbows/response/range.rb +0 -34
  71. 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
@@ -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