Esempio n. 1
0
static
int add_trace_path(GList **trace_paths, const char *path)
{
	GString *norm_path = NULL;
	int ret = 0;

	norm_path = bt_common_normalize_path(path, NULL);
	if (!norm_path) {
		BT_LOGE("Failed to normalize path `%s`.", path);
		ret = -1;
		goto end;
	}

	// FIXME: Remove or ifdef for __MINGW32__
	if (strcmp(norm_path->str, "/") == 0) {
		BT_LOGE("Opening a trace in `/` is not supported.");
		ret = -1;
		goto end;
	}

	*trace_paths = g_list_prepend(*trace_paths, norm_path);
	BT_ASSERT(*trace_paths);
	norm_path = NULL;

end:
	if (norm_path) {
		g_string_free(norm_path, TRUE);
	}

	return ret;
}
Esempio n. 2
0
BT_HIDDEN
struct bt_value *bt_attributes_get_field_value(struct bt_value *attr_obj,
		uint64_t index)
{
	struct bt_value *value_obj = NULL;
	struct bt_value *attr_field_obj = NULL;

	if (!attr_obj) {
		BT_LOGW_STR("Invalid parameter: attributes object is NULL.");
		goto end;
	}

	attr_field_obj = bt_value_array_get(attr_obj, index);
	if (!attr_field_obj) {
		BT_LOGE("Cannot get attributes object's array value's element by index: "
			"value-addr=%p, index=%" PRIu64, attr_obj, index);
		goto end;
	}

	value_obj = bt_value_array_get(attr_field_obj,
		BT_ATTR_VALUE_INDEX);
	if (!value_obj) {
		BT_LOGE("Cannot get attribute array value's element by index: "
			"value-addr=%p, index=%" PRIu64, attr_field_obj,
			(uint64_t) BT_ATTR_VALUE_INDEX);
	}

end:
	BT_PUT(attr_field_obj);
	return value_obj;
}
Esempio n. 3
0
enum bt_value_status bt_value_map_extend(
		const struct bt_value *base_map_obj,
		const struct bt_value *extension_obj,
		struct bt_value **extended_map_obj)
{
	struct extend_map_element_data extend_data = {
		.extended_obj = NULL,
		.status = BT_VALUE_STATUS_OK,
	};

	BT_ASSERT_PRE_NON_NULL(base_map_obj, "Base value object");
	BT_ASSERT_PRE_NON_NULL(extension_obj, "Extension value object");
	BT_ASSERT_PRE_NON_NULL(extended_map_obj,
		"Extended value object (output)");
	BT_ASSERT_PRE_VALUE_IS_TYPE(base_map_obj, BT_VALUE_TYPE_MAP);
	BT_ASSERT_PRE_VALUE_IS_TYPE(extension_obj, BT_VALUE_TYPE_MAP);
	BT_LOGD("Extending map value: base-value-addr=%p, extension-value-addr=%p",
		base_map_obj, extension_obj);
	*extended_map_obj = NULL;

	/* Create copy of base map object to start with */
	extend_data.status = bt_value_copy(base_map_obj, extended_map_obj);
	if (extend_data.status) {
		BT_LOGE("Cannot copy base value: base-value-addr=%p",
			base_map_obj);
		goto error;
	}

	BT_ASSERT(extended_map_obj);

	/*
	 * For each key in the extension map object, replace this key
	 * in the copied map object.
	 */
	extend_data.extended_obj = *extended_map_obj;

	if (bt_value_map_foreach_entry_const(extension_obj, extend_map_element,
			&extend_data)) {
		BT_LOGE("Cannot iterate on the extension object's elements: "
			"extension-value-addr=%p", extension_obj);
		goto error;
	}

	if (extend_data.status) {
		BT_LOGE("Failed to successfully iterate on the extension object's elements: "
			"extension-value-addr=%p", extension_obj);
		goto error;
	}

	BT_LOGD("Extended map value: extended-value-addr=%p",
		*extended_map_obj);
	goto end;

error:
	BT_OBJECT_PUT_REF_AND_RESET(*extended_map_obj);
	*extended_map_obj = NULL;

end:
	return extend_data.status;
}
Esempio n. 4
0
int ctf_fs_metadata_set_trace(struct ctf_fs_trace *ctf_fs_trace,
		struct ctf_fs_metadata_config *config)
{
	int ret = 0;
	struct ctf_fs_file *file = NULL;
	struct ctf_metadata_decoder *metadata_decoder = NULL;
	struct ctf_metadata_decoder_config decoder_config = {
		.clock_class_offset_s = config ? config->clock_class_offset_s : 0,
		.clock_class_offset_ns = config ? config->clock_class_offset_ns : 0,
	};

	file = get_file(ctf_fs_trace->path->str);
	if (!file) {
		BT_LOGE("Cannot create metadata file object");
		ret = -1;
		goto end;
	}

	metadata_decoder = ctf_metadata_decoder_create(
		config ? &decoder_config : NULL,
		ctf_fs_trace->name->str);
	if (!metadata_decoder) {
		BT_LOGE("Cannot create metadata decoder object");
		ret = -1;
		goto end;
	}

	ret = ctf_metadata_decoder_decode(metadata_decoder, file->fp);
	if (ret) {
		BT_LOGE("Cannot decode metadata file");
		goto end;
	}

	ctf_fs_trace->metadata->trace = ctf_metadata_decoder_get_trace(
		metadata_decoder);
	assert(ctf_fs_trace->metadata->trace);

end:
	ctf_fs_file_destroy(file);
	ctf_metadata_decoder_destroy(metadata_decoder);
	return ret;
}

int ctf_fs_metadata_init(struct ctf_fs_metadata *metadata)
{
	/* Nothing to initialize for the moment. */
	return 0;
}

void ctf_fs_metadata_fini(struct ctf_fs_metadata *metadata)
{
	if (metadata->text) {
		free(metadata->text);
	}

	if (metadata->trace) {
		BT_PUT(metadata->trace);
	}
}
Esempio n. 5
0
static
struct bt_value *bt_attributes_get_field_by_name(
		struct bt_value *attr_obj, const char *name)
{
	uint64_t i;
	int64_t attr_size;
	struct bt_value *value_obj = NULL;
	struct bt_value *attr_field_name_obj = NULL;

	attr_size = bt_value_array_size(attr_obj);
	if (attr_size < 0) {
		BT_LOGE("Cannot get array value's size: value-addr=%p",
			attr_obj);
		goto error;
	}

	for (i = 0; i < attr_size; ++i) {
		int ret;
		const char *field_name;

		value_obj = bt_value_array_get(attr_obj, i);
		if (!value_obj) {
			BT_LOGE("Cannot get attributes object's array value's element by index: "
				"value-addr=%p, index=%" PRIu64, attr_obj, i);
			goto error;
		}

		attr_field_name_obj = bt_value_array_get(value_obj, 0);
		if (!attr_field_name_obj) {
			BT_LOGE("Cannot get attribute array value's element by index: "
				"value-addr=%p, index=%" PRIu64,
				value_obj, (int64_t) 0);
			goto error;
		}

		ret = bt_value_string_get(attr_field_name_obj, &field_name);
		if (ret) {
			BT_LOGE("Cannot get raw value from string value: value-addr=%p",
				attr_field_name_obj);
			goto error;
		}

		if (!strcmp(field_name, name)) {
			BT_PUT(attr_field_name_obj);
			break;
		}

		BT_PUT(attr_field_name_obj);
		BT_PUT(value_obj);
	}

	return value_obj;

error:
	BT_PUT(attr_field_name_obj);
	BT_PUT(value_obj);

	return value_obj;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
static
struct bt_value *bt_value_map_copy(const struct bt_value *map_obj)
{
	int ret;
	GHashTableIter iter;
	gpointer key, element_obj;
	struct bt_value *copy_obj;
	struct bt_value *element_obj_copy = NULL;
	struct bt_value_map *typed_map_obj;

	BT_LOGD("Copying map value: addr=%p", map_obj);
	typed_map_obj = BT_VALUE_TO_MAP(map_obj);
	copy_obj = bt_value_map_create();
	if (!copy_obj) {
		goto end;
	}

	g_hash_table_iter_init(&iter, typed_map_obj->ght);

	while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
		const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));

		BT_ASSERT(key_str);
		BT_LOGD("Copying map value's element: element-addr=%p, "
			"key=\"%s\"", element_obj, key_str);
		ret = bt_value_copy(element_obj, &element_obj_copy);
		if (ret) {
			BT_LOGE("Cannot copy map value's element: "
				"map-addr=%p, key=\"%s\"",
				map_obj, key_str);
			BT_OBJECT_PUT_REF_AND_RESET(copy_obj);
			goto end;
		}

		BT_ASSERT(element_obj_copy);
		ret = bt_value_map_insert_entry(copy_obj, key_str,
			(void *) element_obj_copy);
		BT_OBJECT_PUT_REF_AND_RESET(element_obj_copy);
		if (ret) {
			BT_LOGE("Cannot insert into map value: addr=%p, key=\"%s\"",
				map_obj, key_str);
			BT_OBJECT_PUT_REF_AND_RESET(copy_obj);
			goto end;
		}
	}

	BT_LOGD("Copied map value: addr=%p", map_obj);

end:
	return copy_obj;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
static
int stack_push(struct stack *stack, struct bt_field_type *base_type,
	size_t base_len)
{
	int ret = 0;
	struct stack_entry *entry;

	assert(stack);
	assert(base_type);

	BT_LOGV("Pushing field type on stack: stack-addr=%p, "
		"ft-addr=%p, ft-id=%s, base-length=%zu, "
		"stack-size-before=%u, stack-size-after=%u",
		stack, base_type, bt_field_type_id_string(
			bt_field_type_get_type_id(base_type)),
		base_len, stack->entries->len, stack->entries->len + 1);
	entry = g_new0(struct stack_entry, 1);
	if (!entry) {
		BT_LOGE("Failed to allocate one stack entry: stack-addr=%p",
			stack);
		ret = BT_BTR_STATUS_ERROR;
		goto end;
	}

	entry->base_type = base_type;
	bt_get(entry->base_type);
	entry->base_len = base_len;
	g_ptr_array_add(stack->entries, entry);

end:
	return ret;
}
Esempio n. 10
0
static
bool stream_classes_all_have_default_clock_class(bt_trace_class *tc)
{
	uint64_t i, sc_count;
	const bt_clock_class *cc = NULL;
	const bt_stream_class *sc;
	bool ret = true;

	sc_count = bt_trace_class_get_stream_class_count(tc);
	for (i = 0; i < sc_count; i++) {
		sc = bt_trace_class_borrow_stream_class_by_index_const(tc, i);

		BT_ASSERT(sc);

		cc = bt_stream_class_borrow_default_clock_class_const(sc);
		if (!cc) {
			ret = false;
			BT_LOGE("Stream class doesn't have a default clock class: "
				"sc-id=%" PRIu64 ", sc-name=\"%s\"",
				bt_stream_class_get_id(sc),
				bt_stream_class_get_name(sc));
			goto end;
		}
	}

end:
	return ret;
}
Esempio n. 11
0
BT_HIDDEN
struct bt_value *bt_attributes_get_field_value_by_name(
		struct bt_value *attr_obj, const char *name)
{
	struct bt_value *value_obj = NULL;
	struct bt_value *attr_field_obj = NULL;

	if (!attr_obj || !name) {
		BT_LOGW("Invalid parameter: attributes object or name is NULL: "
			"value-addr=%p, name-addr=%p", attr_obj, name);
		goto end;
	}

	attr_field_obj = bt_attributes_get_field_by_name(attr_obj, name);
	if (!attr_field_obj) {
		BT_LOGD("Cannot find attributes object's field by name: "
			"value-addr=%p, name=\"%s\"", attr_obj, name);
		goto end;
	}

	value_obj = bt_value_array_get(attr_field_obj,
		BT_ATTR_VALUE_INDEX);
	if (!value_obj) {
		BT_LOGE("Cannot get attribute array value's element by index: "
			"value-addr=%p, index=%" PRIu64, attr_field_obj,
			(uint64_t) BT_ATTR_VALUE_INDEX);
	}

end:
	BT_PUT(attr_field_obj);

	return value_obj;
}
Esempio n. 12
0
bool read_src_fs_parameters(const bt_value *params,
		const bt_value **paths, struct ctf_fs_component *ctf_fs) {
	bool ret;
	const bt_value *value;

	/* paths parameter */
	*paths = bt_value_map_borrow_entry_value_const(params, "paths");
	if (!validate_paths_parameter(*paths)) {
		goto error;
	}

	/* clock-class-offset-s parameter */
	value = bt_value_map_borrow_entry_value_const(params,
		"clock-class-offset-s");
	if (value) {
		if (!bt_value_is_signed_integer(value)) {
			BT_LOGE("clock-class-offset-s must be an integer");
			goto error;
		}
		ctf_fs->metadata_config.clock_class_offset_s =
			bt_value_signed_integer_get(value);
	}

	/* clock-class-offset-ns parameter */
	value = bt_value_map_borrow_entry_value_const(params,
		"clock-class-offset-ns");
	if (value) {
		if (!bt_value_is_signed_integer(value)) {
			BT_LOGE("clock-class-offset-ns must be an integer");
			goto error;
		}
		ctf_fs->metadata_config.clock_class_offset_ns =
			bt_value_signed_integer_get(value);
	}


	ret = true;
	goto end;

error:
	ret = false;

end:
	return ret;
}
Esempio n. 13
0
BT_HIDDEN
const char *bt_attributes_get_field_name(struct bt_value *attr_obj,
		uint64_t index)
{
	int rc;
	const char *ret = NULL;
	struct bt_value *attr_field_obj = NULL;
	struct bt_value *attr_field_name_obj = NULL;

	if (!attr_obj) {
		BT_LOGW_STR("Invalid parameter: attributes object is NULL.");
		goto end;
	}

	attr_field_obj = bt_value_array_get(attr_obj, index);
	if (!attr_field_obj) {
		BT_LOGE("Cannot get attributes object's array value's element by index: "
			"value-addr=%p, index=%" PRIu64, attr_obj, index);
		goto end;
	}

	attr_field_name_obj = bt_value_array_get(attr_field_obj,
		BT_ATTR_NAME_INDEX);
	if (!attr_field_name_obj) {
		BT_LOGE("Cannot get attribute array value's element by index: "
			"value-addr=%p, index=%" PRIu64, attr_field_obj,
			(uint64_t) BT_ATTR_NAME_INDEX);
		goto end;
	}

	rc = bt_value_string_get(attr_field_name_obj, &ret);
	if (rc) {
		BT_LOGE("Cannot get raw value from string value: value-addr=%p",
			attr_field_name_obj);
		ret = NULL;
	}

end:
	BT_PUT(attr_field_name_obj);
	BT_PUT(attr_field_obj);
	return ret;
}
Esempio n. 14
0
static
bt_bool extend_map_element(const char *key,
		const struct bt_value *extension_obj_elem, void *data)
{
	bt_bool ret = BT_TRUE;
	struct extend_map_element_data *extend_data = data;
	struct bt_value *extension_obj_elem_copy = NULL;

	/* Copy object which is to replace the current one */
	extend_data->status = bt_value_copy(extension_obj_elem,
					    &extension_obj_elem_copy);
	if (extend_data->status) {
		BT_LOGE("Cannot copy map element: addr=%p",
			extension_obj_elem);
		goto error;
	}

	BT_ASSERT(extension_obj_elem_copy);

	/* Replace in extended object */
	extend_data->status = bt_value_map_insert_entry(
		extend_data->extended_obj, key,
		(void *) extension_obj_elem_copy);
	if (extend_data->status) {
		BT_LOGE("Cannot replace value in extended value: key=\"%s\", "
			"extended-value-addr=%p, element-value-addr=%p",
			key, extend_data->extended_obj,
			extension_obj_elem_copy);
		goto error;
	}

	goto end;

error:
	BT_ASSERT(extend_data->status != BT_VALUE_STATUS_OK);
	ret = BT_FALSE;

end:
	BT_OBJECT_PUT_REF_AND_RESET(extension_obj_elem_copy);
	return ret;
}
Esempio n. 15
0
static
bool validate_paths_parameter(const bt_value *paths)
{
	bool ret;
	bt_value_type type;
	uint64_t i;

	if (!paths) {
		BT_LOGE("missing \"paths\" parameter");
		goto error;
	}

	type = bt_value_get_type(paths);
	if (type != BT_VALUE_TYPE_ARRAY) {
		BT_LOGE("`paths` parameter: expecting array value: type=%s",
			bt_common_value_type_string(type));
		goto error;
	}

	for (i = 0; i < bt_value_array_get_size(paths); i++) {
		const bt_value *elem;

		elem = bt_value_array_borrow_element_by_index_const(paths, i);
		type = bt_value_get_type(elem);
		if (type != BT_VALUE_TYPE_STRING) {
			BT_LOGE("`paths` parameter: expecting string value: index=%" PRIu64 ", type=%s",
				i, bt_common_value_type_string(type));
			goto error;
		}
	}

	ret = true;
	goto end;

error:
	ret = false;

end:
	return ret;
}
Esempio n. 16
0
struct bt_ctf_field_type *
bt_ctf_event_class_get_payload_type_field_type_by_name(
		struct bt_ctf_event_class *event_class, const char *name)
{
	GQuark name_quark;
	struct bt_ctf_field_type *field_type = NULL;

	if (!event_class || !name) {
		BT_LOGW("Invalid parameter: event class or name is NULL: "
			"event-class-addr=%p, name-addr=%p",
			event_class, name);
		goto end;
	}

	if (!event_class->common.payload_field_type) {
		BT_LOGV("Event class has no payload field type: "
			"addr=%p, name=\"%s\", id=%" PRId64,
			event_class, bt_ctf_event_class_get_name(event_class),
			bt_ctf_event_class_get_id(event_class));
		goto end;
	}

	BT_ASSERT(bt_ctf_field_type_common_get_type_id(
		event_class->common.payload_field_type) ==
			BT_CTF_FIELD_TYPE_ID_STRUCT);
	name_quark = g_quark_try_string(name);
	if (!name_quark) {
		BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
		goto end;
	}

	/*
	 * No need to increment field_type's reference count since getting it
	 * from the structure already does.
	 */
	field_type = (void *)
		bt_ctf_field_type_structure_get_field_type_by_name(
			(void *) event_class->common.payload_field_type, name);

end:
	return field_type;
}
Esempio n. 17
0
BT_HIDDEN
int bt_attributes_freeze(struct bt_value *attr_obj)
{
	uint64_t i;
	int64_t count;
	int ret = 0;

	if (!attr_obj) {
		BT_LOGW_STR("Invalid parameter: attributes object is NULL.");
		ret = -1;
		goto end;
	}

	BT_LOGD("Freezing attributes object: value-addr=%p", attr_obj);
	count = bt_value_array_size(attr_obj);
	assert(count >= 0);

	/*
	 * We do not freeze the array value object itself here, since
	 * internal stuff could need to modify/add attributes. Each
	 * attribute is frozen one by one.
	 */
	for (i = 0; i < count; ++i) {
		struct bt_value *obj = NULL;

		obj = bt_attributes_get_field_value(attr_obj, i);
		if (!obj) {
			BT_LOGE("Cannot get attributes object's field value by index: "
				"value-addr=%p, index=%" PRIu64,
				attr_obj, i);
			ret = -1;
			goto end;
		}

		bt_value_freeze(obj);
		BT_PUT(obj);
	}

end:
	return ret;
}
Esempio n. 18
0
BT_HIDDEN
bt_query_status ctf_fs_query(
		bt_self_component_class_source *comp_class,
		const bt_query_executor *query_exec,
		const char *object, const bt_value *params,
		const bt_value **result)
{
	bt_query_status status = BT_QUERY_STATUS_OK;

	if (!strcmp(object, "metadata-info")) {
		status = metadata_info_query(comp_class, params, result);
	} else if (!strcmp(object, "trace-info")) {
		status = trace_info_query(comp_class, params, result);
	} else {
		BT_LOGE("Unknown query object `%s`", object);
		status = BT_QUERY_STATUS_INVALID_OBJECT;
		goto end;
	}
end:
	return status;
}
Esempio n. 19
0
static
int create_ports_for_trace(struct ctf_fs_component *ctf_fs,
		struct ctf_fs_trace *ctf_fs_trace)
{
	int ret = 0;
	size_t i;

	/* Create one output port for each stream file group */
	for (i = 0; i < ctf_fs_trace->ds_file_groups->len; i++) {
		struct ctf_fs_ds_file_group *ds_file_group =
			g_ptr_array_index(ctf_fs_trace->ds_file_groups, i);

		ret = create_one_port_for_trace(ctf_fs, ctf_fs_trace,
			ds_file_group);
		if (ret) {
			BT_LOGE("Cannot create output port.");
			goto end;
		}
	}

end:
	return ret;
}
Esempio n. 20
0
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;
}
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;
}
Esempio n. 22
0
static
int create_ds_file_groups(struct ctf_fs_trace *ctf_fs_trace)
{
	int ret = 0;
	const char *basename;
	GError *error = NULL;
	GDir *dir = NULL;

	/* Check each file in the path directory, except specific ones */
	dir = g_dir_open(ctf_fs_trace->path->str, 0, &error);
	if (!dir) {
		BT_LOGE("Cannot open directory `%s`: %s (code %d)",
			ctf_fs_trace->path->str, error->message,
			error->code);
		goto error;
	}

	while ((basename = g_dir_read_name(dir))) {
		struct ctf_fs_file *file;

		if (!strcmp(basename, CTF_FS_METADATA_FILENAME)) {
			/* Ignore the metadata stream. */
			BT_LOGD("Ignoring metadata file `%s" G_DIR_SEPARATOR_S "%s`",
				ctf_fs_trace->path->str, basename);
			continue;
		}

		if (basename[0] == '.') {
			BT_LOGD("Ignoring hidden file `%s" G_DIR_SEPARATOR_S "%s`",
				ctf_fs_trace->path->str, basename);
			continue;
		}

		/* Create the file. */
		file = ctf_fs_file_create();
		if (!file) {
			BT_LOGE("Cannot create stream file object for file `%s" G_DIR_SEPARATOR_S "%s`",
				ctf_fs_trace->path->str, basename);
			goto error;
		}

		/* Create full path string. */
		g_string_append_printf(file->path, "%s" G_DIR_SEPARATOR_S "%s",
				ctf_fs_trace->path->str, basename);
		if (!g_file_test(file->path->str, G_FILE_TEST_IS_REGULAR)) {
			BT_LOGD("Ignoring non-regular file `%s`",
				file->path->str);
			ctf_fs_file_destroy(file);
			file = NULL;
			continue;
		}

		ret = ctf_fs_file_open(file, "rb");
		if (ret) {
			BT_LOGE("Cannot open stream file `%s`", file->path->str);
			goto error;
		}

		if (file->size == 0) {
			/* Skip empty stream. */
			BT_LOGD("Ignoring empty file `%s`", file->path->str);
			ctf_fs_file_destroy(file);
			continue;
		}

		ret = add_ds_file_to_ds_file_group(ctf_fs_trace,
			file->path->str);
		if (ret) {
			BT_LOGE("Cannot add stream file `%s` to stream file group",
				file->path->str);
			ctf_fs_file_destroy(file);
			goto error;
		}

		ctf_fs_file_destroy(file);
	}

	goto end;

error:
	ret = -1;

end:
	if (dir) {
		g_dir_close(dir);
		dir = NULL;
	}

	if (error) {
		g_error_free(error);
	}

	return ret;
}
Esempio n. 23
0
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;
}
Esempio n. 24
0
BT_HIDDEN
enum lttng_live_iterator_status lttng_live_metadata_update(
		struct lttng_live_trace *trace)
{
	struct lttng_live_session *session = trace->session;
	struct lttng_live_metadata *metadata = trace->metadata;
	struct lttng_live_component *lttng_live =
		session->lttng_live_msg_iter->lttng_live_comp;
	ssize_t ret = 0;
	size_t size, len_read = 0;
	char *metadata_buf = NULL;
	FILE *fp = NULL;
	enum ctf_metadata_decoder_status decoder_status;
	enum lttng_live_iterator_status status =
		LTTNG_LIVE_ITERATOR_STATUS_OK;

	/* No metadata stream yet. */
	if (!metadata) {
		if (session->new_streams_needed) {
			status = LTTNG_LIVE_ITERATOR_STATUS_AGAIN;
		} else {
			session->new_streams_needed = true;
			status = LTTNG_LIVE_ITERATOR_STATUS_CONTINUE;
		}
		goto end;
	}

	if (!metadata->trace) {
		trace->new_metadata_needed = false;
	}

	if (!trace->new_metadata_needed) {
		goto end;
	}

	/* Open for writing */
	fp = bt_open_memstream(&metadata_buf, &size);
	if (!fp) {
		BT_LOGE("Metadata open_memstream: %s", strerror(errno));
		goto error;
	}

	/* Grab all available metadata. */
	do {
		/*
		 * get_one_metadata_packet returns the number of bytes
		 * received, 0 when we have received everything, a
		 * negative value on error.
		 */
		ret = lttng_live_get_one_metadata_packet(trace, fp);
		if (ret > 0) {
			len_read += ret;
		}
	} while (ret > 0);

	/*
	 * Consider metadata closed as soon as we get an error reading
	 * it (e.g. cannot be found).
	 */
	if (ret < 0) {
		if (!metadata->closed) {
			metadata->closed = true;
			/*
			 * Release our reference on the trace as soon as
			 * we know the metadata stream is not available
			 * anymore. This won't necessarily teardown the
			 * metadata objects immediately, but only when
			 * the data streams are done.
			 */
			metadata->trace = NULL;
		}
		if (errno == EINTR) {
			if (lttng_live_graph_is_canceled(lttng_live)) {
				status = LTTNG_LIVE_ITERATOR_STATUS_AGAIN;
				goto end;
			}
		}
	}

	if (bt_close_memstream(&metadata_buf, &size, fp)) {
		BT_LOGE("bt_close_memstream: %s", strerror(errno));
	}
	ret = 0;
	fp = NULL;

	if (len_read == 0) {
		if (!trace->trace) {
			status = LTTNG_LIVE_ITERATOR_STATUS_AGAIN;
			goto end;
		}
		trace->new_metadata_needed = false;
		goto end;
	}

	fp = bt_fmemopen(metadata_buf, len_read, "rb");
	if (!fp) {
		BT_LOGE("Cannot memory-open metadata buffer: %s",
			strerror(errno));
		goto error;
	}

	/*
	 * The call to ctf_metadata_decoder_decode will append new metadata to
	 * our current trace class.
	 */
	decoder_status = ctf_metadata_decoder_decode(metadata->decoder, fp);
	switch (decoder_status) {
	case CTF_METADATA_DECODER_STATUS_OK:
		if (!trace->trace_class) {
			trace->trace_class =
				ctf_metadata_decoder_get_ir_trace_class(
						metadata->decoder);
			trace->trace = bt_trace_create(trace->trace_class);
			if (!stream_classes_all_have_default_clock_class(
					trace->trace_class)) {
				/* Error logged in function. */
				goto error;
			}
			trace->clock_class =
				borrow_any_clock_class(trace->trace_class);
		}
		trace->new_metadata_needed = false;

		break;
	case CTF_METADATA_DECODER_STATUS_INCOMPLETE:
		status = LTTNG_LIVE_ITERATOR_STATUS_AGAIN;
		break;
	case CTF_METADATA_DECODER_STATUS_ERROR:
	case CTF_METADATA_DECODER_STATUS_INVAL_VERSION:
	case CTF_METADATA_DECODER_STATUS_IR_VISITOR_ERROR:
		goto error;
	}

	goto end;
error:
	status = LTTNG_LIVE_ITERATOR_STATUS_ERROR;
end:
	if (fp) {
		int closeret;

		closeret = fclose(fp);
		if (closeret) {
			BT_LOGE("Error on fclose");
		}
	}
	free(metadata_buf);
	return status;
}
Esempio n. 25
0
static
int create_streams_for_trace(struct ctf_fs_trace *ctf_fs_trace)
{
	int ret;
	GString *name = NULL;
	guint i;

	for (i = 0; i < ctf_fs_trace->ds_file_groups->len; i++) {
		struct ctf_fs_ds_file_group *ds_file_group =
			g_ptr_array_index(ctf_fs_trace->ds_file_groups, i);
		name = get_stream_instance_unique_name(ds_file_group);

		if (!name) {
			goto error;
		}

		if (ds_file_group->sc->ir_sc) {
			BT_ASSERT(ctf_fs_trace->trace);

			if (ds_file_group->stream_id == UINT64_C(-1)) {
				/* No stream ID: use 0 */
				ds_file_group->stream = bt_stream_create_with_id(
					ds_file_group->sc->ir_sc,
					ctf_fs_trace->trace,
					ctf_fs_trace->next_stream_id);
				ctf_fs_trace->next_stream_id++;
			} else {
				/* Specific stream ID */
				ds_file_group->stream = bt_stream_create_with_id(
					ds_file_group->sc->ir_sc,
					ctf_fs_trace->trace,
					(uint64_t) ds_file_group->stream_id);
			}
		} else {
			ds_file_group->stream = NULL;
		}

		if (!ds_file_group->stream) {
			BT_LOGE("Cannot create stream for DS file group: "
				"addr=%p, stream-name=\"%s\"",
				ds_file_group, name->str);
			goto error;
		}

		ret = bt_stream_set_name(ds_file_group->stream,
			name->str);
		if (ret) {
			BT_LOGE("Cannot set stream's name: "
				"addr=%p, stream-name=\"%s\"",
				ds_file_group->stream, name->str);
			goto error;
		}

		g_string_free(name, TRUE);
		name = NULL;
	}

	ret = 0;
	goto end;

error:
	ret = -1;

end:

	if (name) {
		g_string_free(name, TRUE);
	}
	return ret;
}
Esempio n. 26
0
static
int ctf_fs_component_create_ctf_fs_traces_one_root(bt_self_component_source *self_comp,
		struct ctf_fs_component *ctf_fs,
		const char *path_param)
{
	struct ctf_fs_trace *ctf_fs_trace = NULL;
	int ret = 0;
	GString *norm_path = NULL;
	GList *trace_paths = NULL;
	GList *trace_names = NULL;
	GList *tp_node;
	GList *tn_node;

	norm_path = bt_common_normalize_path(path_param, NULL);
	if (!norm_path) {
		BT_LOGE("Failed to normalize path: `%s`.",
			path_param);
		goto error;
	}

	ret = ctf_fs_find_traces(&trace_paths, norm_path->str);
	if (ret) {
		goto error;
	}

	if (!trace_paths) {
		BT_LOGE("No CTF traces recursively found in `%s`.",
			path_param);
		goto error;
	}

	trace_names = ctf_fs_create_trace_names(trace_paths, norm_path->str);
	if (!trace_names) {
		BT_LOGE("Cannot create trace names from trace paths.");
		goto error;
	}

	for (tp_node = trace_paths, tn_node = trace_names; tp_node;
			tp_node = g_list_next(tp_node),
			tn_node = g_list_next(tn_node)) {
		GString *trace_path = tp_node->data;
		GString *trace_name = tn_node->data;

		ctf_fs_trace = ctf_fs_trace_create(self_comp,
				trace_path->str, trace_name->str,
				&ctf_fs->metadata_config);
		if (!ctf_fs_trace) {
			BT_LOGE("Cannot create trace for `%s`.",
				trace_path->str);
			goto error;
		}

		g_ptr_array_add(ctf_fs->traces, ctf_fs_trace);
		ctf_fs_trace = NULL;
	}

	goto end;

error:
	ret = -1;
	ctf_fs_trace_destroy(ctf_fs_trace);

end:
	for (tp_node = trace_paths; tp_node; tp_node = g_list_next(tp_node)) {
		if (tp_node->data) {
			g_string_free(tp_node->data, TRUE);
		}
	}

	for (tn_node = trace_names; tn_node; tn_node = g_list_next(tn_node)) {
		if (tn_node->data) {
			g_string_free(tn_node->data, TRUE);
		}
	}

	if (trace_paths) {
		g_list_free(trace_paths);
	}

	if (trace_names) {
		g_list_free(trace_names);
	}

	if (norm_path) {
		g_string_free(norm_path, TRUE);
	}

	return ret;
}
Esempio n. 27
0
static
int ctf_fs_find_traces(GList **trace_paths, const char *start_path)
{
	int ret;
	GError *error = NULL;
	GDir *dir = NULL;
	const char *basename = NULL;

	/* Check if the starting path is a CTF trace itself */
	ret = path_is_ctf_trace(start_path);
	if (ret < 0) {
		goto end;
	}

	if (ret) {
		/*
		 * Stop recursion: a CTF trace cannot contain another
		 * CTF trace.
		 */
		ret = add_trace_path(trace_paths, start_path);
		goto end;
	}

	/* Look for subdirectories */
	if (!g_file_test(start_path, G_FILE_TEST_IS_DIR)) {
		/* Starting path is not a directory: end of recursion */
		goto end;
	}

	dir = g_dir_open(start_path, 0, &error);
	if (!dir) {
		if (error->code == G_FILE_ERROR_ACCES) {
			BT_LOGD("Cannot open directory `%s`: %s (code %d): continuing",
				start_path, error->message, error->code);
			goto end;
		}

		BT_LOGE("Cannot open directory `%s`: %s (code %d)",
			start_path, error->message, error->code);
		ret = -1;
		goto end;
	}

	while ((basename = g_dir_read_name(dir))) {
		GString *sub_path = g_string_new(NULL);

		if (!sub_path) {
			ret = -1;
			goto end;
		}

		g_string_printf(sub_path, "%s" G_DIR_SEPARATOR_S "%s", start_path, basename);
		ret = ctf_fs_find_traces(trace_paths, sub_path->str);
		g_string_free(sub_path, TRUE);
		if (ret) {
			goto end;
		}
	}

end:
	if (dir) {
		g_dir_close(dir);
	}

	if (error) {
		g_error_free(error);
	}

	return ret;
}
Esempio n. 28
0
static
int ctf_metadata_decoder_packetized_file_stream_to_buf_with_mdec(
		struct ctf_metadata_decoder *mdec, FILE *fp,
		char **buf, int byte_order)
{
	FILE *out_fp;
	size_t size;
	int ret = 0;
	int tret;
	size_t packet_index = 0;

	out_fp = bt_open_memstream(buf, &size);
	if (out_fp == NULL) {
		BT_LOGE("Cannot open memory stream: %s: mdec-addr=%p",
			strerror(errno), mdec);
		goto error;
	}

	for (;;) {
		if (feof(fp) != 0) {
			break;
		}

		tret = decode_packet(mdec, fp, out_fp, byte_order);
		if (tret) {
			BT_LOGE("Cannot decode packet: index=%zu, mdec-addr=%p",
				packet_index, mdec);
			goto error;
		}

		packet_index++;
	}

	/* Make sure the whole string ends with a null character */
	tret = fputc('\0', out_fp);
	if (tret == EOF) {
		BT_LOGE("Cannot append '\\0' to the decoded metadata buffer: "
			"mdec-addr=%p", mdec);
		goto error;
	}

	/* Close stream, which also flushes the buffer */
	ret = bt_close_memstream(buf, &size, out_fp);
	/*
	 * See fclose(3). Further access to out_fp after both success
	 * and error, even through another bt_close_memstream(), results
	 * in undefined behavior. Nullify out_fp to ensure we don't
	 * fclose it twice on error.
	 */
	out_fp = NULL;
	if (ret < 0) {
		BT_LOGE("Cannot close memory stream: %s: mdec-addr=%p",
			strerror(errno), mdec);
		goto error;
	}

	goto end;

error:
	ret = -1;

	if (out_fp) {
		if (bt_close_memstream(buf, &size, out_fp)) {
			BT_LOGE("Cannot close memory stream: %s: mdec-addr=%p",
				strerror(errno), mdec);
		}
	}

	if (*buf) {
		free(*buf);
		*buf = NULL;
	}

end:
	return ret;
}
Esempio n. 29
0
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);
}
Esempio n. 30
0
static
int decode_packet(struct ctf_metadata_decoder *mdec, FILE *in_fp, FILE *out_fp,
		int byte_order)
{
	struct packet_header header;
	size_t readlen, writelen, toread;
	uint8_t buf[512 + 1];	/* + 1 for debug-mode \0 */
	int ret = 0;
	const long offset = ftell(in_fp);

	if (offset < 0) {
		BT_LOGE_ERRNO("Failed to get current metadata file position",
			".");
		goto error;
	}
	BT_LOGV("Decoding metadata packet: mdec-addr=%p, offset=%ld",
		mdec, offset);
	readlen = fread(&header, sizeof(header), 1, in_fp);
	if (feof(in_fp) != 0) {
		BT_LOGV("Reached end of file: offset=%ld", ftell(in_fp));
		goto end;
	}
	if (readlen < 1) {
		BT_LOGV("Cannot decode metadata packet: offset=%ld", offset);
		goto error;
	}

	if (byte_order != BYTE_ORDER) {
		header.magic = GUINT32_SWAP_LE_BE(header.magic);
		header.checksum = GUINT32_SWAP_LE_BE(header.checksum);
		header.content_size = GUINT32_SWAP_LE_BE(header.content_size);
		header.packet_size = GUINT32_SWAP_LE_BE(header.packet_size);
	}

	if (header.compression_scheme) {
		BT_LOGE("Metadata packet compression is not supported as of this version: "
			"compression-scheme=%u, offset=%ld",
			(unsigned int) header.compression_scheme, offset);
		goto error;
	}

	if (header.encryption_scheme) {
		BT_LOGE("Metadata packet encryption is not supported as of this version: "
			"encryption-scheme=%u, offset=%ld",
			(unsigned int) header.encryption_scheme, offset);
		goto error;
	}

	if (header.checksum || header.checksum_scheme) {
		BT_LOGE("Metadata packet checksum verification is not supported as of this version: "
			"checksum-scheme=%u, checksum=%x, offset=%ld",
			(unsigned int) header.checksum_scheme, header.checksum,
			offset);
		goto error;
	}

	if (!is_version_valid(header.major, header.minor)) {
		BT_LOGE("Invalid metadata packet version: "
			"version=%u.%u, offset=%ld",
			header.major, header.minor, offset);
		goto error;
	}

	/* Set expected trace UUID if not set; otherwise validate it */
	if (mdec) {
		if (!mdec->is_uuid_set) {
			memcpy(mdec->uuid, header.uuid, sizeof(header.uuid));
			mdec->is_uuid_set = true;
		} else if (bt_uuid_compare(header.uuid, mdec->uuid)) {
			BT_LOGE("Metadata UUID mismatch between packets of the same stream: "
				"packet-uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\", "
				"expected-uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\", "
				"offset=%ld",
				(unsigned int) header.uuid[0],
				(unsigned int) header.uuid[1],
				(unsigned int) header.uuid[2],
				(unsigned int) header.uuid[3],
				(unsigned int) header.uuid[4],
				(unsigned int) header.uuid[5],
				(unsigned int) header.uuid[6],
				(unsigned int) header.uuid[7],
				(unsigned int) header.uuid[8],
				(unsigned int) header.uuid[9],
				(unsigned int) header.uuid[10],
				(unsigned int) header.uuid[11],
				(unsigned int) header.uuid[12],
				(unsigned int) header.uuid[13],
				(unsigned int) header.uuid[14],
				(unsigned int) header.uuid[15],
				(unsigned int) mdec->uuid[0],
				(unsigned int) mdec->uuid[1],
				(unsigned int) mdec->uuid[2],
				(unsigned int) mdec->uuid[3],
				(unsigned int) mdec->uuid[4],
				(unsigned int) mdec->uuid[5],
				(unsigned int) mdec->uuid[6],
				(unsigned int) mdec->uuid[7],
				(unsigned int) mdec->uuid[8],
				(unsigned int) mdec->uuid[9],
				(unsigned int) mdec->uuid[10],
				(unsigned int) mdec->uuid[11],
				(unsigned int) mdec->uuid[12],
				(unsigned int) mdec->uuid[13],
				(unsigned int) mdec->uuid[14],
				(unsigned int) mdec->uuid[15],
				offset);
			goto error;
		}
	}

	if ((header.content_size / CHAR_BIT) < sizeof(header)) {
		BT_LOGE("Bad metadata packet content size: content-size=%u, "
			"offset=%ld", header.content_size, offset);
		goto error;
	}

	toread = header.content_size / CHAR_BIT - sizeof(header);

	for (;;) {
		size_t loop_read;

		loop_read = MIN(sizeof(buf) - 1, toread);
		readlen = fread(buf, sizeof(uint8_t), loop_read, in_fp);
		if (ferror(in_fp)) {
			BT_LOGE("Cannot read metadata packet buffer: "
				"offset=%ld, read-size=%zu",
				ftell(in_fp), loop_read);
			goto error;
		}
		if (readlen > loop_read) {
			BT_LOGE("fread returned more byte than expected: "
				"read-size-asked=%zu, read-size-returned=%zu",
				loop_read, readlen);
			goto error;
		}

		writelen = fwrite(buf, sizeof(uint8_t), readlen, out_fp);
		if (writelen < readlen || ferror(out_fp)) {
			BT_LOGE("Cannot write decoded metadata text to buffer: "
				"read-offset=%ld, write-size=%zu",
				ftell(in_fp), readlen);
			goto error;
		}

		toread -= readlen;
		if (toread == 0) {
			int fseek_ret;

			/* Read leftover padding */
			toread = (header.packet_size - header.content_size) /
				CHAR_BIT;
			fseek_ret = fseek(in_fp, toread, SEEK_CUR);
			if (fseek_ret < 0) {
				BT_LOGW_STR("Missing padding at the end of the metadata stream.");
			}
			break;
		}
	}

	goto end;

error:
	ret = -1;

end:
	return ret;
}