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

Class Method Details

.__deprecatedObject

:nodoc:



8
9
10
11
12
13
# File 'lib/io/splice.rb', line 8

def self.__deprecated # :nodoc:
  return if @warned
  warn("IO::Splice.{copy_stream,full} are deprecated " \
       "and to be removed in io_splice 5.x")
  @warned = true
end

.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

Unlike IO.copy_stream, this does not take into account userspace I/O buffers nor IO-like objects with no underlying file descriptor (e.g. StringIO).

This is unsafe for socket-to-socket copies unless there is an active (blocking) reader on the other end.

This method is deprecated and will be removed in a future, as it is potentially unsafe for socket-to-socket operations and difficult-to-use. IO.copy_stream on Linux 2.6.33 and later allows using sendfile for file-to-file copies, so this offers no advantage.



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/io/splice.rb', line 58

def self.copy_stream(src, dst, len = nil, src_offset = nil)
  __deprecated
  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.



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/io/splice.rb', line 109

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:

Returns:

  • (Boolean)


36
37
38
39
# File 'lib/io/splice.rb', line 36

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



119
120
121
122
123
124
125
126
127
# File 'lib/io/splice.rb', line 119

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