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