sendfile 1.2.0 → 1.2.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.
@@ -157,15 +157,16 @@ static VALUE nogvl_sendfile(void *data)
157
157
  {
158
158
  struct sendfile_args *args = data;
159
159
  int rv;
160
- off_t written;
161
- size_t w = count_max(args->count);
160
+ off_t written = args->count;
162
161
 
163
- rv = sendfile(args->in, args->out, args->off, args->count,
162
+ rv = sendfile(args->in, args->out, args->off, &written,
164
163
  NULL, 0);
165
- if (rv == 0)
164
+ if (written == 0 && rv == 0) {
166
165
  args->eof = 1;
167
- if (rv > 0)
168
- args->count -= rv;
166
+ } else {
167
+ args->off += written;
168
+ args->count -= written;
169
+ }
169
170
 
170
171
  return (VALUE)rv;
171
172
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  spec = Gem::Specification.new do |gs|
4
4
  gs.name = 'sendfile'
5
- gs.version = '1.2.0'
5
+ gs.version = '1.2.1'
6
6
  gs.summary = 'Ruby interface to sendfile(2) system call'
7
7
  gs.description = <<-EOF
8
8
  Allows Ruby programs to access sendfile(2) functionality on
@@ -2,253 +2,251 @@
2
2
  # vim:set ts=4 sw=4 ai:
3
3
  require 'io/nonblock'
4
4
  begin
5
- require 'rubygems'
5
+ require 'rubygems'
6
6
  rescue
7
- nil
7
+ nil
8
8
  end
9
9
  require 'sendfile'
10
10
  require 'socket'
11
11
  require 'tempfile'
12
- require 'test/unit'
12
+ require "minitest/autorun"
13
+ require 'minitest'
13
14
  require 'zlib'
14
15
 
15
- class TestSendfile < Test::Unit::TestCase
16
- def __fork_server
17
- # open pipe for backchannel
18
- @rd, @wr = IO.pipe
19
- # fork server child
20
- @pid = fork do
21
- # close read end in child
22
- @rd.close
23
-
24
- # start listening and send port back to parent
25
- ss = TCPServer.new @host, 0
26
- @wr.write( [ ss.addr[1] ].pack( "S"))
27
- @wr.flush
28
-
29
- # read what they send and push it back up the pipe
30
- while s = ss.accept
31
- data = s.read
32
- s.close
33
- @wr.write( [data.length].pack( "N"))
34
- @wr.write data
35
- @wr.flush
36
- end
37
- end
38
-
39
- # close write end in parent and get server port
40
- @wr.close
41
- @port = @rd.read( 2).unpack( "S")[0]
42
- end
43
-
44
- def setup
45
- @dir = File.dirname __FILE__
46
- @host = '127.0.0.1'
47
- __fork_server
48
-
49
- @smallfile = "#{@dir}/small"
50
- @small = File.open @smallfile
51
- @small_data = File.read @smallfile
52
-
53
- File.open( "#{@dir}/large.gz") do |f|
54
- gzipped = Zlib::GzipReader.new f
55
- @large_data = gzipped.read
56
- end
57
- @largefile = "/tmp/sendfiletest"
58
- @large = File.open @largefile, 'w+'
59
- @large.write @large_data
60
- @large.flush
61
- end
62
-
63
- def teardown
64
- @small.close
65
- @large.close
66
- File.unlink @largefile
67
-
68
- Process.kill 'KILL', @pid
69
- Process.wait
70
- end
71
-
72
- def __do_sendfile file, off=nil, count=nil
73
- s = TCPSocket.new @host, @port
74
- yield s if block_given?
75
- sent = s.sendfile file, off, count
76
- s.close
77
- len = @rd.read( 4).unpack( "N")[0]
78
- read = @rd.read len
79
- [ sent, read ]
80
- end
81
-
82
- def test_blocking_full_small
83
- sent, read = __do_sendfile( @small)
84
- assert_equal @small_data.size, sent
85
- assert_equal @small_data.size, read.size
86
- assert_equal @small_data, read
87
- end
88
-
89
- def test_nonblocking_full_small
90
- sent, read = __do_sendfile( @small) { |s| s.nonblock = true }
91
- assert_equal @small_data.size, sent
92
- assert_equal @small_data.size, read.size
93
- assert_equal @small_data, read
94
- end
95
-
96
- def test_blocking_full_large
97
- sent, read = __do_sendfile( @large)
98
- assert_equal @large_data.size, sent
99
- assert_equal @large_data.size, read.size
100
- assert_equal @large_data, read
101
- end
102
-
103
- def test_nonblocking_full_large
104
- sent, read = __do_sendfile( @large) { |s| s.nonblock = true }
105
- assert_equal @large_data.size, sent
106
- assert_equal @large_data.size, read.size
107
- assert_equal @large_data, read
108
- end
109
-
110
- def test_blocking_from_offset
111
- data = @large_data[4096..-1]
112
- sent, read = __do_sendfile( @large, 4096)
113
- assert_equal data.size, sent
114
- assert_equal data.size, read.size
115
- assert_equal data, read
116
- end
117
-
118
- def test_blocking_partial_from_beginning
119
- data = @large_data[0, 1048576]
120
- sent, read = __do_sendfile( @large, 0, 1048576)
121
- assert_equal data.size, sent
122
- assert_equal data.size, read.size
123
- assert_equal data, read
124
- end
125
-
126
- def test_blocking_partial_from_middle
127
- data = @large_data[2048, 1048576]
128
- sent, read = __do_sendfile( @large, 2048, 1048576)
129
- assert_equal data.size, sent
130
- assert_equal data.size, read.size
131
- assert_equal data, read
132
- end
133
-
134
- def test_blocking_partial_to_end
135
- data = @large_data[-1048576, 1048576]
136
- sent, read = __do_sendfile( @large, @large_data.size - 1048576, 1048576)
137
- assert_equal data.size, sent
138
- assert_equal data.size, read.size
139
- assert_equal data, read
140
- end
141
-
142
- def test_nonblocking_from_offset
143
- data = @large_data[4096..-1]
144
- sent, read = __do_sendfile( @large, 4096) { |s| s.nonblock = true }
145
- assert_equal data.size, sent
146
- assert_equal data.size, read.size
147
- assert_equal data, read
148
- end
149
-
150
- def test_nonblocking_partial_from_beginning
151
- data = @large_data[0, 1048576]
152
- sent, read = __do_sendfile( @large, 0, 1048576) { |s| s.nonblock = true }
153
- assert_equal data.size, sent
154
- assert_equal data.size, read.size
155
- assert_equal data, read
156
- end
157
-
158
- def test_nonblocking_partial_from_middle
159
- data = @large_data[2048, 1048576]
160
- sent, read = __do_sendfile( @large, 2048, 1048576) { |s| s.nonblock = true }
161
- assert_equal data.size, sent
162
- assert_equal data.size, read.size
163
- assert_equal data, read
164
- end
165
-
166
- def test_nonblocking_partial_to_end
167
- data = @large_data[-1048576, 1048576]
168
- sent, read = __do_sendfile( @large, @large_data.size - 1048576, 1048576) { |s| s.nonblock = true }
169
- assert_equal data.size, sent
170
- assert_equal data.size, read.size
171
- assert_equal data, read
172
- end
173
-
174
- def test_sendfile_nonblock
175
- c, s = UNIXSocket.pair
176
- nr_sent = 0
177
- assert_raises(Errno::EAGAIN) do
178
- loop do
179
- nr_sent += c.sendfile_nonblock @small
180
- end
181
- end
182
- c.close
183
- nr_read = s.read.size
184
- s.close
185
- assert_equal nr_read, nr_sent
186
- end
187
-
188
- def test_trysendfile
189
- c, s = UNIXSocket.pair
190
- nr_sent = 0
191
- assert_nothing_raised do
192
- case rv = c.trysendfile(@small)
193
- when :wait_writable
194
- break
195
- when Integer
196
- nr_sent += rv
197
- else
198
- raise "Unexpected return: #{rv.inspect}"
199
- end while true
200
- end
201
- assert nr_sent > 0, "nr_sent: #{nr_sent} <= 0"
202
- c.close
203
- nr_read = s.read.size
204
- s.close
205
- assert_equal nr_read, nr_sent
206
- end
207
-
208
- def test_tempfile
209
- tmp = Tempfile.new ''
210
- tmp.write @small_data
211
- tmp.rewind
212
- sent, read = __do_sendfile(tmp)
213
- assert_equal @small_data.size, sent
214
- assert_equal @small_data.size, read.size
215
- assert_equal @small_data, read
216
- end
217
-
218
- def test_invalid_file
219
- assert_raises(TypeError) { __do_sendfile(:hello) }
220
- end
221
-
222
- def test_sendfile_too_big_eof
223
- sent = read = nil
224
- count = @small_data.size * 2
225
- s = TCPSocket.new @host, @port
226
- sent = s.sendfile @small, nil, count
227
- assert_raises(EOFError) do
228
- s.sendfile @small, sent, 1
229
- end
230
- s.close
231
- len = @rd.read( 4).unpack( "N")[0]
232
- read = @rd.read len
233
- assert_equal @small_data.size, sent
234
- assert_equal @small_data.size, read.size
235
- assert_equal @small_data, read
236
- end
237
-
238
- def test_sendfile_nonblock_eof
239
- s = TCPSocket.new @host, @port
240
- off = @small_data.size
241
- assert_raises(EOFError) do
242
- s.sendfile_nonblock @small, off, 1
243
- end
244
- s.close
245
- end
246
-
247
- def test_trysendfile_eof
248
- s = TCPSocket.new @host, @port
249
- off = @small_data.size
250
- assert_nil s.trysendfile(@small, off, 1)
251
- s.close
252
- end
253
- end # class TestSendfile
254
-
16
+ class TestSendfile < MiniTest::Test
17
+ def __fork_server
18
+ # open pipe for backchannel
19
+ @rd, @wr = IO.pipe
20
+ # fork server child
21
+ @pid = fork do
22
+ # close read end in child
23
+ @rd.close
24
+
25
+ # start listening and send port back to parent
26
+ ss = TCPServer.new @host, 0
27
+ @wr.write( [ ss.addr[1] ].pack( "S"))
28
+ @wr.flush
29
+
30
+ # read what they send and push it back up the pipe
31
+ while s = ss.accept
32
+ data = s.read
33
+ s.close
34
+ @wr.write( [data.length].pack( "N"))
35
+ @wr.write data
36
+ @wr.flush
37
+ end
38
+ end
39
+
40
+ # close write end in parent and get server port
41
+ @wr.close
42
+ @port = @rd.read( 2).unpack( "S")[0]
43
+ end
44
+
45
+ def setup
46
+ @dir = File.dirname __FILE__
47
+ @host = '127.0.0.1'
48
+ __fork_server
49
+
50
+ @smallfile = "#{@dir}/small"
51
+ @small = File.open @smallfile
52
+ @small_data = File.read @smallfile
53
+
54
+ File.open( "#{@dir}/large.gz") do |f|
55
+ gzipped = Zlib::GzipReader.new f
56
+ @large_data = gzipped.read
57
+ end
58
+ @largefile = "/tmp/sendfiletest"
59
+ @large = File.open @largefile, 'w+'
60
+ @large.write @large_data
61
+ @large.flush
62
+ end
63
+
64
+ def teardown
65
+ @small.close
66
+ @large.close
67
+ File.unlink @largefile
68
+
69
+ Process.kill 'KILL', @pid
70
+ Process.wait
71
+ end
72
+
73
+ def __do_sendfile file, off=nil, count=nil
74
+ s = TCPSocket.new @host, @port
75
+ yield s if block_given?
76
+ sent = s.sendfile file, off, count
77
+ s.close
78
+ len = @rd.read( 4).unpack( "N")[0]
79
+ read = @rd.read len
80
+ [ sent, read ]
81
+ end
82
+
83
+ def test_blocking_full_small
84
+ sent, read = __do_sendfile( @small)
85
+ assert_equal @small_data.size, sent
86
+ assert_equal @small_data.size, read.size
87
+ assert_equal @small_data, read
88
+ end
89
+
90
+ def test_nonblocking_full_small
91
+ sent, read = __do_sendfile( @small) { |s| s.nonblock = true }
92
+ assert_equal @small_data.size, sent
93
+ assert_equal @small_data.size, read.size
94
+ assert_equal @small_data, read
95
+ end
96
+
97
+ def test_blocking_full_large
98
+ sent, read = __do_sendfile( @large)
99
+ assert_equal @large_data.size, sent
100
+ assert_equal @large_data.size, read.size
101
+ assert_equal @large_data, read
102
+ end
103
+
104
+ def test_nonblocking_full_large
105
+ sent, read = __do_sendfile( @large) { |s| s.nonblock = true }
106
+ assert_equal @large_data.size, sent
107
+ assert_equal @large_data.size, read.size
108
+ assert_equal @large_data, read
109
+ end
110
+
111
+ def test_blocking_from_offset
112
+ data = @large_data[4096..-1]
113
+ sent, read = __do_sendfile( @large, 4096)
114
+ assert_equal data.size, sent
115
+ assert_equal data.size, read.size
116
+ assert_equal data, read
117
+ end
118
+
119
+ def test_blocking_partial_from_beginning
120
+ data = @large_data[0, 1048576]
121
+ sent, read = __do_sendfile( @large, 0, 1048576)
122
+ assert_equal data.size, sent
123
+ assert_equal data.size, read.size
124
+ assert_equal data, read
125
+ end
126
+
127
+ def test_blocking_partial_from_middle
128
+ data = @large_data[2048, 1048576]
129
+ sent, read = __do_sendfile( @large, 2048, 1048576)
130
+ assert_equal data.size, sent
131
+ assert_equal data.size, read.size
132
+ assert_equal data, read
133
+ end
134
+
135
+ def test_blocking_partial_to_end
136
+ data = @large_data[-1048576, 1048576]
137
+ sent, read = __do_sendfile( @large, @large_data.size - 1048576, 1048576)
138
+ assert_equal data.size, sent
139
+ assert_equal data.size, read.size
140
+ assert_equal data, read
141
+ end
142
+
143
+ def test_nonblocking_from_offset
144
+ data = @large_data[4096..-1]
145
+ sent, read = __do_sendfile( @large, 4096) { |s| s.nonblock = true }
146
+ assert_equal data.size, sent
147
+ assert_equal data.size, read.size
148
+ assert_equal data, read
149
+ end
150
+
151
+ def test_nonblocking_partial_from_beginning
152
+ data = @large_data[0, 1048576]
153
+ sent, read = __do_sendfile( @large, 0, 1048576) { |s| s.nonblock = true }
154
+ assert_equal data.size, sent
155
+ assert_equal data.size, read.size
156
+ assert_equal data, read
157
+ end
158
+
159
+ def test_nonblocking_partial_from_middle
160
+ data = @large_data[2048, 1048576]
161
+ sent, read = __do_sendfile( @large, 2048, 1048576) { |s| s.nonblock = true }
162
+ assert_equal data.size, sent
163
+ assert_equal data.size, read.size
164
+ assert_equal data, read
165
+ end
166
+
167
+ def test_nonblocking_partial_to_end
168
+ data = @large_data[-1048576, 1048576]
169
+ sent, read = __do_sendfile( @large, @large_data.size - 1048576, 1048576) { |s| s.nonblock = true }
170
+ assert_equal data.size, sent
171
+ assert_equal data.size, read.size
172
+ assert_equal data, read
173
+ end
174
+
175
+ def test_sendfile_nonblock
176
+ c, s = UNIXSocket.pair
177
+ nr_sent = 0
178
+ assert_raises(Errno::EAGAIN) do
179
+ loop do
180
+ nr_sent += c.sendfile_nonblock @small
181
+ end
182
+ end
183
+ c.close
184
+ nr_read = s.read.size
185
+ s.close
186
+ assert_equal nr_read, nr_sent
187
+ end
188
+
189
+ def test_trysendfile
190
+ c, s = UNIXSocket.pair
191
+ nr_sent = 0
192
+ case rv = c.trysendfile(@small)
193
+ when :wait_writable
194
+ break
195
+ when Integer
196
+ nr_sent += rv
197
+ else
198
+ raise "Unexpected return: #{rv.inspect}"
199
+ end while true
200
+ assert nr_sent > 0, "nr_sent: #{nr_sent} <= 0"
201
+ c.close
202
+ nr_read = s.read.size
203
+ s.close
204
+ assert_equal nr_read, nr_sent
205
+ end
206
+
207
+ def test_tempfile
208
+ tmp = Tempfile.new ''
209
+ tmp.write @small_data
210
+ tmp.rewind
211
+ sent, read = __do_sendfile(tmp)
212
+ assert_equal @small_data.size, sent
213
+ assert_equal @small_data.size, read.size
214
+ assert_equal @small_data, read
215
+ end
216
+
217
+ def test_invalid_file
218
+ assert_raises(TypeError) { __do_sendfile(:hello) }
219
+ end
220
+
221
+ def test_sendfile_too_big_eof
222
+ sent = read = nil
223
+ count = @small_data.size * 2
224
+ s = TCPSocket.new @host, @port
225
+ sent = s.sendfile @small, nil, count
226
+ assert_raises(EOFError) do
227
+ s.sendfile @small, sent, 1
228
+ end
229
+ s.close
230
+ len = @rd.read( 4).unpack( "N")[0]
231
+ read = @rd.read len
232
+ assert_equal @small_data.size, sent
233
+ assert_equal @small_data.size, read.size
234
+ assert_equal @small_data, read
235
+ end
236
+
237
+ def test_sendfile_nonblock_eof
238
+ s = TCPSocket.new @host, @port
239
+ off = @small_data.size
240
+ assert_raises(EOFError) do
241
+ s.sendfile_nonblock @small, off, 1
242
+ end
243
+ s.close
244
+ end
245
+
246
+ def test_trysendfile_eof
247
+ s = TCPSocket.new @host, @port
248
+ off = @small_data.size
249
+ assert_nil s.trysendfile(@small, off, 1)
250
+ s.close
251
+ end
252
+ end # class TestSendfile
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sendfile
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-30 00:00:00.000000000 Z
12
+ date: 2013-07-01 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: ! "Allows Ruby programs to access sendfile(2) functionality on \nany
15
15
  IO object. Works on Linux, Solaris, FreeBSD and Darwin with\nblocking and non-blocking