Example #1
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);
	}
}
Example #2
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;
}