def _handle_rcl_lifecycle_state_machine_init( self, event: Dict, metadata: EventMetadata, ) -> None: node_handle = get_field(event, 'node_handle') state_machine = get_field(event, 'state_machine') self.data.add_lifecycle_state_machine(state_machine, node_handle)
def _handle_rclcpp_callback_register( self, event: Dict, metadata: EventMetadata, ) -> None: callback_object = get_field(event, 'callback') timestamp = metadata.timestamp symbol = get_field(event, 'symbol') self.data.add_callback_symbol(callback_object, timestamp, symbol)
def _handle_rmw_subscription_init( self, event: Dict, metadata: EventMetadata, ) -> None: handle = get_field(event, 'rmw_subscription_handle') timestamp = metadata.timestamp gid = get_field(event, 'gid') self.data.add_rmw_subscription(handle, timestamp, gid)
def _handle_rcl_publish( self, event: Dict, metadata: EventMetadata, ) -> None: handle = get_field(event, 'publisher_handle') timestamp = metadata.timestamp message = get_field(event, 'message') self.data.add_rcl_publish_instance(handle, timestamp, message)
def _handle_rmw_publisher_init( self, event: Dict, metadata: EventMetadata, ) -> None: handle = get_field(event, 'rmw_publisher_handle') timestamp = metadata.timestamp gid = get_field(event, 'gid') self.data.add_rmw_publisher(handle, timestamp, gid)
def _handle_rclcpp_timer_link_node( self, event: Dict, metadata: EventMetadata, ) -> None: handle = get_field(event, 'timer_handle') timestamp = metadata.timestamp node_handle = get_field(event, 'node_handle') self.data.add_timer_node_link(handle, timestamp, node_handle)
def _handle_rclcpp_timer_callback_added( self, event: Dict, metadata: EventMetadata, ) -> None: handle = get_field(event, 'timer_handle') timestamp = metadata.timestamp callback_object = get_field(event, 'callback') self.data.add_callback_object(handle, timestamp, callback_object)
def _handle_rcl_timer_init( self, event: Dict, metadata: EventMetadata, ) -> None: handle = get_field(event, 'timer_handle') timestamp = metadata.timestamp period = get_field(event, 'period') tid = metadata.tid self.data.add_timer(handle, timestamp, period, tid)
def _handle_rclcpp_subscription_callback_added( self, event: Dict, metadata: EventMetadata, ) -> None: subscription_pointer = get_field(event, 'subscription') timestamp = metadata.timestamp callback_object = get_field(event, 'callback') self.data.add_callback_object(subscription_pointer, timestamp, callback_object)
def _handle_rclcpp_subscription_init( self, event: Dict, metadata: EventMetadata, ) -> None: subscription_pointer = get_field(event, 'subscription') timestamp = metadata.timestamp handle = get_field(event, 'subscription_handle') self.data.add_rclcpp_subscription(subscription_pointer, timestamp, handle)
def _handle_rcl_init( self, event: Dict, metadata: EventMetadata, ) -> None: context_handle = get_field(event, 'context_handle') timestamp = metadata.timestamp pid = metadata.pid version = get_field(event, 'version') self.data.add_context(context_handle, timestamp, pid, version)
def _handle_rcl_lifecycle_transition( self, event: Dict, metadata: EventMetadata, ) -> None: timestamp = metadata.timestamp state_machine = get_field(event, 'state_machine') start_label = get_field(event, 'start_label') goal_label = get_field(event, 'goal_label') self.data.add_lifecycle_state_transition(state_machine, start_label, goal_label, timestamp)
def _handle_rcl_node_init( self, event: Dict, metadata: EventMetadata, ) -> None: handle = get_field(event, 'node_handle') timestamp = metadata.timestamp tid = metadata.tid rmw_handle = get_field(event, 'rmw_handle') name = get_field(event, 'node_name') namespace = get_field(event, 'namespace') self.data.add_node(handle, timestamp, tid, rmw_handle, name, namespace)
def _handle_rmw_take( self, event: Dict, metadata: EventMetadata, ) -> None: subscription_handle = get_field(event, 'rmw_subscription_handle') timestamp = metadata.timestamp message = get_field(event, 'message') source_timestamp = get_field(event, 'source_timestamp') taken = bool(get_field(event, 'taken')) self.data.add_rmw_take_instance(subscription_handle, timestamp, message, source_timestamp, taken)
def _handle_rcl_client_init( self, event: Dict, metadata: EventMetadata, ) -> None: handle = get_field(event, 'client_handle') timestamp = metadata.timestamp node_handle = get_field(event, 'node_handle') rmw_handle = get_field(event, 'rmw_client_handle') service_name = get_field(event, 'service_name') self.data.add_client(handle, timestamp, node_handle, rmw_handle, service_name)
def _handle_rcl_publisher_init( self, event: Dict, metadata: EventMetadata, ) -> None: handle = get_field(event, 'publisher_handle') timestamp = metadata.timestamp node_handle = get_field(event, 'node_handle') rmw_handle = get_field(event, 'rmw_publisher_handle') topic_name = get_field(event, 'topic_name') depth = get_field(event, 'queue_depth') self.data.add_rcl_publisher(handle, timestamp, node_handle, rmw_handle, topic_name, depth)
def _handle_rclcpp_take( self, event: Dict, metadata: EventMetadata, ) -> None: timestamp = metadata.timestamp message = get_field(event, 'message') self.data.add_rclcpp_take_instance(timestamp, message)
def _handle_callback_start( self, event: Dict, metadata: EventMetadata, ) -> None: # Add to dict callback_addr = get_field(event, 'callback') self._callback_instances[callback_addr] = (event, metadata)
def _process_event(self, event: DictEvent) -> None: """Process a single event.""" event_name = get_event_name(event) handler_functions = self._handler_multimap.get(event_name, None) if handler_functions is not None: for handler_function in handler_functions: timestamp = get_field(event, '_timestamp') cpu_id = get_field(event, 'cpu_id') # TODO perhaps validate fields depending on the type of event, # i.e. all UST events should have procname, (v)pid and (v)tid # context info, since analyses might not work otherwise procname = get_field(event, 'procname', raise_if_not_found=False) pid = get_field( event, 'vpid', default=get_field( event, 'pid', raise_if_not_found=False), raise_if_not_found=False) tid = get_field( event, 'vtid', default=get_field( event, 'tid', raise_if_not_found=False), raise_if_not_found=False) metadata = EventMetadata(event_name, timestamp, cpu_id, procname, pid, tid) handler_function(event, metadata)
def _handle_rcl_subscription_init( self, event: Dict, metadata: EventMetadata, ) -> None: handle = get_field(event, 'subscription_handle') timestamp = metadata.timestamp node_handle = get_field(event, 'node_handle') rmw_handle = get_field(event, 'rmw_subscription_handle') topic_name = get_field(event, 'topic_name') depth = get_field(event, 'queue_depth') self.data.add_rcl_subscription( handle, timestamp, node_handle, rmw_handle, topic_name, depth, )
def _handle_callback_end( self, event: Dict, metadata: EventMetadata, ) -> None: # Fetch from dict callback_object = get_field(event, 'callback') callback_instance_data = self._callback_instances.get(callback_object) if callback_instance_data is not None: (event_start, metadata_start) = callback_instance_data del self._callback_instances[callback_object] duration = metadata.timestamp - metadata_start.timestamp is_intra_process = get_field(event_start, 'is_intra_process', raise_if_not_found=False) self.data.add_callback_instance(callback_object, metadata_start.timestamp, duration, bool(is_intra_process)) else: print( f'No matching callback start for callback object "{callback_object}"' )
def _handle_sched_switch(self, event: Dict, metadata: EventMetadata) -> None: timestamp = metadata.timestamp # If function(s) currently running stop(s) executing prev_tid = get_field(event, 'prev_tid') prev_info_list = self._current_funcs.get(prev_tid, None) if prev_info_list is not None: # Increment durations using last start timestamp for info in prev_info_list: last_start = info[2] total_duration = info[3] total_duration += timestamp - last_start info[2] = -1 info[3] = total_duration # If stopped function(s) start(s) executing again next_tid = get_field(event, 'next_tid') next_info_list = self._current_funcs.get(next_tid, None) if next_info_list is not None: # Set last start timestamp to now for info in next_info_list: assert info[2] == -1 info[2] = timestamp
def _handle_sched_switch( self, event: Dict, metadata: EventMetadata ) -> None: timestamp = metadata.timestamp cpu_id = metadata.cpu_id # Process if there is a previous thread timestamp # TODO instead of discarding it, use first ever timestamp # of the trace (with TraceCollection.timestamp_begin) prev_timestamp = self._cpu_start.get(cpu_id, None) if prev_timestamp is not None: prev_tid = get_field(event, 'prev_tid') duration = timestamp - prev_timestamp self.data.add_duration(prev_tid, prev_timestamp, duration, cpu_id) # Set start timestamp of next thread self._cpu_start[cpu_id] = timestamp
def get_events_with_field_value( self, field_name: str, field_values: Any, events: List[DictEvent] = None, ) -> List[DictEvent]: """ Get all events with the given field:value. :param field_name: the name of the field to check :param field_values: the value(s) of the field to check :param events: the events to check (or `None` to check all events) :return: the events with the given field:value pair """ if not isinstance(field_values, list): field_values = [field_values] if events is None: events = self._events return [ e for e in events if get_field(e, field_name, None) in field_values ]
def get_field( self, event: DictEvent, field_name: str, ) -> Any: """ Get field value; will fail test if not found. :param event: the event from which to get the value :param field_name: the field name :return: the value """ try: value = get_field(event, field_name, default=None, raise_if_not_found=True) except AttributeError as e: # Explicitly failing here self.fail(str(e)) else: return value
def _get_function_name(self, event: Dict) -> str: address = get_field(event, 'addr') resolution = self._resolve_function_address(address) if resolution is None: resolution = self.int_to_hex_str(address) return resolution