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