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