rainbows 2.1.0 → 3.0.0

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