6 * Copyright 2011-2012 EfficiOS Inc. and Linux Foundation
8 * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
9 * Julien Desfossez <julien.desfossez@efficios.com>
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
22 #include <babeltrace/babeltrace.h>
23 #include <babeltrace/format.h>
24 #include <babeltrace/ctf/events.h>
25 #include <babeltrace/ctf-ir/metadata.h>
26 #include <babeltrace/prio_heap.h>
27 #include <babeltrace/iterator-internal.h>
28 #include <babeltrace/ctf/events-internal.h>
29 #include <babeltrace/ctf/metadata.h>
32 #include "events-private.h"
35 * thread local storage to store the last error that occured
36 * while reading a field, this variable must be accessed by
37 * bt_ctf_field_error only
39 __thread
int bt_ctf_last_field_error
= 0;
41 const struct definition
*bt_ctf_get_top_level_scope(const struct bt_ctf_event
*ctf_event
,
42 enum bt_ctf_scope scope
)
44 struct definition
*tmp
= NULL
;
45 struct ctf_event_definition
*event
= ctf_event
->parent
;
48 case BT_TRACE_PACKET_HEADER
:
51 if (event
->stream
->trace_packet_header
)
52 tmp
= &event
->stream
->trace_packet_header
->p
;
54 case BT_STREAM_PACKET_CONTEXT
:
57 if (event
->stream
->stream_packet_context
)
58 tmp
= &event
->stream
->stream_packet_context
->p
;
60 case BT_STREAM_EVENT_HEADER
:
63 if (event
->stream
->stream_event_header
)
64 tmp
= &event
->stream
->stream_event_header
->p
;
66 case BT_STREAM_EVENT_CONTEXT
:
69 if (event
->stream
->stream_event_context
)
70 tmp
= &event
->stream
->stream_event_context
->p
;
72 case BT_EVENT_CONTEXT
:
73 if (event
->event_context
)
74 tmp
= &event
->event_context
->p
;
77 if (event
->event_fields
)
78 tmp
= &event
->event_fields
->p
;
87 const struct definition
*bt_ctf_get_field(const struct bt_ctf_event
*ctf_event
,
88 const struct definition
*scope
,
91 struct definition
*def
;
92 char *field_underscore
;
95 def
= lookup_definition(scope
, field
);
97 * optionally a field can have an underscore prefix, try
98 * to lookup the field with this prefix if it failed
101 field_underscore
= g_new(char, strlen(field
) + 2);
102 field_underscore
[0] = '_';
103 strcpy(&field_underscore
[1], field
);
104 def
= lookup_definition(scope
, field_underscore
);
105 g_free(field_underscore
);
107 if (bt_ctf_field_type(def
) == CTF_TYPE_VARIANT
) {
108 struct definition_variant
*variant_definition
;
109 variant_definition
= container_of(def
,
110 struct definition_variant
, p
);
111 return variant_definition
->current_field
;
118 const struct definition
*bt_ctf_get_index(const struct bt_ctf_event
*ctf_event
,
119 const struct definition
*field
,
122 struct definition
*ret
= NULL
;
124 if (bt_ctf_field_type(field
) == CTF_TYPE_ARRAY
) {
125 struct definition_array
*array_definition
;
126 array_definition
= container_of(field
,
127 struct definition_array
, p
);
128 ret
= array_index(array_definition
, index
);
129 } else if (bt_ctf_field_type(field
) == CTF_TYPE_SEQUENCE
) {
130 struct definition_sequence
*sequence_definition
;
131 sequence_definition
= container_of(field
,
132 struct definition_sequence
, p
);
133 ret
= sequence_index(sequence_definition
, index
);
138 const char *bt_ctf_event_name(const struct bt_ctf_event
*ctf_event
)
140 struct ctf_event_declaration
*event_class
;
141 struct ctf_stream_declaration
*stream_class
;
142 struct ctf_event_definition
*event
= ctf_event
->parent
;
146 stream_class
= event
->stream
->stream_class
;
147 event_class
= g_ptr_array_index(stream_class
->events_by_id
,
148 event
->stream
->event_id
);
149 return g_quark_to_string(event_class
->name
);
152 const char *bt_ctf_field_name(const struct definition
*def
)
155 return rem_(g_quark_to_string(def
->name
));
159 enum ctf_type_id
bt_ctf_field_type(const struct definition
*def
)
162 return def
->declaration
->id
;
163 return CTF_TYPE_UNKNOWN
;
166 int bt_ctf_get_field_list(const struct bt_ctf_event
*ctf_event
,
167 const struct definition
*scope
,
168 struct definition
const * const **list
,
171 switch (bt_ctf_field_type(scope
)) {
172 case CTF_TYPE_INTEGER
:
174 case CTF_TYPE_STRING
:
177 case CTF_TYPE_STRUCT
:
179 const struct definition_struct
*def_struct
;
181 def_struct
= container_of(scope
, const struct definition_struct
, p
);
184 if (def_struct
->fields
->pdata
) {
185 *list
= (struct definition
const* const*) def_struct
->fields
->pdata
;
186 *count
= def_struct
->fields
->len
;
192 case CTF_TYPE_UNTAGGED_VARIANT
:
194 case CTF_TYPE_VARIANT
:
196 const struct definition_variant
*def_variant
;
198 def_variant
= container_of(scope
, const struct definition_variant
, p
);
201 if (def_variant
->fields
->pdata
) {
202 *list
= (struct definition
const* const*) def_variant
->fields
->pdata
;
203 *count
= def_variant
->fields
->len
;
211 const struct definition_array
*def_array
;
213 def_array
= container_of(scope
, const struct definition_array
, p
);
216 if (def_array
->elems
->pdata
) {
217 *list
= (struct definition
const* const*) def_array
->elems
->pdata
;
218 *count
= def_array
->elems
->len
;
224 case CTF_TYPE_SEQUENCE
:
226 const struct definition_sequence
*def_sequence
;
228 def_sequence
= container_of(scope
, const struct definition_sequence
, p
);
231 if (def_sequence
->elems
->pdata
) {
232 *list
= (struct definition
const* const*) def_sequence
->elems
->pdata
;
233 *count
= def_sequence
->elems
->len
;
252 struct bt_context
*bt_ctf_event_get_context(const struct bt_ctf_event
*ctf_event
)
254 struct bt_context
*ret
= NULL
;
255 struct ctf_file_stream
*cfs
;
256 struct ctf_trace
*trace
;
257 struct ctf_event_definition
*event
= ctf_event
->parent
;
259 cfs
= container_of(event
->stream
, struct ctf_file_stream
,
261 trace
= cfs
->parent
.stream_class
->trace
;
268 int bt_ctf_event_get_handle_id(const struct bt_ctf_event
*ctf_event
)
271 struct ctf_file_stream
*cfs
;
272 struct ctf_trace
*trace
;
273 struct ctf_event_definition
*event
= ctf_event
->parent
;
275 cfs
= container_of(event
->stream
, struct ctf_file_stream
,
277 trace
= cfs
->parent
.stream_class
->trace
;
279 ret
= trace
->handle
->id
;
284 uint64_t bt_ctf_get_real_timestamp(const struct bt_ctf_event
*ctf_event
)
286 struct ctf_event_definition
*event
= ctf_event
->parent
;
287 if (event
&& event
->stream
->has_timestamp
)
288 return event
->stream
->real_timestamp
;
293 uint64_t bt_ctf_get_cycles_timestamp(const struct bt_ctf_event
*ctf_event
)
295 struct ctf_event_definition
*event
= ctf_event
->parent
;
296 if (event
&& event
->stream
->has_timestamp
)
297 return event
->stream
->cycles_timestamp
;
302 static void bt_ctf_field_set_error(int error
)
304 bt_ctf_last_field_error
= error
;
307 int bt_ctf_field_get_error(void)
310 ret
= bt_ctf_last_field_error
;
311 bt_ctf_last_field_error
= 0;
316 int bt_ctf_get_int_signedness(const struct definition
*field
)
320 if (field
&& bt_ctf_field_type(field
) == CTF_TYPE_INTEGER
) {
321 ret
= get_int_signedness(field
);
324 bt_ctf_field_set_error(-EINVAL
);
330 int bt_ctf_get_int_base(const struct definition
*field
)
334 if (field
&& bt_ctf_field_type(field
) == CTF_TYPE_INTEGER
) {
335 ret
= get_int_base(field
);
338 bt_ctf_field_set_error(-EINVAL
);
344 int bt_ctf_get_int_byte_order(const struct definition
*field
)
348 if (field
&& bt_ctf_field_type(field
) == CTF_TYPE_INTEGER
) {
349 ret
= get_int_byte_order(field
);
352 bt_ctf_field_set_error(-EINVAL
);
358 ssize_t
bt_ctf_get_int_len(const struct definition
*field
)
362 if (field
&& bt_ctf_field_type(field
) == CTF_TYPE_INTEGER
) {
363 ret
= (ssize_t
) get_int_len(field
);
366 bt_ctf_field_set_error(-EINVAL
);
372 enum ctf_string_encoding
bt_ctf_get_encoding(const struct definition
*field
)
374 enum ctf_string_encoding ret
= 0;
379 if (bt_ctf_field_type(field
) == CTF_TYPE_INTEGER
)
380 ret
= get_int_encoding(field
);
381 else if (bt_ctf_field_type(field
) == CTF_TYPE_STRING
)
382 ret
= get_string_encoding(field
);
390 bt_ctf_field_set_error(-EINVAL
);
394 int bt_ctf_get_array_len(const struct definition
*field
)
398 if (field
&& bt_ctf_field_type(field
) == CTF_TYPE_ARRAY
) {
399 ret
= get_array_len(field
);
402 bt_ctf_field_set_error(-EINVAL
);
408 uint64_t bt_ctf_get_uint64(const struct definition
*field
)
410 unsigned int ret
= 0;
412 if (field
&& bt_ctf_field_type(field
) == CTF_TYPE_INTEGER
)
413 ret
= get_unsigned_int(field
);
415 bt_ctf_field_set_error(-EINVAL
);
420 int64_t bt_ctf_get_int64(const struct definition
*field
)
424 if (field
&& bt_ctf_field_type(field
) == CTF_TYPE_INTEGER
)
425 ret
= get_signed_int(field
);
427 bt_ctf_field_set_error(-EINVAL
);
433 char *bt_ctf_get_char_array(const struct definition
*field
)
437 if (field
&& bt_ctf_field_type(field
) == CTF_TYPE_ARRAY
)
438 ret
= get_char_array(field
)->str
;
440 bt_ctf_field_set_error(-EINVAL
);
445 char *bt_ctf_get_string(const struct definition
*field
)
449 if (field
&& bt_ctf_field_type(field
) == CTF_TYPE_STRING
)
450 ret
= get_string(field
);
452 bt_ctf_field_set_error(-EINVAL
);
457 int bt_ctf_get_event_decl_list(int handle_id
, struct bt_context
*ctx
,
458 struct bt_ctf_event_decl
* const **list
,
461 struct bt_trace_handle
*handle
;
462 struct trace_descriptor
*td
;
463 struct ctf_trace
*tin
;
468 handle
= g_hash_table_lookup(ctx
->trace_handles
,
469 (gpointer
) (unsigned long) handle_id
);
474 tin
= container_of(td
, struct ctf_trace
, parent
);
476 *list
= (struct bt_ctf_event_decl
* const*) tin
->event_declarations
->pdata
;
477 *count
= tin
->event_declarations
->len
;
484 const char *bt_ctf_get_decl_event_name(const struct bt_ctf_event_decl
*event
)
488 return g_quark_to_string(event
->parent
.name
);
491 int bt_ctf_get_decl_fields(struct bt_ctf_event_decl
*event_decl
,
492 enum bt_ctf_scope scope
,
493 struct bt_ctf_field_decl
const * const **list
,
497 GArray
*fields
= NULL
;
498 gpointer
*ret_list
= NULL
;
499 GPtrArray
*fields_array
= NULL
;
504 case BT_EVENT_CONTEXT
:
505 if (event_decl
->context_decl
) {
506 ret_list
= event_decl
->context_decl
->pdata
;
507 *count
= event_decl
->context_decl
->len
;
510 event_decl
->context_decl
= g_ptr_array_new();
511 if (!event_decl
->parent
.context_decl
) {
515 fields
= event_decl
->parent
.context_decl
->fields
;
516 fields_array
= event_decl
->context_decl
;
518 case BT_EVENT_FIELDS
:
519 if (event_decl
->fields_decl
) {
520 ret_list
= event_decl
->fields_decl
->pdata
;
521 *count
= event_decl
->fields_decl
->len
;
524 event_decl
->fields_decl
= g_ptr_array_new();
525 if (!event_decl
->parent
.fields_decl
) {
529 fields
= event_decl
->parent
.fields_decl
->fields
;
530 fields_array
= event_decl
->fields_decl
;
532 case BT_STREAM_PACKET_CONTEXT
:
533 if (event_decl
->packet_context_decl
) {
534 ret_list
= event_decl
->packet_context_decl
->pdata
;
535 *count
= event_decl
->packet_context_decl
->len
;
538 event_decl
->packet_context_decl
= g_ptr_array_new();
539 if (!event_decl
->parent
.stream
->packet_context_decl
) {
543 fields
= event_decl
->parent
.stream
->packet_context_decl
->fields
;
544 fields_array
= event_decl
->packet_context_decl
;
546 case BT_STREAM_EVENT_CONTEXT
:
547 if (event_decl
->event_context_decl
) {
548 ret_list
= event_decl
->event_context_decl
->pdata
;
549 *count
= event_decl
->event_context_decl
->len
;
552 event_decl
->event_context_decl
= g_ptr_array_new();
553 if (!event_decl
->parent
.stream
->event_context_decl
) {
557 fields
= event_decl
->parent
.stream
->event_context_decl
->fields
;
558 fields_array
= event_decl
->event_context_decl
;
560 case BT_STREAM_EVENT_HEADER
:
561 if (event_decl
->event_header_decl
) {
562 ret_list
= event_decl
->event_header_decl
->pdata
;
563 *count
= event_decl
->event_header_decl
->len
;
566 event_decl
->event_header_decl
= g_ptr_array_new();
567 if (!event_decl
->parent
.stream
->event_header_decl
) {
571 fields
= event_decl
->parent
.stream
->event_header_decl
->fields
;
572 fields_array
= event_decl
->event_header_decl
;
574 case BT_TRACE_PACKET_HEADER
:
575 if (event_decl
->packet_header_decl
) {
576 ret_list
= event_decl
->packet_header_decl
->pdata
;
577 *count
= event_decl
->packet_header_decl
->len
;
580 event_decl
->packet_header_decl
= g_ptr_array_new();
581 if (!event_decl
->parent
.stream
->trace
->packet_header_decl
) {
585 fields
= event_decl
->parent
.stream
->trace
->packet_header_decl
->fields
;
586 fields_array
= event_decl
->packet_header_decl
;
590 for (i
= 0; i
< fields
->len
; i
++) {
591 g_ptr_array_add(fields_array
,
592 &g_array_index(fields
,
593 struct declaration_field
, i
));
595 ret_list
= fields_array
->pdata
;
596 *count
= fields
->len
;
599 *list
= (struct bt_ctf_field_decl
const* const*) ret_list
;
604 const char *bt_ctf_get_decl_field_name(const struct bt_ctf_field_decl
*field
)
607 return rem_(g_quark_to_string(((struct declaration_field
*) field
)->name
));