Class: IO

Inherits:
Object
  • Object
show all
Defined in:
(unknown)

Defined Under Namespace

Modules: Splice

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.splice(io_in, off_in, io_out, off_out, len) ⇒ Integer .splice(io_in, off_in, io_out, off_out, len, flags) ⇒ Integer

Splice len bytes from/to a pipe. Either io_in or io_out MUST be a pipe. io_in and io_out may BOTH be pipes as of Linux 2.6.31 or later.

off_in and off_out if non-nil may be used to specify an offset for the non-pipe file descriptor.

flags defaults to zero if unspecified. flags may be a bitmask of the following flags:

  • IO::Splice::F_MOVE

  • IO::Splice::F_NONBLOCK

  • IO::Splice::F_MORE

  • IO::Splice::WAITALL

Returns the number of bytes spliced. Raises EOFError when io_in has reached end of file. Raises Errno::EAGAIN if the IO::Splice::F_NONBLOCK flag is set and the pipe has no data to read from or space to write to. May also raise Errno::EAGAIN if the non-pipe descriptor has no data to read from or space to write to.

As splice never exposes buffers to userspace, it will not take into account userspace buffering done by Ruby or stdio. It is also not subject to encoding/decoding filters under Ruby 1.9.

Consider using IO.trysplice if you are using non-blocking I/O on both descriptors as it avoids the cost of raising common Errno::EAGAIN exceptions.

See manpage for full documentation: kernel.org/doc/man-pages/online/pages/man2/splice.2.html

Overloads:

  • .splice(io_in, off_in, io_out, off_out, len) ⇒ Integer

    Returns:

    • (Integer)
  • .splice(io_in, off_in, io_out, off_out, len, flags) ⇒ Integer

    Returns:

    • (Integer)


227
228
229
230
231
232
233
234
235
236
# File 'ext/io_splice/io_splice_ext.c', line 227

static VALUE my_splice(int argc, VALUE *argv, VALUE self)
{
	ssize_t n = do_splice(argc, argv, 0);

	if (n == 0)
		rb_eof_error();
	if (n == -1)
		rb_sys_fail("splice");
	return SSIZET2NUM(n);
}

.tee(io_in, io_out, len) ⇒ Integer .tee(io_in, io_out, len, flags) ⇒ Integer

Copies up to len bytes of data from io_in to io_out. io_in and io_out must both refer to pipe descriptors. io_in and io_out may not be endpoints of the same pipe.

flags may be zero (the default) or a combination of:

  • IO::Splice::F_NONBLOCK

  • IO::Splice::WAITALL

Other IO::Splice flags are currently unimplemented or have no effect.

Returns the number of bytes duplicated if successful. Raises EOFError when io_in is closed and emptied. Raises Errno::EAGAIN when io_in is empty and/or io_out is full and flags contains IO::Splice::F_NONBLOCK

Consider using IO.trytee if you are using IO::Splice::F_NONBLOCK as it avoids the cost of raising common Errno::EAGAIN exceptions.

See manpage for full documentation: kernel.org/doc/man-pages/online/pages/man2/tee.2.html

Overloads:

  • .tee(io_in, io_out, len) ⇒ Integer

    Returns:

    • (Integer)
  • .tee(io_in, io_out, len, flags) ⇒ Integer

    Returns:

    • (Integer)


351
352
353
354
355
356
357
358
359
360
361
# File 'ext/io_splice/io_splice_ext.c', line 351

static VALUE my_tee(int argc, VALUE *argv, VALUE self)
{
	ssize_t n = do_tee(argc, argv, 0);

	if (n == 0)
		rb_eof_error();
	if (n == -1)
		rb_sys_fail("tee");

	return SSIZET2NUM(n);
}

.trysplice(io_in, off_in, io_out, off_out, len) ⇒ Integer .trysplice(io_in, off_in, io_out, off_out, len, flags) ⇒ Integer

Exactly like IO.splice, except :EAGAIN is returned when either the read or write end would block instead of raising Errno::EAGAIN.

IO::Splice::F_NONBLOCK is always passed for the pipe descriptor, but this can still block if the non-pipe descriptor is blocking.

See IO.splice documentation for more details.

Overloads:

  • .trysplice(io_in, off_in, io_out, off_out, len) ⇒ Integer

    Returns:

    • (Integer)
  • .trysplice(io_in, off_in, io_out, off_out, len, flags) ⇒ Integer

    Returns:

    • (Integer)


251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'ext/io_splice/io_splice_ext.c', line 251

static VALUE trysplice(int argc, VALUE *argv, VALUE self)
{
	ssize_t n = do_splice(argc, argv, SPLICE_F_NONBLOCK);

	if (n == 0)
		return Qnil;
	if (n == -1) {
		if (errno == EAGAIN)
			return sym_EAGAIN;
		rb_sys_fail("splice");
	}
	return SSIZET2NUM(n);
}

.trytee(io_in, io_out, len) ⇒ Integer .trytee(io_in, io_out, len, flags) ⇒ Integer

Exactly like IO.tee, except :EAGAIN is returned when either the read or write end would block instead of raising Errno::EAGAIN.

IO::Splice::F_NONBLOCK is always passed for the pipe descriptor, but this can still block if the non-pipe descriptor is blocking.

See IO.tee documentation for more details.

Overloads:

  • .trytee(io_in, io_out, len) ⇒ Integer

    Returns:

    • (Integer)
  • .trytee(io_in, io_out, len, flags) ⇒ Integer

    Returns:

    • (Integer)


376
377
378
379
380
381
382
383
384
385
386
387
388
389
# File 'ext/io_splice/io_splice_ext.c', line 376

static VALUE trytee(int argc, VALUE *argv, VALUE self)
{
	ssize_t n = do_tee(argc, argv, SPLICE_F_NONBLOCK);

	if (n == 0)
		return Qnil;
	if (n == -1) {
		if (errno == EAGAIN)
			return sym_EAGAIN;
		rb_sys_fail("tee");
	}

	return SSIZET2NUM(n);
}

.vmsplice(io, string_array) ⇒ Integer .vmsplice(io, string_array, flags) ⇒ Integer .vmsplice(io, string) ⇒ Integer .vmsplice(io, string, flags) ⇒ Integer

Transfers an array of strings into the pipe descriptor given by io. io must be the writable end of a pipe.

This may allow the kernel to avoid data copies in some cases. but is (probably) of limited usefulness in Ruby. If you have use cases or ideas for making this more useful for Ruby users, please tell us at [email protected]!

Also consider the “sendfile” RubyGem or IO.copy_stream in Ruby 1.9 if you want to do zero-copy file transfers to pipes or sockets. As of Linux 2.6.33, sendfile(2) can copy to any output descriptor, not just sockets.

See manpage for full documentation: kernel.org/doc/man-pages/online/pages/man2/vmsplice.2.html

Overloads:

  • .vmsplice(io, string_array) ⇒ Integer

    Returns:

    • (Integer)
  • .vmsplice(io, string_array, flags) ⇒ Integer

    Returns:

    • (Integer)
  • .vmsplice(io, string) ⇒ Integer

    Returns:

    • (Integer)
  • .vmsplice(io, string, flags) ⇒ Integer

    Returns:

    • (Integer)


479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
# File 'ext/io_splice/io_splice_ext.c', line 479

static VALUE my_vmsplice(int argc, VALUE * argv, VALUE self)
{
	ssize_t rv = 0;
	ssize_t left;
	struct vmsplice_args a;
	VALUE io, data, flags;

	rb_scan_args(argc, argv, "21", &io, &data, &flags);

	switch (TYPE(data)) {
	case T_STRING: {
		struct iovec iov;

		iov.iov_base = RSTRING_PTR(data);
		iov.iov_len = (size_t)(left = (ssize_t)RSTRING_LEN(data));
		a.iov = &iov;
		a.nr_segs = 1;
		}
		break;
	case T_ARRAY:
		ARY2IOVEC(a.iov, a.nr_segs, left, data);
		break;
	default:
		rb_raise(rb_eTypeError, "wrong argument type %s "
		         "(expected a String or Array of strings)",
		         rb_obj_classname(data));
	}
	a.fd = my_fileno(io);
	a.flags = NIL_P(flags) ? 0 : NUM2UINT(flags);

	for (;;) {
		ssize_t n = (ssize_t)io_run(nogvl_vmsplice, &a);

		if (n == -1) {
			if (errno == EAGAIN) {
				if (a.flags & SPLICE_F_NONBLOCK) {
					rb_sys_fail("vmsplice");
				} else {
					a.fd = check_fileno(io);
					if (rb_io_wait_writable(a.fd))
						continue;
				}
				/* fall through on error */
			}
			/*
			 * unlikely to hit this case, return the
			 * already written bytes, we'll let the next
			 * write (or close) fail instead
			 */
			if (rv > 0)
				break;
			if (errno == EINTR) {
				a.fd = check_fileno(io);
				continue;
			}
			rb_sys_fail("vmsplice");
		}

		rv += n;
		left -= n;
		if (left == 0)
			break;
		advance_vmsplice_args(&a, n);
	}

	return SSIZET2NUM(rv);
}

Instance Method Details

#readerObject #pipe_sizeInteger

Returns the pipe capacity of the underlying pipe in bytes. The default capacity is 65536 bytes since Linux 2.6.11, and 4096 bytes in previous kernels.

Since the pipe is a circular buffer in the same kernel, the size of the reader is exactly the same as the size of the writer.

This method is only exposed on Linux 2.6.35 or later.

Overloads:

  • #pipe_sizeInteger

    Returns:

    • (Integer)


561
562
563
564
565
566
567
568
569
# File 'ext/io_splice/io_splice_ext.c', line 561

static VALUE pipe_size(VALUE self)
{
	int size = fcntl(my_fileno(self),  F_GETPIPE_SZ);

	if (size < 0)
		rb_sys_fail("fcntl(F_GETPIPE_SZ)");

	return INT2NUM(size);
}

#readerObject #pipe_size=(integer) ⇒ Object

Sets and returns the pipe capacity of the underlying pipe in bytes.

This MUST be a power-of-two, or Errno::EINVAL will be raised. Linux will silently increase this to be equal to the page size (4096 bytes on most architectures) if the specified value is less than the size of a page.

For users without CAP_SYS_RESOURCE, this raises Errno::EPERM when attempting to specify a value greater than the value in /proc/sys/fs/pipe-max-size.

Since the pipe is a circular buffer in the same kernel, the size of the reader is exactly the same as the size of the writer.

Raises Errno::EBUSY if the assigned value is less than the currently filled portion of the pipe.

This method is only exposed on Linux 2.6.35 or later.



595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
# File 'ext/io_splice/io_splice_ext.c', line 595

static VALUE set_pipe_size(VALUE self, VALUE size)
{
	int fd = my_fileno(self);
	int bytes = NUM2INT(size);
	int rv = fcntl(fd, F_SETPIPE_SZ, bytes);

	if (rv < 0) {
		if (errno == ENOMEM) {
			rb_gc();
			rv = fcntl(fd, F_SETPIPE_SZ, bytes);
		}
		if (rv < 0)
			rb_sys_fail("fcntl(F_SETPIPE_SZ)");
	}

	return size;
}