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 void lttng_live_metadata_fini(struct lttng_live_trace *trace) { struct lttng_live_metadata *metadata = trace->metadata; if (!metadata) { return; } ctf_metadata_decoder_destroy(metadata->decoder); trace->metadata = NULL; g_free(metadata); }
BT_HIDDEN int lttng_live_metadata_create_stream(struct lttng_live_session *session, uint64_t ctf_trace_id, uint64_t stream_id, const char *trace_name) { struct lttng_live_component *lttng_live = session->lttng_live_msg_iter->lttng_live_comp; struct lttng_live_metadata *metadata = NULL; struct lttng_live_trace *trace; const char *match; metadata = g_new0(struct lttng_live_metadata, 1); if (!metadata) { return -1; } metadata->stream_id = stream_id; match = strstr(trace_name, session->session_name->str); if (!match) { goto error; } metadata->decoder = ctf_metadata_decoder_create( lttng_live->self_comp, NULL); if (!metadata->decoder) { goto error; } trace = lttng_live_borrow_trace(session, ctf_trace_id); if (!trace) { goto error; } metadata->trace = trace; trace->metadata = metadata; return 0; error: ctf_metadata_decoder_destroy(metadata->decoder); g_free(metadata); return -1; }
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); }