Split notification iterator API into base and specialized functions
[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 35#include <babeltrace/graph/private-component-source.h>
90157d89 36#include <babeltrace/graph/private-connection-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"
6de92955 50#include "../common/notif-iter/notif-iter.h"
a429c321 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,
6de92955 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);
6de92955
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
90157d89
PP
99struct bt_notification_iterator_next_method_return ctf_fs_iterator_next(
100 struct bt_private_connection_private_notification_iterator *iterator)
ea0b4b9e 101{
90157d89 102 struct bt_notification_iterator_next_method_return next_ret;
94cf822e 103 struct ctf_fs_notif_iter_data *notif_iter_data =
90157d89 104 bt_private_connection_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
90157d89 149void ctf_fs_iterator_finalize(struct bt_private_connection_private_notification_iterator *it)
760051fa 150{
94cf822e 151 void *notif_iter_data =
90157d89 152 bt_private_connection_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 157enum bt_notification_iterator_status ctf_fs_iterator_init(
90157d89 158 struct bt_private_connection_private_notification_iterator *it,
4f1f88a6 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
6de92955
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
90157d89 196 ret = bt_private_connection_private_notification_iterator_set_user_data(it, notif_iter_data);
7401e2d1 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 204error:
90157d89 205 (void) bt_private_connection_private_notification_iterator_set_user_data(it, NULL);
4f1f88a6 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
547eacf1
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
547eacf1 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
05afcecd 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);
547eacf1 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
547eacf1
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
8bf7105e
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
8bf7105e 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;
6de92955 629 struct ctf_fs_ds_file *ds_file = NULL;
97ade20b 630 struct ctf_fs_ds_index *index = NULL;
6de92955 631 struct bt_ctf_notif_iter *notif_iter = NULL;
94cf822e 632
6de92955
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);
a429c321
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,
547eacf1 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
547eacf1
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
547eacf1
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 }
547eacf1 748
97ade20b 749 ctf_fs_ds_file_destroy(ds_file);
6de92955
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;
547eacf1 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. */
3743a302 785 BT_LOGD("Ignoring metadata file `%s" G_DIR_SEPARATOR_S "%s`",
1a9f7075 786 ctf_fs_trace->path->str, basename);
e7a4393b
JG
787 continue;
788 }
789
4f1f88a6 790 if (basename[0] == '.') {
3743a302 791 BT_LOGD("Ignoring hidden file `%s" G_DIR_SEPARATOR_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) {
3743a302 799 BT_LOGE("Cannot create stream file object for file `%s" G_DIR_SEPARATOR_S "%s`",
1a9f7075 800 ctf_fs_trace->path->str, basename);
e7a4393b
JG
801 goto error;
802 }
803
804 /* Create full path string. */
3743a302 805 g_string_append_printf(file->path, "%s" G_DIR_SEPARATOR_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
547eacf1
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
7742909c 869 if (!ds_file_group->stream) {
547eacf1
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,
a2a54545 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
a2a54545 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
3743a302 1007 g_string_printf(metadata_path, "%s" G_DIR_SEPARATOR_S "%s", path, CTF_FS_METADATA_FILENAME);
1a9f7075
PP
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
3743a302 1032 // FIXME: Remove or ifdef for __MINGW32__
4bd72b60 1033 if (strcmp(norm_path->str, "/") == 0) {
55314f2a 1034 BT_LOGE("Opening a trace in `/` is not supported.");
1a9f7075
PP
1035 ret = -1;
1036 goto end;
1037 }
1038
4bd72b60 1039 *trace_paths = g_list_prepend(*trace_paths, norm_path);
1a9f7075 1040 assert(*trace_paths);
4bd72b60 1041 norm_path = NULL;
1a9f7075
PP
1042
1043end:
4bd72b60
PP
1044 if (norm_path) {
1045 g_string_free(norm_path, TRUE);
1046 }
1047
1a9f7075
PP
1048 return ret;
1049}
1050
55314f2a
JG
1051BT_HIDDEN
1052int ctf_fs_find_traces(GList **trace_paths, const char *start_path)
1a9f7075
PP
1053{
1054 int ret;
1055 GError *error = NULL;
1056 GDir *dir = NULL;
1057 const char *basename = NULL;
1058
1059 /* Check if the starting path is a CTF trace itself */
1060 ret = path_is_ctf_trace(start_path);
1061 if (ret < 0) {
1062 goto end;
1063 }
1064
1065 if (ret) {
1066 /*
4bd72b60
PP
1067 * Stop recursion: a CTF trace cannot contain another
1068 * CTF trace.
1a9f7075 1069 */
55314f2a 1070 ret = add_trace_path(trace_paths, start_path);
1a9f7075
PP
1071 goto end;
1072 }
1073
1074 /* Look for subdirectories */
1075 if (!g_file_test(start_path, G_FILE_TEST_IS_DIR)) {
1076 /* Starting path is not a directory: end of recursion */
1077 goto end;
1078 }
1079
1080 dir = g_dir_open(start_path, 0, &error);
1081 if (!dir) {
1082 if (error->code == G_FILE_ERROR_ACCES) {
55314f2a 1083 BT_LOGD("Cannot open directory `%s`: %s (code %d): continuing",
1a9f7075
PP
1084 start_path, error->message, error->code);
1085 goto end;
1086 }
1087
55314f2a 1088 BT_LOGE("Cannot open directory `%s`: %s (code %d)",
1a9f7075
PP
1089 start_path, error->message, error->code);
1090 ret = -1;
1091 goto end;
1092 }
1093
1094 while ((basename = g_dir_read_name(dir))) {
1095 GString *sub_path = g_string_new(NULL);
1096
1097 if (!sub_path) {
1098 ret = -1;
1099 goto end;
1100 }
1101
3743a302 1102 g_string_printf(sub_path, "%s" G_DIR_SEPARATOR_S "%s", start_path, basename);
55314f2a 1103 ret = ctf_fs_find_traces(trace_paths, sub_path->str);
1a9f7075
PP
1104 g_string_free(sub_path, TRUE);
1105 if (ret) {
1106 goto end;
1107 }
1108 }
1109
1110end:
1111 if (dir) {
1112 g_dir_close(dir);
1113 }
1114
1115 if (error) {
1116 g_error_free(error);
1117 }
1118
1119 return ret;
1120}
1121
55314f2a
JG
1122BT_HIDDEN
1123GList *ctf_fs_create_trace_names(GList *trace_paths, const char *base_path) {
1a9f7075 1124 GList *trace_names = NULL;
1a9f7075 1125 GList *node;
4bd72b60
PP
1126 const char *last_sep;
1127 size_t base_dist;
1a9f7075
PP
1128
1129 /*
4bd72b60
PP
1130 * At this point we know that all the trace paths are
1131 * normalized, and so is the base path. This means that
1132 * they are absolute and they don't end with a separator.
1133 * We can simply find the location of the last separator
1134 * in the base path, which gives us the name of the actual
1135 * directory to look into, and use this location as the
1136 * start of each trace name within each trace path.
1137 *
1138 * For example:
1139 *
1140 * Base path: /home/user/my-traces/some-trace
1141 * Trace paths:
1142 * - /home/user/my-traces/some-trace/host1/trace1
1143 * - /home/user/my-traces/some-trace/host1/trace2
1144 * - /home/user/my-traces/some-trace/host2/trace
1145 * - /home/user/my-traces/some-trace/other-trace
1146 *
1147 * In this case the trace names are:
1148 *
1149 * - some-trace/host1/trace1
1150 * - some-trace/host1/trace2
1151 * - some-trace/host2/trace
1152 * - some-trace/other-trace
1a9f7075 1153 */
4bd72b60 1154 last_sep = strrchr(base_path, G_DIR_SEPARATOR);
1a9f7075 1155
4bd72b60
PP
1156 /* We know there's at least one separator */
1157 assert(last_sep);
1a9f7075 1158
4bd72b60
PP
1159 /* Distance to base */
1160 base_dist = last_sep - base_path + 1;
1a9f7075
PP
1161
1162 /* Create the trace names */
1163 for (node = trace_paths; node; node = g_list_next(node)) {
1164 GString *trace_name = g_string_new(NULL);
1165 GString *trace_path = node->data;
1166
4bd72b60
PP
1167 assert(trace_name);
1168 g_string_assign(trace_name, &trace_path->str[base_dist]);
1a9f7075
PP
1169 trace_names = g_list_append(trace_names, trace_name);
1170 }
1171
1172 return trace_names;
1173}
1174
1175static
1176int create_ctf_fs_traces(struct ctf_fs_component *ctf_fs,
1177 const char *path_param)
1178{
1179 struct ctf_fs_trace *ctf_fs_trace = NULL;
1180 int ret = 0;
4bd72b60 1181 GString *norm_path = NULL;
1a9f7075
PP
1182 GList *trace_paths = NULL;
1183 GList *trace_names = NULL;
1184 GList *tp_node;
1185 GList *tn_node;
1186
4bd72b60
PP
1187 norm_path = bt_common_normalize_path(path_param, NULL);
1188 if (!norm_path) {
55314f2a 1189 BT_LOGE("Failed to normalize path: `%s`.",
4bd72b60
PP
1190 path_param);
1191 goto error;
1192 }
1193
55314f2a 1194 ret = ctf_fs_find_traces(&trace_paths, norm_path->str);
1a9f7075
PP
1195 if (ret) {
1196 goto error;
1197 }
1198
1199 if (!trace_paths) {
55314f2a 1200 BT_LOGE("No CTF traces recursively found in `%s`.",
1a9f7075
PP
1201 path_param);
1202 goto error;
1203 }
1204
55314f2a 1205 trace_names = ctf_fs_create_trace_names(trace_paths, norm_path->str);
1a9f7075 1206 if (!trace_names) {
55314f2a 1207 BT_LOGE("Cannot create trace names from trace paths.");
1a9f7075
PP
1208 goto error;
1209 }
1210
1211 for (tp_node = trace_paths, tn_node = trace_names; tp_node;
1212 tp_node = g_list_next(tp_node),
1213 tn_node = g_list_next(tn_node)) {
1214 GString *trace_path = tp_node->data;
1215 GString *trace_name = tn_node->data;
1216
55314f2a 1217 ctf_fs_trace = ctf_fs_trace_create(trace_path->str,
a2a54545 1218 trace_name->str, &ctf_fs->metadata_config);
1a9f7075 1219 if (!ctf_fs_trace) {
55314f2a 1220 BT_LOGE("Cannot create trace for `%s`.",
1a9f7075
PP
1221 trace_path->str);
1222 goto error;
1223 }
52c5fe74 1224
55314f2a
JG
1225 ret = create_ports_for_trace(ctf_fs, ctf_fs_trace);
1226 if (ret) {
1227 goto error;
1228 }
1229
52c5fe74
PP
1230 g_ptr_array_add(ctf_fs->traces, ctf_fs_trace);
1231 ctf_fs_trace = NULL;
1a9f7075
PP
1232 }
1233
1a9f7075
PP
1234 goto end;
1235
1236error:
1237 ret = -1;
1238 ctf_fs_trace_destroy(ctf_fs_trace);
1239
1240end:
1241 for (tp_node = trace_paths; tp_node; tp_node = g_list_next(tp_node)) {
1242 if (tp_node->data) {
1243 g_string_free(tp_node->data, TRUE);
1244 }
1245 }
1246
1247 for (tn_node = trace_names; tn_node; tn_node = g_list_next(tn_node)) {
1248 if (tn_node->data) {
1249 g_string_free(tn_node->data, TRUE);
1250 }
1251 }
1252
1253 if (trace_paths) {
1254 g_list_free(trace_paths);
1255 }
1256
1257 if (trace_names) {
1258 g_list_free(trace_names);
1259 }
1260
4bd72b60
PP
1261 if (norm_path) {
1262 g_string_free(norm_path, TRUE);
1263 }
1264
1a9f7075
PP
1265 return ret;
1266}
1267
5b29e799 1268static
4f1f88a6
PP
1269struct ctf_fs_component *ctf_fs_create(struct bt_private_component *priv_comp,
1270 struct bt_value *params)
56a1cced
JG
1271{
1272 struct ctf_fs_component *ctf_fs;
1ef09eb5 1273 struct bt_value *value = NULL;
1a9f7075 1274 const char *path_param;
3faba6d4
MD
1275 enum bt_component_status ret;
1276 enum bt_value_status value_ret;
56a1cced
JG
1277
1278 ctf_fs = g_new0(struct ctf_fs_component, 1);
1279 if (!ctf_fs) {
1280 goto end;
1281 }
1282
1a9f7075 1283 ret = bt_private_component_set_user_data(priv_comp, ctf_fs);
3faba6d4 1284 assert(ret == BT_COMPONENT_STATUS_OK);
1a9f7075 1285
4f1f88a6
PP
1286 /*
1287 * We don't need to get a new reference here because as long as
1288 * our private ctf_fs_component object exists, the containing
1289 * private component should also exist.
1290 */
1291 ctf_fs->priv_comp = priv_comp;
56a1cced 1292 value = bt_value_map_get(params, "path");
1a9f7075 1293 if (!bt_value_is_string(value)) {
56a1cced
JG
1294 goto error;
1295 }
1296
3faba6d4
MD
1297 value_ret = bt_value_string_get(value, &path_param);
1298 assert(value_ret == BT_VALUE_STATUS_OK);
1a9f7075 1299 BT_PUT(value);
a2a54545 1300 value = bt_value_map_get(params, "clock-class-offset-s");
92540773 1301 if (value) {
a2a54545
PP
1302 if (!bt_value_is_integer(value)) {
1303 BT_LOGE("clock-class-offset-s should be an integer");
1304 goto error;
1305 }
3faba6d4 1306 value_ret = bt_value_integer_get(value,
a2a54545 1307 &ctf_fs->metadata_config.clock_class_offset_s);
3faba6d4 1308 assert(value_ret == BT_VALUE_STATUS_OK);
a2a54545
PP
1309 BT_PUT(value);
1310 }
92540773 1311
a2a54545
PP
1312 value = bt_value_map_get(params, "clock-class-offset-ns");
1313 if (value) {
92540773 1314 if (!bt_value_is_integer(value)) {
a2a54545 1315 BT_LOGE("clock-class-offset-ns should be an integer");
92540773
JD
1316 goto error;
1317 }
3faba6d4 1318 value_ret = bt_value_integer_get(value,
a2a54545 1319 &ctf_fs->metadata_config.clock_class_offset_ns);
3faba6d4 1320 assert(value_ret == BT_VALUE_STATUS_OK);
1a9f7075 1321 BT_PUT(value);
92540773
JD
1322 }
1323
1a9f7075
PP
1324 ctf_fs->port_data = g_ptr_array_new_with_free_func(port_data_destroy);
1325 if (!ctf_fs->port_data) {
4f1f88a6
PP
1326 goto error;
1327 }
1328
97ade20b
JG
1329 ctf_fs->traces = g_ptr_array_new_with_free_func(
1330 ctf_fs_trace_destroy_notifier);
1a9f7075 1331 if (!ctf_fs->traces) {
599faa1c
PP
1332 goto error;
1333 }
1334
3faba6d4 1335 if (create_ctf_fs_traces(ctf_fs, path_param)) {
4f1f88a6
PP
1336 goto error;
1337 }
1338
1ef09eb5
JG
1339 goto end;
1340
56a1cced 1341error:
1a9f7075 1342 ctf_fs_destroy(ctf_fs);
e7a4393b 1343 ctf_fs = NULL;
1a9f7075 1344 ret = bt_private_component_set_user_data(priv_comp, NULL);
3faba6d4 1345 assert(ret == BT_COMPONENT_STATUS_OK);
1a9f7075 1346
1ef09eb5 1347end:
1a9f7075 1348 bt_put(value);
56a1cced
JG
1349 return ctf_fs;
1350}
1351
ea0b4b9e 1352BT_HIDDEN
4f1f88a6 1353enum bt_component_status ctf_fs_init(struct bt_private_component *priv_comp,
7d61fa8e 1354 struct bt_value *params, UNUSED_VAR void *init_method_data)
ea0b4b9e
JG
1355{
1356 struct ctf_fs_component *ctf_fs;
1357 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1358
4f1f88a6 1359 ctf_fs = ctf_fs_create(priv_comp, params);
ea0b4b9e 1360 if (!ctf_fs) {
1a9f7075 1361 ret = BT_COMPONENT_STATUS_ERROR;
ea0b4b9e 1362 }
4c1456f0 1363
ea0b4b9e
JG
1364 return ret;
1365}
33f93973
PP
1366
1367BT_HIDDEN
90157d89 1368struct bt_component_class_query_method_return ctf_fs_query(
c7eee084
PP
1369 struct bt_component_class *comp_class,
1370 struct bt_query_executor *query_exec,
a67681c1 1371 const char *object, struct bt_value *params)
33f93973 1372{
90157d89 1373 struct bt_component_class_query_method_return ret = {
c7eee084
PP
1374 .result = NULL,
1375 .status = BT_QUERY_STATUS_OK,
1376 };
33f93973 1377
04c0ba87 1378 if (!strcmp(object, "metadata-info")) {
c7eee084 1379 ret = metadata_info_query(comp_class, params);
97ade20b 1380 } else if (!strcmp(object, "trace-info")) {
c7eee084 1381 ret = trace_info_query(comp_class, params);
33f93973 1382 } else {
55314f2a 1383 BT_LOGE("Unknown query object `%s`", object);
c7eee084 1384 ret.status = BT_QUERY_STATUS_INVALID_OBJECT;
04c0ba87 1385 goto end;
33f93973 1386 }
33f93973 1387end:
c7eee084 1388 return ret;
33f93973 1389}
This page took 0.139843 seconds and 4 git commands to generate.