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