Class: Roby::DRoby::Logfile::Index

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/roby/droby/logfile/index.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file_size, file_time, data) ⇒ Index

Returns a new instance of Index.



93
94
95
96
97
# File 'lib/roby/droby/logfile/index.rb', line 93

def initialize(file_size, file_time, data)
    @file_size = file_size
    @file_time = file_time
    @data = data
end

Instance Attribute Details

#dataArray<Hash> (readonly)

The index data

Returns:

  • (Array<Hash>)


91
92
93
# File 'lib/roby/droby/logfile/index.rb', line 91

def data
  @data
end

#file_sizeObject (readonly)

The size in bytes of the file that has been indexed



85
86
87
# File 'lib/roby/droby/logfile/index.rb', line 85

def file_size
  @file_size
end

#file_timeObject (readonly)

The modification time of the file that has been indexed



87
88
89
# File 'lib/roby/droby/logfile/index.rb', line 87

def file_time
  @file_time
end

Class Method Details

.process_one_cycle(pos, cycle) ⇒ Object

Convert a log’s cycle into the info hash expected in the index file

Parameters:

  • pos (Integer)

    the position of the cycle in the log file

  • cycle

    the decoded cycle information, as returned by e.g. Reader#load_one_cycle



32
33
34
35
36
37
38
39
40
41
# File 'lib/roby/droby/logfile/index.rb', line 32

def self.process_one_cycle(pos, cycle)
    info = cycle.last.last
    event_count = 0
    cycle.each_slice(4) do |m, *|
        event_count += 1 if m.to_s !~ /^timepoint/
    end
    info[:event_count] = event_count
    info[:pos] = pos
    info
end

.read(filename) ⇒ Object

Read an index file

Parameters:

  • filename (String)

    the index file path



145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/roby/droby/logfile/index.rb', line 145

def self.read(filename)
    io = File.open(filename)
    file_info = io.read(16)
    size, tv_sec, tv_nsec = file_info.unpack("Q<L<L<")
    data = []
    begin
        data << ::Marshal.load(Logfile.read_one_chunk(io)) until io.eof?
    rescue EOFError # rubocop:disable Lint/SuppressedException
    end

    new(size, Time.at(tv_sec, Rational(tv_nsec, 1000)), data)
ensure
    io&.close
end

.rebuild(event_io, index_io) ⇒ Object

Creates an index file for event_log in index_log



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/roby/droby/logfile/index.rb', line 10

def self.rebuild(event_io, index_io)
    stat = File.stat(event_io.path)
    event_log = Reader.new(event_io)

    write_header(index_io, stat.size, stat.mtime)
    until event_log.eof?
        pos = event_log.tell
        yield(Float(pos) / end_pos) if block_given?

        cycle = event_log.load_one_cycle
        write_one_cycle(index_io, pos, cycle)
    end
rescue EOFError # rubocop:disable Lint/SuppressedException
ensure
    index_io&.flush
end

.rebuild_file(log_path, index_path) ⇒ Object

Rebuild the index of a given log file

Parameters:

  • log_path (Pathname)
  • index_path (Pathname)


76
77
78
79
80
81
82
# File 'lib/roby/droby/logfile/index.rb', line 76

def self.rebuild_file(log_path, index_path)
    File.open(log_path, "r") do |event_io|
        File.open(index_path, "w") do |index_io|
            Index.rebuild(event_io, index_io)
        end
    end
end

.valid_file?(path, index_path) ⇒ Boolean

Returns whether an index file exists and is valid for a log file

Parameters:

  • path (String)

    the path to the log file

  • index_path (String)

    the path to the

Returns:

  • (Boolean)


164
165
166
167
# File 'lib/roby/droby/logfile/index.rb', line 164

def self.valid_file?(path, index_path)
    File.exist?(index_path) &&
        read(index_path).valid_for?(path)
end

.write_entry(index_io, info) ⇒ Object

Write an index entry from the raw info hash

Parameters:

  • index_io

    the IO object to write to

  • info (Hash)

    the info hash to be saved in the index



67
68
69
70
# File 'lib/roby/droby/logfile/index.rb', line 67

def self.write_entry(index_io, info)
    info = ::Marshal.dump(info)
    Logfile.write_entry(index_io, info)
end

.write_header(index_io, size, mtime) ⇒ Object

Write the index’s header

Parameters:

  • size (Integer)

    the size of the log file being indexed

  • mtime (Time)

    the modification time of the log file being indexed



47
48
49
50
51
# File 'lib/roby/droby/logfile/index.rb', line 47

def self.write_header(index_io, size, mtime)
    index_io.write(
        [size, mtime.tv_sec, mtime.tv_nsec].pack("Q<L<L<")
    )
end

.write_one_cycle(index_io, pos, cycle) ⇒ Object

Write a cycle’s index entry based on the decoded log chunk

Parameters:

  • index_io

    the IO object to write to

  • pos (Integer)

    the position of the cycle’s data

  • cycle

    the cycle data, decoded with e.g. Reader#load_one_cycle



58
59
60
61
# File 'lib/roby/droby/logfile/index.rb', line 58

def self.write_one_cycle(index_io, pos, cycle)
    info = process_one_cycle(pos, cycle)
    write_entry(index_io, info)
end

Instance Method Details

#[](*args) ⇒ Object



103
104
105
# File 'lib/roby/droby/logfile/index.rb', line 103

def [](*args)
    data[*args]
end

#cycle_countObject

Returns the number of cycles in this index



123
124
125
# File 'lib/roby/droby/logfile/index.rb', line 123

def cycle_count
    data.size
end

#each(&block) ⇒ Object



107
108
109
# File 'lib/roby/droby/logfile/index.rb', line 107

def each(&block)
    data.each(&block)
end

#empty?Boolean

Tests whether this index contains cycles

Returns:

  • (Boolean)


128
129
130
# File 'lib/roby/droby/logfile/index.rb', line 128

def empty?
    data.empty?
end

#rangenil, (Time,Time)

The time range

Returns:

  • (nil, (Time,Time))


135
136
137
138
139
140
# File 'lib/roby/droby/logfile/index.rb', line 135

def range
    return if data.empty?

    [Time.at(*data.first[:start]),
     Time.at(*data.last[:start]) + data.last[:end]]
end

#sizeObject



99
100
101
# File 'lib/roby/droby/logfile/index.rb', line 99

def size
    data.size
end

#valid_for?(path) ⇒ Boolean

Tests whether this index is valid for a given file

Parameters:

  • path (String)

    the log file path

Returns:

  • (Boolean)


117
118
119
120
# File 'lib/roby/droby/logfile/index.rb', line 117

def valid_for?(path)
    stat = File.stat(path)
    stat.size == file_size && stat.mtime == file_time
end