9a552e7b09773682f13618ae5a28464b6cfaaebb
[babeltrace.git] / lib / ctf-ir / event.c
1 /*
2 * event.c
3 *
4 * Babeltrace CTF IR - Event
5 *
6 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 *
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
29 #define BT_LOG_TAG "EVENT"
30 #include <babeltrace/lib-logging-internal.h>
31
32 #include <babeltrace/ctf-ir/fields-internal.h>
33 #include <babeltrace/ctf-ir/field-types-internal.h>
34 #include <babeltrace/ctf-ir/clock-class.h>
35 #include <babeltrace/ctf-ir/clock-class-internal.h>
36 #include <babeltrace/ctf-ir/event-internal.h>
37 #include <babeltrace/ctf-ir/event-class.h>
38 #include <babeltrace/ctf-ir/event-class-internal.h>
39 #include <babeltrace/ctf-ir/stream-class.h>
40 #include <babeltrace/ctf-ir/stream-class-internal.h>
41 #include <babeltrace/ctf-ir/stream-internal.h>
42 #include <babeltrace/ctf-ir/packet.h>
43 #include <babeltrace/ctf-ir/packet-internal.h>
44 #include <babeltrace/ctf-ir/trace-internal.h>
45 #include <babeltrace/ctf-ir/validation-internal.h>
46 #include <babeltrace/ctf-ir/packet-internal.h>
47 #include <babeltrace/ctf-ir/utils.h>
48 #include <babeltrace/ctf-writer/serialize-internal.h>
49 #include <babeltrace/ref.h>
50 #include <babeltrace/ctf-ir/attributes-internal.h>
51 #include <babeltrace/compiler-internal.h>
52 #include <inttypes.h>
53
54 static
55 void bt_ctf_event_destroy(struct bt_object *obj);
56
57 struct bt_ctf_event *bt_ctf_event_create(struct bt_ctf_event_class *event_class)
58 {
59 int ret;
60 enum bt_ctf_validation_flag validation_flags =
61 BT_CTF_VALIDATION_FLAG_STREAM |
62 BT_CTF_VALIDATION_FLAG_EVENT;
63 struct bt_ctf_event *event = NULL;
64 struct bt_ctf_trace *trace = NULL;
65 struct bt_ctf_stream_class *stream_class = NULL;
66 struct bt_ctf_field_type *packet_header_type = NULL;
67 struct bt_ctf_field_type *packet_context_type = NULL;
68 struct bt_ctf_field_type *event_header_type = NULL;
69 struct bt_ctf_field_type *stream_event_ctx_type = NULL;
70 struct bt_ctf_field_type *event_context_type = NULL;
71 struct bt_ctf_field_type *event_payload_type = NULL;
72 struct bt_ctf_field *event_header = NULL;
73 struct bt_ctf_field *stream_event_context = NULL;
74 struct bt_ctf_field *event_context = NULL;
75 struct bt_ctf_field *event_payload = NULL;
76 struct bt_value *environment = NULL;
77 struct bt_ctf_validation_output validation_output = { 0 };
78 int trace_valid = 0;
79
80 BT_LOGD("Creating event object: event-class-addr=%p, "
81 "event-class-name=\"%s\", event-class-id=%" PRId64,
82 event_class, bt_ctf_event_class_get_name(event_class),
83 bt_ctf_event_class_get_id(event_class));
84
85 if (!event_class) {
86 BT_LOGW_STR("Invalid parameter: event class is NULL.");
87 goto error;
88 }
89
90 stream_class = bt_ctf_event_class_get_stream_class(event_class);
91
92 /*
93 * We disallow the creation of an event if its event class has not been
94 * associated to a stream class.
95 */
96 if (!stream_class) {
97 BT_LOGW_STR("Event class is not part of a stream class.");
98 goto error;
99 }
100
101 /* A stream class should always have an existing event header type */
102 assert(stream_class->event_header_type);
103
104 /* The event class was frozen when added to its stream class */
105 assert(event_class->frozen);
106
107 /* Validate the trace (if any), the stream class, and the event class */
108 trace = bt_ctf_stream_class_get_trace(stream_class);
109 if (trace) {
110 BT_LOGD_STR("Event's class is part of a trace.");
111 packet_header_type = bt_ctf_trace_get_packet_header_type(trace);
112 trace_valid = trace->valid;
113 assert(trace_valid);
114 environment = trace->environment;
115 }
116
117 packet_context_type = bt_ctf_stream_class_get_packet_context_type(
118 stream_class);
119 event_header_type = bt_ctf_stream_class_get_event_header_type(
120 stream_class);
121 stream_event_ctx_type = bt_ctf_stream_class_get_event_context_type(
122 stream_class);
123 event_context_type = bt_ctf_event_class_get_context_type(event_class);
124 event_payload_type = bt_ctf_event_class_get_payload_type(event_class);
125 ret = bt_ctf_validate_class_types(environment, packet_header_type,
126 packet_context_type, event_header_type, stream_event_ctx_type,
127 event_context_type, event_payload_type, trace_valid,
128 stream_class->valid, event_class->valid,
129 &validation_output, validation_flags);
130 BT_PUT(packet_header_type);
131 BT_PUT(packet_context_type);
132 BT_PUT(event_header_type);
133 BT_PUT(stream_event_ctx_type);
134 BT_PUT(event_context_type);
135 BT_PUT(event_payload_type);
136 if (ret) {
137 /*
138 * This means something went wrong during the validation
139 * process, not that the objects are invalid.
140 */
141 BT_LOGE("Failed to validate event and parents: ret=%d", ret);
142 goto error;
143 }
144
145 if ((validation_output.valid_flags & validation_flags) !=
146 validation_flags) {
147 /* Invalid trace/stream class/event class */
148 BT_LOGW("Invalid trace, stream class, or event class: "
149 "valid-flags=0x%x", validation_output.valid_flags);
150 goto error;
151 }
152
153 /*
154 * At this point we know the trace (if associated to the stream
155 * class), the stream class, and the event class, with their
156 * current types, are valid. We may proceed with creating
157 * the event.
158 */
159 event = g_new0(struct bt_ctf_event, 1);
160 if (!event) {
161 BT_LOGE_STR("Failed to allocate one event.");
162 goto error;
163 }
164
165 bt_object_init(event, bt_ctf_event_destroy);
166
167 /*
168 * event does not share a common ancestor with the event class; it has
169 * to guarantee its existence by holding a reference. This reference
170 * shall be released once the event is associated to a stream since,
171 * from that point, the event and its class will share the same
172 * lifetime.
173 */
174 event->event_class = bt_get(event_class);
175 event->clock_values = g_hash_table_new_full(g_direct_hash,
176 g_direct_equal, bt_put, bt_put);
177
178 if (validation_output.event_header_type) {
179 BT_LOGD("Creating initial event header field: ft-addr=%p",
180 validation_output.event_header_type);
181 event_header =
182 bt_ctf_field_create(validation_output.event_header_type);
183 if (!event_header) {
184 BT_LOGE_STR("Cannot create initial event header field object.");
185 goto error;
186 }
187 }
188
189 if (validation_output.stream_event_ctx_type) {
190 BT_LOGD("Creating initial stream event context field: ft-addr=%p",
191 validation_output.stream_event_ctx_type);
192 stream_event_context = bt_ctf_field_create(
193 validation_output.stream_event_ctx_type);
194 if (!stream_event_context) {
195 BT_LOGE_STR("Cannot create initial stream event context field object.");
196 goto error;
197 }
198 }
199
200 if (validation_output.event_context_type) {
201 BT_LOGD("Creating initial event context field: ft-addr=%p",
202 validation_output.event_context_type);
203 event_context = bt_ctf_field_create(
204 validation_output.event_context_type);
205 if (!event_context) {
206 BT_LOGE_STR("Cannot create initial event context field object.");
207 goto error;
208 }
209 }
210
211 if (validation_output.event_payload_type) {
212 BT_LOGD("Creating initial event payload field: ft-addr=%p",
213 validation_output.event_payload_type);
214 event_payload = bt_ctf_field_create(
215 validation_output.event_payload_type);
216 if (!event_payload) {
217 BT_LOGE_STR("Cannot create initial event payload field object.");
218 goto error;
219 }
220 }
221
222 /*
223 * At this point all the fields are created, potentially from
224 * validated copies of field types, so that the field types and
225 * fields can be replaced in the trace, stream class,
226 * event class, and created event.
227 */
228 bt_ctf_validation_replace_types(trace, stream_class,
229 event_class, &validation_output, validation_flags);
230 BT_MOVE(event->event_header, event_header);
231 BT_MOVE(event->stream_event_context, stream_event_context);
232 BT_MOVE(event->context_payload, event_context);
233 BT_MOVE(event->fields_payload, event_payload);
234
235 /*
236 * Put what was not moved in bt_ctf_validation_replace_types().
237 */
238 bt_ctf_validation_output_put_types(&validation_output);
239
240 /*
241 * Freeze the stream class since the event header must not be changed
242 * anymore.
243 */
244 bt_ctf_stream_class_freeze(stream_class);
245
246 /*
247 * Mark stream class, and event class as valid since
248 * they're all frozen now.
249 */
250 stream_class->valid = 1;
251 event_class->valid = 1;
252
253 /* Put stuff we borrowed from the event class */
254 BT_PUT(stream_class);
255 BT_PUT(trace);
256 BT_LOGD("Created event object: addr=%p, event-class-name=\"%s\", "
257 "event-class-id=%" PRId64,
258 event, bt_ctf_event_class_get_name(event->event_class),
259 bt_ctf_event_class_get_id(event_class));
260 return event;
261
262 error:
263 bt_ctf_validation_output_put_types(&validation_output);
264 BT_PUT(event);
265 BT_PUT(stream_class);
266 BT_PUT(trace);
267 BT_PUT(event_header);
268 BT_PUT(stream_event_context);
269 BT_PUT(event_context);
270 BT_PUT(event_payload);
271 assert(!packet_header_type);
272 assert(!packet_context_type);
273 assert(!event_header_type);
274 assert(!stream_event_ctx_type);
275 assert(!event_context_type);
276 assert(!event_payload_type);
277
278 return event;
279 }
280
281 struct bt_ctf_event_class *bt_ctf_event_get_class(struct bt_ctf_event *event)
282 {
283 struct bt_ctf_event_class *event_class = NULL;
284
285 if (!event) {
286 BT_LOGW_STR("Invalid parameter: event is NULL.");
287 goto end;
288 }
289
290 event_class = event ? bt_get(bt_ctf_event_borrow_event_class(event)) :
291 NULL;
292 end:
293 return event_class;
294 }
295
296 struct bt_ctf_stream *bt_ctf_event_get_stream(struct bt_ctf_event *event)
297 {
298 struct bt_ctf_stream *stream = NULL;
299
300 if (!event) {
301 BT_LOGW_STR("Invalid parameter: event is NULL.");
302 goto end;
303 }
304
305 /*
306 * If the event has a parent, then this is its (writer) stream.
307 * If the event has no parent, then if it has a packet, this
308 * is its (non-writer) stream.
309 */
310 if (event->base.parent) {
311 stream = (struct bt_ctf_stream *) bt_object_get_parent(event);
312 } else {
313 if (event->packet) {
314 stream = bt_get(event->packet->stream);
315 }
316 }
317
318 end:
319 return stream;
320 }
321
322 int bt_ctf_event_set_payload(struct bt_ctf_event *event,
323 const char *name,
324 struct bt_ctf_field *payload)
325 {
326 int ret = 0;
327
328 if (!event || !payload) {
329 BT_LOGW("Invalid parameter: event or payload field is NULL: "
330 "event-addr=%p, payload-field-addr=%p",
331 event, payload);
332 ret = -1;
333 goto end;
334 }
335
336 if (event->frozen) {
337 BT_LOGW("Invalid parameter: event is frozen: addr=%p, "
338 "event-class-name=\"%s\", event-class-id=%" PRId64,
339 event, bt_ctf_event_class_get_name(event->event_class),
340 bt_ctf_event_class_get_id(event->event_class));
341 ret = -1;
342 goto end;
343 }
344
345 if (name) {
346 ret = bt_ctf_field_structure_set_field(event->fields_payload,
347 name, payload);
348 } else {
349 struct bt_ctf_field_type *payload_type;
350
351 payload_type = bt_ctf_field_get_type(payload);
352
353 if (bt_ctf_field_type_compare(payload_type,
354 event->event_class->fields) == 0) {
355 bt_put(event->fields_payload);
356 bt_get(payload);
357 event->fields_payload = payload;
358 } else {
359 BT_LOGW("Invalid parameter: payload field type is different from the expected field type: "
360 "event-addr=%p, event-class-name=\"%s\", "
361 "event-class-id=%" PRId64,
362 event,
363 bt_ctf_event_class_get_name(event->event_class),
364 bt_ctf_event_class_get_id(event->event_class));
365 ret = -1;
366 }
367
368 bt_put(payload_type);
369 }
370
371 if (ret) {
372 BT_LOGW("Failed to set event's payload field: event-addr=%p, "
373 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
374 "payload-field-name=\"%s\", payload-field-addr=%p",
375 event, bt_ctf_event_class_get_name(event->event_class),
376 bt_ctf_event_class_get_id(event->event_class),
377 name, payload);
378 } else {
379 BT_LOGV("Set event's payload field: event-addr=%p, "
380 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
381 "payload-field-name=\"%s\", payload-field-addr=%p",
382 event, bt_ctf_event_class_get_name(event->event_class),
383 bt_ctf_event_class_get_id(event->event_class),
384 name, payload);
385 }
386
387 end:
388 return ret;
389 }
390
391 struct bt_ctf_field *bt_ctf_event_get_event_payload(struct bt_ctf_event *event)
392 {
393 struct bt_ctf_field *payload = NULL;
394
395 if (!event) {
396 BT_LOGW_STR("Invalid parameter: event is NULL.");
397 goto end;
398 }
399
400 if (!event->fields_payload) {
401 BT_LOGV("Event has no current payload field: addr=%p, "
402 "event-class-name=\"%s\", event-class-id=%" PRId64,
403 event, bt_ctf_event_class_get_name(event->event_class),
404 bt_ctf_event_class_get_id(event->event_class));
405 goto end;
406 }
407
408 payload = event->fields_payload;
409 bt_get(payload);
410 end:
411 return payload;
412 }
413
414 int bt_ctf_event_set_event_payload(struct bt_ctf_event *event,
415 struct bt_ctf_field *payload)
416 {
417 return bt_ctf_event_set_payload(event, NULL, payload);
418 }
419
420 struct bt_ctf_field *bt_ctf_event_get_payload(struct bt_ctf_event *event,
421 const char *name)
422 {
423 struct bt_ctf_field *field = NULL;
424
425 if (!event) {
426 BT_LOGW_STR("Invalid parameter: event is NULL.");
427 goto end;
428 }
429
430 if (name) {
431 field = bt_ctf_field_structure_get_field(event->fields_payload,
432 name);
433 } else {
434 field = event->fields_payload;
435 bt_get(field);
436 }
437 end:
438 return field;
439 }
440
441 struct bt_ctf_field *bt_ctf_event_get_payload_by_index(
442 struct bt_ctf_event *event, uint64_t index)
443 {
444 struct bt_ctf_field *field = NULL;
445
446 if (!event) {
447 BT_LOGW_STR("Invalid parameter: event is NULL.");
448 goto end;
449 }
450
451 field = bt_ctf_field_structure_get_field_by_index(event->fields_payload,
452 index);
453 end:
454 return field;
455 }
456
457 struct bt_ctf_field *bt_ctf_event_get_header(
458 struct bt_ctf_event *event)
459 {
460 struct bt_ctf_field *header = NULL;
461
462 if (!event) {
463 BT_LOGW_STR("Invalid parameter: event is NULL.");
464 goto end;
465 }
466
467 if (!event->event_header) {
468 BT_LOGV("Event has no current header field: addr=%p, "
469 "event-class-name=\"%s\", event-class-id=%" PRId64,
470 event, bt_ctf_event_class_get_name(event->event_class),
471 bt_ctf_event_class_get_id(event->event_class));
472 goto end;
473 }
474
475 header = event->event_header;
476 bt_get(header);
477 end:
478 return header;
479 }
480
481 int bt_ctf_event_set_header(struct bt_ctf_event *event,
482 struct bt_ctf_field *header)
483 {
484 int ret = 0;
485 struct bt_ctf_field_type *field_type = NULL;
486 struct bt_ctf_stream_class *stream_class = NULL;
487
488 if (!event) {
489 BT_LOGW_STR("Invalid parameter: event is NULL.");
490 ret = -1;
491 goto end;
492 }
493
494 if (event->frozen) {
495 BT_LOGW("Invalid parameter: event is frozen: addr=%p, "
496 "event-class-name=\"%s\", event-class-id=%" PRId64,
497 event, bt_ctf_event_class_get_name(event->event_class),
498 bt_ctf_event_class_get_id(event->event_class));
499 ret = -1;
500 goto end;
501 }
502
503 stream_class = (struct bt_ctf_stream_class *) bt_object_get_parent(
504 event->event_class);
505 /*
506 * Ensure the provided header's type matches the one registered to the
507 * stream class.
508 */
509 if (header) {
510 field_type = bt_ctf_field_get_type(header);
511 if (bt_ctf_field_type_compare(field_type,
512 stream_class->event_header_type)) {
513 BT_LOGW("Invalid parameter: header field type is different from the expected field type: "
514 "event-addr=%p, event-class-name=\"%s\", "
515 "event-class-id=%" PRId64,
516 event,
517 bt_ctf_event_class_get_name(event->event_class),
518 bt_ctf_event_class_get_id(event->event_class));
519 ret = -1;
520 goto end;
521 }
522 } else {
523 if (stream_class->event_header_type) {
524 BT_LOGW("Invalid parameter: setting no event header but event header field type is not NULL: "
525 "event-addr=%p, event-class-name=\"%s\", "
526 "event-class-id=%" PRId64 ", "
527 "event-header-ft-addr=%p",
528 event,
529 bt_ctf_event_class_get_name(event->event_class),
530 bt_ctf_event_class_get_id(event->event_class),
531 stream_class->event_header_type);
532 ret = -1;
533 goto end;
534 }
535 }
536
537 bt_put(event->event_header);
538 event->event_header = bt_get(header);
539 BT_LOGV("Set event's header field: event-addr=%p, "
540 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
541 "header-field-addr=%p",
542 event, bt_ctf_event_class_get_name(event->event_class),
543 bt_ctf_event_class_get_id(event->event_class), header);
544 end:
545 bt_put(stream_class);
546 bt_put(field_type);
547 return ret;
548 }
549
550 struct bt_ctf_field *bt_ctf_event_get_event_context(
551 struct bt_ctf_event *event)
552 {
553 struct bt_ctf_field *context = NULL;
554
555 if (!event) {
556 BT_LOGW_STR("Invalid parameter: event is NULL.");
557 goto end;
558 }
559
560 if (!event->context_payload) {
561 BT_LOGV("Event has no current context field: addr=%p, "
562 "event-class-name=\"%s\", event-class-id=%" PRId64,
563 event, bt_ctf_event_class_get_name(event->event_class),
564 bt_ctf_event_class_get_id(event->event_class));
565 goto end;
566 }
567
568 context = event->context_payload;
569 bt_get(context);
570 end:
571 return context;
572 }
573
574 int bt_ctf_event_set_event_context(struct bt_ctf_event *event,
575 struct bt_ctf_field *context)
576 {
577 int ret = 0;
578 struct bt_ctf_field_type *field_type = NULL;
579
580 if (!event) {
581 BT_LOGW_STR("Invalid parameter: event is NULL.");
582 ret = -1;
583 goto end;
584 }
585
586 if (event->frozen) {
587 BT_LOGW("Invalid parameter: event is frozen: addr=%p, "
588 "event-class-name=\"%s\", event-class-id=%" PRId64,
589 event, bt_ctf_event_class_get_name(event->event_class),
590 bt_ctf_event_class_get_id(event->event_class));
591 ret = -1;
592 goto end;
593 }
594
595 if (context) {
596 field_type = bt_ctf_field_get_type(context);
597
598 if (bt_ctf_field_type_compare(field_type,
599 event->event_class->context)) {
600 BT_LOGW("Invalid parameter: context field type is different from the expected field type: "
601 "event-addr=%p, event-class-name=\"%s\", "
602 "event-class-id=%" PRId64,
603 event,
604 bt_ctf_event_class_get_name(event->event_class),
605 bt_ctf_event_class_get_id(event->event_class));
606 ret = -1;
607 goto end;
608 }
609 } else {
610 if (event->event_class->context) {
611 BT_LOGW("Invalid parameter: setting no event context but event context field type is not NULL: "
612 "event-addr=%p, event-class-name=\"%s\", "
613 "event-class-id=%" PRId64 ", "
614 "event-context-ft-addr=%p",
615 event,
616 bt_ctf_event_class_get_name(event->event_class),
617 bt_ctf_event_class_get_id(event->event_class),
618 event->event_class->context);
619 ret = -1;
620 goto end;
621 }
622 }
623
624 bt_put(event->context_payload);
625 event->context_payload = bt_get(context);
626 BT_LOGV("Set event's context field: event-addr=%p, "
627 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
628 "context-field-addr=%p",
629 event, bt_ctf_event_class_get_name(event->event_class),
630 bt_ctf_event_class_get_id(event->event_class), context);
631 end:
632 bt_put(field_type);
633 return ret;
634 }
635
636 struct bt_ctf_field *bt_ctf_event_get_stream_event_context(
637 struct bt_ctf_event *event)
638 {
639 struct bt_ctf_field *stream_event_context = NULL;
640
641 if (!event) {
642 BT_LOGW_STR("Invalid parameter: event is NULL.");
643 goto end;
644 }
645
646 if (!event->stream_event_context) {
647 BT_LOGV("Event has no current stream event context field: addr=%p, "
648 "event-class-name=\"%s\", event-class-id=%" PRId64,
649 event, bt_ctf_event_class_get_name(event->event_class),
650 bt_ctf_event_class_get_id(event->event_class));
651 goto end;
652 }
653
654 stream_event_context = event->stream_event_context;
655 end:
656 return bt_get(stream_event_context);
657 }
658
659 int bt_ctf_event_set_stream_event_context(struct bt_ctf_event *event,
660 struct bt_ctf_field *stream_event_context)
661 {
662 int ret = 0;
663 struct bt_ctf_field_type *field_type = NULL;
664 struct bt_ctf_stream_class *stream_class = NULL;
665
666 if (!event) {
667 BT_LOGW_STR("Invalid parameter: event is NULL.");
668 ret = -1;
669 goto end;
670 }
671
672 if (event->frozen) {
673 BT_LOGW("Invalid parameter: event is frozen: addr=%p, "
674 "event-class-name=\"%s\", event-class-id=%" PRId64,
675 event, bt_ctf_event_class_get_name(event->event_class),
676 bt_ctf_event_class_get_id(event->event_class));
677 ret = -1;
678 goto end;
679 }
680
681 stream_class = bt_ctf_event_class_get_stream_class(event->event_class);
682 /*
683 * We should not have been able to create the event without associating
684 * the event class to a stream class.
685 */
686 assert(stream_class);
687
688 if (stream_event_context) {
689 field_type = bt_ctf_field_get_type(stream_event_context);
690 if (bt_ctf_field_type_compare(field_type,
691 stream_class->event_context_type)) {
692 BT_LOGW("Invalid parameter: stream event context field type is different from the expected field type: "
693 "event-addr=%p, event-class-name=\"%s\", "
694 "event-class-id=%" PRId64,
695 event,
696 bt_ctf_event_class_get_name(event->event_class),
697 bt_ctf_event_class_get_id(event->event_class));
698 ret = -1;
699 goto end;
700 }
701 } else {
702 if (stream_class->event_context_type) {
703 BT_LOGW("Invalid parameter: setting no stream event context but stream event context field type is not NULL: "
704 "event-addr=%p, event-class-name=\"%s\", "
705 "event-class-id=%" PRId64 ", "
706 "stream-event-context-ft-addr=%p",
707 event,
708 bt_ctf_event_class_get_name(event->event_class),
709 bt_ctf_event_class_get_id(event->event_class),
710 stream_class->event_context_type);
711 ret = -1;
712 goto end;
713 }
714 }
715
716 bt_get(stream_event_context);
717 BT_MOVE(event->stream_event_context, stream_event_context);
718 BT_LOGV("Set event's stream event context field: event-addr=%p, "
719 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
720 "stream-event-context-field-addr=%p",
721 event, bt_ctf_event_class_get_name(event->event_class),
722 bt_ctf_event_class_get_id(event->event_class),
723 stream_event_context);
724 end:
725 BT_PUT(stream_class);
726 bt_put(field_type);
727 return ret;
728 }
729
730 /* Pre-2.0 CTF writer backward compatibility */
731 void bt_ctf_event_get(struct bt_ctf_event *event)
732 {
733 bt_get(event);
734 }
735
736 /* Pre-2.0 CTF writer backward compatibility */
737 void bt_ctf_event_put(struct bt_ctf_event *event)
738 {
739 bt_put(event);
740 }
741
742 void bt_ctf_event_destroy(struct bt_object *obj)
743 {
744 struct bt_ctf_event *event;
745
746 event = container_of(obj, struct bt_ctf_event, base);
747 BT_LOGD("Destroying event: addr=%p, "
748 "event-class-name=\"%s\", event-class-id=%" PRId64,
749 event, bt_ctf_event_class_get_name(event->event_class),
750 bt_ctf_event_class_get_id(event->event_class));
751
752 if (!event->base.parent) {
753 /*
754 * Event was keeping a reference to its class since it shared no
755 * common ancestor with it to guarantee they would both have the
756 * same lifetime.
757 */
758 bt_put(event->event_class);
759 }
760 g_hash_table_destroy(event->clock_values);
761 BT_LOGD_STR("Putting event's header field.");
762 bt_put(event->event_header);
763 BT_LOGD_STR("Putting event's stream event context field.");
764 bt_put(event->stream_event_context);
765 BT_LOGD_STR("Putting event's context field.");
766 bt_put(event->context_payload);
767 BT_LOGD_STR("Putting event's payload field.");
768 bt_put(event->fields_payload);
769 BT_LOGD_STR("Putting event's packet.");
770 bt_put(event->packet);
771 g_free(event);
772 }
773
774 struct bt_ctf_clock_value *bt_ctf_event_get_clock_value(
775 struct bt_ctf_event *event, struct bt_ctf_clock_class *clock_class)
776 {
777 struct bt_ctf_clock_value *clock_value = NULL;
778
779 if (!event || !clock_class) {
780 BT_LOGW("Invalid parameter: event or clock class is NULL: "
781 "event-addr=%p, clock-class-addr=%p",
782 event, clock_class);
783 goto end;
784 }
785
786 clock_value = g_hash_table_lookup(event->clock_values, clock_class);
787 if (!clock_value) {
788 BT_LOGV("No clock value associated to the given clock class: "
789 "event-addr=%p, event-class-name=\"%s\", "
790 "event-class-id=%" PRId64 ", clock-class-addr=%p, "
791 "clock-class-name=\"%s\"", event,
792 bt_ctf_event_class_get_name(event->event_class),
793 bt_ctf_event_class_get_id(event->event_class),
794 clock_class, bt_ctf_clock_class_get_name(clock_class));
795 goto end;
796 }
797
798 bt_get(clock_value);
799 end:
800 return clock_value;
801 }
802
803 int bt_ctf_event_set_clock_value(struct bt_ctf_event *event,
804 struct bt_ctf_clock_value *value)
805 {
806 int ret = 0;
807 struct bt_ctf_trace *trace;
808 struct bt_ctf_stream_class *stream_class;
809 struct bt_ctf_event_class *event_class;
810 struct bt_ctf_clock_class *clock_class = NULL;
811
812 if (!event || !value) {
813 BT_LOGW("Invalid parameter: event or clock value is NULL: "
814 "event-addr=%p, clock-value-addr=%p",
815 event, value);
816 ret = -1;
817 goto end;
818 }
819
820 if (event->frozen) {
821 BT_LOGW("Invalid parameter: event is frozen: addr=%p, "
822 "event-class-name=\"%s\", event-class-id=%" PRId64,
823 event, bt_ctf_event_class_get_name(event->event_class),
824 bt_ctf_event_class_get_id(event->event_class));
825 ret = -1;
826 goto end;
827 }
828
829 clock_class = bt_ctf_clock_value_get_class(value);
830 event_class = bt_ctf_event_borrow_event_class(event);
831 assert(event_class);
832 stream_class = bt_ctf_event_class_borrow_stream_class(event_class);
833 assert(stream_class);
834 trace = bt_ctf_stream_class_borrow_trace(stream_class);
835 assert(trace);
836
837 if (!bt_ctf_trace_has_clock_class(trace, clock_class)) {
838 BT_LOGW("Invalid parameter: clock class is not part of event's trace: "
839 "event-addr=%p, event-class-name=\"%s\", "
840 "event-class-id=%" PRId64 ", clock-class-addr=%p, "
841 "clock-class-name=\"%s\"",
842 event, bt_ctf_event_class_get_name(event->event_class),
843 bt_ctf_event_class_get_id(event->event_class),
844 clock_class, bt_ctf_clock_class_get_name(clock_class));
845 ret = -1;
846 goto end;
847 }
848
849 g_hash_table_insert(event->clock_values, clock_class, bt_get(value));
850 BT_LOGV("Set event's clock value: "
851 "event-addr=%p, event-class-name=\"%s\", "
852 "event-class-id=%" PRId64 ", clock-class-addr=%p, "
853 "clock-class-name=\"%s\", clock-value-addr=%p, "
854 "clock-value-cycles=%" PRIu64,
855 event, bt_ctf_event_class_get_name(event->event_class),
856 bt_ctf_event_class_get_id(event->event_class),
857 clock_class, bt_ctf_clock_class_get_name(clock_class),
858 value, value->value);
859 clock_class = NULL;
860
861 end:
862 bt_put(clock_class);
863 return ret;
864 }
865
866 BT_HIDDEN
867 int bt_ctf_event_validate(struct bt_ctf_event *event)
868 {
869 /* Make sure each field's payload has been set */
870 int ret;
871 struct bt_ctf_stream_class *stream_class = NULL;
872
873 assert(event);
874 ret = bt_ctf_field_validate(event->event_header);
875 if (ret) {
876 BT_LOGD("Invalid event's header field: "
877 "event-addr=%p, event-class-name=\"%s\", "
878 "event-class-id=%" PRId64,
879 event, bt_ctf_event_class_get_name(event->event_class),
880 bt_ctf_event_class_get_id(event->event_class));
881 goto end;
882 }
883
884 stream_class = bt_ctf_event_class_get_stream_class(event->event_class);
885 /*
886 * We should not have been able to create the event without associating
887 * the event class to a stream class.
888 */
889 assert(stream_class);
890 if (stream_class->event_context_type) {
891 ret = bt_ctf_field_validate(event->stream_event_context);
892 if (ret) {
893 BT_LOGD("Invalid event's stream event context field: "
894 "event-addr=%p, event-class-name=\"%s\", "
895 "event-class-id=%" PRId64,
896 event,
897 bt_ctf_event_class_get_name(event->event_class),
898 bt_ctf_event_class_get_id(event->event_class));
899 goto end;
900 }
901 }
902
903 ret = bt_ctf_field_validate(event->fields_payload);
904 if (ret) {
905 BT_LOGD("Invalid event's payload field: "
906 "event-addr=%p, event-class-name=\"%s\", "
907 "event-class-id=%" PRId64,
908 event,
909 bt_ctf_event_class_get_name(event->event_class),
910 bt_ctf_event_class_get_id(event->event_class));
911 goto end;
912 }
913
914 if (event->event_class->context) {
915 BT_LOGD("Invalid event's context field: "
916 "event-addr=%p, event-class-name=\"%s\", "
917 "event-class-id=%" PRId64,
918 event,
919 bt_ctf_event_class_get_name(event->event_class),
920 bt_ctf_event_class_get_id(event->event_class));
921 ret = bt_ctf_field_validate(event->context_payload);
922 }
923 end:
924 bt_put(stream_class);
925 return ret;
926 }
927
928 BT_HIDDEN
929 int bt_ctf_event_serialize(struct bt_ctf_event *event,
930 struct bt_ctf_stream_pos *pos,
931 enum bt_ctf_byte_order native_byte_order)
932 {
933 int ret = 0;
934
935 assert(event);
936 assert(pos);
937
938 BT_LOGV_STR("Serializing event's context field.");
939 if (event->context_payload) {
940 ret = bt_ctf_field_serialize(event->context_payload, pos,
941 native_byte_order);
942 if (ret) {
943 BT_LOGW("Cannot serialize event's context field: "
944 "event-addr=%p, event-class-name=\"%s\", "
945 "event-class-id=%" PRId64,
946 event,
947 bt_ctf_event_class_get_name(event->event_class),
948 bt_ctf_event_class_get_id(event->event_class));
949 goto end;
950 }
951 }
952
953 BT_LOGV_STR("Serializing event's payload field.");
954 if (event->fields_payload) {
955 ret = bt_ctf_field_serialize(event->fields_payload, pos,
956 native_byte_order);
957 if (ret) {
958 BT_LOGW("Cannot serialize event's payload field: "
959 "event-addr=%p, event-class-name=\"%s\", "
960 "event-class-id=%" PRId64,
961 event,
962 bt_ctf_event_class_get_name(event->event_class),
963 bt_ctf_event_class_get_id(event->event_class));
964 goto end;
965 }
966 }
967 end:
968 return ret;
969 }
970
971 struct bt_ctf_packet *bt_ctf_event_get_packet(struct bt_ctf_event *event)
972 {
973 struct bt_ctf_packet *packet = NULL;
974
975 if (!event) {
976 BT_LOGW_STR("Invalid parameter: event is NULL.");
977 goto end;
978 }
979
980 if (!event->packet) {
981 BT_LOGV("Event has no current packet: addr=%p, "
982 "event-class-name=\"%s\", event-class-id=%" PRId64,
983 event, bt_ctf_event_class_get_name(event->event_class),
984 bt_ctf_event_class_get_id(event->event_class));
985 goto end;
986 }
987
988 packet = bt_get(event->packet);
989 end:
990 return packet;
991 }
992
993 int bt_ctf_event_set_packet(struct bt_ctf_event *event,
994 struct bt_ctf_packet *packet)
995 {
996 struct bt_ctf_stream_class *event_stream_class = NULL;
997 struct bt_ctf_stream_class *packet_stream_class = NULL;
998 struct bt_ctf_stream *stream = NULL;
999 int ret = 0;
1000
1001 if (!event || !packet) {
1002 BT_LOGW("Invalid parameter: event or packet is NULL: "
1003 "event-addr=%p, packet-addr=%p",
1004 event, packet);
1005 ret = -1;
1006 goto end;
1007 }
1008
1009 if (event->frozen) {
1010 BT_LOGW("Invalid parameter: event is frozen: addr=%p, "
1011 "event-class-name=\"%s\", event-class-id=%" PRId64,
1012 event, bt_ctf_event_class_get_name(event->event_class),
1013 bt_ctf_event_class_get_id(event->event_class));
1014 ret = -1;
1015 goto end;
1016 }
1017
1018 /*
1019 * Make sure the new packet was created by this event's
1020 * stream, if it is set.
1021 */
1022 stream = bt_ctf_event_get_stream(event);
1023 if (stream) {
1024 if (packet->stream != stream) {
1025 BT_LOGW("Invalid parameter: packet's stream and event's stream differ: "
1026 "event-addr=%p, event-class-name=\"%s\", "
1027 "event-class-id=%" PRId64 ", packet-stream-addr=%p, "
1028 "event-stream-addr=%p",
1029 event, bt_ctf_event_class_get_name(event->event_class),
1030 bt_ctf_event_class_get_id(event->event_class),
1031 packet->stream, stream);
1032 ret = -1;
1033 goto end;
1034 }
1035 } else {
1036 event_stream_class =
1037 bt_ctf_event_class_get_stream_class(event->event_class);
1038 packet_stream_class =
1039 bt_ctf_stream_get_class(packet->stream);
1040
1041 assert(event_stream_class);
1042 assert(packet_stream_class);
1043
1044 if (event_stream_class != packet_stream_class) {
1045 BT_LOGW("Invalid parameter: packet's stream class and event's stream class differ: "
1046 "event-addr=%p, event-class-name=\"%s\", "
1047 "event-class-id=%" PRId64 ", packet-stream-class-addr=%p, "
1048 "event-stream-class-addr=%p",
1049 event, bt_ctf_event_class_get_name(event->event_class),
1050 bt_ctf_event_class_get_id(event->event_class),
1051 packet_stream_class, event_stream_class);
1052 ret = -1;
1053 goto end;
1054 }
1055 }
1056
1057 bt_get(packet);
1058 BT_MOVE(event->packet, packet);
1059 BT_LOGV("Set event's packet: event-addr=%p, "
1060 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
1061 "packet-addr=%p",
1062 event, bt_ctf_event_class_get_name(event->event_class),
1063 bt_ctf_event_class_get_id(event->event_class), packet);
1064
1065 end:
1066 BT_PUT(stream);
1067 BT_PUT(event_stream_class);
1068 BT_PUT(packet_stream_class);
1069
1070 return ret;
1071 }
1072
1073 BT_HIDDEN
1074 void bt_ctf_event_freeze(struct bt_ctf_event *event)
1075 {
1076 assert(event);
1077
1078 if (event->frozen) {
1079 return;
1080 }
1081
1082 BT_LOGD("Freezing event: addr=%p, "
1083 "event-class-name=\"%s\", event-class-id=%" PRId64,
1084 event, bt_ctf_event_class_get_name(event->event_class),
1085 bt_ctf_event_class_get_id(event->event_class));
1086 bt_ctf_packet_freeze(event->packet);
1087 BT_LOGD_STR("Freezing event's header field.");
1088 bt_ctf_field_freeze(event->event_header);
1089 BT_LOGD_STR("Freezing event's stream event context field.");
1090 bt_ctf_field_freeze(event->stream_event_context);
1091 BT_LOGD_STR("Freezing event's context field.");
1092 bt_ctf_field_freeze(event->context_payload);
1093 BT_LOGD_STR("Freezing event's payload field.");
1094 bt_ctf_field_freeze(event->fields_payload);
1095 event->frozen = 1;
1096 }
This page took 0.049267 seconds and 3 git commands to generate.