io_splice 4.1.0 → 4.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/GIT-VERSION-GEN +1 -1
- data/ext/io_splice/io_splice_ext.c +11 -3
- data/lib/io/splice.rb +16 -10
- data/test/test_tcp_splice.rb +49 -0
- metadata +6 -4
data/GIT-VERSION-GEN
CHANGED
@@ -217,9 +217,9 @@ static ssize_t do_splice(int argc, VALUE *argv, unsigned dflags)
|
|
217
217
|
* into account userspace buffering done by Ruby or stdio. It is
|
218
218
|
* also not subject to encoding/decoding filters under Ruby 1.9.
|
219
219
|
*
|
220
|
-
* Consider using IO.trysplice if you are using
|
221
|
-
* both descriptors as it avoids the cost of raising
|
222
|
-
* exceptions.
|
220
|
+
* Consider using IO.trysplice if +io_out+ is a pipe or if you are using
|
221
|
+
* non-blocking I/O on both descriptors as it avoids the cost of raising
|
222
|
+
* common Errno::EAGAIN exceptions.
|
223
223
|
*
|
224
224
|
* See manpage for full documentation:
|
225
225
|
* http://kernel.org/doc/man-pages/online/pages/man2/splice.2.html
|
@@ -247,6 +247,8 @@ static VALUE my_splice(int argc, VALUE *argv, VALUE self)
|
|
247
247
|
* but this can still block if the non-pipe descriptor is blocking.
|
248
248
|
*
|
249
249
|
* See IO.splice documentation for more details.
|
250
|
+
*
|
251
|
+
* This method is recommended whenever +io_out+ is a pipe.
|
250
252
|
*/
|
251
253
|
static VALUE trysplice(int argc, VALUE *argv, VALUE self)
|
252
254
|
{
|
@@ -639,6 +641,12 @@ void Init_io_splice_ext(void)
|
|
639
641
|
* themselves are ignored by this family of functions, and
|
640
642
|
* using this flag is the only way to get non-blocking operation
|
641
643
|
* out of them.
|
644
|
+
*
|
645
|
+
* It is highly recommended this flag be set (or IO.trysplice used)
|
646
|
+
* whenever splicing from a socket into a pipe unless there is
|
647
|
+
* another (native) thread or process doing a blocking read on that
|
648
|
+
* pipe. Otherwise it is possible to block a single-threaded process
|
649
|
+
* if the socket buffers are larger than the pipe buffers.
|
642
650
|
*/
|
643
651
|
rb_define_const(mSplice, "F_NONBLOCK", UINT2NUM(SPLICE_F_NONBLOCK));
|
644
652
|
assert(WAITALL != SPLICE_F_NONBLOCK && "WAITALL == F_NONBLOCK");
|
data/lib/io/splice.rb
CHANGED
@@ -84,6 +84,13 @@ module IO::Splice
|
|
84
84
|
# This will block and wait for IO completion of +len+
|
85
85
|
# Raises +EOFError+ if end of file is reached.
|
86
86
|
# bytes. Returns the number of bytes actually spliced (always +len+)
|
87
|
+
# unless +src+ does not have +len+ bytes to read.
|
88
|
+
#
|
89
|
+
# Do not use this method to splice a socket +src+ into a pipe +dst+
|
90
|
+
# unless there is another process or native thread doing a blocking
|
91
|
+
# read on the other end of the +dst+ pipe.
|
92
|
+
#
|
93
|
+
# This method is safe for splicing a pipe +src+ into any type of +dst+ IO.
|
87
94
|
def self.full(src, dst, len, src_offset)
|
88
95
|
IO.splice(src, src_offset, dst, nil, len, F_MOVE | WAITALL)
|
89
96
|
end
|
@@ -94,16 +101,15 @@ module IO::Splice
|
|
94
101
|
# Returns the number of bytes actually spliced.
|
95
102
|
# Like IO#readpartial, this never returns Errno::EAGAIN
|
96
103
|
def self.partial(src, dst, len, src_offset)
|
97
|
-
IO.
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
rv
|
104
|
+
case rv = IO.trysplice(src, src_offset, dst, nil, len, F_MOVE)
|
105
|
+
when :EAGAIN
|
106
|
+
src.to_io.wait
|
107
|
+
IO.select(nil, [dst])
|
108
|
+
when Integer
|
109
|
+
return rv
|
110
|
+
else
|
111
|
+
return nil
|
112
|
+
end while true
|
107
113
|
end
|
108
114
|
end
|
109
115
|
if (! defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby") &&
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'io/wait'
|
3
|
+
require 'io/splice'
|
4
|
+
require 'io/nonblock'
|
5
|
+
require "test/unit"
|
6
|
+
|
7
|
+
class TestTCPCopyStream < Test::Unit::TestCase
|
8
|
+
def setup
|
9
|
+
host = ENV["TEST_HOST"] || "127.0.0.1"
|
10
|
+
@srv = TCPServer.new(host, 0)
|
11
|
+
@port = @srv.addr[1]
|
12
|
+
@client = TCPSocket.new(host, @port)
|
13
|
+
@client.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
|
14
|
+
@accept = @srv.accept
|
15
|
+
@accept.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
|
16
|
+
@client.sync = @accept.sync = true
|
17
|
+
@r, @w = IO.pipe
|
18
|
+
end
|
19
|
+
|
20
|
+
def teardown
|
21
|
+
@srv.close
|
22
|
+
[ @client, @accept, @r, @w ].each { |io| io.close unless io.closed? }
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_client_to_server_eof
|
26
|
+
nr = 2000
|
27
|
+
buf = '0123456789abcdef' * 1024
|
28
|
+
expect = buf.size * nr
|
29
|
+
thr = Thread.new do
|
30
|
+
nr.times { @client.write(buf) }
|
31
|
+
@client.close
|
32
|
+
end
|
33
|
+
sleep 1 # wait for rcvbuf to fill up
|
34
|
+
bytes = IO::Splice.copy_stream(@accept, "/dev/null")
|
35
|
+
assert_equal expect, bytes
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_client_to_server_expect
|
39
|
+
nr = 2000
|
40
|
+
buf = '0123456789abcdef' * 1024
|
41
|
+
expect = buf.size * nr
|
42
|
+
thr = Thread.new do
|
43
|
+
nr.times { @client.write(buf) }
|
44
|
+
end
|
45
|
+
sleep 1 # wait for rcvbuf to fill up
|
46
|
+
bytes = IO::Splice.copy_stream(@accept, "/dev/null", expect)
|
47
|
+
assert_equal expect, bytes
|
48
|
+
end
|
49
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: io_splice
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 57
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 4
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 4.1.
|
9
|
+
- 1
|
10
|
+
version: 4.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ruby io_splice hackers
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-05-
|
18
|
+
date: 2011-05-18 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: wrongdoc
|
@@ -96,6 +96,7 @@ files:
|
|
96
96
|
- test/test_io_splice_eintr.rb
|
97
97
|
- test/test_io_splice_in_full.rb
|
98
98
|
- test/test_rack_file_compat.rb
|
99
|
+
- test/test_tcp_splice.rb
|
99
100
|
homepage: http://bogomips.org/ruby_io_splice/
|
100
101
|
licenses: []
|
101
102
|
|
@@ -135,6 +136,7 @@ summary: zero-copy pipe I/O for Linux and Ruby
|
|
135
136
|
test_files:
|
136
137
|
- test/test_rack_file_compat.rb
|
137
138
|
- test/test_io_splice_in_full.rb
|
139
|
+
- test/test_tcp_splice.rb
|
138
140
|
- test/test_io_splice.rb
|
139
141
|
- test/test_copy_stream.rb
|
140
142
|
- test/test_io_splice_eintr.rb
|