class Pocolog::StreamIndex
This file contains the index of a data stream.
Through this index it is possible to have an O(1) acess to the data position with an given sample number.
Time base access has a complexity of O(log N)
Attributes
base_time[R]
time_to_position_map[R]
Public Class Methods
new()
click to toggle source
# File lib/pocolog/stream_index.rb, line 31 def initialize # The index holds three arrays, which associate # the position number of a sample in a stream # with the file, file position and time of the sample # # The file is encoded as an index value (rio) since # pocolog accepts multifile log streams # @nr_to_position_map = Array.new() @base_time = nil @time_to_position_map = Array.new() @nr_to_rio = Array.new() end
time_from_internal(time, base_time)
click to toggle source
# File lib/pocolog/stream_index.rb, line 64 def self.time_from_internal(time, base_time) time = time + base_time Time.at(time / 1_000_000, time % 1_000_000) end
time_to_internal(time, base_time)
click to toggle source
# File lib/pocolog/stream_index.rb, line 69 def self.time_to_internal(time, base_time) internal = time.tv_sec * 1_000_000 + time.tv_usec internal - base_time end
Public Instance Methods
add_sample_to_index(rio, pos, time)
click to toggle source
adds a given sample header (and thus the sample) to the index
# File lib/pocolog/stream_index.rb, line 47 def add_sample_to_index(rio, pos, time) #store the posiiton of the header of the data sample @nr_to_rio << rio @nr_to_position_map << pos internal_time = time.tv_sec * 1_000_000 + time.tv_usec @base_time ||= internal_time @time_to_position_map << [(internal_time - @base_time), time_to_position_map.size] end
base_time=(value)
click to toggle source
# File lib/pocolog/stream_index.rb, line 17 def base_time=(value) @base_time ||= value offset = @base_time - value return if offset == 0 @time_to_position_map = time_to_position_map.map do |t, i| [t + offset, i] end @base_time = value end
file_position_by_sample_number(sample_nr)
click to toggle source
Expects the number of the sample that needs to be accessed and returns the position of the sample in the file
# File lib/pocolog/stream_index.rb, line 94 def file_position_by_sample_number(sample_nr) return @nr_to_rio[sample_nr], @nr_to_position_map[sample_nr] end
internal_time_by_sample_number(sample_nr)
click to toggle source
# File lib/pocolog/stream_index.rb, line 98 def internal_time_by_sample_number(sample_nr) if(sample_nr < 0 || sample_nr >= size) raise ArgumentError, "#{sample_nr} out of bounds" end @time_to_position_map[sample_nr].first end
marshal_dump()
click to toggle source
# File lib/pocolog/stream_index.rb, line 111 def marshal_dump [@nr_to_rio.pack("n*"), @nr_to_position_map.pack("Q>*"), @base_time, @time_to_position_map.map(&:first).pack("Q>*")] end
marshal_load(info)
click to toggle source
# File lib/pocolog/stream_index.rb, line 118 def marshal_load(info) if info.size == 4 nr_to_rio, nr_to_position_map, base_time, time_to_position_map = *info @nr_to_rio = nr_to_rio.unpack("n*") @nr_to_position_map = nr_to_position_map.unpack("Q>*") @base_time = base_time @time_to_position_map = time_to_position_map.unpack("Q>*").each_with_index.map do |time, i| [time, i] end return end nr_to_rio, nr_to_position_map, time_to_position_map = *info if nr_to_rio.respond_to?(:to_str) @nr_to_rio = nr_to_rio.unpack("n*") @nr_to_position_map = nr_to_position_map.unpack("Q>*") time_to_position_map = time_to_position_map.unpack("Q>*") if time_to_position_map.empty? else # Old-new-style :( [tv_sec, tv_usec] base, _ = time_to_position_map.first @base_time = base @time_to_position_map = time_to_position_map.each_slice(2).map { |sec, usec| (sec - base) * 1_000_000 + usec } end else Pocolog.warn "found an old-format index. Consider deleting all your index files to upgrade to a newer format" @nr_to_rio = nr_to_rio @nr_to_position_map = nr_to_position_map @time_to_position_map = time_to_position_map.map do |tv_sec, tv_usec| Time.at(tv_sec, tv_usec) end end end
sample_number_by_internal_time(sample_time)
click to toggle source
Returns the sample number of the first sample whose time is not before the given time
@param [Integer]
# File lib/pocolog/stream_index.rb, line 87 def sample_number_by_internal_time(sample_time) _, idx = @time_to_position_map.bsearch { |t, _| t >= sample_time } idx || size end
sample_number_by_time(sample_time)
click to toggle source
Returns the sample number of the first sample whose time is not before the given time
@param [Time]
# File lib/pocolog/stream_index.rb, line 78 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
sane?()
click to toggle source
sanity check for the index, which gets called after marshalling, to see if the index needs rebuilding
# File lib/pocolog/stream_index.rb, line 58 def sane? @nr_to_rio && @nr_to_position_map && @time_to_position_map && @nr_to_rio.size == @nr_to_position_map.size && @nr_to_rio.size == @time_to_position_map.size end
size()
click to toggle source
# File lib/pocolog/stream_index.rb, line 27 def size @time_to_position_map.size end
time_by_sample_number(sample_nr)
click to toggle source
expects a sample nr and returns the time of the sample
# File lib/pocolog/stream_index.rb, line 107 def time_by_sample_number(sample_nr) StreamIndex.time_from_internal(internal_time_by_sample_number(sample_nr), base_time) end