Commit | Line | Data |
---|---|---|
04c0ba87 | 1 | /* |
0235b0db | 2 | * SPDX-License-Identifier: MIT |
04c0ba87 JG |
3 | * |
4 | * Copyright 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
5 | * | |
0235b0db | 6 | * Babeltrace CTF file system Reader Component queries |
04c0ba87 JG |
7 | */ |
8 | ||
c802cacb SM |
9 | #include <glib.h> |
10 | #include <glib/gstdio.h> | |
c802cacb SM |
11 | #include <sys/types.h> |
12 | ||
13 | #include <babeltrace2/babeltrace.h> | |
14 | ||
c02af779 | 15 | #include "cpp-common/bt2/exc.hpp" |
a9a4f6b9 | 16 | #include "cpp-common/bt2c/file-utils.hpp" |
69d91bb3 | 17 | #include "cpp-common/bt2c/glib-up.hpp" |
8d049eb2 | 18 | |
69d91bb3 SM |
19 | #include "plugins/common/param-validation/param-validation.h" |
20 | ||
a9a4f6b9 FD |
21 | #include "../common/src/metadata/metadata-stream-parser-utils.hpp" |
22 | #include "../common/src/metadata/tsdl/metadata-stream-decoder.hpp" | |
873c329a | 23 | #include "data-stream-file.hpp" |
087cd0f5 | 24 | #include "fs.hpp" |
cdf7de78 | 25 | #include "metadata.hpp" |
c802cacb | 26 | #include "query.hpp" |
55314f2a | 27 | |
4164020e | 28 | #define METADATA_TEXT_SIG "/* CTF 1.8" |
04c0ba87 | 29 | |
4164020e SM |
30 | struct range |
31 | { | |
32 | int64_t begin_ns = 0; | |
33 | int64_t end_ns = 0; | |
34 | bool set = false; | |
97ade20b JG |
35 | }; |
36 | ||
69d91bb3 SM |
37 | static bt_param_validation_map_value_entry_descr metadataInfoQueryParamsDesc[] = { |
38 | {"path", BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_MANDATORY, | |
39 | bt_param_validation_value_descr::makeString()}, | |
40 | BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_END}; | |
41 | ||
c02af779 | 42 | bt2::Value::Shared metadata_info_query(const bt2::ConstMapValue params, const bt2c::Logger& logger) |
04c0ba87 | 43 | { |
69d91bb3 SM |
44 | gchar *validateError = nullptr; |
45 | const auto validationStatus = bt_param_validation_validate( | |
46 | params.libObjPtr(), metadataInfoQueryParamsDesc, &validateError); | |
4164020e | 47 | |
69d91bb3 SM |
48 | if (validationStatus == BT_PARAM_VALIDATION_STATUS_MEMORY_ERROR) { |
49 | throw bt2::MemoryError {}; | |
50 | } else if (validationStatus == BT_PARAM_VALIDATION_STATUS_VALIDATION_ERROR) { | |
51 | const bt2c::GCharUP deleter {validateError}; | |
52 | ||
53 | BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(logger, bt2::Error, "{}", validateError); | |
4164020e SM |
54 | } |
55 | ||
69d91bb3 | 56 | const auto path = params["path"]->asString().value(); |
4164020e | 57 | |
a9a4f6b9 FD |
58 | try { |
59 | const auto buffer = bt2c::dataFromFile(fmt::format("{}/metadata", path), logger, true); | |
60 | ctf::src::MetadataStreamDecoder decoder {logger}; | |
61 | auto plainText = decoder.decode(buffer); | |
62 | const auto result = bt2::MapValue::create(); | |
4164020e | 63 | |
a9a4f6b9 FD |
64 | /* |
65 | * If the metadata does not already start with the plaintext metadata | |
66 | * signature, prepend it. | |
67 | */ | |
68 | if (plainText.rfind(METADATA_TEXT_SIG, 0) != 0) { | |
69 | plainText.insert(0, std::string {METADATA_TEXT_SIG} + " */\n\n"); | |
70 | } | |
c719eabb | 71 | |
a9a4f6b9 FD |
72 | result->insert("text", plainText.data()); |
73 | result->insert("is-packetized", decoder.pktInfo().has_value()); | |
74 | return result; | |
75 | } catch (const bt2c::Error&) { | |
76 | BT_CPPLOGE_APPEND_CAUSE_AND_RETHROW_SPEC(logger, "Error reading metadata file"); | |
4164020e | 77 | } |
97ade20b | 78 | } |
9ec238a8 | 79 | |
f9f2dd71 | 80 | static void add_range(const bt2::MapValue info, const range& range, const char *range_name) |
97ade20b | 81 | { |
f9f2dd71 | 82 | if (!range.set) { |
4164020e | 83 | /* Not an error. */ |
c02af779 | 84 | return; |
4164020e SM |
85 | } |
86 | ||
c02af779 | 87 | const auto rangeMap = info.insertEmptyMap(range_name); |
f9f2dd71 SM |
88 | rangeMap.insert("begin", range.begin_ns); |
89 | rangeMap.insert("end", range.end_ns); | |
97ade20b JG |
90 | } |
91 | ||
f9f2dd71 | 92 | static void populate_stream_info(struct ctf_fs_ds_file_group *group, const bt2::MapValue groupInfo) |
97ade20b | 93 | { |
4164020e SM |
94 | /* |
95 | * Since each `struct ctf_fs_ds_file_group` has a sorted array of | |
96 | * `struct ctf_fs_ds_index_entry`, we can compute the stream range from | |
97 | * the timestamp_begin of the first index entry and the timestamp_end | |
98 | * of the last index entry. | |
99 | */ | |
c46b32d8 | 100 | BT_ASSERT(!group->index.entries.empty()); |
4164020e SM |
101 | |
102 | /* First entry. */ | |
c46b32d8 | 103 | const auto& first_ds_index_entry = group->index.entries.front(); |
4164020e SM |
104 | |
105 | /* Last entry. */ | |
c46b32d8 | 106 | const auto& last_ds_index_entry = group->index.entries.back(); |
4164020e | 107 | |
f9f2dd71 SM |
108 | range stream_range; |
109 | stream_range.begin_ns = first_ds_index_entry.timestamp_begin_ns; | |
110 | stream_range.end_ns = last_ds_index_entry.timestamp_end_ns; | |
4164020e SM |
111 | |
112 | /* | |
113 | * If any of the begin and end timestamps is not set it means that | |
114 | * packets don't include `timestamp_begin` _and_ `timestamp_end` fields | |
115 | * in their packet context so we can't set the range. | |
116 | */ | |
f9f2dd71 | 117 | stream_range.set = stream_range.begin_ns != UINT64_C(-1) && stream_range.end_ns != UINT64_C(-1); |
4164020e | 118 | |
c02af779 | 119 | add_range(groupInfo, stream_range, "range-ns"); |
3045bbcb | 120 | groupInfo.insert("port-name", ctf_fs_make_port_name(group)); |
97ade20b JG |
121 | } |
122 | ||
c02af779 SM |
123 | static void populate_trace_info(const struct ctf_fs_trace *trace, const bt2::MapValue traceInfo, |
124 | const bt2c::Logger& logger) | |
97ade20b | 125 | { |
4164020e | 126 | /* Add trace range info only if it contains streams. */ |
cdf7de78 | 127 | if (trace->ds_file_groups.empty()) { |
cee8a466 SM |
128 | BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(logger, bt2::Error, |
129 | "Trace has no streams: trace-path={}", trace->path); | |
4164020e SM |
130 | } |
131 | ||
c02af779 | 132 | const auto fileGroups = traceInfo.insertEmptyArray("stream-infos"); |
4164020e SM |
133 | |
134 | /* Find range of all stream groups, and of the trace. */ | |
cdf7de78 | 135 | for (const auto& group : trace->ds_file_groups) { |
c02af779 | 136 | const auto groupInfo = fileGroups.appendEmptyMap(); |
f9f2dd71 | 137 | populate_stream_info(group.get(), groupInfo); |
4164020e | 138 | } |
97ade20b JG |
139 | } |
140 | ||
c02af779 | 141 | bt2::Value::Shared trace_infos_query(const bt2::ConstMapValue params, const bt2c::Logger& logger) |
97ade20b | 142 | { |
c5a5a936 | 143 | const auto parameters = read_src_fs_parameters(params, logger); |
e1d200e5 | 144 | ctf_fs_component ctf_fs {parameters.clkClsCfg, logger}; |
4164020e | 145 | |
c5a5a936 SM |
146 | if (ctf_fs_component_create_ctf_fs_trace( |
147 | &ctf_fs, parameters.inputs, | |
4d6634b8 | 148 | parameters.traceName ? parameters.traceName->c_str() : nullptr, {})) { |
c02af779 | 149 | BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(logger, bt2::Error, "Failed to create trace"); |
4164020e SM |
150 | } |
151 | ||
c02af779 SM |
152 | const auto result = bt2::ArrayValue::create(); |
153 | const auto traceInfo = result->appendEmptyMap(); | |
5e502e99 | 154 | populate_trace_info(ctf_fs.trace.get(), traceInfo, logger); |
c7eee084 | 155 | |
c02af779 | 156 | return result; |
04c0ba87 | 157 | } |
73760435 | 158 | |
69d91bb3 SM |
159 | static bt_param_validation_map_value_entry_descr supportInfoQueryParamsDesc[] = { |
160 | {"type", BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_MANDATORY, | |
161 | bt_param_validation_value_descr::makeString()}, | |
162 | {"input", BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_MANDATORY, | |
163 | bt_param_validation_value_descr::makeString()}, | |
164 | BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_END}; | |
165 | ||
c02af779 | 166 | bt2::Value::Shared support_info_query(const bt2::ConstMapValue params, const bt2c::Logger& logger) |
73760435 | 167 | { |
69d91bb3 SM |
168 | gchar *validateError = NULL; |
169 | const auto validationStatus = bt_param_validation_validate( | |
170 | params.libObjPtr(), supportInfoQueryParamsDesc, &validateError); | |
171 | ||
172 | if (validationStatus == BT_PARAM_VALIDATION_STATUS_MEMORY_ERROR) { | |
173 | throw bt2::MemoryError {}; | |
174 | } else if (validationStatus == BT_PARAM_VALIDATION_STATUS_VALIDATION_ERROR) { | |
175 | const bt2c::GCharUP deleter {validateError}; | |
176 | ||
177 | BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(logger, bt2::Error, "{}", validateError); | |
178 | } | |
179 | ||
180 | const auto type = params["type"]->asString().value(); | |
4164020e | 181 | |
c02af779 | 182 | if (strcmp(type, "directory") != 0) { |
69d91bb3 SM |
183 | /* |
184 | * The input type is not a directory so we are 100% sure it's not a CTF | |
185 | * 1.8 trace as it would need a directory with at least 1 metadata file | |
186 | * and 1 data stream file. | |
187 | */ | |
c02af779 SM |
188 | const auto result = bt2::MapValue::create(); |
189 | result->insert("weight", 0.0f); | |
190 | return result; | |
4164020e SM |
191 | } |
192 | ||
69d91bb3 | 193 | const auto input = params["input"]->asString().value(); |
4164020e | 194 | |
a9a4f6b9 FD |
195 | const auto result = bt2::MapValue::create(); |
196 | try { | |
197 | const auto buffer = bt2c::dataFromFile(fmt::format("{}/metadata", input), logger, false); | |
198 | const auto parseRet = ctf::src::parseMetadataStream({}, {}, buffer, logger); | |
4164020e | 199 | |
a9a4f6b9 | 200 | BT_ASSERT(parseRet.traceCls); |
4164020e SM |
201 | |
202 | /* | |
a9a4f6b9 FD |
203 | * We were able to parse the metadata file, so we are confident it's a |
204 | * CTF trace. | |
4164020e | 205 | */ |
a9a4f6b9 FD |
206 | /* ⚠️ TODO: also consider namespace and name */ |
207 | result->insert("weight", 0.75); | |
208 | if (parseRet.traceCls->uid()) { | |
209 | result->insert("group", *parseRet.traceCls->uid()); | |
4164020e | 210 | } |
a9a4f6b9 FD |
211 | } catch (const bt2c::NoSuchFileOrDirectoryError&) { |
212 | /* | |
213 | * Failing to find the metadata file is not an error, it simply | |
214 | * indicates that the directory is not a trace. Report appropriate | |
215 | * weight of zero. | |
216 | */ | |
217 | result->insert("weight", 0.0); | |
4164020e SM |
218 | } |
219 | ||
c02af779 | 220 | return result; |
73760435 | 221 | } |