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