lib: allow a single mapped clock class within a stream class
[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-value.h>
36 #include <babeltrace/ctf-ir/clock-value-internal.h>
37 #include <babeltrace/ctf-ir/clock-class-internal.h>
38 #include <babeltrace/ctf-ir/event-internal.h>
39 #include <babeltrace/ctf-ir/event-class.h>
40 #include <babeltrace/ctf-ir/event-class-internal.h>
41 #include <babeltrace/ctf-ir/stream-class.h>
42 #include <babeltrace/ctf-ir/stream-class-internal.h>
43 #include <babeltrace/ctf-ir/stream-internal.h>
44 #include <babeltrace/ctf-ir/packet.h>
45 #include <babeltrace/ctf-ir/packet-internal.h>
46 #include <babeltrace/ctf-ir/trace-internal.h>
47 #include <babeltrace/ctf-ir/validation-internal.h>
48 #include <babeltrace/ctf-ir/packet-internal.h>
49 #include <babeltrace/ctf-ir/utils.h>
50 #include <babeltrace/ctf-writer/serialize-internal.h>
51 #include <babeltrace/ctf-writer/clock-internal.h>
52 #include <babeltrace/ref.h>
53 #include <babeltrace/ctf-ir/attributes-internal.h>
54 #include <babeltrace/compiler-internal.h>
55 #include <inttypes.h>
56
57 static
58 void bt_event_destroy(struct bt_object *obj);
59
60 struct bt_event *bt_event_create(struct bt_event_class *event_class)
61 {
62 int ret;
63 enum bt_validation_flag validation_flags =
64 BT_VALIDATION_FLAG_STREAM |
65 BT_VALIDATION_FLAG_EVENT;
66 struct bt_event *event = NULL;
67 struct bt_trace *trace = NULL;
68 struct bt_stream_class *stream_class = NULL;
69 struct bt_field_type *packet_header_type = NULL;
70 struct bt_field_type *packet_context_type = NULL;
71 struct bt_field_type *event_header_type = NULL;
72 struct bt_field_type *stream_event_ctx_type = NULL;
73 struct bt_field_type *event_context_type = NULL;
74 struct bt_field_type *event_payload_type = NULL;
75 struct bt_field *event_header = NULL;
76 struct bt_field *stream_event_context = NULL;
77 struct bt_field *event_context = NULL;
78 struct bt_field *event_payload = NULL;
79 struct bt_value *environment = NULL;
80 struct bt_validation_output validation_output = { 0 };
81 int trace_valid = 0;
82 struct bt_clock_class *expected_clock_class = NULL;
83
84 BT_LOGD("Creating event object: event-class-addr=%p, "
85 "event-class-name=\"%s\", event-class-id=%" PRId64,
86 event_class, bt_event_class_get_name(event_class),
87 bt_event_class_get_id(event_class));
88
89 if (!event_class) {
90 BT_LOGW_STR("Invalid parameter: event class is NULL.");
91 goto error;
92 }
93
94 stream_class = bt_event_class_get_stream_class(event_class);
95
96 /*
97 * We disallow the creation of an event if its event class has not been
98 * associated to a stream class.
99 */
100 if (!stream_class) {
101 BT_LOGW_STR("Event class is not part of a stream class.");
102 goto error;
103 }
104
105 /* The event class was frozen when added to its stream class */
106 assert(event_class->frozen);
107
108 if (!stream_class->frozen) {
109 if (stream_class->clock) {
110 expected_clock_class =
111 bt_get(stream_class->clock->clock_class);
112 }
113
114 /*
115 * Because this function freezes the stream class,
116 * validate that this stream class contains at most a
117 * single clock class so that we set its expected clock
118 * class for future checks.
119 */
120 ret = bt_stream_class_validate_single_clock_class(
121 stream_class, &expected_clock_class);
122 if (ret) {
123 BT_LOGW("Event class's stream class or one of its event "
124 "classes contains a field type which is not "
125 "recursively mapped to the expected "
126 "clock class: "
127 "stream-class-addr=%p, "
128 "stream-class-id=%" PRId64 ", "
129 "stream-class-name=\"%s\", "
130 "expected-clock-class-addr=%p, "
131 "expected-clock-class-name=\"%s\"",
132 stream_class, bt_stream_class_get_id(stream_class),
133 bt_stream_class_get_name(stream_class),
134 expected_clock_class,
135 expected_clock_class ?
136 bt_clock_class_get_name(expected_clock_class) :
137 NULL);
138 goto error;
139 }
140 }
141
142 /* Validate the trace (if any), the stream class, and the event class */
143 trace = bt_stream_class_get_trace(stream_class);
144 if (trace) {
145 BT_LOGD_STR("Event's class is part of a trace.");
146 packet_header_type = bt_trace_get_packet_header_type(trace);
147 trace_valid = trace->valid;
148 assert(trace_valid);
149 environment = trace->environment;
150 }
151
152 packet_context_type = bt_stream_class_get_packet_context_type(
153 stream_class);
154 event_header_type = bt_stream_class_get_event_header_type(
155 stream_class);
156 stream_event_ctx_type = bt_stream_class_get_event_context_type(
157 stream_class);
158 event_context_type = bt_event_class_get_context_type(event_class);
159 event_payload_type = bt_event_class_get_payload_type(event_class);
160 ret = bt_validate_class_types(environment, packet_header_type,
161 packet_context_type, event_header_type, stream_event_ctx_type,
162 event_context_type, event_payload_type, trace_valid,
163 stream_class->valid, event_class->valid,
164 &validation_output, validation_flags);
165 BT_PUT(packet_header_type);
166 BT_PUT(packet_context_type);
167 BT_PUT(event_header_type);
168 BT_PUT(stream_event_ctx_type);
169 BT_PUT(event_context_type);
170 BT_PUT(event_payload_type);
171 if (ret) {
172 /*
173 * This means something went wrong during the validation
174 * process, not that the objects are invalid.
175 */
176 BT_LOGE("Failed to validate event and parents: ret=%d", ret);
177 goto error;
178 }
179
180 if ((validation_output.valid_flags & validation_flags) !=
181 validation_flags) {
182 /* Invalid trace/stream class/event class */
183 BT_LOGW("Invalid trace, stream class, or event class: "
184 "valid-flags=0x%x", validation_output.valid_flags);
185 goto error;
186 }
187
188 /*
189 * At this point we know the trace (if associated to the stream
190 * class), the stream class, and the event class, with their
191 * current types, are valid. We may proceed with creating
192 * the event.
193 */
194 event = g_new0(struct bt_event, 1);
195 if (!event) {
196 BT_LOGE_STR("Failed to allocate one event.");
197 goto error;
198 }
199
200 bt_object_init(event, bt_event_destroy);
201
202 /*
203 * event does not share a common ancestor with the event class; it has
204 * to guarantee its existence by holding a reference. This reference
205 * shall be released once the event is associated to a stream since,
206 * from that point, the event and its class will share the same
207 * lifetime.
208 */
209 event->event_class = bt_get(event_class);
210 event->clock_values = g_hash_table_new_full(g_direct_hash,
211 g_direct_equal, bt_put, bt_put);
212
213 if (validation_output.event_header_type) {
214 BT_LOGD("Creating initial event header field: ft-addr=%p",
215 validation_output.event_header_type);
216 event_header =
217 bt_field_create(validation_output.event_header_type);
218 if (!event_header) {
219 BT_LOGE_STR("Cannot create initial event header field object.");
220 goto error;
221 }
222 }
223
224 if (validation_output.stream_event_ctx_type) {
225 BT_LOGD("Creating initial stream event context field: ft-addr=%p",
226 validation_output.stream_event_ctx_type);
227 stream_event_context = bt_field_create(
228 validation_output.stream_event_ctx_type);
229 if (!stream_event_context) {
230 BT_LOGE_STR("Cannot create initial stream event context field object.");
231 goto error;
232 }
233 }
234
235 if (validation_output.event_context_type) {
236 BT_LOGD("Creating initial event context field: ft-addr=%p",
237 validation_output.event_context_type);
238 event_context = bt_field_create(
239 validation_output.event_context_type);
240 if (!event_context) {
241 BT_LOGE_STR("Cannot create initial event context field object.");
242 goto error;
243 }
244 }
245
246 if (validation_output.event_payload_type) {
247 BT_LOGD("Creating initial event payload field: ft-addr=%p",
248 validation_output.event_payload_type);
249 event_payload = bt_field_create(
250 validation_output.event_payload_type);
251 if (!event_payload) {
252 BT_LOGE_STR("Cannot create initial event payload field object.");
253 goto error;
254 }
255 }
256
257 /*
258 * At this point all the fields are created, potentially from
259 * validated copies of field types, so that the field types and
260 * fields can be replaced in the trace, stream class,
261 * event class, and created event.
262 */
263 bt_validation_replace_types(trace, stream_class,
264 event_class, &validation_output, validation_flags);
265 BT_MOVE(event->event_header, event_header);
266 BT_MOVE(event->stream_event_context, stream_event_context);
267 BT_MOVE(event->context_payload, event_context);
268 BT_MOVE(event->fields_payload, event_payload);
269
270 /*
271 * Put what was not moved in bt_validation_replace_types().
272 */
273 bt_validation_output_put_types(&validation_output);
274
275 /*
276 * Freeze the stream class since the event header must not be changed
277 * anymore.
278 */
279 bt_stream_class_freeze(stream_class);
280
281 /*
282 * It is safe to set the stream class's unique clock class
283 * now because the stream class is frozen.
284 */
285 if (expected_clock_class) {
286 BT_MOVE(stream_class->clock_class, expected_clock_class);
287 }
288
289 /*
290 * Mark stream class, and event class as valid since
291 * they're all frozen now.
292 */
293 stream_class->valid = 1;
294 event_class->valid = 1;
295
296 /* Put stuff we borrowed from the event class */
297 BT_PUT(stream_class);
298 BT_PUT(trace);
299 BT_LOGD("Created event object: addr=%p, event-class-name=\"%s\", "
300 "event-class-id=%" PRId64,
301 event, bt_event_class_get_name(event->event_class),
302 bt_event_class_get_id(event_class));
303 return event;
304
305 error:
306 bt_validation_output_put_types(&validation_output);
307 BT_PUT(event);
308 BT_PUT(stream_class);
309 BT_PUT(trace);
310 BT_PUT(event_header);
311 BT_PUT(stream_event_context);
312 BT_PUT(event_context);
313 BT_PUT(event_payload);
314 bt_put(expected_clock_class);
315 assert(!packet_header_type);
316 assert(!packet_context_type);
317 assert(!event_header_type);
318 assert(!stream_event_ctx_type);
319 assert(!event_context_type);
320 assert(!event_payload_type);
321
322 return event;
323 }
324
325 struct bt_event_class *bt_event_get_class(struct bt_event *event)
326 {
327 struct bt_event_class *event_class = NULL;
328
329 if (!event) {
330 BT_LOGW_STR("Invalid parameter: event is NULL.");
331 goto end;
332 }
333
334 event_class = bt_get(bt_event_borrow_event_class(event));
335 end:
336 return event_class;
337 }
338
339 struct bt_stream *bt_event_get_stream(struct bt_event *event)
340 {
341 struct bt_stream *stream = NULL;
342
343 if (!event) {
344 BT_LOGW_STR("Invalid parameter: event is NULL.");
345 goto end;
346 }
347
348 /*
349 * If the event has a parent, then this is its (writer) stream.
350 * If the event has no parent, then if it has a packet, this
351 * is its (non-writer) stream.
352 */
353 if (event->base.parent) {
354 stream = (struct bt_stream *) bt_object_get_parent(event);
355 } else {
356 if (event->packet) {
357 stream = bt_get(event->packet->stream);
358 }
359 }
360
361 end:
362 return stream;
363 }
364
365 int bt_event_set_payload(struct bt_event *event,
366 const char *name,
367 struct bt_field *payload)
368 {
369 int ret = 0;
370
371 if (!event || !payload) {
372 BT_LOGW("Invalid parameter: event or payload field is NULL: "
373 "event-addr=%p, payload-field-addr=%p",
374 event, payload);
375 ret = -1;
376 goto end;
377 }
378
379 if (event->frozen) {
380 BT_LOGW("Invalid parameter: event is frozen: addr=%p, "
381 "event-class-name=\"%s\", event-class-id=%" PRId64,
382 event, bt_event_class_get_name(event->event_class),
383 bt_event_class_get_id(event->event_class));
384 ret = -1;
385 goto end;
386 }
387
388 if (name) {
389 ret = bt_field_structure_set_field_by_name(
390 event->fields_payload, name, payload);
391 } else {
392 struct bt_field_type *payload_type;
393
394 payload_type = bt_field_get_type(payload);
395
396 if (bt_field_type_compare(payload_type,
397 event->event_class->fields) == 0) {
398 bt_put(event->fields_payload);
399 bt_get(payload);
400 event->fields_payload = payload;
401 } else {
402 BT_LOGW("Invalid parameter: payload field type is different from the expected field type: "
403 "event-addr=%p, event-class-name=\"%s\", "
404 "event-class-id=%" PRId64,
405 event,
406 bt_event_class_get_name(event->event_class),
407 bt_event_class_get_id(event->event_class));
408 ret = -1;
409 }
410
411 bt_put(payload_type);
412 }
413
414 if (ret) {
415 BT_LOGW("Failed to set event's payload field: event-addr=%p, "
416 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
417 "payload-field-name=\"%s\", payload-field-addr=%p",
418 event, bt_event_class_get_name(event->event_class),
419 bt_event_class_get_id(event->event_class),
420 name, payload);
421 } else {
422 BT_LOGV("Set event's payload field: event-addr=%p, "
423 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
424 "payload-field-name=\"%s\", payload-field-addr=%p",
425 event, bt_event_class_get_name(event->event_class),
426 bt_event_class_get_id(event->event_class),
427 name, payload);
428 }
429
430 end:
431 return ret;
432 }
433
434 struct bt_field *bt_event_get_event_payload(struct bt_event *event)
435 {
436 struct bt_field *payload = NULL;
437
438 if (!event) {
439 BT_LOGW_STR("Invalid parameter: event is NULL.");
440 goto end;
441 }
442
443 if (!event->fields_payload) {
444 BT_LOGV("Event has no current payload field: addr=%p, "
445 "event-class-name=\"%s\", event-class-id=%" PRId64,
446 event, bt_event_class_get_name(event->event_class),
447 bt_event_class_get_id(event->event_class));
448 goto end;
449 }
450
451 payload = event->fields_payload;
452 bt_get(payload);
453 end:
454 return payload;
455 }
456
457 int bt_event_set_event_payload(struct bt_event *event,
458 struct bt_field *payload)
459 {
460 return bt_event_set_payload(event, NULL, payload);
461 }
462
463 struct bt_field *bt_event_get_payload(struct bt_event *event,
464 const char *name)
465 {
466 struct bt_field *field = NULL;
467
468 if (!event) {
469 BT_LOGW_STR("Invalid parameter: event is NULL.");
470 goto end;
471 }
472
473 if (name) {
474 field = bt_field_structure_get_field_by_name(
475 event->fields_payload, name);
476 } else {
477 field = event->fields_payload;
478 bt_get(field);
479 }
480 end:
481 return field;
482 }
483
484 struct bt_field *bt_event_get_payload_by_index(
485 struct bt_event *event, uint64_t index)
486 {
487 struct bt_field *field = NULL;
488
489 if (!event) {
490 BT_LOGW_STR("Invalid parameter: event is NULL.");
491 goto end;
492 }
493
494 field = bt_field_structure_get_field_by_index(event->fields_payload,
495 index);
496 end:
497 return field;
498 }
499
500 struct bt_field *bt_event_get_header(
501 struct bt_event *event)
502 {
503 struct bt_field *header = NULL;
504
505 if (!event) {
506 BT_LOGW_STR("Invalid parameter: event is NULL.");
507 goto end;
508 }
509
510 if (!event->event_header) {
511 BT_LOGV("Event has no current header field: addr=%p, "
512 "event-class-name=\"%s\", event-class-id=%" PRId64,
513 event, bt_event_class_get_name(event->event_class),
514 bt_event_class_get_id(event->event_class));
515 goto end;
516 }
517
518 header = event->event_header;
519 bt_get(header);
520 end:
521 return header;
522 }
523
524 int bt_event_set_header(struct bt_event *event,
525 struct bt_field *header)
526 {
527 int ret = 0;
528 struct bt_field_type *field_type = NULL;
529 struct bt_stream_class *stream_class = NULL;
530
531 if (!event) {
532 BT_LOGW_STR("Invalid parameter: event is NULL.");
533 ret = -1;
534 goto end;
535 }
536
537 if (event->frozen) {
538 BT_LOGW("Invalid parameter: event is frozen: addr=%p, "
539 "event-class-name=\"%s\", event-class-id=%" PRId64,
540 event, bt_event_class_get_name(event->event_class),
541 bt_event_class_get_id(event->event_class));
542 ret = -1;
543 goto end;
544 }
545
546 stream_class = (struct bt_stream_class *) bt_object_get_parent(
547 event->event_class);
548 /*
549 * Ensure the provided header's type matches the one registered to the
550 * stream class.
551 */
552 if (header) {
553 field_type = bt_field_get_type(header);
554 if (bt_field_type_compare(field_type,
555 stream_class->event_header_type)) {
556 BT_LOGW("Invalid parameter: header field type is different from the expected field type: "
557 "event-addr=%p, event-class-name=\"%s\", "
558 "event-class-id=%" PRId64,
559 event,
560 bt_event_class_get_name(event->event_class),
561 bt_event_class_get_id(event->event_class));
562 ret = -1;
563 goto end;
564 }
565 } else {
566 if (stream_class->event_header_type) {
567 BT_LOGW("Invalid parameter: setting no event header but event header field type is not NULL: "
568 "event-addr=%p, event-class-name=\"%s\", "
569 "event-class-id=%" PRId64 ", "
570 "event-header-ft-addr=%p",
571 event,
572 bt_event_class_get_name(event->event_class),
573 bt_event_class_get_id(event->event_class),
574 stream_class->event_header_type);
575 ret = -1;
576 goto end;
577 }
578 }
579
580 bt_put(event->event_header);
581 event->event_header = bt_get(header);
582 BT_LOGV("Set event's header field: event-addr=%p, "
583 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
584 "header-field-addr=%p",
585 event, bt_event_class_get_name(event->event_class),
586 bt_event_class_get_id(event->event_class), header);
587 end:
588 bt_put(stream_class);
589 bt_put(field_type);
590 return ret;
591 }
592
593 struct bt_field *bt_event_get_event_context(
594 struct bt_event *event)
595 {
596 struct bt_field *context = NULL;
597
598 if (!event) {
599 BT_LOGW_STR("Invalid parameter: event is NULL.");
600 goto end;
601 }
602
603 if (!event->context_payload) {
604 BT_LOGV("Event has no current context field: addr=%p, "
605 "event-class-name=\"%s\", event-class-id=%" PRId64,
606 event, bt_event_class_get_name(event->event_class),
607 bt_event_class_get_id(event->event_class));
608 goto end;
609 }
610
611 context = event->context_payload;
612 bt_get(context);
613 end:
614 return context;
615 }
616
617 int bt_event_set_event_context(struct bt_event *event,
618 struct bt_field *context)
619 {
620 int ret = 0;
621 struct bt_field_type *field_type = NULL;
622
623 if (!event) {
624 BT_LOGW_STR("Invalid parameter: event is NULL.");
625 ret = -1;
626 goto end;
627 }
628
629 if (event->frozen) {
630 BT_LOGW("Invalid parameter: event is frozen: addr=%p, "
631 "event-class-name=\"%s\", event-class-id=%" PRId64,
632 event, bt_event_class_get_name(event->event_class),
633 bt_event_class_get_id(event->event_class));
634 ret = -1;
635 goto end;
636 }
637
638 if (context) {
639 field_type = bt_field_get_type(context);
640
641 if (bt_field_type_compare(field_type,
642 event->event_class->context)) {
643 BT_LOGW("Invalid parameter: context field type is different from the expected field type: "
644 "event-addr=%p, event-class-name=\"%s\", "
645 "event-class-id=%" PRId64,
646 event,
647 bt_event_class_get_name(event->event_class),
648 bt_event_class_get_id(event->event_class));
649 ret = -1;
650 goto end;
651 }
652 } else {
653 if (event->event_class->context) {
654 BT_LOGW("Invalid parameter: setting no event context but event context field type is not NULL: "
655 "event-addr=%p, event-class-name=\"%s\", "
656 "event-class-id=%" PRId64 ", "
657 "event-context-ft-addr=%p",
658 event,
659 bt_event_class_get_name(event->event_class),
660 bt_event_class_get_id(event->event_class),
661 event->event_class->context);
662 ret = -1;
663 goto end;
664 }
665 }
666
667 bt_put(event->context_payload);
668 event->context_payload = bt_get(context);
669 BT_LOGV("Set event's context field: event-addr=%p, "
670 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
671 "context-field-addr=%p",
672 event, bt_event_class_get_name(event->event_class),
673 bt_event_class_get_id(event->event_class), context);
674 end:
675 bt_put(field_type);
676 return ret;
677 }
678
679 struct bt_field *bt_event_get_stream_event_context(
680 struct bt_event *event)
681 {
682 struct bt_field *stream_event_context = NULL;
683
684 if (!event) {
685 BT_LOGW_STR("Invalid parameter: event is NULL.");
686 goto end;
687 }
688
689 if (!event->stream_event_context) {
690 BT_LOGV("Event has no current stream event context field: addr=%p, "
691 "event-class-name=\"%s\", event-class-id=%" PRId64,
692 event, bt_event_class_get_name(event->event_class),
693 bt_event_class_get_id(event->event_class));
694 goto end;
695 }
696
697 stream_event_context = event->stream_event_context;
698 end:
699 return bt_get(stream_event_context);
700 }
701
702 int bt_event_set_stream_event_context(struct bt_event *event,
703 struct bt_field *stream_event_context)
704 {
705 int ret = 0;
706 struct bt_field_type *field_type = NULL;
707 struct bt_stream_class *stream_class = NULL;
708
709 if (!event) {
710 BT_LOGW_STR("Invalid parameter: event is NULL.");
711 ret = -1;
712 goto end;
713 }
714
715 if (event->frozen) {
716 BT_LOGW("Invalid parameter: event is frozen: addr=%p, "
717 "event-class-name=\"%s\", event-class-id=%" PRId64,
718 event, bt_event_class_get_name(event->event_class),
719 bt_event_class_get_id(event->event_class));
720 ret = -1;
721 goto end;
722 }
723
724 stream_class = bt_event_class_get_stream_class(event->event_class);
725 /*
726 * We should not have been able to create the event without associating
727 * the event class to a stream class.
728 */
729 assert(stream_class);
730
731 if (stream_event_context) {
732 field_type = bt_field_get_type(stream_event_context);
733 if (bt_field_type_compare(field_type,
734 stream_class->event_context_type)) {
735 BT_LOGW("Invalid parameter: stream event context field type is different from the expected field type: "
736 "event-addr=%p, event-class-name=\"%s\", "
737 "event-class-id=%" PRId64,
738 event,
739 bt_event_class_get_name(event->event_class),
740 bt_event_class_get_id(event->event_class));
741 ret = -1;
742 goto end;
743 }
744 } else {
745 if (stream_class->event_context_type) {
746 BT_LOGW("Invalid parameter: setting no stream event context but stream event context field type is not NULL: "
747 "event-addr=%p, event-class-name=\"%s\", "
748 "event-class-id=%" PRId64 ", "
749 "stream-event-context-ft-addr=%p",
750 event,
751 bt_event_class_get_name(event->event_class),
752 bt_event_class_get_id(event->event_class),
753 stream_class->event_context_type);
754 ret = -1;
755 goto end;
756 }
757 }
758
759 bt_get(stream_event_context);
760 BT_MOVE(event->stream_event_context, stream_event_context);
761 BT_LOGV("Set event's stream event context field: event-addr=%p, "
762 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
763 "stream-event-context-field-addr=%p",
764 event, bt_event_class_get_name(event->event_class),
765 bt_event_class_get_id(event->event_class),
766 stream_event_context);
767 end:
768 BT_PUT(stream_class);
769 bt_put(field_type);
770 return ret;
771 }
772
773 /* Pre-2.0 CTF writer backward compatibility */
774 void bt_ctf_event_get(struct bt_event *event)
775 {
776 bt_get(event);
777 }
778
779 /* Pre-2.0 CTF writer backward compatibility */
780 void bt_ctf_event_put(struct bt_event *event)
781 {
782 bt_put(event);
783 }
784
785 void bt_event_destroy(struct bt_object *obj)
786 {
787 struct bt_event *event;
788
789 event = container_of(obj, struct bt_event, base);
790 BT_LOGD("Destroying event: addr=%p, "
791 "event-class-name=\"%s\", event-class-id=%" PRId64,
792 event, bt_event_class_get_name(event->event_class),
793 bt_event_class_get_id(event->event_class));
794
795 if (!event->base.parent) {
796 /*
797 * Event was keeping a reference to its class since it shared no
798 * common ancestor with it to guarantee they would both have the
799 * same lifetime.
800 */
801 bt_put(event->event_class);
802 }
803 g_hash_table_destroy(event->clock_values);
804 BT_LOGD_STR("Putting event's header field.");
805 bt_put(event->event_header);
806 BT_LOGD_STR("Putting event's stream event context field.");
807 bt_put(event->stream_event_context);
808 BT_LOGD_STR("Putting event's context field.");
809 bt_put(event->context_payload);
810 BT_LOGD_STR("Putting event's payload field.");
811 bt_put(event->fields_payload);
812 BT_LOGD_STR("Putting event's packet.");
813 bt_put(event->packet);
814 g_free(event);
815 }
816
817 struct bt_clock_value *bt_event_get_clock_value(
818 struct bt_event *event, struct bt_clock_class *clock_class)
819 {
820 struct bt_clock_value *clock_value = NULL;
821
822 if (!event || !clock_class) {
823 BT_LOGW("Invalid parameter: event or clock class is NULL: "
824 "event-addr=%p, clock-class-addr=%p",
825 event, clock_class);
826 goto end;
827 }
828
829 clock_value = g_hash_table_lookup(event->clock_values, clock_class);
830 if (!clock_value) {
831 BT_LOGV("No clock value associated to the given clock class: "
832 "event-addr=%p, event-class-name=\"%s\", "
833 "event-class-id=%" PRId64 ", clock-class-addr=%p, "
834 "clock-class-name=\"%s\"", event,
835 bt_event_class_get_name(event->event_class),
836 bt_event_class_get_id(event->event_class),
837 clock_class, bt_clock_class_get_name(clock_class));
838 goto end;
839 }
840
841 bt_get(clock_value);
842 end:
843 return clock_value;
844 }
845
846 int bt_event_set_clock_value(struct bt_event *event,
847 struct bt_clock_value *value)
848 {
849 int ret = 0;
850 struct bt_trace *trace;
851 struct bt_stream_class *stream_class;
852 struct bt_event_class *event_class;
853 struct bt_clock_class *clock_class = NULL;
854
855 if (!event || !value) {
856 BT_LOGW("Invalid parameter: event or clock value is NULL: "
857 "event-addr=%p, clock-value-addr=%p",
858 event, value);
859 ret = -1;
860 goto end;
861 }
862
863 if (event->frozen) {
864 BT_LOGW("Invalid parameter: event is frozen: addr=%p, "
865 "event-class-name=\"%s\", event-class-id=%" PRId64,
866 event, bt_event_class_get_name(event->event_class),
867 bt_event_class_get_id(event->event_class));
868 ret = -1;
869 goto end;
870 }
871
872 clock_class = bt_clock_value_get_class(value);
873 event_class = bt_event_borrow_event_class(event);
874 assert(event_class);
875 stream_class = bt_event_class_borrow_stream_class(event_class);
876 assert(stream_class);
877 trace = bt_stream_class_borrow_trace(stream_class);
878 assert(trace);
879
880 if (!bt_trace_has_clock_class(trace, clock_class)) {
881 BT_LOGW("Invalid parameter: clock class is not part of event's trace: "
882 "event-addr=%p, event-class-name=\"%s\", "
883 "event-class-id=%" PRId64 ", clock-class-addr=%p, "
884 "clock-class-name=\"%s\"",
885 event, bt_event_class_get_name(event->event_class),
886 bt_event_class_get_id(event->event_class),
887 clock_class, bt_clock_class_get_name(clock_class));
888 ret = -1;
889 goto end;
890 }
891
892 g_hash_table_insert(event->clock_values, clock_class, bt_get(value));
893 BT_LOGV("Set event's clock value: "
894 "event-addr=%p, event-class-name=\"%s\", "
895 "event-class-id=%" PRId64 ", clock-class-addr=%p, "
896 "clock-class-name=\"%s\", clock-value-addr=%p, "
897 "clock-value-cycles=%" PRIu64,
898 event, bt_event_class_get_name(event->event_class),
899 bt_event_class_get_id(event->event_class),
900 clock_class, bt_clock_class_get_name(clock_class),
901 value, value->value);
902 clock_class = NULL;
903
904 end:
905 bt_put(clock_class);
906 return ret;
907 }
908
909 BT_HIDDEN
910 int bt_event_validate(struct bt_event *event)
911 {
912 /* Make sure each field's payload has been set */
913 int ret;
914 struct bt_stream_class *stream_class = NULL;
915
916 assert(event);
917 if (event->event_header) {
918 ret = bt_field_validate(event->event_header);
919 if (ret) {
920 BT_LOGD("Invalid event's header field: "
921 "event-addr=%p, event-class-name=\"%s\", "
922 "event-class-id=%" PRId64,
923 event, bt_event_class_get_name(event->event_class),
924 bt_event_class_get_id(event->event_class));
925 goto end;
926 }
927 }
928
929 stream_class = bt_event_class_get_stream_class(event->event_class);
930 /*
931 * We should not have been able to create the event without associating
932 * the event class to a stream class.
933 */
934 assert(stream_class);
935 if (stream_class->event_context_type) {
936 ret = bt_field_validate(event->stream_event_context);
937 if (ret) {
938 BT_LOGD("Invalid event's stream event context field: "
939 "event-addr=%p, event-class-name=\"%s\", "
940 "event-class-id=%" PRId64,
941 event,
942 bt_event_class_get_name(event->event_class),
943 bt_event_class_get_id(event->event_class));
944 goto end;
945 }
946 }
947
948 ret = bt_field_validate(event->fields_payload);
949 if (ret) {
950 BT_LOGD("Invalid event's payload field: "
951 "event-addr=%p, event-class-name=\"%s\", "
952 "event-class-id=%" PRId64,
953 event,
954 bt_event_class_get_name(event->event_class),
955 bt_event_class_get_id(event->event_class));
956 goto end;
957 }
958
959 if (event->event_class->context) {
960 BT_LOGD("Invalid event's context field: "
961 "event-addr=%p, event-class-name=\"%s\", "
962 "event-class-id=%" PRId64,
963 event,
964 bt_event_class_get_name(event->event_class),
965 bt_event_class_get_id(event->event_class));
966 ret = bt_field_validate(event->context_payload);
967 }
968 end:
969 bt_put(stream_class);
970 return ret;
971 }
972
973 BT_HIDDEN
974 int bt_event_serialize(struct bt_event *event,
975 struct bt_stream_pos *pos,
976 enum bt_byte_order native_byte_order)
977 {
978 int ret = 0;
979
980 assert(event);
981 assert(pos);
982
983 BT_LOGV_STR("Serializing event's context field.");
984 if (event->context_payload) {
985 ret = bt_field_serialize(event->context_payload, pos,
986 native_byte_order);
987 if (ret) {
988 BT_LOGW("Cannot serialize event's context field: "
989 "event-addr=%p, event-class-name=\"%s\", "
990 "event-class-id=%" PRId64,
991 event,
992 bt_event_class_get_name(event->event_class),
993 bt_event_class_get_id(event->event_class));
994 goto end;
995 }
996 }
997
998 BT_LOGV_STR("Serializing event's payload field.");
999 if (event->fields_payload) {
1000 ret = bt_field_serialize(event->fields_payload, pos,
1001 native_byte_order);
1002 if (ret) {
1003 BT_LOGW("Cannot serialize event's payload field: "
1004 "event-addr=%p, event-class-name=\"%s\", "
1005 "event-class-id=%" PRId64,
1006 event,
1007 bt_event_class_get_name(event->event_class),
1008 bt_event_class_get_id(event->event_class));
1009 goto end;
1010 }
1011 }
1012 end:
1013 return ret;
1014 }
1015
1016 struct bt_packet *bt_event_get_packet(struct bt_event *event)
1017 {
1018 struct bt_packet *packet = NULL;
1019
1020 if (!event) {
1021 BT_LOGW_STR("Invalid parameter: event is NULL.");
1022 goto end;
1023 }
1024
1025 if (!event->packet) {
1026 BT_LOGV("Event has no current packet: addr=%p, "
1027 "event-class-name=\"%s\", event-class-id=%" PRId64,
1028 event, bt_event_class_get_name(event->event_class),
1029 bt_event_class_get_id(event->event_class));
1030 goto end;
1031 }
1032
1033 packet = bt_get(event->packet);
1034 end:
1035 return packet;
1036 }
1037
1038 int bt_event_set_packet(struct bt_event *event,
1039 struct bt_packet *packet)
1040 {
1041 struct bt_stream_class *event_stream_class = NULL;
1042 struct bt_stream_class *packet_stream_class = NULL;
1043 struct bt_stream *stream = NULL;
1044 int ret = 0;
1045
1046 if (!event || !packet) {
1047 BT_LOGW("Invalid parameter: event or packet is NULL: "
1048 "event-addr=%p, packet-addr=%p",
1049 event, packet);
1050 ret = -1;
1051 goto end;
1052 }
1053
1054 if (event->frozen) {
1055 BT_LOGW("Invalid parameter: event is frozen: addr=%p, "
1056 "event-class-name=\"%s\", event-class-id=%" PRId64,
1057 event, bt_event_class_get_name(event->event_class),
1058 bt_event_class_get_id(event->event_class));
1059 ret = -1;
1060 goto end;
1061 }
1062
1063 /*
1064 * Make sure the new packet was created by this event's
1065 * stream, if it is set.
1066 */
1067 stream = bt_event_get_stream(event);
1068 if (stream) {
1069 if (packet->stream != stream) {
1070 BT_LOGW("Invalid parameter: packet's stream and event's stream differ: "
1071 "event-addr=%p, event-class-name=\"%s\", "
1072 "event-class-id=%" PRId64 ", packet-stream-addr=%p, "
1073 "event-stream-addr=%p",
1074 event, bt_event_class_get_name(event->event_class),
1075 bt_event_class_get_id(event->event_class),
1076 packet->stream, stream);
1077 ret = -1;
1078 goto end;
1079 }
1080 } else {
1081 event_stream_class =
1082 bt_event_class_get_stream_class(event->event_class);
1083 packet_stream_class =
1084 bt_stream_get_class(packet->stream);
1085
1086 assert(event_stream_class);
1087 assert(packet_stream_class);
1088
1089 if (event_stream_class != packet_stream_class) {
1090 BT_LOGW("Invalid parameter: packet's stream class and event's stream class differ: "
1091 "event-addr=%p, event-class-name=\"%s\", "
1092 "event-class-id=%" PRId64 ", packet-stream-class-addr=%p, "
1093 "event-stream-class-addr=%p",
1094 event, bt_event_class_get_name(event->event_class),
1095 bt_event_class_get_id(event->event_class),
1096 packet_stream_class, event_stream_class);
1097 ret = -1;
1098 goto end;
1099 }
1100 }
1101
1102 bt_get(packet);
1103 BT_MOVE(event->packet, packet);
1104 BT_LOGV("Set event's packet: event-addr=%p, "
1105 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
1106 "packet-addr=%p",
1107 event, bt_event_class_get_name(event->event_class),
1108 bt_event_class_get_id(event->event_class), packet);
1109
1110 end:
1111 BT_PUT(stream);
1112 BT_PUT(event_stream_class);
1113 BT_PUT(packet_stream_class);
1114
1115 return ret;
1116 }
1117
1118 BT_HIDDEN
1119 void bt_event_freeze(struct bt_event *event)
1120 {
1121 assert(event);
1122
1123 if (event->frozen) {
1124 return;
1125 }
1126
1127 BT_LOGD("Freezing event: addr=%p, "
1128 "event-class-name=\"%s\", event-class-id=%" PRId64,
1129 event, bt_event_class_get_name(event->event_class),
1130 bt_event_class_get_id(event->event_class));
1131 bt_packet_freeze(event->packet);
1132 BT_LOGD_STR("Freezing event's header field.");
1133 bt_field_freeze(event->event_header);
1134 BT_LOGD_STR("Freezing event's stream event context field.");
1135 bt_field_freeze(event->stream_event_context);
1136 BT_LOGD_STR("Freezing event's context field.");
1137 bt_field_freeze(event->context_payload);
1138 BT_LOGD_STR("Freezing event's payload field.");
1139 bt_field_freeze(event->fields_payload);
1140 event->frozen = 1;
1141 }
This page took 0.051005 seconds and 5 git commands to generate.