Пример #1
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;
}
Пример #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;
}