io_splice 4.1.0 → 4.1.1
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/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
|