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