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