sendfile 1.2.0 → 1.2.1

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