b35f54a8ecba9cee1f5000323b47b3c082462c7a
[babeltrace.git] / formats / ctf / events.c
1 /*
2 * ctf/events.c
3 *
4 * Babeltrace Library
5 *
6 * Copyright 2011-2012 EfficiOS Inc. and Linux Foundation
7 *
8 * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
9 * Julien Desfossez <julien.desfossez@efficios.com>
10 *
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:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 */
21
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>
30 #include <glib.h>
31
32 #include "events-private.h"
33
34 /*
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
38 */
39 __thread int bt_ctf_last_field_error = 0;
40
41 struct bt_ctf_iter *bt_ctf_iter_create(struct bt_context *ctx,
42 struct bt_iter_pos *begin_pos,
43 struct bt_iter_pos *end_pos)
44 {
45 struct bt_ctf_iter *iter;
46 int ret;
47
48 iter = g_new0(struct bt_ctf_iter, 1);
49 ret = bt_iter_init(&iter->parent, ctx, begin_pos, end_pos);
50 if (ret) {
51 g_free(iter);
52 return NULL;
53 }
54 iter->callbacks = g_array_new(0, 1, sizeof(struct bt_stream_callbacks));
55 iter->recalculate_dep_graph = 0;
56 iter->main_callbacks.callback = NULL;
57 iter->dep_gc = g_ptr_array_new();
58 return iter;
59 }
60
61 void bt_ctf_iter_destroy(struct bt_ctf_iter *iter)
62 {
63 struct bt_stream_callbacks *bt_stream_cb;
64 struct bt_callback_chain *bt_chain;
65 int i, j;
66
67 /* free all events callbacks */
68 if (iter->main_callbacks.callback)
69 g_array_free(iter->main_callbacks.callback, TRUE);
70
71 /* free per-event callbacks */
72 for (i = 0; i < iter->callbacks->len; i++) {
73 bt_stream_cb = &g_array_index(iter->callbacks,
74 struct bt_stream_callbacks, i);
75 if (!bt_stream_cb || !bt_stream_cb->per_id_callbacks)
76 continue;
77 for (j = 0; j < bt_stream_cb->per_id_callbacks->len; j++) {
78 bt_chain = &g_array_index(bt_stream_cb->per_id_callbacks,
79 struct bt_callback_chain, j);
80 if (bt_chain->callback) {
81 g_array_free(bt_chain->callback, TRUE);
82 }
83 }
84 g_array_free(bt_stream_cb->per_id_callbacks, TRUE);
85 }
86
87 bt_iter_fini(&iter->parent);
88 g_free(iter);
89 }
90
91 struct bt_iter *bt_ctf_get_iter(struct bt_ctf_iter *iter)
92 {
93 return &iter->parent;
94 }
95
96 struct bt_ctf_event *bt_ctf_iter_read_event(struct bt_ctf_iter *iter)
97 {
98 struct ctf_file_stream *file_stream;
99 struct bt_ctf_event *ret = &iter->current_ctf_event;
100
101 file_stream = heap_maximum(iter->parent.stream_heap);
102 if (!file_stream) {
103 /* end of file for all streams */
104 goto stop;
105 }
106 ret->stream = &file_stream->parent;
107 ret->event = g_ptr_array_index(ret->stream->events_by_id,
108 ret->stream->event_id);
109
110 if (ret->stream->stream_id > iter->callbacks->len)
111 goto end;
112
113 process_callbacks(iter, ret->stream);
114
115 end:
116 return ret;
117 stop:
118 return NULL;
119 }
120
121 struct definition *bt_ctf_get_top_level_scope(struct bt_ctf_event *event,
122 enum bt_ctf_scope scope)
123 {
124 struct definition *tmp = NULL;
125
126 switch (scope) {
127 case BT_TRACE_PACKET_HEADER:
128 if (!event->stream)
129 goto error;
130 if (event->stream->trace_packet_header)
131 tmp = &event->stream->trace_packet_header->p;
132 break;
133 case BT_STREAM_PACKET_CONTEXT:
134 if (!event->stream)
135 goto error;
136 if (event->stream->stream_packet_context)
137 tmp = &event->stream->stream_packet_context->p;
138 break;
139 case BT_STREAM_EVENT_HEADER:
140 if (!event->stream)
141 goto error;
142 if (event->stream->stream_event_header)
143 tmp = &event->stream->stream_event_header->p;
144 break;
145 case BT_STREAM_EVENT_CONTEXT:
146 if (!event->stream)
147 goto error;
148 if (event->stream->stream_event_context)
149 tmp = &event->stream->stream_event_context->p;
150 break;
151 case BT_EVENT_CONTEXT:
152 if (!event->event)
153 goto error;
154 if (event->event->event_context)
155 tmp = &event->event->event_context->p;
156 break;
157 case BT_EVENT_FIELDS:
158 if (!event->event)
159 goto error;
160 if (event->event->event_fields)
161 tmp = &event->event->event_fields->p;
162 break;
163 }
164 return tmp;
165
166 error:
167 return NULL;
168 }
169
170 struct definition *bt_ctf_get_field(struct bt_ctf_event *event,
171 struct definition *scope,
172 const char *field)
173 {
174 struct definition *def;
175 char *field_underscore;
176
177 if (scope) {
178 def = lookup_definition(scope, field);
179 /*
180 * optionally a field can have an underscore prefix, try
181 * to lookup the field with this prefix if it failed
182 */
183 if (!def) {
184 field_underscore = g_new(char, strlen(field) + 2);
185 field_underscore[0] = '_';
186 strcpy(&field_underscore[1], field);
187 def = lookup_definition(scope, field_underscore);
188 g_free(field_underscore);
189 }
190 if (bt_ctf_field_type(def) == CTF_TYPE_VARIANT) {
191 struct definition_variant *variant_definition;
192 variant_definition = container_of(def,
193 struct definition_variant, p);
194 return variant_definition->current_field;
195 }
196 return def;
197 }
198 return NULL;
199 }
200
201 struct definition *bt_ctf_get_index(struct bt_ctf_event *event,
202 struct definition *field,
203 unsigned int index)
204 {
205 struct definition *ret = NULL;
206
207 if (bt_ctf_field_type(field) == CTF_TYPE_ARRAY) {
208 struct definition_array *array_definition;
209 array_definition = container_of(field,
210 struct definition_array, p);
211 ret = array_index(array_definition, index);
212 } else if (bt_ctf_field_type(field) == CTF_TYPE_SEQUENCE) {
213 struct definition_sequence *sequence_definition;
214 sequence_definition = container_of(field,
215 struct definition_sequence, p);
216 ret = sequence_index(sequence_definition, index);
217 }
218 return ret;
219 }
220
221 const char *bt_ctf_event_name(struct bt_ctf_event *event)
222 {
223 struct ctf_event *event_class;
224 struct ctf_stream_class *stream_class;
225
226 if (!event)
227 return NULL;
228 stream_class = event->stream->stream_class;
229 event_class = g_ptr_array_index(stream_class->events_by_id,
230 event->stream->event_id);
231 return g_quark_to_string(event_class->name);
232 }
233
234 const char *bt_ctf_field_name(const struct definition *def)
235 {
236 if (def)
237 return rem_(g_quark_to_string(def->name));
238 return NULL;
239 }
240
241 enum ctf_type_id bt_ctf_field_type(const struct definition *def)
242 {
243 if (def)
244 return def->declaration->id;
245 return CTF_TYPE_UNKNOWN;
246 }
247
248 int bt_ctf_get_field_list(struct bt_ctf_event *event,
249 struct definition *scope,
250 struct definition const * const **list,
251 unsigned int *count)
252 {
253 switch (bt_ctf_field_type(scope)) {
254 case CTF_TYPE_INTEGER:
255 case CTF_TYPE_FLOAT:
256 case CTF_TYPE_STRING:
257 case CTF_TYPE_ENUM:
258 goto error;
259 case CTF_TYPE_STRUCT:
260 {
261 struct definition_struct *def_struct;
262
263 def_struct = container_of(scope, struct definition_struct, p);
264 if (!def_struct)
265 goto error;
266 if (def_struct->fields->pdata) {
267 *list = (struct definition const* const*) def_struct->fields->pdata;
268 *count = def_struct->fields->len;
269 goto end;
270 } else {
271 goto error;
272 }
273 }
274 case CTF_TYPE_UNTAGGED_VARIANT:
275 goto error;
276 case CTF_TYPE_VARIANT:
277 {
278 struct definition_variant *def_variant;
279
280 def_variant = container_of(scope, struct definition_variant, p);
281 if (!def_variant)
282 goto error;
283 if (def_variant->fields->pdata) {
284 *list = (struct definition const* const*) def_variant->fields->pdata;
285 *count = def_variant->fields->len;
286 goto end;
287 } else {
288 goto error;
289 }
290 }
291 case CTF_TYPE_ARRAY:
292 {
293 struct definition_array *def_array;
294
295 def_array = container_of(scope, struct definition_array, p);
296 if (!def_array)
297 goto error;
298 if (def_array->elems->pdata) {
299 *list = (struct definition const* const*) def_array->elems->pdata;
300 *count = def_array->elems->len;
301 goto end;
302 } else {
303 goto error;
304 }
305 }
306 case CTF_TYPE_SEQUENCE:
307 {
308 struct definition_sequence *def_sequence;
309
310 def_sequence = container_of(scope, struct definition_sequence, p);
311 if (!def_sequence)
312 goto error;
313 if (def_sequence->elems->pdata) {
314 *list = (struct definition const* const*) def_sequence->elems->pdata;
315 *count = def_sequence->elems->len;
316 goto end;
317 } else {
318 goto error;
319 }
320 }
321 default:
322 break;
323 }
324
325 end:
326 return 0;
327
328 error:
329 *list = NULL;
330 *count = 0;
331 return -1;
332 }
333
334 uint64_t bt_ctf_get_timestamp_raw(struct bt_ctf_event *event)
335 {
336 if (event && event->stream->has_timestamp)
337 return ctf_get_timestamp_raw(event->stream,
338 event->stream->timestamp);
339 else
340 return -1ULL;
341 }
342
343 uint64_t bt_ctf_get_timestamp(struct bt_ctf_event *event)
344 {
345 if (event && event->stream->has_timestamp)
346 return ctf_get_timestamp(event->stream,
347 event->stream->timestamp);
348 else
349 return -1ULL;
350 }
351
352 static void bt_ctf_field_set_error(int error)
353 {
354 bt_ctf_last_field_error = error;
355 }
356
357 int bt_ctf_field_get_error(void)
358 {
359 int ret;
360 ret = bt_ctf_last_field_error;
361 bt_ctf_last_field_error = 0;
362
363 return ret;
364 }
365
366 int bt_ctf_get_int_signedness(const struct definition *field)
367 {
368 int ret;
369
370 if (field && bt_ctf_field_type(field) == CTF_TYPE_INTEGER) {
371 ret = get_int_signedness(field);
372 } else {
373 ret = -1;
374 bt_ctf_field_set_error(-EINVAL);
375 }
376
377 return ret;
378 }
379
380 int bt_ctf_get_int_base(const struct definition *field)
381 {
382 int ret;
383
384 if (field && bt_ctf_field_type(field) == CTF_TYPE_INTEGER) {
385 ret = get_int_base(field);
386 } else {
387 ret = -1;
388 bt_ctf_field_set_error(-EINVAL);
389 }
390
391 return ret;
392 }
393
394 int bt_ctf_get_int_byte_order(const struct definition *field)
395 {
396 int ret;
397
398 if (field && bt_ctf_field_type(field) == CTF_TYPE_INTEGER) {
399 ret = get_int_byte_order(field);
400 } else {
401 ret = -1;
402 bt_ctf_field_set_error(-EINVAL);
403 }
404
405 return ret;
406 }
407
408 enum ctf_string_encoding bt_ctf_get_encoding(const struct definition *field)
409 {
410 enum ctf_string_encoding ret = 0;
411
412 if (!field)
413 goto end;
414
415 if (bt_ctf_field_type(field) == CTF_TYPE_INTEGER)
416 ret = get_int_encoding(field);
417 else if (bt_ctf_field_type(field) == CTF_TYPE_STRING)
418 ret = get_string_encoding(field);
419 else
420 goto error;
421
422 end:
423 return ret;
424
425 error:
426 bt_ctf_field_set_error(-EINVAL);
427 return -1;
428 }
429
430 int bt_ctf_get_array_len(const struct definition *field)
431 {
432 int ret;
433
434 if (field && bt_ctf_field_type(field) == CTF_TYPE_ARRAY) {
435 ret = get_array_len(field);
436 } else {
437 ret = -1;
438 bt_ctf_field_set_error(-EINVAL);
439 }
440
441 return ret;
442 }
443
444 uint64_t bt_ctf_get_uint64(const struct definition *field)
445 {
446 unsigned int ret = 0;
447
448 if (field && bt_ctf_field_type(field) == CTF_TYPE_INTEGER)
449 ret = get_unsigned_int(field);
450 else
451 bt_ctf_field_set_error(-EINVAL);
452
453 return ret;
454 }
455
456 int64_t bt_ctf_get_int64(const struct definition *field)
457 {
458 int ret = 0;
459
460 if (field && bt_ctf_field_type(field) == CTF_TYPE_INTEGER)
461 ret = get_signed_int(field);
462 else
463 bt_ctf_field_set_error(-EINVAL);
464
465 return ret;
466
467 }
468
469 char *bt_ctf_get_char_array(const struct definition *field)
470 {
471 char *ret = NULL;
472
473 if (field && bt_ctf_field_type(field) == CTF_TYPE_ARRAY)
474 ret = get_char_array(field)->str;
475 else
476 bt_ctf_field_set_error(-EINVAL);
477
478 return ret;
479 }
480
481 char *bt_ctf_get_string(const struct definition *field)
482 {
483 char *ret = NULL;
484
485 if (field && bt_ctf_field_type(field) == CTF_TYPE_STRING)
486 ret = get_string(field);
487 else
488 bt_ctf_field_set_error(-EINVAL);
489
490 return ret;
491 }
This page took 0.059775 seconds and 3 git commands to generate.