io_splice 2.2.0 → 2.2.0.18.g3025
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +1 -0
- data/.gitignore +2 -0
- data/.wrongdoc.yml +5 -0
- data/GNUmakefile +7 -193
- data/README +2 -2
- data/Rakefile +20 -106
- data/ext/io_splice/io_splice_ext.c +129 -36
- data/io_splice.gemspec +12 -24
- data/lib/io/splice.rb +95 -101
- data/pkg.mk +168 -0
- data/test/test_io_splice.rb +99 -50
- metadata +37 -13
data/io_splice.gemspec
CHANGED
@@ -1,38 +1,26 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
|
-
|
3
2
|
ENV["VERSION"] or abort "VERSION= must be specified"
|
4
3
|
manifest = File.readlines('.manifest').map! { |x| x.chomp! }
|
5
|
-
|
4
|
+
require 'wrongdoc'
|
5
|
+
extend Wrongdoc::Gemspec
|
6
|
+
name, summary, title = readme_metadata
|
6
7
|
|
7
8
|
Gem::Specification.new do |s|
|
8
9
|
s.name = %q{io_splice}
|
9
|
-
s.version = ENV["VERSION"]
|
10
|
-
|
11
|
-
s.authors = ["io_splice hackers"]
|
10
|
+
s.version = ENV["VERSION"].dup
|
11
|
+
s.authors = ["Ruby io_splice hackers"]
|
12
12
|
s.date = Time.now.utc.strftime('%Y-%m-%d')
|
13
|
-
s.description =
|
13
|
+
s.description = readme_description
|
14
14
|
s.email = %q{ruby.io.splice@librelist.com}
|
15
15
|
s.extensions = %w(ext/io_splice/extconf.rb)
|
16
|
-
|
17
|
-
s.extra_rdoc_files = File.readlines('.document').map! do |x|
|
18
|
-
x.chomp!
|
19
|
-
if File.directory?(x)
|
20
|
-
manifest.grep(%r{\A#{x}/})
|
21
|
-
elsif File.file?(x)
|
22
|
-
x
|
23
|
-
else
|
24
|
-
nil
|
25
|
-
end
|
26
|
-
end.flatten.compact
|
27
|
-
|
16
|
+
s.extra_rdoc_files = extra_rdoc_files(manifest)
|
28
17
|
s.files = manifest
|
29
|
-
s.homepage =
|
30
|
-
s.summary =
|
31
|
-
s.rdoc_options =
|
32
|
-
s.require_paths = %w(lib)
|
18
|
+
s.homepage = Wrongdoc.config[:rdoc_url]
|
19
|
+
s.summary = summary
|
20
|
+
s.rdoc_options = rdoc_options
|
33
21
|
s.rubyforge_project = %q{qrp}
|
34
|
-
|
35
|
-
s.
|
22
|
+
s.test_files = Dir['test/test_*.rb']
|
23
|
+
s.add_development_dependency('wrongdoc', '~> 1.5')
|
36
24
|
|
37
25
|
# s.licenses = %w(LGPL) # accessor not compatible with older RubyGems
|
38
26
|
end
|
data/lib/io/splice.rb
CHANGED
@@ -1,120 +1,114 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
require 'io_splice_ext'
|
3
3
|
|
4
|
-
|
4
|
+
module IO::Splice
|
5
5
|
|
6
|
-
|
6
|
+
# the version of IO::Splice, currently 2.2.0
|
7
|
+
VERSION = '2.2.0'
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
rd.close
|
29
|
-
n
|
30
|
-
end
|
9
|
+
# The maximum default capacity of the pipe in bytes.
|
10
|
+
# Under stock Linux, this is 65536 bytes as of 2.6.11, and 4096 before
|
11
|
+
# We detect this at runtime as it is easy to recompile the kernel
|
12
|
+
# and set a new value.
|
13
|
+
# Starting with Linux 2.6.35, pipe capacity will be tunable
|
14
|
+
# and this will only represent the default capacity of a
|
15
|
+
# newly-created pipe.
|
16
|
+
PIPE_CAPA = begin
|
17
|
+
rd, wr = IO.pipe
|
18
|
+
buf = ' ' * PIPE_BUF
|
19
|
+
n = 0
|
20
|
+
begin
|
21
|
+
n += wr.write_nonblock(buf)
|
22
|
+
rescue Errno::EAGAIN
|
23
|
+
break
|
24
|
+
end while true
|
25
|
+
wr.close
|
26
|
+
rd.close
|
27
|
+
n
|
28
|
+
end
|
31
29
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
30
|
+
# copies the contents of the IO object given by +src+ to +dst+
|
31
|
+
# If +len+ is specified, then only +len+ bytes are copied and
|
32
|
+
# +EOFError+ is raised if fewer than +len+ bytes could be copied.
|
33
|
+
# Otherwise the copy will be until EOF is reached on the +src+.
|
34
|
+
# +src+ and +dst+ must be IO objects or respond to +to_io+
|
35
|
+
def self.copy_stream(src, dst, len = nil, src_offset = nil)
|
36
|
+
close = []
|
37
|
+
src.kind_of?(String) and close << (src = File.open(src))
|
38
|
+
dst.kind_of?(String) and close << (dst = File.open(dst, "w"))
|
39
|
+
src, dst = src.to_io, dst.to_io
|
40
|
+
rv = len
|
41
|
+
src.sysseek(src_offset) if src_offset
|
42
|
+
select_args = selectable(src, dst)
|
44
43
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
44
|
+
if src.stat.pipe? || dst.stat.pipe?
|
45
|
+
if len
|
46
|
+
len -= full(src, dst, len, select_args) until len == 0
|
47
|
+
else
|
48
|
+
rv = 0
|
49
|
+
while n = partial(src, dst, PIPE_CAPA, select_args)
|
50
|
+
rv += n
|
51
|
+
end
|
52
|
+
end
|
53
|
+
else
|
54
|
+
r, w = tmp = IO.pipe
|
55
|
+
close.concat(tmp)
|
56
|
+
if len
|
57
|
+
while len != 0 && n = partial(src, w, len, select_args)
|
58
|
+
len -= full(r, dst, n, select_args)
|
55
59
|
end
|
56
60
|
else
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
while len != 0
|
61
|
-
nr = partial(src, w, len, select_args)
|
62
|
-
len -= full(r, dst, nr, select_args)
|
63
|
-
end
|
64
|
-
else
|
65
|
-
rv = 0
|
66
|
-
begin
|
67
|
-
nr = partial(src, w, PIPE_CAPA, select_args)
|
68
|
-
rv += full(r, dst, nr, select_args)
|
69
|
-
rescue EOFError
|
70
|
-
break
|
71
|
-
end while true
|
61
|
+
rv = 0
|
62
|
+
while n = partial(src, w, PIPE_CAPA, select_args)
|
63
|
+
rv += full(r, dst, n, select_args)
|
72
64
|
end
|
73
65
|
end
|
74
|
-
|
75
|
-
rv
|
76
|
-
ensure
|
77
|
-
close.each { |io| io.close }
|
78
66
|
end
|
79
67
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
# bytes. Returns the nubmer of bytes actually spliced (always +len+)
|
85
|
-
# The +_select_args+ parameter is reserved for internal use and
|
86
|
-
# may be removed in future versions. Do not write code that
|
87
|
-
# depends on +_select_args+.
|
88
|
-
def Splice.full(src, dst, len, _select_args = selectable(src, dst))
|
89
|
-
nr = len
|
90
|
-
nr -= partial(src, dst, nr, _select_args) until nr == 0
|
91
|
-
len
|
92
|
-
end
|
68
|
+
rv
|
69
|
+
ensure
|
70
|
+
close.each { |io| io.close }
|
71
|
+
end
|
93
72
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
73
|
+
# splice the full amount specified from +src+ to +dst+
|
74
|
+
# Either +dst+ or +src+ must be a pipe. +dst+ and +src+
|
75
|
+
# may BOTH be pipes in Linux 2.6.31 or later.
|
76
|
+
# This will block and wait for IO completion of +len+
|
77
|
+
# Raises +EOFError+ if end of file is reached.
|
78
|
+
# bytes. Returns the number of bytes actually spliced (always +len+)
|
79
|
+
# The +_select_args+ parameter is reserved for internal use and
|
80
|
+
# may be removed in future versions. Do not write code that
|
81
|
+
# depends on +_select_args+.
|
82
|
+
def self.full(src, dst, len, _select_args = selectable(src, dst))
|
83
|
+
nr = len
|
84
|
+
while nr > 0
|
85
|
+
n = partial(src, dst, nr, _select_args) or
|
86
|
+
raise EOFError, "end of file reached"
|
87
|
+
nr -= n
|
109
88
|
end
|
89
|
+
len
|
90
|
+
end
|
110
91
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
92
|
+
# splice up to +len+ bytes from +src+ to +dst+.
|
93
|
+
# Either +dst+ or +src+ must be a pipe. +dst+ and +src+
|
94
|
+
# may BOTH be pipes in Linux 2.6.31 or later.
|
95
|
+
# Returns the number of bytes actually spliced.
|
96
|
+
# Like IO#readpartial, this never returns Errno::EAGAIN
|
97
|
+
# The +_select_args+ parameter is reserved for internal use and
|
98
|
+
# may be removed in future versions. Do not write code that
|
99
|
+
# depends on +_select_args+.
|
100
|
+
def self.partial(src, dst, len, _select_args = selectable(src, dst))
|
101
|
+
begin
|
102
|
+
rv = IO.trysplice(src, nil, dst, nil, len, F_MOVE)
|
103
|
+
end while rv == :EAGAIN and IO.select(*_select_args)
|
104
|
+
rv
|
105
|
+
end
|
118
106
|
|
107
|
+
# returns an array suitable for splat-ing to IO.select for blocking I/O
|
108
|
+
def self.selectable(src, dst)
|
109
|
+
rv = []
|
110
|
+
src.stat.pipe? or rv[0] = [ src ]
|
111
|
+
dst.stat.pipe? or rv[1] = [ dst ]
|
112
|
+
rv
|
119
113
|
end
|
120
114
|
end
|
data/pkg.mk
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
RUBY = ruby
|
2
|
+
RAKE = rake
|
3
|
+
RSYNC = rsync
|
4
|
+
WRONGDOC = wrongdoc
|
5
|
+
|
6
|
+
GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
|
7
|
+
@./GIT-VERSION-GEN
|
8
|
+
-include GIT-VERSION-FILE
|
9
|
+
-include local.mk
|
10
|
+
DLEXT := $(shell $(RUBY) -rrbconfig -e 'puts RbConfig::CONFIG["DLEXT"]')
|
11
|
+
RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
|
12
|
+
RUBY_ENGINE := $(shell $(RUBY) -e 'puts((RUBY_ENGINE rescue "ruby"))')
|
13
|
+
lib := lib
|
14
|
+
|
15
|
+
ifeq ($(shell test -f script/isolate_for_tests && echo t),t)
|
16
|
+
isolate_libs := tmp/isolate/$(RUBY_ENGINE)-$(RUBY_VERSION)/isolate.mk
|
17
|
+
$(isolate_libs): script/isolate_for_tests
|
18
|
+
@$(RUBY) script/isolate_for_tests
|
19
|
+
-include $(isolate_libs)
|
20
|
+
lib := $(lib):$(ISOLATE_LIBS)
|
21
|
+
endif
|
22
|
+
|
23
|
+
ext := $(firstword $(wildcard ext/*))
|
24
|
+
ifneq ($(ext),)
|
25
|
+
ext_pfx := tmp/ext/$(RUBY_ENGINE)-$(RUBY_VERSION)
|
26
|
+
ext_h := $(wildcard $(ext)/*/*.h $(ext)/*.h)
|
27
|
+
ext_src := $(wildcard $(ext)/*.c $(ext_h))
|
28
|
+
ext_pfx_src := $(addprefix $(ext_pfx)/,$(ext_src))
|
29
|
+
ext_d := $(ext_pfx)/$(ext)/.d
|
30
|
+
$(ext)/extconf.rb: $(wildcard $(ext)/*.h)
|
31
|
+
@>> $@
|
32
|
+
$(ext_d):
|
33
|
+
@mkdir -p $(@D)
|
34
|
+
@> $@
|
35
|
+
$(ext_pfx)/$(ext)/%: $(ext)/% $(ext_d)
|
36
|
+
install -m 644 $< $@
|
37
|
+
$(ext_pfx)/$(ext)/Makefile: $(ext)/extconf.rb $(ext_d) $(ext_h)
|
38
|
+
$(RM) -f $(@D)/*.o
|
39
|
+
cd $(@D) && $(RUBY) $(CURDIR)/$(ext)/extconf.rb
|
40
|
+
ext_sfx := _ext.$(DLEXT)
|
41
|
+
ext_dl := $(ext_pfx)/$(ext)/$(notdir $(ext)_ext.$(DLEXT))
|
42
|
+
$(ext_dl): $(ext_src) $(ext_pfx_src) $(ext_pfx)/$(ext)/Makefile
|
43
|
+
@echo $^ == $@
|
44
|
+
$(MAKE) -C $(@D)
|
45
|
+
lib := $(lib):$(ext_pfx)/$(ext)
|
46
|
+
build: $(ext_dl)
|
47
|
+
endif
|
48
|
+
|
49
|
+
pkg_extra := GIT-VERSION-FILE NEWS ChangeLog LATEST
|
50
|
+
ChangeLog: GIT-VERSION-FILE .wrongdoc.yml
|
51
|
+
$(WRONGDOC) prepare
|
52
|
+
|
53
|
+
manifest:
|
54
|
+
$(RM) .manifest
|
55
|
+
$(MAKE) .manifest
|
56
|
+
|
57
|
+
.manifest: ChangeLog
|
58
|
+
(git ls-files && for i in $@ $(pkg_extra); do echo $$i; done) | \
|
59
|
+
LC_ALL=C sort > $@+
|
60
|
+
cmp $@+ $@ || mv $@+ $@
|
61
|
+
$(RM) $@+
|
62
|
+
|
63
|
+
doc:: .document .wrongdoc.yml
|
64
|
+
find lib -type f -name '*.rbc' -exec rm -f '{}' ';'
|
65
|
+
-find ext -type f -name '*.rbc' -exec rm -f '{}' ';'
|
66
|
+
$(RM) -r doc
|
67
|
+
$(WRONGDOC) all
|
68
|
+
install -m644 COPYING doc/COPYING
|
69
|
+
install -m644 $(shell grep '^[A-Z]' .document) doc/
|
70
|
+
|
71
|
+
ifneq ($(VERSION),)
|
72
|
+
pkggem := pkg/$(rfpackage)-$(VERSION).gem
|
73
|
+
pkgtgz := pkg/$(rfpackage)-$(VERSION).tgz
|
74
|
+
release_notes := release_notes-$(VERSION)
|
75
|
+
release_changes := release_changes-$(VERSION)
|
76
|
+
|
77
|
+
release-notes: $(release_notes)
|
78
|
+
release-changes: $(release_changes)
|
79
|
+
$(release_changes):
|
80
|
+
$(WRONGDOC) release_changes > $@+
|
81
|
+
$(VISUAL) $@+ && test -s $@+ && mv $@+ $@
|
82
|
+
$(release_notes):
|
83
|
+
$(WRONGDOC) release_notes > $@+
|
84
|
+
$(VISUAL) $@+ && test -s $@+ && mv $@+ $@
|
85
|
+
|
86
|
+
# ensures we're actually on the tagged $(VERSION), only used for release
|
87
|
+
verify:
|
88
|
+
test x"$(shell umask)" = x0022
|
89
|
+
git rev-parse --verify refs/tags/v$(VERSION)^{}
|
90
|
+
git diff-index --quiet HEAD^0
|
91
|
+
test $$(git rev-parse --verify HEAD^0) = \
|
92
|
+
$$(git rev-parse --verify refs/tags/v$(VERSION)^{})
|
93
|
+
|
94
|
+
fix-perms:
|
95
|
+
-git ls-tree -r HEAD | awk '/^100644 / {print $$NF}' | xargs chmod 644
|
96
|
+
-git ls-tree -r HEAD | awk '/^100755 / {print $$NF}' | xargs chmod 755
|
97
|
+
|
98
|
+
gem: $(pkggem)
|
99
|
+
|
100
|
+
install-gem: $(pkggem)
|
101
|
+
gem install $(CURDIR)/$<
|
102
|
+
|
103
|
+
$(pkggem): manifest fix-perms
|
104
|
+
gem build $(rfpackage).gemspec
|
105
|
+
mkdir -p pkg
|
106
|
+
mv $(@F) $@
|
107
|
+
|
108
|
+
$(pkgtgz): distdir = $(basename $@)
|
109
|
+
$(pkgtgz): HEAD = v$(VERSION)
|
110
|
+
$(pkgtgz): manifest fix-perms
|
111
|
+
@test -n "$(distdir)"
|
112
|
+
$(RM) -r $(distdir)
|
113
|
+
mkdir -p $(distdir)
|
114
|
+
tar cf - $$(cat .manifest) | (cd $(distdir) && tar xf -)
|
115
|
+
cd pkg && tar cf - $(basename $(@F)) | gzip -9 > $(@F)+
|
116
|
+
mv $@+ $@
|
117
|
+
|
118
|
+
package: $(pkgtgz) $(pkggem)
|
119
|
+
|
120
|
+
test-release:: verify package $(release_notes) $(release_changes)
|
121
|
+
# make tgz release on RubyForge
|
122
|
+
@echo rubyforge add_release -f \
|
123
|
+
-n $(release_notes) -a $(release_changes) \
|
124
|
+
$(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
|
125
|
+
@echo gem push $(pkggem)
|
126
|
+
@echo rubyforge add_file \
|
127
|
+
$(rfproject) $(rfpackage) $(VERSION) $(pkggem)
|
128
|
+
release:: verify package $(release_notes) $(release_changes)
|
129
|
+
# make tgz release on RubyForge
|
130
|
+
rubyforge add_release -f -n $(release_notes) -a $(release_changes) \
|
131
|
+
$(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
|
132
|
+
# push gem to RubyGems.org
|
133
|
+
gem push $(pkggem)
|
134
|
+
# in case of gem downloads from RubyForge releases page
|
135
|
+
rubyforge add_file \
|
136
|
+
$(rfproject) $(rfpackage) $(VERSION) $(pkggem)
|
137
|
+
else
|
138
|
+
gem install-gem: GIT-VERSION-FILE
|
139
|
+
$(MAKE) $@ VERSION=$(GIT_VERSION)
|
140
|
+
endif
|
141
|
+
|
142
|
+
all:: test
|
143
|
+
test_units := $(wildcard test/test_*.rb)
|
144
|
+
test: test-unit
|
145
|
+
test-unit: $(test_units)
|
146
|
+
$(test_units): build
|
147
|
+
$(RUBY) -I $(lib) $@
|
148
|
+
|
149
|
+
# this requires GNU coreutils variants
|
150
|
+
ifneq ($(RSYNC_DEST),)
|
151
|
+
publish_doc:
|
152
|
+
-git set-file-times
|
153
|
+
$(MAKE) doc
|
154
|
+
find doc/images -type f | \
|
155
|
+
TZ=UTC xargs touch -d '1970-01-01 00:00:06' doc/rdoc.css
|
156
|
+
$(MAKE) doc_gz
|
157
|
+
$(RSYNC) -av doc/ $(RSYNC_DEST)/
|
158
|
+
git ls-files | xargs touch
|
159
|
+
endif
|
160
|
+
|
161
|
+
# Create gzip variants of the same timestamp as the original so nginx
|
162
|
+
# "gzip_static on" can serve the gzipped versions directly.
|
163
|
+
doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
|
164
|
+
doc_gz:
|
165
|
+
for i in $(docs); do \
|
166
|
+
gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
|
167
|
+
|
168
|
+
.PHONY: all .FORCE-GIT-VERSION-FILE doc test $(test_units) manifest
|
data/test/test_io_splice.rb
CHANGED
@@ -7,48 +7,6 @@ require 'timeout'
|
|
7
7
|
$-w = true
|
8
8
|
require 'io/splice'
|
9
9
|
|
10
|
-
# unused_port provides an unused port on +addr+ usable for TCP that is
|
11
|
-
# guaranteed to be unused across all unicorn builds on that system. It
|
12
|
-
# prevents race conditions by using a lock file other unicorn builds
|
13
|
-
# will see. This is required if you perform several builds in parallel
|
14
|
-
# with a continuous integration system or run tests in parallel via
|
15
|
-
# gmake. This is NOT guaranteed to be race-free if you run other
|
16
|
-
# processes that bind to random ports for testing (but the window
|
17
|
-
# for a race condition is very small).
|
18
|
-
def unused_port(addr = '127.0.0.1')
|
19
|
-
retries = 100
|
20
|
-
base = 5000
|
21
|
-
port = sock = nil
|
22
|
-
begin
|
23
|
-
begin
|
24
|
-
port = base + rand(32768 - base)
|
25
|
-
while port == 8080
|
26
|
-
port = base + rand(32768 - base)
|
27
|
-
end
|
28
|
-
|
29
|
-
sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
30
|
-
sock.bind(Socket.pack_sockaddr_in(port, addr))
|
31
|
-
sock.listen(5)
|
32
|
-
rescue Errno::EADDRINUSE, Errno::EACCES
|
33
|
-
sock.close rescue nil
|
34
|
-
retry if (retries -= 1) >= 0
|
35
|
-
end
|
36
|
-
|
37
|
-
# since we'll end up closing the random port we just got, there's a race
|
38
|
-
# condition could allow the random port we just chose to reselect itself
|
39
|
-
# when running tests in parallel with gmake. Create a lock file while
|
40
|
-
# we have the port here to ensure that does not happen .
|
41
|
-
lock_path = "#{Dir::tmpdir}/unicorn_test.#{addr}:#{port}.lock"
|
42
|
-
lock = File.open(lock_path, File::WRONLY|File::CREAT|File::EXCL, 0600)
|
43
|
-
at_exit { File.unlink(lock_path) rescue nil }
|
44
|
-
rescue Errno::EEXIST
|
45
|
-
sock.close rescue nil
|
46
|
-
retry
|
47
|
-
end
|
48
|
-
sock.close rescue nil
|
49
|
-
port
|
50
|
-
end
|
51
|
-
|
52
10
|
class Test_IO_Splice < Test::Unit::TestCase
|
53
11
|
|
54
12
|
def test_splice
|
@@ -83,6 +41,38 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
83
41
|
assert_equal str, rd.sysread(size)
|
84
42
|
end
|
85
43
|
|
44
|
+
def test_splice_io_noflags
|
45
|
+
str = 'abcde'
|
46
|
+
size = 5
|
47
|
+
rd, wr = IO.pipe
|
48
|
+
tmp = Tempfile.new('ruby_io_splice')
|
49
|
+
|
50
|
+
assert_nothing_raised {
|
51
|
+
tmp.syswrite(str)
|
52
|
+
tmp.sysseek(0)
|
53
|
+
}
|
54
|
+
|
55
|
+
nr = IO.splice(tmp, nil, wr, nil, size)
|
56
|
+
assert_equal size, nr
|
57
|
+
assert_equal str, rd.sysread(size)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_trysplice_io_noflags
|
61
|
+
str = 'abcde'
|
62
|
+
size = 5
|
63
|
+
rd, wr = IO.pipe
|
64
|
+
tmp = Tempfile.new('ruby_io_splice')
|
65
|
+
|
66
|
+
assert_nothing_raised {
|
67
|
+
tmp.syswrite(str)
|
68
|
+
tmp.sysseek(0)
|
69
|
+
}
|
70
|
+
|
71
|
+
nr = IO.trysplice(tmp, nil, wr, nil, size)
|
72
|
+
assert_equal size, nr
|
73
|
+
assert_equal str, rd.sysread(size)
|
74
|
+
end
|
75
|
+
|
86
76
|
def test_splice_io_ish
|
87
77
|
str = 'abcde'
|
88
78
|
size = 5
|
@@ -141,6 +131,20 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
141
131
|
}
|
142
132
|
end
|
143
133
|
|
134
|
+
def test_trysplice_nonblock
|
135
|
+
rd, wr = IO.pipe
|
136
|
+
tmp = Tempfile.new('ruby_io_splice')
|
137
|
+
assert_equal :EAGAIN,
|
138
|
+
IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_NONBLOCK)
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_trysplice_nonblock_noargs
|
142
|
+
rd, wr = IO.pipe
|
143
|
+
tmp = Tempfile.new('ruby_io_splice')
|
144
|
+
assert_equal :EAGAIN, IO.trysplice(rd, nil, tmp, 0, 5)
|
145
|
+
assert_equal :EAGAIN, IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_MORE)
|
146
|
+
end
|
147
|
+
|
144
148
|
def test_splice_eof
|
145
149
|
rd, wr = IO.pipe
|
146
150
|
tmp = Tempfile.new('ruby_io_splice')
|
@@ -154,9 +158,20 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
154
158
|
}
|
155
159
|
end
|
156
160
|
|
161
|
+
def test_trysplice_eof
|
162
|
+
rd, wr = IO.pipe
|
163
|
+
tmp = Tempfile.new('ruby_io_splice')
|
164
|
+
wr.syswrite 'abc'
|
165
|
+
wr.close
|
166
|
+
|
167
|
+
nr = IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_NONBLOCK)
|
168
|
+
assert_equal 3, nr
|
169
|
+
assert_nil IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_NONBLOCK)
|
170
|
+
end
|
171
|
+
|
157
172
|
def test_splice_nonblock_socket
|
158
|
-
|
159
|
-
|
173
|
+
server = TCPServer.new('127.0.0.1', 0)
|
174
|
+
port = server.addr[1]
|
160
175
|
rp, wp = IO.pipe
|
161
176
|
rs = TCPSocket.new('127.0.0.1', port)
|
162
177
|
rs.nonblock = true
|
@@ -178,6 +193,19 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
178
193
|
assert_equal str, rda.sysread(5)
|
179
194
|
end
|
180
195
|
|
196
|
+
def test_trytee
|
197
|
+
str = 'abcde'
|
198
|
+
size = 5
|
199
|
+
rda, wra = IO.pipe
|
200
|
+
rdb, wrb = IO.pipe
|
201
|
+
|
202
|
+
assert_nothing_raised { wra.syswrite(str) }
|
203
|
+
nr = IO.trytee(rda, wrb, size, 0)
|
204
|
+
assert_equal 5, nr
|
205
|
+
assert_equal str, rdb.sysread(5)
|
206
|
+
assert_equal str, rda.sysread(5)
|
207
|
+
end
|
208
|
+
|
181
209
|
def test_tee_eof
|
182
210
|
rda, wra = IO.pipe
|
183
211
|
rdb, wrb = IO.pipe
|
@@ -185,6 +213,13 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
185
213
|
assert_raises(EOFError) { IO.tee(rda.fileno, wrb.fileno, 4096, 0) }
|
186
214
|
end
|
187
215
|
|
216
|
+
def test_trytee_eof
|
217
|
+
rda, wra = IO.pipe
|
218
|
+
rdb, wrb = IO.pipe
|
219
|
+
wra.close
|
220
|
+
assert_nil IO.trytee(rda, wrb, 4096)
|
221
|
+
end
|
222
|
+
|
188
223
|
def test_tee_nonblock
|
189
224
|
rda, wra = IO.pipe
|
190
225
|
rdb, wrb = IO.pipe
|
@@ -193,6 +228,12 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
193
228
|
}
|
194
229
|
end
|
195
230
|
|
231
|
+
def test_trytee_nonblock
|
232
|
+
rda, wra = IO.pipe
|
233
|
+
rdb, wrb = IO.pipe
|
234
|
+
assert_equal :EAGAIN, IO.trytee(rda, wrb, 4096)
|
235
|
+
end
|
236
|
+
|
196
237
|
def test_tee_io
|
197
238
|
str = 'abcde'
|
198
239
|
size = 5
|
@@ -214,6 +255,14 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
214
255
|
assert_equal data.join(''), r.readpartial(16384)
|
215
256
|
end
|
216
257
|
|
258
|
+
def test_vmsplice_noflags
|
259
|
+
data = %w(hello world how are you today)
|
260
|
+
r, w = IO.pipe
|
261
|
+
n = IO.vmsplice(w, data)
|
262
|
+
assert_equal data.join('').size, n
|
263
|
+
assert_equal data.join(''), r.readpartial(16384)
|
264
|
+
end
|
265
|
+
|
217
266
|
def test_vmsplice_string
|
218
267
|
r, w = IO.pipe
|
219
268
|
assert_equal 5, IO.vmsplice(w, 'hello', 0)
|
@@ -344,8 +393,8 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
344
393
|
end
|
345
394
|
|
346
395
|
def test_copy_stream_nonblock_src
|
347
|
-
|
348
|
-
|
396
|
+
server = TCPServer.new('127.0.0.1', 0)
|
397
|
+
port = server.addr[1]
|
349
398
|
rp, wp = IO.pipe
|
350
399
|
rs = TCPSocket.new('127.0.0.1', port)
|
351
400
|
rs.nonblock = true
|
@@ -359,8 +408,8 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
359
408
|
end
|
360
409
|
|
361
410
|
def test_copy_stream_nonblock_dst
|
362
|
-
|
363
|
-
|
411
|
+
server = TCPServer.new('127.0.0.1', 0)
|
412
|
+
port = server.addr[1]
|
364
413
|
rp, wp = IO.pipe
|
365
414
|
rs = TCPSocket.new('127.0.0.1', port)
|
366
415
|
rs.nonblock = true
|
@@ -395,10 +444,10 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
395
444
|
|
396
445
|
def test_pipe_size
|
397
446
|
r, w = IO.pipe
|
398
|
-
|
447
|
+
assert_kind_of Integer, r.pipe_size
|
399
448
|
assert(r.pipe_size >= 512)
|
400
449
|
assert_nothing_raised { w.pipe_size = 8192 }
|
401
|
-
|
450
|
+
assert_equal 8192, r.pipe_size
|
402
451
|
|
403
452
|
w.write('*' * 4097)
|
404
453
|
assert_raises(Errno::EBUSY) { r.pipe_size = 4096 }
|