struct bt_btr *bt_btr_create(struct bt_btr_cbs cbs, void *data) { struct bt_btr *btr; BT_LOGD_STR("Creating binary type reader (BTR)."); btr = g_new0(struct bt_btr, 1); if (!btr) { BT_LOGE_STR("Failed to allocate one binary type reader."); goto end; } btr->stack = stack_new(); if (!btr->stack) { BT_LOGE_STR("Cannot create BTR's stack."); bt_btr_destroy(btr); btr = NULL; goto end; } btr->state = BTR_STATE_NEXT_FIELD; btr->user.cbs = cbs; btr->user.data = data; BT_LOGD("Created BTR: addr=%p", btr); end: return btr; }
static struct stack *stack_new(void) { struct stack *stack = NULL; stack = g_new0(struct stack, 1); if (!stack) { BT_LOGE_STR("Failed to allocate one stack."); goto error; } stack->entries = g_ptr_array_new_with_free_func(stack_entry_free_func); if (!stack->entries) { BT_LOGE_STR("Failed to allocate a GPtrArray."); goto error; } BT_LOGD("Created stack: addr=%p", stack); return stack; error: g_free(stack); return NULL; }
struct bt_value *bt_value_map_create(void) { struct bt_value_map *map_obj; BT_LOGD_STR("Creating empty map value object."); map_obj = g_new0(struct bt_value_map, 1); if (!map_obj) { BT_LOGE_STR("Failed to allocate one map object."); goto end; } map_obj->base = bt_value_create_base(BT_VALUE_TYPE_MAP); map_obj->ght = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) bt_object_put_ref); if (!map_obj->ght) { BT_LOGE_STR("Failed to allocate a GHashTable."); g_free(map_obj); map_obj = NULL; goto end; } BT_LOGD("Created map value object: addr=%p", map_obj); end: return (void *) map_obj; }
struct bt_value *bt_value_string_create_init(const char *val) { struct bt_value_string *string_obj = NULL; if (!val) { BT_LOGW_STR("Invalid parameter: value is NULL."); goto end; } BT_LOGD("Creating string value object: val-len=%zu", strlen(val)); string_obj = g_new0(struct bt_value_string, 1); if (!string_obj) { BT_LOGE_STR("Failed to allocate one string object."); goto end; } string_obj->base = bt_value_create_base(BT_VALUE_TYPE_STRING); string_obj->gstr = g_string_new(val); if (!string_obj->gstr) { BT_LOGE_STR("Failed to allocate a GString."); g_free(string_obj); string_obj = NULL; goto end; } BT_LOGD("Created string value object: addr=%p", string_obj); end: return (void *) string_obj; }
struct bt_value *bt_value_array_create(void) { struct bt_value_array *array_obj; BT_LOGD_STR("Creating empty array value object."); array_obj = g_new0(struct bt_value_array, 1); if (!array_obj) { BT_LOGE_STR("Failed to allocate one array object."); goto end; } array_obj->base = bt_value_create_base(BT_VALUE_TYPE_ARRAY); array_obj->garray = bt_g_ptr_array_new_full(0, (GDestroyNotify) bt_object_put_ref); if (!array_obj->garray) { BT_LOGE_STR("Failed to allocate a GPtrArray."); g_free(array_obj); array_obj = NULL; goto end; } BT_LOGD("Created array value object: addr=%p", array_obj); end: return (void *) array_obj; }
BT_HIDDEN struct bt_value *bt_attributes_create(void) { struct bt_value *attr_obj; /* * Attributes: array value object of array value objects, each one * containing two entries: a string value object (attributes * field name), and a value object (attributes field value). * * Example (JSON representation): * * [ * ["hostname", "eeppdesk"], * ["sysname", "Linux"], * ["tracer_major", 2], * ["tracer_minor", 5] * ] */ BT_LOGD_STR("Creating attributes object."); attr_obj = bt_value_array_create(); if (!attr_obj) { BT_LOGE_STR("Failed to create array value."); } else { BT_LOGD("Created attributes object: addr=%p", attr_obj); } return attr_obj; }
struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name) { struct bt_ctf_event_class *ctf_event_class = NULL; int ret; if (!name) { BT_LOGW_STR("Invalid parameter: name is NULL."); goto error; } BT_LOGD("Creating event class object: name=\"%s\"", name); ctf_event_class = g_new0(struct bt_ctf_event_class, 1); if (!ctf_event_class) { BT_LOGE_STR("Failed to allocate one event class."); goto error; } ret = bt_ctf_event_class_common_initialize(BT_CTF_TO_COMMON(ctf_event_class), name, bt_ctf_event_class_destroy, (bt_ctf_field_type_structure_create_func) bt_ctf_field_type_structure_create); if (ret) { goto error; } goto end; error: bt_ctf_object_put_ref(ctf_event_class); end: return ctf_event_class; }
static inline struct bt_value *bt_value_integer_create_init(enum bt_value_type type, uint64_t uval) { struct bt_value_integer *integer_obj; BT_ASSERT(type == BT_VALUE_TYPE_UNSIGNED_INTEGER || type == BT_VALUE_TYPE_SIGNED_INTEGER); if (type == BT_VALUE_TYPE_UNSIGNED_INTEGER) { BT_LOGD("Creating unsigned integer value object: val=%" PRIu64, uval); } else { BT_LOGD("Creating signed integer value object: val=%" PRId64, (int64_t) uval); } integer_obj = g_new0(struct bt_value_integer, 1); if (!integer_obj) { BT_LOGE_STR("Failed to allocate one integer value object."); goto end; } integer_obj->base = bt_value_create_base(type); integer_obj->value.u = uval; BT_LOGD("Created %ssigned integer value object: addr=%p", type == BT_VALUE_TYPE_UNSIGNED_INTEGER ? "un" : "", integer_obj); end: return (void *) integer_obj; }
BT_HIDDEN struct bt_port *bt_port_create(struct bt_component *parent_component, enum bt_port_type type, const char *name, void *user_data) { struct bt_port *port = NULL; assert(name); assert(parent_component); assert(type == BT_PORT_TYPE_INPUT || type == BT_PORT_TYPE_OUTPUT); if (strlen(name) == 0) { BT_LOGW_STR("Invalid parameter: name is an empty string."); goto end; } port = g_new0(struct bt_port, 1); if (!port) { BT_LOGE_STR("Failed to allocate one port."); goto end; } BT_LOGD("Creating port for component: " "comp-addr=%p, comp-name=\"%s\", port-type=%s, " "port-name=\"%s\"", parent_component, bt_component_get_name(parent_component), bt_port_type_string(type), name); bt_object_init(port, bt_port_destroy); port->name = g_string_new(name); if (!port->name) { BT_LOGE_STR("Failed to allocate one GString."); BT_PUT(port); goto end; } port->type = type; port->user_data = user_data; bt_object_set_parent(port, &parent_component->base); BT_LOGD("Created port for component: " "comp-addr=%p, comp-name=\"%s\", port-type=%s, " "port-name=\"%s\", port-addr=%p", parent_component, bt_component_get_name(parent_component), bt_port_type_string(type), name, port); end: return port; }
BT_HIDDEN bt_self_message_iterator_status ctf_fs_iterator_init( bt_self_message_iterator *self_msg_iter, bt_self_component_source *self_comp, bt_self_component_port_output *self_port) { struct ctf_fs_port_data *port_data; struct ctf_fs_msg_iter_data *msg_iter_data = NULL; bt_self_message_iterator_status ret = BT_SELF_MESSAGE_ITERATOR_STATUS_OK; port_data = bt_self_component_port_get_data( bt_self_component_port_output_as_self_component_port( self_port)); BT_ASSERT(port_data); msg_iter_data = g_new0(struct ctf_fs_msg_iter_data, 1); if (!msg_iter_data) { ret = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM; goto error; } msg_iter_data->pc_msg_iter = self_msg_iter; msg_iter_data->msg_iter = bt_msg_iter_create( port_data->ds_file_group->ctf_fs_trace->metadata->tc, bt_common_get_page_size() * 8, ctf_fs_ds_file_medops, NULL); if (!msg_iter_data->msg_iter) { BT_LOGE_STR("Cannot create a CTF message iterator."); ret = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM; goto error; } msg_iter_data->ds_file_group = port_data->ds_file_group; if (ctf_fs_iterator_reset(msg_iter_data)) { ret = BT_SELF_MESSAGE_ITERATOR_STATUS_ERROR; goto error; } bt_self_message_iterator_set_data(self_msg_iter, msg_iter_data); if (ret != BT_SELF_MESSAGE_ITERATOR_STATUS_OK) { goto error; } msg_iter_data = NULL; goto end; error: bt_self_message_iterator_set_data(self_msg_iter, NULL); end: ctf_fs_msg_iter_data_destroy(msg_iter_data); return ret; }
static struct bt_value *bt_value_array_copy(const struct bt_value *array_obj) { int i; int ret; struct bt_value *copy_obj; struct bt_value_array *typed_array_obj; BT_LOGD("Copying array value: addr=%p", array_obj); typed_array_obj = BT_VALUE_TO_ARRAY(array_obj); copy_obj = bt_value_array_create(); if (!copy_obj) { BT_LOGE_STR("Cannot create empty array value."); goto end; } for (i = 0; i < typed_array_obj->garray->len; ++i) { struct bt_value *element_obj_copy = NULL; const struct bt_value *element_obj = bt_value_array_borrow_element_by_index_const( array_obj, i); BT_ASSERT(element_obj); BT_LOGD("Copying array value's element: element-addr=%p, " "index=%d", element_obj, i); ret = bt_value_copy(element_obj, &element_obj_copy); if (ret) { BT_LOGE("Cannot copy array value's element: " "array-addr=%p, index=%d", array_obj, i); BT_OBJECT_PUT_REF_AND_RESET(copy_obj); goto end; } BT_ASSERT(element_obj_copy); ret = bt_value_array_append_element(copy_obj, (void *) element_obj_copy); BT_OBJECT_PUT_REF_AND_RESET(element_obj_copy); if (ret) { BT_LOGE("Cannot append to array value: addr=%p", array_obj); BT_OBJECT_PUT_REF_AND_RESET(copy_obj); goto end; } } BT_LOGD("Copied array value: original-addr=%p, copy-addr=%p", array_obj, copy_obj); end: return copy_obj; }
BT_HIDDEN int bt_ctf_event_class_common_initialize(struct bt_ctf_event_class_common *event_class, const char *name, bt_ctf_object_release_func release_func, bt_ctf_field_type_structure_create_func ft_struct_create_func) { int ret = 0; BT_LOGD("Initializing common event class object: name=\"%s\"", name); bt_ctf_object_init_shared_with_parent(&event_class->base, release_func); event_class->payload_field_type = ft_struct_create_func(); if (!event_class->payload_field_type) { BT_LOGE_STR("Cannot create event class's initial payload field type object."); goto error; } event_class->id = -1; event_class->name = g_string_new(name); if (!event_class->name) { BT_LOGE_STR("Failed to allocate a GString."); goto error; } event_class->emf_uri = g_string_new(NULL); if (!event_class->emf_uri) { BT_LOGE_STR("Failed to allocate a GString."); goto error; } event_class->log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED; BT_LOGD("Initialized common event class object: addr=%p, name=\"%s\"", event_class, bt_ctf_event_class_common_get_name(event_class)); return ret; error: ret = -1; return ret; }
BT_HIDDEN int bt_attributes_set_field_value(struct bt_value *attr_obj, const char *name, struct bt_value *value_obj) { int ret = 0; struct bt_value *attr_field_obj = NULL; if (!attr_obj || !name || !value_obj) { BT_LOGW("Invalid parameter: attributes object, name, or value object is NULL: " "attr-value-addr=%p, name-addr=%p, value-addr=%p", attr_obj, name, value_obj); ret = -1; goto end; } attr_field_obj = bt_attributes_get_field_by_name(attr_obj, name); if (attr_field_obj) { ret = bt_value_array_set(attr_field_obj, BT_ATTR_VALUE_INDEX, value_obj); goto end; } attr_field_obj = bt_value_array_create(); if (!attr_field_obj) { BT_LOGE_STR("Failed to create empty array value."); ret = -1; goto end; } ret = bt_value_array_append_string(attr_field_obj, name); ret |= bt_value_array_append(attr_field_obj, value_obj); if (ret) { BT_LOGE("Cannot append elements to array value: addr=%p", attr_field_obj); goto end; } ret = bt_value_array_append(attr_obj, attr_field_obj); if (ret) { BT_LOGE("Cannot append element to array value: " "array-value-addr=%p, element-value-addr=%p", attr_obj, attr_field_obj); } end: BT_PUT(attr_field_obj); return ret; }
static int set_trace_name(bt_trace *trace, const char *name_suffix) { int ret = 0; const bt_trace_class *tc = bt_trace_borrow_class_const(trace); const bt_value *val; GString *name; name = g_string_new(NULL); if (!name) { BT_LOGE_STR("Failed to allocate a GString."); ret = -1; goto end; } /* * Check if we have a trace environment string value named `hostname`. * If so, use it as the trace name's prefix. */ val = bt_trace_class_borrow_environment_entry_value_by_name_const( tc, "hostname"); if (val && bt_value_is_string(val)) { g_string_append(name, bt_value_string_get(val)); if (name_suffix) { g_string_append_c(name, G_DIR_SEPARATOR); } } if (name_suffix) { g_string_append(name, name_suffix); } ret = bt_trace_set_name(trace, name->str); if (ret) { goto end; } goto end; end: if (name) { g_string_free(name, TRUE); } return ret; }
struct bt_value *bt_value_bool_create_init(bt_bool val) { struct bt_value_bool *bool_obj; BT_LOGD("Creating boolean value object: val=%d", val); bool_obj = g_new0(struct bt_value_bool, 1); if (!bool_obj) { BT_LOGE_STR("Failed to allocate one boolean value object."); goto end; } bool_obj->base = bt_value_create_base(BT_VALUE_TYPE_BOOL); bool_obj->value = val; BT_LOGD("Created boolean value object: addr=%p", bool_obj); end: return (void *) bool_obj; }
struct bt_value *bt_value_real_create_init(double val) { struct bt_value_real *real_obj; BT_LOGD("Creating real number value object: val=%f", val); real_obj = g_new0(struct bt_value_real, 1); if (!real_obj) { BT_LOGE_STR("Failed to allocate one real number value object."); goto end; } real_obj->base = bt_value_create_base(BT_VALUE_TYPE_REAL); real_obj->value = val; BT_LOGD("Created real number value object: addr=%p", real_obj); end: return (void *) real_obj; }
enum bt_value_status bt_value_copy(const struct bt_value *object, struct bt_value **copy_obj) { enum bt_value_status status = BT_VALUE_STATUS_OK; BT_ASSERT_PRE_NON_NULL(object, "Value object"); BT_ASSERT_PRE_NON_NULL(copy_obj, "Value object copy (output)"); BT_LOGD("Copying value object: addr=%p", object); *copy_obj = copy_funcs[object->type](object); if (*copy_obj) { BT_LOGD("Copied value object: copy-value-addr=%p", copy_obj); } else { status = BT_VALUE_STATUS_NOMEM; *copy_obj = NULL; BT_LOGE_STR("Failed to copy value object."); } return status; }
static inline void handle_lib_unload_event(FILE *err, struct debug_info *debug_info, struct bt_event *event) { struct proc_debug_info_sources *proc_dbg_info_src; uint64_t baddr; int64_t vpid; gpointer key_ptr = NULL; int ret; ret = get_payload_unsigned_int_field_value(err, event, BADDR_FIELD_NAME, &baddr); if (ret) { BT_LOGE_STR("Failed to get unsigned int value for " BADDR_FIELD_NAME " field."); ret = -1; goto end; } ret = get_stream_event_context_int_field_value(err, event, VPID_FIELD_NAME, &vpid); if (ret) { goto end; } proc_dbg_info_src = proc_debug_info_sources_ht_get_entry( debug_info->vpid_to_proc_dbg_info_src, vpid); if (!proc_dbg_info_src) { goto end; } key_ptr = (gpointer) &baddr; (void) g_hash_table_remove(proc_dbg_info_src->baddr_to_bin_info, key_ptr); end: return; }
BT_HIDDEN struct bt_clock_snapshot *bt_clock_snapshot_new( struct bt_clock_class *clock_class) { struct bt_clock_snapshot *ret = NULL; BT_ASSERT(clock_class); BT_LIB_LOGD("Creating clock snapshot object: %![cc-]+K=", clock_class); ret = g_new0(struct bt_clock_snapshot, 1); if (!ret) { BT_LOGE_STR("Failed to allocate one clock snapshot."); goto end; } bt_object_init_unique(&ret->base); ret->clock_class = clock_class; bt_object_get_no_null_check(clock_class); bt_clock_class_freeze(clock_class); BT_LIB_LOGD("Created clock snapshot object: %!+k", ret); end: return ret; }
struct bt_event *bt_event_create(struct bt_event_class *event_class) { int ret; enum bt_validation_flag validation_flags = BT_VALIDATION_FLAG_STREAM | BT_VALIDATION_FLAG_EVENT; struct bt_event *event = NULL; struct bt_trace *trace = NULL; struct bt_stream_class *stream_class = NULL; struct bt_field_type *packet_header_type = NULL; struct bt_field_type *packet_context_type = NULL; struct bt_field_type *event_header_type = NULL; struct bt_field_type *stream_event_ctx_type = NULL; struct bt_field_type *event_context_type = NULL; struct bt_field_type *event_payload_type = NULL; struct bt_field *event_header = NULL; struct bt_field *stream_event_context = NULL; struct bt_field *event_context = NULL; struct bt_field *event_payload = NULL; struct bt_value *environment = NULL; struct bt_validation_output validation_output = { 0 }; int trace_valid = 0; BT_LOGD("Creating event object: event-class-addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64, event_class, bt_event_class_get_name(event_class), bt_event_class_get_id(event_class)); if (!event_class) { BT_LOGW_STR("Invalid parameter: event class is NULL."); goto error; } stream_class = bt_event_class_get_stream_class(event_class); /* * We disallow the creation of an event if its event class has not been * associated to a stream class. */ if (!stream_class) { BT_LOGW_STR("Event class is not part of a stream class."); goto error; } /* The event class was frozen when added to its stream class */ assert(event_class->frozen); /* Validate the trace (if any), the stream class, and the event class */ trace = bt_stream_class_get_trace(stream_class); if (trace) { BT_LOGD_STR("Event's class is part of a trace."); packet_header_type = bt_trace_get_packet_header_type(trace); trace_valid = trace->valid; assert(trace_valid); environment = trace->environment; } packet_context_type = bt_stream_class_get_packet_context_type( stream_class); event_header_type = bt_stream_class_get_event_header_type( stream_class); stream_event_ctx_type = bt_stream_class_get_event_context_type( stream_class); event_context_type = bt_event_class_get_context_type(event_class); event_payload_type = bt_event_class_get_payload_type(event_class); ret = bt_validate_class_types(environment, packet_header_type, packet_context_type, event_header_type, stream_event_ctx_type, event_context_type, event_payload_type, trace_valid, stream_class->valid, event_class->valid, &validation_output, validation_flags); BT_PUT(packet_header_type); BT_PUT(packet_context_type); BT_PUT(event_header_type); BT_PUT(stream_event_ctx_type); BT_PUT(event_context_type); BT_PUT(event_payload_type); if (ret) { /* * This means something went wrong during the validation * process, not that the objects are invalid. */ BT_LOGE("Failed to validate event and parents: ret=%d", ret); goto error; } if ((validation_output.valid_flags & validation_flags) != validation_flags) { /* Invalid trace/stream class/event class */ BT_LOGW("Invalid trace, stream class, or event class: " "valid-flags=0x%x", validation_output.valid_flags); goto error; } /* * At this point we know the trace (if associated to the stream * class), the stream class, and the event class, with their * current types, are valid. We may proceed with creating * the event. */ event = g_new0(struct bt_event, 1); if (!event) { BT_LOGE_STR("Failed to allocate one event."); goto error; } bt_object_init(event, bt_event_destroy); /* * event does not share a common ancestor with the event class; it has * to guarantee its existence by holding a reference. This reference * shall be released once the event is associated to a stream since, * from that point, the event and its class will share the same * lifetime. */ event->event_class = bt_get(event_class); event->clock_values = g_hash_table_new_full(g_direct_hash, g_direct_equal, bt_put, bt_put); if (validation_output.event_header_type) { BT_LOGD("Creating initial event header field: ft-addr=%p", validation_output.event_header_type); event_header = bt_field_create(validation_output.event_header_type); if (!event_header) { BT_LOGE_STR("Cannot create initial event header field object."); goto error; } } if (validation_output.stream_event_ctx_type) { BT_LOGD("Creating initial stream event context field: ft-addr=%p", validation_output.stream_event_ctx_type); stream_event_context = bt_field_create( validation_output.stream_event_ctx_type); if (!stream_event_context) { BT_LOGE_STR("Cannot create initial stream event context field object."); goto error; } } if (validation_output.event_context_type) { BT_LOGD("Creating initial event context field: ft-addr=%p", validation_output.event_context_type); event_context = bt_field_create( validation_output.event_context_type); if (!event_context) { BT_LOGE_STR("Cannot create initial event context field object."); goto error; } } if (validation_output.event_payload_type) { BT_LOGD("Creating initial event payload field: ft-addr=%p", validation_output.event_payload_type); event_payload = bt_field_create( validation_output.event_payload_type); if (!event_payload) { BT_LOGE_STR("Cannot create initial event payload field object."); goto error; } } /* * At this point all the fields are created, potentially from * validated copies of field types, so that the field types and * fields can be replaced in the trace, stream class, * event class, and created event. */ bt_validation_replace_types(trace, stream_class, event_class, &validation_output, validation_flags); BT_MOVE(event->event_header, event_header); BT_MOVE(event->stream_event_context, stream_event_context); BT_MOVE(event->context_payload, event_context); BT_MOVE(event->fields_payload, event_payload); /* * Put what was not moved in bt_validation_replace_types(). */ bt_validation_output_put_types(&validation_output); /* * Freeze the stream class since the event header must not be changed * anymore. */ bt_stream_class_freeze(stream_class); /* * Mark stream class, and event class as valid since * they're all frozen now. */ stream_class->valid = 1; event_class->valid = 1; /* Put stuff we borrowed from the event class */ BT_PUT(stream_class); BT_PUT(trace); BT_LOGD("Created event object: addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64, event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event_class)); return event; error: bt_validation_output_put_types(&validation_output); BT_PUT(event); BT_PUT(stream_class); BT_PUT(trace); BT_PUT(event_header); BT_PUT(stream_event_context); BT_PUT(event_context); BT_PUT(event_payload); assert(!packet_header_type); assert(!packet_context_type); assert(!event_header_type); assert(!stream_event_ctx_type); assert(!event_context_type); assert(!event_payload_type); return event; }
G_MODULE_EXPORT struct bt_plugin_set *bt_plugin_python_create_all_from_file(const char *path) { struct bt_plugin_set *plugin_set = NULL; struct bt_plugin *plugin = NULL; PyObject *py_plugin_info = NULL; gchar *basename = NULL; size_t path_len; assert(path); if (python_state == PYTHON_STATE_CANNOT_INITIALIZE) { /* * We do not even care about the rest of the function * here because we already know Python cannot be fully * initialized. */ goto error; } BT_LOGD("Creating all Python plugins from file: path=\"%s\"", path); path_len = strlen(path); /* File name ends with `.py` */ if (strncmp(path + path_len - PYTHON_PLUGIN_FILE_EXT_LEN, PYTHON_PLUGIN_FILE_EXT, PYTHON_PLUGIN_FILE_EXT_LEN) != 0) { BT_LOGD("Skipping non-Python file: path=\"%s\"", path); goto error; } /* File name starts with `bt_plugin_` */ basename = g_path_get_basename(path); if (!basename) { BT_LOGW("Cannot get path's basename: path=\"%s\"", path); goto error; } if (strncmp(basename, PYTHON_PLUGIN_FILE_PREFIX, PYTHON_PLUGIN_FILE_PREFIX_LEN) != 0) { BT_LOGD("Skipping Python file not starting with `%s`: " "path=\"%s\"", PYTHON_PLUGIN_FILE_PREFIX, path); goto error; } /* * Initialize Python now. * * This is not done in the library contructor because the * interpreter is somewhat slow to initialize. If you don't * have any potential Python plugins, you don't need to endure * this waiting time everytime you load the library. */ init_python(); if (python_state != PYTHON_STATE_FULLY_INITIALIZED) { /* * For some reason we cannot initialize Python, * import the required modules, and get the required * attributes from them. */ BT_LOGI("Failed to initialize Python interpreter."); goto error; } /* * Call bt2.py_plugin._try_load_plugin_module() with this path * to get plugin info if the plugin is loadable and complete. * This function returns None when there's an error, but just in * case we also manually clear the last Python error state. */ BT_LOGD_STR("Getting Python plugin info object from Python module."); py_plugin_info = PyObject_CallFunction(py_try_load_plugin_module_func, "(s)", path); if (!py_plugin_info || py_plugin_info == Py_None) { BT_LOGW("Cannot load Python plugin: path=\"%s\"", path); print_python_traceback_warn(); PyErr_Clear(); goto error; } /* * Get bt_plugin from plugin info object. */ plugin = bt_plugin_from_python_plugin_info(py_plugin_info); if (!plugin) { BT_LOGW("Cannot create plugin object from Python plugin info object: " "path=\"%s\", py-plugin-info-addr=%p", path, py_plugin_info); goto error; } bt_plugin_set_path(plugin, path); plugin_set = bt_plugin_set_create(); if (!plugin_set) { BT_LOGE_STR("Cannot create empty plugin set."); goto error; } bt_plugin_set_add_plugin(plugin_set, plugin); BT_LOGD("Created all Python plugins from file: path=\"%s\", " "plugin-addr=%p, plugin-name=\"%s\"", path, plugin, bt_plugin_get_name(plugin)); goto end; error: BT_PUT(plugin_set); end: bt_put(plugin); Py_XDECREF(py_plugin_info); g_free(basename); return plugin_set; }
static struct bt_plugin *bt_plugin_from_python_plugin_info(PyObject *plugin_info) { struct bt_plugin *plugin = NULL; PyObject *py_name = NULL; PyObject *py_author = NULL; PyObject *py_description = NULL; PyObject *py_license = NULL; PyObject *py_version = NULL; PyObject *py_comp_class_addrs = NULL; const char *name = NULL; const char *author = NULL; const char *description = NULL; const char *license = NULL; unsigned int major = 0, minor = 0, patch = 0; const char *version_extra = NULL; int ret; assert(plugin_info); assert(python_state == PYTHON_STATE_FULLY_INITIALIZED); py_name = PyObject_GetAttrString(plugin_info, "name"); if (!py_name) { BT_LOGW("Cannot find `name` attribute in Python plugin info object: " "py-plugin-info-addr=%p", plugin_info); goto error; } py_author = PyObject_GetAttrString(plugin_info, "author"); if (!py_author) { BT_LOGW("Cannot find `author` attribute in Python plugin info object: " "py-plugin-info-addr=%p", plugin_info); goto error; } py_description = PyObject_GetAttrString(plugin_info, "description"); if (!py_description) { BT_LOGW("Cannot find `desciption` attribute in Python plugin info object: " "py-plugin-info-addr=%p", plugin_info); goto error; } py_license = PyObject_GetAttrString(plugin_info, "license"); if (!py_license) { BT_LOGW("Cannot find `license` attribute in Python plugin info object: " "py-plugin-info-addr=%p", plugin_info); goto error; } py_version = PyObject_GetAttrString(plugin_info, "version"); if (!py_version) { BT_LOGW("Cannot find `version` attribute in Python plugin info object: " "py-plugin-info-addr=%p", plugin_info); goto error; } py_comp_class_addrs = PyObject_GetAttrString(plugin_info, "comp_class_addrs"); if (!py_comp_class_addrs) { BT_LOGW("Cannot find `comp_class_addrs` attribute in Python plugin info object: " "py-plugin-info-addr=%p", plugin_info); goto error; } if (PyUnicode_Check(py_name)) { name = PyUnicode_AsUTF8(py_name); if (!name) { BT_LOGW("Cannot decode Python plugin name string: " "py-plugin-info-addr=%p", plugin_info); goto error; } } else { /* Plugin name is mandatory */ BT_LOGW("Plugin name is not a string: " "py-plugin-info-addr=%p", plugin_info); goto error; } if (PyUnicode_Check(py_author)) { author = PyUnicode_AsUTF8(py_author); if (!author) { BT_LOGW("Cannot decode Python plugin author string: " "py-plugin-info-addr=%p", plugin_info); goto error; } } if (PyUnicode_Check(py_description)) { description = PyUnicode_AsUTF8(py_description); if (!description) { BT_LOGW("Cannot decode Python plugin description string: " "py-plugin-info-addr=%p", plugin_info); goto error; } } if (PyUnicode_Check(py_license)) { license = PyUnicode_AsUTF8(py_license); if (!license) { BT_LOGW("Cannot decode Python plugin license string: " "py-plugin-info-addr=%p", plugin_info); goto error; } } if (PyTuple_Check(py_version)) { if (PyTuple_Size(py_version) >= 3) { PyObject *py_major = PyTuple_GetItem(py_version, 0); PyObject *py_minor = PyTuple_GetItem(py_version, 1); PyObject *py_patch = PyTuple_GetItem(py_version, 2); assert(py_major); assert(py_minor); assert(py_patch); if (PyLong_Check(py_major)) { major = PyLong_AsUnsignedLong(py_major); } if (PyLong_Check(py_minor)) { minor = PyLong_AsUnsignedLong(py_minor); } if (PyLong_Check(py_patch)) { patch = PyLong_AsUnsignedLong(py_patch); } if (PyErr_Occurred()) { /* Overflow error, most probably */ BT_LOGW("Invalid Python plugin version format: " "py-plugin-info-addr=%p", plugin_info); goto error; } } if (PyTuple_Size(py_version) >= 4) { PyObject *py_extra = PyTuple_GetItem(py_version, 3); assert(py_extra); if (PyUnicode_Check(py_extra)) { version_extra = PyUnicode_AsUTF8(py_extra); if (!version_extra) { BT_LOGW("Cannot decode Python plugin version's extra string: " "py-plugin-info-addr=%p", plugin_info); goto error; } } } } plugin = bt_plugin_create_empty(BT_PLUGIN_TYPE_PYTHON); if (!plugin) { BT_LOGE_STR("Cannot create empty plugin object."); goto error; } bt_plugin_set_name(plugin, name); if (description) { bt_plugin_set_description(plugin, description); } if (author) { bt_plugin_set_author(plugin, author); } if (license) { bt_plugin_set_license(plugin, license); } bt_plugin_set_version(plugin, major, minor, patch, version_extra); if (PyList_Check(py_comp_class_addrs)) { size_t i; for (i = 0; i < PyList_Size(py_comp_class_addrs); i++) { struct bt_component_class *comp_class; PyObject *py_comp_class_addr; py_comp_class_addr = PyList_GetItem(py_comp_class_addrs, i); assert(py_comp_class_addr); if (PyLong_Check(py_comp_class_addr)) { comp_class = (struct bt_component_class *) PyLong_AsUnsignedLongLong(py_comp_class_addr); } else { BT_LOGW("Component class address is not an integer in Python plugin info object: " "py-plugin-info-addr=%p, index=%zu", plugin_info, i); continue; } ret = bt_plugin_add_component_class(plugin, comp_class); if (ret < 0) { BT_LOGE("Cannot add component class to plugin: " "py-plugin-info-addr=%p, " "plugin-addr=%p, plugin-name=\"%s\", " "comp-class-addr=%p, " "comp-class-name=\"%s\", " "comp-class-type=%s", plugin_info, plugin, bt_plugin_get_name(plugin), comp_class, bt_component_class_get_name(comp_class), bt_component_class_type_string( bt_component_class_get_type(comp_class))); continue; } } } bt_plugin_freeze(plugin); goto end; error: print_python_traceback_warn(); pyerr_clear(); BT_PUT(plugin); end: Py_XDECREF(py_name); Py_XDECREF(py_author); Py_XDECREF(py_description); Py_XDECREF(py_license); Py_XDECREF(py_version); Py_XDECREF(py_comp_class_addrs); return plugin; }
static inline struct bt_message *create_discarded_items_message( struct bt_self_message_iterator *self_msg_iter, enum bt_message_type type, struct bt_stream *stream, bool with_cs, uint64_t beginning_raw_value, uint64_t end_raw_value) { struct bt_message_discarded_items *message; struct bt_stream_class *stream_class; BT_ASSERT_PRE_NON_NULL(self_msg_iter, "Message iterator"); BT_ASSERT_PRE_NON_NULL(stream, "Stream"); stream_class = bt_stream_borrow_class(stream); BT_ASSERT(stream_class); BT_ASSERT_PRE((with_cs && stream_class->default_clock_class) || (!with_cs && !stream_class->default_clock_class), "Creating a message with a default clock snapshot, but without " "a default clock class, or without a default clock snapshot, " "but with a default clock class: ", "type=%s, %![stream-]+s, %![sc-]+S, with-cs=%d, " "cs-begin-val=%" PRIu64 ", cs-end-val=%" PRIu64, bt_message_type_string(type), stream, stream_class, with_cs, beginning_raw_value, end_raw_value); BT_LIB_LOGD("Creating discarded items message object: " "type=%s, %![stream-]+s, %![sc-]+S, with-cs=%d, " "cs-begin-val=%" PRIu64 ", cs-end-val=%" PRIu64, bt_message_type_string(type), stream, stream_class, with_cs, beginning_raw_value, end_raw_value); message = g_new0(struct bt_message_discarded_items, 1); if (!message) { BT_LOGE_STR("Failed to allocate one discarded items message."); goto error; } bt_message_init(&message->parent, type, destroy_discarded_items_message, NULL); message->stream = stream; bt_object_get_no_null_check(message->stream); if (with_cs) { BT_ASSERT(stream_class->default_clock_class); message->default_begin_cs = bt_clock_snapshot_create( stream_class->default_clock_class); if (!message->default_begin_cs) { goto error; } bt_clock_snapshot_set_raw_value(message->default_begin_cs, beginning_raw_value); message->default_end_cs = bt_clock_snapshot_create( stream_class->default_clock_class); if (!message->default_end_cs) { goto error; } bt_clock_snapshot_set_raw_value(message->default_end_cs, end_raw_value); } bt_property_uint_init(&message->count, BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE, 0); BT_LIB_LOGD("Created discarded items message object: " "%![msg-]+n, %![stream-]+s, %![sc-]+S", message, stream, stream_class); return (void *) &message->parent; error: return NULL; }
static void handle_bin_info_event(FILE *err, struct debug_info *debug_info, struct bt_event *event, bool has_pic_field) { struct proc_debug_info_sources *proc_dbg_info_src; struct bin_info *bin; uint64_t baddr, memsz; int64_t vpid; const char *path; gpointer key = NULL; bool is_pic; int ret; ret = get_payload_unsigned_int_field_value(err, event, BADDR_FIELD_NAME, &baddr); if (ret) { BT_LOGE_STR("Failed to get unsigned int value for " BADDR_FIELD_NAME " field."); goto end; } ret = get_payload_unsigned_int_field_value(err, event, MEMSZ_FIELD_NAME, &memsz); if (ret) { BT_LOGE_STR("Failed to get unsigned int value for " MEMSZ_FIELD_NAME " field."); goto end; } /* * This field is not produced by the dlopen event emitted before * lttng-ust 2.9. */ ret = get_payload_string_field_value(err, event, PATH_FIELD_NAME, &path); if (ret || !path) { goto end; } if (has_pic_field) { uint64_t tmp; ret = get_payload_unsigned_int_field_value(err, event, IS_PIC_FIELD_NAME, &tmp); if (ret) { BT_LOGE_STR("Failed to get unsigned int value for " IS_PIC_FIELD_NAME " field."); ret = -1; goto end; } is_pic = (tmp == 1); } else { /* * dlopen has no is_pic field, because the shared * object is always PIC. */ is_pic = true; } ret = get_stream_event_context_int_field_value(err, event, VPID_FIELD_NAME, &vpid); if (ret) { goto end; } if (memsz == 0) { /* Ignore VDSO. */ goto end; } proc_dbg_info_src = proc_debug_info_sources_ht_get_entry( debug_info->vpid_to_proc_dbg_info_src, vpid); if (!proc_dbg_info_src) { goto end; } key = g_new0(uint64_t, 1); if (!key) { goto end; } *((uint64_t *) key) = baddr; bin = g_hash_table_lookup(proc_dbg_info_src->baddr_to_bin_info, key); if (bin) { goto end; } bin = bin_info_create(path, baddr, memsz, is_pic, debug_info->comp->arg_debug_dir, debug_info->comp->arg_target_prefix); if (!bin) { goto end; } g_hash_table_insert(proc_dbg_info_src->baddr_to_bin_info, key, bin); /* Ownership passed to ht. */ key = NULL; end: g_free(key); return; }
static void handle_statedump_debug_link_event(FILE *err, struct debug_info *debug_info, struct bt_event *event) { struct proc_debug_info_sources *proc_dbg_info_src; struct bin_info *bin = NULL; int64_t vpid; uint64_t baddr; const char *filename = NULL; uint32_t crc32; uint64_t tmp; int ret; ret = get_stream_event_context_int_field_value(err, event, VPID_FIELD_NAME, &vpid); if (ret) { goto end; } ret = get_payload_unsigned_int_field_value(err, event, BADDR_FIELD_NAME, &baddr); if (ret) { BT_LOGE_STR("Failed to get unsigned int value for " BADDR_FIELD_NAME " field."); ret = -1; goto end; } ret = get_payload_unsigned_int_field_value(err, event, CRC32_FIELD_NAME, &tmp); if (ret) { BT_LOGE_STR("Failed to get unsigned int value for " CRC32_FIELD_NAME " field."); ret = -1; goto end; } crc32 = (uint32_t) tmp; ret = get_payload_string_field_value(err, event, FILENAME_FIELD_NAME, &filename); if (ret) { BT_LOGE_STR("Failed to get string value for " FILENAME_FIELD_NAME " field."); ret = -1; goto end; } proc_dbg_info_src = proc_debug_info_sources_ht_get_entry( debug_info->vpid_to_proc_dbg_info_src, vpid); if (!proc_dbg_info_src) { goto end; } bin = g_hash_table_lookup(proc_dbg_info_src->baddr_to_bin_info, (gpointer) &baddr); if (!bin) { /* * The debug_link event comes after the bin has been * created. If it isn't found, just ignore this event. */ goto end; } bin_info_set_debug_link(bin, filename, crc32); end: return; }
static void handle_statedump_build_id_event(FILE *err, struct debug_info *debug_info, struct bt_event *event) { struct proc_debug_info_sources *proc_dbg_info_src; struct bin_info *bin = NULL; int ret; int64_t vpid; uint64_t baddr; uint64_t build_id_len; ret = get_stream_event_context_int_field_value(err, event, VPID_FIELD_NAME, &vpid); if (ret) { goto end; } ret = get_payload_unsigned_int_field_value(err, event, BADDR_FIELD_NAME, &baddr); if (ret) { BT_LOGE_STR("Failed to get unsigned int value for " VPID_FIELD_NAME " field."); goto end; } proc_dbg_info_src = proc_debug_info_sources_ht_get_entry( debug_info->vpid_to_proc_dbg_info_src, vpid); if (!proc_dbg_info_src) { goto end; } bin = g_hash_table_lookup(proc_dbg_info_src->baddr_to_bin_info, (gpointer) &baddr); if (!bin) { /* * The build_id event comes after the bin has been * created. If it isn't found, just ignore this event. */ goto end; } ret = get_payload_build_id_field_value(err, event, BUILD_ID_FIELD_NAME, &bin->build_id, &build_id_len); if (ret) { BT_LOGE_STR("Failed to get " BUILD_ID_FIELD_NAME " field value."); goto end; } if (build_id_len > SIZE_MAX) { bin->build_id_len = (size_t) build_id_len; } /* * Reset the is_elf_only flag in case it had been set * previously, because we might find separate debug info using * the new build id information. */ bin->is_elf_only = false; // TODO // bin_info_set_build_id(bin, build_id, build_id_len); end: return; }
BT_HIDDEN struct ctf_metadata_decoder *ctf_metadata_decoder_create( const struct ctf_metadata_decoder_config *config, const char *name) { struct ctf_metadata_decoder *mdec = g_new0(struct ctf_metadata_decoder, 1); struct ctf_metadata_decoder_config default_config = { .clock_class_offset_s = 0, .clock_class_offset_ns = 0, }; if (!config) { config = &default_config; } BT_LOGD("Creating CTF metadata decoder: " "clock-class-offset-s=%" PRId64 ", " "clock-class-offset-ns=%" PRId64 ", name=\"%s\"", config->clock_class_offset_s, config->clock_class_offset_ns, name); if (!mdec) { BT_LOGE_STR("Failed to allocate one CTF metadata decoder."); goto end; } mdec->config = *config; mdec->visitor = ctf_visitor_generate_ir_create(config, name); if (!mdec->visitor) { BT_LOGE("Failed to create a CTF IR metadata AST visitor: " "mdec-addr=%p", mdec); ctf_metadata_decoder_destroy(mdec); mdec = NULL; goto end; } BT_LOGD("Creating CTF metadata decoder: " "clock-class-offset-s=%" PRId64 ", " "clock-class-offset-ns=%" PRId64 ", " "name=\"%s\", addr=%p", config->clock_class_offset_s, config->clock_class_offset_ns, name, mdec); end: return mdec; } BT_HIDDEN void ctf_metadata_decoder_destroy(struct ctf_metadata_decoder *mdec) { if (!mdec) { return; } BT_LOGD("Destroying CTF metadata decoder: addr=%p", mdec); ctf_visitor_generate_ir_destroy(mdec->visitor); g_free(mdec); } BT_HIDDEN enum ctf_metadata_decoder_status ctf_metadata_decoder_decode( struct ctf_metadata_decoder *mdec, FILE *fp) { enum ctf_metadata_decoder_status status = CTF_METADATA_DECODER_STATUS_OK; int ret; struct ctf_scanner *scanner = NULL; char *buf = NULL; bool close_fp = false; assert(mdec); if (ctf_metadata_decoder_is_packetized(fp, &mdec->bo)) { BT_LOGD("Metadata stream is packetized: mdec-addr=%p", mdec); ret = ctf_metadata_decoder_packetized_file_stream_to_buf_with_mdec( mdec, fp, &buf, mdec->bo); if (ret) { BT_LOGE("Cannot decode packetized metadata packets to metadata text: " "mdec-addr=%p, ret=%d", mdec, ret); status = CTF_METADATA_DECODER_STATUS_ERROR; goto end; } if (strlen(buf) == 0) { /* An empty metadata packet is OK. */ goto end; } /* Convert the real file pointer to a memory file pointer */ fp = bt_fmemopen(buf, strlen(buf), "rb"); close_fp = true; if (!fp) { BT_LOGE("Cannot memory-open metadata buffer: %s: " "mdec-addr=%p", strerror(errno), mdec); status = CTF_METADATA_DECODER_STATUS_ERROR; goto end; } } else { unsigned int major, minor; ssize_t nr_items; const long init_pos = ftell(fp); BT_LOGD("Metadata stream is plain text: mdec-addr=%p", mdec); if (init_pos < 0) { BT_LOGE_ERRNO("Failed to get current file position", "."); status = CTF_METADATA_DECODER_STATUS_ERROR; goto end; } /* Check text-only metadata header and version */ nr_items = fscanf(fp, "/* CTF %10u.%10u", &major, &minor); if (nr_items < 2) { BT_LOGW("Missing \"/* CTF major.minor\" signature in plain text metadata file stream: " "mdec-addr=%p", mdec); } BT_LOGD("Found metadata stream version in signature: version=%u.%u", major, minor); if (!is_version_valid(major, minor)) { BT_LOGE("Invalid metadata version found in plain text signature: " "version=%u.%u, mdec-addr=%p", major, minor, mdec); status = CTF_METADATA_DECODER_STATUS_INVAL_VERSION; goto end; } if (fseek(fp, init_pos, SEEK_SET)) { BT_LOGE("Cannot seek metadata file stream to initial position: %s: " "mdec-addr=%p", strerror(errno), mdec); status = CTF_METADATA_DECODER_STATUS_ERROR; goto end; } } if (BT_LOG_ON_VERBOSE) { yydebug = 1; } /* Allocate a scanner and append the metadata text content */ scanner = ctf_scanner_alloc(); if (!scanner) { BT_LOGE("Cannot allocate a metadata lexical scanner: " "mdec-addr=%p", mdec); status = CTF_METADATA_DECODER_STATUS_ERROR; goto end; } assert(fp); ret = ctf_scanner_append_ast(scanner, fp); if (ret) { BT_LOGE("Cannot create the metadata AST out of the metadata text: " "mdec-addr=%p", mdec); status = CTF_METADATA_DECODER_STATUS_INCOMPLETE; goto end; } ret = ctf_visitor_semantic_check(0, &scanner->ast->root); if (ret) { BT_LOGE("Validation of the metadata semantics failed: " "mdec-addr=%p", mdec); status = CTF_METADATA_DECODER_STATUS_ERROR; goto end; } ret = ctf_visitor_generate_ir_visit_node(mdec->visitor, &scanner->ast->root); switch (ret) { case 0: /* Success */ break; case -EINCOMPLETE: BT_LOGD("While visiting metadata AST: incomplete data: " "mdec-addr=%p", mdec); status = CTF_METADATA_DECODER_STATUS_INCOMPLETE; goto end; default: BT_LOGE("Failed to visit AST node to create CTF IR objects: " "mdec-addr=%p, ret=%d", mdec, ret); status = CTF_METADATA_DECODER_STATUS_IR_VISITOR_ERROR; goto end; } end: if (scanner) { ctf_scanner_free(scanner); } yydebug = 0; if (fp && close_fp) { if (fclose(fp)) { BT_LOGE("Cannot close metadata file stream: " "mdec-addr=%p", mdec); } } if (buf) { free(buf); } return status; } BT_HIDDEN struct bt_trace *ctf_metadata_decoder_get_trace( struct ctf_metadata_decoder *mdec) { return ctf_visitor_generate_ir_get_trace(mdec->visitor); }
static int add_ds_file_to_ds_file_group(struct ctf_fs_trace *ctf_fs_trace, const char *path) { int64_t stream_instance_id = -1; int64_t begin_ns = -1; struct ctf_fs_ds_file_group *ds_file_group = NULL; bool add_group = false; int ret; size_t i; struct ctf_fs_ds_file *ds_file = NULL; struct ctf_fs_ds_index *index = NULL; struct bt_msg_iter *msg_iter = NULL; struct ctf_stream_class *sc = NULL; struct bt_msg_iter_packet_properties props; msg_iter = bt_msg_iter_create(ctf_fs_trace->metadata->tc, bt_common_get_page_size() * 8, ctf_fs_ds_file_medops, NULL); if (!msg_iter) { BT_LOGE_STR("Cannot create a CTF message iterator."); goto error; } ds_file = ctf_fs_ds_file_create(ctf_fs_trace, NULL, msg_iter, NULL, path); if (!ds_file) { goto error; } ret = bt_msg_iter_get_packet_properties(ds_file->msg_iter, &props); if (ret) { BT_LOGE("Cannot get stream file's first packet's header and context fields (`%s`).", path); goto error; } sc = ctf_trace_class_borrow_stream_class_by_id(ds_file->metadata->tc, props.stream_class_id); BT_ASSERT(sc); stream_instance_id = props.data_stream_id; if (props.snapshots.beginning_clock != UINT64_C(-1)) { BT_ASSERT(sc->default_clock_class); ret = bt_util_clock_cycles_to_ns_from_origin( props.snapshots.beginning_clock, sc->default_clock_class->frequency, sc->default_clock_class->offset_seconds, sc->default_clock_class->offset_cycles, &begin_ns); if (ret) { BT_LOGE("Cannot convert clock cycles to nanoseconds from origin (`%s`).", path); goto error; } } index = ctf_fs_ds_file_build_index(ds_file); if (!index) { BT_LOGW("Failed to index CTF stream file \'%s\'", ds_file->file->path->str); } if (begin_ns == -1) { /* * No beggining timestamp to sort the stream files * within a stream file group, so consider that this * file must be the only one within its group. */ stream_instance_id = -1; } if (stream_instance_id == -1) { /* * No stream instance ID or no beginning timestamp: * create a unique stream file group for this stream * file because, even if there's a stream instance ID, * there's no timestamp to order the file within its * group. */ ds_file_group = ctf_fs_ds_file_group_create(ctf_fs_trace, sc, UINT64_C(-1)); if (!ds_file_group) { goto error; } ret = ctf_fs_ds_file_group_add_ds_file_info(ds_file_group, path, begin_ns, index); /* Ownership of index is transferred. */ index = NULL; if (ret) { goto error; } add_group = true; goto end; } BT_ASSERT(stream_instance_id != -1); BT_ASSERT(begin_ns != -1); /* Find an existing stream file group with this ID */ for (i = 0; i < ctf_fs_trace->ds_file_groups->len; i++) { ds_file_group = g_ptr_array_index( ctf_fs_trace->ds_file_groups, i); if (ds_file_group->sc == sc && ds_file_group->stream_id == stream_instance_id) { break; } ds_file_group = NULL; } if (!ds_file_group) { ds_file_group = ctf_fs_ds_file_group_create(ctf_fs_trace, sc, stream_instance_id); if (!ds_file_group) { goto error; } add_group = true; } ret = ctf_fs_ds_file_group_add_ds_file_info(ds_file_group, path, begin_ns, index); index = NULL; if (ret) { goto error; } goto end; error: ctf_fs_ds_file_group_destroy(ds_file_group); ds_file_group = NULL; ret = -1; end: if (add_group && ds_file_group) { g_ptr_array_add(ctf_fs_trace->ds_file_groups, ds_file_group); } ctf_fs_ds_file_destroy(ds_file); if (msg_iter) { bt_msg_iter_destroy(msg_iter); } ctf_fs_ds_index_destroy(index); return ret; }