Class: Pocolog::IOSequence
- Inherits:
-
Object
- Object
- Pocolog::IOSequence
- Defined in:
- lib/pocolog/io_sequence.rb
Overview
Present a sequence of IOs as one aggregate IO
Pocolog can read sequence of log files. This class presents such a sequence as a single IO
It is very limited, tailored to be used in pocolog
Instance Attribute Summary collapse
-
#ios ⇒ Object
readonly
The IO sequence itself.
-
#size ⇒ Object
readonly
The overall stream size in bytes.
Instance Method Summary collapse
- #add_io(io) ⇒ Object
- #close ⇒ Object
- #closed? ⇒ Boolean
- #each_io ⇒ Object
- #eof? ⇒ Boolean
- #flush ⇒ Object
-
#initialize(*ios) ⇒ IOSequence
constructor
A new instance of IOSequence.
- #num_io ⇒ Object
- #open ⇒ Object
-
#read(byte_count) ⇒ Object
Read a certain amount of bytes in the underlying IO.
-
#rewind ⇒ Object
Seek to the beginning of the file.
-
#seek(pos) ⇒ Object
Seek to the given absolute position in the sequential stream.
-
#select_io_from_pos(pos) ⇒ Object
private
Selects the IO that can provide the given position, and sets the relevant internal state accordingly.
-
#select_next_io ⇒ Object
private
Go to the next IO.
-
#tell ⇒ Object
The current position in the sequence.
Constructor Details
#initialize(*ios) ⇒ IOSequence
Returns a new instance of IOSequence
14 15 16 17 18 19 20 |
# File 'lib/pocolog/io_sequence.rb', line 14 def initialize(*ios) @size = 0 @ios = Array.new ios.each do |io| add_io(io) end end |
Instance Attribute Details
#ios ⇒ Object (readonly)
The IO sequence itself
10 11 12 |
# File 'lib/pocolog/io_sequence.rb', line 10 def ios @ios end |
#size ⇒ Object (readonly)
The overall stream size in bytes
12 13 14 |
# File 'lib/pocolog/io_sequence.rb', line 12 def size @size end |
Instance Method Details
#add_io(io) ⇒ Object
26 27 28 29 30 31 32 33 |
# File 'lib/pocolog/io_sequence.rb', line 26 def add_io(io) io_size = io.size @size += io_size ios << [io, io_size] if ios.size == 1 rewind end end |
#close ⇒ Object
43 44 45 |
# File 'lib/pocolog/io_sequence.rb', line 43 def close each_io(&:close) end |
#closed? ⇒ Boolean
39 40 41 |
# File 'lib/pocolog/io_sequence.rb', line 39 def closed? each_io.any?(&:flush) end |
#each_io ⇒ Object
47 48 49 50 51 52 |
# File 'lib/pocolog/io_sequence.rb', line 47 def each_io return enum_for(__method__) if !block_given? ios.each do |io, _io_size| yield(io) end end |
#eof? ⇒ Boolean
54 55 56 |
# File 'lib/pocolog/io_sequence.rb', line 54 def eof? (@current_io == ios.last) && @current_io.eof? end |
#flush ⇒ Object
35 36 37 |
# File 'lib/pocolog/io_sequence.rb', line 35 def flush each_io(&:flush) end |
#num_io ⇒ Object
22 23 24 |
# File 'lib/pocolog/io_sequence.rb', line 22 def num_io ios.size end |
#open ⇒ Object
58 59 60 61 62 63 64 65 |
# File 'lib/pocolog/io_sequence.rb', line 58 def open @io = io.map do |file| if file.closed? File.open(file.path) else file end end end |
#read(byte_count) ⇒ Object
Read a certain amount of bytes in the underlying IO
A read can never cross IO boundaries (i.e. it will only be served by a single file)
91 92 93 94 95 96 97 98 99 |
# File 'lib/pocolog/io_sequence.rb', line 91 def read(byte_count) buffer = @current_io.read(byte_count) if !buffer select_next_io @current_io.read(byte_count) else buffer end end |
#rewind ⇒ Object
Seek to the beginning of the file
68 69 70 |
# File 'lib/pocolog/io_sequence.rb', line 68 def rewind select_io_from_pos(0) end |
#seek(pos) ⇒ Object
Seek to the given absolute position in the sequential stream
80 81 82 83 84 85 |
# File 'lib/pocolog/io_sequence.rb', line 80 def seek(pos) if pos < @current_io_start || @current_io_end <= pos select_io_from_pos(pos) end @current_io.seek(pos - @current_io_start, IO::SEEK_SET) end |
#select_io_from_pos(pos) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Selects the IO that can provide the given position, and sets the relevant internal state accordingly
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/pocolog/io_sequence.rb', line 107 def select_io_from_pos(pos) current_start = 0 matching_io_index = ios.index do |io, size| current_end = current_start + size if pos < current_end true else current_start = current_end false end end if !matching_io_index raise RangeError, "#{pos} is out of range" end matching_io, matching_io_size = ios[matching_io_index] @current_io_index = matching_io_index @current_io = matching_io @current_io_start = current_start @current_io_end = current_start + matching_io_size end |
#select_next_io ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Go to the next IO
It does nothing if the current IO is the last
134 135 136 137 138 139 140 141 142 143 |
# File 'lib/pocolog/io_sequence.rb', line 134 def select_next_io io, size = ios[@current_io_index + 1] if io @current_io_index += 1 @current_io = io io.rewind @current_io_start = @current_io_end @current_io_end += size end end |
#tell ⇒ Object
The current position in the sequence
73 74 75 |
# File 'lib/pocolog/io_sequence.rb', line 73 def tell @current_io_start + @current_io.tell end |