4 * Babeltrace CTF Writer Output Plugin Event Handling
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
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:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
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
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>
40 #include <ctfcopytrace.h>
45 void trace_is_static_listener(struct bt_ctf_trace
*trace
, void *data
)
51 struct bt_ctf_stream_class
*insert_new_stream_class(
52 struct writer_component
*writer_component
,
53 struct bt_ctf_writer
*ctf_writer
,
54 struct bt_ctf_stream_class
*stream_class
)
56 struct bt_ctf_stream_class
*writer_stream_class
= NULL
;
57 struct bt_ctf_trace
*trace
= NULL
, *writer_trace
= NULL
;
58 enum bt_component_status ret
;
60 trace
= bt_ctf_stream_class_get_trace(stream_class
);
62 fprintf(writer_component
->err
,
63 "[error] %s in %s:%d\n", __func__
, __FILE__
,
68 writer_trace
= bt_ctf_writer_get_trace(ctf_writer
);
70 fprintf(writer_component
->err
,
71 "[error] %s in %s:%d\n", __func__
, __FILE__
,
76 ret
= ctf_copy_clock_classes(writer_component
->err
, writer_trace
,
77 writer_stream_class
, trace
);
78 if (ret
!= BT_COMPONENT_STATUS_OK
) {
79 fprintf(writer_component
->err
,
80 "[error] %s in %s:%d\n", __func__
, __FILE__
,
85 writer_stream_class
= ctf_copy_stream_class(writer_component
->err
,
86 stream_class
, writer_trace
, true);
87 if (!writer_stream_class
) {
88 fprintf(writer_component
->err
, "[error] Failed to copy stream class\n");
89 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
90 __func__
, __FILE__
, __LINE__
);
94 g_hash_table_insert(writer_component
->stream_class_map
,
95 (gpointer
) stream_class
, writer_stream_class
);
100 BT_PUT(writer_stream_class
);
102 bt_put(writer_trace
);
104 return writer_stream_class
;
108 struct bt_ctf_stream
*insert_new_stream(
109 struct writer_component
*writer_component
,
110 struct bt_ctf_writer
*ctf_writer
,
111 struct bt_ctf_stream_class
*stream_class
,
112 struct bt_ctf_stream
*stream
)
114 struct bt_ctf_stream
*writer_stream
= NULL
;
115 struct bt_ctf_stream_class
*writer_stream_class
= NULL
;
117 writer_stream_class
= g_hash_table_lookup(
118 writer_component
->stream_class_map
,
119 (gpointer
) stream_class
);
120 if (!writer_stream_class
) {
121 writer_stream_class
= insert_new_stream_class(
122 writer_component
, ctf_writer
, stream_class
);
123 if (!writer_stream_class
) {
124 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
125 __func__
, __FILE__
, __LINE__
);
129 bt_get(writer_stream_class
);
131 writer_stream
= bt_ctf_writer_create_stream(ctf_writer
,
132 writer_stream_class
);
133 if (!writer_stream
) {
134 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
135 __func__
, __FILE__
, __LINE__
);
139 g_hash_table_insert(writer_component
->stream_map
, (gpointer
) stream
,
145 BT_PUT(writer_stream
);
147 bt_put(writer_stream_class
);
148 return writer_stream
;
152 struct bt_ctf_stream
*lookup_stream(struct writer_component
*writer_component
,
153 struct bt_ctf_stream
*stream
)
155 return (struct bt_ctf_stream
*) g_hash_table_lookup(
156 writer_component
->stream_map
,
161 struct bt_ctf_event_class
*get_event_class(struct writer_component
*writer_component
,
162 struct bt_ctf_stream_class
*writer_stream_class
,
163 struct bt_ctf_event_class
*event_class
)
165 return bt_ctf_stream_class_get_event_class_by_id(writer_stream_class
,
166 bt_ctf_event_class_get_id(event_class
));
169 struct fs_writer
*insert_new_writer(
170 struct writer_component
*writer_component
,
171 struct bt_ctf_trace
*trace
)
173 struct bt_ctf_writer
*ctf_writer
= NULL
;
174 struct bt_ctf_trace
*writer_trace
= NULL
;
175 char trace_name
[PATH_MAX
];
176 enum bt_component_status ret
;
177 struct fs_writer
*fs_writer
;
179 /* FIXME: replace with trace name when it will work. */
180 snprintf(trace_name
, PATH_MAX
, "%s/%s_%03d",
181 writer_component
->base_path
->str
,
182 writer_component
->trace_name_base
->str
,
183 writer_component
->trace_id
++);
184 printf_verbose("CTF-Writer creating trace in %s\n", trace_name
);
186 ctf_writer
= bt_ctf_writer_create(trace_name
);
188 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
189 __func__
, __FILE__
, __LINE__
);
193 writer_trace
= bt_ctf_writer_get_trace(ctf_writer
);
195 fprintf(writer_component
->err
,
196 "[error] %s in %s:%d\n", __func__
, __FILE__
,
201 ret
= ctf_copy_trace(writer_component
->err
, trace
, writer_trace
);
202 if (ret
!= BT_COMPONENT_STATUS_OK
) {
203 fprintf(writer_component
->err
, "[error] Failed to copy trace\n");
204 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
205 __func__
, __FILE__
, __LINE__
);
210 fs_writer
= g_new0(struct fs_writer
, 1);
212 fprintf(writer_component
->err
,
213 "[error] %s in %s:%d\n", __func__
, __FILE__
,
217 fs_writer
->writer
= ctf_writer
;
218 fs_writer
->writer_trace
= writer_trace
;
219 BT_PUT(writer_trace
);
220 if (bt_ctf_trace_is_static(trace
)) {
221 fs_writer
->trace_static
= 1;
222 fs_writer
->static_listener_id
= -1;
224 ret
= bt_ctf_trace_add_is_static_listener(trace
,
225 trace_is_static_listener
, &fs_writer
->trace_static
);
227 fprintf(writer_component
->err
,
228 "[error] %s in %s:%d\n", __func__
, __FILE__
,
234 fs_writer
->static_listener_id
= ret
;
237 g_hash_table_insert(writer_component
->trace_map
, (gpointer
) trace
,
243 bt_put(writer_trace
);
250 struct fs_writer
*get_fs_writer(struct writer_component
*writer_component
,
251 struct bt_ctf_stream_class
*stream_class
)
253 struct bt_ctf_trace
*trace
= NULL
;
254 struct fs_writer
*fs_writer
;
256 trace
= bt_ctf_stream_class_get_trace(stream_class
);
258 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
259 __func__
, __FILE__
, __LINE__
);
263 fs_writer
= g_hash_table_lookup(writer_component
->trace_map
,
266 fs_writer
= insert_new_writer(writer_component
, trace
);
278 struct bt_ctf_stream
*get_writer_stream(
279 struct writer_component
*writer_component
,
280 struct bt_ctf_packet
*packet
, struct bt_ctf_stream
*stream
)
282 struct bt_ctf_stream
*writer_stream
= NULL
;
284 writer_stream
= lookup_stream(writer_component
, stream
);
285 if (!writer_stream
) {
286 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
287 __func__
, __FILE__
, __LINE__
);
290 bt_get(writer_stream
);
295 BT_PUT(writer_stream
);
297 return writer_stream
;
301 enum bt_component_status
writer_close(
302 struct writer_component
*writer_component
,
303 struct fs_writer
*fs_writer
,
304 struct bt_ctf_trace
*trace
)
306 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
308 if (fs_writer
->static_listener_id
> 0) {
309 bt_ctf_trace_remove_is_static_listener(trace
,
310 fs_writer
->static_listener_id
);
312 g_hash_table_remove(writer_component
->trace_map
, trace
);
317 enum bt_component_status
writer_stream_begin(
318 struct writer_component
*writer_component
,
319 struct bt_ctf_stream
*stream
)
321 struct bt_ctf_stream_class
*stream_class
= NULL
;
322 struct fs_writer
*fs_writer
;
323 struct bt_ctf_writer
*ctf_writer
= NULL
;
324 struct bt_ctf_stream
*writer_stream
= NULL
;
325 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
327 stream_class
= bt_ctf_stream_get_class(stream
);
329 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
330 __func__
, __FILE__
, __LINE__
);
334 fs_writer
= get_fs_writer(writer_component
, stream_class
);
336 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
337 __func__
, __FILE__
, __LINE__
);
340 ctf_writer
= bt_get(fs_writer
->writer
);
341 writer_stream
= insert_new_stream(writer_component
, ctf_writer
,
342 stream_class
, stream
);
343 if (!writer_stream
) {
344 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
345 __func__
, __FILE__
, __LINE__
);
348 fs_writer
->active_streams
++;
353 ret
= BT_COMPONENT_STATUS_ERROR
;
356 bt_put(stream_class
);
361 enum bt_component_status
writer_stream_end(
362 struct writer_component
*writer_component
,
363 struct bt_ctf_stream
*stream
)
365 struct bt_ctf_stream_class
*stream_class
= NULL
;
366 struct fs_writer
*fs_writer
;
367 struct bt_ctf_trace
*trace
= NULL
;
368 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
370 g_hash_table_remove(writer_component
->stream_map
, stream
);
372 stream_class
= bt_ctf_stream_get_class(stream
);
374 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
375 __func__
, __FILE__
, __LINE__
);
379 fs_writer
= get_fs_writer(writer_component
, stream_class
);
381 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
382 __func__
, __FILE__
, __LINE__
);
386 assert(fs_writer
->active_streams
> 0);
387 fs_writer
->active_streams
--;
388 if (fs_writer
->active_streams
== 0 && fs_writer
->trace_static
) {
389 trace
= bt_ctf_stream_class_get_trace(stream_class
);
391 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
392 __func__
, __FILE__
, __LINE__
);
395 ret
= writer_close(writer_component
, fs_writer
, trace
);
401 ret
= BT_COMPONENT_STATUS_ERROR
;
404 BT_PUT(stream_class
);
409 enum bt_component_status
writer_new_packet(
410 struct writer_component
*writer_component
,
411 struct bt_ctf_packet
*packet
)
413 struct bt_ctf_stream
*stream
= NULL
, *writer_stream
= NULL
;
414 struct bt_ctf_field
*writer_packet_context
= NULL
;
415 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
418 stream
= bt_ctf_packet_get_stream(packet
);
420 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
421 __func__
, __FILE__
, __LINE__
);
425 writer_stream
= get_writer_stream(writer_component
, packet
, stream
);
426 if (!writer_stream
) {
427 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
428 __func__
, __FILE__
, __LINE__
);
433 writer_packet_context
= ctf_copy_packet_context(writer_component
->err
,
434 packet
, writer_stream
, 1);
435 if (!writer_packet_context
) {
436 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
437 __func__
, __FILE__
, __LINE__
);
441 int_ret
= bt_ctf_stream_set_packet_context(writer_stream
,
442 writer_packet_context
);
444 fprintf(writer_component
->err
, "[error] %s in %s:%d\n", __func__
,
448 BT_PUT(writer_stream
);
449 BT_PUT(writer_packet_context
);
454 ret
= BT_COMPONENT_STATUS_ERROR
;
456 bt_put(writer_stream
);
457 bt_put(writer_packet_context
);
463 enum bt_component_status
writer_close_packet(
464 struct writer_component
*writer_component
,
465 struct bt_ctf_packet
*packet
)
467 struct bt_ctf_stream
*stream
= NULL
, *writer_stream
= NULL
;
468 enum bt_component_status ret
;
470 stream
= bt_ctf_packet_get_stream(packet
);
472 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
473 __func__
, __FILE__
, __LINE__
);
477 writer_stream
= lookup_stream(writer_component
, stream
);
478 if (!writer_stream
) {
479 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
480 __func__
, __FILE__
, __LINE__
);
485 bt_get(writer_stream
);
487 ret
= bt_ctf_stream_flush(writer_stream
);
489 fprintf(writer_component
->err
,
490 "[error] Failed to flush packet\n");
493 BT_PUT(writer_stream
);
495 ret
= BT_COMPONENT_STATUS_OK
;
499 ret
= BT_COMPONENT_STATUS_ERROR
;
501 bt_put(writer_stream
);
507 enum bt_component_status
writer_output_event(
508 struct writer_component
*writer_component
,
509 struct bt_ctf_event
*event
)
511 enum bt_component_status ret
;
512 struct bt_ctf_event_class
*event_class
= NULL
, *writer_event_class
= NULL
;
513 struct bt_ctf_stream
*stream
= NULL
, *writer_stream
= NULL
;
514 struct bt_ctf_stream_class
*stream_class
= NULL
, *writer_stream_class
= NULL
;
515 struct bt_ctf_event
*writer_event
= NULL
;
516 const char *event_name
;
519 event_class
= bt_ctf_event_get_class(event
);
521 fprintf(writer_component
->err
, "[error] %s in %s:%d\n", __func__
,
526 event_name
= bt_ctf_event_class_get_name(event_class
);
528 fprintf(writer_component
->err
, "[error] %s in %s:%d\n", __func__
,
533 stream
= bt_ctf_event_get_stream(event
);
535 fprintf(writer_component
->err
, "[error] %s in %s:%d\n", __func__
,
540 writer_stream
= lookup_stream(writer_component
, stream
);
541 if (!writer_stream
|| !bt_get(writer_stream
)) {
542 fprintf(writer_component
->err
, "[error] %s in %s:%d\n", __func__
,
547 stream_class
= bt_ctf_event_class_get_stream_class(event_class
);
549 fprintf(writer_component
->err
, "[error] %s in %s:%d\n", __func__
,
554 writer_stream_class
= g_hash_table_lookup(
555 writer_component
->stream_class_map
,
556 (gpointer
) stream_class
);
557 if (!writer_stream_class
|| !bt_get(writer_stream_class
)) {
558 fprintf(writer_component
->err
, "[error] %s in %s:%d\n", __func__
,
563 writer_event_class
= get_event_class(writer_component
,
564 writer_stream_class
, event_class
);
565 if (!writer_event_class
) {
566 writer_event_class
= ctf_copy_event_class(writer_component
->err
,
568 if (!writer_event_class
) {
569 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
570 __func__
, __FILE__
, __LINE__
);
573 int_ret
= bt_ctf_stream_class_add_event_class(
574 writer_stream_class
, writer_event_class
);
576 fprintf(writer_component
->err
, "[error] %s in %s:%d\n",
577 __func__
, __FILE__
, __LINE__
);
582 writer_event
= ctf_copy_event(writer_component
->err
, event
,
583 writer_event_class
, true);
585 fprintf(writer_component
->err
, "[error] %s in %s:%d\n", __func__
,
587 fprintf(writer_component
->err
, "[error] Failed to copy event %s\n",
588 bt_ctf_event_class_get_name(writer_event_class
));
592 int_ret
= bt_ctf_stream_append_event(writer_stream
, writer_event
);
594 fprintf(writer_component
->err
, "[error] %s in %s:%d\n", __func__
,
596 fprintf(writer_component
->err
, "[error] Failed to append event %s\n",
597 bt_ctf_event_class_get_name(writer_event_class
));
601 ret
= BT_COMPONENT_STATUS_OK
;
605 ret
= BT_COMPONENT_STATUS_ERROR
;
607 bt_put(writer_event
);
608 bt_put(writer_event_class
);
609 bt_put(writer_stream_class
);
610 bt_put(stream_class
);
611 bt_put(writer_stream
);