From a9a4f6b94df8cc9098118488851f98dc513be967 Mon Sep 17 00:00:00 2001 From: Francis Deslauriers Date: Tue, 7 May 2024 11:17:57 -0400 Subject: [PATCH] src.ctf.fs: Implement queries with new `MetadataStreamDecoder' and `Ctf1MetadataStreamParser` Rewrite the `babeltrace.support-info` query using the new `Ctf1MetadataStreamParser` class. Rewrite the `metadata-info` query using the new `MetadataStreamDecoder` class. Signed-off-by: Francis Deslauriers Change-Id: I80530c6eef7ca62c4271a568e527e48e8ec2602a Reviewed-on: https://review.lttng.org/c/babeltrace/+/7946 Reviewed-by: Philippe Proulx Reviewed-on: https://review.lttng.org/c/babeltrace/+/12740 Tested-by: jenkins CI-Build: Simon Marchi --- src/plugins/ctf/fs-src/query.cpp | 129 ++++++------------ .../query/test-query-metadata-info.sh | 12 +- tests/utils/utils.sh | 6 + 3 files changed, 53 insertions(+), 94 deletions(-) diff --git a/src/plugins/ctf/fs-src/query.cpp b/src/plugins/ctf/fs-src/query.cpp index 4143f9c0..20645320 100644 --- a/src/plugins/ctf/fs-src/query.cpp +++ b/src/plugins/ctf/fs-src/query.cpp @@ -13,12 +13,13 @@ #include #include "cpp-common/bt2/exc.hpp" +#include "cpp-common/bt2c/file-utils.hpp" #include "cpp-common/bt2c/glib-up.hpp" -#include "cpp-common/bt2c/libc-up.hpp" #include "plugins/common/param-validation/param-validation.h" -#include "../common/src/metadata/tsdl/decoder.hpp" +#include "../common/src/metadata/metadata-stream-parser-utils.hpp" +#include "../common/src/metadata/tsdl/metadata-stream-decoder.hpp" #include "data-stream-file.hpp" #include "fs.hpp" #include "metadata.hpp" @@ -53,53 +54,27 @@ bt2::Value::Shared metadata_info_query(const bt2::ConstMapValue params, const bt } const auto path = params["path"]->asString().value(); - bt2c::FileUP metadataFp {ctf_fs_metadata_open_file(path, logger)}; - if (!metadataFp) { - BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(logger, bt2::Error, - "Cannot open trace metadata: path=\"{}\".", path); - } - - bool is_packetized; - int bo; - int ret = ctf_metadata_decoder_is_packetized(metadataFp.get(), &is_packetized, &bo, logger); - - if (ret) { - BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC( - logger, bt2::Error, - "Cannot check whether or not the metadata stream is packetized: path=\"{}\".", path); - } - - ctf_metadata_decoder_config decoder_cfg {logger}; - decoder_cfg.keep_plain_text = true; - ctf_metadata_decoder_up decoder = ctf_metadata_decoder_create(&decoder_cfg); - if (!decoder) { - BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC( - logger, bt2::Error, "Cannot create metadata decoder: path=\"{}\".", path); - } - rewind(metadataFp.get()); - ctf_metadata_decoder_status decoder_status = - ctf_metadata_decoder_append_content(decoder.get(), metadataFp.get()); - if (decoder_status) { - BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC( - logger, bt2::Error, "Cannot update metadata decoder's content: path=\"{}\".", path); - } + try { + const auto buffer = bt2c::dataFromFile(fmt::format("{}/metadata", path), logger, true); + ctf::src::MetadataStreamDecoder decoder {logger}; + auto plainText = decoder.decode(buffer); + const auto result = bt2::MapValue::create(); - const char *plain_text = ctf_metadata_decoder_get_text(decoder.get()); - std::string metadata_text; + /* + * If the metadata does not already start with the plaintext metadata + * signature, prepend it. + */ + if (plainText.rfind(METADATA_TEXT_SIG, 0) != 0) { + plainText.insert(0, std::string {METADATA_TEXT_SIG} + " */\n\n"); + } - if (strncmp(plain_text, METADATA_TEXT_SIG, sizeof(METADATA_TEXT_SIG) - 1) != 0) { - metadata_text = METADATA_TEXT_SIG; - metadata_text += " */\n\n"; + result->insert("text", plainText.data()); + result->insert("is-packetized", decoder.pktInfo().has_value()); + return result; + } catch (const bt2c::Error&) { + BT_CPPLOGE_APPEND_CAUSE_AND_RETHROW_SPEC(logger, "Error reading metadata file"); } - - metadata_text += plain_text; - - const auto result = bt2::MapValue::create(); - result->insert("text", metadata_text); - result->insert("is-packetized", is_packetized); - - return result; } static void add_range(const bt2::MapValue info, const range& range, const char *range_name) @@ -217,57 +192,29 @@ bt2::Value::Shared support_info_query(const bt2::ConstMapValue params, const bt2 const auto input = params["input"]->asString().value(); - bt2c::GCharUP metadataPath {g_build_filename(input, CTF_FS_METADATA_FILENAME, NULL)}; - if (!metadataPath) { - BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(logger, bt2::Error, "Failed to read parameters"); - } - - double weight = 0; - char uuid_str[BT_UUID_STR_LEN + 1]; - bool has_uuid = false; - bt2c::FileUP metadataFile {g_fopen(metadataPath.get(), "rb")}; - if (metadataFile) { - enum ctf_metadata_decoder_status decoder_status; - bt_uuid_t uuid; - - ctf_metadata_decoder_config metadata_decoder_config {logger}; - - ctf_metadata_decoder_up metadata_decoder = - ctf_metadata_decoder_create(&metadata_decoder_config); - if (!metadata_decoder) { - BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(logger, bt2::Error, - "Failed to create metadata decoder"); - } + const auto result = bt2::MapValue::create(); + try { + const auto buffer = bt2c::dataFromFile(fmt::format("{}/metadata", input), logger, false); + const auto parseRet = ctf::src::parseMetadataStream({}, {}, buffer, logger); - decoder_status = - ctf_metadata_decoder_append_content(metadata_decoder.get(), metadataFile.get()); - if (decoder_status != CTF_METADATA_DECODER_STATUS_OK) { - BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC( - logger, bt2::Error, "Failed to append metadata content: metadata-decoder-status={}", - decoder_status); - } + BT_ASSERT(parseRet.traceCls); /* - * We were able to parse the metadata file, so we are - * confident it's a CTF trace. + * We were able to parse the metadata file, so we are confident it's a + * CTF trace. */ - weight = 0.75; - - /* If the trace has a UUID, return the stringified UUID as the group. */ - if (ctf_metadata_decoder_get_trace_class_uuid(metadata_decoder.get(), uuid) == 0) { - bt_uuid_to_str(uuid, uuid_str); - has_uuid = true; + /* ⚠️ TODO: also consider namespace and name */ + result->insert("weight", 0.75); + if (parseRet.traceCls->uid()) { + result->insert("group", *parseRet.traceCls->uid()); } - } - - const auto result = bt2::MapValue::create(); - result->insert("weight", weight); - - /* We are not supposed to have weight == 0 and a UUID. */ - BT_ASSERT(weight > 0 || !has_uuid); - - if (weight > 0 && has_uuid) { - result->insert("group", uuid_str); + } catch (const bt2c::NoSuchFileOrDirectoryError&) { + /* + * Failing to find the metadata file is not an error, it simply + * indicates that the directory is not a trace. Report appropriate + * weight of zero. + */ + result->insert("weight", 0.0); } return result; diff --git a/tests/plugins/src.ctf.fs/query/test-query-metadata-info.sh b/tests/plugins/src.ctf.fs/query/test-query-metadata-info.sh index 6f4545b4..14a61822 100755 --- a/tests/plugins/src.ctf.fs/query/test-query-metadata-info.sh +++ b/tests/plugins/src.ctf.fs/query/test-query-metadata-info.sh @@ -59,6 +59,7 @@ test_non_existent_trace_dir() { empty_dir=$(mktemp -d) stdout_file="$(mktemp -t actual-stdout.XXXXXX)" stderr_file="$(mktemp -t actual-stderr.XXXXXX)" + stderr_file_no_crlf="$(mktemp -t actual-stderr-no-crlf.XXXXXX)" query=("query" "src.ctf.fs" "metadata-info" "--params" "path=\"$empty_dir\"") bt_cli "$stdout_file" "$stderr_file" \ @@ -73,12 +74,17 @@ test_non_existent_trace_dir() { "${stderr_file}" \ "non existent trace dir: babeltrace produces an error stack" + # If TMPDIR is too long, the error message gets wrapped, and grep + # doesn't find the expected message. As a quick workaround, remove + # newlines before searching. + bt_remove_crlf "$stderr_file" "$stderr_file_no_crlf" + bt_grep_ok \ - "Failed to open metadata file: No such file or directory: path=\".*metadata\"" \ - "$stderr_file" \ + "No such file or directory: *path=\".*metadata\"" \ + "$stderr_file_no_crlf" \ "non existent trace dir: babeltrace produces the expected error message" - rm -f "${stdout_file}" "${stderr_file}" + rm -f "${stdout_file}" "${stderr_file}" "${stderr_file_no_crlf}" rmdir "${empty_dir}" } diff --git a/tests/utils/utils.sh b/tests/utils/utils.sh index f3d4d945..c597418b 100644 --- a/tests/utils/utils.sh +++ b/tests/utils/utils.sh @@ -205,6 +205,12 @@ bt_remove_cr_inline() { "$BT_TESTS_SED_BIN" 's/\r//g' "$1" } +# Writes the contents of the file `$1` to the file `$2` without the +# CR and LF characters. +bt_remove_crlf() { + tr -d '\r\n' < "$1" > "$2" +} + # Runs the `$BT_TESTS_BT2_BIN` command within an environment which can # import the `bt2` Python package, redirecting the standard output to # the `$1` file and the standard error to the `$2` file. -- 2.34.1