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