src.ctf.fs: honor component's initial log level
[babeltrace.git] / src / plugins / ctf / fs-src / query.c
CommitLineData
04c0ba87
JG
1/*
2 * query.c
3 *
4 * Babeltrace CTF file system Reader Component queries
5 *
6 * Copyright 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26
98903a3e
PP
27#define BT_LOG_OUTPUT_LEVEL log_level
28#define BT_LOG_TAG "PLUGIN/SRC.CTF.FS/QUERY"
29#include "logging/log.h"
30
04c0ba87
JG
31#include "query.h"
32#include <stdbool.h>
578e048b 33#include "common/assert.h"
04c0ba87
JG
34#include "metadata.h"
35#include "../common/metadata/decoder.h"
578e048b 36#include "common/common.h"
91d81473 37#include "common/macros.h"
3fadfbc0 38#include <babeltrace2/babeltrace.h>
97ade20b 39#include "fs.h"
55314f2a 40
04c0ba87
JG
41#define METADATA_TEXT_SIG "/* CTF 1.8"
42
97ade20b
JG
43struct range {
44 int64_t begin_ns;
45 int64_t end_ns;
46 bool set;
47};
48
04c0ba87 49BT_HIDDEN
4cdfc5e8 50bt_query_status metadata_info_query(
b19ff26f 51 bt_self_component_class_source *comp_class,
98903a3e 52 const bt_value *params, bt_logging_level log_level,
b19ff26f 53 const bt_value **user_result)
04c0ba87 54{
4cdfc5e8 55 bt_query_status status = BT_QUERY_STATUS_OK;
b19ff26f
PP
56 bt_value *result = NULL;
57 const bt_value *path_value = NULL;
04c0ba87
JG
58 char *metadata_text = NULL;
59 FILE *metadata_fp = NULL;
60 GString *g_metadata_text = NULL;
61 int ret;
62 int bo;
63 const char *path;
64 bool is_packetized;
65
05e21286 66 result = bt_value_map_create();
da91b29a 67 if (!result) {
d94d92ac 68 status = BT_QUERY_STATUS_NOMEM;
04c0ba87
JG
69 goto error;
70 }
71
f6ccaed9
PP
72 BT_ASSERT(params);
73
04c0ba87 74 if (!bt_value_is_map(params)) {
f7d0e29c 75 BT_LOGE_STR("Query parameters is not a map value object.");
d94d92ac 76 status = BT_QUERY_STATUS_INVALID_PARAMS;
04c0ba87
JG
77 goto error;
78 }
79
05e21286 80 path_value = bt_value_map_borrow_entry_value_const(params, "path");
07330b50
FD
81 if (!path_value) {
82 BT_LOGE_STR("Mandatory `path` parameter missing");
83 status = BT_QUERY_STATUS_INVALID_PARAMS;
84 goto error;
85 }
86
87 if (!bt_value_is_string(path_value)) {
88 BT_LOGE_STR("`path` parameter is required to be a string value");
89 status = BT_QUERY_STATUS_INVALID_PARAMS;
90 goto error;
91 }
92
601b0d3c 93 path = bt_value_string_get(path_value);
04c0ba87 94
f6ccaed9 95 BT_ASSERT(path);
04c0ba87
JG
96 metadata_fp = ctf_fs_metadata_open_file(path);
97 if (!metadata_fp) {
f7d0e29c 98 BT_LOGE("Cannot open trace metadata: path=\"%s\".", path);
04c0ba87
JG
99 goto error;
100 }
101
102 is_packetized = ctf_metadata_decoder_is_packetized(metadata_fp,
98903a3e 103 &bo, log_level, NULL);
04c0ba87
JG
104
105 if (is_packetized) {
106 ret = ctf_metadata_decoder_packetized_file_stream_to_buf(
98903a3e 107 metadata_fp, &metadata_text, bo, log_level, NULL);
04c0ba87 108 if (ret) {
f7d0e29c
JG
109 BT_LOGE("Cannot decode packetized metadata file: path=\"%s\"",
110 path);
04c0ba87
JG
111 goto error;
112 }
113 } else {
114 long filesize;
115
677e1a21
MD
116 ret = fseek(metadata_fp, 0, SEEK_END);
117 if (ret) {
f7d0e29c
JG
118 BT_LOGE_ERRNO("Failed to seek to the end of the metadata file",
119 ": path=\"%s\"", path);
677e1a21
MD
120 goto error;
121 }
04c0ba87 122 filesize = ftell(metadata_fp);
677e1a21 123 if (filesize < 0) {
f7d0e29c
JG
124 BT_LOGE_ERRNO("Failed to get the current position in the metadata file",
125 ": path=\"%s\"", path);
677e1a21
MD
126 goto error;
127 }
04c0ba87
JG
128 rewind(metadata_fp);
129 metadata_text = malloc(filesize + 1);
130 if (!metadata_text) {
f7d0e29c 131 BT_LOGE_STR("Cannot allocate buffer for metadata text.");
04c0ba87
JG
132 goto error;
133 }
134
135 if (fread(metadata_text, filesize, 1, metadata_fp) != 1) {
f7d0e29c
JG
136 BT_LOGE_ERRNO("Cannot read metadata file", ": path=\"%s\"",
137 path);
04c0ba87
JG
138 goto error;
139 }
140
141 metadata_text[filesize] = '\0';
142 }
143
144 g_metadata_text = g_string_new(NULL);
145 if (!g_metadata_text) {
146 goto error;
147 }
148
149 if (strncmp(metadata_text, METADATA_TEXT_SIG,
150 sizeof(METADATA_TEXT_SIG) - 1) != 0) {
151 g_string_assign(g_metadata_text, METADATA_TEXT_SIG);
152 g_string_append(g_metadata_text, " */\n\n");
153 }
154
155 g_string_append(g_metadata_text, metadata_text);
156
05e21286 157 ret = bt_value_map_insert_string_entry(result, "text",
04c0ba87
JG
158 g_metadata_text->str);
159 if (ret) {
f7d0e29c 160 BT_LOGE_STR("Cannot insert metadata text into query result.");
04c0ba87
JG
161 goto error;
162 }
163
05e21286 164 ret = bt_value_map_insert_bool_entry(result, "is-packetized",
04c0ba87
JG
165 is_packetized);
166 if (ret) {
f7d0e29c 167 BT_LOGE_STR("Cannot insert \"is-packetized\" attribute into query result.");
04c0ba87
JG
168 goto error;
169 }
170
171 goto end;
172
173error:
c5b9b441 174 BT_VALUE_PUT_REF_AND_RESET(result);
d94d92ac 175 result = NULL;
c7eee084 176
d94d92ac
PP
177 if (status >= 0) {
178 status = BT_QUERY_STATUS_ERROR;
c7eee084 179 }
04c0ba87
JG
180
181end:
04c0ba87
JG
182 free(metadata_text);
183
184 if (g_metadata_text) {
185 g_string_free(g_metadata_text, TRUE);
186 }
187
188 if (metadata_fp) {
189 fclose(metadata_fp);
190 }
c7eee084 191
05e21286 192 *user_result = result;
d94d92ac 193 return status;
97ade20b 194}
9ec238a8 195
97ade20b 196static
b19ff26f 197int add_range(bt_value *info, struct range *range,
97ade20b
JG
198 const char *range_name)
199{
200 int ret = 0;
4cdfc5e8 201 bt_value_status status;
b19ff26f 202 bt_value *range_map = NULL;
97ade20b
JG
203
204 if (!range->set) {
205 /* Not an error. */
206 goto end;
207 }
208
05e21286 209 range_map = bt_value_map_create();
97ade20b
JG
210 if (!range_map) {
211 ret = -1;
212 goto end;
213 }
214
fdd3a2da 215 status = bt_value_map_insert_signed_integer_entry(range_map, "begin",
97ade20b
JG
216 range->begin_ns);
217 if (status != BT_VALUE_STATUS_OK) {
218 ret = -1;
219 goto end;
220 }
221
fdd3a2da 222 status = bt_value_map_insert_signed_integer_entry(range_map, "end",
97ade20b
JG
223 range->end_ns);
224 if (status != BT_VALUE_STATUS_OK) {
225 ret = -1;
226 goto end;
227 }
228
05e21286
PP
229 status = bt_value_map_insert_entry(info, range_name,
230 range_map);
97ade20b
JG
231 if (status != BT_VALUE_STATUS_OK) {
232 ret = -1;
233 goto end;
234 }
da91b29a 235
97ade20b 236end:
c5b9b441 237 bt_value_put_ref(range_map);
97ade20b
JG
238 return ret;
239}
240
241static
60363f2f 242int add_stream_ids(bt_value *info, struct ctf_fs_ds_file_group *ds_file_group)
97ade20b
JG
243{
244 int ret = 0;
4cdfc5e8 245 bt_value_status status;
97ade20b 246
60363f2f 247 if (ds_file_group->stream_id != UINT64_C(-1)) {
fdd3a2da
PP
248 status = bt_value_map_insert_unsigned_integer_entry(info, "id",
249 ds_file_group->stream_id);
97ade20b
JG
250 if (status != BT_VALUE_STATUS_OK) {
251 ret = -1;
252 goto end;
253 }
254 }
255
fdd3a2da
PP
256 status = bt_value_map_insert_unsigned_integer_entry(info, "class-id",
257 ds_file_group->sc->id);
97ade20b
JG
258 if (status != BT_VALUE_STATUS_OK) {
259 ret = -1;
260 goto end;
261 }
0b29603d 262
97ade20b 263end:
97ade20b
JG
264 return ret;
265}
266
267static
268int populate_stream_info(struct ctf_fs_ds_file_group *group,
b19ff26f 269 bt_value *group_info, struct range *stream_range)
97ade20b
JG
270{
271 int ret = 0;
272 size_t file_idx;
4cdfc5e8 273 bt_value_status status;
b19ff26f 274 bt_value *file_paths;
b1c001b6 275 struct ctf_fs_ds_index_entry *first_ds_index_entry, *last_ds_index_entry;
a38d7650 276 gchar *port_name = NULL;
97ade20b 277
05e21286 278 file_paths = bt_value_array_create();
97ade20b
JG
279 if (!file_paths) {
280 ret = -1;
281 goto end;
282 }
283
284 for (file_idx = 0; file_idx < group->ds_file_infos->len; file_idx++) {
97ade20b 285 struct ctf_fs_ds_file_info *info =
60363f2f
PP
286 g_ptr_array_index(group->ds_file_infos,
287 file_idx);
97ade20b 288
05e21286 289 status = bt_value_array_append_string_element(file_paths,
97ade20b
JG
290 info->path->str);
291 if (status != BT_VALUE_STATUS_OK) {
292 ret = -1;
293 goto end;
294 }
97ade20b
JG
295 }
296
b1c001b6 297 /*
7ed5243a
FD
298 * Since each `struct ctf_fs_ds_file_group` has a sorted array of
299 * `struct ctf_fs_ds_index_entry`, we can compute the stream range from
300 * the timestamp_begin of the first index entry and the timestamp_end
301 * of the last index entry.
b1c001b6 302 */
7ed5243a
FD
303 BT_ASSERT(group->index);
304 BT_ASSERT(group->index->entries);
305 BT_ASSERT(group->index->entries->len > 0);
b1c001b6 306
7ed5243a
FD
307 /* First entry. */
308 first_ds_index_entry = (struct ctf_fs_ds_index_entry *) g_ptr_array_index(
309 group->index->entries, 0);
b1c001b6 310
7ed5243a
FD
311 /* Last entry. */
312 last_ds_index_entry = (struct ctf_fs_ds_index_entry *) g_ptr_array_index(
313 group->index->entries, group->index->entries->len - 1);
b1c001b6
FD
314
315 stream_range->begin_ns = first_ds_index_entry->timestamp_begin_ns;
316 stream_range->end_ns = last_ds_index_entry->timestamp_end_ns;
b1c001b6 317
1d4ac4b6
FD
318 /*
319 * If any of the begin and end timestamps is not set it means that
320 * packets don't include `timestamp_begin` _and_ `timestamp_end` fields
321 * in their packet context so we can't set the range.
322 */
323 stream_range->set = stream_range->begin_ns != UINT64_C(-1) &&
324 stream_range->end_ns != UINT64_C(-1);
325
326 ret = add_range(group_info, stream_range, "range-ns");
327 if (ret) {
328 goto end;
97ade20b
JG
329 }
330
05e21286
PP
331 status = bt_value_map_insert_entry(group_info, "paths",
332 file_paths);
97ade20b
JG
333 if (status != BT_VALUE_STATUS_OK) {
334 ret = -1;
335 goto end;
336 }
337
60363f2f 338 ret = add_stream_ids(group_info, group);
97ade20b
JG
339 if (ret) {
340 goto end;
341 }
a38d7650
SM
342
343 port_name = ctf_fs_make_port_name(group);
344 if (!port_name) {
345 ret = -1;
346 goto end;
347 }
348
349 status = bt_value_map_insert_string_entry(group_info, "port-name",
350 port_name);
351 if (status != BT_VALUE_STATUS_OK) {
352 ret = -1;
353 goto end;
354 }
355
97ade20b 356end:
c5b9b441 357 bt_value_put_ref(file_paths);
97ade20b
JG
358 return ret;
359}
360
361static
f280892e 362int populate_trace_info(const struct ctf_fs_trace *trace, bt_value *trace_info)
97ade20b
JG
363{
364 int ret = 0;
365 size_t group_idx;
4cdfc5e8 366 bt_value_status status;
f280892e 367 bt_value *file_groups = NULL;
97ade20b
JG
368 struct range trace_range = {
369 .begin_ns = INT64_MAX,
370 .end_ns = 0,
371 .set = false,
372 };
373 struct range trace_intersection = {
374 .begin_ns = 0,
375 .end_ns = INT64_MAX,
376 .set = false,
377 };
378
f280892e
SM
379 BT_ASSERT(trace->ds_file_groups);
380 /* Add trace range info only if it contains streams. */
381 if (trace->ds_file_groups->len == 0) {
382 ret = -1;
383 goto end;
384 }
385
05e21286 386 file_groups = bt_value_array_create();
97ade20b
JG
387 if (!file_groups) {
388 goto end;
389 }
390
05e21286 391 status = bt_value_map_insert_string_entry(trace_info, "name",
f280892e 392 trace->name->str);
97ade20b
JG
393 if (status != BT_VALUE_STATUS_OK) {
394 ret = -1;
395 goto end;
396 }
05e21286 397 status = bt_value_map_insert_string_entry(trace_info, "path",
f280892e 398 trace->path->str);
97ade20b
JG
399 if (status != BT_VALUE_STATUS_OK) {
400 ret = -1;
401 goto end;
402 }
403
97ade20b
JG
404 /* Find range of all stream groups, and of the trace. */
405 for (group_idx = 0; group_idx < trace->ds_file_groups->len;
406 group_idx++) {
b19ff26f 407 bt_value *group_info;
97ade20b
JG
408 struct range group_range = { .set = false };
409 struct ctf_fs_ds_file_group *group = g_ptr_array_index(
410 trace->ds_file_groups, group_idx);
411
05e21286 412 group_info = bt_value_map_create();
97ade20b
JG
413 if (!group_info) {
414 ret = -1;
415 goto end;
416 }
417
418 ret = populate_stream_info(group, group_info, &group_range);
419 if (ret) {
c5b9b441 420 bt_value_put_ref(group_info);
97ade20b
JG
421 goto end;
422 }
423
7233204d
FD
424 status = bt_value_array_append_element(file_groups, group_info);
425 bt_value_put_ref(group_info);
426 if (status != BT_VALUE_STATUS_OK) {
427 goto end;
428 }
429
97ade20b 430 if (group_range.set) {
91d81473 431 trace_range.begin_ns = MIN(trace_range.begin_ns,
97ade20b 432 group_range.begin_ns);
91d81473 433 trace_range.end_ns = MAX(trace_range.end_ns,
97ade20b
JG
434 group_range.end_ns);
435 trace_range.set = true;
436
91d81473 437 trace_intersection.begin_ns = MAX(trace_intersection.begin_ns,
97ade20b 438 group_range.begin_ns);
91d81473 439 trace_intersection.end_ns = MIN(trace_intersection.end_ns,
97ade20b
JG
440 group_range.end_ns);
441 trace_intersection.set = true;
97ade20b
JG
442 }
443 }
444
445 ret = add_range(trace_info, &trace_range, "range-ns");
446 if (ret) {
447 goto end;
448 }
c6daf8b2
PP
449
450 if (trace_intersection.begin_ns < trace_intersection.end_ns) {
451 ret = add_range(trace_info, &trace_intersection,
452 "intersection-range-ns");
453 if (ret) {
454 goto end;
455 }
97ade20b
JG
456 }
457
05e21286
PP
458 status = bt_value_map_insert_entry(trace_info, "streams",
459 file_groups);
c5b9b441 460 BT_VALUE_PUT_REF_AND_RESET(file_groups);
97ade20b
JG
461 if (status != BT_VALUE_STATUS_OK) {
462 ret = -1;
463 goto end;
464 }
465
466end:
c5b9b441 467 bt_value_put_ref(file_groups);
97ade20b
JG
468 return ret;
469}
470
471BT_HIDDEN
4cdfc5e8 472bt_query_status trace_info_query(
b19ff26f 473 bt_self_component_class_source *comp_class,
98903a3e 474 const bt_value *params, bt_logging_level log_level,
b19ff26f 475 const bt_value **user_result)
97ade20b 476{
f280892e 477 struct ctf_fs_component *ctf_fs = NULL;
4cdfc5e8 478 bt_query_status status = BT_QUERY_STATUS_OK;
b19ff26f 479 bt_value *result = NULL;
f280892e 480 const bt_value *paths_value = NULL;
97ade20b 481 int ret = 0;
f280892e 482 guint i;
97ade20b 483
f6ccaed9
PP
484 BT_ASSERT(params);
485
97ade20b
JG
486 if (!bt_value_is_map(params)) {
487 BT_LOGE("Query parameters is not a map value object.");
d94d92ac 488 status = BT_QUERY_STATUS_INVALID_PARAMS;
97ade20b
JG
489 goto error;
490 }
491
98903a3e 492 ctf_fs = ctf_fs_component_create(log_level);
d907165c 493 if (!ctf_fs) {
97ade20b
JG
494 goto error;
495 }
97ade20b 496
d907165c
SM
497 if (!read_src_fs_parameters(params, &paths_value, ctf_fs)) {
498 status = BT_QUERY_STATUS_INVALID_PARAMS;
97ade20b
JG
499 goto error;
500 }
501
f280892e 502 if (ctf_fs_component_create_ctf_fs_traces(NULL, ctf_fs, paths_value)) {
97ade20b
JG
503 goto error;
504 }
505
05e21286 506 result = bt_value_array_create();
da91b29a 507 if (!result) {
d94d92ac 508 status = BT_QUERY_STATUS_NOMEM;
97ade20b
JG
509 goto error;
510 }
511
f280892e
SM
512 for (i = 0; i < ctf_fs->traces->len; i++) {
513 struct ctf_fs_trace *trace;
b19ff26f 514 bt_value *trace_info;
f280892e
SM
515 bt_value_status status;
516
517 trace = g_ptr_array_index(ctf_fs->traces, i);
518 BT_ASSERT(trace);
97ade20b 519
05e21286 520 trace_info = bt_value_map_create();
97ade20b
JG
521 if (!trace_info) {
522 BT_LOGE("Failed to create trace info map.");
523 goto error;
524 }
525
f280892e 526 ret = populate_trace_info(trace, trace_info);
97ade20b 527 if (ret) {
c5b9b441 528 bt_value_put_ref(trace_info);
97ade20b
JG
529 goto error;
530 }
531
05e21286 532 status = bt_value_array_append_element(result, trace_info);
c5b9b441 533 bt_value_put_ref(trace_info);
97ade20b
JG
534 if (status != BT_VALUE_STATUS_OK) {
535 goto error;
536 }
537 }
538
539 goto end;
540
541error:
c5b9b441 542 BT_VALUE_PUT_REF_AND_RESET(result);
d94d92ac 543 result = NULL;
c7eee084 544
d94d92ac
PP
545 if (status >= 0) {
546 status = BT_QUERY_STATUS_ERROR;
c7eee084
PP
547 }
548
97ade20b 549end:
f280892e
SM
550 if (ctf_fs) {
551 ctf_fs_destroy(ctf_fs);
552 ctf_fs = NULL;
97ade20b 553 }
d94d92ac 554
05e21286 555 *user_result = result;
d94d92ac 556 return status;
04c0ba87 557}
This page took 0.064071 seconds and 4 git commands to generate.