writer: create event classes lazily
[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 <ctfcopytrace.h>
40
41 #include "writer.h"
42
43 static
44 struct bt_ctf_stream_class *insert_new_stream_class(
45 struct writer_component *writer_component,
46 struct bt_ctf_writer *ctf_writer,
47 struct bt_ctf_stream_class *stream_class)
48 {
49 struct bt_ctf_stream_class *writer_stream_class = NULL;
50 struct bt_ctf_trace *trace, *writer_trace;
51 enum bt_component_status ret;
52
53 trace = bt_ctf_stream_class_get_trace(stream_class);
54 if (!trace) {
55 fprintf(writer_component->err,
56 "[error] %s in %s:%d\n", __func__, __FILE__,
57 __LINE__);
58 goto end;
59 }
60
61 writer_trace = bt_ctf_writer_get_trace(ctf_writer);
62 if (!writer_trace) {
63 bt_put(trace);
64 fprintf(writer_component->err,
65 "[error] %s in %s:%d\n", __func__, __FILE__,
66 __LINE__);
67 ret = BT_COMPONENT_STATUS_ERROR;
68 goto end_put_trace;
69 }
70
71 ret = ctf_copy_clock_classes(writer_component->err, writer_trace,
72 writer_stream_class, trace);
73 if (ret != BT_COMPONENT_STATUS_OK) {
74 bt_put(trace);
75 fprintf(writer_component->err,
76 "[error] %s in %s:%d\n", __func__, __FILE__,
77 __LINE__);
78 goto end_put_writer_trace;
79 }
80
81 writer_stream_class = ctf_copy_stream_class(writer_component->err,
82 stream_class, writer_trace, true);
83 if (!writer_stream_class) {
84 fprintf(writer_component->err, "[error] Failed to copy stream class\n");
85 fprintf(writer_component->err, "[error] %s in %s:%d\n",
86 __func__, __FILE__, __LINE__);
87 goto end_put_writer_trace;
88 }
89
90 g_hash_table_insert(writer_component->stream_class_map,
91 (gpointer) stream_class, writer_stream_class);
92
93 end_put_writer_trace:
94 bt_put(writer_trace);
95 end_put_trace:
96 bt_put(trace);
97 end:
98 return writer_stream_class;
99 }
100
101 static
102 struct bt_ctf_stream *insert_new_stream(
103 struct writer_component *writer_component,
104 struct bt_ctf_writer *ctf_writer,
105 struct bt_ctf_stream_class *stream_class,
106 struct bt_ctf_stream *stream)
107 {
108 struct bt_ctf_stream *writer_stream;
109 struct bt_ctf_stream_class *writer_stream_class;
110
111 writer_stream_class = g_hash_table_lookup(
112 writer_component->stream_class_map,
113 (gpointer) stream_class);
114 if (writer_stream_class) {
115 if (!bt_get(writer_stream_class)) {
116 writer_stream = NULL;
117 fprintf(writer_component->err, "[error] %s in %s:%d\n",
118 __func__, __FILE__, __LINE__);
119 goto end;
120 }
121 } else {
122 writer_stream_class = insert_new_stream_class(
123 writer_component, ctf_writer, stream_class);
124 if (!writer_stream_class) {
125 writer_stream = NULL;
126 fprintf(writer_component->err, "[error] %s in %s:%d\n",
127 __func__, __FILE__, __LINE__);
128 goto end_put;
129 }
130 }
131
132 writer_stream = bt_ctf_writer_create_stream(ctf_writer,
133 writer_stream_class);
134 if (!writer_stream) {
135 fprintf(writer_component->err, "[error] %s in %s:%d\n",
136 __func__, __FILE__, __LINE__);
137 goto end_put;
138 }
139
140 g_hash_table_insert(writer_component->stream_map, (gpointer) stream,
141 writer_stream);
142
143 bt_ctf_writer_flush_metadata(ctf_writer);
144
145 end_put:
146 bt_put(writer_stream_class);
147 end:
148 return writer_stream;
149 }
150
151 static
152 struct bt_ctf_stream *lookup_stream(struct writer_component *writer_component,
153 struct bt_ctf_stream *stream)
154 {
155 return (struct bt_ctf_stream *) g_hash_table_lookup(
156 writer_component->stream_map,
157 (gpointer) stream);
158 }
159
160 static
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)
164 {
165 return bt_ctf_stream_class_get_event_class_by_name(writer_stream_class,
166 bt_ctf_event_class_get_name(event_class));
167 }
168
169 struct bt_ctf_writer *insert_new_writer(
170 struct writer_component *writer_component,
171 struct bt_ctf_trace *trace)
172 {
173 struct bt_ctf_writer *ctf_writer;
174 struct bt_ctf_trace *writer_trace;
175 char trace_name[PATH_MAX];
176 enum bt_component_status ret;
177
178 snprintf(trace_name, PATH_MAX, "%s/%s_%03d",
179 writer_component->base_path->str,
180 writer_component->trace_name_base->str,
181 writer_component->trace_id++);
182 printf_verbose("CTF-Writer creating trace in %s\n", trace_name);
183
184 ctf_writer = bt_ctf_writer_create(trace_name);
185 if (!ctf_writer) {
186 fprintf(writer_component->err, "[error] %s in %s:%d\n",
187 __func__, __FILE__, __LINE__);
188 goto end;
189 }
190
191 writer_trace = bt_ctf_writer_get_trace(ctf_writer);
192 if (!writer_trace) {
193 ret = BT_COMPONENT_STATUS_ERROR;
194 fprintf(writer_component->err,
195 "[error] %s in %s:%d\n", __func__, __FILE__,
196 __LINE__);
197 goto end;
198 }
199
200 ret = ctf_copy_trace(writer_component->err, trace, writer_trace);
201 bt_put(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__);
206 BT_PUT(ctf_writer);
207 goto end;
208 }
209
210 g_hash_table_insert(writer_component->trace_map, (gpointer) trace,
211 ctf_writer);
212
213 end:
214 return ctf_writer;
215 }
216
217 static
218 struct bt_ctf_writer *get_writer(struct writer_component *writer_component,
219 struct bt_ctf_stream_class *stream_class)
220 {
221 struct bt_ctf_trace *trace;
222 struct bt_ctf_writer *ctf_writer;
223
224 trace = bt_ctf_stream_class_get_trace(stream_class);
225 if (!trace) {
226 ctf_writer = NULL;
227 fprintf(writer_component->err, "[error] %s in %s:%d\n",
228 __func__, __FILE__, __LINE__);
229 goto end;
230 }
231
232 ctf_writer = g_hash_table_lookup(writer_component->trace_map,
233 (gpointer) trace);
234 if (ctf_writer) {
235 if (!bt_get(ctf_writer)) {
236 ctf_writer = NULL;
237 fprintf(writer_component->err, "[error] %s in %s:%d\n",
238 __func__, __FILE__, __LINE__);
239 goto end;
240 }
241 } else {
242 ctf_writer = insert_new_writer(writer_component, trace);
243 }
244 bt_put(trace);
245
246 end:
247 return ctf_writer;
248 }
249
250 static
251 struct bt_ctf_stream *get_writer_stream(
252 struct writer_component *writer_component,
253 struct bt_ctf_packet *packet, struct bt_ctf_stream *stream)
254 {
255 struct bt_ctf_stream_class *stream_class;
256 struct bt_ctf_writer *ctf_writer;
257 struct bt_ctf_stream *writer_stream;
258
259 stream_class = bt_ctf_stream_get_class(stream);
260 if (!stream_class) {
261 writer_stream = NULL;
262 fprintf(writer_component->err, "[error] %s in %s:%d\n",
263 __func__, __FILE__, __LINE__);
264 goto end;
265 }
266
267 ctf_writer = get_writer(writer_component, stream_class);
268 if (!ctf_writer) {
269 writer_stream = NULL;
270 fprintf(writer_component->err, "[error] %s in %s:%d\n",
271 __func__, __FILE__, __LINE__);
272 goto end_put_stream_class;
273 }
274
275 writer_stream = lookup_stream(writer_component, stream);
276
277 if (writer_stream) {
278 if (!bt_get(writer_stream)) {
279 writer_stream = NULL;
280 fprintf(writer_component->err, "[error] %s in %s:%d\n",
281 __func__, __FILE__, __LINE__);
282 goto end_put_stream_class;
283 }
284 } else {
285 writer_stream = insert_new_stream(writer_component, ctf_writer,
286 stream_class, stream);
287 bt_get(writer_stream);
288 }
289
290 bt_put(ctf_writer);
291 end_put_stream_class:
292 bt_put(stream_class);
293 end:
294 return writer_stream;
295 }
296
297 BT_HIDDEN
298 enum bt_component_status writer_new_packet(
299 struct writer_component *writer_component,
300 struct bt_ctf_packet *packet)
301 {
302 struct bt_ctf_stream *stream, *writer_stream;
303 struct bt_ctf_field *writer_packet_context;
304 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
305 int int_ret;
306
307 stream = bt_ctf_packet_get_stream(packet);
308 if (!stream) {
309 ret = BT_COMPONENT_STATUS_ERROR;
310 fprintf(writer_component->err, "[error] %s in %s:%d\n",
311 __func__, __FILE__, __LINE__);
312 goto end;
313 }
314
315 writer_stream = get_writer_stream(writer_component, packet, stream);
316 if (!writer_stream) {
317 ret = BT_COMPONENT_STATUS_ERROR;
318 fprintf(writer_component->err, "[error] %s in %s:%d\n",
319 __func__, __FILE__, __LINE__);
320 goto end_put;
321 }
322
323 writer_packet_context = ctf_copy_packet_context(writer_component->err,
324 packet, writer_stream);
325 if (!writer_packet_context) {
326 ret = BT_COMPONENT_STATUS_ERROR;
327 fprintf(writer_component->err, "[error] %s in %s:%d\n",
328 __func__, __FILE__, __LINE__);
329 goto end_put;
330 }
331
332 int_ret = bt_ctf_stream_set_packet_context(writer_stream,
333 writer_packet_context);
334 if (int_ret < 0) {
335 ret = BT_COMPONENT_STATUS_ERROR;
336 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
337 __FILE__, __LINE__);
338 goto end_put_writer_packet_context;
339 }
340
341 bt_put(writer_stream);
342
343 end_put_writer_packet_context:
344 bt_put(writer_packet_context);
345 end_put:
346 bt_put(stream);
347 end:
348 return ret;
349 }
350
351 BT_HIDDEN
352 enum bt_component_status writer_close_packet(
353 struct writer_component *writer_component,
354 struct bt_ctf_packet *packet)
355 {
356 struct bt_ctf_stream *stream, *writer_stream;
357 enum bt_component_status ret;
358
359 stream = bt_ctf_packet_get_stream(packet);
360 if (!stream) {
361 ret = BT_COMPONENT_STATUS_ERROR;
362 fprintf(writer_component->err, "[error] %s in %s:%d\n",
363 __func__, __FILE__, __LINE__);
364 goto end;
365 }
366
367 writer_stream = lookup_stream(writer_component, stream);
368 if (!writer_stream) {
369 ret = BT_COMPONENT_STATUS_ERROR;
370 fprintf(writer_component->err, "[error] %s in %s:%d\n",
371 __func__, __FILE__, __LINE__);
372 goto end_put;
373 }
374
375 if (!bt_get(writer_stream)) {
376 fprintf(writer_component->err,
377 "[error] Failed to get reference on writer stream\n");
378 fprintf(writer_component->err, "[error] %s in %s:%d\n",
379 __func__, __FILE__, __LINE__);
380 ret = BT_COMPONENT_STATUS_ERROR;
381 goto end_put;
382 }
383
384 ret = bt_ctf_stream_flush(writer_stream);
385 if (ret < 0) {
386 fprintf(writer_component->err,
387 "[error] Failed to flush packet\n");
388 ret = BT_COMPONENT_STATUS_ERROR;
389 }
390
391 ret = BT_COMPONENT_STATUS_OK;
392
393 bt_put(writer_stream);
394
395 end_put:
396 bt_put(stream);
397 end:
398 return ret;
399 }
400
401 BT_HIDDEN
402 enum bt_component_status writer_output_event(
403 struct writer_component *writer_component,
404 struct bt_ctf_event *event)
405 {
406 enum bt_component_status ret;
407 struct bt_ctf_event_class *event_class, *writer_event_class;
408 struct bt_ctf_stream *stream, *writer_stream;
409 struct bt_ctf_stream_class *stream_class, *writer_stream_class;
410 struct bt_ctf_event *writer_event;
411 const char *event_name;
412 int int_ret;
413
414 event_class = bt_ctf_event_get_class(event);
415 if (!event_class) {
416 ret = BT_COMPONENT_STATUS_ERROR;
417 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
418 __FILE__, __LINE__);
419 goto end;
420 }
421
422 event_name = bt_ctf_event_class_get_name(event_class);
423 if (!event_name) {
424 ret = BT_COMPONENT_STATUS_ERROR;
425 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
426 __FILE__, __LINE__);
427 goto end_put_event_class;
428 }
429
430 stream = bt_ctf_event_get_stream(event);
431 if (!stream) {
432 ret = BT_COMPONENT_STATUS_ERROR;
433 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
434 __FILE__, __LINE__);
435 goto end_put_event_class;
436 }
437
438 writer_stream = lookup_stream(writer_component, stream);
439 if (!writer_stream || !bt_get(writer_stream)) {
440 ret = BT_COMPONENT_STATUS_ERROR;
441 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
442 __FILE__, __LINE__);
443 goto end_put_stream;
444 }
445
446 stream_class = bt_ctf_event_class_get_stream_class(event_class);
447 if (!stream_class) {
448 ret = BT_COMPONENT_STATUS_ERROR;
449 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
450 __FILE__, __LINE__);
451 goto end_put_writer_stream;
452 }
453
454 writer_stream_class = g_hash_table_lookup(
455 writer_component->stream_class_map,
456 (gpointer) stream_class);
457 if (!writer_stream_class || !bt_get(writer_stream_class)) {
458 ret = BT_COMPONENT_STATUS_ERROR;
459 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
460 __FILE__, __LINE__);
461 goto end_put_stream_class;
462 }
463
464 writer_event_class = get_event_class(writer_component,
465 writer_stream_class, event_class);
466 if (!writer_event_class) {
467 writer_event_class = ctf_copy_event_class(writer_component->err,
468 event_class);
469 if (!writer_event_class) {
470 ret = BT_COMPONENT_STATUS_ERROR;
471 fprintf(writer_component->err, "[error] %s in %s:%d\n",
472 __func__, __FILE__, __LINE__);
473 goto end_put_writer_stream_class;
474 }
475 int_ret = bt_ctf_stream_class_add_event_class(
476 writer_stream_class, writer_event_class);
477 if (int_ret) {
478 ret = BT_COMPONENT_STATUS_ERROR;
479 fprintf(writer_component->err, "[error] %s in %s:%d\n",
480 __func__, __FILE__, __LINE__);
481 goto end_put_writer_stream_class;
482 }
483 }
484
485 writer_event = ctf_copy_event(writer_component->err, event,
486 writer_event_class, true);
487 if (!writer_event) {
488 ret = BT_COMPONENT_STATUS_ERROR;
489 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
490 __FILE__, __LINE__);
491 fprintf(writer_component->err, "[error] Failed to copy event %s\n",
492 bt_ctf_event_class_get_name(writer_event_class));
493 goto end_put_writer_event_class;
494 }
495
496 int_ret = bt_ctf_stream_append_event(writer_stream, writer_event);
497 if (int_ret < 0) {
498 ret = BT_COMPONENT_STATUS_ERROR;
499 fprintf(writer_component->err, "[error] %s in %s:%d\n", __func__,
500 __FILE__, __LINE__);
501 fprintf(writer_component->err, "[error] Failed to append event %s\n",
502 bt_ctf_event_class_get_name(writer_event_class));
503 goto end_put_writer_event;
504 }
505
506 ret = BT_COMPONENT_STATUS_OK;
507
508 end_put_writer_event:
509 bt_put(writer_event);
510 end_put_writer_event_class:
511 bt_put(writer_event_class);
512 end_put_writer_stream_class:
513 bt_put(writer_stream_class);
514 end_put_stream_class:
515 bt_put(stream_class);
516 end_put_writer_stream:
517 bt_put(writer_stream);
518 end_put_stream:
519 bt_put(stream);
520 end_put_event_class:
521 bt_put(event_class);
522 end:
523 return ret;
524 }
This page took 0.039298 seconds and 4 git commands to generate.