CTF Writer sink
[babeltrace.git] / plugins / writer / write.c
1 /*
2 * writer.c
3 *
4 * Babeltrace CTF Writer Output Plugin Event Handling
5 *
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
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
29 #include <babeltrace/ctf-ir/event.h>
30 #include <babeltrace/ctf-ir/packet.h>
31 #include <babeltrace/ctf-ir/event-class.h>
32 #include <babeltrace/ctf-ir/stream.h>
33 #include <babeltrace/ctf-ir/stream-class.h>
34 #include <babeltrace/ctf-ir/clock.h>
35 #include <babeltrace/ctf-ir/fields.h>
36 #include <babeltrace/ctf-writer/stream-class.h>
37 #include <babeltrace/ctf-writer/stream.h>
38
39 #include "writer.h"
40
41 static
42 void tmp_clock(struct bt_ctf_writer *writer,
43 struct bt_ctf_stream_class *writer_stream_class,
44 struct bt_ctf_clock *writer_clock)
45 {
46 const char *clock_description = "This is a test clock";
47 const uint64_t frequency = 1000000000ULL;
48 const uint64_t offset_s = 1351530929945824323;
49 const uint64_t precision = 10;
50 const int is_absolute = 0xFF;
51
52 bt_ctf_clock_set_description(writer_clock, clock_description);
53 bt_ctf_clock_set_frequency(writer_clock, frequency);
54 bt_ctf_clock_set_offset_s(writer_clock, offset_s);
55 bt_ctf_clock_set_precision(writer_clock, precision);
56 bt_ctf_clock_set_is_absolute(writer_clock, is_absolute);
57 bt_ctf_writer_add_clock(writer, writer_clock);
58 bt_ctf_stream_class_set_clock(writer_stream_class, writer_clock);
59 }
60
61 static
62 enum bt_component_status copy_clock(FILE *err, struct bt_ctf_writer *writer,
63 struct bt_ctf_stream_class *writer_stream_class,
64 struct bt_ctf_clock *clock,
65 struct bt_ctf_clock *writer_clock)
66 {
67 enum bt_component_status ret;
68 int64_t offset, offset_s;
69 int int_ret;
70 uint64_t u64_ret;
71 const char *name, *description;
72
73 name = bt_ctf_clock_get_name(clock);
74 if (!name) {
75 ret = BT_COMPONENT_STATUS_ERROR;
76 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
77 __LINE__);
78 goto end;
79 }
80
81 writer_clock = bt_ctf_clock_create(name);
82 if (!writer_clock) {
83 ret = BT_COMPONENT_STATUS_ERROR;
84 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
85 __LINE__);
86 goto end;
87 }
88
89 description = bt_ctf_clock_get_description(clock);
90 if (!description) {
91 ret = BT_COMPONENT_STATUS_ERROR;
92 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
93 __LINE__);
94 goto end_destroy;
95 }
96
97 int_ret = bt_ctf_clock_set_description(writer_clock,
98 description);
99 if (int_ret != 0) {
100 ret = BT_COMPONENT_STATUS_ERROR;
101 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
102 __LINE__);
103 goto end_destroy;
104 }
105
106 u64_ret = bt_ctf_clock_get_frequency(clock);
107 if (u64_ret == -1ULL) {
108 ret = BT_COMPONENT_STATUS_ERROR;
109 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
110 __LINE__);
111 goto end_destroy;
112 }
113 int_ret = bt_ctf_clock_set_frequency(writer_clock, u64_ret);
114 if (int_ret != 0) {
115 ret = BT_COMPONENT_STATUS_ERROR;
116 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
117 __LINE__);
118 goto end_destroy;
119 }
120
121 u64_ret = bt_ctf_clock_get_precision(clock);
122 if (u64_ret == -1ULL) {
123 ret = BT_COMPONENT_STATUS_ERROR;
124 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
125 __LINE__);
126 goto end_destroy;
127 }
128 int_ret = bt_ctf_clock_set_precision(writer_clock, u64_ret);
129 if (int_ret != 0) {
130 ret = BT_COMPONENT_STATUS_ERROR;
131 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
132 __LINE__);
133 goto end_destroy;
134 }
135
136 int_ret = bt_ctf_clock_get_offset_s(clock, &offset_s);
137 if (int_ret != 0) {
138 ret = BT_COMPONENT_STATUS_ERROR;
139 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
140 __LINE__);
141 goto end_destroy;
142 }
143
144 int_ret = bt_ctf_clock_set_offset_s(writer_clock, offset_s);
145 if (int_ret != 0) {
146 ret = BT_COMPONENT_STATUS_ERROR;
147 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
148 __LINE__);
149 goto end_destroy;
150 }
151
152 int_ret = bt_ctf_clock_get_offset(clock, &offset);
153 if (int_ret != 0) {
154 ret = BT_COMPONENT_STATUS_ERROR;
155 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
156 __LINE__);
157 goto end_destroy;
158 }
159
160 int_ret = bt_ctf_clock_set_offset(writer_clock, offset);
161 if (int_ret != 0) {
162 ret = BT_COMPONENT_STATUS_ERROR;
163 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
164 __LINE__);
165 goto end_destroy;
166 }
167
168 int_ret = bt_ctf_clock_get_is_absolute(clock);
169 if (int_ret == -1) {
170 ret = BT_COMPONENT_STATUS_ERROR;
171 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
172 __LINE__);
173 goto end_destroy;
174 }
175 int_ret = bt_ctf_clock_set_is_absolute(writer_clock, int_ret);
176 if (int_ret != 0) {
177 ret = BT_COMPONENT_STATUS_ERROR;
178 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
179 __LINE__);
180 goto end_destroy;
181 }
182
183 ret = bt_ctf_writer_add_clock(writer, writer_clock);
184 if (ret != 0) {
185 ret = BT_COMPONENT_STATUS_ERROR;
186 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
187 __LINE__);
188 goto end_destroy;
189 }
190
191 ret = bt_ctf_stream_class_set_clock(writer_stream_class,
192 writer_clock);
193 if (ret != 0) {
194 ret = BT_COMPONENT_STATUS_ERROR;
195 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
196 __LINE__);
197 goto end_destroy;
198 }
199 /*
200 * Ownership transferred to the writer and the stream_class.
201 */
202 bt_put(writer_clock);
203
204 ret = BT_COMPONENT_STATUS_OK;
205 goto end;
206
207 end_destroy:
208 bt_put(writer_clock);
209 end:
210 return ret;
211 }
212
213 static
214 struct bt_ctf_event_class *copy_event_class(FILE *err, struct bt_ctf_event_class *event_class)
215 {
216 struct bt_ctf_event_class *writer_event_class = NULL;
217 const char *name;
218 struct bt_ctf_field_type *context;
219 int count, i, ret;
220
221 name = bt_ctf_event_class_get_name(event_class);
222 if (!name) {
223 fprintf(err, "[error] %s in %s:%d\n", __func__,
224 __FILE__, __LINE__);
225 goto end;
226 }
227
228 writer_event_class = bt_ctf_event_class_create(name);
229 if (!writer_event_class) {
230 fprintf(err, "[error] %s in %s:%d\n", __func__,
231 __FILE__, __LINE__);
232 goto end;
233 }
234
235 count = bt_ctf_event_class_get_attribute_count(event_class);
236 for (i = 0; i < count; i++) {
237 const char *attr_name;
238 struct bt_value *attr_value;
239 int ret;
240
241 attr_name = bt_ctf_event_class_get_attribute_name(event_class, i);
242 if (!attr_name) {
243 fprintf(err, "[error] %s in %s:%d\n", __func__,
244 __FILE__, __LINE__);
245 BT_PUT(writer_event_class);
246 goto end;
247 }
248 attr_value = bt_ctf_event_class_get_attribute_value(event_class, i);
249 if (!attr_value) {
250 fprintf(err, "[error] %s in %s:%d\n", __func__,
251 __FILE__, __LINE__);
252 BT_PUT(writer_event_class);
253 goto end;
254 }
255
256 ret = bt_ctf_event_class_set_attribute(writer_event_class,
257 attr_name, attr_value);
258 if (ret < 0) {
259 fprintf(err, "[error] %s in %s:%d\n", __func__,
260 __FILE__, __LINE__);
261 BT_PUT(writer_event_class);
262 goto end;
263 }
264 }
265
266 context = bt_ctf_event_class_get_context_type(event_class);
267 if (!context) {
268 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
269 __LINE__);
270 goto end;
271 }
272
273 ret = bt_ctf_event_class_set_context_type(writer_event_class, context);
274 if (ret < 0) {
275 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
276 __LINE__);
277 goto end;
278 }
279
280 count = bt_ctf_event_class_get_field_count(event_class);
281 for (i = 0; i < count; i++) {
282 const char *field_name;
283 struct bt_ctf_field_type *field_type;
284 int ret;
285
286 ret = bt_ctf_event_class_get_field(event_class, &field_name,
287 &field_type, i);
288 if (ret < 0) {
289 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, __LINE__);
290 BT_PUT(writer_event_class);
291 goto end;
292 }
293
294 ret = bt_ctf_event_class_add_field(writer_event_class, field_type,
295 field_name);
296 if (ret < 0) {
297 fprintf(err, "[error] Cannot add field %s\n", field_name);
298 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, __LINE__);
299 bt_put(field_type);
300 BT_PUT(writer_event_class);
301 goto end;
302 }
303 bt_put(field_type);
304 }
305
306 end:
307 return writer_event_class;
308 }
309
310 static
311 enum bt_component_status copy_event_classes(FILE *err,
312 struct bt_ctf_writer *writer,
313 struct bt_ctf_stream_class *stream_class,
314 struct bt_ctf_stream_class *writer_stream_class)
315 {
316 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
317 int count, i;
318
319 count = bt_ctf_stream_class_get_event_class_count(stream_class);
320 if (count < 0) {
321 fprintf(err, "[error] %s in %s:%d\n", __func__,
322 __FILE__, __LINE__);
323 goto end;
324 }
325
326 for (i = 0; i < count; i++) {
327 struct bt_ctf_event_class *event_class, *writer_event_class;
328 int int_ret;
329
330 event_class = bt_ctf_stream_class_get_event_class(
331 stream_class, i);
332 if (!event_class) {
333 fprintf(err, "[error] %s in %s:%d\n", __func__,
334 __FILE__, __LINE__);
335 ret = BT_COMPONENT_STATUS_ERROR;
336 bt_put(event_class);
337 goto end;
338 }
339 writer_event_class = copy_event_class(err, event_class);
340 if (!writer_event_class) {
341 fprintf(err, "[error] %s in %s:%d\n", __func__,
342 __FILE__, __LINE__);
343 ret = BT_COMPONENT_STATUS_ERROR;
344 bt_put(event_class);
345 goto end;
346 }
347 int_ret = bt_ctf_stream_class_add_event_class(writer_stream_class,
348 writer_event_class);
349 if (int_ret < 0) {
350 fprintf(err, "[error] Failed to add event class\n");
351 fprintf(err, "[error] %s in %s:%d\n", __func__,
352 __FILE__, __LINE__);
353 ret = BT_COMPONENT_STATUS_ERROR;
354 bt_put(event_class);
355 goto end;
356 }
357 bt_put(event_class);
358 }
359
360 end:
361 return ret;
362 }
363
364 static
365 enum bt_component_status copy_stream_class(FILE *err,
366 struct bt_ctf_writer *writer,
367 struct bt_ctf_stream_class *stream_class,
368 struct bt_ctf_stream_class *writer_stream_class)
369 {
370 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
371 struct bt_ctf_field_type *type;
372 int ret_int;
373 struct bt_ctf_clock *writer_clock;
374
375 writer_clock = bt_ctf_clock_create("monotonic");
376 if (!writer_clock) {
377 ret = BT_COMPONENT_STATUS_ERROR;
378 fprintf(err, "[error] Failed to create clock\n");
379 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
380 __LINE__);
381 goto end;
382 }
383
384 tmp_clock(writer, writer_stream_class, writer_clock);
385
386 /*
387 * FIXME: waiting for the clock to work
388 *
389 struct bt_ctf_clock *clock;
390 clock = bt_ctf_stream_class_get_clock(stream_class);
391 if (!clock) {
392 ret = BT_COMPONENT_STATUS_ERROR;
393 goto end;
394 }
395 ret = copy_clock(err, writer, writer_stream_class, clock, writer_clock);
396 if (ret != BT_COMPONENT_STATUS_OK) {
397 goto end_put_clock;
398 }
399 */
400
401 type = bt_ctf_stream_class_get_packet_context_type(stream_class);
402 if (!type) {
403 ret = BT_COMPONENT_STATUS_ERROR;
404 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
405 __LINE__);
406 goto end_put_clock;
407 }
408
409 ret_int = bt_ctf_stream_class_set_packet_context_type(
410 writer_stream_class, type);
411 if (ret_int < 0) {
412 ret = BT_COMPONENT_STATUS_ERROR;
413 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
414 __LINE__);
415 goto end_put_clock;
416 }
417
418 type = bt_ctf_stream_class_get_event_header_type(stream_class);
419 if (!type) {
420 ret = BT_COMPONENT_STATUS_ERROR;
421 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
422 __LINE__);
423 goto end_put_clock;
424 }
425
426 ret_int = bt_ctf_stream_class_set_event_header_type(
427 writer_stream_class, type);
428 if (ret_int < 0) {
429 ret = BT_COMPONENT_STATUS_ERROR;
430 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
431 __LINE__);
432 goto end_put_clock;
433 }
434
435 type = bt_ctf_stream_class_get_event_context_type(stream_class);
436 if (!type) {
437 ret = BT_COMPONENT_STATUS_ERROR;
438 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
439 __LINE__);
440 goto end_put_clock;
441 }
442
443 ret_int = bt_ctf_stream_class_set_event_context_type(
444 writer_stream_class, type);
445 if (ret_int < 0) {
446 ret = BT_COMPONENT_STATUS_ERROR;
447 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
448 __LINE__);
449 goto end_put_clock;
450 }
451
452 ret = copy_event_classes(err, writer, stream_class, writer_stream_class);
453 if (ret != BT_COMPONENT_STATUS_OK) {
454 fprintf(err, "[error] Failed to copy event classes\n");
455 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
456 __LINE__);
457 goto end_put_clock;
458 }
459
460 end_put_clock:
461 // bt_put(clock);
462 end:
463 return ret;
464 }
465
466 static
467 enum bt_component_status copy_trace(FILE *err, struct bt_ctf_writer *ctf_writer,
468 struct bt_ctf_trace *trace)
469 {
470 struct bt_ctf_trace *writer_trace;
471 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
472 int field_count, i, int_ret;
473 struct bt_ctf_field_type *header_type;
474
475 writer_trace = bt_ctf_writer_get_trace(ctf_writer);
476 if (!writer_trace) {
477 ret = BT_COMPONENT_STATUS_ERROR;
478 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
479 __LINE__);
480 goto end;
481 }
482
483 field_count = bt_ctf_trace_get_environment_field_count(trace);
484 for (i = 0; i < field_count; i++) {
485 int ret_int;
486 const char *name;
487 struct bt_value *value;
488
489 name = bt_ctf_trace_get_environment_field_name(trace, i);
490 if (!name) {
491 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
492 __LINE__);
493 ret = BT_COMPONENT_STATUS_ERROR;
494 goto end_put_writer_trace;
495 }
496 value = bt_ctf_trace_get_environment_field_value(trace, i);
497 if (!value) {
498 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
499 __LINE__);
500 ret = BT_COMPONENT_STATUS_ERROR;
501 goto end_put_writer_trace;
502 }
503
504 ret_int = bt_ctf_trace_set_environment_field(writer_trace,
505 name, value);
506 if (ret_int < 0) {
507 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
508 __LINE__);
509 fprintf(err, "[error] Unable to set environment field %s\n",
510 name);
511 ret = BT_COMPONENT_STATUS_ERROR;
512 goto end_put_writer_trace;
513 }
514 }
515
516 header_type = bt_ctf_trace_get_packet_header_type(writer_trace);
517 if (!header_type) {
518 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, __LINE__);
519 ret = BT_COMPONENT_STATUS_ERROR;
520 goto end_put_writer_trace;
521 }
522
523 int_ret = bt_ctf_trace_set_packet_header_type(writer_trace, header_type);
524 if (int_ret < 0) {
525 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, __LINE__);
526 ret = BT_COMPONENT_STATUS_ERROR;
527 goto end_put_header_type;
528 }
529
530 end_put_header_type:
531 bt_put(header_type);
532 end_put_writer_trace:
533 bt_put(writer_trace);
534 end:
535 return ret;
536 }
537
538 static
539 struct bt_ctf_stream_class *insert_new_stream_class(
540 struct writer_component *writer_component,
541 struct bt_ctf_writer *ctf_writer,
542 struct bt_ctf_stream_class *stream_class)
543 {
544 struct bt_ctf_stream_class *writer_stream_class;
545 const char *name = bt_ctf_stream_class_get_name(stream_class);
546 enum bt_component_status ret;
547
548 if (strlen(name) == 0) {
549 name = NULL;
550 }
551
552 writer_stream_class = bt_ctf_stream_class_create(name);
553 if (!writer_stream_class) {
554 fprintf(writer_component->err, "[error] %s in %s:%d\n",
555 __func__, __FILE__, __LINE__);
556 goto end;
557 }
558
559 ret = copy_stream_class(writer_component->err,
560 ctf_writer, stream_class, writer_stream_class);
561 if (ret != BT_COMPONENT_STATUS_OK) {
562 fprintf(writer_component->err, "[error] Failed to copy stream class\n");
563 fprintf(writer_component->err, "[error] %s in %s:%d\n",
564 __func__, __FILE__, __LINE__);
565 BT_PUT(writer_stream_class);
566 goto end;
567 }
568 g_hash_table_insert(writer_component->stream_class_map,
569 (gpointer) stream_class, writer_stream_class);
570
571 end:
572 return writer_stream_class;
573 }
574
575 static
576 struct bt_ctf_stream *insert_new_stream(
577 struct writer_component *writer_component,
578 struct bt_ctf_writer *ctf_writer,
579 struct bt_ctf_stream_class *stream_class,
580 struct bt_ctf_stream *stream)
581 {
582 struct bt_ctf_stream *writer_stream;
583 struct bt_ctf_stream_class *writer_stream_class;
584
585 writer_stream_class = g_hash_table_lookup(
586 writer_component->stream_class_map,
587 (gpointer) stream_class);
588 if (writer_stream_class) {
589 if (!bt_get(writer_stream_class)) {
590 writer_stream = NULL;
591 fprintf(writer_component->err, "[error] %s in %s:%d\n",
592 __func__, __FILE__, __LINE__);
593 goto end;
594 }
595 } else {
596 writer_stream_class = insert_new_stream_class(
597 writer_component, ctf_writer, stream_class);
598 if (!writer_stream_class) {
599 writer_stream = NULL;
600 fprintf(writer_component->err, "[error] %s in %s:%d\n",
601 __func__, __FILE__, __LINE__);
602 goto end_put;
603 }
604 }
605
606 writer_stream = bt_ctf_writer_create_stream(ctf_writer,
607 writer_stream_class);
608 if (!writer_stream) {
609 fprintf(writer_component->err, "[error] %s in %s:%d\n",
610 __func__, __FILE__, __LINE__);
611 goto end_put;
612 }
613
614 g_hash_table_insert(writer_component->stream_map, (gpointer) stream,
615 writer_stream);
616
617 bt_ctf_writer_flush_metadata(ctf_writer);
618
619 end_put:
620 bt_put(writer_stream_class);
621 end:
622 return writer_stream;
623 }
624
625 static
626 struct bt_ctf_stream *lookup_stream(struct writer_component *writer_component,
627 struct bt_ctf_stream *stream)
628 {
629 return (struct bt_ctf_stream *) g_hash_table_lookup(
630 writer_component->stream_map,
631 (gpointer) stream);
632 }
633
634 static
635 struct bt_ctf_event_class *get_event_class(struct writer_component *writer_component,
636 struct bt_ctf_stream_class *writer_stream_class,
637 struct bt_ctf_event_class *event_class)
638 {
639 return bt_ctf_stream_class_get_event_class_by_name(writer_stream_class,
640 bt_ctf_event_class_get_name(event_class));
641 }
642
643 struct bt_ctf_writer *insert_new_writer(
644 struct writer_component *writer_component,
645 struct bt_ctf_trace *trace)
646 {
647 struct bt_ctf_writer *ctf_writer;
648 char trace_name[PATH_MAX];
649 enum bt_component_status ret;
650
651 snprintf(trace_name, PATH_MAX, "%s/%s_%03d",
652 writer_component->base_path,
653 writer_component->trace_name_base,
654 writer_component->trace_id++);
655 printf_verbose("CTF-Writer creating trace in %s\n", trace_name);
656
657 ctf_writer = bt_ctf_writer_create(trace_name);
658 if (!ctf_writer) {
659 fprintf(writer_component->err, "[error] %s in %s:%d\n",
660 __func__, __FILE__, __LINE__);
661 goto end;
662 }
663
664 ret = copy_trace(writer_component->err, ctf_writer, trace);
665 if (ret != BT_COMPONENT_STATUS_OK) {
666 fprintf(writer_component->err, "[error] Failed to copy trace\n");
667 fprintf(writer_component->err, "[error] %s in %s:%d\n",
668 __func__, __FILE__, __LINE__);
669 BT_PUT(ctf_writer);
670 goto end;
671 }
672
673 g_hash_table_insert(writer_component->trace_map, (gpointer) trace,
674 ctf_writer);
675
676 end:
677 return ctf_writer;
678 }
679
680 static
681 struct bt_ctf_writer *get_writer(struct writer_component *writer_component,
682 struct bt_ctf_stream_class *stream_class)
683 {
684 struct bt_ctf_trace *trace;
685 struct bt_ctf_writer *ctf_writer;
686
687 trace = bt_ctf_stream_class_get_trace(stream_class);
688 if (!trace) {
689 ctf_writer = NULL;
690 fprintf(writer_component->err, "[error] %s in %s:%d\n",
691 __func__, __FILE__, __LINE__);
692 goto end;
693 }
694
695 ctf_writer = g_hash_table_lookup(writer_component->trace_map,
696 (gpointer) trace);
697 if (ctf_writer) {
698 if (!bt_get(ctf_writer)) {
699 ctf_writer = NULL;
700 fprintf(writer_component->err, "[error] %s in %s:%d\n",
701 __func__, __FILE__, __LINE__);
702 goto end;
703 }
704 } else {
705 ctf_writer = insert_new_writer(writer_component, trace);
706 }
707 bt_put(trace);
708
709 end:
710 return ctf_writer;
711 }
712
713 static
714 struct bt_ctf_stream *get_writer_stream(
715 struct writer_component *writer_component,
716 struct bt_ctf_packet *packet, struct bt_ctf_stream *stream)
717 {
718 struct bt_ctf_stream_class *stream_class;
719 struct bt_ctf_writer *ctf_writer;
720 struct bt_ctf_stream *writer_stream;
721
722 stream_class = bt_ctf_stream_get_class(stream);
723 if (!stream_class) {
724 writer_stream = NULL;
725 fprintf(writer_component->err, "[error] %s in %s:%d\n",
726 __func__, __FILE__, __LINE__);
727 goto end;
728 }
729
730 ctf_writer = get_writer(writer_component, stream_class);
731 if (!ctf_writer) {
732 writer_stream = NULL;
733 fprintf(writer_component->err, "[error] %s in %s:%d\n",
734 __func__, __FILE__, __LINE__);
735 goto end_put_stream_class;
736 }
737
738 writer_stream = lookup_stream(writer_component, stream);
739
740 if (writer_stream) {
741 if (!bt_get(writer_stream)) {
742 writer_stream = NULL;
743 fprintf(writer_component->err, "[error] %s in %s:%d\n",
744 __func__, __FILE__, __LINE__);
745 goto end_put_stream_class;
746 }
747 } else {
748 writer_stream = insert_new_stream(writer_component, ctf_writer,
749 stream_class, stream);
750 }
751
752 bt_put(ctf_writer);
753 end_put_stream_class:
754 bt_put(stream_class);
755 end:
756 return writer_stream;
757 }
758
759 BT_HIDDEN
760 enum bt_component_status writer_new_packet(
761 struct writer_component *writer_component,
762 struct bt_ctf_packet *packet)
763 {
764 struct bt_ctf_stream *stream, *writer_stream;
765 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
766
767 stream = bt_ctf_packet_get_stream(packet);
768 if (!stream) {
769 ret = BT_COMPONENT_STATUS_ERROR;
770 fprintf(writer_component->err, "[error] %s in %s:%d\n",
771 __func__, __FILE__, __LINE__);
772 goto end;
773 }
774
775 /* TODO: copy values for event discarded and packet_seq_num */
776 writer_stream = get_writer_stream(writer_component, packet, stream);
777 if (!writer_stream) {
778 ret = BT_COMPONENT_STATUS_ERROR;
779 fprintf(writer_component->err, "[error] %s in %s:%d\n",
780 __func__, __FILE__, __LINE__);
781 goto end_put;
782 }
783
784 bt_put(writer_stream);
785
786 end_put:
787 bt_put(stream);
788 end:
789 return ret;
790 }
791
792 static
793 enum bt_component_status copy_packet_context_field(FILE *err,
794 struct bt_ctf_field *field, const char *field_name,
795 struct bt_ctf_field *writer_packet_context,
796 struct bt_ctf_field_type *writer_packet_context_type)
797 {
798 enum bt_component_status ret;
799 struct bt_ctf_field *writer_field;
800 int int_ret;
801 uint64_t value;
802
803 /*
804 * TODO: handle the special case of the first/last packet that might
805 * be trimmed. In these cases, the timestamp_begin/end need to be
806 * explicitely set to the first/last event timestamps.
807 */
808
809 writer_field = bt_ctf_field_structure_get_field(writer_packet_context,
810 field_name);
811 if (!writer_field) {
812 ret = BT_COMPONENT_STATUS_ERROR;
813 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
814 __LINE__);
815 goto end;
816 }
817
818 int_ret = bt_ctf_field_unsigned_integer_get_value(field, &value);
819 if (int_ret < 0) {
820 fprintf(err, "[error] Wrong packet_context field type\n");
821 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
822 __LINE__);
823 ret = BT_COMPONENT_STATUS_ERROR;
824 goto end_put_writer_field;
825 }
826
827 int_ret = bt_ctf_field_unsigned_integer_set_value(writer_field, value);
828 if (int_ret < 0) {
829 ret = BT_COMPONENT_STATUS_ERROR;
830 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
831 __LINE__);
832 goto end_put_writer_field;
833 }
834
835 ret = BT_COMPONENT_STATUS_OK;
836
837 end_put_writer_field:
838 bt_put(writer_field);
839 end:
840 return ret;
841 }
842
843 static
844 enum bt_component_status copy_packet_context(FILE *err,
845 struct bt_ctf_packet *packet,
846 struct bt_ctf_stream *writer_stream)
847 {
848 enum bt_component_status ret;
849 struct bt_ctf_field *packet_context, *writer_packet_context;
850 struct bt_ctf_field_type *struct_type, *writer_packet_context_type;
851 struct bt_ctf_stream_class *writer_stream_class;
852 int nr_fields, i, int_ret;
853
854 packet_context = bt_ctf_packet_get_context(packet);
855 if (!packet_context) {
856 ret = BT_COMPONENT_STATUS_ERROR;
857 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
858 __LINE__);
859 goto end;
860 }
861
862 writer_stream_class = bt_ctf_stream_get_class(writer_stream);
863 if (!writer_stream_class) {
864 ret = BT_COMPONENT_STATUS_ERROR;
865 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
866 __LINE__);
867 goto end_put_packet_context;
868 }
869
870 writer_packet_context_type = bt_ctf_stream_class_get_packet_context_type(
871 writer_stream_class);
872 if (!writer_packet_context_type) {
873 ret = BT_COMPONENT_STATUS_ERROR;
874 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
875 __LINE__);
876 goto end_put_writer_stream_class;
877 }
878
879 struct_type = bt_ctf_field_get_type(packet_context);
880 if (!struct_type) {
881 ret = BT_COMPONENT_STATUS_ERROR;
882 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
883 __LINE__);
884 goto end_put_writer_packet_context_type;
885 }
886
887 writer_packet_context = bt_ctf_field_create(writer_packet_context_type);
888 if (!writer_packet_context) {
889 ret = BT_COMPONENT_STATUS_ERROR;
890 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
891 __LINE__);
892 goto end_put_struct_type;
893 }
894
895 nr_fields = bt_ctf_field_type_structure_get_field_count(struct_type);
896 for (i = 0; i < nr_fields; i++) {
897 struct bt_ctf_field *field;
898 struct bt_ctf_field_type *field_type;
899 const char *field_name;
900
901 field = bt_ctf_field_structure_get_field_by_index(
902 packet_context, i);
903 if (!field) {
904 ret = BT_COMPONENT_STATUS_ERROR;
905 fprintf(err, "[error] %s in %s:%d\n", __func__,
906 __FILE__, __LINE__);
907 goto end_put_writer_packet_context;
908 }
909 if (bt_ctf_field_type_structure_get_field(struct_type,
910 &field_name, &field_type, i) < 0) {
911 ret = BT_COMPONENT_STATUS_ERROR;
912 bt_put(field);
913 fprintf(err, "[error] %s in %s:%d\n", __func__,
914 __FILE__, __LINE__);
915 goto end_put_writer_packet_context;
916 }
917
918 if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_TYPE_ID_INTEGER) {
919 fprintf(err, "[error] Unexpected packet context field type\n");
920 bt_put(field);
921 ret = BT_COMPONENT_STATUS_ERROR;
922 goto end_put_writer_packet_context;
923 }
924
925 ret = copy_packet_context_field(err, field, field_name,
926 writer_packet_context, writer_packet_context_type);
927 bt_put(field_type);
928 bt_put(field);
929 if (ret != BT_COMPONENT_STATUS_OK) {
930 fprintf(err, "[error] %s in %s:%d\n", __func__,
931 __FILE__, __LINE__);
932 goto end_put_writer_packet_context;
933 }
934 }
935
936 int_ret = bt_ctf_stream_set_packet_context(writer_stream,
937 writer_packet_context);
938 if (int_ret < 0) {
939 ret = BT_COMPONENT_STATUS_ERROR;
940 goto end_put_writer_packet_context;
941 }
942
943 end_put_writer_packet_context:
944 bt_put(writer_packet_context);
945 end_put_struct_type:
946 bt_put(struct_type);
947 end_put_writer_packet_context_type:
948 bt_put(writer_packet_context_type);
949 end_put_writer_stream_class:
950 bt_put(writer_stream_class);
951 end_put_packet_context:
952 bt_put(packet_context);
953 end:
954 return ret;
955 }
956
957 BT_HIDDEN
958 enum bt_component_status writer_close_packet(
959 struct writer_component *writer_component,
960 struct bt_ctf_packet *packet)
961 {
962 struct bt_ctf_stream *stream, *writer_stream;
963 enum bt_component_status ret;
964
965 stream = bt_ctf_packet_get_stream(packet);
966 if (!stream) {
967 ret = BT_COMPONENT_STATUS_ERROR;
968 fprintf(writer_component->err, "[error] %s in %s:%d\n",
969 __func__, __FILE__, __LINE__);
970 goto end;
971 }
972
973 writer_stream = lookup_stream(writer_component, stream);
974 if (!writer_stream) {
975 ret = BT_COMPONENT_STATUS_ERROR;
976 fprintf(writer_component->err, "[error] %s in %s:%d\n",
977 __func__, __FILE__, __LINE__);
978 goto end_put;
979 }
980
981 if (!bt_get(writer_stream)) {
982 fprintf(writer_component->err,
983 "[error] Failed to get reference on writer stream\n");
984 fprintf(writer_component->err, "[error] %s in %s:%d\n",
985 __func__, __FILE__, __LINE__);
986 ret = BT_COMPONENT_STATUS_ERROR;
987 goto end_put;
988 }
989
990 ret = copy_packet_context(writer_component->err, packet, writer_stream);
991 if (ret != BT_COMPONENT_STATUS_OK) {
992 ret = BT_COMPONENT_STATUS_ERROR;
993 fprintf(writer_component->err, "[error] %s in %s:%d\n",
994 __func__, __FILE__, __LINE__);
995 goto end_put;
996 }
997
998 ret = bt_ctf_stream_flush(writer_stream);
999 if (ret < 0) {
1000 fprintf(writer_component->err,
1001 "[error] Failed to flush packet\n");
1002 ret = BT_COMPONENT_STATUS_ERROR;
1003 }
1004
1005 ret = BT_COMPONENT_STATUS_OK;
1006
1007 bt_put(writer_stream);
1008
1009 end_put:
1010 bt_put(stream);
1011 end:
1012 return ret;
1013 }
1014
1015 static
1016 struct bt_ctf_event *copy_event(FILE *err, struct bt_ctf_event *event,
1017 struct bt_ctf_event_class *writer_event_class)
1018 {
1019 struct bt_ctf_event *writer_event;
1020 struct bt_ctf_field *field;
1021 int ret;
1022
1023 writer_event = bt_ctf_event_create(writer_event_class);
1024 if (!writer_event) {
1025 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, __LINE__);
1026 goto end;
1027 }
1028
1029 field = bt_ctf_event_get_header(event);
1030 ret = bt_ctf_event_set_header(writer_event,
1031 bt_ctf_field_copy(field));
1032 if (ret < 0) {
1033 BT_PUT(writer_event);
1034 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, __LINE__);
1035 goto end;
1036 }
1037
1038 field = bt_ctf_event_get_stream_event_context(event);
1039 ret = bt_ctf_event_set_stream_event_context(writer_event,
1040 bt_ctf_field_copy(field));
1041 if (ret < 0) {
1042 BT_PUT(writer_event);
1043 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, __LINE__);
1044 goto end;
1045 }
1046
1047 field = bt_ctf_event_get_event_context(event);
1048 ret = bt_ctf_event_set_event_context(writer_event,
1049 bt_ctf_field_copy(field));
1050 if (ret < 0) {
1051 BT_PUT(writer_event);
1052 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, __LINE__);
1053 goto end;
1054 }
1055
1056 field = bt_ctf_event_get_payload_field(event);
1057 ret = bt_ctf_event_set_payload_field(writer_event,
1058 bt_ctf_field_copy(field));
1059 if (ret < 0) {
1060 BT_PUT(writer_event);
1061 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, __LINE__);
1062 goto end;
1063 }
1064
1065 end:
1066 return writer_event;
1067 }
1068
1069 BT_HIDDEN
1070 enum bt_component_status writer_output_event(
1071 struct writer_component *writer_component,
1072 struct bt_ctf_event *event)
1073 {
1074 enum bt_component_status ret;
1075 struct bt_ctf_event_class *event_class, *writer_event_class;
1076 struct bt_ctf_stream *stream, *writer_stream;
1077 struct bt_ctf_stream_class *stream_class, *writer_stream_class;
1078 struct bt_ctf_event *writer_event;
1079 const char *event_name;
1080 int int_ret;
1081
1082 event_class = bt_ctf_event_get_class(event);
1083 if (!event_class) {
1084 ret = BT_COMPONENT_STATUS_ERROR;
1085 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
1086 __FILE__, __LINE__);
1087 goto end;
1088 }
1089
1090 event_name = bt_ctf_event_class_get_name(event_class);
1091 if (!event_name) {
1092 ret = BT_COMPONENT_STATUS_ERROR;
1093 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
1094 __FILE__, __LINE__);
1095 goto end_put_event_class;
1096 }
1097 // printf("%s\n", event_name);
1098
1099 stream = bt_ctf_event_get_stream(event);
1100 if (!stream) {
1101 ret = BT_COMPONENT_STATUS_ERROR;
1102 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
1103 __FILE__, __LINE__);
1104 goto end_put_event_class;
1105 }
1106
1107 writer_stream = lookup_stream(writer_component, stream);
1108 if (!writer_stream || !bt_get(writer_stream)) {
1109 ret = BT_COMPONENT_STATUS_ERROR;
1110 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
1111 __FILE__, __LINE__);
1112 goto end_put_stream;
1113 }
1114
1115 stream_class = bt_ctf_event_class_get_stream_class(event_class);
1116 if (!stream_class) {
1117 ret = BT_COMPONENT_STATUS_ERROR;
1118 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
1119 __FILE__, __LINE__);
1120 goto end_put_writer_stream;
1121 }
1122
1123 writer_stream_class = g_hash_table_lookup(
1124 writer_component->stream_class_map,
1125 (gpointer) stream_class);
1126 if (!writer_stream_class || !bt_get(writer_stream_class)) {
1127 ret = BT_COMPONENT_STATUS_ERROR;
1128 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
1129 __FILE__, __LINE__);
1130 goto end_put_stream_class;
1131 }
1132
1133 writer_event_class = get_event_class(writer_component,
1134 writer_stream_class, event_class);
1135 if (!writer_event_class) {
1136 ret = BT_COMPONENT_STATUS_ERROR;
1137 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
1138 __FILE__, __LINE__);
1139 goto end_put_writer_stream_class;
1140 }
1141
1142 writer_event = copy_event(writer_component->err, event, writer_event_class);
1143 if (!writer_event) {
1144 ret = BT_COMPONENT_STATUS_ERROR;
1145 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
1146 __FILE__, __LINE__);
1147 fprintf(writer_component->err, "[error] Failed to copy event %s\n",
1148 bt_ctf_event_class_get_name(writer_event_class));
1149 goto end_put_writer_event_class;
1150 }
1151
1152 int_ret = bt_ctf_stream_append_event(writer_stream, writer_event);
1153 if (int_ret < 0) {
1154 ret = BT_COMPONENT_STATUS_ERROR;
1155 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
1156 __FILE__, __LINE__);
1157 fprintf(writer_component->err, "[error] Failed to append event %s\n",
1158 bt_ctf_event_class_get_name(writer_event_class));
1159 goto end_put_writer_event;
1160 }
1161
1162 ret = BT_COMPONENT_STATUS_OK;
1163
1164 end_put_writer_event:
1165 bt_put(writer_event);
1166 end_put_writer_event_class:
1167 bt_put(writer_event_class);
1168 end_put_writer_stream_class:
1169 bt_put(writer_stream_class);
1170 end_put_stream_class:
1171 bt_put(stream_class);
1172 end_put_writer_stream:
1173 bt_put(writer_stream);
1174 end_put_stream:
1175 bt_put(stream);
1176 end_put_event_class:
1177 bt_put(event_class);
1178 end:
1179 return ret;
1180 }
This page took 0.084859 seconds and 4 git commands to generate.