src.ctf.fs: use C++ value wrappers in queries
[babeltrace.git] / src / plugins / ctf / fs-src / query.cpp
CommitLineData
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"
8d049eb2
SM
16#include "cpp-common/bt2c/libc-up.hpp"
17
5656cea5 18#include "../common/src/metadata/tsdl/decoder.hpp"
087cd0f5 19#include "fs.hpp"
c802cacb 20#include "query.hpp"
55314f2a 21
4164020e 22#define METADATA_TEXT_SIG "/* CTF 1.8"
04c0ba87 23
4164020e
SM
24struct range
25{
26 int64_t begin_ns = 0;
27 int64_t end_ns = 0;
28 bool set = false;
97ade20b
JG
29};
30
c02af779 31bt2::Value::Shared metadata_info_query(const bt2::ConstMapValue params, const bt2c::Logger& logger)
04c0ba87 32{
c02af779
SM
33 const auto pathValue = params["path"];
34 if (!pathValue) {
35 BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(logger, bt2::Error,
36 "Mandatory `path` parameter missing");
4164020e
SM
37 }
38
c02af779
SM
39 if (!pathValue->isString()) {
40 BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(logger, bt2::Error,
41 "`path` parameter is required to be a string value");
4164020e
SM
42 }
43
c02af779
SM
44 const auto path = pathValue->asString().value();
45 bt2c::FileUP metadataFp {ctf_fs_metadata_open_file(path, logger)};
46 if (!metadataFp) {
47 BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(logger, bt2::Error,
48 "Cannot open trace metadata: path=\"{}\".", path);
4164020e
SM
49 }
50
c02af779
SM
51 bool is_packetized;
52 int bo;
53 int ret = ctf_metadata_decoder_is_packetized(metadataFp.get(), &is_packetized, &bo, logger);
4164020e 54
4164020e 55 if (ret) {
c02af779
SM
56 BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(
57 logger, bt2::Error,
58 "Cannot check whether or not the metadata stream is packetized: path=\"{}\".", path);
4164020e
SM
59 }
60
c02af779 61 ctf_metadata_decoder_config decoder_cfg {logger};
4164020e 62 decoder_cfg.keep_plain_text = true;
c02af779 63 ctf_metadata_decoder_up decoder = ctf_metadata_decoder_create(&decoder_cfg);
4164020e 64 if (!decoder) {
c02af779
SM
65 BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(
66 logger, bt2::Error, "Cannot create metadata decoder: path=\"{}}\".", path);
4164020e
SM
67 }
68
c02af779
SM
69 rewind(metadataFp.get());
70 ctf_metadata_decoder_status decoder_status =
71 ctf_metadata_decoder_append_content(decoder.get(), metadataFp.get());
4164020e 72 if (decoder_status) {
c02af779
SM
73 BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(
74 logger, bt2::Error, "Cannot update metadata decoder's content: path=\"{}\".", path);
4164020e
SM
75 }
76
c02af779
SM
77 const char *plain_text = ctf_metadata_decoder_get_text(decoder.get());
78 std::string metadata_text;
c719eabb 79
c02af779
SM
80 if (strncmp(plain_text, METADATA_TEXT_SIG, sizeof(METADATA_TEXT_SIG) - 1) != 0) {
81 metadata_text = METADATA_TEXT_SIG;
82 metadata_text += " */\n\n";
4164020e
SM
83 }
84
c02af779 85 metadata_text += plain_text;
04c0ba87 86
c02af779
SM
87 const auto result = bt2::MapValue::create();
88 result->insert("text", metadata_text);
89 result->insert("is-packetized", is_packetized);
c7eee084 90
c02af779 91 return result;
97ade20b 92}
9ec238a8 93
c02af779 94static void add_range(const bt2::MapValue info, struct range *range, const char *range_name)
97ade20b 95{
4164020e
SM
96 if (!range->set) {
97 /* Not an error. */
c02af779 98 return;
4164020e
SM
99 }
100
c02af779
SM
101 const auto rangeMap = info.insertEmptyMap(range_name);
102 rangeMap.insert("begin", range->begin_ns);
103 rangeMap.insert("end", range->end_ns);
97ade20b
JG
104}
105
c02af779
SM
106static void populate_stream_info(struct ctf_fs_ds_file_group *group, const bt2::MapValue groupInfo,
107 struct range *stream_range, const bt2c::Logger& logger)
97ade20b 108{
4164020e
SM
109 /*
110 * Since each `struct ctf_fs_ds_file_group` has a sorted array of
111 * `struct ctf_fs_ds_index_entry`, we can compute the stream range from
112 * the timestamp_begin of the first index entry and the timestamp_end
113 * of the last index entry.
114 */
115 BT_ASSERT(group->index);
116 BT_ASSERT(group->index->entries);
117 BT_ASSERT(group->index->entries->len > 0);
118
119 /* First entry. */
c02af779 120 ctf_fs_ds_index_entry *first_ds_index_entry =
4164020e
SM
121 (struct ctf_fs_ds_index_entry *) g_ptr_array_index(group->index->entries, 0);
122
123 /* Last entry. */
c02af779 124 ctf_fs_ds_index_entry *last_ds_index_entry = (struct ctf_fs_ds_index_entry *) g_ptr_array_index(
4164020e
SM
125 group->index->entries, group->index->entries->len - 1);
126
127 stream_range->begin_ns = first_ds_index_entry->timestamp_begin_ns;
128 stream_range->end_ns = last_ds_index_entry->timestamp_end_ns;
129
130 /*
131 * If any of the begin and end timestamps is not set it means that
132 * packets don't include `timestamp_begin` _and_ `timestamp_end` fields
133 * in their packet context so we can't set the range.
134 */
135 stream_range->set =
136 stream_range->begin_ns != UINT64_C(-1) && stream_range->end_ns != UINT64_C(-1);
137
c02af779 138 add_range(groupInfo, stream_range, "range-ns");
4164020e 139
c02af779
SM
140 bt2c::GCharUP portName = ctf_fs_make_port_name(group);
141 if (!portName) {
142 BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(logger, bt2::Error, "Failed to make port name");
4164020e
SM
143 }
144
c02af779 145 groupInfo.insert("port-name", portName.get());
97ade20b
JG
146}
147
c02af779
SM
148static void populate_trace_info(const struct ctf_fs_trace *trace, const bt2::MapValue traceInfo,
149 const bt2c::Logger& logger)
97ade20b 150{
4164020e
SM
151 BT_ASSERT(trace->ds_file_groups);
152 /* Add trace range info only if it contains streams. */
153 if (trace->ds_file_groups->len == 0) {
c02af779
SM
154 BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(
155 logger, bt2::Error, "Trace has no streams: trace-path={}", trace->path->str);
4164020e
SM
156 }
157
c02af779 158 const auto fileGroups = traceInfo.insertEmptyArray("stream-infos");
4164020e
SM
159
160 /* Find range of all stream groups, and of the trace. */
c02af779 161 for (size_t group_idx = 0; group_idx < trace->ds_file_groups->len; group_idx++) {
4164020e
SM
162 range group_range;
163 ctf_fs_ds_file_group *group =
164 (ctf_fs_ds_file_group *) g_ptr_array_index(trace->ds_file_groups, group_idx);
165
c02af779
SM
166 const auto groupInfo = fileGroups.appendEmptyMap();
167 populate_stream_info(group, groupInfo, &group_range, logger);
4164020e 168 }
97ade20b
JG
169}
170
c02af779 171bt2::Value::Shared trace_infos_query(const bt2::ConstMapValue params, const bt2c::Logger& logger)
97ade20b 172{
c02af779 173 ctf_fs_component::UP ctf_fs = ctf_fs_component_create(logger);
4164020e 174 if (!ctf_fs) {
c02af779
SM
175 BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(logger, bt2::Error,
176 "Cannot create ctf_fs_component");
4164020e
SM
177 }
178
c02af779
SM
179 const bt_value *inputs_value = NULL;
180 const bt_value *trace_name_value;
4164020e 181
c02af779
SM
182 if (!read_src_fs_parameters(params.libObjPtr(), &inputs_value, &trace_name_value,
183 ctf_fs.get())) {
184 BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(logger, bt2::Error, "Failed to read parameters");
4164020e
SM
185 }
186
c02af779
SM
187 if (ctf_fs_component_create_ctf_fs_trace(ctf_fs.get(), inputs_value, trace_name_value, NULL)) {
188 BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(logger, bt2::Error, "Failed to create trace");
4164020e
SM
189 }
190
c02af779
SM
191 const auto result = bt2::ArrayValue::create();
192 const auto traceInfo = result->appendEmptyMap();
193 populate_trace_info(ctf_fs->trace, traceInfo, logger);
c7eee084 194
c02af779 195 return result;
04c0ba87 196}
73760435 197
c02af779 198bt2::Value::Shared support_info_query(const bt2::ConstMapValue params, const bt2c::Logger& logger)
73760435 199{
c02af779
SM
200 const auto typeValue = params["type"];
201 BT_ASSERT(typeValue);
202 BT_ASSERT(typeValue->isString());
203 const auto type = typeValue->asString().value();
4164020e 204
c02af779
SM
205 if (strcmp(type, "directory") != 0) {
206 const auto result = bt2::MapValue::create();
207 result->insert("weight", 0.0f);
208 return result;
4164020e
SM
209 }
210
c02af779
SM
211 const auto inputValue = params["input"];
212 BT_ASSERT(inputValue);
213 BT_ASSERT(inputValue->isString());
214 const auto input = inputValue->asString().value();
4164020e 215
c02af779
SM
216 bt2c::GCharUP metadataPath {g_build_filename(input, CTF_FS_METADATA_FILENAME, NULL)};
217 if (!metadataPath) {
218 BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(logger, bt2::Error, "Failed to read parameters");
4164020e
SM
219 }
220
c02af779
SM
221 double weight = 0;
222 char uuid_str[BT_UUID_STR_LEN + 1];
223 bool has_uuid = false;
224 bt2c::FileUP metadataFile {g_fopen(metadataPath.get(), "rb")};
225 if (metadataFile) {
4164020e
SM
226 enum ctf_metadata_decoder_status decoder_status;
227 bt_uuid_t uuid;
228
0f5c5d5c 229 ctf_metadata_decoder_config metadata_decoder_config {logger};
4164020e 230
c02af779
SM
231 ctf_metadata_decoder_up metadata_decoder =
232 ctf_metadata_decoder_create(&metadata_decoder_config);
4164020e 233 if (!metadata_decoder) {
c02af779
SM
234 BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(logger, bt2::Error,
235 "Failed to create metadata decoder");
4164020e
SM
236 }
237
c02af779
SM
238 decoder_status =
239 ctf_metadata_decoder_append_content(metadata_decoder.get(), metadataFile.get());
4164020e 240 if (decoder_status != CTF_METADATA_DECODER_STATUS_OK) {
c02af779
SM
241 BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(
242 logger, bt2::Error, "Failed to append metadata content: metadata-decoder-status={}",
243 decoder_status);
4164020e
SM
244 }
245
246 /*
247 * We were able to parse the metadata file, so we are
248 * confident it's a CTF trace.
249 */
250 weight = 0.75;
251
252 /* If the trace has a UUID, return the stringified UUID as the group. */
1fa280c9 253 if (ctf_metadata_decoder_get_trace_class_uuid(metadata_decoder.get(), uuid) == 0) {
4164020e
SM
254 bt_uuid_to_str(uuid, uuid_str);
255 has_uuid = true;
256 }
257 }
73760435 258
c02af779
SM
259 const auto result = bt2::MapValue::create();
260 result->insert("weight", weight);
4164020e
SM
261
262 /* We are not supposed to have weight == 0 and a UUID. */
263 BT_ASSERT(weight > 0 || !has_uuid);
264
265 if (weight > 0 && has_uuid) {
c02af779 266 result->insert("group", uuid_str);
4164020e
SM
267 }
268
c02af779 269 return result;
73760435 270}
This page took 0.100532 seconds and 4 git commands to generate.