sendfile 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/sendfile.c +47 -5
- data/sendfile.gemspec +1 -1
- data/test/test_sendfile.rb +27 -0
- metadata +4 -4
data/ext/sendfile.c
CHANGED
@@ -43,6 +43,7 @@
|
|
43
43
|
#include <unistd.h>
|
44
44
|
#include <fcntl.h>
|
45
45
|
#include "config.h"
|
46
|
+
static VALUE sym_wait_writable;
|
46
47
|
|
47
48
|
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
|
48
49
|
/*
|
@@ -185,7 +186,7 @@ static off_t sendfile_full(struct sendfile_args *args)
|
|
185
186
|
return all - args->count;
|
186
187
|
}
|
187
188
|
|
188
|
-
static
|
189
|
+
static VALUE sendfile_nonblock(struct sendfile_args *args, int try)
|
189
190
|
{
|
190
191
|
ssize_t rv;
|
191
192
|
off_t before = args->count;
|
@@ -201,12 +202,18 @@ static off_t sendfile_nonblock(struct sendfile_args *args)
|
|
201
202
|
|
202
203
|
rv = (ssize_t)rb_thread_blocking_region(nogvl_sendfile, args,
|
203
204
|
RUBY_UBF_IO, NULL);
|
204
|
-
if (rv < 0)
|
205
|
+
if (rv < 0) {
|
206
|
+
if (try && errno == EAGAIN)
|
207
|
+
return sym_wait_writable;
|
205
208
|
rb_sys_fail("sendfile");
|
206
|
-
|
209
|
+
}
|
210
|
+
if (args->eof) {
|
211
|
+
if (try)
|
212
|
+
return Qnil;
|
207
213
|
rb_eof_error();
|
214
|
+
}
|
208
215
|
|
209
|
-
return before - args->count;
|
216
|
+
return OFFT2NUM(before - args->count);
|
210
217
|
}
|
211
218
|
|
212
219
|
static void convert_args(int argc, VALUE *argv, VALUE self,
|
@@ -287,7 +294,40 @@ static VALUE rb_io_sendfile_nonblock(int argc, VALUE *argv, VALUE self)
|
|
287
294
|
|
288
295
|
convert_args(argc, argv, self, &args);
|
289
296
|
|
290
|
-
return
|
297
|
+
return sendfile_nonblock(&args, 0);
|
298
|
+
}
|
299
|
+
|
300
|
+
/* call-seq:
|
301
|
+
* writeIO.trysendfile(readIO, offset=0, count=nil) => integer, nil, or
|
302
|
+
* :wait_writable
|
303
|
+
*
|
304
|
+
* Transfers count bytes starting at offset from readIO directly to writeIO
|
305
|
+
* without copying (i.e. invoking the kernel to do it for you).
|
306
|
+
*
|
307
|
+
* Unlike IO#sendfile, this will set the O_NONBLOCK flag on writeIO
|
308
|
+
* before calling sendfile(2) and will return :wait_writable instead
|
309
|
+
* of blocking. This method is intended for use with non-blocking
|
310
|
+
* event frameworks, including those that rely on Fibers.
|
311
|
+
*
|
312
|
+
* If offset is omitted, transfer starts at the beginning of the file.
|
313
|
+
*
|
314
|
+
* If count is omitted, the full length of the file will be sent.
|
315
|
+
*
|
316
|
+
* Returns the number of bytes sent on success, nil on EOF, and
|
317
|
+
* :wait_writable on EAGAIN. Will throw system error exception on error.
|
318
|
+
* (check man sendfile(2) on your platform for
|
319
|
+
* information on what errors could result and how to handle them)
|
320
|
+
*
|
321
|
+
* This method is a faster alternative to sendfile_nonblock as it does
|
322
|
+
* not raise exceptions on common EAGAIN errors.
|
323
|
+
*/
|
324
|
+
static VALUE rb_io_trysendfile(int argc, VALUE *argv, VALUE self)
|
325
|
+
{
|
326
|
+
struct sendfile_args args;
|
327
|
+
|
328
|
+
convert_args(argc, argv, self, &args);
|
329
|
+
|
330
|
+
return sendfile_nonblock(&args, 1);
|
291
331
|
}
|
292
332
|
|
293
333
|
/* Interface to the UNIX sendfile(2) system call. Should work on FreeBSD,
|
@@ -295,8 +335,10 @@ static VALUE rb_io_sendfile_nonblock(int argc, VALUE *argv, VALUE self)
|
|
295
335
|
*/
|
296
336
|
void Init_sendfile(void)
|
297
337
|
{
|
338
|
+
sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
|
298
339
|
rb_define_method(rb_cIO, "sendfile", rb_io_sendfile, -1);
|
299
340
|
rb_define_method(rb_cIO, "sendfile_nonblock",
|
300
341
|
rb_io_sendfile_nonblock, -1);
|
342
|
+
rb_define_method(rb_cIO, "trysendfile", rb_io_trysendfile, -1);
|
301
343
|
}
|
302
344
|
|
data/sendfile.gemspec
CHANGED
data/test/test_sendfile.rb
CHANGED
@@ -185,6 +185,26 @@ class TestSendfile < Test::Unit::TestCase
|
|
185
185
|
assert_equal nr_read, nr_sent
|
186
186
|
end
|
187
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
|
+
|
188
208
|
def test_tempfile
|
189
209
|
tmp = Tempfile.new ''
|
190
210
|
tmp.write @small_data
|
@@ -223,5 +243,12 @@ class TestSendfile < Test::Unit::TestCase
|
|
223
243
|
end
|
224
244
|
s.close
|
225
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
|
226
253
|
end # class TestSendfile
|
227
254
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sendfile
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 1.0.0
|
10
|
+
version: 1.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Toby DiPasquale
|
@@ -15,7 +15,7 @@ autorequire: sendfile
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2011-03-05 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|