Fix: various fixes for ctf-traces/succeed test cases
[babeltrace.git] / plugins / ctf / fs-src / fs.c
CommitLineData
7a278c8e 1/*
ea0b4b9e 2 * fs.c
7a278c8e 3 *
ea0b4b9e 4 * Babeltrace CTF file system Reader Component
7a278c8e 5 *
1a9f7075 6 * Copyright 2015-2017 Philippe Proulx <pproulx@efficios.com>
f3bc2010 7 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7a278c8e 8 *
7a278c8e
JG
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 */
27
4bd72b60 28#include <babeltrace/common-internal.h>
5b29e799 29#include <babeltrace/ctf-ir/packet.h>
ac0c6bdd 30#include <babeltrace/ctf-ir/clock-class.h>
94cf822e
PP
31#include <babeltrace/ctf-ir/stream.h>
32#include <babeltrace/ctf-ir/fields.h>
4f1f88a6 33#include <babeltrace/graph/private-port.h>
b2e0c907 34#include <babeltrace/graph/private-component.h>
4f1f88a6
PP
35#include <babeltrace/graph/private-component-source.h>
36#include <babeltrace/graph/private-notification-iterator.h>
b2e0c907
PP
37#include <babeltrace/graph/component.h>
38#include <babeltrace/graph/notification-iterator.h>
599faa1c 39#include <babeltrace/graph/clock-class-priority-map.h>
7d61fa8e 40#include <plugins-common.h>
ea0b4b9e
JG
41#include <glib.h>
42#include <assert.h>
94cf822e 43#include <inttypes.h>
c55a9f58 44#include <stdbool.h>
56a1cced 45#include "fs.h"
413bc2c4 46#include "metadata.h"
94cf822e 47#include "data-stream-file.h"
e7a4393b 48#include "file.h"
1e649dff 49#include "../common/metadata/decoder.h"
04c0ba87 50#include "query.h"
e7a4393b 51
55314f2a
JG
52#define BT_LOG_TAG "PLUGIN-CTF-FS-SRC"
53#include "logging.h"
ea0b4b9e 54
78bb6992
MD
55BT_HIDDEN
56bool ctf_fs_debug;
ea0b4b9e 57
94cf822e
PP
58static
59int notif_iter_data_set_current_ds_file(struct ctf_fs_notif_iter_data *notif_iter_data)
60{
61 struct ctf_fs_ds_file_info *ds_file_info;
62 int ret = 0;
63
64 assert(notif_iter_data->ds_file_info_index <
65 notif_iter_data->ds_file_group->ds_file_infos->len);
66 ds_file_info = g_ptr_array_index(
67 notif_iter_data->ds_file_group->ds_file_infos,
68 notif_iter_data->ds_file_info_index);
69
70 ctf_fs_ds_file_destroy(notif_iter_data->ds_file);
71 notif_iter_data->ds_file = ctf_fs_ds_file_create(
72 notif_iter_data->ds_file_group->ctf_fs_trace,
73 notif_iter_data->ds_file_group->stream,
97ade20b 74 ds_file_info->path->str);
94cf822e
PP
75 if (!notif_iter_data->ds_file) {
76 ret = -1;
77 }
78
79 return ret;
80}
81
82static
83void ctf_fs_notif_iter_data_destroy(
84 struct ctf_fs_notif_iter_data *notif_iter_data)
85{
86 if (!notif_iter_data) {
87 return;
88 }
89
90 ctf_fs_ds_file_destroy(notif_iter_data->ds_file);
91 g_free(notif_iter_data);
92}
93
41a2b7ae 94struct bt_notification_iterator_next_return ctf_fs_iterator_next(
4f1f88a6 95 struct bt_private_notification_iterator *iterator)
ea0b4b9e 96{
94cf822e
PP
97 struct bt_notification_iterator_next_return next_ret;
98 struct ctf_fs_notif_iter_data *notif_iter_data =
4f1f88a6 99 bt_private_notification_iterator_get_user_data(iterator);
94cf822e
PP
100 int ret;
101
102 assert(notif_iter_data->ds_file);
103 next_ret = ctf_fs_ds_file_next(notif_iter_data->ds_file);
104 if (next_ret.status == BT_NOTIFICATION_ITERATOR_STATUS_END) {
105 assert(!next_ret.notification);
106 notif_iter_data->ds_file_info_index++;
107
108 if (notif_iter_data->ds_file_info_index ==
109 notif_iter_data->ds_file_group->ds_file_infos->len) {
110 /*
111 * No more stream files to read: we reached the
112 * real end.
113 */
114 goto end;
115 }
116
117 /*
118 * Open and start reading the next stream file within
119 * our stream file group.
120 */
121 ret = notif_iter_data_set_current_ds_file(notif_iter_data);
122 if (ret) {
123 next_ret.status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
124 goto end;
125 }
126
127 next_ret = ctf_fs_ds_file_next(notif_iter_data->ds_file);
128
129 /*
130 * We should not get BT_NOTIFICATION_ITERATOR_STATUS_END
131 * with a brand new stream file because empty stream
132 * files are not even part of stream file groups, which
133 * means we're sure to get at least one pair of "packet
134 * begin" and "packet end" notifications in the case of
135 * a single, empty packet.
136 */
137 assert(next_ret.status != BT_NOTIFICATION_ITERATOR_STATUS_END);
138 }
d01e0f33 139
94cf822e
PP
140end:
141 return next_ret;
ea0b4b9e 142}
bfd20a42 143
4f1f88a6 144void ctf_fs_iterator_finalize(struct bt_private_notification_iterator *it)
760051fa 145{
94cf822e 146 void *notif_iter_data =
4f1f88a6 147 bt_private_notification_iterator_get_user_data(it);
760051fa 148
94cf822e 149 ctf_fs_notif_iter_data_destroy(notif_iter_data);
760051fa
JG
150}
151
4f1f88a6
PP
152enum bt_notification_iterator_status ctf_fs_iterator_init(
153 struct bt_private_notification_iterator *it,
154 struct bt_private_port *port)
4c1456f0 155{
4f1f88a6 156 struct ctf_fs_port_data *port_data;
94cf822e 157 struct ctf_fs_notif_iter_data *notif_iter_data = NULL;
4f1f88a6
PP
158 enum bt_notification_iterator_status ret =
159 BT_NOTIFICATION_ITERATOR_STATUS_OK;
94cf822e 160 int iret;
760051fa 161
4f1f88a6
PP
162 port_data = bt_private_port_get_user_data(port);
163 if (!port_data) {
fe8ad2b6 164 ret = BT_NOTIFICATION_ITERATOR_STATUS_INVALID;
4f1f88a6
PP
165 goto error;
166 }
5b29e799 167
94cf822e
PP
168 notif_iter_data = g_new0(struct ctf_fs_notif_iter_data, 1);
169 if (!notif_iter_data) {
170 ret = BT_NOTIFICATION_ITERATOR_STATUS_NOMEM;
171 goto error;
172 }
173
174 notif_iter_data->ds_file_group = port_data->ds_file_group;
175 iret = notif_iter_data_set_current_ds_file(notif_iter_data);
176 if (iret) {
177 ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
4f1f88a6 178 goto error;
760051fa
JG
179 }
180
94cf822e 181 ret = bt_private_notification_iterator_set_user_data(it, notif_iter_data);
4f1f88a6
PP
182 if (ret) {
183 goto error;
760051fa
JG
184 }
185
94cf822e 186 notif_iter_data = NULL;
4f1f88a6 187 goto end;
5b29e799 188
4f1f88a6
PP
189error:
190 (void) bt_private_notification_iterator_set_user_data(it, NULL);
191
192 if (ret == BT_NOTIFICATION_ITERATOR_STATUS_OK) {
193 ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
760051fa 194 }
5b29e799 195
760051fa 196end:
94cf822e 197 ctf_fs_notif_iter_data_destroy(notif_iter_data);
760051fa
JG
198 return ret;
199}
200
760051fa 201static
1a9f7075 202void ctf_fs_destroy(struct ctf_fs_component *ctf_fs)
760051fa 203{
4f1f88a6 204 if (!ctf_fs) {
8fa760ba
JG
205 return;
206 }
4f1f88a6 207
1a9f7075
PP
208 if (ctf_fs->traces) {
209 g_ptr_array_free(ctf_fs->traces, TRUE);
56a1cced 210 }
4f1f88a6
PP
211
212 if (ctf_fs->port_data) {
213 g_ptr_array_free(ctf_fs->port_data, TRUE);
c14d7e26 214 }
760051fa 215
1a9f7075
PP
216 g_free(ctf_fs);
217}
218
97ade20b
JG
219BT_HIDDEN
220void ctf_fs_trace_destroy(struct ctf_fs_trace *ctf_fs_trace)
1a9f7075 221{
1a9f7075
PP
222 if (!ctf_fs_trace) {
223 return;
224 }
225
94cf822e
PP
226 if (ctf_fs_trace->ds_file_groups) {
227 g_ptr_array_free(ctf_fs_trace->ds_file_groups, TRUE);
228 }
229
1a9f7075
PP
230 if (ctf_fs_trace->path) {
231 g_string_free(ctf_fs_trace->path, TRUE);
4f1f88a6 232 }
760051fa 233
1a9f7075
PP
234 if (ctf_fs_trace->name) {
235 g_string_free(ctf_fs_trace->name, TRUE);
236 }
237
238 if (ctf_fs_trace->metadata) {
239 ctf_fs_metadata_fini(ctf_fs_trace->metadata);
240 g_free(ctf_fs_trace->metadata);
241 }
242
243 bt_put(ctf_fs_trace->cc_prio_map);
244 g_free(ctf_fs_trace);
4c1456f0
JG
245}
246
97ade20b
JG
247static
248void ctf_fs_trace_destroy_notifier(void *data)
249{
250 struct ctf_fs_trace *trace = data;
251 ctf_fs_trace_destroy(trace);
252}
253
4f1f88a6 254void ctf_fs_finalize(struct bt_private_component *component)
a4792757 255{
4f1f88a6
PP
256 void *data = bt_private_component_get_user_data(component);
257
1a9f7075 258 ctf_fs_destroy(data);
a4792757
JG
259}
260
e7a4393b 261static
4f1f88a6
PP
262void port_data_destroy(void *data) {
263 struct ctf_fs_port_data *port_data = data;
264
265 if (!port_data) {
266 return;
267 }
268
4f1f88a6 269 g_free(port_data);
5b29e799
JG
270}
271
272static
55314f2a
JG
273int create_one_port_for_trace(struct ctf_fs_component *ctf_fs,
274 struct ctf_fs_trace *ctf_fs_trace,
94cf822e 275 struct ctf_fs_ds_file_group *ds_file_group)
5b29e799 276{
4f1f88a6 277 int ret = 0;
4f1f88a6
PP
278 struct ctf_fs_port_data *port_data = NULL;
279 GString *port_name = NULL;
94cf822e
PP
280 struct ctf_fs_ds_file_info *ds_file_info =
281 g_ptr_array_index(ds_file_group->ds_file_infos, 0);
4f1f88a6
PP
282
283 port_name = g_string_new(NULL);
284 if (!port_name) {
285 goto error;
286 }
287
94cf822e
PP
288 /*
289 * Assign the name for the new output port. If there's more than
290 * one stream file in the stream file group, the first
291 * (earliest) stream file's path is used.
292 */
293 assert(ds_file_group->ds_file_infos->len > 0);
294 ds_file_info = g_ptr_array_index(ds_file_group->ds_file_infos, 0);
295 g_string_assign(port_name, ds_file_info->path->str);
55314f2a 296 BT_LOGD("Creating one port named `%s`", port_name->str);
4f1f88a6
PP
297
298 /* Create output port for this file */
4f1f88a6
PP
299 port_data = g_new0(struct ctf_fs_port_data, 1);
300 if (!port_data) {
301 goto error;
302 }
303
94cf822e 304 port_data->ds_file_group = ds_file_group;
147337a3
PP
305 ret = bt_private_component_source_add_output_private_port(
306 ctf_fs->priv_comp, port_name->str, port_data, NULL);
307 if (ret) {
4f1f88a6
PP
308 goto error;
309 }
310
311 g_ptr_array_add(ctf_fs->port_data, port_data);
312 port_data = NULL;
313 goto end;
314
315error:
316 ret = -1;
317
318end:
319 if (port_name) {
320 g_string_free(port_name, TRUE);
321 }
322
4f1f88a6
PP
323 port_data_destroy(port_data);
324 return ret;
5b29e799
JG
325}
326
327static
55314f2a
JG
328int create_ports_for_trace(struct ctf_fs_component *ctf_fs,
329 struct ctf_fs_trace *ctf_fs_trace)
94cf822e
PP
330{
331 int ret = 0;
94cf822e
PP
332 size_t i;
333
334 /* Create one output port for each stream file group */
335 for (i = 0; i < ctf_fs_trace->ds_file_groups->len; i++) {
336 struct ctf_fs_ds_file_group *ds_file_group =
337 g_ptr_array_index(ctf_fs_trace->ds_file_groups, i);
338
55314f2a
JG
339 ret = create_one_port_for_trace(ctf_fs, ctf_fs_trace,
340 ds_file_group);
94cf822e 341 if (ret) {
55314f2a 342 BT_LOGE("Cannot create output port.");
94cf822e
PP
343 goto end;
344 }
345 }
346
347end:
348 return ret;
349}
350
351uint64_t get_packet_header_stream_instance_id(struct ctf_fs_trace *ctf_fs_trace,
352 struct bt_ctf_field *packet_header_field)
353{
354 struct bt_ctf_field *stream_instance_id_field = NULL;
355 uint64_t stream_instance_id = -1ULL;
356 int ret;
357
358 if (!packet_header_field) {
359 goto end;
360 }
361
362 stream_instance_id_field = bt_ctf_field_structure_get_field_by_name(
363 packet_header_field, "stream_instance_id");
364 if (!stream_instance_id_field) {
365 goto end;
366 }
367
368 ret = bt_ctf_field_unsigned_integer_get_value(stream_instance_id_field,
369 &stream_instance_id);
370 if (ret) {
371 stream_instance_id = -1ULL;
372 goto end;
373 }
374
375end:
376 bt_put(stream_instance_id_field);
377 return stream_instance_id;
378}
379
380struct bt_ctf_stream_class *stream_class_from_packet_header(
381 struct ctf_fs_trace *ctf_fs_trace,
382 struct bt_ctf_field *packet_header_field)
383{
384 struct bt_ctf_field *stream_id_field = NULL;
385 struct bt_ctf_stream_class *stream_class = NULL;
386 uint64_t stream_id = -1ULL;
387 int ret;
388
389 if (!packet_header_field) {
390 goto single_stream_class;
391 }
392
393 stream_id_field = bt_ctf_field_structure_get_field_by_name(
394 packet_header_field, "stream_id");
395 if (!stream_id_field) {
89b08333 396 goto single_stream_class;
94cf822e
PP
397 }
398
399 ret = bt_ctf_field_unsigned_integer_get_value(stream_id_field,
400 &stream_id);
401 if (ret) {
402 stream_id = -1ULL;
403 }
404
405 if (stream_id == -1ULL) {
406single_stream_class:
407 /* Single stream class */
408 if (bt_ctf_trace_get_stream_class_count(
409 ctf_fs_trace->metadata->trace) == 0) {
410 goto end;
411 }
412
413 stream_class = bt_ctf_trace_get_stream_class_by_index(
414 ctf_fs_trace->metadata->trace, 0);
415 } else {
416 stream_class = bt_ctf_trace_get_stream_class_by_id(
417 ctf_fs_trace->metadata->trace, stream_id);
418 }
419
420end:
421 bt_put(stream_id_field);
422 return stream_class;
423}
424
425uint64_t get_packet_context_timestamp_begin_ns(
426 struct ctf_fs_trace *ctf_fs_trace,
427 struct bt_ctf_field *packet_context_field)
428{
429 int ret;
430 struct bt_ctf_field *timestamp_begin_field = NULL;
431 struct bt_ctf_field_type *timestamp_begin_ft = NULL;
432 uint64_t timestamp_begin_raw_value = -1ULL;
433 uint64_t timestamp_begin_ns = -1ULL;
434 int64_t timestamp_begin_ns_signed;
435 struct bt_ctf_clock_class *timestamp_begin_clock_class = NULL;
436 struct bt_ctf_clock_value *clock_value = NULL;
437
438 if (!packet_context_field) {
439 goto end;
440 }
441
442 timestamp_begin_field = bt_ctf_field_structure_get_field_by_name(
443 packet_context_field, "timestamp_begin");
444 if (!timestamp_begin_field) {
445 goto end;
446 }
447
448 timestamp_begin_ft = bt_ctf_field_get_type(timestamp_begin_field);
449 assert(timestamp_begin_ft);
450 timestamp_begin_clock_class =
451 bt_ctf_field_type_integer_get_mapped_clock_class(timestamp_begin_ft);
452 if (!timestamp_begin_clock_class) {
453 goto end;
454 }
455
456 ret = bt_ctf_field_unsigned_integer_get_value(timestamp_begin_field,
457 &timestamp_begin_raw_value);
458 if (ret) {
459 goto end;
460 }
461
462 clock_value = bt_ctf_clock_value_create(timestamp_begin_clock_class,
463 timestamp_begin_raw_value);
464 if (!clock_value) {
465 goto end;
466 }
467
468 ret = bt_ctf_clock_value_get_value_ns_from_epoch(clock_value,
469 &timestamp_begin_ns_signed);
470 if (ret) {
471 goto end;
472 }
473
474 timestamp_begin_ns = (uint64_t) timestamp_begin_ns_signed;
475
476end:
477 bt_put(timestamp_begin_field);
478 bt_put(timestamp_begin_ft);
479 bt_put(timestamp_begin_clock_class);
480 bt_put(clock_value);
481 return timestamp_begin_ns;
482}
483
484static
485void ctf_fs_ds_file_info_destroy(struct ctf_fs_ds_file_info *ds_file_info)
486{
487 if (!ds_file_info) {
488 return;
489 }
490
491 if (ds_file_info->path) {
492 g_string_free(ds_file_info->path, TRUE);
493 }
494
97ade20b 495 ctf_fs_ds_index_destroy(ds_file_info->index);
94cf822e
PP
496 g_free(ds_file_info);
497}
498
499static
500struct ctf_fs_ds_file_info *ctf_fs_ds_file_info_create(const char *path,
97ade20b 501 uint64_t begin_ns, struct ctf_fs_ds_index *index)
94cf822e
PP
502{
503 struct ctf_fs_ds_file_info *ds_file_info;
504
505 ds_file_info = g_new0(struct ctf_fs_ds_file_info, 1);
506 if (!ds_file_info) {
507 goto end;
508 }
509
510 ds_file_info->path = g_string_new(path);
511 if (!ds_file_info->path) {
512 ctf_fs_ds_file_info_destroy(ds_file_info);
513 ds_file_info = NULL;
514 goto end;
515 }
516
517 ds_file_info->begin_ns = begin_ns;
97ade20b
JG
518 ds_file_info->index = index;
519 index = NULL;
94cf822e
PP
520
521end:
97ade20b 522 ctf_fs_ds_index_destroy(index);
94cf822e
PP
523 return ds_file_info;
524}
525
526static
527void ctf_fs_ds_file_group_destroy(struct ctf_fs_ds_file_group *ds_file_group)
528{
529 if (!ds_file_group) {
530 return;
531 }
532
533 if (ds_file_group->ds_file_infos) {
534 g_ptr_array_free(ds_file_group->ds_file_infos, TRUE);
535 }
536
537 bt_put(ds_file_group->stream);
538 g_free(ds_file_group);
539}
540
541static
542struct ctf_fs_ds_file_group *ctf_fs_ds_file_group_create(
543 struct ctf_fs_trace *ctf_fs_trace,
544 struct bt_ctf_stream_class *stream_class,
545 uint64_t stream_instance_id)
546{
547 struct ctf_fs_ds_file_group *ds_file_group;
548
549 assert(stream_class);
550 ds_file_group = g_new0(struct ctf_fs_ds_file_group, 1);
551 if (!ds_file_group) {
552 goto error;
553 }
554
555 ds_file_group->ds_file_infos = g_ptr_array_new_with_free_func(
556 (GDestroyNotify) ctf_fs_ds_file_info_destroy);
557 if (!ds_file_group->ds_file_infos) {
558 goto error;
559 }
560
561 if (stream_instance_id == -1ULL) {
562 ds_file_group->stream = bt_ctf_stream_create(
563 stream_class, NULL);
564 } else {
565 ds_file_group->stream = bt_ctf_stream_create_with_id(
566 stream_class, NULL, stream_instance_id);
567 }
568
569 if (!ds_file_group->stream) {
570 goto error;
571 }
572
573 ds_file_group->ctf_fs_trace = ctf_fs_trace;
574
575 goto end;
576
577error:
578 ctf_fs_ds_file_group_destroy(ds_file_group);
579 ds_file_group = NULL;
580
581end:
582 return ds_file_group;
583}
584
585static
586int ctf_fs_ds_file_group_add_ds_file_info(
587 struct ctf_fs_ds_file_group *ds_file_group,
97ade20b
JG
588 const char *path, uint64_t begin_ns,
589 struct ctf_fs_ds_index *index)
94cf822e
PP
590{
591 struct ctf_fs_ds_file_info *ds_file_info;
592 gint i = 0;
593 int ret = 0;
594
97ade20b
JG
595 /* Onwership of index is transferred. */
596 ds_file_info = ctf_fs_ds_file_info_create(path, begin_ns, index);
597 index = NULL;
94cf822e
PP
598 if (!ds_file_info) {
599 goto error;
600 }
601
602 /* Find a spot to insert this one */
603 for (i = 0; i < ds_file_group->ds_file_infos->len; i++) {
604 struct ctf_fs_ds_file_info *other_ds_file_info =
605 g_ptr_array_index(ds_file_group->ds_file_infos, i);
606
607 if (begin_ns < other_ds_file_info->begin_ns) {
608 break;
609 }
610 }
611
612 if (i == ds_file_group->ds_file_infos->len) {
613 /* Append instead */
614 i = -1;
615 }
616
617 g_ptr_array_insert(ds_file_group->ds_file_infos, i, ds_file_info);
618 ds_file_info = NULL;
619 goto end;
620
621error:
622 ctf_fs_ds_file_info_destroy(ds_file_info);
97ade20b 623 ctf_fs_ds_index_destroy(index);
94cf822e 624 ret = -1;
94cf822e
PP
625end:
626 return ret;
627}
628
629static
630int add_ds_file_to_ds_file_group(struct ctf_fs_trace *ctf_fs_trace,
631 const char *path)
632{
633 struct bt_ctf_field *packet_header_field = NULL;
634 struct bt_ctf_field *packet_context_field = NULL;
635 struct bt_ctf_stream_class *stream_class = NULL;
94cf822e
PP
636 uint64_t stream_instance_id = -1ULL;
637 uint64_t begin_ns = -1ULL;
638 struct ctf_fs_ds_file_group *ds_file_group = NULL;
639 bool add_group = false;
640 int ret;
641 size_t i;
97ade20b
JG
642 struct ctf_fs_ds_file *ds_file;
643 struct ctf_fs_ds_index *index = NULL;
94cf822e 644
97ade20b
JG
645 ds_file = ctf_fs_ds_file_create(ctf_fs_trace, NULL, path);
646 if (!ds_file) {
647 goto error;
648 }
649
650 ret = ctf_fs_ds_file_get_packet_header_context_fields(ds_file,
651 &packet_header_field, &packet_context_field);
94cf822e 652 if (ret) {
55314f2a 653 BT_LOGE("Cannot get stream file's first packet's header and context fields (`%s`).",
94cf822e
PP
654 path);
655 goto error;
656 }
657
658 stream_instance_id = get_packet_header_stream_instance_id(ctf_fs_trace,
659 packet_header_field);
660 begin_ns = get_packet_context_timestamp_begin_ns(ctf_fs_trace,
661 packet_context_field);
662 stream_class = stream_class_from_packet_header(ctf_fs_trace,
663 packet_header_field);
664 if (!stream_class) {
665 goto error;
666 }
667
97ade20b
JG
668 index = ctf_fs_ds_file_build_index(ds_file);
669 if (!index) {
670 BT_LOGW("Failed to index CTF stream file \'%s\'",
671 ds_file->file->path->str);
672 }
673
94cf822e
PP
674 if (begin_ns == -1ULL) {
675 /*
676 * No beggining timestamp to sort the stream files
677 * within a stream file group, so consider that this
678 * file must be the only one within its group.
679 */
680 stream_instance_id = -1ULL;
681 }
682
683 if (stream_instance_id == -1ULL) {
684 /*
685 * No stream instance ID or no beginning timestamp:
686 * create a unique stream file group for this stream
687 * file because, even if there's a stream instance ID,
688 * there's no timestamp to order the file within its
689 * group.
690 */
691
692 ds_file_group = ctf_fs_ds_file_group_create(ctf_fs_trace,
693 stream_class, stream_instance_id);
694 if (!ds_file_group) {
695 goto error;
696 }
697
698 ret = ctf_fs_ds_file_group_add_ds_file_info(ds_file_group,
97ade20b
JG
699 path, begin_ns, index);
700 /* Ownership of index is transferred. */
701 index = NULL;
94cf822e
PP
702 if (ret) {
703 goto error;
704 }
705
706 add_group = true;
707 goto end;
708 }
709
710 assert(stream_instance_id != -1ULL);
711 assert(begin_ns != -1ULL);
712
713 /* Find an existing stream file group with this ID */
714 for (i = 0; i < ctf_fs_trace->ds_file_groups->len; i++) {
715 int64_t id;
716 struct bt_ctf_stream_class *cand_stream_class;
717
718 ds_file_group = g_ptr_array_index(
719 ctf_fs_trace->ds_file_groups, i);
720 id = bt_ctf_stream_get_id(ds_file_group->stream);
721 cand_stream_class = bt_ctf_stream_get_class(
722 ds_file_group->stream);
723
724 assert(cand_stream_class);
725 bt_put(cand_stream_class);
726
727 if (cand_stream_class == stream_class &&
728 (uint64_t) id == stream_instance_id) {
729 break;
730 }
731
732 ds_file_group = NULL;
733 }
734
735 if (!ds_file_group) {
736 ds_file_group = ctf_fs_ds_file_group_create(ctf_fs_trace,
737 stream_class, stream_instance_id);
738 if (!ds_file_group) {
739 goto error;
740 }
741
742 add_group = true;
743 }
744
745 ret = ctf_fs_ds_file_group_add_ds_file_info(ds_file_group,
97ade20b
JG
746 path, begin_ns, index);
747 index = NULL;
94cf822e
PP
748 if (ret) {
749 goto error;
750 }
751
752 goto end;
753
754error:
755 ctf_fs_ds_file_group_destroy(ds_file_group);
756 ret = -1;
757
758end:
759 if (add_group && ds_file_group) {
760 g_ptr_array_add(ctf_fs_trace->ds_file_groups, ds_file_group);
761 }
97ade20b
JG
762 ctf_fs_ds_file_destroy(ds_file);
763 ctf_fs_ds_index_destroy(index);
94cf822e
PP
764 bt_put(packet_header_field);
765 bt_put(packet_context_field);
766 bt_put(stream_class);
767 return ret;
768}
769
770static
771int create_ds_file_groups(struct ctf_fs_trace *ctf_fs_trace)
e7a4393b
JG
772{
773 int ret = 0;
4f1f88a6 774 const char *basename;
e7a4393b 775 GError *error = NULL;
4f1f88a6 776 GDir *dir = NULL;
e7a4393b 777
94cf822e 778 /* Check each file in the path directory, except specific ones */
1a9f7075 779 dir = g_dir_open(ctf_fs_trace->path->str, 0, &error);
e7a4393b 780 if (!dir) {
55314f2a 781 BT_LOGE("Cannot open directory `%s`: %s (code %d)",
1a9f7075 782 ctf_fs_trace->path->str, error->message,
4f1f88a6 783 error->code);
e7a4393b
JG
784 goto error;
785 }
786
4f1f88a6 787 while ((basename = g_dir_read_name(dir))) {
94cf822e
PP
788 struct ctf_fs_file *file;
789
4f1f88a6 790 if (!strcmp(basename, CTF_FS_METADATA_FILENAME)) {
e7a4393b 791 /* Ignore the metadata stream. */
55314f2a 792 BT_LOGD("Ignoring metadata file `%s/%s`",
1a9f7075 793 ctf_fs_trace->path->str, basename);
e7a4393b
JG
794 continue;
795 }
796
4f1f88a6 797 if (basename[0] == '.') {
55314f2a 798 BT_LOGD("Ignoring hidden file `%s/%s`",
1a9f7075 799 ctf_fs_trace->path->str, basename);
e7a4393b
JG
800 continue;
801 }
802
803 /* Create the file. */
55314f2a 804 file = ctf_fs_file_create();
e7a4393b 805 if (!file) {
55314f2a 806 BT_LOGE("Cannot create stream file object for file `%s/%s`",
1a9f7075 807 ctf_fs_trace->path->str, basename);
e7a4393b
JG
808 goto error;
809 }
810
811 /* Create full path string. */
812 g_string_append_printf(file->path, "%s/%s",
1a9f7075 813 ctf_fs_trace->path->str, basename);
e7a4393b 814 if (!g_file_test(file->path->str, G_FILE_TEST_IS_REGULAR)) {
55314f2a 815 BT_LOGD("Ignoring non-regular file `%s`",
1a9f7075 816 file->path->str);
e7a4393b 817 ctf_fs_file_destroy(file);
4f1f88a6 818 file = NULL;
e7a4393b
JG
819 continue;
820 }
821
55314f2a 822 ret = ctf_fs_file_open(file, "rb");
4f1f88a6 823 if (ret) {
55314f2a 824 BT_LOGE("Cannot open stream file `%s`", file->path->str);
e7a4393b
JG
825 goto error;
826 }
827
9fa0891a
JG
828 if (file->size == 0) {
829 /* Skip empty stream. */
55314f2a 830 BT_LOGD("Ignoring empty file `%s`", file->path->str);
9fa0891a
JG
831 ctf_fs_file_destroy(file);
832 continue;
833 }
834
94cf822e
PP
835 ret = add_ds_file_to_ds_file_group(ctf_fs_trace,
836 file->path->str);
4f1f88a6 837 if (ret) {
89b08333 838 BT_LOGE("Cannot add stream file `%s` to stream file group",
1a9f7075 839 file->path->str);
94cf822e 840 ctf_fs_file_destroy(file);
e7a4393b
JG
841 goto error;
842 }
843
4f1f88a6 844 ctf_fs_file_destroy(file);
e7a4393b
JG
845 }
846
847 goto end;
4f1f88a6 848
e7a4393b
JG
849error:
850 ret = -1;
4f1f88a6 851
e7a4393b
JG
852end:
853 if (dir) {
854 g_dir_close(dir);
855 dir = NULL;
856 }
4f1f88a6 857
e7a4393b
JG
858 if (error) {
859 g_error_free(error);
860 }
5b29e799 861
91457551 862 return ret;
5b29e799
JG
863}
864
599faa1c 865static
1a9f7075 866int create_cc_prio_map(struct ctf_fs_trace *ctf_fs_trace)
599faa1c
PP
867{
868 int ret = 0;
869 size_t i;
870 int count;
871
1a9f7075
PP
872 assert(ctf_fs_trace);
873 ctf_fs_trace->cc_prio_map = bt_clock_class_priority_map_create();
874 if (!ctf_fs_trace->cc_prio_map) {
599faa1c
PP
875 ret = -1;
876 goto end;
877 }
878
1a9f7075
PP
879 count = bt_ctf_trace_get_clock_class_count(
880 ctf_fs_trace->metadata->trace);
599faa1c
PP
881 assert(count >= 0);
882
883 for (i = 0; i < count; i++) {
884 struct bt_ctf_clock_class *clock_class =
9ac68eb1 885 bt_ctf_trace_get_clock_class_by_index(
1a9f7075 886 ctf_fs_trace->metadata->trace, i);
599faa1c
PP
887
888 assert(clock_class);
889 ret = bt_clock_class_priority_map_add_clock_class(
1a9f7075 890 ctf_fs_trace->cc_prio_map, clock_class, 0);
599faa1c
PP
891 BT_PUT(clock_class);
892
893 if (ret) {
894 goto end;
895 }
896 }
897
898end:
899 return ret;
900}
901
97ade20b 902BT_HIDDEN
55314f2a
JG
903struct ctf_fs_trace *ctf_fs_trace_create(const char *path, const char *name,
904 struct metadata_overrides *overrides)
1a9f7075
PP
905{
906 struct ctf_fs_trace *ctf_fs_trace;
907 int ret;
908
909 ctf_fs_trace = g_new0(struct ctf_fs_trace, 1);
910 if (!ctf_fs_trace) {
911 goto end;
912 }
913
1a9f7075
PP
914 ctf_fs_trace->path = g_string_new(path);
915 if (!ctf_fs_trace->path) {
916 goto error;
917 }
918
919 ctf_fs_trace->name = g_string_new(name);
920 if (!ctf_fs_trace->name) {
921 goto error;
922 }
923
924 ctf_fs_trace->metadata = g_new0(struct ctf_fs_metadata, 1);
925 if (!ctf_fs_trace->metadata) {
926 goto error;
927 }
928
94cf822e
PP
929 ctf_fs_trace->ds_file_groups = g_ptr_array_new_with_free_func(
930 (GDestroyNotify) ctf_fs_ds_file_group_destroy);
931 if (!ctf_fs_trace->ds_file_groups) {
932 goto error;
933 }
934
55314f2a 935 ret = ctf_fs_metadata_set_trace(ctf_fs_trace, overrides);
1a9f7075
PP
936 if (ret) {
937 goto error;
938 }
939
94cf822e
PP
940 ret = create_ds_file_groups(ctf_fs_trace);
941 if (ret) {
942 goto error;
943 }
944
1a9f7075
PP
945 ret = create_cc_prio_map(ctf_fs_trace);
946 if (ret) {
947 goto error;
948 }
949
27d1a78b
PP
950 /*
951 * create_ds_file_groups() created all the streams that this
952 * trace needs. There won't be any more. Therefore it is safe to
953 * make this trace static.
954 */
955 (void) bt_ctf_trace_set_is_static(ctf_fs_trace->metadata->trace);
956
1a9f7075
PP
957 goto end;
958
959error:
960 ctf_fs_trace_destroy(ctf_fs_trace);
961 ctf_fs_trace = NULL;
962end:
963 return ctf_fs_trace;
964}
965
966static
967int path_is_ctf_trace(const char *path)
968{
969 GString *metadata_path = g_string_new(NULL);
970 int ret = 0;
971
972 if (!metadata_path) {
973 ret = -1;
974 goto end;
975 }
976
977 g_string_printf(metadata_path, "%s/%s", path, CTF_FS_METADATA_FILENAME);
978
979 if (g_file_test(metadata_path->str, G_FILE_TEST_IS_REGULAR)) {
980 ret = 1;
981 goto end;
982 }
983
984end:
985 g_string_free(metadata_path, TRUE);
986 return ret;
987}
988
989static
55314f2a 990int add_trace_path(GList **trace_paths, const char *path)
1a9f7075 991{
4bd72b60 992 GString *norm_path = NULL;
1a9f7075 993 int ret = 0;
1a9f7075 994
4bd72b60
PP
995 norm_path = bt_common_normalize_path(path, NULL);
996 if (!norm_path) {
55314f2a 997 BT_LOGE("Failed to normalize path `%s`.", path);
1a9f7075
PP
998 ret = -1;
999 goto end;
1000 }
1001
4bd72b60 1002 if (strcmp(norm_path->str, "/") == 0) {
55314f2a 1003 BT_LOGE("Opening a trace in `/` is not supported.");
1a9f7075
PP
1004 ret = -1;
1005 goto end;
1006 }
1007
4bd72b60 1008 *trace_paths = g_list_prepend(*trace_paths, norm_path);
1a9f7075 1009 assert(*trace_paths);
4bd72b60 1010 norm_path = NULL;
1a9f7075
PP
1011
1012end:
4bd72b60
PP
1013 if (norm_path) {
1014 g_string_free(norm_path, TRUE);
1015 }
1016
1a9f7075
PP
1017 return ret;
1018}
1019
55314f2a
JG
1020BT_HIDDEN
1021int ctf_fs_find_traces(GList **trace_paths, const char *start_path)
1a9f7075
PP
1022{
1023 int ret;
1024 GError *error = NULL;
1025 GDir *dir = NULL;
1026 const char *basename = NULL;
1027
1028 /* Check if the starting path is a CTF trace itself */
1029 ret = path_is_ctf_trace(start_path);
1030 if (ret < 0) {
1031 goto end;
1032 }
1033
1034 if (ret) {
1035 /*
4bd72b60
PP
1036 * Stop recursion: a CTF trace cannot contain another
1037 * CTF trace.
1a9f7075 1038 */
55314f2a 1039 ret = add_trace_path(trace_paths, start_path);
1a9f7075
PP
1040 goto end;
1041 }
1042
1043 /* Look for subdirectories */
1044 if (!g_file_test(start_path, G_FILE_TEST_IS_DIR)) {
1045 /* Starting path is not a directory: end of recursion */
1046 goto end;
1047 }
1048
1049 dir = g_dir_open(start_path, 0, &error);
1050 if (!dir) {
1051 if (error->code == G_FILE_ERROR_ACCES) {
55314f2a 1052 BT_LOGD("Cannot open directory `%s`: %s (code %d): continuing",
1a9f7075
PP
1053 start_path, error->message, error->code);
1054 goto end;
1055 }
1056
55314f2a 1057 BT_LOGE("Cannot open directory `%s`: %s (code %d)",
1a9f7075
PP
1058 start_path, error->message, error->code);
1059 ret = -1;
1060 goto end;
1061 }
1062
1063 while ((basename = g_dir_read_name(dir))) {
1064 GString *sub_path = g_string_new(NULL);
1065
1066 if (!sub_path) {
1067 ret = -1;
1068 goto end;
1069 }
1070
1071 g_string_printf(sub_path, "%s/%s", start_path, basename);
55314f2a 1072 ret = ctf_fs_find_traces(trace_paths, sub_path->str);
1a9f7075
PP
1073 g_string_free(sub_path, TRUE);
1074 if (ret) {
1075 goto end;
1076 }
1077 }
1078
1079end:
1080 if (dir) {
1081 g_dir_close(dir);
1082 }
1083
1084 if (error) {
1085 g_error_free(error);
1086 }
1087
1088 return ret;
1089}
1090
55314f2a
JG
1091BT_HIDDEN
1092GList *ctf_fs_create_trace_names(GList *trace_paths, const char *base_path) {
1a9f7075 1093 GList *trace_names = NULL;
1a9f7075 1094 GList *node;
4bd72b60
PP
1095 const char *last_sep;
1096 size_t base_dist;
1a9f7075
PP
1097
1098 /*
4bd72b60
PP
1099 * At this point we know that all the trace paths are
1100 * normalized, and so is the base path. This means that
1101 * they are absolute and they don't end with a separator.
1102 * We can simply find the location of the last separator
1103 * in the base path, which gives us the name of the actual
1104 * directory to look into, and use this location as the
1105 * start of each trace name within each trace path.
1106 *
1107 * For example:
1108 *
1109 * Base path: /home/user/my-traces/some-trace
1110 * Trace paths:
1111 * - /home/user/my-traces/some-trace/host1/trace1
1112 * - /home/user/my-traces/some-trace/host1/trace2
1113 * - /home/user/my-traces/some-trace/host2/trace
1114 * - /home/user/my-traces/some-trace/other-trace
1115 *
1116 * In this case the trace names are:
1117 *
1118 * - some-trace/host1/trace1
1119 * - some-trace/host1/trace2
1120 * - some-trace/host2/trace
1121 * - some-trace/other-trace
1a9f7075 1122 */
4bd72b60 1123 last_sep = strrchr(base_path, G_DIR_SEPARATOR);
1a9f7075 1124
4bd72b60
PP
1125 /* We know there's at least one separator */
1126 assert(last_sep);
1a9f7075 1127
4bd72b60
PP
1128 /* Distance to base */
1129 base_dist = last_sep - base_path + 1;
1a9f7075
PP
1130
1131 /* Create the trace names */
1132 for (node = trace_paths; node; node = g_list_next(node)) {
1133 GString *trace_name = g_string_new(NULL);
1134 GString *trace_path = node->data;
1135
4bd72b60
PP
1136 assert(trace_name);
1137 g_string_assign(trace_name, &trace_path->str[base_dist]);
1a9f7075
PP
1138 trace_names = g_list_append(trace_names, trace_name);
1139 }
1140
1141 return trace_names;
1142}
1143
1144static
1145int create_ctf_fs_traces(struct ctf_fs_component *ctf_fs,
1146 const char *path_param)
1147{
1148 struct ctf_fs_trace *ctf_fs_trace = NULL;
1149 int ret = 0;
4bd72b60 1150 GString *norm_path = NULL;
1a9f7075
PP
1151 GList *trace_paths = NULL;
1152 GList *trace_names = NULL;
1153 GList *tp_node;
1154 GList *tn_node;
55314f2a
JG
1155 struct metadata_overrides metadata_overrides = {
1156 .clock_offset_s = ctf_fs->options.clock_offset,
1157 .clock_offset_ns = ctf_fs->options.clock_offset_ns,
1158 };
1a9f7075 1159
4bd72b60
PP
1160 norm_path = bt_common_normalize_path(path_param, NULL);
1161 if (!norm_path) {
55314f2a 1162 BT_LOGE("Failed to normalize path: `%s`.",
4bd72b60
PP
1163 path_param);
1164 goto error;
1165 }
1166
55314f2a 1167 ret = ctf_fs_find_traces(&trace_paths, norm_path->str);
1a9f7075
PP
1168 if (ret) {
1169 goto error;
1170 }
1171
1172 if (!trace_paths) {
55314f2a 1173 BT_LOGE("No CTF traces recursively found in `%s`.",
1a9f7075
PP
1174 path_param);
1175 goto error;
1176 }
1177
55314f2a 1178 trace_names = ctf_fs_create_trace_names(trace_paths, norm_path->str);
1a9f7075 1179 if (!trace_names) {
55314f2a 1180 BT_LOGE("Cannot create trace names from trace paths.");
1a9f7075
PP
1181 goto error;
1182 }
1183
1184 for (tp_node = trace_paths, tn_node = trace_names; tp_node;
1185 tp_node = g_list_next(tp_node),
1186 tn_node = g_list_next(tn_node)) {
1187 GString *trace_path = tp_node->data;
1188 GString *trace_name = tn_node->data;
1189
55314f2a
JG
1190 ctf_fs_trace = ctf_fs_trace_create(trace_path->str,
1191 trace_name->str, &metadata_overrides);
1a9f7075 1192 if (!ctf_fs_trace) {
55314f2a 1193 BT_LOGE("Cannot create trace for `%s`.",
1a9f7075
PP
1194 trace_path->str);
1195 goto error;
1196 }
52c5fe74 1197
55314f2a
JG
1198 ret = create_ports_for_trace(ctf_fs, ctf_fs_trace);
1199 if (ret) {
1200 goto error;
1201 }
1202
52c5fe74
PP
1203 g_ptr_array_add(ctf_fs->traces, ctf_fs_trace);
1204 ctf_fs_trace = NULL;
1a9f7075
PP
1205 }
1206
1a9f7075
PP
1207 goto end;
1208
1209error:
1210 ret = -1;
1211 ctf_fs_trace_destroy(ctf_fs_trace);
1212
1213end:
1214 for (tp_node = trace_paths; tp_node; tp_node = g_list_next(tp_node)) {
1215 if (tp_node->data) {
1216 g_string_free(tp_node->data, TRUE);
1217 }
1218 }
1219
1220 for (tn_node = trace_names; tn_node; tn_node = g_list_next(tn_node)) {
1221 if (tn_node->data) {
1222 g_string_free(tn_node->data, TRUE);
1223 }
1224 }
1225
1226 if (trace_paths) {
1227 g_list_free(trace_paths);
1228 }
1229
1230 if (trace_names) {
1231 g_list_free(trace_names);
1232 }
1233
4bd72b60
PP
1234 if (norm_path) {
1235 g_string_free(norm_path, TRUE);
1236 }
1237
1a9f7075
PP
1238 return ret;
1239}
1240
5b29e799 1241static
4f1f88a6
PP
1242struct ctf_fs_component *ctf_fs_create(struct bt_private_component *priv_comp,
1243 struct bt_value *params)
56a1cced
JG
1244{
1245 struct ctf_fs_component *ctf_fs;
1ef09eb5 1246 struct bt_value *value = NULL;
1a9f7075 1247 const char *path_param;
4f1f88a6 1248 int ret;
56a1cced
JG
1249
1250 ctf_fs = g_new0(struct ctf_fs_component, 1);
1251 if (!ctf_fs) {
1252 goto end;
1253 }
1254
1a9f7075
PP
1255 ret = bt_private_component_set_user_data(priv_comp, ctf_fs);
1256 assert(ret == 0);
1257
4f1f88a6
PP
1258 /*
1259 * We don't need to get a new reference here because as long as
1260 * our private ctf_fs_component object exists, the containing
1261 * private component should also exist.
1262 */
1263 ctf_fs->priv_comp = priv_comp;
56a1cced 1264 value = bt_value_map_get(params, "path");
1a9f7075 1265 if (!bt_value_is_string(value)) {
56a1cced
JG
1266 goto error;
1267 }
1268
1a9f7075
PP
1269 ret = bt_value_string_get(value, &path_param);
1270 assert(ret == 0);
1271 BT_PUT(value);
92540773
JD
1272 value = bt_value_map_get(params, "offset-s");
1273 if (value) {
1274 int64_t offset;
1275
1276 if (!bt_value_is_integer(value)) {
55314f2a 1277 BT_LOGE("offset-s should be an integer");
92540773
JD
1278 goto error;
1279 }
1280 ret = bt_value_integer_get(value, &offset);
1a9f7075 1281 assert(ret == 0);
92540773 1282 ctf_fs->options.clock_offset = offset;
1a9f7075 1283 BT_PUT(value);
92540773
JD
1284 }
1285
1286 value = bt_value_map_get(params, "offset-ns");
1287 if (value) {
1288 int64_t offset;
1289
1290 if (!bt_value_is_integer(value)) {
55314f2a 1291 BT_LOGE("offset-ns should be an integer");
92540773
JD
1292 goto error;
1293 }
1294 ret = bt_value_integer_get(value, &offset);
1a9f7075 1295 assert(ret == 0);
92540773 1296 ctf_fs->options.clock_offset_ns = offset;
1a9f7075 1297 BT_PUT(value);
92540773
JD
1298 }
1299
1a9f7075
PP
1300 ctf_fs->port_data = g_ptr_array_new_with_free_func(port_data_destroy);
1301 if (!ctf_fs->port_data) {
4f1f88a6
PP
1302 goto error;
1303 }
1304
97ade20b
JG
1305 ctf_fs->traces = g_ptr_array_new_with_free_func(
1306 ctf_fs_trace_destroy_notifier);
1a9f7075 1307 if (!ctf_fs->traces) {
599faa1c
PP
1308 goto error;
1309 }
1310
1a9f7075 1311 ret = create_ctf_fs_traces(ctf_fs, path_param);
4f1f88a6
PP
1312 if (ret) {
1313 goto error;
1314 }
1315
1ef09eb5
JG
1316 goto end;
1317
56a1cced 1318error:
1a9f7075 1319 ctf_fs_destroy(ctf_fs);
e7a4393b 1320 ctf_fs = NULL;
1a9f7075
PP
1321 ret = bt_private_component_set_user_data(priv_comp, NULL);
1322 assert(ret == 0);
1323
1ef09eb5 1324end:
1a9f7075 1325 bt_put(value);
56a1cced
JG
1326 return ctf_fs;
1327}
1328
ea0b4b9e 1329BT_HIDDEN
4f1f88a6 1330enum bt_component_status ctf_fs_init(struct bt_private_component *priv_comp,
7d61fa8e 1331 struct bt_value *params, UNUSED_VAR void *init_method_data)
ea0b4b9e
JG
1332{
1333 struct ctf_fs_component *ctf_fs;
1334 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1335
ea0b4b9e 1336 ctf_fs_debug = g_strcmp0(getenv("CTF_FS_DEBUG"), "1") == 0;
4f1f88a6 1337 ctf_fs = ctf_fs_create(priv_comp, params);
ea0b4b9e 1338 if (!ctf_fs) {
1a9f7075 1339 ret = BT_COMPONENT_STATUS_ERROR;
ea0b4b9e 1340 }
4c1456f0 1341
ea0b4b9e
JG
1342 return ret;
1343}
33f93973
PP
1344
1345BT_HIDDEN
a67681c1
PP
1346struct bt_value *ctf_fs_query(struct bt_component_class *comp_class,
1347 const char *object, struct bt_value *params)
33f93973 1348{
04c0ba87 1349 struct bt_value *result = NULL;
33f93973 1350
04c0ba87
JG
1351 if (!strcmp(object, "metadata-info")) {
1352 result = metadata_info_query(comp_class, params);
97ade20b
JG
1353 } else if (!strcmp(object, "trace-info")) {
1354 result = trace_info_query(comp_class, params);
33f93973 1355 } else {
55314f2a 1356 BT_LOGE("Unknown query object `%s`", object);
04c0ba87 1357 goto end;
33f93973 1358 }
33f93973 1359end:
04c0ba87 1360 return result;
33f93973 1361}
This page took 0.093618 seconds and 4 git commands to generate.