Module: IO::Splice
- Defined in:
- lib/io/splice/mri_18.rb,
lib/io/splice.rb
Constant Summary collapse
- PIPE_CAPA =
The maximum default capacity of the pipe in bytes. Under stock Linux, this is 65536 bytes as of 2.6.11, and 4096 before We detect this at runtime as it is easy to recompile the kernel and set a new value. Starting with Linux 2.6.35, pipe capacity will be tunable and this will only represent the default capacity of a newly-created pipe.
begin rd, wr = IO.pipe buf = ' ' * PIPE_BUF n = 0 begin n += wr.write_nonblock(buf) rescue Errno::EAGAIN break end while true wr.close rd.close n end
Class Method Summary collapse
-
.copy_stream(src, dst, len = nil, src_offset = nil) ⇒ Object
copies the contents of the IO object given by
src
todst
Iflen
is specified, then onlylen
bytes are copied andEOFError
is raised if fewer thanlen
bytes could be copied. -
.full(src, dst, len, src_offset) ⇒ Object
splice the full amount specified from
src
todst
Eitherdst
orsrc
must be a pipe. -
.need_open?(obj) ⇒ Boolean
:nodoc:.
-
.partial(src, dst, len, src_offset) ⇒ Object
splice up to
len
bytes fromsrc
todst
.
Class Method Details
.copy_stream(src, dst, len = nil, src_offset = nil) ⇒ Object
copies the contents of the IO object given by src
to dst
If len
is specified, then only len
bytes are copied and EOFError
is raised if fewer than len
bytes could be copied. Otherwise the copy will be until EOF is reached on the src
. src
and dst
must be IO objects or respond to to_io
This is nearly a drop-in replacement for IO.copy_stream (in Ruby 1.9) but does not take into account userspace I/O buffers nor IO-like objects with no underlying file descriptor (e.g. StringIO).
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/io/splice.rb', line 42 def self.copy_stream(src, dst, len = nil, src_offset = nil) close = [] need_open?(src) and close << (src = File.open(src)) need_open?(dst) and close << (dst = File.open(dst, "w")) rv = len src, dst = src.to_io, dst.to_io if src.stat.pipe? || dst.stat.pipe? return full(src, dst, len, src_offset) if len rv = 0 while n = partial(src, dst, MAX_AT_ONCE, src_offset) rv += n src_offset += n if src_offset end else r, w = tmp = IO.pipe close.concat(tmp) rv = 0 if len while len != 0 && n = partial(src, w, len, src_offset) src_offset += n if src_offset rv += n len -= full(r, dst, n, nil) end else while n = partial(src, w, MAX_AT_ONCE, src_offset) src_offset += n if src_offset rv += full(r, dst, n, nil) end end end rv ensure close.each { |io| io.close } end |
.full(src, dst, len, src_offset) ⇒ Object
splice the full amount specified from src
to dst
Either dst
or src
must be a pipe. dst
and src
may BOTH be pipes in Linux 2.6.31 or later. This will block and wait for IO completion of len
Raises EOFError
if end of file is reached. bytes. Returns the number of bytes actually spliced (always len
) unless src
does not have len
bytes to read.
Do not use this method to splice a socket src
into a pipe dst
unless there is another process or native thread doing a blocking read on the other end of the dst
pipe.
This method is safe for splicing a pipe src
into any type of dst
IO.
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/io/splice.rb', line 92 def self.full(src, dst, len, src_offset) dst.to_io.nonblock = src.to_io.nonblock = true spliced = 0 case n = IO.trysplice(src, src_offset, dst, nil, len, IO::Splice::F_MOVE) when :EAGAIN src.to_io.wait IO.select(nil, [dst]) when Integer spliced += n len -= n src_offset += n if src_offset when nil break end while len > 0 spliced end |
.need_open?(obj) ⇒ Boolean
:nodoc:
28 29 30 31 |
# File 'lib/io/splice.rb', line 28 def self.need_open?(obj) # :nodoc: return false if obj.respond_to?(:to_io) obj.respond_to?(:to_path) || obj.kind_of?(String) end |
.partial(src, dst, len, src_offset) ⇒ Object
splice up to len
bytes from src
to dst
. Either dst
or src
must be a pipe. dst
and src
may BOTH be pipes in Linux 2.6.31 or later. Returns the number of bytes actually spliced. Like IO#readpartial, this never returns Errno::EAGAIN
101 102 103 104 105 106 107 108 109 |
# File 'lib/io/splice.rb', line 101 def self.partial(src, dst, len, src_offset) dst.to_io.nonblock = src.to_io.nonblock = true begin src.to_io.wait IO.select(nil, [dst]) rv = IO.trysplice(src, src_offset, dst, nil, len, IO::Splice::F_MOVE) end while rv == :EAGAIN rv end |