Class: Pocolog::StreamIndex Private

Inherits:
Object
  • Object
show all
Defined in:
lib/pocolog/stream_index.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Index containing the information for a given stream

The stream can possibly span multiple files if it is backed by a IOSequence object. This is transparent to the index as IOSequence provides an interface where positions span the IOs

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base_time: nil) ⇒ StreamIndex

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.

Returns a new instance of StreamIndex



30
31
32
33
# File 'lib/pocolog/stream_index.rb', line 30

def initialize(base_time: nil)
    @base_time = base_time
    @index_map = []
end

Instance Attribute Details

#base_timeObject

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.



12
13
14
# File 'lib/pocolog/stream_index.rb', line 12

def base_time
  @base_time
end

#index_mapObject (readonly)

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.

The index information

This is an array of tuples.

REALLY IMPORTANT: the tuples MUST be of size 3 or lower. On CRuby, this ensures that the elements are stored within the array object itself instead of allocating extra memory on the heap.



21
22
23
# File 'lib/pocolog/stream_index.rb', line 21

def index_map
  @index_map
end

Class Method Details

.from_raw_data(base_time, index_map) ⇒ 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.

Initialize a stream index object from the raw information



24
25
26
27
28
# File 'lib/pocolog/stream_index.rb', line 24

def self.from_raw_data(base_time, index_map)
    index = StreamIndex.new(base_time: base_time)
    index.index_map.concat(index_map)
    index
end

.time_from_internal(time, base_time) ⇒ 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.

Create a Time object from the index' own internal Time representation



175
176
177
178
# File 'lib/pocolog/stream_index.rb', line 175

def self.time_from_internal(time, base_time)
    time += base_time
    Time.at(time / 1_000_000, time % 1_000_000)
end

.time_to_internal(time, base_time) ⇒ 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.

Converts a Time object into the index' internal representation



181
182
183
184
# File 'lib/pocolog/stream_index.rb', line 181

def self.time_to_internal(time, base_time)
    internal = time.tv_sec * 1_000_000 + time.tv_usec
    internal - base_time
end

Instance Method Details

#add_raw_sample(pos, time) ⇒ 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.

Append a new sample to the index



100
101
102
103
# File 'lib/pocolog/stream_index.rb', line 100

def add_raw_sample(pos, time)
    @base_time ||= time
    @index_map << [pos, time - @base_time, @index_map.size]
end

#add_sample(pos, time) ⇒ 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.

Append a new sample to the index



95
96
97
# File 'lib/pocolog/stream_index.rb', line 95

def add_sample(pos, time)
    add_raw_sample(pos, time)
end

#concat(stream_index, file_pos_offset = 0) ⇒ 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.

Concatenates followup information for the same stream

Parameters:

  • stream_index (StreamIndex)

    the index to concatenate

  • file_pos_offset (Integer) (defaults to: 0)

    offset to apply to the added stream's file position. This is used when building the index of a stream backed by a IOSequence.



82
83
84
85
86
87
88
89
90
91
92
# File 'lib/pocolog/stream_index.rb', line 82

def concat(stream_index, file_pos_offset = 0)
    @base_time ||= stream_index.base_time

    time_offset         = stream_index.base_time - base_time
    sample_index_offset = size
    stream_index.index_map.each do |file_pos, time, sample_index|
        index_map << [file_pos + file_pos_offset,
                      time + time_offset,
                      sample_index + sample_index_offset]
    end
end

#empty?Boolean

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.

True if there are no samples indexed in self

Returns:

  • (Boolean)


62
63
64
# File 'lib/pocolog/stream_index.rb', line 62

def empty?
    @index_map.empty?
end

#end_timeTime?

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.

Return the time of the last sample

Returns:

  • (Time, nil)


170
171
172
# File 'lib/pocolog/stream_index.rb', line 170

def end_time
    time_by_sample_number(-1) unless empty?
end

#file_position_by_sample_number(sample_number) ⇒ Integer

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.

Returns the IO position of a sample

Parameters:

  • sample_number (Integer)

    the sample index in the stream

Returns:

  • (Integer)

    the sample's position in the backing IO

Raises:

  • IndexError if the sample number is out of bounds



209
210
211
# File 'lib/pocolog/stream_index.rb', line 209

def file_position_by_sample_number(sample_number)
    @index_map.fetch(sample_number)[0]
end

#initialize_copy(_copy) ⇒ 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.

Raises:

  • (NotImplementedError)


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

def initialize_copy(_copy)
    raise NotImplementedError, 'StreamInfo is non-copyable'
end

#internal_time_by_sample_number(sample_number) ⇒ Integer

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.

Returns the time of a sample

Parameters:

  • sample_number (Integer)

    the sample index in the stream

Returns:

  • (Integer)

    the sample's time in the index' internal encoding

Raises:

  • IndexError if the sample number is out of bounds



218
219
220
# File 'lib/pocolog/stream_index.rb', line 218

def internal_time_by_sample_number(sample_number)
    @index_map.fetch(sample_number)[1]
end

#raw_each {|file_pos, time| ... } ⇒ 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.

Iterate over the index

Yield Parameters:

  • file_pos (Integer)

    the position in the file

  • time (Integer)

    the time since #base_time



70
71
72
73
74
# File 'lib/pocolog/stream_index.rb', line 70

def raw_each
    @index_map.each do |file_pos, time, _|
        yield(file_pos, time)
    end
end

#remove_after(time) ⇒ StreamIndex

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.

Return a new index without any sample after the given time

Returns:



121
122
123
124
# File 'lib/pocolog/stream_index.rb', line 121

def remove_after(time)
    index = sample_number_by_time(time)
    self.class.from_raw_data(@base_time, @index_map[0...index])
end

#remove_before(time) ⇒ StreamIndex

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.

Return a new index without any sample before the given time

Returns:



108
109
110
111
112
113
114
115
116
# File 'lib/pocolog/stream_index.rb', line 108

def remove_before(time)
    index = sample_number_by_time(time)
    index_map = (index...size).map do |i|
        e = @index_map[i].dup
        e[2] = i - index
        e
    end
    self.class.from_raw_data(@base_time, index_map)
end

#resample_by_index(period) ⇒ 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.

Return the index with only every N-th samples



127
128
129
130
131
132
133
134
135
136
137
# File 'lib/pocolog/stream_index.rb', line 127

def resample_by_index(period)
    self.class.from_raw_data(@base_time, @index_map) if period == 1

    new_map = Array.new((size + period - 1) / period)
    new_map.size.times do |i|
        entry = @index_map[i * period].dup
        entry[2] = i
        new_map[i] = entry
    end
    self.class.from_raw_data(@base_time, new_map)
end

#resample_by_time(period, start_time: nil) ⇒ 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.

Return the index with only every N-th samples



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/pocolog/stream_index.rb', line 140

def resample_by_time(period, start_time: nil)
    period_us = period * 1_000_000
    next_time =
        if start_time
            self.class.time_to_internal(start_time, @base_time)
        else
            internal_time_by_sample_number(0)
        end

    new_map = []
    @index_map.each do |entry|
        entry_t = entry[1]
        if entry_t >= next_time
            new_map << [entry[0], entry[1], new_map.size]
            next_time += period_us until entry_t < next_time
        end
    end
    self.class.from_raw_data(@base_time, new_map)
end

#sample_number_by_internal_time(sample_time) ⇒ 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.

Returns the sample number of the first sample whose time is not before the given time

Parameters:

  • (Integer)


199
200
201
202
# File 'lib/pocolog/stream_index.rb', line 199

def sample_number_by_internal_time(sample_time)
    _pos_, _time, idx = @index_map.bsearch { |_, t, _| t >= sample_time }
    idx || size
end

#sample_number_by_time(sample_time) ⇒ 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.

Returns the sample number of the first sample whose time is not before the given time

Parameters:

  • (Time)


190
191
192
193
# File 'lib/pocolog/stream_index.rb', line 190

def sample_number_by_time(sample_time)
    sample_time = StreamIndex.time_to_internal(sample_time, base_time)
    sample_number_by_internal_time(sample_time)
end

#sizeObject

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.

Number of samples in this index



57
58
59
# File 'lib/pocolog/stream_index.rb', line 57

def size
    @index_map.size
end

#start_timeTime?

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.

Return the time of the first sample

Returns:

  • (Time, nil)


163
164
165
# File 'lib/pocolog/stream_index.rb', line 163

def start_time
    time_by_sample_number(0) unless empty?
end

#time_by_sample_number(sample_number) ⇒ Time

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.

Returns the time of a sample

Parameters:

  • sample_number (Integer)

    the sample index in the stream

Returns:

  • (Time)

    the sample's time in the index' internal encoding

Raises:

  • IndexError if the sample number is out of bounds



227
228
229
230
231
232
# File 'lib/pocolog/stream_index.rb', line 227

def time_by_sample_number(sample_number)
    StreamIndex.time_from_internal(
        internal_time_by_sample_number(sample_number),
        base_time
    )
end