Docs: allow NULL packet, stream and event headers, contexts and payloads
[babeltrace.git] / plugins / ctf / fs / fs.c
CommitLineData
7a278c8e 1/*
ea0b4b9e 2 * fs.c
7a278c8e 3 *
ea0b4b9e 4 * Babeltrace CTF file system Reader Component
7a278c8e 5 *
f3bc2010 6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7a278c8e
JG
7 *
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
ea0b4b9e 29#include <babeltrace/plugin/plugin-system.h>
5b29e799 30#include <babeltrace/ctf-ir/packet.h>
a4792757 31#include <babeltrace/ctf-ir/clock.h>
760051fa 32#include <babeltrace/plugin/notification/iterator.h>
5b29e799
JG
33#include <babeltrace/plugin/notification/stream.h>
34#include <babeltrace/plugin/notification/event.h>
35#include <babeltrace/plugin/notification/packet.h>
36#include <babeltrace/plugin/notification/heap.h>
ea0b4b9e
JG
37#include <glib.h>
38#include <assert.h>
56a1cced
JG
39#include <unistd.h>
40#include "fs.h"
413bc2c4
JG
41#include "metadata.h"
42#include "data-stream.h"
e7a4393b
JG
43#include "file.h"
44
45#define PRINT_ERR_STREAM ctf_fs->error_fp
46#define PRINT_PREFIX "ctf-fs"
47#include "print.h"
ea0b4b9e
JG
48
49static bool ctf_fs_debug;
50
51static
760051fa
JG
52struct bt_notification *ctf_fs_iterator_get(
53 struct bt_notification_iterator *iterator)
ea0b4b9e 54{
5b29e799
JG
55 struct ctf_fs_iterator *ctf_it =
56 bt_notification_iterator_get_private_data(iterator);
d01e0f33 57
5b29e799 58 return bt_get(ctf_it->current_notification);
ea0b4b9e
JG
59}
60
61static
5b29e799
JG
62enum bt_notification_iterator_status ctf_fs_iterator_get_next_notification(
63 struct ctf_fs_iterator *it,
64 struct ctf_fs_stream *stream,
65 struct bt_notification **notification)
ea0b4b9e 66{
5b29e799 67 enum bt_ctf_notif_iter_status status;
d01e0f33 68 enum bt_notification_iterator_status ret;
d01e0f33 69
5b29e799
JG
70 if (stream->end_reached) {
71 status = BT_CTF_NOTIF_ITER_STATUS_EOF;
d01e0f33
JG
72 goto end;
73 }
74
5b29e799
JG
75 status = bt_ctf_notif_iter_get_next_notification(stream->notif_iter,
76 notification);
77 if (status != BT_CTF_NOTIF_ITER_STATUS_OK &&
78 status != BT_CTF_NOTIF_ITER_STATUS_EOF) {
d01e0f33
JG
79 goto end;
80 }
81
5b29e799
JG
82 /* Should be handled in bt_ctf_notif_iter_get_next_notification. */
83 if (status == BT_CTF_NOTIF_ITER_STATUS_EOF) {
84 *notification = bt_notification_stream_end_create(
85 stream->stream);
86 if (!*notification) {
87 status = BT_CTF_NOTIF_ITER_STATUS_ERROR;
88 }
89 status = BT_CTF_NOTIF_ITER_STATUS_OK;
90 stream->end_reached = true;
91 }
d01e0f33 92end:
5b29e799
JG
93 switch (status) {
94 case BT_CTF_NOTIF_ITER_STATUS_EOF:
95 ret = BT_NOTIFICATION_ITERATOR_STATUS_END;
96 break;
97 case BT_CTF_NOTIF_ITER_STATUS_OK:
98 ret = BT_NOTIFICATION_ITERATOR_STATUS_OK;
99 break;
100 case BT_CTF_NOTIF_ITER_STATUS_AGAIN:
101 /*
102 * Should not make it this far as this is medium-specific;
103 * there is nothing for the user to do and it should have been
104 * handled upstream.
105 */
106 assert(0);
107 case BT_CTF_NOTIF_ITER_STATUS_INVAL:
108 /* No argument provided by the user, so don't return INVAL. */
109 case BT_CTF_NOTIF_ITER_STATUS_ERROR:
110 default:
111 ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
112 break;
113 }
043e2020 114 return ret;
ea0b4b9e 115}
bfd20a42 116
5b29e799
JG
117/*
118 * Remove me. This is a temporary work-around due to our inhability to use
119 * libbabeltrace-ctf from libbabeltrace-plugin.
120 */
760051fa 121static
5b29e799
JG
122struct bt_ctf_stream *internal_bt_notification_get_stream(
123 struct bt_notification *notification)
760051fa 124{
5b29e799
JG
125 struct bt_ctf_stream *stream = NULL;
126
127 assert(notification);
128 switch (bt_notification_get_type(notification)) {
129 case BT_NOTIFICATION_TYPE_EVENT:
130 {
131 struct bt_ctf_event *event;
132
133 event = bt_notification_event_get_event(notification);
134 stream = bt_ctf_event_get_stream(event);
135 bt_put(event);
136 break;
137 }
138 case BT_NOTIFICATION_TYPE_PACKET_START:
139 {
140 struct bt_ctf_packet *packet;
141
142 packet = bt_notification_packet_start_get_packet(notification);
143 stream = bt_ctf_packet_get_stream(packet);
144 bt_put(packet);
145 break;
146 }
147 case BT_NOTIFICATION_TYPE_PACKET_END:
148 {
149 struct bt_ctf_packet *packet;
150
151 packet = bt_notification_packet_end_get_packet(notification);
152 stream = bt_ctf_packet_get_stream(packet);
153 bt_put(packet);
154 break;
155 }
156 case BT_NOTIFICATION_TYPE_STREAM_END:
157 stream = bt_notification_stream_end_get_stream(notification);
158 break;
159 default:
160 goto end;
161 }
162end:
163 return stream;
760051fa
JG
164}
165
166static
5b29e799 167enum bt_notification_iterator_status populate_heap(struct ctf_fs_iterator *it)
760051fa 168{
5b29e799
JG
169 size_t i, pending_streams_count = it->pending_streams->len;
170 enum bt_notification_iterator_status ret =
171 BT_NOTIFICATION_ITERATOR_STATUS_OK;
172
173 /* Insert one stream-associated notification for each stream. */
174 for (i = 0; i < pending_streams_count; i++) {
175 struct bt_notification *notification;
176 struct ctf_fs_stream *fs_stream;
177 struct bt_ctf_stream *stream;
178 size_t pending_stream_index = pending_streams_count - 1 - i;
179
180 fs_stream = g_ptr_array_index(it->pending_streams,
181 pending_stream_index);
182
183 do {
184 int heap_ret;
185
186 ret = ctf_fs_iterator_get_next_notification(
187 it, fs_stream, &notification);
188 if (ret && ret != BT_NOTIFICATION_ITERATOR_STATUS_END) {
189 printf_debug("Failed to populate heap at stream %zu\n",
190 pending_stream_index);
191 goto end;
192 }
193
194 stream = internal_bt_notification_get_stream(
195 notification);
196 if (stream) {
197 gboolean inserted;
198
199 /*
200 * Associate pending ctf_fs_stream to
201 * bt_ctf_stream. Ownership of stream
202 * is passed to the stream ht.
203 */
204 inserted = g_hash_table_insert(it->stream_ht,
205 stream, fs_stream);
206 if (!inserted) {
207 ret = BT_NOTIFICATION_ITERATOR_STATUS_NOMEM;
208 printf_debug("Failed to associate fs stream to ctf stream\n");
209 goto end;
210 }
211 }
212
213 heap_ret = bt_notification_heap_insert(
214 it->pending_notifications,
215 notification);
216 bt_put(notification);
217 if (heap_ret) {
218 ret = BT_NOTIFICATION_ITERATOR_STATUS_NOMEM;
219 printf_debug("Failed to insert notification in heap\n");
220 goto end;
221 }
222 } while (!stream && ret != BT_NOTIFICATION_ITERATOR_STATUS_END);
223 /*
224 * Set NULL so the destruction callback registered with the
225 * array is not invoked on the stream (its ownership was
226 * transferred to the streams hashtable).
227 */
228 g_ptr_array_index(it->pending_streams,
229 pending_stream_index) = NULL;
230 g_ptr_array_remove_index(it->pending_streams,
231 pending_stream_index);
232 }
760051fa 233
5b29e799
JG
234 g_ptr_array_free(it->pending_streams, TRUE);
235 it->pending_streams = NULL;
236end:
237 return ret;
760051fa
JG
238}
239
240static
5b29e799
JG
241enum bt_notification_iterator_status ctf_fs_iterator_next(
242 struct bt_notification_iterator *iterator)
4c1456f0 243{
5b29e799 244 int heap_ret;
a11bd504 245 struct bt_ctf_stream *stream = NULL;
5b29e799
JG
246 struct ctf_fs_stream *fs_stream;
247 struct bt_notification *notification;
248 struct bt_notification *next_stream_notification;
249 enum bt_notification_iterator_status ret =
250 BT_NOTIFICATION_ITERATOR_STATUS_OK;
251 struct ctf_fs_iterator *ctf_it =
252 bt_notification_iterator_get_private_data(iterator);
253
254 notification = bt_notification_heap_pop(ctf_it->pending_notifications);
255 if (!notification && !ctf_it->pending_streams) {
256 ret = BT_NOTIFICATION_ITERATOR_STATUS_END;
760051fa
JG
257 goto end;
258 }
259
5b29e799
JG
260 if (!notification && ctf_it->pending_streams) {
261 /*
262 * Insert at one notification per stream in the heap and pop
263 * one.
264 */
265 ret = populate_heap(ctf_it);
266 if (ret) {
267 goto end;
268 }
269
270 notification = bt_notification_heap_pop(
271 ctf_it->pending_notifications);
272 if (!notification) {
273 ret = BT_NOTIFICATION_ITERATOR_STATUS_END;
274 goto end;
275 }
760051fa
JG
276 }
277
5b29e799
JG
278 /* notification is set from here. */
279
280 stream = internal_bt_notification_get_stream(notification);
281 if (!stream) {
282 /*
283 * The current notification is not associated to a particular
284 * stream, there is no need to insert a new notification from
285 * a stream in the heap.
286 */
287 goto end;
760051fa
JG
288 }
289
5b29e799
JG
290 fs_stream = g_hash_table_lookup(ctf_it->stream_ht, stream);
291 if (!fs_stream) {
292 /* We have reached this stream's end. */
293 goto end;
760051fa
JG
294 }
295
5b29e799
JG
296 ret = ctf_fs_iterator_get_next_notification(ctf_it, fs_stream,
297 &next_stream_notification);
298 if ((ret && ret != BT_NOTIFICATION_ITERATOR_STATUS_END)) {
299 heap_ret = bt_notification_heap_insert(
300 ctf_it->pending_notifications, notification);
301
302 assert(!next_stream_notification);
303 if (heap_ret) {
304 /*
305 * We're dropping the most recent notification, but at
306 * this point, something is seriously wrong...
307 */
308 ret = BT_NOTIFICATION_ITERATOR_STATUS_NOMEM;
309 }
310 BT_PUT(notification);
311 goto end;
312 }
313
314 if (ret == BT_NOTIFICATION_ITERATOR_STATUS_END) {
315 gboolean success;
316
317 /* Remove stream. */
318 success = g_hash_table_remove(ctf_it->stream_ht, stream);
319 assert(success);
320 ret = BT_NOTIFICATION_ITERATOR_STATUS_OK;
321 } else {
322 heap_ret = bt_notification_heap_insert(ctf_it->pending_notifications,
323 next_stream_notification);
324 BT_PUT(next_stream_notification);
325 if (heap_ret) {
326 /*
327 * We're dropping the most recent notification...
328 */
329 ret = BT_NOTIFICATION_ITERATOR_STATUS_NOMEM;
330 }
760051fa 331 }
5b29e799
JG
332
333 /*
334 * Ensure that the stream is removed from both pending_streams and
335 * the streams hashtable on reception of the "end of stream"
336 * notification.
337 */
760051fa 338end:
5b29e799 339 BT_MOVE(ctf_it->current_notification, notification);
33bf10b7 340 bt_put(stream);
760051fa
JG
341 return ret;
342}
343
760051fa 344static
5b29e799 345void ctf_fs_iterator_destroy_data(struct ctf_fs_iterator *ctf_it)
760051fa 346{
5b29e799
JG
347 bt_put(ctf_it->current_notification);
348 bt_put(ctf_it->pending_notifications);
349 if (ctf_it->pending_streams) {
350 g_ptr_array_free(ctf_it->pending_streams, TRUE);
56a1cced 351 }
5b29e799
JG
352 if (ctf_it->stream_ht) {
353 g_hash_table_destroy(ctf_it->stream_ht);
c14d7e26 354 }
5b29e799 355 g_free(ctf_it);
760051fa
JG
356}
357
358static
5b29e799 359void ctf_fs_iterator_destroy(struct bt_notification_iterator *it)
760051fa 360{
5b29e799 361 void *data = bt_notification_iterator_get_private_data(it);
760051fa 362
5b29e799 363 ctf_fs_iterator_destroy_data(data);
4c1456f0
JG
364}
365
a4792757
JG
366static
367bool compare_event_notifications(struct bt_notification *a,
368 struct bt_notification *b)
369{
370 int ret;
371 struct bt_ctf_clock *clock;
372 struct bt_ctf_clock_value *a_clock_value, *b_clock_value;
373 struct bt_ctf_stream_class *a_stream_class;
374 struct bt_ctf_stream *a_stream;
375 struct bt_ctf_event *a_event, *b_event;
376 struct bt_ctf_trace *trace;
377 int64_t a_ts, b_ts;
378
379 // FIXME - assumes only one clock
380 a_event = bt_notification_event_get_event(a);
381 b_event = bt_notification_event_get_event(b);
382 assert(a_event);
383 assert(b_event);
384
385 a_stream = bt_ctf_event_get_stream(a_event);
386 assert(a_stream);
387 a_stream_class = bt_ctf_stream_get_class(a_stream);
388 assert(a_stream_class);
389 trace = bt_ctf_stream_class_get_trace(a_stream_class);
390 assert(trace);
391
392 clock = bt_ctf_trace_get_clock(trace, 0);
393 a_clock_value = bt_ctf_event_get_clock_value(a_event, clock);
394 b_clock_value = bt_ctf_event_get_clock_value(b_event, clock);
395 assert(a_clock_value);
396 assert(b_clock_value);
397
398 ret = bt_ctf_clock_value_get_value_ns_from_epoch(a_clock_value, &a_ts);
399 assert(!ret);
400 ret = bt_ctf_clock_value_get_value_ns_from_epoch(b_clock_value, &b_ts);
401 assert(!ret);
402
403 bt_put(a_event);
404 bt_put(b_event);
405 bt_put(a_clock_value);
406 bt_put(b_clock_value);
407 bt_put(a_stream);
408 bt_put(a_stream_class);
409 bt_put(clock);
410 bt_put(trace);
411 return a_ts < b_ts;
412}
413
e7a4393b 414static
5b29e799
JG
415bool compare_notifications(struct bt_notification *a, struct bt_notification *b,
416 void *unused)
417{
a4792757
JG
418 static int notification_priorities[] = {
419 [BT_NOTIFICATION_TYPE_NEW_TRACE] = 0,
420 [BT_NOTIFICATION_TYPE_NEW_STREAM_CLASS] = 1,
421 [BT_NOTIFICATION_TYPE_NEW_EVENT_CLASS] = 2,
422 [BT_NOTIFICATION_TYPE_PACKET_START] = 3,
423 [BT_NOTIFICATION_TYPE_PACKET_END] = 4,
424 [BT_NOTIFICATION_TYPE_EVENT] = 5,
425 [BT_NOTIFICATION_TYPE_END_OF_TRACE] = 6,
426 };
427 int a_prio, b_prio;
428 enum bt_notification_type a_type, b_type;
429
430 assert(a && b);
431 a_type = bt_notification_get_type(a);
432 b_type = bt_notification_get_type(b);
433 assert(a_type > BT_NOTIFICATION_TYPE_ALL);
434 assert(a_type < BT_NOTIFICATION_TYPE_NR);
435 assert(b_type > BT_NOTIFICATION_TYPE_ALL);
436 assert(b_type < BT_NOTIFICATION_TYPE_NR);
437
438 a_prio = notification_priorities[a_type];
439 b_prio = notification_priorities[b_type];
440
441 if (likely((a_type == b_type) && a_type == BT_NOTIFICATION_TYPE_EVENT)) {
442 return compare_event_notifications(a, b);
443 }
444
445 if (unlikely(a_prio != b_prio)) {
446 return a_prio < b_prio;
447 }
448
449 /* Notification types are equal, but not of type "event". */
450 switch (a_type) {
451 case BT_NOTIFICATION_TYPE_PACKET_START:
452 case BT_NOTIFICATION_TYPE_PACKET_END:
453 case BT_NOTIFICATION_TYPE_STREAM_END:
454 {
455 int64_t a_sc_id, b_sc_id;
456 struct bt_ctf_stream *a_stream, *b_stream;
457 struct bt_ctf_stream_class *a_sc, *b_sc;
458
459 a_stream = internal_bt_notification_get_stream(a);
460 b_stream = internal_bt_notification_get_stream(b);
461 assert(a_stream && b_stream);
462
463 a_sc = bt_ctf_stream_get_class(a_stream);
464 b_sc = bt_ctf_stream_get_class(b_stream);
465 assert(a_sc && b_sc);
466
467 a_sc_id = bt_ctf_stream_class_get_id(a_sc);
468 b_sc_id = bt_ctf_stream_class_get_id(b_sc);
469 assert(a_sc_id >= 0 && b_sc_id >= 0);
470 bt_put(a_sc);
471 bt_put(a_stream);
472 bt_put(b_sc);
473 bt_put(b_stream);
474 return a_sc_id < b_sc_id;
475 }
476 case BT_NOTIFICATION_TYPE_NEW_TRACE:
477 case BT_NOTIFICATION_TYPE_END_OF_TRACE:
478 /* Impossible to have two separate traces. */
479 default:
480 assert(0);
481 }
482
483 assert(0);
5b29e799
JG
484 return a < b;
485}
486
487static
488void stream_destroy(void *stream)
489{
490 ctf_fs_stream_destroy((struct ctf_fs_stream *) stream);
491}
492
493static
494int open_trace_streams(struct ctf_fs_component *ctf_fs,
495 struct ctf_fs_iterator *ctf_it)
e7a4393b
JG
496{
497 int ret = 0;
498 const char *name;
499 GError *error = NULL;
500 GDir *dir = g_dir_open(ctf_fs->trace_path->str, 0, &error);
501
502 if (!dir) {
503 PERR("Cannot open directory \"%s\": %s (code %d)\n",
504 ctf_fs->trace_path->str, error->message,
505 error->code);
506 goto error;
507 }
508
509 while ((name = g_dir_read_name(dir))) {
510 struct ctf_fs_file *file = NULL;
511 struct ctf_fs_stream *stream = NULL;
512
513 if (!strcmp(name, CTF_FS_METADATA_FILENAME)) {
514 /* Ignore the metadata stream. */
515 PDBG("Ignoring metadata file \"%s\"\n",
516 name);
517 continue;
518 }
519
520 if (name[0] == '.') {
521 PDBG("Ignoring hidden file \"%s\"\n",
522 name);
523 continue;
524 }
525
526 /* Create the file. */
527 file = ctf_fs_file_create(ctf_fs);
528 if (!file) {
529 PERR("Cannot create stream file object\n");
530 goto error;
531 }
532
533 /* Create full path string. */
534 g_string_append_printf(file->path, "%s/%s",
535 ctf_fs->trace_path->str, name);
536 if (!g_file_test(file->path->str, G_FILE_TEST_IS_REGULAR)) {
537 PDBG("Ignoring non-regular file \"%s\"\n", name);
538 ctf_fs_file_destroy(file);
539 continue;
540 }
541
542 /* Open the file. */
543 if (ctf_fs_file_open(ctf_fs, file, "rb")) {
544 ctf_fs_file_destroy(file);
545 goto error;
546 }
547
548 /* Create a private stream; file ownership is passed to it. */
549 stream = ctf_fs_stream_create(ctf_fs, file);
550 if (!stream) {
551 ctf_fs_file_destroy(file);
552 goto error;
553 }
554
5b29e799 555 g_ptr_array_add(ctf_it->pending_streams, stream);
e7a4393b
JG
556 }
557
558 goto end;
559error:
560 ret = -1;
561end:
562 if (dir) {
563 g_dir_close(dir);
564 dir = NULL;
565 }
566 if (error) {
567 g_error_free(error);
568 }
569 return ret;
570}
571
572static
5b29e799
JG
573enum bt_component_status ctf_fs_iterator_init(struct bt_component *source,
574 struct bt_notification_iterator *it)
e7a4393b 575{
5b29e799
JG
576 struct ctf_fs_iterator *ctf_it;
577 struct ctf_fs_component *ctf_fs;
578 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
579
580 assert(source && it);
581
582 ctf_fs = bt_component_get_private_data(source);
583 if (!ctf_fs) {
584 ret = BT_COMPONENT_STATUS_INVALID;
585 goto end;
586 }
587
588 ctf_it = g_new0(struct ctf_fs_iterator, 1);
589 if (!ctf_it) {
590 ret = BT_COMPONENT_STATUS_NOMEM;
591 goto end;
592 }
593
594 ctf_it->stream_ht = g_hash_table_new_full(g_direct_hash,
595 g_direct_equal, bt_put, stream_destroy);
596 if (!ctf_it->stream_ht) {
597 goto error;
598 }
599 ctf_it->pending_streams = g_ptr_array_new_with_free_func(
600 stream_destroy);
601 if (!ctf_it->pending_streams) {
602 goto error;
603 }
604 ctf_it->pending_notifications = bt_notification_heap_create(
605 compare_notifications, NULL);
606 if (!ctf_it->pending_notifications) {
607 goto error;
608 }
609
610 ret = open_trace_streams(ctf_fs, ctf_it);
611 if (ret) {
612 goto error;
613 }
614
615 ret = bt_notification_iterator_set_get_cb(it, ctf_fs_iterator_get);
616 if (ret) {
617 goto error;
618 }
619
620 ret = bt_notification_iterator_set_next_cb(it, ctf_fs_iterator_next);
621 if (ret) {
622 goto error;
623 }
624
625 ret = bt_notification_iterator_set_destroy_cb(it,
626 ctf_fs_iterator_destroy);
627 if (ret) {
628 goto error;
629 }
630
631 ret = bt_notification_iterator_set_private_data(it, ctf_it);
632 if (ret) {
633 goto error;
634 }
635end:
636 return ret;
637error:
638 (void) bt_notification_iterator_set_private_data(it, NULL);
639 ctf_fs_iterator_destroy_data(ctf_it);
640 goto end;
641}
642
643static
644void ctf_fs_destroy_data(struct ctf_fs_component *ctf_fs)
645{
646 if (ctf_fs->trace_path) {
647 g_string_free(ctf_fs->trace_path, TRUE);
648 }
649 if (ctf_fs->metadata) {
650 ctf_fs_metadata_fini(ctf_fs->metadata);
651 g_free(ctf_fs->metadata);
652 }
653 g_free(ctf_fs);
654}
655
656static
657void ctf_fs_destroy(struct bt_component *component)
658{
659 void *data = bt_component_get_private_data(component);
660
661 ctf_fs_destroy_data(data);
e7a4393b
JG
662}
663
56a1cced
JG
664static
665struct ctf_fs_component *ctf_fs_create(struct bt_value *params)
666{
667 struct ctf_fs_component *ctf_fs;
1ef09eb5 668 struct bt_value *value = NULL;
56a1cced
JG
669 const char *path;
670 enum bt_value_status ret;
671
672 ctf_fs = g_new0(struct ctf_fs_component, 1);
673 if (!ctf_fs) {
674 goto end;
675 }
676
677 /* FIXME: should probably look for a source URI */
678 value = bt_value_map_get(params, "path");
679 if (!value || bt_value_is_null(value) || !bt_value_is_string(value)) {
680 goto error;
681 }
682
683 ret = bt_value_string_get(value, &path);
684 if (ret != BT_VALUE_STATUS_OK) {
685 goto error;
686 }
687
688 ctf_fs->trace_path = g_string_new(path);
689 if (!ctf_fs->trace_path) {
690 goto error;
691 }
56a1cced
JG
692 ctf_fs->error_fp = stderr;
693 ctf_fs->page_size = (size_t) getpagesize();
e7a4393b
JG
694
695 // FIXME: check error.
5b29e799
JG
696 ctf_fs->metadata = g_new0(struct ctf_fs_metadata, 1);
697 if (!ctf_fs->metadata) {
e7a4393b
JG
698 goto error;
699 }
5b29e799 700 ctf_fs_metadata_set_trace(ctf_fs);
1ef09eb5
JG
701 goto end;
702
56a1cced
JG
703error:
704 ctf_fs_destroy_data(ctf_fs);
e7a4393b 705 ctf_fs = NULL;
1ef09eb5
JG
706end:
707 BT_PUT(value);
56a1cced
JG
708 return ctf_fs;
709}
710
ea0b4b9e
JG
711BT_HIDDEN
712enum bt_component_status ctf_fs_init(struct bt_component *source,
5c80adeb 713 struct bt_value *params)
ea0b4b9e
JG
714{
715 struct ctf_fs_component *ctf_fs;
716 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
717
718 assert(source);
719 ctf_fs_debug = g_strcmp0(getenv("CTF_FS_DEBUG"), "1") == 0;
720 ctf_fs = ctf_fs_create(params);
721 if (!ctf_fs) {
722 ret = BT_COMPONENT_STATUS_NOMEM;
723 goto end;
724 }
4c1456f0 725
ea0b4b9e
JG
726 ret = bt_component_set_destroy_cb(source, ctf_fs_destroy);
727 if (ret != BT_COMPONENT_STATUS_OK) {
728 goto error;
729 }
730
731 ret = bt_component_set_private_data(source, ctf_fs);
732 if (ret != BT_COMPONENT_STATUS_OK) {
733 goto error;
734 }
735
736 ret = bt_component_source_set_iterator_init_cb(source,
737 ctf_fs_iterator_init);
738 if (ret != BT_COMPONENT_STATUS_OK) {
739 goto error;
740 }
741end:
742 return ret;
743error:
744 (void) bt_component_set_private_data(source, NULL);
760051fa 745 ctf_fs_destroy_data(ctf_fs);
ea0b4b9e
JG
746 return ret;
747}
This page took 0.058891 seconds and 4 git commands to generate.