Class: Cosmos::PacketLogReader

Inherits:
Object
  • Object
show all
Includes:
PacketLogConstants
Defined in:
lib/cosmos/logs/packet_log_reader.rb

Overview

Reads a packet log of either commands or telemetry.

Constant Summary collapse

MAX_READ_SIZE =
1000000000

Constants included from PacketLogConstants

Cosmos::PacketLogConstants::COSMOS2_FILE_HEADER, Cosmos::PacketLogConstants::COSMOS4_FILE_HEADER, Cosmos::PacketLogConstants::COSMOS5_CMD_FLAG_MASK, Cosmos::PacketLogConstants::COSMOS5_ENTRY_TYPE_MASK, Cosmos::PacketLogConstants::COSMOS5_FILE_HEADER, Cosmos::PacketLogConstants::COSMOS5_HEADER_LENGTH, Cosmos::PacketLogConstants::COSMOS5_ID_FIXED_SIZE, Cosmos::PacketLogConstants::COSMOS5_ID_FLAG_MASK, Cosmos::PacketLogConstants::COSMOS5_INDEX_HEADER, Cosmos::PacketLogConstants::COSMOS5_JSON_PACKET_ENTRY_TYPE_MASK, Cosmos::PacketLogConstants::COSMOS5_MAX_PACKET_INDEX, Cosmos::PacketLogConstants::COSMOS5_MAX_TARGET_INDEX, Cosmos::PacketLogConstants::COSMOS5_OFFSET_MARKER_ENTRY_TYPE_MASK, Cosmos::PacketLogConstants::COSMOS5_OFFSET_MARKER_PACK_DIRECTIVE, Cosmos::PacketLogConstants::COSMOS5_OFFSET_MARKER_PACK_ITEMS, Cosmos::PacketLogConstants::COSMOS5_OFFSET_MARKER_SECONDARY_FIXED_SIZE, Cosmos::PacketLogConstants::COSMOS5_PACKET_DECLARATION_ENTRY_TYPE_MASK, Cosmos::PacketLogConstants::COSMOS5_PACKET_DECLARATION_PACK_DIRECTIVE, Cosmos::PacketLogConstants::COSMOS5_PACKET_DECLARATION_PACK_ITEMS, Cosmos::PacketLogConstants::COSMOS5_PACKET_DECLARATION_SECONDARY_FIXED_SIZE, Cosmos::PacketLogConstants::COSMOS5_PACKET_PACK_DIRECTIVE, Cosmos::PacketLogConstants::COSMOS5_PACKET_PACK_ITEMS, Cosmos::PacketLogConstants::COSMOS5_PACKET_SECONDARY_FIXED_SIZE, Cosmos::PacketLogConstants::COSMOS5_PRIMARY_FIXED_SIZE, Cosmos::PacketLogConstants::COSMOS5_RAW_PACKET_ENTRY_TYPE_MASK, Cosmos::PacketLogConstants::COSMOS5_STORED_FLAG_MASK, Cosmos::PacketLogConstants::COSMOS5_TARGET_DECLARATION_ENTRY_TYPE_MASK, Cosmos::PacketLogConstants::COSMOS5_TARGET_DECLARATION_PACK_DIRECTIVE, Cosmos::PacketLogConstants::COSMOS5_TARGET_DECLARATION_PACK_ITEMS, Cosmos::PacketLogConstants::COSMOS5_TARGET_DECLARATION_SECONDARY_FIXED_SIZE

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializePacketLogReader

Create a new log file reader



36
37
38
# File 'lib/cosmos/logs/packet_log_reader.rb', line 36

def initialize
  reset()
end

Instance Attribute Details

#redis_offsetObject (readonly)

Returns the value of attribute redis_offset.



31
32
33
# File 'lib/cosmos/logs/packet_log_reader.rb', line 31

def redis_offset
  @redis_offset
end

Instance Method Details

#bytes_readInteger

Returns The current file position in the log file.

Returns:

  • (Integer)

    The current file position in the log file



280
281
282
# File 'lib/cosmos/logs/packet_log_reader.rb', line 280

def bytes_read
  @file.pos
end

#closeObject

Closes the current log file



99
100
101
# File 'lib/cosmos/logs/packet_log_reader.rb', line 99

def close
  @file.close if @file and !@file.closed?
end

#each(filename, identify_and_define = true, start_time = nil, end_time = nil) {|packet| ... } ⇒ Boolean

Yields back each packet as it is found in the log file.

Parameters:

  • filename (String)

    The log file to read

  • identify_and_define (Boolean) (defaults to: true)

    Once the packet has been read from the log file, whether to both identify the packet by setting the target and packet name, and define the packet by populating all the items.

  • start_time (Time|nil) (defaults to: nil)

    Time at which to start returning packets. Packets found with a timestamp before this time are ignored. Pass nil to return all packets.

  • end_time (Time|nil) (defaults to: nil)

    Time at which to stop returning packets. Packets found with a timestamp after this time are ignored. Pass nil to return all packets.

Yield Parameters:

Returns:

  • (Boolean)

    Whether we reached the end_time while reading



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/cosmos/logs/packet_log_reader.rb', line 54

def each(filename, identify_and_define = true, start_time = nil, end_time = nil)
  reached_end_time = false
  open(filename)

  # seek_to_time(start_time) if start_time

  while true
    packet = read(identify_and_define)
    break unless packet

    time = packet.packet_time
    if time
      next if start_time and time < start_time
      # If we reach the end_time that means we found all the packets we asked for
      # This can be used by callers to know they are done reading
      if end_time and time > end_time
        reached_end_time = true
        break
      end
    end
    yield packet
  end
  reached_end_time
ensure # No implicit return value in the ensure block
  close()
end

#open(filename) ⇒ Boolean, Exception

Returns true if successfully changed to configuration specified in log, otherwise returns false and potentially an Exception class if an error occurred. If no error occurred false indicates that the requested configuration was simply not found.

Parameters:

  • filename (String)

    The log filename to open

Returns:

  • (Boolean, Exception)

    Returns true if successfully changed to configuration specified in log, otherwise returns false and potentially an Exception class if an error occurred. If no error occurred false indicates that the requested configuration was simply not found.



85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/cosmos/logs/packet_log_reader.rb', line 85

def open(filename)
  close()
  reset()
  @filename = filename
  @file = BufferedFile.open(@filename, 'rb')
  @max_read_size = @file.size
  @max_read_size = MAX_READ_SIZE if @max_read_size > MAX_READ_SIZE
  return read_file_header()
rescue => err
  close()
  raise err
end

#read(identify_and_define = true) ⇒ Packet

Read a packet from the log file

Parameters:

  • identify_and_define (Boolean) (defaults to: true)

    Once the packet has been read from the log file, whether to both identify the packet by setting the target and packet name, and define the packet by populating all the items.

Returns:



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/cosmos/logs/packet_log_reader.rb', line 107

def read(identify_and_define = true)
  # Read entry length
  length = @file.read(4)
  return nil if !length or length.length <= 0

  length = length.unpack('N')[0]
  entry = @file.read(length)
  flags = entry[0..1].unpack('n')[0]

  cmd_or_tlm = :TLM
  cmd_or_tlm = :CMD if flags & COSMOS5_CMD_FLAG_MASK == COSMOS5_CMD_FLAG_MASK
  stored = false
  stored = true if flags & COSMOS5_STORED_FLAG_MASK == COSMOS5_STORED_FLAG_MASK
  id = false
  id = true if flags & COSMOS5_ID_FLAG_MASK == COSMOS5_ID_FLAG_MASK

  if flags & COSMOS5_ENTRY_TYPE_MASK == COSMOS5_JSON_PACKET_ENTRY_TYPE_MASK
    packet_index, time_nsec_since_epoch = entry[2..11].unpack('nQ>')
    json_data = entry[12..-1]
    lookup_cmd_or_tlm, target_name, packet_name, id = @packets[packet_index]
    if cmd_or_tlm != lookup_cmd_or_tlm
      raise "Packet type mismatch, packet:#{cmd_or_tlm}, lookup:#{lookup_cmd_or_tlm}"
    end

    return JsonPacket.new(cmd_or_tlm, target_name, packet_name, time_nsec_since_epoch, stored, json_data)
  elsif flags & COSMOS5_ENTRY_TYPE_MASK == COSMOS5_RAW_PACKET_ENTRY_TYPE_MASK
    packet_index, time_nsec_since_epoch = entry[2..11].unpack('nQ>')
    packet_data = entry[12..-1]
    lookup_cmd_or_tlm, target_name, packet_name, id = @packets[packet_index]
    if cmd_or_tlm != lookup_cmd_or_tlm
      raise "Packet type mismatch, packet:#{cmd_or_tlm}, lookup:#{lookup_cmd_or_tlm}"
    end

    received_time = Time.from_nsec_from_epoch(time_nsec_since_epoch)
    if identify_and_define
      packet = identify_and_define_packet_data(cmd_or_tlm, target_name, packet_name, received_time, packet_data)
    else
      # Build Packet
      packet = Packet.new(target_name, packet_name, :BIG_ENDIAN, nil, packet_data)
    end
    packet.set_received_time_fast(received_time)
    packet.cmd_or_tlm = cmd_or_tlm
    packet.stored = stored
    packet.received_count += 1
    return packet
  elsif flags & COSMOS5_ENTRY_TYPE_MASK == COSMOS5_TARGET_DECLARATION_ENTRY_TYPE_MASK
    target_name_length = length - COSMOS5_PRIMARY_FIXED_SIZE - COSMOS5_TARGET_DECLARATION_SECONDARY_FIXED_SIZE
    target_name_length -= COSMOS5_ID_FIXED_SIZE if id
    target_name = entry[2..(target_name_length + 1)]
    if id
      id = entry[(target_name_length + 3)..(target_name_length + 34)]
      @target_ids << id
    end
    @target_names << target_name
    return read(identify_and_define)
  elsif flags & COSMOS5_ENTRY_TYPE_MASK == COSMOS5_PACKET_DECLARATION_ENTRY_TYPE_MASK
    target_index = entry[2..3].unpack('n')[0]
    target_name = @target_names[target_index]
    packet_name_length = length - COSMOS5_PRIMARY_FIXED_SIZE - COSMOS5_PACKET_DECLARATION_SECONDARY_FIXED_SIZE
    packet_name_length -= COSMOS5_ID_FIXED_SIZE if id
    packet_name = entry[4..(packet_name_length + 3)]
    if id
      id = entry[(packet_name_length + 4)..-1]
      @packet_ids << id
    end
    @packets << [cmd_or_tlm, target_name, packet_name, id]
    return read(identify_and_define)
  elsif flags & COSMOS5_ENTRY_TYPE_MASK == COSMOS5_OFFSET_MARKER_ENTRY_TYPE_MASK
    @redis_offset = entry[2..-1]
    return read(identify_and_define)
  else
    raise "Invalid Entry Flags: #{flags}"
  end
rescue => err
  close()
  raise err
end

#sizeInteger

Returns The size of the log file being processed.

Returns:

  • (Integer)

    The size of the log file being processed



275
276
277
# File 'lib/cosmos/logs/packet_log_reader.rb', line 275

def size
  @file.stat.size
end