ctf plugin: add bt_ctf_notif_iter_get_packet_header_context_fields()
[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
5b29e799 28#include <babeltrace/ctf-ir/packet.h>
ac0c6bdd 29#include <babeltrace/ctf-ir/clock-class.h>
4f1f88a6 30#include <babeltrace/graph/private-port.h>
b2e0c907 31#include <babeltrace/graph/private-component.h>
4f1f88a6
PP
32#include <babeltrace/graph/private-component-source.h>
33#include <babeltrace/graph/private-notification-iterator.h>
b2e0c907
PP
34#include <babeltrace/graph/component.h>
35#include <babeltrace/graph/notification-iterator.h>
599faa1c 36#include <babeltrace/graph/clock-class-priority-map.h>
7d61fa8e 37#include <plugins-common.h>
ea0b4b9e
JG
38#include <glib.h>
39#include <assert.h>
c55a9f58 40#include <stdbool.h>
56a1cced
JG
41#include <unistd.h>
42#include "fs.h"
413bc2c4
JG
43#include "metadata.h"
44#include "data-stream.h"
e7a4393b 45#include "file.h"
1e649dff 46#include "../common/metadata/decoder.h"
e7a4393b
JG
47
48#define PRINT_ERR_STREAM ctf_fs->error_fp
49#define PRINT_PREFIX "ctf-fs"
cd00e1d3
MD
50#define PRINT_DBG_CHECK ctf_fs_debug
51#include "../print.h"
33f93973 52#define METADATA_TEXT_SIG "/* CTF 1.8"
ea0b4b9e 53
78bb6992
MD
54BT_HIDDEN
55bool ctf_fs_debug;
ea0b4b9e 56
41a2b7ae 57struct bt_notification_iterator_next_return ctf_fs_iterator_next(
4f1f88a6 58 struct bt_private_notification_iterator *iterator)
ea0b4b9e 59{
4f1f88a6
PP
60 struct ctf_fs_stream *fs_stream =
61 bt_private_notification_iterator_get_user_data(iterator);
d01e0f33 62
4f1f88a6 63 return ctf_fs_stream_next(fs_stream);
ea0b4b9e 64}
bfd20a42 65
4f1f88a6 66void ctf_fs_iterator_finalize(struct bt_private_notification_iterator *it)
760051fa 67{
4f1f88a6
PP
68 void *ctf_fs_stream =
69 bt_private_notification_iterator_get_user_data(it);
760051fa 70
4f1f88a6 71 ctf_fs_stream_destroy(ctf_fs_stream);
760051fa
JG
72}
73
4f1f88a6
PP
74enum bt_notification_iterator_status ctf_fs_iterator_init(
75 struct bt_private_notification_iterator *it,
76 struct bt_private_port *port)
4c1456f0 77{
1a9f7075 78 struct ctf_fs_stream *ctf_fs_stream = NULL;
4f1f88a6 79 struct ctf_fs_port_data *port_data;
4f1f88a6
PP
80 enum bt_notification_iterator_status ret =
81 BT_NOTIFICATION_ITERATOR_STATUS_OK;
760051fa 82
4f1f88a6
PP
83 port_data = bt_private_port_get_user_data(port);
84 if (!port_data) {
fe8ad2b6 85 ret = BT_NOTIFICATION_ITERATOR_STATUS_INVALID;
4f1f88a6
PP
86 goto error;
87 }
5b29e799 88
1a9f7075
PP
89 ctf_fs_stream = ctf_fs_stream_create(port_data->ctf_fs_trace,
90 port_data->path->str);
91 if (!ctf_fs_stream) {
4f1f88a6 92 goto error;
760051fa
JG
93 }
94
1a9f7075 95 ret = bt_private_notification_iterator_set_user_data(it, ctf_fs_stream);
4f1f88a6
PP
96 if (ret) {
97 goto error;
760051fa
JG
98 }
99
1a9f7075 100 ctf_fs_stream = NULL;
4f1f88a6 101 goto end;
5b29e799 102
4f1f88a6
PP
103error:
104 (void) bt_private_notification_iterator_set_user_data(it, NULL);
105
106 if (ret == BT_NOTIFICATION_ITERATOR_STATUS_OK) {
107 ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
760051fa 108 }
5b29e799 109
760051fa 110end:
1a9f7075 111 ctf_fs_stream_destroy(ctf_fs_stream);
760051fa
JG
112 return ret;
113}
114
760051fa 115static
1a9f7075 116void ctf_fs_destroy(struct ctf_fs_component *ctf_fs)
760051fa 117{
4f1f88a6 118 if (!ctf_fs) {
8fa760ba
JG
119 return;
120 }
4f1f88a6 121
1a9f7075
PP
122 if (ctf_fs->traces) {
123 g_ptr_array_free(ctf_fs->traces, TRUE);
56a1cced 124 }
4f1f88a6
PP
125
126 if (ctf_fs->port_data) {
127 g_ptr_array_free(ctf_fs->port_data, TRUE);
c14d7e26 128 }
760051fa 129
1a9f7075
PP
130 g_free(ctf_fs);
131}
132
133static
134void ctf_fs_trace_destroy(void *data)
135{
136 struct ctf_fs_trace *ctf_fs_trace = data;
137
138 if (!ctf_fs_trace) {
139 return;
140 }
141
142 if (ctf_fs_trace->path) {
143 g_string_free(ctf_fs_trace->path, TRUE);
4f1f88a6 144 }
760051fa 145
1a9f7075
PP
146 if (ctf_fs_trace->name) {
147 g_string_free(ctf_fs_trace->name, TRUE);
148 }
149
150 if (ctf_fs_trace->metadata) {
151 ctf_fs_metadata_fini(ctf_fs_trace->metadata);
152 g_free(ctf_fs_trace->metadata);
153 }
154
155 bt_put(ctf_fs_trace->cc_prio_map);
156 g_free(ctf_fs_trace);
4c1456f0
JG
157}
158
4f1f88a6 159void ctf_fs_finalize(struct bt_private_component *component)
a4792757 160{
4f1f88a6
PP
161 void *data = bt_private_component_get_user_data(component);
162
1a9f7075 163 ctf_fs_destroy(data);
a4792757
JG
164}
165
e7a4393b 166static
4f1f88a6
PP
167void port_data_destroy(void *data) {
168 struct ctf_fs_port_data *port_data = data;
169
170 if (!port_data) {
171 return;
172 }
173
174 if (port_data->path) {
175 g_string_free(port_data->path, TRUE);
176 }
177
178 g_free(port_data);
5b29e799
JG
179}
180
181static
1a9f7075
PP
182int create_one_port_for_trace(struct ctf_fs_trace *ctf_fs_trace,
183 const char *stream_path)
5b29e799 184{
4f1f88a6
PP
185 int ret = 0;
186 struct bt_private_port *port = NULL;
187 struct ctf_fs_port_data *port_data = NULL;
188 GString *port_name = NULL;
1a9f7075 189 struct ctf_fs_component *ctf_fs = ctf_fs_trace->ctf_fs;
4f1f88a6
PP
190
191 port_name = g_string_new(NULL);
192 if (!port_name) {
193 goto error;
194 }
195
196 /* Assign the name for the new output port */
1a9f7075
PP
197 g_string_printf(port_name, "%s", stream_path);
198 PDBG("Creating one port named `%s`\n", port_name->str);
4f1f88a6
PP
199
200 /* Create output port for this file */
4f1f88a6
PP
201 port_data = g_new0(struct ctf_fs_port_data, 1);
202 if (!port_data) {
203 goto error;
204 }
205
1a9f7075 206 port_data->ctf_fs_trace = ctf_fs_trace;
4f1f88a6
PP
207 port_data->path = g_string_new(stream_path);
208 if (!port_data->path) {
209 goto error;
210 }
211
3e9b0023
PP
212 port = bt_private_component_source_add_output_private_port(
213 ctf_fs->priv_comp, port_name->str, port_data);
214 if (!port) {
4f1f88a6
PP
215 goto error;
216 }
217
218 g_ptr_array_add(ctf_fs->port_data, port_data);
219 port_data = NULL;
220 goto end;
221
222error:
223 ret = -1;
224
225end:
226 if (port_name) {
227 g_string_free(port_name, TRUE);
228 }
229
230 bt_put(port);
231 port_data_destroy(port_data);
232 return ret;
5b29e799
JG
233}
234
235static
1a9f7075 236int create_ports_for_trace(struct ctf_fs_trace *ctf_fs_trace)
e7a4393b
JG
237{
238 int ret = 0;
4f1f88a6 239 const char *basename;
e7a4393b 240 GError *error = NULL;
4f1f88a6 241 GDir *dir = NULL;
4f1f88a6 242 struct ctf_fs_file *file = NULL;
1a9f7075 243 struct ctf_fs_component *ctf_fs = ctf_fs_trace->ctf_fs;
e7a4393b 244
4f1f88a6 245 /* Create one output port for each stream file */
1a9f7075 246 dir = g_dir_open(ctf_fs_trace->path->str, 0, &error);
e7a4393b 247 if (!dir) {
4f1f88a6 248 PERR("Cannot open directory `%s`: %s (code %d)\n",
1a9f7075 249 ctf_fs_trace->path->str, error->message,
4f1f88a6 250 error->code);
e7a4393b
JG
251 goto error;
252 }
253
4f1f88a6
PP
254 while ((basename = g_dir_read_name(dir))) {
255 if (!strcmp(basename, CTF_FS_METADATA_FILENAME)) {
e7a4393b 256 /* Ignore the metadata stream. */
1a9f7075
PP
257 PDBG("Ignoring metadata file `%s/%s`\n",
258 ctf_fs_trace->path->str, basename);
e7a4393b
JG
259 continue;
260 }
261
4f1f88a6 262 if (basename[0] == '.') {
1a9f7075
PP
263 PDBG("Ignoring hidden file `%s/%s`\n",
264 ctf_fs_trace->path->str, basename);
e7a4393b
JG
265 continue;
266 }
267
268 /* Create the file. */
269 file = ctf_fs_file_create(ctf_fs);
270 if (!file) {
1a9f7075
PP
271 PERR("Cannot create stream file object for file `%s/%s`\n",
272 ctf_fs_trace->path->str, basename);
e7a4393b
JG
273 goto error;
274 }
275
276 /* Create full path string. */
277 g_string_append_printf(file->path, "%s/%s",
1a9f7075 278 ctf_fs_trace->path->str, basename);
e7a4393b 279 if (!g_file_test(file->path->str, G_FILE_TEST_IS_REGULAR)) {
1a9f7075
PP
280 PDBG("Ignoring non-regular file `%s`\n",
281 file->path->str);
e7a4393b 282 ctf_fs_file_destroy(file);
4f1f88a6 283 file = NULL;
e7a4393b
JG
284 continue;
285 }
286
4f1f88a6
PP
287 ret = ctf_fs_file_open(ctf_fs, file, "rb");
288 if (ret) {
1a9f7075 289 PERR("Cannot open stream file `%s`\n", file->path->str);
e7a4393b
JG
290 goto error;
291 }
292
9fa0891a
JG
293 if (file->size == 0) {
294 /* Skip empty stream. */
1a9f7075 295 PDBG("Ignoring empty file `%s`\n", file->path->str);
9fa0891a 296 ctf_fs_file_destroy(file);
4f1f88a6 297 file = NULL;
9fa0891a
JG
298 continue;
299 }
300
1a9f7075 301 ret = create_one_port_for_trace(ctf_fs_trace, file->path->str);
4f1f88a6
PP
302 if (ret) {
303 PERR("Cannot create output port for file `%s`\n",
1a9f7075 304 file->path->str);
e7a4393b
JG
305 goto error;
306 }
307
4f1f88a6
PP
308 ctf_fs_file_destroy(file);
309 file = NULL;
e7a4393b
JG
310 }
311
312 goto end;
4f1f88a6 313
e7a4393b
JG
314error:
315 ret = -1;
4f1f88a6 316
e7a4393b
JG
317end:
318 if (dir) {
319 g_dir_close(dir);
320 dir = NULL;
321 }
4f1f88a6 322
e7a4393b
JG
323 if (error) {
324 g_error_free(error);
325 }
5b29e799 326
4f1f88a6 327 ctf_fs_file_destroy(file);
91457551 328 return ret;
5b29e799
JG
329}
330
599faa1c 331static
1a9f7075 332int create_cc_prio_map(struct ctf_fs_trace *ctf_fs_trace)
599faa1c
PP
333{
334 int ret = 0;
335 size_t i;
336 int count;
337
1a9f7075
PP
338 assert(ctf_fs_trace);
339 ctf_fs_trace->cc_prio_map = bt_clock_class_priority_map_create();
340 if (!ctf_fs_trace->cc_prio_map) {
599faa1c
PP
341 ret = -1;
342 goto end;
343 }
344
1a9f7075
PP
345 count = bt_ctf_trace_get_clock_class_count(
346 ctf_fs_trace->metadata->trace);
599faa1c
PP
347 assert(count >= 0);
348
349 for (i = 0; i < count; i++) {
350 struct bt_ctf_clock_class *clock_class =
9ac68eb1 351 bt_ctf_trace_get_clock_class_by_index(
1a9f7075 352 ctf_fs_trace->metadata->trace, i);
599faa1c
PP
353
354 assert(clock_class);
355 ret = bt_clock_class_priority_map_add_clock_class(
1a9f7075 356 ctf_fs_trace->cc_prio_map, clock_class, 0);
599faa1c
PP
357 BT_PUT(clock_class);
358
359 if (ret) {
360 goto end;
361 }
362 }
363
364end:
365 return ret;
366}
367
1a9f7075
PP
368static
369struct ctf_fs_trace *ctf_fs_trace_create(struct ctf_fs_component *ctf_fs,
370 const char *path, const char *name)
371{
372 struct ctf_fs_trace *ctf_fs_trace;
373 int ret;
374
375 ctf_fs_trace = g_new0(struct ctf_fs_trace, 1);
376 if (!ctf_fs_trace) {
377 goto end;
378 }
379
380 ctf_fs_trace->ctf_fs = ctf_fs;
381 ctf_fs_trace->path = g_string_new(path);
382 if (!ctf_fs_trace->path) {
383 goto error;
384 }
385
386 ctf_fs_trace->name = g_string_new(name);
387 if (!ctf_fs_trace->name) {
388 goto error;
389 }
390
391 ctf_fs_trace->metadata = g_new0(struct ctf_fs_metadata, 1);
392 if (!ctf_fs_trace->metadata) {
393 goto error;
394 }
395
396 ret = ctf_fs_metadata_set_trace(ctf_fs_trace);
397 if (ret) {
398 goto error;
399 }
400
401 ret = create_cc_prio_map(ctf_fs_trace);
402 if (ret) {
403 goto error;
404 }
405
406 ret = create_ports_for_trace(ctf_fs_trace);
407 if (ret) {
408 goto error;
409 }
410
411 goto end;
412
413error:
414 ctf_fs_trace_destroy(ctf_fs_trace);
415 ctf_fs_trace = NULL;
416end:
417 return ctf_fs_trace;
418}
419
420static
421int path_is_ctf_trace(const char *path)
422{
423 GString *metadata_path = g_string_new(NULL);
424 int ret = 0;
425
426 if (!metadata_path) {
427 ret = -1;
428 goto end;
429 }
430
431 g_string_printf(metadata_path, "%s/%s", path, CTF_FS_METADATA_FILENAME);
432
433 if (g_file_test(metadata_path->str, G_FILE_TEST_IS_REGULAR)) {
434 ret = 1;
435 goto end;
436 }
437
438end:
439 g_string_free(metadata_path, TRUE);
440 return ret;
441}
442
443static
444int add_trace_path(struct ctf_fs_component *ctf_fs, GList **trace_paths,
445 const char *path)
446{
447 GString *path_str = g_string_new(NULL);
448 int ret = 0;
449 char *rp = NULL;
450
451 if (!path_str) {
452 ret = -1;
453 goto end;
454 }
455
456 /*
457 * Find the real path so that we don't have relative components
458 * in the trace name. This also squashes consecutive slashes and
459 * removes any slash at the end.
460 */
461 rp = realpath(path, NULL);
462 if (!rp) {
463 PERR("realpath() failed: %s (%d)\n", strerror(errno), errno);
464 ret = -1;
465 goto end;
466 }
467
468 if (strcmp(rp, "/") == 0) {
469 PERR("Opening a trace in `/` is not supported.\n");
470 ret = -1;
471 goto end;
472 }
473
474 g_string_assign(path_str, rp);
475 *trace_paths = g_list_prepend(*trace_paths, path_str);
476 assert(*trace_paths);
477
478end:
479 free(rp);
480 return ret;
481}
482
483static
484int find_ctf_traces(struct ctf_fs_component *ctf_fs,
485 GList **trace_paths, const char *start_path)
486{
487 int ret;
488 GError *error = NULL;
489 GDir *dir = NULL;
490 const char *basename = NULL;
491
492 /* Check if the starting path is a CTF trace itself */
493 ret = path_is_ctf_trace(start_path);
494 if (ret < 0) {
495 goto end;
496 }
497
498 if (ret) {
499 /*
500 * Do not even recurse: a CTF trace cannot contain
501 * another CTF trace.
502 */
503 ret = add_trace_path(ctf_fs, trace_paths, start_path);
504 goto end;
505 }
506
507 /* Look for subdirectories */
508 if (!g_file_test(start_path, G_FILE_TEST_IS_DIR)) {
509 /* Starting path is not a directory: end of recursion */
510 goto end;
511 }
512
513 dir = g_dir_open(start_path, 0, &error);
514 if (!dir) {
515 if (error->code == G_FILE_ERROR_ACCES) {
516 PDBG("Cannot open directory `%s`: %s (code %d): continuing\n",
517 start_path, error->message, error->code);
518 goto end;
519 }
520
521 PERR("Cannot open directory `%s`: %s (code %d)\n",
522 start_path, error->message, error->code);
523 ret = -1;
524 goto end;
525 }
526
527 while ((basename = g_dir_read_name(dir))) {
528 GString *sub_path = g_string_new(NULL);
529
530 if (!sub_path) {
531 ret = -1;
532 goto end;
533 }
534
535 g_string_printf(sub_path, "%s/%s", start_path, basename);
536 ret = find_ctf_traces(ctf_fs, trace_paths, sub_path->str);
537 g_string_free(sub_path, TRUE);
538 if (ret) {
539 goto end;
540 }
541 }
542
543end:
544 if (dir) {
545 g_dir_close(dir);
546 }
547
548 if (error) {
549 g_error_free(error);
550 }
551
552 return ret;
553}
554
555static
556GList *create_trace_names(GList *trace_paths) {
557 GList *trace_names = NULL;
558 size_t chars_to_strip = 0;
559 size_t at = 0;
560 GList *node;
561 bool done = false;
562
563 /*
564 * Find the number of characters to strip from the beginning,
565 * that is, the longest prefix until a common slash (also
566 * stripped).
567 */
568 while (true) {
569 gchar common_ch = '\0';
570
571 for (node = trace_paths; node; node = g_list_next(node)) {
572 GString *gstr = node->data;
573 gchar this_ch = gstr->str[at];
574
575 if (this_ch == '\0') {
576 done = true;
577 break;
578 }
579
580 if (common_ch == '\0') {
581 /*
582 * Establish the expected common
583 * character at this position.
584 */
585 common_ch = this_ch;
586 continue;
587 }
588
589 if (this_ch != common_ch) {
590 done = true;
591 break;
592 }
593 }
594
595 if (done) {
596 break;
597 }
598
599 if (common_ch == '/') {
600 /*
601 * Common character is a slash: safe to include
602 * this slash in the number of characters to
603 * strip because the paths are guaranteed not to
604 * end with slash.
605 */
606 chars_to_strip = at + 1;
607 }
608
609 at++;
610 }
611
612 /* Create the trace names */
613 for (node = trace_paths; node; node = g_list_next(node)) {
614 GString *trace_name = g_string_new(NULL);
615 GString *trace_path = node->data;
616
617 g_string_assign(trace_name, &trace_path->str[chars_to_strip]);
618 trace_names = g_list_append(trace_names, trace_name);
619 }
620
621 return trace_names;
622}
623
624static
625int create_ctf_fs_traces(struct ctf_fs_component *ctf_fs,
626 const char *path_param)
627{
628 struct ctf_fs_trace *ctf_fs_trace = NULL;
629 int ret = 0;
630 GList *trace_paths = NULL;
631 GList *trace_names = NULL;
632 GList *tp_node;
633 GList *tn_node;
634
635 ret = find_ctf_traces(ctf_fs, &trace_paths, path_param);
636 if (ret) {
637 goto error;
638 }
639
640 if (!trace_paths) {
641 PERR("No CTF traces recursively found in `%s`.\n",
642 path_param);
643 goto error;
644 }
645
646 trace_names = create_trace_names(trace_paths);
647 if (!trace_names) {
648 PERR("Cannot create trace names from trace paths.\n");
649 goto error;
650 }
651
652 for (tp_node = trace_paths, tn_node = trace_names; tp_node;
653 tp_node = g_list_next(tp_node),
654 tn_node = g_list_next(tn_node)) {
655 GString *trace_path = tp_node->data;
656 GString *trace_name = tn_node->data;
657
658 ctf_fs_trace = ctf_fs_trace_create(ctf_fs, trace_path->str,
659 trace_name->str);
660 if (!ctf_fs_trace) {
661 PERR("Cannot create trace for `%s`.\n",
662 trace_path->str);
663 goto error;
664 }
52c5fe74
PP
665
666 g_ptr_array_add(ctf_fs->traces, ctf_fs_trace);
667 ctf_fs_trace = NULL;
1a9f7075
PP
668 }
669
1a9f7075
PP
670 goto end;
671
672error:
673 ret = -1;
674 ctf_fs_trace_destroy(ctf_fs_trace);
675
676end:
677 for (tp_node = trace_paths; tp_node; tp_node = g_list_next(tp_node)) {
678 if (tp_node->data) {
679 g_string_free(tp_node->data, TRUE);
680 }
681 }
682
683 for (tn_node = trace_names; tn_node; tn_node = g_list_next(tn_node)) {
684 if (tn_node->data) {
685 g_string_free(tn_node->data, TRUE);
686 }
687 }
688
689 if (trace_paths) {
690 g_list_free(trace_paths);
691 }
692
693 if (trace_names) {
694 g_list_free(trace_names);
695 }
696
697 return ret;
698}
699
5b29e799 700static
4f1f88a6
PP
701struct ctf_fs_component *ctf_fs_create(struct bt_private_component *priv_comp,
702 struct bt_value *params)
56a1cced
JG
703{
704 struct ctf_fs_component *ctf_fs;
1ef09eb5 705 struct bt_value *value = NULL;
1a9f7075 706 const char *path_param;
4f1f88a6 707 int ret;
56a1cced
JG
708
709 ctf_fs = g_new0(struct ctf_fs_component, 1);
710 if (!ctf_fs) {
711 goto end;
712 }
713
1a9f7075
PP
714 ret = bt_private_component_set_user_data(priv_comp, ctf_fs);
715 assert(ret == 0);
716
4f1f88a6
PP
717 /*
718 * We don't need to get a new reference here because as long as
719 * our private ctf_fs_component object exists, the containing
720 * private component should also exist.
721 */
722 ctf_fs->priv_comp = priv_comp;
56a1cced 723 value = bt_value_map_get(params, "path");
1a9f7075 724 if (!bt_value_is_string(value)) {
56a1cced
JG
725 goto error;
726 }
727
1a9f7075
PP
728 ret = bt_value_string_get(value, &path_param);
729 assert(ret == 0);
730 BT_PUT(value);
92540773
JD
731 value = bt_value_map_get(params, "offset-s");
732 if (value) {
733 int64_t offset;
734
735 if (!bt_value_is_integer(value)) {
736 fprintf(stderr,
737 "offset-s should be an integer\n");
738 goto error;
739 }
740 ret = bt_value_integer_get(value, &offset);
1a9f7075 741 assert(ret == 0);
92540773 742 ctf_fs->options.clock_offset = offset;
1a9f7075 743 BT_PUT(value);
92540773
JD
744 }
745
746 value = bt_value_map_get(params, "offset-ns");
747 if (value) {
748 int64_t offset;
749
750 if (!bt_value_is_integer(value)) {
751 fprintf(stderr,
752 "offset-ns should be an integer\n");
753 goto error;
754 }
755 ret = bt_value_integer_get(value, &offset);
1a9f7075 756 assert(ret == 0);
92540773 757 ctf_fs->options.clock_offset_ns = offset;
1a9f7075 758 BT_PUT(value);
92540773
JD
759 }
760
56a1cced
JG
761 ctf_fs->error_fp = stderr;
762 ctf_fs->page_size = (size_t) getpagesize();
1a9f7075
PP
763 ctf_fs->port_data = g_ptr_array_new_with_free_func(port_data_destroy);
764 if (!ctf_fs->port_data) {
4f1f88a6
PP
765 goto error;
766 }
767
1a9f7075
PP
768 ctf_fs->traces = g_ptr_array_new_with_free_func(ctf_fs_trace_destroy);
769 if (!ctf_fs->traces) {
599faa1c
PP
770 goto error;
771 }
772
1a9f7075 773 ret = create_ctf_fs_traces(ctf_fs, path_param);
4f1f88a6
PP
774 if (ret) {
775 goto error;
776 }
777
1ef09eb5
JG
778 goto end;
779
56a1cced 780error:
1a9f7075 781 ctf_fs_destroy(ctf_fs);
e7a4393b 782 ctf_fs = NULL;
1a9f7075
PP
783 ret = bt_private_component_set_user_data(priv_comp, NULL);
784 assert(ret == 0);
785
1ef09eb5 786end:
1a9f7075 787 bt_put(value);
56a1cced
JG
788 return ctf_fs;
789}
790
ea0b4b9e 791BT_HIDDEN
4f1f88a6 792enum bt_component_status ctf_fs_init(struct bt_private_component *priv_comp,
7d61fa8e 793 struct bt_value *params, UNUSED_VAR void *init_method_data)
ea0b4b9e
JG
794{
795 struct ctf_fs_component *ctf_fs;
796 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
797
ea0b4b9e 798 ctf_fs_debug = g_strcmp0(getenv("CTF_FS_DEBUG"), "1") == 0;
4f1f88a6 799 ctf_fs = ctf_fs_create(priv_comp, params);
ea0b4b9e 800 if (!ctf_fs) {
1a9f7075 801 ret = BT_COMPONENT_STATUS_ERROR;
ea0b4b9e 802 }
4c1456f0 803
ea0b4b9e
JG
804 return ret;
805}
33f93973
PP
806
807BT_HIDDEN
a67681c1
PP
808struct bt_value *ctf_fs_query(struct bt_component_class *comp_class,
809 const char *object, struct bt_value *params)
33f93973
PP
810{
811 struct bt_value *results = NULL;
812 struct bt_value *path_value = NULL;
813 char *metadata_text = NULL;
814 FILE *metadata_fp = NULL;
815 GString *g_metadata_text = NULL;
816
a67681c1 817 if (strcmp(object, "metadata-info") == 0) {
33f93973
PP
818 int ret;
819 int bo;
820 const char *path;
821 bool is_packetized;
822
823 results = bt_value_map_create();
824 if (!results) {
825 goto error;
826 }
827
828 if (!bt_value_is_map(params)) {
829 fprintf(stderr,
a67681c1 830 "Query parameters is not a map value object\n");
33f93973
PP
831 goto error;
832 }
833
834 path_value = bt_value_map_get(params, "path");
835 ret = bt_value_string_get(path_value, &path);
836 if (ret) {
837 fprintf(stderr,
838 "Cannot get `path` string parameter\n");
839 goto error;
840 }
841
842 assert(path);
843 metadata_fp = ctf_fs_metadata_open_file(path);
844 if (!metadata_fp) {
845 fprintf(stderr,
846 "Cannot open trace at path `%s`\n", path);
847 goto error;
848 }
849
1e649dff
PP
850 is_packetized = ctf_metadata_decoder_is_packetized(metadata_fp,
851 &bo);
33f93973
PP
852
853 if (is_packetized) {
1e649dff
PP
854 ret = ctf_metadata_decoder_packetized_file_stream_to_buf(
855 metadata_fp, &metadata_text, bo);
33f93973
PP
856 if (ret) {
857 fprintf(stderr,
858 "Cannot decode packetized metadata file\n");
859 goto error;
860 }
861 } else {
862 long filesize;
863
864 fseek(metadata_fp, 0, SEEK_END);
865 filesize = ftell(metadata_fp);
866 rewind(metadata_fp);
867 metadata_text = malloc(filesize + 1);
868 if (!metadata_text) {
869 fprintf(stderr,
870 "Cannot allocate buffer for metadata text\n");
871 goto error;
872 }
873
874 if (fread(metadata_text, filesize, 1, metadata_fp) !=
875 1) {
876 fprintf(stderr,
877 "Cannot read metadata file\n");
878 goto error;
879 }
880
881 metadata_text[filesize] = '\0';
882 }
883
884 g_metadata_text = g_string_new(NULL);
885 if (!g_metadata_text) {
886 goto error;
887 }
888
889 if (strncmp(metadata_text, METADATA_TEXT_SIG,
890 sizeof(METADATA_TEXT_SIG) - 1) != 0) {
891 g_string_assign(g_metadata_text, METADATA_TEXT_SIG);
892 g_string_append(g_metadata_text, " */\n\n");
893 }
894
895 g_string_append(g_metadata_text, metadata_text);
896
897 ret = bt_value_map_insert_string(results, "text",
898 g_metadata_text->str);
899 if (ret) {
900 fprintf(stderr, "Cannot insert metadata text into results\n");
901 goto error;
902 }
903
904 ret = bt_value_map_insert_bool(results, "is-packetized",
905 is_packetized);
906 if (ret) {
907 fprintf(stderr, "Cannot insert is packetized into results\n");
908 goto error;
909 }
910 } else {
a67681c1 911 fprintf(stderr, "Unknown query object `%s`\n", object);
33f93973
PP
912 goto error;
913 }
914
915 goto end;
916
917error:
918 BT_PUT(results);
919
920end:
921 bt_put(path_value);
922 free(metadata_text);
923
924 if (g_metadata_text) {
925 g_string_free(g_metadata_text, TRUE);
926 }
927
928 if (metadata_fp) {
929 fclose(metadata_fp);
930 }
931 return results;
932}
This page took 0.076081 seconds and 4 git commands to generate.