lib: make trace IR API const-correct
[babeltrace.git] / plugins / ctf / fs-sink / write.c
CommitLineData
bc506aa5
JD
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
449f71e3
JD
29#define BT_LOG_TAG "PLUGIN-CTF-FS-SINK-WRITE"
30#include "logging.h"
31
9d408fca 32#include <babeltrace/babeltrace.h>
f6ccaed9 33#include <babeltrace/assert-internal.h>
bfe3fb96 34#include <glib.h>
bc506aa5 35
91b73004
JD
36#include <ctfcopytrace.h>
37
bc506aa5
JD
38#include "writer.h"
39
a619fcb7 40static
40f4ba76 41void unref_stream_class(const struct bt_stream_class *writer_stream_class)
a619fcb7 42{
65300d60 43 bt_object_put_ref(writer_stream_class);
a619fcb7
JD
44}
45
46static
40f4ba76 47void unref_stream(const struct bt_stream_class *writer_stream)
a619fcb7 48{
65300d60 49 bt_object_put_ref(writer_stream);
a619fcb7
JD
50}
51
1c78e839 52static
a619fcb7
JD
53gboolean empty_ht(gpointer key, gpointer value, gpointer user_data)
54{
55 return TRUE;
56}
57
1c78e839 58static
2e4636e1
JD
59gboolean empty_streams_ht(gpointer key, gpointer value, gpointer user_data)
60{
885a8803 61 int ret;
40f4ba76 62 const struct bt_stream *writer_stream = value;
2e4636e1 63
50842bdc 64 ret = bt_stream_flush(writer_stream);
885a8803
JG
65 if (ret) {
66 BT_LOGD_STR("Failed to flush stream while emptying hash table.");
67 }
2e4636e1
JD
68 return TRUE;
69}
70
1c78e839 71static
cdcf612f
JD
72void destroy_stream_state_key(gpointer key)
73{
74 g_free((enum fs_writer_stream_state *) key);
75}
76
1c78e839 77static
6f25f7c4
JD
78void check_completed_trace(gpointer key, gpointer value, gpointer user_data)
79{
80 enum fs_writer_stream_state *state = value;
81 int *trace_completed = user_data;
82
83 if (*state != FS_WRITER_COMPLETED_STREAM) {
84 *trace_completed = 0;
85 }
86}
87
f3168545 88static
40f4ba76 89void trace_is_static_listener(const struct bt_trace *trace, void *data)
f3168545 90{
6f25f7c4
JD
91 struct fs_writer *fs_writer = data;
92 int trace_completed = 1;
93
94 fs_writer->trace_static = 1;
95
96 g_hash_table_foreach(fs_writer->stream_states,
97 check_completed_trace, &trace_completed);
98 if (trace_completed) {
99 writer_close(fs_writer->writer_component, fs_writer);
100 g_hash_table_remove(fs_writer->writer_component->trace_map,
101 fs_writer->trace);
102 }
f3168545
JD
103}
104
bc506aa5 105static
40f4ba76 106const struct bt_stream_class *insert_new_stream_class(
91b73004 107 struct writer_component *writer_component,
a619fcb7 108 struct fs_writer *fs_writer,
40f4ba76 109 const struct bt_stream_class *stream_class)
bc506aa5 110{
40f4ba76
PP
111 const struct bt_stream_class *writer_stream_class = NULL;
112 const struct bt_trace *trace = NULL, *writer_trace = NULL;
a619fcb7 113 struct bt_ctf_writer *ctf_writer = fs_writer->writer;
3241bc18 114 enum bt_component_status ret;
bc506aa5 115
50842bdc 116 trace = bt_stream_class_get_trace(stream_class);
f6ccaed9 117 BT_ASSERT(trace);
bc506aa5 118
91b73004 119 writer_trace = bt_ctf_writer_get_trace(ctf_writer);
f6ccaed9 120 BT_ASSERT(writer_trace);
bc506aa5 121
91b73004
JD
122 ret = ctf_copy_clock_classes(writer_component->err, writer_trace,
123 writer_stream_class, trace);
bc506aa5 124 if (ret != BT_COMPONENT_STATUS_OK) {
449f71e3 125 BT_LOGE_STR("Failed to copy clock classes.");
9ae49d3d 126 goto error;
b2f1f465
JD
127 }
128
129 writer_stream_class = ctf_copy_stream_class(writer_component->err,
130 stream_class, writer_trace, true);
131 if (!writer_stream_class) {
449f71e3 132 BT_LOGE_STR("Failed to copy stream class.");
9ae49d3d 133 goto error;
bc506aa5 134 }
bc506aa5 135
50842bdc 136 ret = bt_trace_add_stream_class(writer_trace, writer_stream_class);
e48a596a 137 if (ret) {
449f71e3 138 BT_LOGE_STR("Failed to add stream_class.");
e48a596a
PP
139 goto error;
140 }
141
a619fcb7 142 g_hash_table_insert(fs_writer->stream_class_map,
bc506aa5
JD
143 (gpointer) stream_class, writer_stream_class);
144
9ae49d3d
JD
145 goto end;
146
147error:
65300d60 148 BT_OBJECT_PUT_REF_AND_RESET(writer_stream_class);
9ae49d3d 149end:
65300d60
PP
150 bt_object_put_ref(writer_trace);
151 bt_object_put_ref(trace);
bc506aa5
JD
152 return writer_stream_class;
153}
154
2881e5b5
JD
155static
156enum fs_writer_stream_state *insert_new_stream_state(
157 struct writer_component *writer_component,
40f4ba76 158 struct fs_writer *fs_writer, const struct bt_stream *stream)
2881e5b5
JD
159{
160 enum fs_writer_stream_state *v = NULL;
161
162 v = g_new0(enum fs_writer_stream_state, 1);
163 if (!v) {
56eb9e16
JG
164 BT_LOGE_STR("Failed to allocate fs_writer_stream_state.");
165 goto end;
2881e5b5
JD
166 }
167 *v = FS_WRITER_UNKNOWN_STREAM;
168
169 g_hash_table_insert(fs_writer->stream_states, stream, v);
56eb9e16 170end:
2881e5b5
JD
171 return v;
172}
173
6ca0eb99
JD
174/*
175 * Make sure the output path is valid for a single trace: either it does
176 * not exists or it is empty.
177 *
178 * Return 0 if the path is valid, -1 otherwise.
179 */
180static
181bool valid_single_trace_path(const char *path)
182{
bfe3fb96
MJ
183 GError *error = NULL;
184 GDir *dir = NULL;
185 int ret = 0;
186
187 dir = g_dir_open(path, 0, &error);
6ca0eb99 188
802af08e 189 /* Non-existent directory. */
6ca0eb99 190 if (!dir) {
bfe3fb96
MJ
191 /* For any other error, return an error */
192 if (error->code != G_FILE_ERROR_NOENT) {
193 ret = -1;
6ca0eb99 194 }
6ca0eb99
JD
195 goto end;
196 }
197
bfe3fb96
MJ
198 /* g_dir_read_name skips "." and "..", error out on first result */
199 while (g_dir_read_name(dir) != NULL) {
6ca0eb99 200 ret = -1;
bfe3fb96 201 break;
6ca0eb99
JD
202 }
203
204end:
bfe3fb96
MJ
205 if (dir) {
206 g_dir_close(dir);
207 }
208 if (error) {
209 g_error_free(error);
210 }
211
6ca0eb99
JD
212 return ret;
213}
214
9b4f54fb
JD
215static
216int make_trace_path(struct writer_component *writer_component,
40f4ba76 217 const struct bt_trace *trace, char *trace_path)
9b4f54fb
JD
218{
219 int ret;
220 const char *trace_name;
221
6ca0eb99
JD
222 if (writer_component->single_trace) {
223 trace_name = "\0";
224 } else {
50842bdc 225 trace_name = bt_trace_get_name(trace);
6ca0eb99
JD
226 if (!trace_name) {
227 trace_name = writer_component->trace_name_base->str;
228 }
9b4f54fb 229 }
9b4f54fb
JD
230
231 /* Sanitize the trace name. */
232 if (strlen(trace_name) == 2 && !strcmp(trace_name, "..")) {
449f71e3 233 BT_LOGE_STR("Trace name cannot be \"..\".");
9b4f54fb
JD
234 goto error;
235 }
236
237 if (strstr(trace_name, "../")) {
449f71e3 238 BT_LOGE_STR("Trace name cannot contain \"../\".");
9b4f54fb
JD
239 goto error;
240
241 }
242
3743a302 243 snprintf(trace_path, PATH_MAX, "%s" G_DIR_SEPARATOR_S "%s",
9b4f54fb
JD
244 writer_component->base_path->str,
245 trace_name);
6ca0eb99
JD
246 /*
247 * Append a suffix if the trace_path exists and we are not in
248 * single-trace mode.
249 */
250 if (writer_component->single_trace) {
251 if (valid_single_trace_path(trace_path) != 0) {
449f71e3 252 BT_LOGE_STR("Invalid output directory.");
9b4f54fb
JD
253 goto error;
254 }
6ca0eb99
JD
255 } else {
256 if (g_file_test(trace_path, G_FILE_TEST_EXISTS)) {
257 int i = 0;
258
259 do {
3743a302 260 snprintf(trace_path, PATH_MAX, "%s" G_DIR_SEPARATOR_S "%s-%d",
6ca0eb99
JD
261 writer_component->base_path->str,
262 trace_name, ++i);
263 } while (g_file_test(trace_path, G_FILE_TEST_EXISTS) && i < INT_MAX);
264 if (i == INT_MAX) {
449f71e3 265 BT_LOGE_STR("Unable to find a unique trace path.");
6ca0eb99
JD
266 goto error;
267 }
268 }
9b4f54fb
JD
269 }
270
271 ret = 0;
9b4f54fb
JD
272 goto end;
273
274error:
275 ret = -1;
276end:
277 return ret;
278}
279
bc506aa5 280static
f3168545 281struct fs_writer *insert_new_writer(
bc506aa5 282 struct writer_component *writer_component,
40f4ba76 283 const struct bt_trace *trace)
bc506aa5 284{
9ae49d3d 285 struct bt_ctf_writer *ctf_writer = NULL;
40f4ba76 286 const struct bt_trace *writer_trace = NULL;
9b4f54fb 287 char trace_path[PATH_MAX];
bc506aa5 288 enum bt_component_status ret;
40f4ba76 289 const struct bt_stream *stream = NULL;
cdcf612f
JD
290 struct fs_writer *fs_writer = NULL;
291 int nr_stream, i;
bc506aa5 292
6ca0eb99 293 if (writer_component->single_trace && writer_component->nr_traces > 0) {
449f71e3 294 BT_LOGE_STR("Trying to process more than one trace but single trace mode enabled.");
6ca0eb99
JD
295 goto error;
296 }
297
9b4f54fb
JD
298 ret = make_trace_path(writer_component, trace, trace_path);
299 if (ret) {
449f71e3 300 BT_LOGE_STR("Failed to make trace path.");
9b4f54fb
JD
301 goto error;
302 }
303
304 printf("ctf.fs sink creating trace in %s\n", trace_path);
9057f037 305
9b4f54fb 306 ctf_writer = bt_ctf_writer_create(trace_path);
bc506aa5 307 if (!ctf_writer) {
449f71e3 308 BT_LOGE_STR("Failed to create CTF writer.");
9ae49d3d 309 goto error;
bc506aa5
JD
310 }
311
91b73004 312 writer_trace = bt_ctf_writer_get_trace(ctf_writer);
f6ccaed9 313 BT_ASSERT(writer_trace);
91b73004
JD
314
315 ret = ctf_copy_trace(writer_component->err, trace, writer_trace);
bc506aa5 316 if (ret != BT_COMPONENT_STATUS_OK) {
449f71e3 317 BT_LOGE_STR("Failed to copy trace.");
65300d60 318 BT_OBJECT_PUT_REF_AND_RESET(ctf_writer);
f3168545 319 goto error;
bc506aa5 320 }
f3168545
JD
321
322 fs_writer = g_new0(struct fs_writer, 1);
323 if (!fs_writer) {
449f71e3 324 BT_LOGE_STR("Failed to allocate fs_writer.");
f3168545
JD
325 goto error;
326 }
327 fs_writer->writer = ctf_writer;
cdcf612f
JD
328 fs_writer->trace = trace;
329 fs_writer->writer_trace = writer_trace;
6f25f7c4 330 fs_writer->writer_component = writer_component;
65300d60 331 BT_OBJECT_PUT_REF_AND_RESET(writer_trace);
a619fcb7
JD
332 fs_writer->stream_class_map = g_hash_table_new_full(g_direct_hash,
333 g_direct_equal, NULL, (GDestroyNotify) unref_stream_class);
334 fs_writer->stream_map = g_hash_table_new_full(g_direct_hash,
335 g_direct_equal, NULL, (GDestroyNotify) unref_stream);
cdcf612f
JD
336 fs_writer->stream_states = g_hash_table_new_full(g_direct_hash,
337 g_direct_equal, NULL, destroy_stream_state_key);
338
339 /* Set all the existing streams in the unknown state. */
50842bdc 340 nr_stream = bt_trace_get_stream_count(trace);
cdcf612f 341 for (i = 0; i < nr_stream; i++) {
50842bdc 342 stream = bt_trace_get_stream_by_index(trace, i);
f6ccaed9 343 BT_ASSERT(stream);
449f71e3 344
2881e5b5 345 insert_new_stream_state(writer_component, fs_writer, stream);
65300d60 346 BT_OBJECT_PUT_REF_AND_RESET(stream);
cdcf612f
JD
347 }
348
349 /* Check if the trace is already static or register a listener. */
50842bdc 350 if (bt_trace_is_static(trace)) {
f3168545
JD
351 fs_writer->trace_static = 1;
352 fs_writer->static_listener_id = -1;
353 } else {
50842bdc 354 ret = bt_trace_add_is_static_listener(trace,
8480c8cc 355 trace_is_static_listener, NULL, fs_writer);
f6ccaed9 356 BT_ASSERT(ret >= 0);
f3168545
JD
357 fs_writer->static_listener_id = ret;
358 }
bc506aa5 359
6ca0eb99 360 writer_component->nr_traces++;
bc506aa5 361 g_hash_table_insert(writer_component->trace_map, (gpointer) trace,
f3168545 362 fs_writer);
bc506aa5 363
9ae49d3d
JD
364 goto end;
365
366error:
cdcf612f
JD
367 g_free(fs_writer);
368 fs_writer = NULL;
65300d60
PP
369 bt_object_put_ref(writer_trace);
370 bt_object_put_ref(stream);
371 BT_OBJECT_PUT_REF_AND_RESET(ctf_writer);
bc506aa5 372end:
f3168545 373 return fs_writer;
bc506aa5
JD
374}
375
376static
f3168545 377struct fs_writer *get_fs_writer(struct writer_component *writer_component,
40f4ba76 378 const struct bt_stream_class *stream_class)
bc506aa5 379{
40f4ba76 380 const struct bt_trace *trace = NULL;
f3168545 381 struct fs_writer *fs_writer;
bc506aa5 382
50842bdc 383 trace = bt_stream_class_get_trace(stream_class);
f6ccaed9 384 BT_ASSERT(trace);
bc506aa5 385
f3168545 386 fs_writer = g_hash_table_lookup(writer_component->trace_map,
bc506aa5 387 (gpointer) trace);
f3168545
JD
388 if (!fs_writer) {
389 fs_writer = insert_new_writer(writer_component, trace);
bc506aa5 390 }
65300d60 391 BT_OBJECT_PUT_REF_AND_RESET(trace);
bc506aa5 392
f3168545 393 return fs_writer;
bc506aa5
JD
394}
395
a619fcb7
JD
396static
397struct fs_writer *get_fs_writer_from_stream(
398 struct writer_component *writer_component,
40f4ba76 399 const struct bt_stream *stream)
a619fcb7 400{
40f4ba76 401 const struct bt_stream_class *stream_class = NULL;
a619fcb7
JD
402 struct fs_writer *fs_writer;
403
50842bdc 404 stream_class = bt_stream_get_class(stream);
f6ccaed9 405 BT_ASSERT(stream_class);
a619fcb7
JD
406
407 fs_writer = get_fs_writer(writer_component, stream_class);
a619fcb7 408
65300d60 409 bt_object_put_ref(stream_class);
a619fcb7
JD
410 return fs_writer;
411}
412
413static
40f4ba76 414const struct bt_stream_class *lookup_stream_class(
a619fcb7 415 struct writer_component *writer_component,
40f4ba76 416 const struct bt_stream_class *stream_class)
a619fcb7
JD
417{
418 struct fs_writer *fs_writer = get_fs_writer(
419 writer_component, stream_class);
f6ccaed9 420 BT_ASSERT(fs_writer);
40f4ba76 421 return (const struct bt_stream_class *) g_hash_table_lookup(
a619fcb7
JD
422 fs_writer->stream_class_map, (gpointer) stream_class);
423}
424
425static
40f4ba76
PP
426const struct bt_stream *lookup_stream(struct writer_component *writer_component,
427 const struct bt_stream *stream)
a619fcb7
JD
428{
429 struct fs_writer *fs_writer = get_fs_writer_from_stream(
430 writer_component, stream);
f6ccaed9 431 BT_ASSERT(fs_writer);
40f4ba76 432 return (const struct bt_stream *) g_hash_table_lookup(
a619fcb7
JD
433 fs_writer->stream_map, (gpointer) stream);
434}
435
436static
40f4ba76 437const struct bt_stream *insert_new_stream(
a619fcb7
JD
438 struct writer_component *writer_component,
439 struct fs_writer *fs_writer,
40f4ba76
PP
440 const struct bt_stream_class *stream_class,
441 const struct bt_stream *stream)
a619fcb7 442{
40f4ba76
PP
443 const struct bt_stream *writer_stream = NULL;
444 const struct bt_stream_class *writer_stream_class = NULL;
65300d60 445 struct bt_ctf_writer *ctf_writer = bt_object_get_ref(fs_writer->writer);
a619fcb7
JD
446
447 writer_stream_class = lookup_stream_class(writer_component,
448 stream_class);
449 if (!writer_stream_class) {
450 writer_stream_class = insert_new_stream_class(
451 writer_component, fs_writer, stream_class);
452 if (!writer_stream_class) {
449f71e3 453 BT_LOGE_STR("Failed to insert a new stream_class.");
a619fcb7
JD
454 goto error;
455 }
456 }
65300d60 457 bt_object_get_ref(writer_stream_class);
a619fcb7 458
50842bdc
PP
459 writer_stream = bt_stream_create(writer_stream_class,
460 bt_stream_get_name(stream));
f6ccaed9 461 BT_ASSERT(writer_stream);
a619fcb7
JD
462
463 g_hash_table_insert(fs_writer->stream_map, (gpointer) stream,
464 writer_stream);
465
466 goto end;
467
468error:
65300d60 469 BT_OBJECT_PUT_REF_AND_RESET(writer_stream);
a619fcb7 470end:
65300d60
PP
471 bt_object_put_ref(ctf_writer);
472 bt_object_put_ref(writer_stream_class);
a619fcb7
JD
473 return writer_stream;
474}
475
476static
40f4ba76
PP
477const struct bt_event_class *get_event_class(struct writer_component *writer_component,
478 const struct bt_stream_class *writer_stream_class,
479 const struct bt_event_class *event_class)
a619fcb7 480{
50842bdc
PP
481 return bt_stream_class_get_event_class_by_id(writer_stream_class,
482 bt_event_class_get_id(event_class));
a619fcb7
JD
483}
484
bc506aa5 485static
40f4ba76 486const struct bt_stream *get_writer_stream(
bc506aa5 487 struct writer_component *writer_component,
40f4ba76 488 const struct bt_packet *packet, const struct bt_stream *stream)
bc506aa5 489{
40f4ba76 490 const struct bt_stream *writer_stream = NULL;
bc506aa5 491
f384901f
JD
492 writer_stream = lookup_stream(writer_component, stream);
493 if (!writer_stream) {
449f71e3 494 BT_LOGE_STR("Failed to find existing stream.");
9ae49d3d 495 goto error;
bc506aa5 496 }
65300d60 497 bt_object_get_ref(writer_stream);
9ae49d3d
JD
498
499 goto end;
bc506aa5 500
9ae49d3d 501error:
65300d60 502 BT_OBJECT_PUT_REF_AND_RESET(writer_stream);
9ae49d3d 503end:
bc506aa5
JD
504 return writer_stream;
505}
506
f3168545 507BT_HIDDEN
a619fcb7
JD
508void writer_close(struct writer_component *writer_component,
509 struct fs_writer *fs_writer)
f3168545 510{
ec273a88 511 if (fs_writer->static_listener_id >= 0) {
50842bdc 512 bt_trace_remove_is_static_listener(fs_writer->trace,
f3168545
JD
513 fs_writer->static_listener_id);
514 }
a619fcb7
JD
515
516 /* Empty the stream class HT. */
517 g_hash_table_foreach_remove(fs_writer->stream_class_map,
518 empty_ht, NULL);
519 g_hash_table_destroy(fs_writer->stream_class_map);
520
521 /* Empty the stream HT. */
522 g_hash_table_foreach_remove(fs_writer->stream_map,
2e4636e1 523 empty_streams_ht, NULL);
a619fcb7 524 g_hash_table_destroy(fs_writer->stream_map);
cdcf612f
JD
525
526 /* Empty the stream state HT. */
527 g_hash_table_foreach_remove(fs_writer->stream_states,
528 empty_ht, NULL);
529 g_hash_table_destroy(fs_writer->stream_states);
f3168545
JD
530}
531
f384901f
JD
532BT_HIDDEN
533enum bt_component_status writer_stream_begin(
534 struct writer_component *writer_component,
40f4ba76 535 const struct bt_stream *stream)
f384901f 536{
40f4ba76 537 const struct bt_stream_class *stream_class = NULL;
f384901f 538 struct fs_writer *fs_writer;
40f4ba76 539 const struct bt_stream *writer_stream = NULL;
f384901f 540 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
cdcf612f 541 enum fs_writer_stream_state *state;
f384901f 542
50842bdc 543 stream_class = bt_stream_get_class(stream);
f6ccaed9 544 BT_ASSERT(stream_class);
f384901f
JD
545
546 fs_writer = get_fs_writer(writer_component, stream_class);
547 if (!fs_writer) {
449f71e3 548 BT_LOGE_STR("Failed to get fs_writer.");
f384901f
JD
549 goto error;
550 }
cdcf612f
JD
551
552 /* Set the stream as active */
553 state = g_hash_table_lookup(fs_writer->stream_states, stream);
2881e5b5
JD
554 if (!state) {
555 if (fs_writer->trace_static) {
449f71e3 556 BT_LOGE_STR("Cannot add new stream on a static trace.");
2881e5b5
JD
557 goto error;
558 }
559 state = insert_new_stream_state(writer_component, fs_writer,
560 stream);
561 }
cdcf612f 562 if (*state != FS_WRITER_UNKNOWN_STREAM) {
449f71e3 563 BT_LOGE("Unexpected stream state: state=%d", *state);
cdcf612f
JD
564 goto error;
565 }
566 *state = FS_WRITER_ACTIVE_STREAM;
567
a619fcb7 568 writer_stream = insert_new_stream(writer_component, fs_writer,
f384901f
JD
569 stream_class, stream);
570 if (!writer_stream) {
449f71e3 571 BT_LOGE_STR("Failed to insert new stream.");
f384901f
JD
572 goto error;
573 }
f384901f
JD
574
575 goto end;
576
577error:
578 ret = BT_COMPONENT_STATUS_ERROR;
579end:
65300d60 580 bt_object_put_ref(stream_class);
f384901f
JD
581 return ret;
582}
583
f3168545
JD
584BT_HIDDEN
585enum bt_component_status writer_stream_end(
586 struct writer_component *writer_component,
40f4ba76 587 const struct bt_stream *stream)
f3168545 588{
40f4ba76 589 const struct bt_stream_class *stream_class = NULL;
f3168545 590 struct fs_writer *fs_writer;
40f4ba76 591 const struct bt_trace *trace = NULL;
f3168545 592 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
cdcf612f 593 enum fs_writer_stream_state *state;
f3168545 594
50842bdc 595 stream_class = bt_stream_get_class(stream);
f6ccaed9 596 BT_ASSERT(stream_class);
f3168545
JD
597
598 fs_writer = get_fs_writer(writer_component, stream_class);
599 if (!fs_writer) {
449f71e3 600 BT_LOGE_STR("Failed to get fs_writer.");
f3168545
JD
601 goto error;
602 }
cdcf612f
JD
603
604 state = g_hash_table_lookup(fs_writer->stream_states, stream);
605 if (*state != FS_WRITER_ACTIVE_STREAM) {
449f71e3 606 BT_LOGE("Unexpected stream state: state=%d", *state);
cdcf612f
JD
607 goto error;
608 }
609 *state = FS_WRITER_COMPLETED_STREAM;
610
a619fcb7 611 g_hash_table_remove(fs_writer->stream_map, stream);
f3168545 612
cdcf612f
JD
613 if (fs_writer->trace_static) {
614 int trace_completed = 1;
615
616 g_hash_table_foreach(fs_writer->stream_states,
617 check_completed_trace, &trace_completed);
618 if (trace_completed) {
619 writer_close(writer_component, fs_writer);
620 g_hash_table_remove(writer_component->trace_map,
621 fs_writer->trace);
622 }
f3168545
JD
623 }
624
625 goto end;
626
627error:
628 ret = BT_COMPONENT_STATUS_ERROR;
629end:
65300d60
PP
630 BT_OBJECT_PUT_REF_AND_RESET(trace);
631 BT_OBJECT_PUT_REF_AND_RESET(stream_class);
f3168545
JD
632 return ret;
633}
634
bc506aa5
JD
635BT_HIDDEN
636enum bt_component_status writer_new_packet(
637 struct writer_component *writer_component,
40f4ba76 638 const struct bt_packet *packet)
bc506aa5 639{
40f4ba76 640 const struct bt_stream *stream = NULL, *writer_stream = NULL;
bc506aa5 641 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
b2f1f465 642 int int_ret;
bc506aa5 643
50842bdc 644 stream = bt_packet_get_stream(packet);
f6ccaed9 645 BT_ASSERT(stream);
bc506aa5 646
bc506aa5
JD
647 writer_stream = get_writer_stream(writer_component, packet, stream);
648 if (!writer_stream) {
449f71e3 649 BT_LOGE_STR("Failed to get writer_stream.");
9ae49d3d 650 goto error;
bc506aa5 651 }
65300d60 652 BT_OBJECT_PUT_REF_AND_RESET(stream);
bc506aa5 653
9877e1aa
JD
654 int_ret = ctf_stream_copy_packet_context(
655 writer_component->err, packet, writer_stream);
656 if (int_ret < 0) {
449f71e3 657 BT_LOGE_STR("Failed to copy packet_context.");
9877e1aa 658 goto error;
b2f1f465 659 }
387483fc
JD
660
661 ret = ctf_stream_copy_packet_header(writer_component->err,
662 packet, writer_stream);
663 if (ret != 0) {
449f71e3 664 BT_LOGE_STR("Failed to copy packet_header.");
387483fc
JD
665 goto error;
666 }
b2f1f465 667
9ae49d3d 668 goto end;
bc506aa5 669
9ae49d3d
JD
670error:
671 ret = BT_COMPONENT_STATUS_ERROR;
672end:
65300d60
PP
673 bt_object_put_ref(writer_stream);
674 bt_object_put_ref(stream);
bc506aa5
JD
675 return ret;
676}
677
678BT_HIDDEN
679enum bt_component_status writer_close_packet(
680 struct writer_component *writer_component,
40f4ba76 681 const struct bt_packet *packet)
bc506aa5 682{
40f4ba76 683 const struct bt_stream *stream = NULL, *writer_stream = NULL;
bc506aa5
JD
684 enum bt_component_status ret;
685
50842bdc 686 stream = bt_packet_get_stream(packet);
f6ccaed9 687 BT_ASSERT(stream);
bc506aa5
JD
688
689 writer_stream = lookup_stream(writer_component, stream);
690 if (!writer_stream) {
449f71e3 691 BT_LOGE_STR("Failed to find existing stream.");
9ae49d3d 692 goto error;
bc506aa5 693 }
65300d60 694 BT_OBJECT_PUT_REF_AND_RESET(stream);
bc506aa5 695
65300d60 696 bt_object_get_ref(writer_stream);
bc506aa5 697
50842bdc 698 ret = bt_stream_flush(writer_stream);
449f71e3
JD
699 if (ret) {
700 BT_LOGE_STR("Failed to flush stream.");
9ae49d3d 701 goto error;
bc506aa5 702 }
449f71e3 703
65300d60 704 BT_OBJECT_PUT_REF_AND_RESET(writer_stream);
bc506aa5
JD
705
706 ret = BT_COMPONENT_STATUS_OK;
9ae49d3d 707 goto end;
bc506aa5 708
9ae49d3d
JD
709error:
710 ret = BT_COMPONENT_STATUS_ERROR;
711end:
65300d60
PP
712 bt_object_put_ref(writer_stream);
713 bt_object_put_ref(stream);
bc506aa5
JD
714 return ret;
715}
716
bc506aa5
JD
717BT_HIDDEN
718enum bt_component_status writer_output_event(
719 struct writer_component *writer_component,
40f4ba76 720 const struct bt_event *event)
bc506aa5
JD
721{
722 enum bt_component_status ret;
40f4ba76
PP
723 const struct bt_event_class *event_class = NULL, *writer_event_class = NULL;
724 const struct bt_stream *stream = NULL, *writer_stream = NULL;
725 const struct bt_stream_class *stream_class = NULL, *writer_stream_class = NULL;
726 const struct bt_event *writer_event = NULL;
bc506aa5 727 int int_ret;
40f4ba76 728 const struct bt_trace *writer_trace = NULL;
bc506aa5 729
50842bdc 730 event_class = bt_event_get_class(event);
f6ccaed9 731 BT_ASSERT(event_class);
bc506aa5 732
50842bdc 733 stream = bt_event_get_stream(event);
f6ccaed9 734 BT_ASSERT(stream);
bc506aa5
JD
735
736 writer_stream = lookup_stream(writer_component, stream);
65300d60 737 if (!writer_stream || !bt_object_get_ref(writer_stream)) {
449f71e3 738 BT_LOGE_STR("Failed for find existing stream.");
9ae49d3d 739 goto error;
bc506aa5
JD
740 }
741
50842bdc 742 stream_class = bt_event_class_get_stream_class(event_class);
f6ccaed9 743 BT_ASSERT(stream_class);
bc506aa5 744
a619fcb7 745 writer_stream_class = lookup_stream_class(writer_component, stream_class);
65300d60 746 if (!writer_stream_class || !bt_object_get_ref(writer_stream_class)) {
449f71e3 747 BT_LOGE_STR("Failed to find existing stream_class.");
9ae49d3d 748 goto error;
bc506aa5
JD
749 }
750
4a2fffdb 751 writer_trace = bt_stream_class_get_trace(writer_stream_class);
f6ccaed9 752 BT_ASSERT(writer_trace);
4a2fffdb 753
bc506aa5
JD
754 writer_event_class = get_event_class(writer_component,
755 writer_stream_class, event_class);
756 if (!writer_event_class) {
af34e875 757 writer_event_class = ctf_copy_event_class(writer_component->err,
4a2fffdb 758 writer_trace, event_class);
af34e875 759 if (!writer_event_class) {
449f71e3 760 BT_LOGE_STR("Failed to copy event_class.");
9ae49d3d 761 goto error;
af34e875 762 }
50842bdc 763 int_ret = bt_stream_class_add_event_class(
af34e875
JD
764 writer_stream_class, writer_event_class);
765 if (int_ret) {
449f71e3 766 BT_LOGE("Failed to add event_class: event_name=\"%s\"",
50842bdc 767 bt_event_class_get_name(event_class));
9ae49d3d 768 goto error;
af34e875 769 }
bc506aa5
JD
770 }
771
b2f1f465
JD
772 writer_event = ctf_copy_event(writer_component->err, event,
773 writer_event_class, true);
bc506aa5 774 if (!writer_event) {
449f71e3 775 BT_LOGE("Failed to copy event: event_class=\"%s\"",
50842bdc 776 bt_event_class_get_name(writer_event_class));
9ae49d3d 777 goto error;
bc506aa5
JD
778 }
779
50842bdc 780 int_ret = bt_stream_append_event(writer_stream, writer_event);
bc506aa5 781 if (int_ret < 0) {
449f71e3 782 BT_LOGE("Failed to append event: event_class=\"%s\"",
50842bdc 783 bt_event_class_get_name(writer_event_class));
9ae49d3d 784 goto error;
bc506aa5
JD
785 }
786
787 ret = BT_COMPONENT_STATUS_OK;
9ae49d3d 788 goto end;
bc506aa5 789
9ae49d3d
JD
790error:
791 ret = BT_COMPONENT_STATUS_ERROR;
792end:
65300d60
PP
793 bt_object_put_ref(writer_trace);
794 bt_object_put_ref(writer_event);
795 bt_object_put_ref(writer_event_class);
796 bt_object_put_ref(writer_stream_class);
797 bt_object_put_ref(stream_class);
798 bt_object_put_ref(writer_stream);
799 bt_object_put_ref(stream);
800 bt_object_put_ref(event_class);
bc506aa5
JD
801 return ret;
802}
This page took 0.07963 seconds and 4 git commands to generate.