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); } }
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; }