sendfile 1.0.0 → 1.1.0
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/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
|
|