lib: make trace IR API const-correct
[babeltrace.git] / plugins / lttng-utils / copy.c
CommitLineData
4f45f9bb
JD
1/*
2 * copy.c
3 *
4 * Babeltrace Copy Trace Structure
5 *
6 * Copyright 2017 Julien Desfossez <jdesfossez@efficios.com>
7 *
8 * Author: Julien Desfossez <jdesfossez@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
b4d4912f
JD
29#define BT_LOG_TAG "PLUGIN-LTTNG-UTILS-DEBUG-INFO-FLT-COPY"
30#include "logging.h"
31
4f45f9bb 32#include <inttypes.h>
f6ccaed9 33#include <babeltrace/assert-internal.h>
9d408fca 34#include <babeltrace/babeltrace.h>
4f45f9bb
JD
35
36#include <ctfcopytrace.h>
37#include "debug-info.h"
38
cb0a5cf8 39static
40f4ba76 40const struct bt_stream *insert_new_stream(
cb0a5cf8 41 struct debug_info_iterator *debug_it,
40f4ba76 42 const struct bt_stream *stream,
cb0a5cf8
JD
43 struct debug_info_trace *di_trace);
44
504db471 45static
40f4ba76 46void unref_stream(const struct bt_stream *stream)
504db471 47{
65300d60 48 bt_object_put_ref(stream);
504db471
JD
49}
50
51static
40f4ba76 52void unref_packet(const struct bt_packet *packet)
504db471 53{
65300d60 54 bt_object_put_ref(packet);
504db471
JD
55}
56
57static
40f4ba76 58void unref_stream_class(const struct bt_stream_class *stream_class)
504db471 59{
65300d60 60 bt_object_put_ref(stream_class);
504db471
JD
61}
62
63static
64void unref_debug_info(struct debug_info *debug_info)
65{
66 debug_info_destroy(debug_info);
67}
68
1c78e839
JD
69static
70void destroy_stream_state_key(gpointer key)
71{
72 g_free((enum fs_writer_stream_state *) key);
73}
74
4f45f9bb 75static
40f4ba76
PP
76const struct bt_field *get_payload_field(FILE *err,
77 const struct bt_event *event, const char *field_name)
4f45f9bb 78{
40f4ba76
PP
79 const struct bt_field *field = NULL, *payload = NULL;
80 const struct bt_field_class *payload_class = NULL;
4f45f9bb 81
50842bdc 82 payload = bt_event_get_payload(event, NULL);
f6ccaed9 83 BT_ASSERT(payload);
4f45f9bb 84
5cd6d0e5
PP
85 payload_class = bt_field_get_class(payload);
86 BT_ASSERT(payload_class);
4f45f9bb 87
864cad70 88 if (bt_field_class_id(payload_class) != BT_FIELD_CLASS_TYPE_STRUCT) {
b4d4912f
JD
89 BT_LOGE("Wrong type, expected struct: field-name=\"%s\"",
90 field_name);
4f45f9bb
JD
91 goto end;
92 }
93
50842bdc 94 field = bt_field_structure_get_field_by_name(payload, field_name);
4f45f9bb
JD
95
96end:
65300d60
PP
97 bt_object_put_ref(payload_class);
98 bt_object_put_ref(payload);
4f45f9bb
JD
99 return field;
100}
101
102static
40f4ba76
PP
103const struct bt_field *get_stream_event_context_field(FILE *err,
104 const struct bt_event *event, const char *field_name)
4f45f9bb 105{
40f4ba76
PP
106 const struct bt_field *field = NULL, *sec = NULL;
107 const struct bt_field_class *sec_class = NULL;
4f45f9bb 108
50842bdc 109 sec = bt_event_get_stream_event_context(event);
4f45f9bb 110 if (!sec) {
4f45f9bb
JD
111 goto end;
112 }
113
5cd6d0e5
PP
114 sec_class = bt_field_get_class(sec);
115 BT_ASSERT(sec_class);
4f45f9bb 116
864cad70 117 if (bt_field_class_id(sec_class) != BT_FIELD_CLASS_TYPE_STRUCT) {
b4d4912f
JD
118 BT_LOGE("Wrong type, expected struct, field-name=\"%s\"",
119 field_name);
4f45f9bb
JD
120 goto end;
121 }
122
50842bdc 123 field = bt_field_structure_get_field_by_name(sec, field_name);
4f45f9bb
JD
124
125end:
65300d60
PP
126 bt_object_put_ref(sec_class);
127 bt_object_put_ref(sec);
4f45f9bb
JD
128 return field;
129}
130
131BT_HIDDEN
132int get_stream_event_context_unsigned_int_field_value(FILE *err,
40f4ba76 133 const struct bt_event *event, const char *field_name,
4f45f9bb
JD
134 uint64_t *value)
135{
136 int ret;
40f4ba76
PP
137 const struct bt_field *field = NULL;
138 const struct bt_field_class *field_class = NULL;
4f45f9bb
JD
139
140 field = get_stream_event_context_field(err, event, field_name);
141 if (!field) {
4f45f9bb
JD
142 goto error;
143 }
144
5cd6d0e5
PP
145 field_class = bt_field_get_class(field);
146 BT_ASSERT(field_class);
4f45f9bb 147
864cad70 148 if (bt_field_class_id(field_class) != BT_FIELD_CLASS_TYPE_INTEGER) {
b4d4912f
JD
149 BT_LOGE("Wrong type, expected integer: field-name=\"%s\"",
150 field_name);
4f45f9bb
JD
151 goto error;
152 }
153
5cd6d0e5 154 if (bt_ctf_field_class_integer_get_signed(field_class) != 0) {
b4d4912f
JD
155 BT_LOGE("Wrong type, expected unsigned integer: field-name=\"%s\"",
156 field_name);
4f45f9bb
JD
157 goto error;
158 }
159
50842bdc 160 ret = bt_field_unsigned_integer_get_value(field, value);
b4d4912f
JD
161 if (ret) {
162 BT_LOGE("Failed to get value: field-name=\"%s\"",
163 field_name);
164 goto error;
165 }
4f45f9bb
JD
166 goto end;
167
168error:
169 ret = -1;
170end:
65300d60
PP
171 bt_object_put_ref(field_class);
172 bt_object_put_ref(field);
4f45f9bb
JD
173 return ret;
174}
175
176BT_HIDDEN
40f4ba76 177int get_stream_event_context_int_field_value(FILE *err, const struct bt_event *event,
4f45f9bb
JD
178 const char *field_name, int64_t *value)
179{
40f4ba76
PP
180 const struct bt_field *field = NULL;
181 const struct bt_field_class *field_class = NULL;
4f45f9bb
JD
182 int ret;
183
184 field = get_stream_event_context_field(err, event, field_name);
185 if (!field) {
186 goto error;
187 }
188
5cd6d0e5
PP
189 field_class = bt_field_get_class(field);
190 BT_ASSERT(field_class);
4f45f9bb 191
864cad70 192 if (bt_field_class_id(field_class) != BT_FIELD_CLASS_TYPE_INTEGER) {
b4d4912f 193 BT_LOGE("Wrong type, expected integer: field-name=\"%s\"", field_name);
4f45f9bb
JD
194 goto error;
195 }
196
5cd6d0e5 197 if (bt_ctf_field_class_integer_get_signed(field_class) != 1) {
b4d4912f
JD
198 BT_LOGE("Wrong type, expected signed integer: field-name=\"%s\"",
199 field_name);
4f45f9bb
JD
200 goto error;
201 }
202
50842bdc 203 ret = bt_field_signed_integer_get_value(field, value);
4f45f9bb
JD
204 goto end;
205
206error:
207 ret = -1;
208end:
65300d60
PP
209 bt_object_put_ref(field_class);
210 bt_object_put_ref(field);
4f45f9bb
JD
211 return ret;
212}
213
214BT_HIDDEN
215int get_payload_unsigned_int_field_value(FILE *err,
40f4ba76 216 const struct bt_event *event, const char *field_name,
4f45f9bb
JD
217 uint64_t *value)
218{
40f4ba76
PP
219 const struct bt_field *field = NULL;
220 const struct bt_field_class *field_class = NULL;
4f45f9bb
JD
221 int ret;
222
223 field = get_payload_field(err, event, field_name);
224 if (!field) {
b4d4912f 225 BT_LOGE("Failed to get payload: field-name=\"%s\"", field_name);
4f45f9bb
JD
226 goto error;
227 }
228
5cd6d0e5
PP
229 field_class = bt_field_get_class(field);
230 BT_ASSERT(field_class);
4f45f9bb 231
864cad70 232 if (bt_field_class_id(field_class) != BT_FIELD_CLASS_TYPE_INTEGER) {
b4d4912f
JD
233 BT_LOGE("Wrong type, expected integer: field-name=\"%s\"",
234 field_name);
4f45f9bb
JD
235 goto error;
236 }
237
5cd6d0e5 238 if (bt_ctf_field_class_integer_get_signed(field_class) != 0) {
b4d4912f
JD
239 BT_LOGE("Wrong type, expected unsigned integer: field-name=\"%s\"",
240 field_name);
4f45f9bb
JD
241 goto error;
242 }
243
50842bdc 244 ret = bt_field_unsigned_integer_get_value(field, value);
b4d4912f
JD
245 if (ret) {
246 BT_LOGE("Failed to get value: field-name=\"%s\"",
247 field_name);
248 goto error;
249 }
4f45f9bb
JD
250 goto end;
251
252error:
253 ret = -1;
254end:
65300d60
PP
255 bt_object_put_ref(field_class);
256 bt_object_put_ref(field);
4f45f9bb
JD
257 return ret;
258}
259
260BT_HIDDEN
40f4ba76 261int get_payload_int_field_value(FILE *err, const struct bt_event *event,
4f45f9bb
JD
262 const char *field_name, int64_t *value)
263{
40f4ba76
PP
264 const struct bt_field *field = NULL;
265 const struct bt_field_class *field_class = NULL;
4f45f9bb
JD
266 int ret;
267
268 field = get_payload_field(err, event, field_name);
269 if (!field) {
b4d4912f 270 BT_LOGE("Failed to get payload: field-name=\"%s\"", field_name);
4f45f9bb
JD
271 goto error;
272 }
273
5cd6d0e5
PP
274 field_class = bt_field_get_class(field);
275 BT_ASSERT(field_class);
4f45f9bb 276
864cad70 277 if (bt_field_class_id(field_class) != BT_FIELD_CLASS_TYPE_INTEGER) {
b4d4912f 278 BT_LOGE("Wrong type, expected integer: field-name=\"%s\"", field_name);
4f45f9bb
JD
279 goto error;
280 }
281
5cd6d0e5 282 if (bt_ctf_field_class_integer_get_signed(field_class) != 1) {
b4d4912f
JD
283 BT_LOGE("Wrong type, expected signed integer field-name=\"%s\"",
284 field_name);
4f45f9bb
JD
285 goto error;
286 }
287
50842bdc 288 ret = bt_field_signed_integer_get_value(field, value);
b4d4912f
JD
289 if (ret) {
290 BT_LOGE("Failed to get value: field-name=\"%s\"",
291 field_name);
292 goto error;
293 }
4f45f9bb
JD
294 goto end;
295
296error:
297 ret = -1;
298end:
65300d60
PP
299 bt_object_put_ref(field_class);
300 bt_object_put_ref(field);
4f45f9bb
JD
301 return ret;
302}
303
304BT_HIDDEN
305int get_payload_string_field_value(FILE *err,
40f4ba76 306 const struct bt_event *event, const char *field_name,
4f45f9bb
JD
307 const char **value)
308{
40f4ba76
PP
309 const struct bt_field *field = NULL;
310 const struct bt_field_class *field_class = NULL;
4f45f9bb
JD
311 int ret;
312
65db8b88
JD
313 /*
314 * The field might not exist, no error here.
315 */
4f45f9bb
JD
316 field = get_payload_field(err, event, field_name);
317 if (!field) {
4f45f9bb
JD
318 goto error;
319 }
320
5cd6d0e5
PP
321 field_class = bt_field_get_class(field);
322 BT_ASSERT(field_class);
4f45f9bb 323
864cad70 324 if (bt_field_class_id(field_class) != BT_FIELD_CLASS_TYPE_STRING) {
b4d4912f
JD
325 BT_LOGE("Wrong type, expected string: field-name=\"%s\"",
326 field_name);
4f45f9bb
JD
327 goto error;
328 }
329
50842bdc 330 *value = bt_field_string_get_value(field);
4f45f9bb 331 if (!*value) {
b4d4912f
JD
332 BT_LOGE("Failed to get value: field-name=\"%s\"",
333 field_name);
4f45f9bb
JD
334 goto error;
335 }
336
337 ret = 0;
338 goto end;
339
340error:
341 ret = -1;
342end:
65300d60
PP
343 bt_object_put_ref(field_class);
344 bt_object_put_ref(field);
4f45f9bb
JD
345 return ret;
346}
347
348BT_HIDDEN
349int get_payload_build_id_field_value(FILE *err,
40f4ba76 350 const struct bt_event *event, const char *field_name,
4f45f9bb
JD
351 uint8_t **build_id, uint64_t *build_id_len)
352{
40f4ba76
PP
353 const struct bt_field *field = NULL, *seq_len = NULL;
354 const struct bt_field_class *field_class = NULL;
355 const struct bt_field *seq_field = NULL;
4f45f9bb
JD
356 uint64_t i;
357 int ret;
358
359 *build_id = NULL;
360
361 field = get_payload_field(err, event, field_name);
362 if (!field) {
b4d4912f 363 BT_LOGE("Failed to get payload: field-name=\"%s\"", field_name);
4f45f9bb
JD
364 goto error;
365 }
366
5cd6d0e5
PP
367 field_class = bt_field_get_class(field);
368 BT_ASSERT(field_class);
4f45f9bb 369
864cad70 370 if (bt_field_class_id(field_class) != BT_FIELD_CLASS_TYPE_SEQUENCE) {
b4d4912f 371 BT_LOGE("Wrong type, expected sequence: field-name=\"%s\"", field_name);
4f45f9bb
JD
372 goto error;
373 }
65300d60 374 BT_OBJECT_PUT_REF_AND_RESET(field_class);
4f45f9bb 375
50842bdc 376 seq_len = bt_field_sequence_get_length(field);
f6ccaed9 377 BT_ASSERT(seq_len);
4f45f9bb 378
50842bdc 379 ret = bt_field_unsigned_integer_get_value(seq_len, build_id_len);
4f45f9bb 380 if (ret) {
b4d4912f
JD
381 BT_LOGE("Failed to get value: field-name=\"%s\"",
382 field_name);
4f45f9bb
JD
383 goto error;
384 }
65300d60 385 BT_OBJECT_PUT_REF_AND_RESET(seq_len);
4f45f9bb
JD
386
387 *build_id = g_new0(uint8_t, *build_id_len);
388 if (!*build_id) {
b4d4912f 389 BT_LOGE_STR("Failed to allocate build_id.");
4f45f9bb
JD
390 goto error;
391 }
392
393 for (i = 0; i < *build_id_len; i++) {
394 uint64_t tmp;
395
50842bdc 396 seq_field = bt_field_sequence_get_field(field, i);
4f45f9bb 397 if (!seq_field) {
b4d4912f
JD
398 BT_LOGE("Failed to get field in sequence: sequence-name=\"%s\", index=%" PRIu64,
399 field_name, i);
4f45f9bb
JD
400 goto error;
401 }
402
50842bdc 403 ret = bt_field_unsigned_integer_get_value(seq_field, &tmp);
4f45f9bb 404 if (ret) {
b4d4912f
JD
405 BT_LOGE("Failed to get value: field-name=\"%s\"",
406 field_name);
4f45f9bb
JD
407 goto error;
408 }
b4d4912f 409
65300d60 410 BT_OBJECT_PUT_REF_AND_RESET(seq_field);
4f45f9bb
JD
411 (*build_id)[i] = (uint8_t) tmp;
412 }
413 ret = 0;
414 goto end;
415
416error:
417 g_free(*build_id);
418 ret = -1;
419end:
65300d60
PP
420 bt_object_put_ref(field_class);
421 bt_object_put_ref(field);
4f45f9bb
JD
422 return ret;
423}
424
425static
426struct debug_info *lookup_trace_debug_info(struct debug_info_iterator *debug_it,
40f4ba76 427 const struct bt_trace *writer_trace,
504db471 428 struct debug_info_trace *di_trace)
4f45f9bb
JD
429{
430 return (struct debug_info *) g_hash_table_lookup(
504db471 431 di_trace->trace_debug_map,
4f45f9bb
JD
432 (gpointer) writer_trace);
433}
434
435static
436struct debug_info *insert_new_debug_info(struct debug_info_iterator *debug_it,
40f4ba76 437 const struct bt_trace *writer_trace,
504db471 438 struct debug_info_trace *di_trace)
4f45f9bb
JD
439{
440 struct debug_info *debug_info = NULL;
441 struct bt_value *field = NULL;
442 const char *str_value;
443 enum bt_value_status ret;
444
50842bdc 445 field = bt_trace_get_environment_field_value_by_name(writer_trace,
4f45f9bb
JD
446 "domain");
447 /* No domain field, no debug info */
448 if (!field) {
449 goto end;
450 }
601b0d3c 451 str_value = bt_value_string_get(field);
b4d4912f 452
4f45f9bb
JD
453 /* Domain not ust, no debug info */
454 if (strcmp(str_value, "ust") != 0) {
455 goto end;
456 }
65300d60 457 BT_OBJECT_PUT_REF_AND_RESET(field);
4f45f9bb
JD
458
459 /* No tracer_name, no debug info */
50842bdc 460 field = bt_trace_get_environment_field_value_by_name(writer_trace,
4f45f9bb
JD
461 "tracer_name");
462 /* No tracer_name, no debug info */
463 if (!field) {
464 goto end;
465 }
601b0d3c 466 str_value = bt_value_string_get(field);
b4d4912f 467
4f45f9bb
JD
468 /* Tracer_name not lttng-ust, no debug info */
469 if (strcmp(str_value, "lttng-ust") != 0) {
470 goto end;
471 }
65300d60 472 BT_OBJECT_PUT_REF_AND_RESET(field);
4f45f9bb 473
9d325e17 474 debug_info = debug_info_create(debug_it->debug_info_component);
4f45f9bb 475 if (!debug_info) {
b4d4912f 476 BT_LOGE_STR("Failed to create debug info.");
4f45f9bb
JD
477 goto end;
478 }
479
504db471 480 g_hash_table_insert(di_trace->trace_debug_map, (gpointer) writer_trace,
4f45f9bb
JD
481 debug_info);
482
483end:
65300d60 484 bt_object_put_ref(field);
4f45f9bb
JD
485 return debug_info;
486}
487
488static
489struct debug_info *get_trace_debug_info(struct debug_info_iterator *debug_it,
40f4ba76 490 const struct bt_trace *writer_trace,
504db471 491 struct debug_info_trace *di_trace)
4f45f9bb
JD
492{
493 struct debug_info *debug_info;
494
504db471 495 debug_info = lookup_trace_debug_info(debug_it, writer_trace, di_trace);
4f45f9bb
JD
496 if (debug_info) {
497 goto end;
498 }
499
504db471 500 debug_info = insert_new_debug_info(debug_it, writer_trace, di_trace);
4f45f9bb
JD
501
502end:
503 return debug_info;
504}
505
506static
504db471 507struct debug_info_trace *lookup_trace(struct debug_info_iterator *debug_it,
40f4ba76 508 const struct bt_trace *trace)
4f45f9bb 509{
504db471 510 return (struct debug_info_trace *) g_hash_table_lookup(
4f45f9bb
JD
511 debug_it->trace_map,
512 (gpointer) trace);
513}
514
1c78e839
JD
515static
516enum debug_info_stream_state *insert_new_stream_state(
517 struct debug_info_iterator *debug_it,
40f4ba76 518 struct debug_info_trace *di_trace, const struct bt_stream *stream)
1c78e839
JD
519{
520 enum debug_info_stream_state *v = NULL;
521
522 v = g_new0(enum debug_info_stream_state, 1);
523 if (!v) {
b4d4912f 524 BT_LOGE_STR("Failed to allocate debug_info_stream_state.");
ec273a88 525 goto end;
1c78e839
JD
526 }
527 *v = DEBUG_INFO_UNKNOWN_STREAM;
528
529 g_hash_table_insert(di_trace->stream_states, stream, v);
530
ec273a88 531end:
1c78e839
JD
532 return v;
533}
534
535static
536void check_completed_trace(gpointer key, gpointer value, gpointer user_data)
537{
538 enum debug_info_stream_state *state = value;
539 int *trace_completed = user_data;
540
541 if (*state != DEBUG_INFO_COMPLETED_STREAM) {
542 *trace_completed = 0;
543 }
544}
545
546static
547gboolean empty_ht(gpointer key, gpointer value, gpointer user_data)
548{
549 return TRUE;
550}
551
552BT_HIDDEN
553void debug_info_close_trace(struct debug_info_iterator *debug_it,
554 struct debug_info_trace *di_trace)
555{
ec273a88 556 if (di_trace->static_listener_id >= 0) {
50842bdc 557 bt_trace_remove_is_static_listener(di_trace->trace,
1c78e839
JD
558 di_trace->static_listener_id);
559 }
560
561 /* Empty the stream class HT. */
562 g_hash_table_foreach_remove(di_trace->stream_class_map,
563 empty_ht, NULL);
564 g_hash_table_destroy(di_trace->stream_class_map);
565
566 /* Empty the stream HT. */
567 g_hash_table_foreach_remove(di_trace->stream_map,
568 empty_ht, NULL);
569 g_hash_table_destroy(di_trace->stream_map);
570
571 /* Empty the stream state HT. */
572 g_hash_table_foreach_remove(di_trace->stream_states,
573 empty_ht, NULL);
574 g_hash_table_destroy(di_trace->stream_states);
575
576 /* Empty the packet HT. */
577 g_hash_table_foreach_remove(di_trace->packet_map,
578 empty_ht, NULL);
579 g_hash_table_destroy(di_trace->packet_map);
580
581 /* Empty the trace_debug HT. */
582 g_hash_table_foreach_remove(di_trace->trace_debug_map,
583 empty_ht, NULL);
584 g_hash_table_destroy(di_trace->trace_debug_map);
585}
586
cb0a5cf8
JD
587static
588int sync_event_classes(struct debug_info_iterator *debug_it,
40f4ba76
PP
589 const struct bt_stream *stream,
590 const struct bt_stream *writer_stream)
cb0a5cf8
JD
591{
592 int int_ret;
40f4ba76 593 const struct bt_stream_class *stream_class = NULL,
cb0a5cf8
JD
594 *writer_stream_class = NULL;
595 enum bt_component_status ret;
596
50842bdc 597 stream_class = bt_stream_get_class(stream);
f6ccaed9 598 BT_ASSERT(stream_class);
cb0a5cf8 599
50842bdc 600 writer_stream_class = bt_stream_get_class(writer_stream);
f6ccaed9 601 BT_ASSERT(writer_stream_class);
cb0a5cf8
JD
602
603 ret = ctf_copy_event_classes(debug_it->err, stream_class,
604 writer_stream_class);
605 if (ret != BT_COMPONENT_STATUS_OK) {
b4d4912f 606 BT_LOGE_STR("Failed to copy event classes.");
cb0a5cf8
JD
607 goto error;
608 }
609
610 int_ret = 0;
611 goto end;
612
613error:
614 int_ret = -1;
615end:
65300d60
PP
616 bt_object_put_ref(stream_class);
617 bt_object_put_ref(writer_stream_class);
cb0a5cf8
JD
618 return int_ret;
619}
620
1c78e839 621static
40f4ba76 622void trace_is_static_listener(const struct bt_trace *trace, void *data)
1c78e839
JD
623{
624 struct debug_info_trace *di_trace = data;
cb0a5cf8 625 int trace_completed = 1, ret, nr_stream, i;
40f4ba76
PP
626 const struct bt_stream *stream = NULL, *writer_stream = NULL;
627 const struct bt_trace *writer_trace = di_trace->writer_trace;
cb0a5cf8
JD
628
629 /*
630 * When the trace becomes static, make sure that we have all
631 * the event classes in our stream_class copies before setting it
632 * static as well.
633 */
50842bdc 634 nr_stream = bt_trace_get_stream_count(trace);
cb0a5cf8 635 for (i = 0; i < nr_stream; i++) {
50842bdc 636 stream = bt_trace_get_stream_by_index(trace, i);
f6ccaed9 637 BT_ASSERT(stream);
b4d4912f 638
50842bdc 639 writer_stream = bt_trace_get_stream_by_index(writer_trace, i);
f6ccaed9 640 BT_ASSERT(writer_stream);
b4d4912f 641
cb0a5cf8
JD
642 ret = sync_event_classes(di_trace->debug_it, stream, writer_stream);
643 if (ret) {
b4d4912f 644 BT_LOGE_STR("Failed to synchronize the event classes.");
cb0a5cf8
JD
645 goto error;
646 }
65300d60
PP
647 BT_OBJECT_PUT_REF_AND_RESET(stream);
648 BT_OBJECT_PUT_REF_AND_RESET(writer_stream);
cb0a5cf8 649 }
1c78e839 650
50842bdc 651 bt_trace_set_is_static(di_trace->writer_trace);
1c78e839
JD
652 di_trace->trace_static = 1;
653
654 g_hash_table_foreach(di_trace->stream_states,
655 check_completed_trace, &trace_completed);
656 if (trace_completed) {
657 debug_info_close_trace(di_trace->debug_it, di_trace);
658 g_hash_table_remove(di_trace->debug_it->trace_map,
659 di_trace->trace);
660 }
cb0a5cf8
JD
661
662error:
65300d60
PP
663 bt_object_put_ref(writer_stream);
664 bt_object_put_ref(stream);
1c78e839
JD
665}
666
4f45f9bb 667static
504db471 668struct debug_info_trace *insert_new_trace(struct debug_info_iterator *debug_it,
40f4ba76
PP
669 const struct bt_stream *stream) {
670 const struct bt_trace *writer_trace = NULL;
504db471 671 struct debug_info_trace *di_trace = NULL;
40f4ba76
PP
672 const struct bt_trace *trace = NULL;
673 const struct bt_stream_class *stream_class = NULL;
674 const struct bt_stream *writer_stream = NULL;
1c78e839 675 int ret, nr_stream, i;
4f45f9bb 676
50842bdc 677 writer_trace = bt_trace_create();
4f45f9bb 678 if (!writer_trace) {
b4d4912f 679 BT_LOGE_STR("Failed to create a new trace.");
4f45f9bb
JD
680 goto error;
681 }
504db471 682
50842bdc 683 stream_class = bt_stream_get_class(stream);
f6ccaed9 684 BT_ASSERT(stream_class);
504db471 685
50842bdc 686 trace = bt_stream_class_get_trace(stream_class);
f6ccaed9 687 BT_ASSERT(trace);
4f45f9bb
JD
688
689 ret = ctf_copy_trace(debug_it->err, trace, writer_trace);
690 if (ret != BT_COMPONENT_STATUS_OK) {
b4d4912f 691 BT_LOGE_STR("Failed to copy CTF trace.");
4f45f9bb
JD
692 goto error;
693 }
694
504db471
JD
695 di_trace = g_new0(struct debug_info_trace, 1);
696 if (!di_trace) {
b4d4912f 697 BT_LOGE_STR("Failed to allocate debug_info_trace.");
504db471
JD
698 goto error;
699 }
700
701 di_trace->trace = trace;
702 di_trace->writer_trace = writer_trace;
703 di_trace->debug_info_component = debug_it->debug_info_component;
1c78e839 704 di_trace->debug_it = debug_it;
504db471
JD
705 di_trace->stream_map = g_hash_table_new_full(g_direct_hash,
706 g_direct_equal, NULL, (GDestroyNotify) unref_stream);
707 di_trace->stream_class_map = g_hash_table_new_full(g_direct_hash,
708 g_direct_equal, NULL, (GDestroyNotify) unref_stream_class);
709 di_trace->packet_map = g_hash_table_new_full(g_direct_hash,
710 g_direct_equal, NULL, (GDestroyNotify) unref_packet);
711 di_trace->trace_debug_map = g_hash_table_new_full(g_direct_hash,
712 g_direct_equal, NULL, (GDestroyNotify) unref_debug_info);
1c78e839
JD
713 di_trace->stream_states = g_hash_table_new_full(g_direct_hash,
714 g_direct_equal, NULL, destroy_stream_state_key);
cb0a5cf8 715 g_hash_table_insert(debug_it->trace_map, (gpointer) trace, di_trace);
1c78e839
JD
716
717 /* Set all the existing streams in the unknown state. */
50842bdc 718 nr_stream = bt_trace_get_stream_count(trace);
1c78e839 719 for (i = 0; i < nr_stream; i++) {
50842bdc 720 stream = bt_trace_get_stream_by_index(trace, i);
f6ccaed9 721 BT_ASSERT(stream);
b4d4912f 722
1c78e839 723 insert_new_stream_state(debug_it, di_trace, stream);
cb0a5cf8
JD
724 writer_stream = insert_new_stream(debug_it, stream, di_trace);
725 if (!writer_stream) {
b4d4912f 726 BT_LOGE_STR("Failed to insert new stream.");
cb0a5cf8
JD
727 goto error;
728 }
65300d60 729 bt_object_get_ref(writer_stream);
cb0a5cf8
JD
730 ret = sync_event_classes(debug_it, stream, writer_stream);
731 if (ret) {
b4d4912f 732 BT_LOGE_STR("Failed to synchronize event classes.");
cb0a5cf8
JD
733 goto error;
734 }
65300d60
PP
735 BT_OBJECT_PUT_REF_AND_RESET(writer_stream);
736 BT_OBJECT_PUT_REF_AND_RESET(stream);
1c78e839
JD
737 }
738
739 /* Check if the trace is already static or register a listener. */
50842bdc 740 if (bt_trace_is_static(trace)) {
1c78e839
JD
741 di_trace->trace_static = 1;
742 di_trace->static_listener_id = -1;
50842bdc 743 bt_trace_set_is_static(writer_trace);
1c78e839 744 } else {
50842bdc 745 ret = bt_trace_add_is_static_listener(trace,
8480c8cc 746 trace_is_static_listener, NULL, di_trace);
f6ccaed9 747 BT_ASSERT(ret >= 0);
1c78e839
JD
748 di_trace->static_listener_id = ret;
749 }
504db471 750
504db471 751
4f45f9bb
JD
752 goto end;
753
754error:
65300d60 755 BT_OBJECT_PUT_REF_AND_RESET(writer_trace);
504db471
JD
756 g_free(di_trace);
757 di_trace = NULL;
4f45f9bb 758end:
65300d60
PP
759 bt_object_put_ref(stream);
760 bt_object_put_ref(writer_stream);
761 bt_object_put_ref(stream_class);
762 bt_object_put_ref(trace);
504db471 763 return di_trace;
4f45f9bb
JD
764}
765
766static
40f4ba76
PP
767const struct bt_packet *lookup_packet(struct debug_info_iterator *debug_it,
768 const struct bt_packet *packet,
504db471 769 struct debug_info_trace *di_trace)
4f45f9bb 770{
40f4ba76 771 return (const struct bt_packet *) g_hash_table_lookup(
504db471 772 di_trace->packet_map,
4f45f9bb
JD
773 (gpointer) packet);
774}
775
776static
40f4ba76
PP
777const struct bt_packet *insert_new_packet(struct debug_info_iterator *debug_it,
778 const struct bt_packet *packet,
779 const struct bt_stream *writer_stream,
504db471 780 struct debug_info_trace *di_trace)
4f45f9bb 781{
40f4ba76 782 const struct bt_packet *writer_packet;
387483fc 783 int ret;
4f45f9bb 784
50842bdc 785 writer_packet = bt_packet_create(writer_stream);
4f45f9bb 786 if (!writer_packet) {
b4d4912f 787 BT_LOGE_STR("Failed to create new packet.");
387483fc
JD
788 goto error;
789 }
790
791 ret = ctf_packet_copy_header(debug_it->err, packet, writer_packet);
792 if (ret) {
b4d4912f 793 BT_LOGE_STR("Failed to copy packet header.");
387483fc 794 goto error;
4f45f9bb 795 }
4f45f9bb 796
387483fc
JD
797 g_hash_table_insert(di_trace->packet_map, (gpointer) packet,
798 writer_packet);
799 goto end;
800
801error:
65300d60 802 BT_OBJECT_PUT_REF_AND_RESET(writer_packet);
4f45f9bb
JD
803end:
804 return writer_packet;
805}
806
807static
808int add_debug_info_fields(FILE *err,
40f4ba76 809 const struct bt_field_class *writer_event_context_class,
4f45f9bb
JD
810 struct debug_info_component *component)
811{
40f4ba76 812 const struct bt_field_class *ip_field = NULL, *debug_field_class = NULL,
5cd6d0e5
PP
813 *bin_field_class = NULL, *func_field_class = NULL,
814 *src_field_class = NULL;
4f45f9bb
JD
815 int ret = 0;
816
5cd6d0e5
PP
817 ip_field = bt_field_class_structure_get_field_class_by_name(
818 writer_event_context_class, IP_FIELD_NAME);
4f45f9bb
JD
819 /* No ip field, so no debug info. */
820 if (!ip_field) {
821 goto end;
822 }
65300d60 823 BT_OBJECT_PUT_REF_AND_RESET(ip_field);
4f45f9bb 824
5cd6d0e5
PP
825 debug_field_class = bt_field_class_structure_get_field_class_by_name(
826 writer_event_context_class,
4f45f9bb
JD
827 component->arg_debug_info_field_name);
828 /* Already existing debug_info field, no need to add it. */
5cd6d0e5 829 if (debug_field_class) {
4f45f9bb
JD
830 goto end;
831 }
832
5cd6d0e5
PP
833 debug_field_class = bt_field_class_structure_create();
834 if (!debug_field_class) {
b4d4912f 835 BT_LOGE_STR("Failed to create debug_info structure.");
4f45f9bb
JD
836 goto error;
837 }
838
5cd6d0e5
PP
839 bin_field_class = bt_field_class_string_create();
840 if (!bin_field_class) {
b4d4912f 841 BT_LOGE_STR("Failed to create string for field=bin.");
4f45f9bb
JD
842 goto error;
843 }
844
5cd6d0e5
PP
845 func_field_class = bt_field_class_string_create();
846 if (!func_field_class) {
b4d4912f 847 BT_LOGE_STR("Failed to create string for field=func.");
4f45f9bb
JD
848 goto error;
849 }
850
5cd6d0e5
PP
851 src_field_class = bt_field_class_string_create();
852 if (!src_field_class) {
b4d4912f 853 BT_LOGE_STR("Failed to create string for field=src.");
4f45f9bb
JD
854 goto error;
855 }
856
5cd6d0e5
PP
857 ret = bt_field_class_structure_add_field(debug_field_class,
858 bin_field_class, "bin");
4f45f9bb 859 if (ret) {
b4d4912f 860 BT_LOGE_STR("Failed to add a field to debug_info struct: field=bin.");
4f45f9bb
JD
861 goto error;
862 }
863
5cd6d0e5
PP
864 ret = bt_field_class_structure_add_field(debug_field_class,
865 func_field_class, "func");
4f45f9bb 866 if (ret) {
b4d4912f 867 BT_LOGE_STR("Failed to add a field to debug_info struct: field=func.");
4f45f9bb
JD
868 goto error;
869 }
870
5cd6d0e5
PP
871 ret = bt_field_class_structure_add_field(debug_field_class,
872 src_field_class, "src");
4f45f9bb 873 if (ret) {
b4d4912f 874 BT_LOGE_STR("Failed to add a field to debug_info struct: field=src.");
4f45f9bb
JD
875 goto error;
876 }
877
5cd6d0e5
PP
878 ret = bt_field_class_structure_add_field(writer_event_context_class,
879 debug_field_class, component->arg_debug_info_field_name);
4f45f9bb 880 if (ret) {
b4d4912f 881 BT_LOGE_STR("Failed to add debug_info field to event_context.");
4f45f9bb
JD
882 goto error;
883 }
884
885 ret = 0;
886 goto end;
887
888error:
65300d60 889 BT_OBJECT_PUT_REF_AND_RESET(debug_field_class);
4f45f9bb
JD
890 ret = -1;
891end:
65300d60
PP
892 bt_object_put_ref(src_field_class);
893 bt_object_put_ref(func_field_class);
894 bt_object_put_ref(bin_field_class);
895 bt_object_put_ref(debug_field_class);
4f45f9bb
JD
896 return ret;
897}
898
899static
5cd6d0e5 900int create_debug_info_event_context_class(FILE *err,
40f4ba76
PP
901 const struct bt_field_class *event_context_class,
902 const struct bt_field_class *writer_event_context_class,
4f45f9bb
JD
903 struct debug_info_component *component)
904{
905 int ret, nr_fields, i;
906
5cd6d0e5 907 nr_fields = bt_field_class_structure_get_field_count(event_context_class);
4f45f9bb 908 for (i = 0; i < nr_fields; i++) {
40f4ba76 909 const struct bt_field_class *field_class = NULL;
4f45f9bb
JD
910 const char *field_name;
911
5cd6d0e5
PP
912 if (bt_field_class_structure_get_field_by_index(event_context_class,
913 &field_name, &field_class, i) < 0) {
b4d4912f
JD
914 BT_LOGE("Failed to get a field from the event-context: field-name=\"%s\"",
915 field_name);
4f45f9bb
JD
916 goto error;
917 }
918
5cd6d0e5
PP
919 ret = bt_field_class_structure_add_field(writer_event_context_class,
920 field_class, field_name);
65300d60 921 BT_OBJECT_PUT_REF_AND_RESET(field_class);
4f45f9bb 922 if (ret) {
b4d4912f
JD
923 BT_LOGE("Failed to add a field to the event-context: field-name=\"%s\"",
924 field_name);
4f45f9bb
JD
925 goto error;
926 }
927 }
928
5cd6d0e5 929 ret = add_debug_info_fields(err, writer_event_context_class,
4f45f9bb
JD
930 component);
931 goto end;
932
933error:
934 ret = -1;
935end:
936 return ret;
937}
938
939static
40f4ba76
PP
940const struct bt_stream_class *copy_stream_class_debug_info(FILE *err,
941 const struct bt_stream_class *stream_class,
942 const struct bt_trace *writer_trace,
4f45f9bb
JD
943 struct debug_info_component *component)
944{
40f4ba76
PP
945 const struct bt_field_class *cls = NULL;
946 const struct bt_stream_class *writer_stream_class = NULL;
947 const struct bt_field_class *writer_event_context_class = NULL;
4f45f9bb 948 int ret_int;
50842bdc 949 const char *name = bt_stream_class_get_name(stream_class);
4f45f9bb 950
50842bdc 951 writer_stream_class = bt_stream_class_create_empty(name);
4f45f9bb 952 if (!writer_stream_class) {
b4d4912f 953 BT_LOGE_STR("Failed to create empty stream class.");
4f45f9bb
JD
954 goto error;
955 }
956
5cd6d0e5 957 type = bt_stream_class_get_packet_context_class(stream_class);
2d64a1eb 958 if (type) {
5cd6d0e5 959 ret_int = bt_stream_class_set_packet_context_class(
2d64a1eb
JD
960 writer_stream_class, type);
961 if (ret_int < 0) {
b4d4912f 962 BT_LOGE_STR("Failed to set packet_context type.");
2d64a1eb
JD
963 goto error;
964 }
65300d60 965 BT_OBJECT_PUT_REF_AND_RESET(type);
4f45f9bb 966 }
4f45f9bb 967
50842bdc 968 type = bt_stream_class_get_event_header_type(stream_class);
290b95cc 969 if (type) {
50842bdc 970 ret_int = bt_stream_class_set_event_header_type(
290b95cc
MD
971 writer_stream_class, type);
972 if (ret_int < 0) {
b4d4912f 973 BT_LOGE_STR("Failed to set event_header type.");
290b95cc
MD
974 goto error;
975 }
65300d60 976 BT_OBJECT_PUT_REF_AND_RESET(type);
4f45f9bb 977 }
4f45f9bb 978
5cd6d0e5 979 type = bt_stream_class_get_event_context_class(stream_class);
4f45f9bb 980 if (type) {
5cd6d0e5
PP
981 writer_event_context_class = bt_field_class_structure_create();
982 if (!writer_event_context_class) {
b4d4912f 983 BT_LOGE_STR("Failed to create writer_event_context struct type.");
4f45f9bb
JD
984 goto error;
985 }
5cd6d0e5
PP
986 ret_int = create_debug_info_event_context_class(err, type,
987 writer_event_context_class, component);
4f45f9bb 988 if (ret_int) {
b4d4912f 989 BT_LOGE_STR("Failed to create debug_info event_context type.");
4f45f9bb
JD
990 goto error;
991 }
65300d60 992 BT_OBJECT_PUT_REF_AND_RESET(type);
4f45f9bb 993
5cd6d0e5
PP
994 ret_int = bt_stream_class_set_event_context_class(
995 writer_stream_class, writer_event_context_class);
4f45f9bb 996 if (ret_int < 0) {
b4d4912f 997 BT_LOGE_STR("Failed to set event_context type.");
4f45f9bb
JD
998 goto error;
999 }
65300d60 1000 BT_OBJECT_PUT_REF_AND_RESET(writer_event_context_class);
4f45f9bb
JD
1001 }
1002
1003 goto end;
1004
1005error:
65300d60 1006 BT_OBJECT_PUT_REF_AND_RESET(writer_stream_class);
4f45f9bb 1007end:
65300d60
PP
1008 bt_object_put_ref(writer_event_context_class);
1009 bt_object_put_ref(type);
4f45f9bb
JD
1010 return writer_stream_class;
1011}
1012
1013/*
1014 * Add the original clock classes to the new trace, we do not need to copy
1015 * them, and if we did, we would have to manually inspect the stream class
1016 * to update the integers mapping to a clock.
1017 */
1018static
40f4ba76
PP
1019int add_clock_classes(FILE *err, const struct bt_trace *writer_trace,
1020 const struct bt_stream_class *writer_stream_class,
1021 const struct bt_trace *trace)
4f45f9bb
JD
1022{
1023 int ret, clock_class_count, i;
1024
50842bdc 1025 clock_class_count = bt_trace_get_clock_class_count(trace);
4f45f9bb
JD
1026
1027 for (i = 0; i < clock_class_count; i++) {
40f4ba76 1028 const struct bt_clock_class *clock_class =
50842bdc 1029 bt_trace_get_clock_class_by_index(trace, i);
40f4ba76 1030 const struct bt_clock_class *existing_clock_class = NULL;
4f45f9bb 1031
f6ccaed9 1032 BT_ASSERT(clock_class);
4f45f9bb 1033
50842bdc
PP
1034 existing_clock_class = bt_trace_get_clock_class_by_name(
1035 writer_trace, bt_clock_class_get_name(clock_class));
65300d60 1036 bt_object_put_ref(existing_clock_class);
30480ffe 1037 if (existing_clock_class) {
65300d60 1038 bt_object_put_ref(clock_class);
30480ffe
PP
1039 continue;
1040 }
1041
50842bdc 1042 ret = bt_trace_add_clock_class(writer_trace, clock_class);
65300d60 1043 BT_OBJECT_PUT_REF_AND_RESET(clock_class);
4f45f9bb 1044 if (ret != 0) {
b4d4912f 1045 BT_LOGE_STR("Failed to add clock_class.");
4f45f9bb
JD
1046 goto error;
1047 }
1048 }
1049
1050 ret = 0;
1051 goto end;
1052
1053error:
1054 ret = -1;
1055end:
1056 return ret;
1057
1058}
1059
1060static
40f4ba76 1061const struct bt_stream_class *insert_new_stream_class(
4f45f9bb 1062 struct debug_info_iterator *debug_it,
40f4ba76 1063 const struct bt_stream_class *stream_class)
4f45f9bb 1064{
40f4ba76
PP
1065 const struct bt_stream_class *writer_stream_class = NULL;
1066 const struct bt_trace *trace, *writer_trace = NULL;
504db471 1067 struct debug_info_trace *di_trace;
4f45f9bb
JD
1068 enum bt_component_status ret;
1069 int int_ret;
1070
50842bdc 1071 trace = bt_stream_class_get_trace(stream_class);
f6ccaed9 1072 BT_ASSERT(trace);
4f45f9bb 1073
504db471
JD
1074 di_trace = lookup_trace(debug_it, trace);
1075 if (!di_trace) {
b4d4912f 1076 BT_LOGE_STR("Failed to find existing trace.");
504db471
JD
1077 ret = BT_COMPONENT_STATUS_ERROR;
1078 goto error;
4f45f9bb 1079 }
504db471 1080 writer_trace = di_trace->writer_trace;
65300d60 1081 bt_object_get_ref(writer_trace);
4f45f9bb
JD
1082
1083 writer_stream_class = copy_stream_class_debug_info(debug_it->err, stream_class,
1084 writer_trace, debug_it->debug_info_component);
1085 if (!writer_stream_class) {
b4d4912f 1086 BT_LOGE_STR("Failed to copy stream class.");
4f45f9bb
JD
1087 goto error;
1088 }
1089
50842bdc 1090 int_ret = bt_trace_add_stream_class(writer_trace, writer_stream_class);
4f45f9bb 1091 if (int_ret) {
b4d4912f 1092 BT_LOGE_STR("Failed to add stream class.");
4f45f9bb
JD
1093 goto error;
1094 }
1095
1096 ret = add_clock_classes(debug_it->err, writer_trace,
1097 writer_stream_class, trace);
1098 if (ret != BT_COMPONENT_STATUS_OK) {
b4d4912f 1099 BT_LOGE_STR("Failed to add clock classes.");
4f45f9bb
JD
1100 goto error;
1101 }
4f45f9bb 1102
504db471 1103 g_hash_table_insert(di_trace->stream_class_map,
4f45f9bb
JD
1104 (gpointer) stream_class, writer_stream_class);
1105
1106 goto end;
1107
1108error:
65300d60 1109 BT_OBJECT_PUT_REF_AND_RESET(writer_stream_class);
4f45f9bb 1110end:
65300d60
PP
1111 bt_object_put_ref(trace);
1112 bt_object_put_ref(writer_trace);
4f45f9bb
JD
1113 return writer_stream_class;
1114}
1115
1116static
40f4ba76 1117const struct bt_stream *insert_new_stream(
4f45f9bb 1118 struct debug_info_iterator *debug_it,
40f4ba76 1119 const struct bt_stream *stream,
504db471 1120 struct debug_info_trace *di_trace)
4f45f9bb 1121{
40f4ba76
PP
1122 const struct bt_stream *writer_stream = NULL;
1123 const struct bt_stream_class *stream_class = NULL;
1124 const struct bt_stream_class *writer_stream_class = NULL;
b910013b 1125 int64_t id;
4f45f9bb 1126
50842bdc 1127 stream_class = bt_stream_get_class(stream);
f6ccaed9 1128 BT_ASSERT(stream_class);
504db471 1129
4f45f9bb 1130 writer_stream_class = g_hash_table_lookup(
504db471 1131 di_trace->stream_class_map,
4f45f9bb
JD
1132 (gpointer) stream_class);
1133
1134 if (!writer_stream_class) {
1135 writer_stream_class = insert_new_stream_class(debug_it,
1136 stream_class);
1137 if (!writer_stream_class) {
b4d4912f 1138 BT_LOGE_STR("Failed to insert new stream class.");
4f45f9bb
JD
1139 goto error;
1140 }
1141 }
65300d60 1142 bt_object_get_ref(writer_stream_class);
4f45f9bb 1143
50842bdc 1144 id = bt_stream_get_id(stream);
b910013b 1145 if (id < 0) {
50842bdc
PP
1146 writer_stream = bt_stream_create(writer_stream_class,
1147 bt_stream_get_name(stream));
b910013b 1148 } else {
50842bdc 1149 writer_stream = bt_stream_create_with_id(
b910013b 1150 writer_stream_class,
50842bdc 1151 bt_stream_get_name(stream), id);
b910013b
PP
1152 }
1153
4f45f9bb 1154 if (!writer_stream) {
b4d4912f 1155 BT_LOGE_STR("Failed to create writer_stream.");
4f45f9bb
JD
1156 goto error;
1157 }
1158
504db471 1159 g_hash_table_insert(di_trace->stream_map, (gpointer) stream,
4f45f9bb
JD
1160 writer_stream);
1161
1162 goto end;
1163
1164error:
65300d60 1165 BT_OBJECT_PUT_REF_AND_RESET(writer_stream);
4f45f9bb 1166end:
65300d60
PP
1167 bt_object_put_ref(stream_class);
1168 bt_object_put_ref(writer_stream_class);
4f45f9bb
JD
1169 return writer_stream;
1170}
1171
1172static
40f4ba76
PP
1173const struct bt_stream *lookup_stream(struct debug_info_iterator *debug_it,
1174 const struct bt_stream *stream,
504db471 1175 struct debug_info_trace *di_trace)
4f45f9bb 1176{
40f4ba76 1177 return (const struct bt_stream *) g_hash_table_lookup(
504db471 1178 di_trace->stream_map, (gpointer) stream);
4f45f9bb
JD
1179}
1180
1181static
40f4ba76
PP
1182const struct bt_event_class *get_event_class(struct debug_info_iterator *debug_it,
1183 const struct bt_stream_class *writer_stream_class,
1184 const struct bt_event_class *event_class)
4f45f9bb 1185{
50842bdc
PP
1186 return bt_stream_class_get_event_class_by_id(writer_stream_class,
1187 bt_event_class_get_id(event_class));
4f45f9bb
JD
1188}
1189
504db471
JD
1190static
1191struct debug_info_trace *lookup_di_trace_from_stream(
1192 struct debug_info_iterator *debug_it,
40f4ba76 1193 const struct bt_stream *stream)
504db471 1194{
40f4ba76
PP
1195 const struct bt_stream_class *stream_class = NULL;
1196 const struct bt_trace *trace = NULL;
504db471
JD
1197 struct debug_info_trace *di_trace = NULL;
1198
50842bdc 1199 stream_class = bt_stream_get_class(stream);
f6ccaed9 1200 BT_ASSERT(stream_class);
504db471 1201
50842bdc 1202 trace = bt_stream_class_get_trace(stream_class);
f6ccaed9 1203 BT_ASSERT(trace);
504db471
JD
1204
1205 di_trace = (struct debug_info_trace *) g_hash_table_lookup(
1206 debug_it->trace_map, (gpointer) trace);
1207
65300d60
PP
1208 BT_OBJECT_PUT_REF_AND_RESET(stream_class);
1209 BT_OBJECT_PUT_REF_AND_RESET(trace);
504db471
JD
1210 return di_trace;
1211}
1212
4f45f9bb 1213static
40f4ba76 1214const struct bt_stream *get_writer_stream(
4f45f9bb 1215 struct debug_info_iterator *debug_it,
40f4ba76 1216 const struct bt_packet *packet, const struct bt_stream *stream)
4f45f9bb 1217{
40f4ba76
PP
1218 const struct bt_stream_class *stream_class = NULL;
1219 const struct bt_stream *writer_stream = NULL;
504db471 1220 struct debug_info_trace *di_trace = NULL;
4f45f9bb 1221
50842bdc 1222 stream_class = bt_stream_get_class(stream);
f6ccaed9 1223 BT_ASSERT(stream_class);
4f45f9bb 1224
504db471
JD
1225 di_trace = lookup_di_trace_from_stream(debug_it, stream);
1226 if (!di_trace) {
b4d4912f 1227 BT_LOGE_STR("Failed to find existing trace from stream.");
504db471
JD
1228 goto error;
1229 }
1230
1231 writer_stream = lookup_stream(debug_it, stream, di_trace);
4f45f9bb 1232 if (!writer_stream) {
b4d4912f 1233 BT_LOGE_STR("Failed to find existing stream.");
504db471 1234 goto error;
4f45f9bb 1235 }
65300d60 1236 bt_object_get_ref(writer_stream);
4f45f9bb
JD
1237
1238 goto end;
1239
1240error:
65300d60 1241 BT_OBJECT_PUT_REF_AND_RESET(writer_stream);
4f45f9bb 1242end:
65300d60 1243 bt_object_put_ref(stream_class);
4f45f9bb
JD
1244 return writer_stream;
1245}
1246
1247BT_HIDDEN
40f4ba76 1248const struct bt_packet *debug_info_new_packet(
4f45f9bb 1249 struct debug_info_iterator *debug_it,
40f4ba76 1250 const struct bt_packet *packet)
4f45f9bb 1251{
40f4ba76
PP
1252 const struct bt_stream *stream = NULL, *writer_stream = NULL;
1253 const struct bt_packet *writer_packet = NULL;
1254 const struct bt_field *packet_context = NULL;
504db471 1255 struct debug_info_trace *di_trace;
4f45f9bb
JD
1256 int int_ret;
1257
50842bdc 1258 stream = bt_packet_get_stream(packet);
f6ccaed9 1259 BT_ASSERT(stream);
4f45f9bb
JD
1260
1261 writer_stream = get_writer_stream(debug_it, packet, stream);
1262 if (!writer_stream) {
b4d4912f 1263 BT_LOGE_STR("Failed to get writer stream.");
4f45f9bb
JD
1264 goto error;
1265 }
1266
504db471
JD
1267 di_trace = lookup_di_trace_from_stream(debug_it, stream);
1268 if (!di_trace) {
b4d4912f 1269 BT_LOGE_STR("Failed to find existing trace from stream.");
504db471
JD
1270 goto error;
1271 }
1272
4f45f9bb
JD
1273 /*
1274 * If a packet was already opened, close it and remove it from
1275 * the HT.
1276 */
504db471 1277 writer_packet = lookup_packet(debug_it, packet, di_trace);
4f45f9bb 1278 if (writer_packet) {
504db471 1279 g_hash_table_remove(di_trace->packet_map, packet);
65300d60 1280 BT_OBJECT_PUT_REF_AND_RESET(writer_packet);
4f45f9bb
JD
1281 }
1282
504db471
JD
1283 writer_packet = insert_new_packet(debug_it, packet, writer_stream,
1284 di_trace);
4f45f9bb 1285 if (!writer_packet) {
b4d4912f 1286 BT_LOGE_STR("Failed to insert new packet.");
4f45f9bb
JD
1287 goto error;
1288 }
4f45f9bb 1289
50842bdc 1290 packet_context = bt_packet_get_context(packet);
2d64a1eb 1291 if (packet_context) {
9877e1aa
JD
1292 int_ret = ctf_packet_copy_context(debug_it->err,
1293 packet, writer_stream, writer_packet);
1294 if (int_ret < 0) {
b4d4912f 1295 BT_LOGE_STR("Failed to copy packet context.");
2d64a1eb
JD
1296 goto error;
1297 }
65300d60 1298 BT_OBJECT_PUT_REF_AND_RESET(packet_context);
4f45f9bb
JD
1299 }
1300
65300d60 1301 bt_object_get_ref(writer_packet);
4f45f9bb
JD
1302 goto end;
1303
1304error:
1305
1306end:
65300d60
PP
1307 bt_object_put_ref(packet_context);
1308 bt_object_put_ref(writer_stream);
1309 bt_object_put_ref(stream);
4f45f9bb
JD
1310 return writer_packet;
1311}
1312
1313BT_HIDDEN
40f4ba76 1314const struct bt_packet *debug_info_close_packet(
4f45f9bb 1315 struct debug_info_iterator *debug_it,
40f4ba76 1316 const struct bt_packet *packet)
4f45f9bb 1317{
40f4ba76
PP
1318 const struct bt_packet *writer_packet = NULL;
1319 const struct bt_stream *stream = NULL;
504db471
JD
1320 struct debug_info_trace *di_trace;
1321
50842bdc 1322 stream = bt_packet_get_stream(packet);
f6ccaed9 1323 BT_ASSERT(stream);
504db471
JD
1324
1325 di_trace = lookup_di_trace_from_stream(debug_it, stream);
1326 if (!di_trace) {
b4d4912f 1327 BT_LOGE_STR("Failed to find trace from stream.");
504db471
JD
1328 goto end;
1329 }
4f45f9bb 1330
504db471 1331 writer_packet = lookup_packet(debug_it, packet, di_trace);
4f45f9bb 1332 if (!writer_packet) {
b4d4912f 1333 BT_LOGE_STR("Failed to find existing packet.");
4f45f9bb
JD
1334 goto end;
1335 }
65300d60 1336 bt_object_get_ref(writer_packet);
504db471 1337 g_hash_table_remove(di_trace->packet_map, packet);
4f45f9bb
JD
1338
1339end:
65300d60 1340 bt_object_put_ref(stream);
4f45f9bb
JD
1341 return writer_packet;
1342}
1343
504db471 1344BT_HIDDEN
40f4ba76 1345const struct bt_stream *debug_info_stream_begin(
504db471 1346 struct debug_info_iterator *debug_it,
40f4ba76 1347 const struct bt_stream *stream)
504db471 1348{
40f4ba76 1349 const struct bt_stream *writer_stream = NULL;
1c78e839 1350 enum debug_info_stream_state *state;
504db471
JD
1351 struct debug_info_trace *di_trace = NULL;
1352
1353 di_trace = lookup_di_trace_from_stream(debug_it, stream);
1354 if (!di_trace) {
1355 di_trace = insert_new_trace(debug_it, stream);
1356 if (!di_trace) {
b4d4912f 1357 BT_LOGE_STR("Failed to insert new trace.");
1c78e839 1358 goto error;
504db471
JD
1359 }
1360 }
1361
1c78e839
JD
1362 /* Set the stream as active */
1363 state = g_hash_table_lookup(di_trace->stream_states, stream);
1364 if (!state) {
1365 if (di_trace->trace_static) {
b4d4912f 1366 BT_LOGE_STR("Failed to add a new stream, trace is static.");
1c78e839
JD
1367 goto error;
1368 }
1369 state = insert_new_stream_state(debug_it, di_trace,
1370 stream);
ec273a88 1371 if (!state) {
b4d4912f 1372 BT_LOGE_STR("Failed to add new stream state.");
ec273a88
JD
1373 goto error;
1374 }
1c78e839
JD
1375 }
1376 if (*state != DEBUG_INFO_UNKNOWN_STREAM) {
b4d4912f 1377 BT_LOGE("Unexpected stream state: state=%d", *state);
1c78e839
JD
1378 goto error;
1379 }
1380 *state = DEBUG_INFO_ACTIVE_STREAM;
1381
cb0a5cf8
JD
1382 writer_stream = lookup_stream(debug_it, stream, di_trace);
1383 if (!writer_stream) {
1384 writer_stream = insert_new_stream(debug_it, stream, di_trace);
1385 }
65300d60 1386 bt_object_get_ref(writer_stream);
504db471 1387
1c78e839
JD
1388 goto end;
1389
1390error:
65300d60 1391 BT_OBJECT_PUT_REF_AND_RESET(writer_stream);
504db471
JD
1392end:
1393 return writer_stream;
1394}
1395
4f45f9bb 1396BT_HIDDEN
40f4ba76
PP
1397const struct bt_stream *debug_info_stream_end(struct debug_info_iterator *debug_it,
1398 const struct bt_stream *stream)
4f45f9bb 1399{
40f4ba76 1400 const struct bt_stream *writer_stream = NULL;
504db471 1401 struct debug_info_trace *di_trace = NULL;
1c78e839 1402 enum debug_info_stream_state *state;
504db471
JD
1403
1404 di_trace = lookup_di_trace_from_stream(debug_it, stream);
1405 if (!di_trace) {
b4d4912f 1406 BT_LOGE_STR("Failed to find existing trace from stream.");
1c78e839 1407 goto error;
504db471 1408 }
4f45f9bb 1409
504db471 1410 writer_stream = lookup_stream(debug_it, stream, di_trace);
4f45f9bb 1411 if (!writer_stream) {
b4d4912f 1412 BT_LOGE_STR("Failed to find existing stream.");
1c78e839 1413 goto error;
4f45f9bb 1414 }
1c78e839
JD
1415 /*
1416 * Take the ref on the stream and keep it until the notification
1417 * is created.
1418 */
65300d60 1419 bt_object_get_ref(writer_stream);
1c78e839
JD
1420
1421 state = g_hash_table_lookup(di_trace->stream_states, stream);
1422 if (*state != DEBUG_INFO_ACTIVE_STREAM) {
b4d4912f 1423 BT_LOGE("Unexpected stream state: state=%d", *state);
1c78e839
JD
1424 goto error;
1425 }
1426 *state = DEBUG_INFO_COMPLETED_STREAM;
1427
504db471 1428 g_hash_table_remove(di_trace->stream_map, stream);
4f45f9bb 1429
1c78e839
JD
1430 if (di_trace->trace_static) {
1431 int trace_completed = 1;
1432
1433 g_hash_table_foreach(di_trace->stream_states,
1434 check_completed_trace, &trace_completed);
1435 if (trace_completed) {
1436 debug_info_close_trace(debug_it, di_trace);
1437 g_hash_table_remove(debug_it->trace_map,
1438 di_trace->trace);
1439 }
1440 }
1441
1442 goto end;
1443
1444error:
65300d60 1445 BT_OBJECT_PUT_REF_AND_RESET(writer_stream);
1c78e839 1446
4f45f9bb
JD
1447end:
1448 return writer_stream;
1449}
1450
1451static
1452struct debug_info_source *lookup_debug_info(FILE *err,
40f4ba76 1453 const struct bt_event *event,
4f45f9bb
JD
1454 struct debug_info *debug_info)
1455{
1456 int64_t vpid;
1457 uint64_t ip;
1458 struct debug_info_source *dbg_info_src = NULL;
1459 int ret;
1460
1461 ret = get_stream_event_context_int_field_value(err, event,
c4838cef 1462 VPID_FIELD_NAME, &vpid);
4f45f9bb
JD
1463 if (ret) {
1464 goto end;
1465 }
1466
1467 ret = get_stream_event_context_unsigned_int_field_value(err, event,
c4838cef 1468 IP_FIELD_NAME, &ip);
4f45f9bb
JD
1469 if (ret) {
1470 goto end;
1471 }
1472
1473 /* Get debug info for this context. */
1474 dbg_info_src = debug_info_query(debug_info, vpid, ip);
1475
1476end:
1477 return dbg_info_src;
1478}
1479
1480static
40f4ba76 1481int set_debug_info_field(FILE *err, const struct bt_field *debug_field,
4f45f9bb
JD
1482 struct debug_info_source *dbg_info_src,
1483 struct debug_info_component *component)
1484{
2afcfbfb 1485 int i, nr_fields, ret = 0;
40f4ba76
PP
1486 const struct bt_field_class *debug_field_class = NULL;
1487 const struct bt_field *field = NULL;
1488 const struct bt_field_class *field_class = NULL;
4f45f9bb 1489
5cd6d0e5
PP
1490 debug_field_class = bt_field_get_class(debug_field);
1491 BT_ASSERT(debug_field_class);
4f45f9bb 1492
5cd6d0e5 1493 nr_fields = bt_field_class_structure_get_field_count(debug_field_class);
4f45f9bb
JD
1494 for (i = 0; i < nr_fields; i++) {
1495 const char *field_name;
1496
5cd6d0e5
PP
1497 if (bt_field_class_structure_get_field_by_index(debug_field_class,
1498 &field_name, &field_class, i) < 0) {
b4d4912f
JD
1499 BT_LOGE("Failed to get field from debug_info struct: field-name=\"%s\"",
1500 field_name);
4f45f9bb
JD
1501 goto error;
1502 }
65300d60 1503 BT_OBJECT_PUT_REF_AND_RESET(field_class);
4f45f9bb 1504
50842bdc 1505 field = bt_field_structure_get_field_by_index(debug_field, i);
4f45f9bb
JD
1506 if (!strcmp(field_name, "bin")) {
1507 if (dbg_info_src && dbg_info_src->bin_path) {
1508 GString *tmp = g_string_new(NULL);
1509
1510 if (component->arg_full_path) {
1511 g_string_printf(tmp, "%s%s",
1512 dbg_info_src->bin_path,
1513 dbg_info_src->bin_loc);
1514 } else {
1515 g_string_printf(tmp, "%s%s",
1516 dbg_info_src->short_bin_path,
1517 dbg_info_src->bin_loc);
1518 }
50842bdc 1519 ret = bt_field_string_set_value(field, tmp->str);
4f45f9bb
JD
1520 g_string_free(tmp, true);
1521 } else {
50842bdc 1522 ret = bt_field_string_set_value(field, "");
4f45f9bb
JD
1523 }
1524 } else if (!strcmp(field_name, "func")) {
1525 if (dbg_info_src && dbg_info_src->func) {
50842bdc 1526 ret = bt_field_string_set_value(field,
4f45f9bb
JD
1527 dbg_info_src->func);
1528 } else {
50842bdc 1529 ret = bt_field_string_set_value(field, "");
4f45f9bb
JD
1530 }
1531 } else if (!strcmp(field_name, "src")) {
1532 if (dbg_info_src && dbg_info_src->src_path) {
1533 GString *tmp = g_string_new(NULL);
1534
1535 if (component->arg_full_path) {
1536 g_string_printf(tmp, "%s:%" PRId64,
1537 dbg_info_src->src_path,
1538 dbg_info_src->line_no);
1539 } else {
1540 g_string_printf(tmp, "%s:%" PRId64,
1541 dbg_info_src->short_src_path,
1542 dbg_info_src->line_no);
1543 }
50842bdc 1544 ret = bt_field_string_set_value(field, tmp->str);
4f45f9bb
JD
1545 g_string_free(tmp, true);
1546 } else {
50842bdc 1547 ret = bt_field_string_set_value(field, "");
4f45f9bb
JD
1548 }
1549 }
65300d60 1550 BT_OBJECT_PUT_REF_AND_RESET(field);
4f45f9bb 1551 if (ret) {
b4d4912f
JD
1552 BT_LOGE("Failed to set value in debug-info struct: field-name=\"%s\"",
1553 field_name);
4f45f9bb
JD
1554 goto error;
1555 }
1556 }
1557 ret = 0;
1558 goto end;
1559
1560error:
1561 ret = -1;
1562end:
65300d60
PP
1563 bt_object_put_ref(field_class);
1564 bt_object_put_ref(field);
1565 bt_object_put_ref(debug_field_class);
4f45f9bb
JD
1566 return ret;
1567}
1568
1569static
1570int copy_set_debug_info_stream_event_context(FILE *err,
40f4ba76
PP
1571 const struct bt_field *event_context,
1572 const struct bt_event *event,
1573 const struct bt_event *writer_event,
4f45f9bb
JD
1574 struct debug_info *debug_info,
1575 struct debug_info_component *component)
1576{
40f4ba76 1577 const struct bt_field_class *writer_event_context_class = NULL,
5cd6d0e5 1578 *event_context_class = NULL;
40f4ba76
PP
1579 const struct bt_field *writer_event_context = NULL;
1580 const struct bt_field *field = NULL, *copy_field = NULL, *debug_field = NULL;
1581 const struct bt_field_class *field_class = NULL;
4f45f9bb
JD
1582 struct debug_info_source *dbg_info_src;
1583 int ret, nr_fields, i;
1584
50842bdc 1585 writer_event_context = bt_event_get_stream_event_context(writer_event);
f6ccaed9 1586 BT_ASSERT(writer_event_context);
4f45f9bb 1587
5cd6d0e5
PP
1588 writer_event_context_class = bt_field_get_class(writer_event_context);
1589 BT_ASSERT(writer_event_context_class);
4f45f9bb 1590
5cd6d0e5
PP
1591 event_context_class = bt_field_get_class(event_context);
1592 BT_ASSERT(event_context_class);
08b6e8e8 1593
4f45f9bb
JD
1594 /*
1595 * If it is not a structure, we did not modify it to add the debug info
1596 * fields, so just assign it as is.
1597 */
864cad70 1598 if (bt_field_class_id(writer_event_context_class) != BT_FIELD_CLASS_TYPE_STRUCT) {
50842bdc 1599 ret = bt_event_set_event_context(writer_event, event_context);
4f45f9bb
JD
1600 goto end;
1601 }
1602
1603 dbg_info_src = lookup_debug_info(err, event, debug_info);
1604
5cd6d0e5 1605 nr_fields = bt_field_class_structure_get_field_count(writer_event_context_class);
4f45f9bb
JD
1606 for (i = 0; i < nr_fields; i++) {
1607 const char *field_name;
1608
5cd6d0e5
PP
1609 if (bt_field_class_structure_get_field_by_index(writer_event_context_class,
1610 &field_name, &field_class, i) < 0) {
b4d4912f
JD
1611 BT_LOGE("Failed to get field from event-context: field-name=\"%s\"",
1612 field_name);
4f45f9bb
JD
1613 goto error;
1614 }
1615
08b6e8e8
JD
1616 /*
1617 * Prevent illegal access in the event_context.
1618 */
5cd6d0e5 1619 if (i < bt_field_class_structure_get_field_count(event_context_class)) {
50842bdc 1620 field = bt_field_structure_get_field_by_index(event_context, i);
08b6e8e8 1621 }
4f45f9bb
JD
1622 /*
1623 * The debug_info field, only exists in the writer event or
1624 * if it was set by a earlier pass of the debug_info plugin.
4f45f9bb
JD
1625 */
1626 if (!strcmp(field_name, component->arg_debug_info_field_name) &&
1627 !field) {
50842bdc 1628 debug_field = bt_field_structure_get_field_by_index(
4f45f9bb 1629 writer_event_context, i);
f6ccaed9 1630 BT_ASSERT(debug_field);
b4d4912f 1631
4f45f9bb
JD
1632 ret = set_debug_info_field(err, debug_field,
1633 dbg_info_src, component);
1634 if (ret) {
b4d4912f 1635 BT_LOGE_STR("Failed to set debug_info field.");
4f45f9bb
JD
1636 goto error;
1637 }
65300d60 1638 BT_OBJECT_PUT_REF_AND_RESET(debug_field);
4f45f9bb 1639 } else {
50842bdc 1640 copy_field = bt_field_copy(field);
4f45f9bb 1641 if (!copy_field) {
b4d4912f
JD
1642 BT_LOGE("Failed to copy field: field-name=\"%s\"",
1643 field_name);
4f45f9bb
JD
1644 goto error;
1645 }
1646
50842bdc 1647 ret = bt_field_structure_set_field_by_name(
2225de6b 1648 writer_event_context,
4f45f9bb
JD
1649 field_name, copy_field);
1650 if (ret) {
b4d4912f
JD
1651 BT_LOGE("Failed to set field: field-name=\"%s\"",
1652 field_name);
4f45f9bb
JD
1653 goto error;
1654 }
65300d60 1655 BT_OBJECT_PUT_REF_AND_RESET(copy_field);
4f45f9bb 1656 }
65300d60
PP
1657 BT_OBJECT_PUT_REF_AND_RESET(field_class);
1658 BT_OBJECT_PUT_REF_AND_RESET(field);
4f45f9bb
JD
1659 }
1660
1661 ret = 0;
1662 goto end;
1663
1664error:
1665 ret = -1;
1666end:
65300d60
PP
1667 bt_object_put_ref(event_context_class);
1668 bt_object_put_ref(writer_event_context_class);
1669 bt_object_put_ref(writer_event_context);
1670 bt_object_put_ref(field);
1671 bt_object_put_ref(copy_field);
1672 bt_object_put_ref(debug_field);
1673 bt_object_put_ref(field_class);
4f45f9bb
JD
1674 return ret;
1675}
1676
1677static
40f4ba76
PP
1678const struct bt_clock_class *stream_class_get_clock_class(FILE *err,
1679 const struct bt_stream_class *stream_class)
4f45f9bb 1680{
40f4ba76
PP
1681 const struct bt_trace *trace = NULL;
1682 const struct bt_clock_class *clock_class = NULL;
4f45f9bb 1683
50842bdc 1684 trace = bt_stream_class_get_trace(stream_class);
f6ccaed9 1685 BT_ASSERT(trace);
4f45f9bb 1686
50842bdc 1687 if (!bt_trace_get_clock_class_count(trace)) {
290b95cc
MD
1688 /* No clock. */
1689 goto end;
1690 }
1691
4f45f9bb 1692 /* FIXME multi-clock? */
50842bdc 1693 clock_class = bt_trace_get_clock_class_by_index(trace, 0);
4f45f9bb 1694
65300d60 1695 bt_object_put_ref(trace);
4f45f9bb
JD
1696
1697end:
1698 return clock_class;
1699}
1700
1701static
40f4ba76 1702const struct bt_clock_class *event_get_clock_class(FILE *err, const struct bt_event *event)
4f45f9bb 1703{
40f4ba76
PP
1704 const struct bt_event_class *event_class = NULL;
1705 const struct bt_stream_class *stream_class = NULL;
1706 const struct bt_clock_class *clock_class = NULL;
4f45f9bb 1707
50842bdc 1708 event_class = bt_event_get_class(event);
f6ccaed9 1709 BT_ASSERT(event_class);
4f45f9bb 1710
50842bdc 1711 stream_class = bt_event_class_get_stream_class(event_class);
f6ccaed9 1712 BT_ASSERT(stream_class);
4f45f9bb
JD
1713
1714 clock_class = stream_class_get_clock_class(err, stream_class);
1715 goto end;
1716
4f45f9bb 1717end:
65300d60
PP
1718 bt_object_put_ref(stream_class);
1719 bt_object_put_ref(event_class);
4f45f9bb
JD
1720 return clock_class;
1721}
1722
1723static
40f4ba76
PP
1724int set_event_clock_value(FILE *err, const struct bt_event *event,
1725 const struct bt_event *writer_event)
4f45f9bb 1726{
40f4ba76 1727 const struct bt_clock_class *clock_class = NULL;
50842bdc 1728 struct bt_clock_value *clock_value = NULL;
1081db08 1729 int ret = 0;
4f45f9bb
JD
1730
1731 clock_class = event_get_clock_class(err, event);
1732 if (!clock_class) {
290b95cc
MD
1733 /* No clock on input trace. */
1734 goto end;
4f45f9bb
JD
1735 }
1736
50842bdc 1737 clock_value = bt_event_get_clock_value(event, clock_class);
4f45f9bb 1738 if (!clock_value) {
b4d4912f
JD
1739 ret = 0;
1740 goto end;
4f45f9bb
JD
1741 }
1742
1743 /*
1744 * We share the same clocks, so we can assign the clock value to the
1745 * writer event.
1746 */
50842bdc 1747 ret = bt_event_set_clock_value(writer_event, clock_value);
4f45f9bb 1748 if (ret) {
b4d4912f 1749 BT_LOGE_STR("Failed to set clock value.");
4f45f9bb
JD
1750 goto error;
1751 }
1752
1753 ret = 0;
1754 goto end;
1755
1756error:
1757 ret = -1;
1758end:
65300d60
PP
1759 bt_object_put_ref(clock_class);
1760 bt_object_put_ref(clock_value);
4f45f9bb
JD
1761 return ret;
1762}
1763
1764static
40f4ba76
PP
1765const struct bt_event *debug_info_copy_event(FILE *err, const struct bt_event *event,
1766 const struct bt_event_class *writer_event_class,
4f45f9bb
JD
1767 struct debug_info *debug_info,
1768 struct debug_info_component *component)
1769{
40f4ba76
PP
1770 const struct bt_event *writer_event = NULL;
1771 const struct bt_field *field = NULL, *copy_field = NULL;
4f45f9bb
JD
1772 int ret;
1773
50842bdc 1774 writer_event = bt_event_create(writer_event_class);
4f45f9bb 1775 if (!writer_event) {
b4d4912f 1776 BT_LOGE_STR("Failed to create new event.");
4f45f9bb
JD
1777 goto error;
1778 }
1779
1780 ret = set_event_clock_value(err, event, writer_event);
1781 if (ret) {
b4d4912f 1782 BT_LOGE_STR("Failed to set clock value.");
4f45f9bb
JD
1783 goto error;
1784 }
1785
60ef553b 1786 /* Optional field, so it can fail silently. */
50842bdc 1787 field = bt_event_get_header(event);
60ef553b
JD
1788 if (field) {
1789 ret = ctf_copy_event_header(err, event, writer_event_class,
1790 writer_event, field);
1791 if (ret) {
b4d4912f 1792 BT_LOGE_STR("Failed to copy event header.");
60ef553b
JD
1793 goto error;
1794 }
65300d60 1795 BT_OBJECT_PUT_REF_AND_RESET(field);
4f45f9bb 1796 }
4f45f9bb
JD
1797
1798 /* Optional field, so it can fail silently. */
50842bdc 1799 field = bt_event_get_stream_event_context(event);
4f45f9bb
JD
1800 if (field) {
1801 ret = copy_set_debug_info_stream_event_context(err,
1802 field, event, writer_event, debug_info,
1803 component);
1804 if (ret < 0) {
b4d4912f 1805 BT_LOGE_STR("Failed to debug_info stream event context.");
4f45f9bb
JD
1806 goto error;
1807 }
65300d60 1808 BT_OBJECT_PUT_REF_AND_RESET(field);
4f45f9bb
JD
1809 }
1810
1811 /* Optional field, so it can fail silently. */
50842bdc 1812 field = bt_event_get_event_context(event);
60ef553b 1813 if (field) {
50842bdc 1814 copy_field = bt_field_copy(field);
60ef553b 1815 if (!copy_field) {
b4d4912f 1816 BT_LOGE_STR("Failed to copy field.");
60ef553b
JD
1817 goto error;
1818 }
50842bdc 1819 ret = bt_event_set_event_context(writer_event, copy_field);
4f45f9bb 1820 if (ret < 0) {
b4d4912f 1821 BT_LOGE_STR("Failed to set event_context.");
4f45f9bb
JD
1822 goto error;
1823 }
65300d60
PP
1824 BT_OBJECT_PUT_REF_AND_RESET(copy_field);
1825 BT_OBJECT_PUT_REF_AND_RESET(field);
4f45f9bb 1826 }
4f45f9bb 1827
50842bdc 1828 field = bt_event_get_event_payload(event);
f6ccaed9 1829 BT_ASSERT(field);
b4d4912f 1830
50842bdc 1831 copy_field = bt_field_copy(field);
4f45f9bb 1832 if (copy_field) {
50842bdc 1833 ret = bt_event_set_event_payload(writer_event, copy_field);
4f45f9bb 1834 if (ret < 0) {
b4d4912f 1835 BT_LOGE_STR("Failed to set event payload.");
4f45f9bb
JD
1836 goto error;
1837 }
65300d60 1838 BT_OBJECT_PUT_REF_AND_RESET(copy_field);
4f45f9bb 1839 }
65300d60 1840 BT_OBJECT_PUT_REF_AND_RESET(field);
4f45f9bb
JD
1841
1842 goto end;
1843
1844error:
65300d60 1845 BT_OBJECT_PUT_REF_AND_RESET(writer_event);
4f45f9bb 1846end:
65300d60
PP
1847 bt_object_put_ref(copy_field);
1848 bt_object_put_ref(field);
4f45f9bb
JD
1849 return writer_event;
1850}
1851
1852BT_HIDDEN
40f4ba76 1853const struct bt_event *debug_info_output_event(
4f45f9bb 1854 struct debug_info_iterator *debug_it,
40f4ba76 1855 const struct bt_event *event)
4f45f9bb 1856{
40f4ba76
PP
1857 const struct bt_event_class *event_class = NULL, *writer_event_class = NULL;
1858 const struct bt_stream_class *stream_class = NULL, *writer_stream_class = NULL;
1859 const struct bt_event *writer_event = NULL;
1860 const struct bt_packet *packet = NULL, *writer_packet = NULL;
1861 const struct bt_trace *writer_trace = NULL;
1862 const struct bt_stream *stream = NULL;
504db471 1863 struct debug_info_trace *di_trace;
4f45f9bb 1864 struct debug_info *debug_info;
4f45f9bb
JD
1865 int int_ret;
1866
50842bdc 1867 event_class = bt_event_get_class(event);
f6ccaed9 1868 BT_ASSERT(event_class);
4f45f9bb 1869
50842bdc 1870 stream_class = bt_event_class_get_stream_class(event_class);
f6ccaed9 1871 BT_ASSERT(stream_class);
b4d4912f 1872
50842bdc 1873 stream = bt_event_get_stream(event);
f6ccaed9 1874 BT_ASSERT(stream);
b4d4912f 1875
504db471
JD
1876 di_trace = lookup_di_trace_from_stream(debug_it, stream);
1877 if (!di_trace) {
b4d4912f 1878 BT_LOGE_STR("Failed to find existing trace from stream.");
504db471
JD
1879 goto error;
1880 }
4f45f9bb
JD
1881
1882 writer_stream_class = g_hash_table_lookup(
504db471 1883 di_trace->stream_class_map,
4f45f9bb 1884 (gpointer) stream_class);
504db471 1885 if (!writer_stream_class) {
b4d4912f 1886 BT_LOGE_STR("Failed to find existing stream_class.");
4f45f9bb
JD
1887 goto error;
1888 }
65300d60 1889 bt_object_get_ref(writer_stream_class);
4a2fffdb 1890 writer_trace = bt_stream_class_get_trace(writer_stream_class);
f6ccaed9 1891 BT_ASSERT(writer_trace);
4f45f9bb
JD
1892 writer_event_class = get_event_class(debug_it,
1893 writer_stream_class, event_class);
1894 if (!writer_event_class) {
1895 writer_event_class = ctf_copy_event_class(debug_it->err,
4a2fffdb 1896 writer_trace, event_class);
4f45f9bb 1897 if (!writer_event_class) {
b4d4912f 1898 BT_LOGE_STR("Failed to copy event_class.");
4f45f9bb
JD
1899 goto error;
1900 }
50842bdc 1901 int_ret = bt_stream_class_add_event_class(
4f45f9bb
JD
1902 writer_stream_class, writer_event_class);
1903 if (int_ret) {
b4d4912f 1904 BT_LOGE_STR("Failed to add event_class.");
4f45f9bb
JD
1905 goto error;
1906 }
1907 }
1908
504db471 1909 debug_info = get_trace_debug_info(debug_it, writer_trace, di_trace);
4f45f9bb
JD
1910 if (debug_info) {
1911 debug_info_handle_event(debug_it->err, event, debug_info);
1912 }
1913
1914 writer_event = debug_info_copy_event(debug_it->err, event,
1915 writer_event_class, debug_info,
1916 debug_it->debug_info_component);
1917 if (!writer_event) {
b4d4912f 1918 BT_LOGE("Failed to copy event: event-class-name=\"%s\"",
50842bdc 1919 bt_event_class_get_name(writer_event_class));
4f45f9bb
JD
1920 goto error;
1921 }
1922
50842bdc 1923 packet = bt_event_get_packet(event);
f6ccaed9 1924 BT_ASSERT(packet);
4f45f9bb 1925
504db471 1926 writer_packet = lookup_packet(debug_it, packet, di_trace);
4f45f9bb 1927 if (!writer_packet) {
b4d4912f 1928 BT_LOGE_STR("Failed to find existing packet.");
4f45f9bb
JD
1929 goto error;
1930 }
65300d60 1931 bt_object_get_ref(writer_packet);
4f45f9bb 1932
50842bdc 1933 int_ret = bt_event_set_packet(writer_event, writer_packet);
4f45f9bb 1934 if (int_ret < 0) {
b4d4912f 1935 BT_LOGE("Failed to append event to event-class-name=\"%s\"",
50842bdc 1936 bt_event_class_get_name(writer_event_class));
4f45f9bb
JD
1937 goto error;
1938 }
1939
1940 /* Keep the reference on the writer event */
1941 goto end;
1942
1943error:
65300d60 1944 BT_OBJECT_PUT_REF_AND_RESET(writer_event);
4f45f9bb
JD
1945
1946end:
65300d60
PP
1947 bt_object_put_ref(stream);
1948 bt_object_put_ref(writer_trace);
1949 bt_object_put_ref(writer_packet);
1950 bt_object_put_ref(packet);
1951 bt_object_put_ref(writer_event_class);
1952 bt_object_put_ref(writer_stream_class);
1953 bt_object_put_ref(stream_class);
1954 bt_object_put_ref(event_class);
4f45f9bb
JD
1955 return writer_event;
1956}
This page took 0.135507 seconds and 4 git commands to generate.