Class: Pocolog::IOSequence

Inherits:
Object
  • Object
show all
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

Instance Method Summary collapse

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

#iosObject (readonly)

The IO sequence itself



10
11
12
# File 'lib/pocolog/io_sequence.rb', line 10

def ios
  @ios
end

#sizeObject (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

#closeObject



43
44
45
# File 'lib/pocolog/io_sequence.rb', line 43

def close
    each_io(&:close)
end

#closed?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/pocolog/io_sequence.rb', line 39

def closed?
    each_io.any?(&:flush)
end

#each_ioObject



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

Returns:

  • (Boolean)


54
55
56
# File 'lib/pocolog/io_sequence.rb', line 54

def eof?
    (@current_io == ios.last) && @current_io.eof?
end

#flushObject



35
36
37
# File 'lib/pocolog/io_sequence.rb', line 35

def flush
    each_io(&:flush)
end

#num_ioObject



22
23
24
# File 'lib/pocolog/io_sequence.rb', line 22

def num_io
    ios.size
end

#openObject



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

#rewindObject

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

Raises:

  • RangeError if the position is outside range



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

Raises:

  • RangeError if the position is outside range



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_ioObject

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

#tellObject

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