From: Philippe Proulx Date: Thu, 15 Nov 2018 13:20:23 +0000 (-0500) Subject: CTF IR -> Trace IR X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=56e18c4ce186892c36d7f2cb5078087425e60134 CTF IR -> Trace IR Also, keep an `include/babeltrace/ctf-ir` directory of which the headers are only including corresponding CTF writer headers for backward compatibility. Signed-off-by: Philippe Proulx --- diff --git a/.gitignore b/.gitignore index b2dcb450..0ef95c97 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,7 @@ /tests/lib/test_bt_notification_heap /tests/lib/test_bt_objects /tests/lib/test_bt_values -/tests/lib/test_ctf_ir_ref +/tests/lib/test_trace_ir_ref /tests/lib/test_ctf_writer /tests/lib/test_ctf_writer_complete /tests/lib/test_dwarf @@ -33,7 +33,7 @@ /tests/lib/test_bt_notification_iterator /tests/lib/test_cc_prio_map /tests/lib/test_graph_topo -/tests/lib/ctf-ir/test_ctf_ir +/tests/lib/trace-ir/test_trace_ir /tests/lib/ctf-writer/test_ctf_writer /tests/plugins/test-utils-muxer /tests/plugins/test-utils-muxer-complete diff --git a/CONTRIBUTING.adoc b/CONTRIBUTING.adoc index f18f9b06..bc6ff471 100644 --- a/CONTRIBUTING.adoc +++ b/CONTRIBUTING.adoc @@ -69,9 +69,9 @@ node of the graph keeps all other reachable nodes alive. The scheme employed in Babeltrace to break this cycle consists in the "children" holding *reverse component references* to their parents. That -is, in the context of CTF IR, that event classes hold a reference to -their parent stream class and stream classes hold a reference to their -parent trace. +is, in the context of the trace IR, that event classes hold a reference +to their parent stream class and stream classes hold a reference to +their parent trace. On the other hand, parents hold *claiming aggregation references* to their children. A claiming aggregation reference means that the object diff --git a/configure.ac b/configure.ac index 16d45c81..bf065d63 100644 --- a/configure.ac +++ b/configure.ac @@ -744,7 +744,7 @@ AC_CONFIG_FILES([ lib/plugin/Makefile lib/graph/Makefile lib/graph/notification/Makefile - lib/ctf-ir/Makefile + lib/trace-ir/Makefile lib/ctf-writer/Makefile include/Makefile logging/Makefile @@ -754,7 +754,7 @@ AC_CONFIG_FILES([ tests/cli/intersection/Makefile tests/lib/Makefile tests/lib/test-plugin-plugins/Makefile - tests/lib/ctf-ir/Makefile + tests/lib/trace-ir/Makefile tests/lib/ctf-writer/Makefile tests/utils/common.sh tests/utils/Makefile @@ -800,7 +800,7 @@ AC_CONFIG_FILES([tests/cli/test_trace_read], [chmod +x tests/cli/test_trace_read AC_CONFIG_FILES([tests/cli/test_trimmer], [chmod +x tests/cli/test_trimmer]) AC_CONFIG_FILES([tests/lib/test_ctf_writer_complete], [chmod +x tests/lib/test_ctf_writer_complete]) AC_CONFIG_FILES([tests/lib/test_plugin_complete], [chmod +x tests/lib/test_plugin_complete]) -AC_CONFIG_FILES([tests/lib/ctf-ir/test_ctf_ir], [chmod +x tests/lib/ctf-ir/test_ctf_ir]) +AC_CONFIG_FILES([tests/lib/trace-ir/test_trace_ir], [chmod +x tests/lib/trace-ir/test_trace_ir]) AC_CONFIG_FILES([tests/lib/ctf-writer/test_ctf_writer], [chmod +x tests/lib/ctf-writer/test_ctf_writer]) AC_CONFIG_FILES([tests/plugins/test-utils-muxer-complete], [chmod +x tests/plugins/test-utils-muxer-complete]) AC_CONFIG_FILES([tests/plugins/test_lttng_utils_debug_info], [chmod +x tests/plugins/test_lttng_utils_debug_info]) diff --git a/include/Makefile.am b/include/Makefile.am index 0bdd90a8..11ecd94c 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -99,24 +99,39 @@ babeltracectfwriterinclude_HEADERS = \ babeltrace/ctf-writer/visitor.h \ babeltrace/ctf-writer/writer.h -# CTF IR API +# Legacy API (for CTF writer) babeltracectfirincludedir = "$(includedir)/babeltrace/ctf-ir" babeltracectfirinclude_HEADERS = \ - babeltrace/ctf-ir/clock-class.h \ - babeltrace/ctf-ir/clock-value.h \ babeltrace/ctf-ir/clock.h \ babeltrace/ctf-ir/event-class.h \ + babeltrace/ctf-ir/event-fields.h \ + babeltrace/ctf-ir/event-types.h \ babeltrace/ctf-ir/event.h \ - babeltrace/ctf-ir/event-header-field.h \ - babeltrace/ctf-ir/field-path.h \ babeltrace/ctf-ir/field-types.h \ babeltrace/ctf-ir/fields.h \ - babeltrace/ctf-ir/packet.h \ - babeltrace/ctf-ir/packet-context-field.h \ - babeltrace/ctf-ir/packet-header-field.h \ babeltrace/ctf-ir/stream-class.h \ babeltrace/ctf-ir/stream.h \ - babeltrace/ctf-ir/trace.h + babeltrace/ctf-ir/trace.h \ + babeltrace/ctf-ir/utils.h + + +# Trace IR API +babeltracetraceirincludedir = "$(includedir)/babeltrace/trace-ir" +babeltracetraceirinclude_HEADERS = \ + babeltrace/trace-ir/clock-class.h \ + babeltrace/trace-ir/clock-value.h \ + babeltrace/trace-ir/event-class.h \ + babeltrace/trace-ir/event.h \ + babeltrace/trace-ir/event-header-field.h \ + babeltrace/trace-ir/field-path.h \ + babeltrace/trace-ir/field-types.h \ + babeltrace/trace-ir/fields.h \ + babeltrace/trace-ir/packet.h \ + babeltrace/trace-ir/packet-context-field.h \ + babeltrace/trace-ir/packet-header-field.h \ + babeltrace/trace-ir/stream-class.h \ + babeltrace/trace-ir/stream.h \ + babeltrace/trace-ir/trace.h # Plugin and plugin development API babeltracepluginincludedir = "$(includedir)/babeltrace/plugin" @@ -202,21 +217,21 @@ noinst_HEADERS = \ babeltrace/align-internal.h \ babeltrace/logging-internal.h \ babeltrace/endian-internal.h \ - babeltrace/ctf-ir/packet-internal.h \ - babeltrace/ctf-ir/event-class-internal.h \ - babeltrace/ctf-ir/utils-internal.h \ - babeltrace/ctf-ir/fields-internal.h \ - babeltrace/ctf-ir/stream-class-internal.h \ - babeltrace/ctf-ir/event-internal.h \ - babeltrace/ctf-ir/field-path-internal.h \ - babeltrace/ctf-ir/field-wrapper-internal.h \ - babeltrace/ctf-ir/trace-internal.h \ - babeltrace/ctf-ir/clock-class-internal.h \ - babeltrace/ctf-ir/field-types-internal.h \ - babeltrace/ctf-ir/clock-value-internal.h \ - babeltrace/ctf-ir/attributes-internal.h \ - babeltrace/ctf-ir/stream-internal.h \ - babeltrace/ctf-ir/resolve-field-path-internal.h \ + babeltrace/trace-ir/packet-internal.h \ + babeltrace/trace-ir/event-class-internal.h \ + babeltrace/trace-ir/utils-internal.h \ + babeltrace/trace-ir/fields-internal.h \ + babeltrace/trace-ir/stream-class-internal.h \ + babeltrace/trace-ir/event-internal.h \ + babeltrace/trace-ir/field-path-internal.h \ + babeltrace/trace-ir/field-wrapper-internal.h \ + babeltrace/trace-ir/trace-internal.h \ + babeltrace/trace-ir/clock-class-internal.h \ + babeltrace/trace-ir/field-types-internal.h \ + babeltrace/trace-ir/clock-value-internal.h \ + babeltrace/trace-ir/attributes-internal.h \ + babeltrace/trace-ir/stream-internal.h \ + babeltrace/trace-ir/resolve-field-path-internal.h \ babeltrace/prio-heap-internal.h \ babeltrace/lib-logging-internal.h \ babeltrace/compiler-internal.h \ diff --git a/include/babeltrace/babeltrace.h b/include/babeltrace/babeltrace.h index 3f99631d..ab8a95cc 100644 --- a/include/babeltrace/babeltrace.h +++ b/include/babeltrace/babeltrace.h @@ -49,22 +49,22 @@ #include #include -/* CTF IR API */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +/* Trace IR API */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* Plugin and plugin development API */ #include diff --git a/include/babeltrace/common-internal.h b/include/babeltrace/common-internal.h index e22a9231..584e38a1 100644 --- a/include/babeltrace/common-internal.h +++ b/include/babeltrace/common-internal.h @@ -4,9 +4,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/include/babeltrace/ctf-ir/attributes-internal.h b/include/babeltrace/ctf-ir/attributes-internal.h deleted file mode 100644 index d7dda55e..00000000 --- a/include/babeltrace/ctf-ir/attributes-internal.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_ATTRIBUTES_H -#define BABELTRACE_CTF_IR_ATTRIBUTES_H - -/* - * attributes.c - * - * Babeltrace - CTF IR: Attributes internal - * - * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation - * Copyright (c) 2015 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -BT_HIDDEN -struct bt_value *bt_attributes_create(void); - -BT_HIDDEN -void bt_attributes_destroy(struct bt_value *attr_obj); - -BT_HIDDEN -int64_t bt_attributes_get_count(struct bt_value *attr_obj); - -BT_HIDDEN -const char *bt_attributes_get_field_name(struct bt_value *attr_obj, - uint64_t index); - -BT_HIDDEN -struct bt_value *bt_attributes_borrow_field_value(struct bt_value *attr_obj, - uint64_t index); - -BT_HIDDEN -int bt_attributes_set_field_value(struct bt_value *attr_obj, - const char *name, struct bt_value *value_obj); - -BT_HIDDEN -struct bt_value *bt_attributes_borrow_field_value_by_name( - struct bt_value *attr_obj, const char *name); - -BT_HIDDEN -int bt_attributes_freeze(struct bt_value *attr_obj); - -#ifdef __cplusplus -} -#endif - -#endif /* BABELTRACE_CTF_IR_ATTRIBUTES_H */ diff --git a/include/babeltrace/ctf-ir/clock-class-internal.h b/include/babeltrace/ctf-ir/clock-class-internal.h deleted file mode 100644 index aab9cb44..00000000 --- a/include/babeltrace/ctf-ir/clock-class-internal.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_CLOCK_CLASS_INTERNAL_H -#define BABELTRACE_CTF_IR_CLOCK_CLASS_INTERNAL_H - -/* - * BabelTrace - CTF IR: Clock internal - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct bt_clock_class { - struct bt_object base; - - struct { - GString *str; - - /* NULL or `str->str` above */ - const char *value; - } name; - - struct { - GString *str; - - /* NULL or `str->str` above */ - const char *value; - } description; - - uint64_t frequency; - uint64_t precision; - int64_t offset_seconds; - uint64_t offset_cycles; - - struct { - uint8_t uuid[BABELTRACE_UUID_LEN]; - - /* NULL or `uuid` above */ - bt_uuid value; - } uuid; - - bool is_absolute; - - /* - * This is computed every time you call - * bt_clock_class_set_frequency() or - * bt_clock_class_set_offset(), as well as initially. It is the - * base offset in nanoseconds including both `offset_seconds` - * and `offset_cycles` above in the result. It is used to - * accelerate future calls to - * bt_clock_value_get_ns_from_origin() and - * bt_clock_class_cycles_to_ns_from_origin(). - * - * `overflows` is true if the base offset cannot be computed - * because of an overflow. - */ - struct { - int64_t value_ns; - bool overflows; - } base_offset; - - /* Pool of `struct bt_clock_value *` */ - struct bt_object_pool cv_pool; - - bool frozen; -}; - -BT_HIDDEN -void _bt_clock_class_freeze(struct bt_clock_class *clock_class); - -#ifdef BT_DEV_MODE -# define bt_clock_class_freeze _bt_clock_class_freeze -#else -# define bt_clock_class_freeze(_cc) -#endif - -BT_HIDDEN -bt_bool bt_clock_class_is_valid(struct bt_clock_class *clock_class); - -#endif /* BABELTRACE_CTF_IR_CLOCK_CLASS_INTERNAL_H */ diff --git a/include/babeltrace/ctf-ir/clock-class.h b/include/babeltrace/ctf-ir/clock-class.h deleted file mode 100644 index 40f53ad3..00000000 --- a/include/babeltrace/ctf-ir/clock-class.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_CLOCK_CLASS_H -#define BABELTRACE_CTF_IR_CLOCK_CLASS_H - -/* - * BabelTrace - CTF IR: Clock class - * - * Copyright 2013, 2014 Jérémie Galarneau - * Copyright 2017-2018 Philippe Proulx - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - -#include - -/* For bt_bool, bt_uuid */ -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct bt_clock_class; -struct bt_clock_value; - -extern struct bt_clock_class *bt_clock_class_create(void); - -extern const char *bt_clock_class_get_name(struct bt_clock_class *clock_class); - -extern int bt_clock_class_set_name(struct bt_clock_class *clock_class, - const char *name); - -extern const char *bt_clock_class_get_description( - struct bt_clock_class *clock_class); - -extern int bt_clock_class_set_description(struct bt_clock_class *clock_class, - const char *description); - -extern uint64_t bt_clock_class_get_frequency( - struct bt_clock_class *clock_class); - -extern int bt_clock_class_set_frequency(struct bt_clock_class *clock_class, - uint64_t freq); - -extern uint64_t bt_clock_class_get_precision( - struct bt_clock_class *clock_class); - -extern int bt_clock_class_set_precision(struct bt_clock_class *clock_class, - uint64_t precision); - -extern void bt_clock_class_get_offset(struct bt_clock_class *clock_class, - int64_t *seconds, uint64_t *cycles); - -extern int bt_clock_class_set_offset(struct bt_clock_class *clock_class, - int64_t seconds, uint64_t cycles); - -extern bt_bool bt_clock_class_is_absolute(struct bt_clock_class *clock_class); - -extern int bt_clock_class_set_is_absolute(struct bt_clock_class *clock_class, - bt_bool is_absolute); - -extern bt_uuid bt_clock_class_get_uuid(struct bt_clock_class *clock_class); - -extern int bt_clock_class_set_uuid(struct bt_clock_class *clock_class, - bt_uuid uuid); - -extern int bt_clock_class_cycles_to_ns_from_origin( - struct bt_clock_class *clock_class, - uint64_t cycles, int64_t *ns_from_origin); - -#ifdef __cplusplus -} -#endif - -#endif /* BABELTRACE_CTF_IR_CLOCK_CLASS_H */ diff --git a/include/babeltrace/ctf-ir/clock-value-internal.h b/include/babeltrace/ctf-ir/clock-value-internal.h deleted file mode 100644 index 1beb9fac..00000000 --- a/include/babeltrace/ctf-ir/clock-value-internal.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_CLOCK_VALUE_INTERNAL_H -#define BABELTRACE_CTF_IR_CLOCK_VALUE_INTERNAL_H - -/* - * Copyright 2017 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -struct bt_clock_class; - -struct bt_clock_value { - struct bt_object base; - struct bt_clock_class *clock_class; - uint64_t value_cycles; - bool ns_from_origin_overflows; - int64_t ns_from_origin; - bool is_set; -}; - -static inline -void bt_clock_value_set(struct bt_clock_value *clock_value) -{ - BT_ASSERT(clock_value); - clock_value->is_set = true; -} - -static inline -void bt_clock_value_reset(struct bt_clock_value *clock_value) -{ - BT_ASSERT(clock_value); - clock_value->is_set = false; -} - -static inline -void set_ns_from_origin(struct bt_clock_value *clock_value) -{ - if (bt_util_ns_from_origin(clock_value->clock_class, clock_value->value_cycles, - &clock_value->ns_from_origin)) { - clock_value->ns_from_origin_overflows = true; - } - -} - -static inline -void bt_clock_value_set_raw_value(struct bt_clock_value *clock_value, - uint64_t cycles) -{ - BT_ASSERT(clock_value); - clock_value->value_cycles = cycles; - set_ns_from_origin(clock_value); - bt_clock_value_set(clock_value); -} - -static inline -void bt_clock_value_set_value_inline(struct bt_clock_value *clock_value, - uint64_t raw_value) -{ - bt_clock_value_set_raw_value(clock_value, raw_value); -} - -BT_HIDDEN -void bt_clock_value_destroy(struct bt_clock_value *clock_value); - -BT_HIDDEN -struct bt_clock_value *bt_clock_value_new(struct bt_clock_class *clock_class); - -BT_HIDDEN -struct bt_clock_value *bt_clock_value_create( - struct bt_clock_class *clock_class); - -BT_HIDDEN -void bt_clock_value_recycle(struct bt_clock_value *clock_value); - -BT_HIDDEN -void bt_clock_value_set_raw_value(struct bt_clock_value *clock_value, - uint64_t cycles); - -#endif /* BABELTRACE_CTF_IR_CLOCK_VALUE_INTERNAL_H */ diff --git a/include/babeltrace/ctf-ir/clock-value-set-internal.h b/include/babeltrace/ctf-ir/clock-value-set-internal.h deleted file mode 100644 index 43205d08..00000000 --- a/include/babeltrace/ctf-ir/clock-value-set-internal.h +++ /dev/null @@ -1,159 +0,0 @@ -#ifndef BABELTRACE_GRAPH_CLOCK_VALUE_SET_H -#define BABELTRACE_GRAPH_CLOCK_VALUE_SET_H - -/* - * Copyright 2018 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include - -struct bt_clock_value_set { - /* Unique objects owned by this */ - GPtrArray *clock_values; - - /* Weak; points to one of the clock values above */ - struct bt_clock_value *default_cv; -}; - -static inline -int bt_clock_value_set_initialize(struct bt_clock_value_set *cv_set) -{ - int ret = 0; - - cv_set->clock_values = g_ptr_array_sized_new(1); - if (!cv_set->clock_values) { -#ifdef BT_LOGE_STR - BT_LOGE_STR("Failed to allocate one GPtrArray."); -#endif - - ret = -1; - goto end; - } - - cv_set->default_cv = NULL; - -end: - return ret; -} - -static inline -void bt_clock_value_set_reset(struct bt_clock_value_set *cv_set) -{ - uint64_t i; - - BT_ASSERT(cv_set); - BT_ASSERT(cv_set->clock_values); - - for (i = 0; i < cv_set->clock_values->len; i++) { - struct bt_clock_value *cv = cv_set->clock_values->pdata[i]; - - BT_ASSERT(cv); - bt_clock_value_reset(cv); - } - - cv_set->default_cv = NULL; -} - -static inline -void bt_clock_value_set_finalize(struct bt_clock_value_set *cv_set) -{ - uint64_t i; - - BT_ASSERT(cv_set); - - if (cv_set->clock_values) { - for (i = 0; i < cv_set->clock_values->len; i++) { - struct bt_clock_value *cv = - cv_set->clock_values->pdata[i]; - - BT_ASSERT(cv); - bt_clock_value_recycle(cv); - } - - g_ptr_array_free(cv_set->clock_values, TRUE); - } - - cv_set->default_cv = NULL; -} - -static inline -int bt_clock_value_set_set_clock_value(struct bt_clock_value_set *cv_set, - struct bt_clock_class *cc, uint64_t raw_value) -{ - int ret = 0; - struct bt_clock_value *clock_value = NULL; - uint64_t i; - - BT_ASSERT(cv_set); - BT_ASSERT(cc); - - /* - * Check if we already have a value for this clock class. - * - * TODO: When we have many clock classes, make this more - * efficient. - */ - for (i = 0; i < cv_set->clock_values->len; i++) { - struct bt_clock_value *cv = cv_set->clock_values->pdata[i]; - - BT_ASSERT(cv); - - if (cv->clock_class == cc) { - clock_value = cv; - break; - } - } - - if (!clock_value) { - clock_value = bt_clock_value_create(cc); - if (!clock_value) { -#ifdef BT_LIB_LOGE - BT_LIB_LOGE("Cannot create a clock value from a clock class: " - "%![cc-]+K", cc); -#endif - - ret = -1; - goto end; - } - - g_ptr_array_add(cv_set->clock_values, clock_value); - } - - bt_clock_value_set_value_inline(clock_value, raw_value); - -end: - return ret; -} - -static inline -void bt_clock_value_set_set_default_clock_value( - struct bt_clock_value_set *cv_set, uint64_t raw_value) -{ - BT_ASSERT(cv_set); - BT_ASSERT(cv_set->default_cv); - bt_clock_value_set_value_inline(cv_set->default_cv, raw_value); -} - -#endif /* BABELTRACE_GRAPH_CLOCK_VALUE_SET_H */ diff --git a/include/babeltrace/ctf-ir/clock-value.h b/include/babeltrace/ctf-ir/clock-value.h deleted file mode 100644 index 5f302427..00000000 --- a/include/babeltrace/ctf-ir/clock-value.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_CLOCK_VALUE_H -#define BABELTRACE_CTF_IR_CLOCK_VALUE_H - -/* - * BabelTrace - CTF IR: Clock class - * - * Copyright 2013, 2014 Jérémie Galarneau - * Copyright 2017 Philippe Proulx - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct bt_clock_class; -struct bt_clock_value; - -enum bt_clock_value_status { - BT_CLOCK_VALUE_STATUS_KNOWN, - BT_CLOCK_VALUE_STATUS_UNKNOWN, -}; - -extern struct bt_clock_class *bt_clock_value_borrow_clock_class( - struct bt_clock_value *clock_value); - -extern uint64_t bt_clock_value_get_value( - struct bt_clock_value *clock_value); - -extern int bt_clock_value_get_ns_from_origin( - struct bt_clock_value *clock_value, int64_t *ns_from_origin); - -#ifdef __cplusplus -} -#endif - -#endif /* BABELTRACE_CTF_IR_CLOCK_VALUE_H */ diff --git a/include/babeltrace/ctf-ir/clock.h b/include/babeltrace/ctf-ir/clock.h index 5f08ac1d..72ca2a3a 100644 --- a/include/babeltrace/ctf-ir/clock.h +++ b/include/babeltrace/ctf-ir/clock.h @@ -1,35 +1,2 @@ -#ifndef BABELTRACE_CTF_IR_CLOCK_H -#define BABELTRACE_CTF_IR_CLOCK_H - -/* - * BabelTrace - CTF IR: Clock - * - * Copyright 2018 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - +/* Pre-2.0 CTF writer backward compatibility */ #include - -#endif /* BABELTRACE_CTF_IR_CLOCK_H */ diff --git a/include/babeltrace/ctf-ir/event-class-internal.h b/include/babeltrace/ctf-ir/event-class-internal.h deleted file mode 100644 index 8fa2ba08..00000000 --- a/include/babeltrace/ctf-ir/event-class-internal.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_EVENT_CLASS_INTERNAL_H -#define BABELTRACE_CTF_IR_EVENT_CLASS_INTERNAL_H - -/* - * Babeltrace - CTF IR: Event class internal - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct bt_event_class { - struct bt_object base; - struct bt_field_type *specific_context_ft; - struct bt_field_type *payload_ft; - - struct { - GString *str; - - /* NULL or `str->str` above */ - const char *value; - } name; - - uint64_t id; - struct bt_property_uint log_level; - - struct { - GString *str; - - /* NULL or `str->str` above */ - const char *value; - } emf_uri; - - /* Pool of `struct bt_event *` */ - struct bt_object_pool event_pool; - - bool frozen; -}; - -BT_HIDDEN -void _bt_event_class_freeze(struct bt_event_class *event_class); - -#ifdef BT_DEV_MODE -# define bt_event_class_freeze _bt_event_class_freeze -#else -# define bt_event_class_freeze(_ec) -#endif - -static inline -struct bt_stream_class *bt_event_class_borrow_stream_class_inline( - struct bt_event_class *event_class) -{ - BT_ASSERT(event_class); - return (void *) bt_object_borrow_parent(&event_class->base); -} - -#endif /* BABELTRACE_CTF_IR_EVENT_CLASS_INTERNAL_H */ diff --git a/include/babeltrace/ctf-ir/event-class.h b/include/babeltrace/ctf-ir/event-class.h index 8752b406..f687a7d1 100644 --- a/include/babeltrace/ctf-ir/event-class.h +++ b/include/babeltrace/ctf-ir/event-class.h @@ -1,112 +1,2 @@ -#ifndef BABELTRACE_CTF_IR_EVENT_CLASS_H -#define BABELTRACE_CTF_IR_EVENT_CLASS_H - -/* - * BabelTrace - CTF IR: Event class - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - -/* For enum bt_property_availability */ -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct bt_event_class; -struct bt_field_type; -struct bt_stream_class; - -enum bt_event_class_log_level { - BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY, - BT_EVENT_CLASS_LOG_LEVEL_ALERT, - BT_EVENT_CLASS_LOG_LEVEL_CRITICAL, - BT_EVENT_CLASS_LOG_LEVEL_ERROR, - BT_EVENT_CLASS_LOG_LEVEL_WARNING, - BT_EVENT_CLASS_LOG_LEVEL_NOTICE, - BT_EVENT_CLASS_LOG_LEVEL_INFO, - BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM, - BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM, - BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS, - BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE, - BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT, - BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION, - BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE, - BT_EVENT_CLASS_LOG_LEVEL_DEBUG, -}; - -extern struct bt_event_class *bt_event_class_create( - struct bt_stream_class *stream_class); - -extern struct bt_event_class *bt_event_class_create_with_id( - struct bt_stream_class *stream_class, uint64_t id); - -extern struct bt_stream_class *bt_event_class_borrow_stream_class( - struct bt_event_class *event_class); - -extern const char *bt_event_class_get_name(struct bt_event_class *event_class); - -extern int bt_event_class_set_name(struct bt_event_class *event_class, - const char *name); - -extern uint64_t bt_event_class_get_id(struct bt_event_class *event_class); - -extern enum bt_property_availability bt_event_class_get_log_level( - struct bt_event_class *event_class, - enum bt_event_class_log_level *log_level); - -extern int bt_event_class_set_log_level(struct bt_event_class *event_class, - enum bt_event_class_log_level log_level); - -extern const char *bt_event_class_get_emf_uri( - struct bt_event_class *event_class); - -extern int bt_event_class_set_emf_uri(struct bt_event_class *event_class, - const char *emf_uri); - -extern struct bt_field_type *bt_event_class_borrow_specific_context_field_type( - struct bt_event_class *event_class); - -extern int bt_event_class_set_specific_context_field_type( - struct bt_event_class *event_class, - struct bt_field_type *field_type); - -extern struct bt_field_type *bt_event_class_borrow_payload_field_type( - struct bt_event_class *event_class); - -extern int bt_event_class_set_payload_field_type( - struct bt_event_class *event_class, - struct bt_field_type *field_type); - -#ifdef __cplusplus -} -#endif - -#endif /* BABELTRACE_CTF_IR_EVENT_CLASS_H */ +/* Pre-2.0 CTF writer backward compatibility */ +#include diff --git a/include/babeltrace/ctf-ir/event-fields.h b/include/babeltrace/ctf-ir/event-fields.h new file mode 100644 index 00000000..0c9395a7 --- /dev/null +++ b/include/babeltrace/ctf-ir/event-fields.h @@ -0,0 +1,2 @@ +/* Pre-2.0 CTF writer backward compatibility */ +#include diff --git a/include/babeltrace/ctf-ir/event-header-field.h b/include/babeltrace/ctf-ir/event-header-field.h deleted file mode 100644 index 0ac9eeaf..00000000 --- a/include/babeltrace/ctf-ir/event-header-field.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_EVENT_HEADER_FIELD_H -#define BABELTRACE_CTF_IR_EVENT_HEADER_FIELD_H - -/* - * Copyright 2018 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - -#ifdef __cplusplus -extern "C" { -#endif - -struct bt_stream_class; -struct bt_event_header_field; -struct bt_field; - -extern -struct bt_event_header_field *bt_event_header_field_create( - struct bt_stream_class *stream_class); - -extern -struct bt_field *bt_event_header_field_borrow_field( - struct bt_event_header_field *field); - -extern -void bt_event_header_field_release(struct bt_event_header_field *field); - -#ifdef __cplusplus -} -#endif - -#endif /* BABELTRACE_CTF_IR_EVENT_HEADER_FIELD_H */ diff --git a/include/babeltrace/ctf-ir/event-internal.h b/include/babeltrace/ctf-ir/event-internal.h deleted file mode 100644 index 39efd2f8..00000000 --- a/include/babeltrace/ctf-ir/event-internal.h +++ /dev/null @@ -1,219 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_EVENT_INTERNAL_H -#define BABELTRACE_CTF_IR_EVENT_INTERNAL_H - -/* - * Babeltrace - CTF IR: Event internal - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* Protection: this file uses BT_LIB_LOG*() macros directly */ -#ifndef BABELTRACE_LIB_LOGGING_INTERNAL_H -# error Please define include before including this file. -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BT_ASSERT_PRE_EVENT_HOT(_event) \ - BT_ASSERT_PRE_HOT((_event), "Event", ": %!+e", (_event)) - -struct bt_event { - struct bt_object base; - struct bt_event_class *class; - struct bt_packet *packet; - struct bt_field_wrapper *header_field; - struct bt_field *common_context_field; - struct bt_field *specific_context_field; - struct bt_field *payload_field; - struct bt_clock_value *default_cv; - bool frozen; -}; - -BT_HIDDEN -void bt_event_destroy(struct bt_event *event); - -BT_HIDDEN -struct bt_event *bt_event_new(struct bt_event_class *event_class); - -BT_HIDDEN -void _bt_event_set_is_frozen(struct bt_event *event, bool is_frozen); - -#ifdef BT_DEV_MODE -# define bt_event_set_is_frozen _bt_event_set_is_frozen -#else -# define bt_event_set_is_frozen(_event, _is_frozen) -#endif - -BT_UNUSED -static inline -void _bt_event_reset_dev_mode(struct bt_event *event) -{ - BT_ASSERT(event); - - if (event->header_field) { - bt_field_set_is_frozen( - event->header_field->field, false); - bt_field_reset( - event->header_field->field); - } - - if (event->common_context_field) { - bt_field_set_is_frozen( - event->common_context_field, false); - bt_field_reset( - event->common_context_field); - } - - if (event->specific_context_field) { - bt_field_set_is_frozen( - event->specific_context_field, false); - bt_field_reset(event->specific_context_field); - } - - if (event->payload_field) { - bt_field_set_is_frozen( - event->payload_field, false); - bt_field_reset(event->payload_field); - } -} - -#ifdef BT_DEV_MODE -# define bt_event_reset_dev_mode _bt_event_reset_dev_mode -#else -# define bt_event_reset_dev_mode(_x) -#endif - -static inline -void bt_event_reset(struct bt_event *event) -{ - BT_ASSERT(event); - BT_LIB_LOGD("Resetting event: %!+e", event); - bt_event_set_is_frozen(event, false); - - if (event->default_cv) { - bt_clock_value_reset(event->default_cv); - } - - bt_object_put_no_null_check(&event->packet->base); - event->packet = NULL; -} - -static inline -void bt_event_recycle(struct bt_event *event) -{ - struct bt_event_class *event_class; - - BT_ASSERT(event); - BT_LIB_LOGD("Recycling event: %!+e", event); - - /* - * Those are the important ordered steps: - * - * 1. Reset the event object (put any permanent reference it - * has, unfreeze it and its fields in developer mode, etc.), - * but do NOT put its class's reference. This event class - * contains the pool to which we're about to recycle this - * event object, so we must guarantee its existence thanks - * to this existing reference. - * - * 2. Move the event class reference to our `event_class` - * variable so that we can set the event's class member - * to NULL before recycling it. We CANNOT do this after - * we put the event class reference because this bt_put() - * could destroy the event class, also destroying its - * event pool, thus also destroying our event object (this - * would result in an invalid write access). - * - * 3. Recycle the event object. - * - * 4. Put our event class reference. - */ - bt_event_reset(event); - event_class = event->class; - BT_ASSERT(event_class); - event->class = NULL; - bt_object_pool_recycle_object(&event_class->event_pool, event); - bt_object_put_no_null_check(&event_class->base); -} - -static inline -void bt_event_set_packet(struct bt_event *event, struct bt_packet *packet) -{ - BT_ASSERT_PRE_NON_NULL(event, "Event"); - BT_ASSERT_PRE_NON_NULL(packet, "Packet"); - BT_ASSERT_PRE_EVENT_HOT(event); - BT_ASSERT_PRE(bt_event_class_borrow_stream_class( - event->class) == packet->stream->class, - "Packet's stream class and event's stream class differ: " - "%![event-]+e, %![packet-]+a", event, packet); - - BT_ASSERT(!event->packet); - event->packet = packet; - bt_object_get_no_null_check_no_parent_check(&event->packet->base); - BT_LIB_LOGV("Set event's packet: %![event-]+e, %![packet-]+a", - event, packet); -} - -static inline -struct bt_event *bt_event_create(struct bt_event_class *event_class, - struct bt_packet *packet) -{ - struct bt_event *event = NULL; - - BT_ASSERT(event_class); - event = bt_object_pool_create_object(&event_class->event_pool); - if (unlikely(!event)) { - BT_LIB_LOGE("Cannot allocate one event from event class's event pool: " - "%![ec-]+E", event_class); - goto end; - } - - if (likely(!event->class)) { - event->class = event_class; - bt_object_get_no_null_check(&event_class->base); - } - - BT_ASSERT(packet); - bt_event_set_packet(event, packet); - goto end; - -end: - return event; -} - -#endif /* BABELTRACE_CTF_IR_EVENT_INTERNAL_H */ diff --git a/include/babeltrace/ctf-ir/event-types.h b/include/babeltrace/ctf-ir/event-types.h new file mode 100644 index 00000000..5bbdda27 --- /dev/null +++ b/include/babeltrace/ctf-ir/event-types.h @@ -0,0 +1,2 @@ +/* Pre-2.0 CTF writer backward compatibility */ +#include diff --git a/include/babeltrace/ctf-ir/event.h b/include/babeltrace/ctf-ir/event.h index 67df08b5..3106be8d 100644 --- a/include/babeltrace/ctf-ir/event.h +++ b/include/babeltrace/ctf-ir/event.h @@ -1,79 +1,2 @@ -#ifndef BABELTRACE_CTF_IR_EVENT_H -#define BABELTRACE_CTF_IR_EVENT_H - -/* - * BabelTrace - CTF IR: Event - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - -#include -#include - -/* For enum bt_clock_value_status */ -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct bt_event; -struct bt_event_header_field; -struct bt_clock_value; -struct bt_event_class; -struct bt_field; -struct bt_packet; - -extern struct bt_event_class *bt_event_borrow_class(struct bt_event *event); - -extern struct bt_packet *bt_event_borrow_packet(struct bt_event *event); - -extern struct bt_stream *bt_event_borrow_stream(struct bt_event *event); - -extern struct bt_field *bt_event_borrow_header_field(struct bt_event *event); - -extern int bt_event_move_header(struct bt_event *event, - struct bt_event_header_field *header); - -extern struct bt_field *bt_event_borrow_common_context_field( - struct bt_event *event); - -extern struct bt_field *bt_event_borrow_specific_context_field( - struct bt_event *event); - -extern struct bt_field *bt_event_borrow_payload_field(struct bt_event *event); - -extern int bt_event_set_default_clock_value(struct bt_event *event, - uint64_t value_cycles); - -extern enum bt_clock_value_status bt_event_borrow_default_clock_value( - struct bt_event *event, struct bt_clock_value **clock_value); - -#ifdef __cplusplus -} -#endif - -#endif /* BABELTRACE_CTF_IR_EVENT_H */ +/* Pre-2.0 CTF writer backward compatibility */ +#include diff --git a/include/babeltrace/ctf-ir/field-path-internal.h b/include/babeltrace/ctf-ir/field-path-internal.h deleted file mode 100644 index f8cb1367..00000000 --- a/include/babeltrace/ctf-ir/field-path-internal.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_FIELD_PATH_INTERNAL -#define BABELTRACE_CTF_IR_FIELD_PATH_INTERNAL - -/* - * BabelTrace - CTF IR: Field path - * - * Copyright 2016 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - -#include -#include -#include -#include - -struct bt_field_path { - struct bt_object base; - enum bt_scope root; - - /* Array of `uint64_t` (indexes) */ - GArray *indexes; -}; - -BT_HIDDEN -struct bt_field_path *bt_field_path_create(void); - -static inline -uint64_t bt_field_path_get_index_by_index_inline( - struct bt_field_path *field_path, uint64_t index) -{ - BT_ASSERT(field_path); - BT_ASSERT(index < field_path->indexes->len); - return g_array_index(field_path->indexes, uint64_t, index); -} - -#endif /* BABELTRACE_CTF_IR_FIELD_PATH_INTERNAL */ diff --git a/include/babeltrace/ctf-ir/field-path.h b/include/babeltrace/ctf-ir/field-path.h deleted file mode 100644 index 7c435abc..00000000 --- a/include/babeltrace/ctf-ir/field-path.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_FIELD_PATH_H -#define BABELTRACE_CTF_IR_FIELD_PATH_H - -/* - * BabelTrace - CTF IR: Field path - * - * Copyright 2016-2018 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct bt_field_path; - -enum bt_scope { - BT_SCOPE_PACKET_HEADER, - BT_SCOPE_PACKET_CONTEXT, - BT_SCOPE_EVENT_HEADER, - BT_SCOPE_EVENT_COMMON_CONTEXT, - BT_SCOPE_EVENT_SPECIFIC_CONTEXT, - BT_SCOPE_EVENT_PAYLOAD, -}; - -extern enum bt_scope bt_field_path_get_root_scope( - struct bt_field_path *field_path); - -extern uint64_t bt_field_path_get_index_count( - struct bt_field_path *field_path); - -extern uint64_t bt_field_path_get_index_by_index( - struct bt_field_path *field_path, uint64_t index); - -#ifdef __cplusplus -} -#endif - -#endif /* BABELTRACE_CTF_IR_FIELD_PATH_H */ diff --git a/include/babeltrace/ctf-ir/field-types-internal.h b/include/babeltrace/ctf-ir/field-types-internal.h deleted file mode 100644 index fcefa063..00000000 --- a/include/babeltrace/ctf-ir/field-types-internal.h +++ /dev/null @@ -1,255 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_FIELD_TYPES_INTERNAL_H -#define BABELTRACE_CTF_IR_FIELD_TYPES_INTERNAL_H - -/* - * BabelTrace - CTF IR: Event field types internal - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define BT_ASSERT_PRE_FT_IS_INT(_ft, _name) \ - BT_ASSERT_PRE( \ - ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_UNSIGNED_INTEGER || \ - ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_SIGNED_INTEGER || \ - ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION || \ - ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, \ - _name " is not an integer field type: %![ft-]+F", (_ft)) - -#define BT_ASSERT_PRE_FT_IS_UNSIGNED_INT(_ft, _name) \ - BT_ASSERT_PRE( \ - ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_UNSIGNED_INTEGER || \ - ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION, \ - _name " is not an unsigned integer field type: %![ft-]+F", (_ft)) - -#define BT_ASSERT_PRE_FT_IS_ENUM(_ft, _name) \ - BT_ASSERT_PRE( \ - ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION || \ - ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, \ - _name " is not an enumeration field type: %![ft-]+F", (_ft)) - -#define BT_ASSERT_PRE_FT_IS_ARRAY(_ft, _name) \ - BT_ASSERT_PRE( \ - ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_STATIC_ARRAY || \ - ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_DYNAMIC_ARRAY, \ - _name " is not an array field type: %![ft-]+F", (_ft)) - -#define BT_ASSERT_PRE_FT_HAS_ID(_ft, _id, _name) \ - BT_ASSERT_PRE(((struct bt_field_type *) (_ft))->id == (_id), \ - _name " has the wrong ID: expected-id=%s, " \ - "%![ft-]+F", bt_common_field_type_id_string(_id), (_ft)) - -#define BT_ASSERT_PRE_FT_HOT(_ft, _name) \ - BT_ASSERT_PRE_HOT((struct bt_field_type *) (_ft), \ - (_name), ": %!+F", (_ft)) - -#define BT_FIELD_TYPE_NAMED_FT_AT_INDEX(_ft, _index) \ - (&g_array_index(((struct bt_field_type_named_field_types_container *) (_ft))->named_fts, \ - struct bt_named_field_type, (_index))) - -#define BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(_ft, _index) \ - (&g_array_index(((struct bt_field_type_enumeration *) (_ft))->mappings, \ - struct bt_field_type_enumeration_mapping, (_index))) - -#define BT_FIELD_TYPE_ENUM_MAPPING_RANGE_AT_INDEX(_mapping, _index) \ - (&g_array_index((_mapping)->ranges, \ - struct bt_field_type_enumeration_mapping_range, (_index))) - -struct bt_field; -struct bt_field_type; - -struct bt_field_type { - struct bt_object base; - enum bt_field_type_id id; - bool frozen; - - /* - * Only used in developer mode, this flag indicates whether or - * not this field type is part of a trace. - */ - bool part_of_trace; -}; - -struct bt_field_type_integer { - struct bt_field_type common; - - /* - * Value range of fields built from this integer field type: - * this is an equivalent integer size in bits. More formally, - * `range` is `n` in: - * - * Unsigned range: [0, 2^n - 1] - * Signed range: [-2^(n - 1), 2^(n - 1) - 1] - */ - uint64_t range; - - enum bt_field_type_integer_preferred_display_base base; -}; - -struct bt_field_type_enumeration_mapping_range { - union { - uint64_t u; - int64_t i; - } lower; - - union { - uint64_t u; - int64_t i; - } upper; -}; - -struct bt_field_type_enumeration_mapping { - GString *label; - - /* Array of `struct bt_field_type_enumeration_mapping_range` */ - GArray *ranges; -}; - -struct bt_field_type_enumeration { - struct bt_field_type_integer common; - - /* Array of `struct bt_field_type_enumeration_mapping *` */ - GArray *mappings; - - /* - * This is an array of `const char *` which acts as a temporary - * (potentially growing) buffer for - * bt_field_type_unsigned_enumeration_get_mapping_labels_by_value() - * and - * bt_field_type_signed_enumeration_get_mapping_labels_by_value(). - * - * The actual strings are owned by the mappings above. - */ - GPtrArray *label_buf; -}; - -struct bt_field_type_real { - struct bt_field_type common; - bool is_single_precision; -}; - -struct bt_field_type_string { - struct bt_field_type common; -}; - -/* A named field type is a (name, field type) pair */ -struct bt_named_field_type { - GString *name; - - /* Owned by this */ - struct bt_field_type *ft; -}; - -/* - * This is the base field type for a container of named field types. - * Structure and variant field types inherit this. - */ -struct bt_field_type_named_field_types_container { - struct bt_field_type common; - - /* - * Key: `const char *`, not owned by this (owned by named field - * type objects contained in `named_fts` below). - */ - GHashTable *name_to_index; - - /* Array of `struct bt_named_field_type` */ - GArray *named_fts; -}; - -struct bt_field_type_structure { - struct bt_field_type_named_field_types_container common; -}; - -struct bt_field_type_array { - struct bt_field_type common; - - /* Owned by this */ - struct bt_field_type *element_ft; -}; - -struct bt_field_type_static_array { - struct bt_field_type_array common; - uint64_t length; -}; - -struct bt_field_type_dynamic_array { - struct bt_field_type_array common; - - /* Weak: never dereferenced, only use to find it elsewhere */ - struct bt_field_type *length_ft; - - /* Owned by this */ - struct bt_field_path *length_field_path; -}; - -struct bt_field_type_variant { - struct bt_field_type_named_field_types_container common; - - /* Weak: never dereferenced, only use to find it elsewhere */ - struct bt_field_type *selector_ft; - - /* Owned by this */ - struct bt_field_path *selector_field_path; -}; - -static inline -bool bt_field_type_has_known_id(struct bt_field_type *ft) -{ - return ft->id >= BT_FIELD_TYPE_ID_UNSIGNED_INTEGER && - ft->id <= BT_FIELD_TYPE_ID_VARIANT; -} - -BT_HIDDEN -void _bt_field_type_freeze(struct bt_field_type *field_type); - -#ifdef BT_DEV_MODE -# define bt_field_type_freeze _bt_field_type_freeze -#else -# define bt_field_type_freeze(_ft) -#endif - -/* - * This function recursively marks `field_type` and its children as - * being part of a trace. This is used to validate that all field types - * are used at a single location within trace objects even if they are - * shared objects for other purposes. - */ -BT_HIDDEN -void _bt_field_type_make_part_of_trace(struct bt_field_type *field_type); - -#ifdef BT_DEV_MODE -# define bt_field_type_make_part_of_trace _bt_field_type_make_part_of_trace -#else -# define bt_field_type_make_part_of_trace(_ft) ((void) _ft) -#endif - -#endif /* BABELTRACE_CTF_IR_FIELD_TYPES_INTERNAL_H */ diff --git a/include/babeltrace/ctf-ir/field-types.h b/include/babeltrace/ctf-ir/field-types.h index 95bc646c..ba9e929c 100644 --- a/include/babeltrace/ctf-ir/field-types.h +++ b/include/babeltrace/ctf-ir/field-types.h @@ -1,222 +1,2 @@ -#ifndef BABELTRACE_CTF_IR_FIELD_TYPES_H -#define BABELTRACE_CTF_IR_FIELD_TYPES_H - -/* - * BabelTrace - CTF IR: Event field types - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - -/* For bt_get() */ -#include - -/* For bt_bool */ -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct bt_field_type; -struct bt_field_path; -struct bt_field_type_signed_enumeration_mapping_ranges; -struct bt_field_type_unsigned_enumeration_mapping_ranges; - -typedef const char * const *bt_field_type_enumeration_mapping_label_array; - -enum bt_field_type_id { - BT_FIELD_TYPE_ID_UNSIGNED_INTEGER, - BT_FIELD_TYPE_ID_SIGNED_INTEGER, - BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION, - BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, - BT_FIELD_TYPE_ID_REAL, - BT_FIELD_TYPE_ID_STRING, - BT_FIELD_TYPE_ID_STRUCTURE, - BT_FIELD_TYPE_ID_STATIC_ARRAY, - BT_FIELD_TYPE_ID_DYNAMIC_ARRAY, - BT_FIELD_TYPE_ID_VARIANT, -}; - -enum bt_field_type_integer_preferred_display_base { - BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_BINARY, - BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL, - BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL, - BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL, -}; - -extern enum bt_field_type_id bt_field_type_get_type_id( - struct bt_field_type *field_type); - -extern struct bt_field_type *bt_field_type_unsigned_integer_create(void); - -extern struct bt_field_type *bt_field_type_signed_integer_create(void); - -extern uint64_t bt_field_type_integer_get_field_value_range( - struct bt_field_type *field_type); - -extern int bt_field_type_integer_set_field_value_range( - struct bt_field_type *field_type, uint64_t size); - -extern enum bt_field_type_integer_preferred_display_base -bt_field_type_integer_get_preferred_display_base( - struct bt_field_type *field_type); - -extern int bt_field_type_integer_set_preferred_display_base( - struct bt_field_type *field_type, - enum bt_field_type_integer_preferred_display_base base); - -extern struct bt_field_type *bt_field_type_real_create(void); - -extern bt_bool bt_field_type_real_is_single_precision( - struct bt_field_type *field_type); - -extern int bt_field_type_real_set_is_single_precision( - struct bt_field_type *field_type, - bt_bool is_single_precision); - -extern struct bt_field_type *bt_field_type_unsigned_enumeration_create(void); - -extern struct bt_field_type *bt_field_type_signed_enumeration_create(void); - -extern uint64_t bt_field_type_enumeration_get_mapping_count( - struct bt_field_type *field_type); - -extern void bt_field_type_unsigned_enumeration_borrow_mapping_by_index( - struct bt_field_type *field_type, uint64_t index, - const char **label, - struct bt_field_type_unsigned_enumeration_mapping_ranges **ranges); - -extern void bt_field_type_signed_enumeration_borrow_mapping_by_index( - struct bt_field_type *field_type, uint64_t index, - const char **label, - struct bt_field_type_signed_enumeration_mapping_ranges **ranges); - -extern uint64_t bt_field_type_unsigned_enumeration_mapping_ranges_get_range_count( - struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges); - -extern uint64_t bt_field_type_signed_enumeration_mapping_ranges_get_range_count( - struct bt_field_type_signed_enumeration_mapping_ranges *ranges); - -extern void bt_field_type_unsigned_enumeration_mapping_ranges_get_range_by_index( - struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges, - uint64_t index, uint64_t *lower, uint64_t *upper); - -extern void bt_field_type_signed_enumeration_mapping_ranges_get_range_by_index( - struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges, - uint64_t index, int64_t *lower, int64_t *upper); - -extern int bt_field_type_unsigned_enumeration_get_mapping_labels_by_value( - struct bt_field_type *field_type, uint64_t value, - bt_field_type_enumeration_mapping_label_array *label_array, - uint64_t *count); - -extern int bt_field_type_signed_enumeration_get_mapping_labels_by_value( - struct bt_field_type *field_type, int64_t value, - bt_field_type_enumeration_mapping_label_array *label_array, - uint64_t *count); - -extern int bt_field_type_unsigned_enumeration_map_range( - struct bt_field_type *field_type, const char *label, - uint64_t range_lower, uint64_t range_upper); - -extern int bt_field_type_signed_enumeration_map_range( - struct bt_field_type *field_type, const char *label, - int64_t range_lower, int64_t range_upper); - -extern struct bt_field_type *bt_field_type_string_create(void); - -extern struct bt_field_type *bt_field_type_structure_create(void); - -extern uint64_t bt_field_type_structure_get_member_count( - struct bt_field_type *field_type); - -extern void bt_field_type_structure_borrow_member_by_index( - struct bt_field_type *struct_field_type, uint64_t index, - const char **name, struct bt_field_type **field_type); - -extern -struct bt_field_type *bt_field_type_structure_borrow_member_field_type_by_name( - struct bt_field_type *field_type, const char *name); - -extern int bt_field_type_structure_append_member( - struct bt_field_type *struct_field_type, const char *name, - struct bt_field_type *field_type); - -extern struct bt_field_type *bt_field_type_static_array_create( - struct bt_field_type *elem_field_type, - uint64_t length); - -extern struct bt_field_type *bt_field_type_dynamic_array_create( - struct bt_field_type *elem_field_type); - -extern struct bt_field_type *bt_field_type_array_borrow_element_field_type( - struct bt_field_type *field_type); - -extern uint64_t bt_field_type_static_array_get_length( - struct bt_field_type *field_type); - -extern struct bt_field_path * -bt_field_type_dynamic_array_borrow_length_field_path( - struct bt_field_type *field_type); - -extern int bt_field_type_dynamic_array_set_length_field_type( - struct bt_field_type *field_type, - struct bt_field_type *length_field_type); - -extern struct bt_field_type *bt_field_type_variant_create(void); - -extern struct bt_field_path * -bt_field_type_variant_borrow_selector_field_path( - struct bt_field_type *field_type); - -extern int bt_field_type_variant_set_selector_field_type( - struct bt_field_type *field_type, - struct bt_field_type *selector_field_type); - -extern uint64_t bt_field_type_variant_get_option_count( - struct bt_field_type *field_type); - -extern void bt_field_type_variant_borrow_option_by_index( - struct bt_field_type *variant_field_type, uint64_t index, - const char **name, struct bt_field_type **field_type); - -extern -struct bt_field_type *bt_field_type_variant_borrow_option_field_type_by_name( - struct bt_field_type *field_type, - const char *name); - -extern int bt_field_type_variant_append_option( - struct bt_field_type *var_field_type, - const char *name, struct bt_field_type *field_type); - -#ifdef __cplusplus -} -#endif - -#endif /* BABELTRACE_CTF_IR_FIELD_TYPES_H */ +/* Pre-2.0 CTF writer backward compatibility */ +#include diff --git a/include/babeltrace/ctf-ir/field-wrapper-internal.h b/include/babeltrace/ctf-ir/field-wrapper-internal.h deleted file mode 100644 index cc164e0c..00000000 --- a/include/babeltrace/ctf-ir/field-wrapper-internal.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_FIELD_WRAPPER_INTERNAL_H -#define BABELTRACE_CTF_IR_FIELD_WRAPPER_INTERNAL_H - -/* - * Copyright 2018 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include - -struct bt_field_wrapper { - struct bt_object base; - - /* Owned by this */ - struct bt_field *field; -}; - -BT_HIDDEN -struct bt_field_wrapper *bt_field_wrapper_new(void *data); - -BT_HIDDEN -void bt_field_wrapper_destroy(struct bt_field_wrapper *field); - -BT_HIDDEN -struct bt_field_wrapper *bt_field_wrapper_create( - struct bt_object_pool *pool, struct bt_field_type *ft); - -#endif /* BABELTRACE_CTF_IR_FIELD_WRAPPER_INTERNAL_H */ diff --git a/include/babeltrace/ctf-ir/fields-internal.h b/include/babeltrace/ctf-ir/fields-internal.h deleted file mode 100644 index 31ec6213..00000000 --- a/include/babeltrace/ctf-ir/fields-internal.h +++ /dev/null @@ -1,206 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_FIELDS_INTERNAL_H -#define BABELTRACE_CTF_IR_FIELDS_INTERNAL_H - -/* - * Babeltrace - CTF IR: Event Fields internal - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(_field, _type_id, _name) \ - BT_ASSERT_PRE(((struct bt_field *) (_field))->type->id == (_type_id), \ - _name " has the wrong type ID: expected-type-id=%s, " \ - "%![field-]+f", \ - bt_common_field_type_id_string(_type_id), (_field)) - -#define BT_ASSERT_PRE_FIELD_IS_UNSIGNED_INT(_field, _name) \ - BT_ASSERT_PRE( \ - ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_UNSIGNED_INTEGER || \ - ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION, \ - _name " is not an unsigned integer field: %![field-]+f", \ - (_field)) - -#define BT_ASSERT_PRE_FIELD_IS_SIGNED_INT(_field, _name) \ - BT_ASSERT_PRE( \ - ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_SIGNED_INTEGER || \ - ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, \ - _name " is not a signed integer field: %![field-]+f", \ - (_field)) - -#define BT_ASSERT_PRE_FIELD_IS_ARRAY(_field, _name) \ - BT_ASSERT_PRE( \ - ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_STATIC_ARRAY || \ - ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_DYNAMIC_ARRAY, \ - _name " is not an array field: %![field-]+f", (_field)) - -#define BT_ASSERT_PRE_FIELD_IS_SET(_field, _name) \ - BT_ASSERT_PRE(bt_field_is_set(_field), \ - _name " is not set: %!+f", (_field)) - -#define BT_ASSERT_PRE_FIELD_HOT(_field, _name) \ - BT_ASSERT_PRE_HOT((struct bt_field *) (_field), (_name), \ - ": %!+f", (_field)) - -struct bt_field; - -typedef struct bt_field *(* bt_field_create_func)(struct bt_field_type *); -typedef void (*bt_field_method_set_is_frozen)(struct bt_field *, bool); -typedef bool (*bt_field_method_is_set)(struct bt_field *); -typedef void (*bt_field_method_reset)(struct bt_field *); - -struct bt_field_methods { - bt_field_method_set_is_frozen set_is_frozen; - bt_field_method_is_set is_set; - bt_field_method_reset reset; -}; - -struct bt_field { - struct bt_object base; - - /* Owned by this */ - struct bt_field_type *type; - - /* Virtual table for slow path (dev mode) operations */ - struct bt_field_methods *methods; - - bool is_set; - bool frozen; -}; - -struct bt_field_integer { - struct bt_field common; - - union { - uint64_t u; - int64_t i; - } value; -}; - -struct bt_field_real { - struct bt_field common; - double value; -}; - -struct bt_field_structure { - struct bt_field common; - - /* Array of `struct bt_field *`, owned by this */ - GPtrArray *fields; -}; - -struct bt_field_variant { - struct bt_field common; - - /* Weak: belongs to `fields` below */ - struct bt_field *selected_field; - - /* Index of currently selected field */ - uint64_t selected_index; - - /* Array of `struct bt_field *`, owned by this */ - GPtrArray *fields; -}; - -struct bt_field_array { - struct bt_field common; - - /* Array of `struct bt_field *`, owned by this */ - GPtrArray *fields; - - /* Current effective length */ - uint64_t length; -}; - -struct bt_field_string { - struct bt_field common; - GArray *buf; - uint64_t length; -}; - -#ifdef BT_DEV_MODE -# define bt_field_set_is_frozen _bt_field_set_is_frozen -# define bt_field_is_set _bt_field_is_set -# define bt_field_reset _bt_field_reset -# define bt_field_set_single _bt_field_set_single -#else -# define bt_field_set_is_frozen(_field, _is_frozen) -# define bt_field_is_set(_field) (BT_FALSE) -# define bt_field_reset(_field) -# define bt_field_set_single(_field, _val) -#endif - -BT_HIDDEN -void _bt_field_set_is_frozen(struct bt_field *field, bool is_frozen); - -static inline -void _bt_field_reset(struct bt_field *field) -{ - BT_ASSERT(field); - BT_ASSERT(field->methods->reset); - field->methods->reset(field); -} - -static inline -void _bt_field_set_single(struct bt_field *field, bool value) -{ - BT_ASSERT(field); - field->is_set = value; -} - -static inline -bt_bool _bt_field_is_set(struct bt_field *field) -{ - bt_bool is_set = BT_FALSE; - - if (!field) { - goto end; - } - - BT_ASSERT(bt_field_type_has_known_id(field->type)); - BT_ASSERT(field->methods->is_set); - is_set = field->methods->is_set(field); - -end: - return is_set; -} - -BT_HIDDEN -struct bt_field *bt_field_create(struct bt_field_type *type); - -BT_HIDDEN -void bt_field_destroy(struct bt_field *field); - -#endif /* BABELTRACE_CTF_IR_FIELDS_INTERNAL_H */ diff --git a/include/babeltrace/ctf-ir/fields.h b/include/babeltrace/ctf-ir/fields.h index 5bf0c3b6..dc6543b0 100644 --- a/include/babeltrace/ctf-ir/fields.h +++ b/include/babeltrace/ctf-ir/fields.h @@ -1,117 +1,2 @@ -#ifndef BABELTRACE_CTF_IR_FIELDS_H -#define BABELTRACE_CTF_IR_FIELDS_H - -/* - * Babeltrace - CTF IR: Event Fields - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - -#include - -/* For bt_bool */ -#include - -/* For enum bt_field_type_id */ -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct bt_field; -struct bt_field_type; -struct bt_field_type_enumeration_mapping_iterator; - -extern struct bt_field_type *bt_field_borrow_type(struct bt_field *field); - -extern enum bt_field_type_id bt_field_get_type_id(struct bt_field *field); - -extern int64_t bt_field_signed_integer_get_value(struct bt_field *field); - -extern void bt_field_signed_integer_set_value(struct bt_field *field, - int64_t value); - -extern uint64_t bt_field_unsigned_integer_get_value(struct bt_field *field); - -extern void bt_field_unsigned_integer_set_value(struct bt_field *field, - uint64_t value); - -extern double bt_field_real_get_value(struct bt_field *field); - -extern void bt_field_real_set_value(struct bt_field *field, double value); - -extern int bt_field_unsigned_enumeration_get_mapping_labels( - struct bt_field *field, - bt_field_type_enumeration_mapping_label_array *label_array, - uint64_t *count); - -extern int bt_field_signed_enumeration_get_mapping_labels( - struct bt_field *field, - bt_field_type_enumeration_mapping_label_array *label_array, - uint64_t *count); - -extern const char *bt_field_string_get_value(struct bt_field *field); - -extern uint64_t bt_field_string_get_length(struct bt_field *field); - -extern int bt_field_string_set_value(struct bt_field *field, const char *value); - -extern int bt_field_string_append(struct bt_field *field, const char *value); - -extern int bt_field_string_append_with_length(struct bt_field *field, - const char *value, uint64_t length); - -extern int bt_field_string_clear(struct bt_field *field); - -extern struct bt_field *bt_field_structure_borrow_member_field_by_index( - struct bt_field *field, uint64_t index); - -extern struct bt_field *bt_field_structure_borrow_member_field_by_name( - struct bt_field *field, const char *name); - -extern uint64_t bt_field_array_get_length(struct bt_field *field); - -extern struct bt_field *bt_field_array_borrow_element_field_by_index( - struct bt_field *field, uint64_t index); - -extern int bt_field_dynamic_array_set_length(struct bt_field *field, - uint64_t length); - -extern int bt_field_variant_select_option_field(struct bt_field *field, - uint64_t index); - -extern uint64_t bt_field_variant_get_selected_option_field_index( - struct bt_field *field); - -extern struct bt_field *bt_field_variant_borrow_selected_option_field( - struct bt_field *field); - -#ifdef __cplusplus -} -#endif - -#endif /* BABELTRACE_CTF_IR_FIELDS_H */ +/* Pre-2.0 CTF writer backward compatibility */ +#include diff --git a/include/babeltrace/ctf-ir/packet-context-field.h b/include/babeltrace/ctf-ir/packet-context-field.h deleted file mode 100644 index 19625422..00000000 --- a/include/babeltrace/ctf-ir/packet-context-field.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_PACKET_CONTEXT_FIELD_H -#define BABELTRACE_CTF_IR_PACKET_CONTEXT_FIELD_H - -/* - * Copyright 2018 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - -#ifdef __cplusplus -extern "C" { -#endif - -struct bt_stream_class; -struct bt_packet_context_field; -struct bt_field; - -extern -struct bt_packet_context_field *bt_packet_context_field_create( - struct bt_stream_class *stream_class); - -extern -struct bt_field *bt_packet_context_field_borrow_field( - struct bt_packet_context_field *field); - -extern -void bt_packet_context_field_release(struct bt_packet_context_field *field); - -#ifdef __cplusplus -} -#endif - -#endif /* BABELTRACE_CTF_IR_PACKET_CONTEXT_FIELD_H */ diff --git a/include/babeltrace/ctf-ir/packet-header-field.h b/include/babeltrace/ctf-ir/packet-header-field.h deleted file mode 100644 index 1e14a8cd..00000000 --- a/include/babeltrace/ctf-ir/packet-header-field.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_PACKET_HEADER_FIELD_H -#define BABELTRACE_CTF_IR_PACKET_HEADER_FIELD_H - -/* - * Copyright 2018 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - -#ifdef __cplusplus -extern "C" { -#endif - -struct bt_trace; -struct bt_packet_header_field; -struct bt_field; - -extern -struct bt_packet_header_field *bt_packet_header_field_create( - struct bt_trace *trace); - -extern -struct bt_field *bt_packet_header_field_borrow_field( - struct bt_packet_header_field *field); - -extern -void bt_packet_header_field_release(struct bt_packet_header_field *field); - -#ifdef __cplusplus -} -#endif - -#endif /* BABELTRACE_CTF_IR_PACKET_HEADER_FIELD_H */ diff --git a/include/babeltrace/ctf-ir/packet-internal.h b/include/babeltrace/ctf-ir/packet-internal.h deleted file mode 100644 index 712903a5..00000000 --- a/include/babeltrace/ctf-ir/packet-internal.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_PACKET_INTERNAL_H -#define BABELTRACE_CTF_IR_PACKET_INTERNAL_H - -/* - * Babeltrace - CTF IR: Stream packet internal - * - * Copyright 2016 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct bt_packet { - struct bt_object base; - struct bt_field_wrapper *header_field; - struct bt_field_wrapper *context_field; - struct bt_stream *stream; - struct bt_clock_value *default_beginning_cv; - struct bt_clock_value *default_end_cv; - struct bt_property_uint discarded_event_counter_snapshot; - struct bt_property_uint packet_counter_snapshot; - bool frozen; -}; - -BT_HIDDEN -void _bt_packet_set_is_frozen(struct bt_packet *packet, bool is_frozen); - -#ifdef BT_DEV_MODE -# define bt_packet_set_is_frozen _bt_packet_set_is_frozen -#else -# define bt_packet_set_is_frozen(_packet, _is_frozen) -#endif /* BT_DEV_MODE */ - -BT_HIDDEN -struct bt_packet *bt_packet_new(struct bt_stream *stream); - -BT_HIDDEN -void bt_packet_recycle(struct bt_packet *packet); - -BT_HIDDEN -void bt_packet_destroy(struct bt_packet *packet); - -#endif /* BABELTRACE_CTF_IR_PACKET_INTERNAL_H */ diff --git a/include/babeltrace/ctf-ir/packet.h b/include/babeltrace/ctf-ir/packet.h deleted file mode 100644 index 7ff057f5..00000000 --- a/include/babeltrace/ctf-ir/packet.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_PACKET_H -#define BABELTRACE_CTF_IR_PACKET_H - -/* - * BabelTrace - CTF IR: Stream packet - * - * Copyright 2016 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - -#include - -/* For enum bt_property_availability */ -#include - -/* For enum bt_clock_value_status */ -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct bt_packet; -struct bt_packet_header_field; -struct bt_packet_context_field; -struct bt_stream; -struct bt_clock_value; - -extern struct bt_packet *bt_packet_create(struct bt_stream *stream); - -extern struct bt_stream *bt_packet_borrow_stream(struct bt_packet *packet); - -extern -struct bt_field *bt_packet_borrow_header_field(struct bt_packet *packet); - -extern -int bt_packet_move_header_field(struct bt_packet *packet, - struct bt_packet_header_field *header); - -extern -struct bt_field *bt_packet_borrow_context_field(struct bt_packet *packet); - -extern -int bt_packet_move_context_field(struct bt_packet *packet, - struct bt_packet_context_field *context); - -extern -enum bt_clock_value_status bt_packet_borrow_default_beginning_clock_value( - struct bt_packet *packet, struct bt_clock_value **clock_value); - -extern -int bt_packet_set_default_beginning_clock_value(struct bt_packet *packet, - uint64_t value_cycles); - -extern -enum bt_clock_value_status bt_packet_borrow_default_end_clock_valeu( - struct bt_packet *packet, struct bt_clock_value **clock_value); - -extern -int bt_packet_set_default_end_clock_value(struct bt_packet *packet, - uint64_t value_cycles); - -extern -enum bt_property_availability bt_packet_get_discarded_event_counter_snapshot( - struct bt_packet *packet, uint64_t *value); - -extern -int bt_packet_set_discarded_event_counter_snapshot(struct bt_packet *packet, - uint64_t value); - -extern -enum bt_property_availability bt_packet_get_packet_counter_snapshot( - struct bt_packet *packet, uint64_t *value); - -extern -int bt_packet_set_packet_counter_snapshot(struct bt_packet *packet, - uint64_t value); - -#ifdef __cplusplus -} -#endif - -#endif /* BABELTRACE_CTF_IR_PACKET_H */ diff --git a/include/babeltrace/ctf-ir/resolve-field-path-internal.h b/include/babeltrace/ctf-ir/resolve-field-path-internal.h deleted file mode 100644 index f2d03214..00000000 --- a/include/babeltrace/ctf-ir/resolve-field-path-internal.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_RESOLVE_FIELD_PATH_INTERNAL -#define BABELTRACE_CTF_IR_RESOLVE_FIELD_PATH_INTERNAL - -/* - * BabelTrace - CTF IR: Field path - * - * Copyright 2016 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - -#include -#include -#include -#include - -struct bt_resolve_field_path_context { - struct bt_field_type *packet_header; - struct bt_field_type *packet_context; - struct bt_field_type *event_header; - struct bt_field_type *event_common_context; - struct bt_field_type *event_specific_context; - struct bt_field_type *event_payload; -}; - -BT_HIDDEN -int bt_resolve_field_paths(struct bt_field_type *ft, - struct bt_resolve_field_path_context *ctx); - -#endif /* BABELTRACE_CTF_IR_RESOLVE_FIELD_PATH_INTERNAL */ diff --git a/include/babeltrace/ctf-ir/resolve-internal.h b/include/babeltrace/ctf-ir/resolve-internal.h deleted file mode 100644 index dad97907..00000000 --- a/include/babeltrace/ctf-ir/resolve-internal.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_RESOLVE_INTERNAL_H -#define BABELTRACE_CTF_IR_RESOLVE_INTERNAL_H - -/* - * Babeltrace - CTF IR: Type resolving internal - * - * Copyright 2015 Jérémie Galarneau - * Copyright 2016 Philippe Proulx - * - * Authors: Jérémie Galarneau - * Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include - -enum bt_resolve_flag { - BT_RESOLVE_FLAG_PACKET_HEADER = 0x01, - BT_RESOLVE_FLAG_PACKET_CONTEXT = 0x02, - BT_RESOLVE_FLAG_EVENT_HEADER = 0x04, - BT_RESOLVE_FLAG_STREAM_EVENT_CTX = 0x08, - BT_RESOLVE_FLAG_EVENT_CONTEXT = 0x10, - BT_RESOLVE_FLAG_EVENT_PAYLOAD = 0x20, -}; - -/* - * Resolves CTF IR field types: recursively locates the tag and length - * field types of resp. variant and sequence field types. - * - * All `*_type` parameters may be resolved, and may as well serve as - * resolving targets. - * - * Resolving is performed based on the flags in `flags`. - * - * It is expected that, amongst all the provided types, no common - * references to sequence variant field types exist. In other words, - * this function does not copy field types. - * - * All parameters are owned by the caller. - */ -BT_HIDDEN -int bt_resolve_types(struct bt_value *environment, - struct bt_field_type *packet_header_type, - struct bt_field_type *packet_context_type, - struct bt_field_type *event_header_type, - struct bt_field_type *stream_event_ctx_type, - struct bt_field_type *event_context_type, - struct bt_field_type *event_payload_type, - enum bt_resolve_flag flags); - -#endif /* BABELTRACE_CTF_IR_RESOLVE_INTERNAL_H */ diff --git a/include/babeltrace/ctf-ir/stream-class-internal.h b/include/babeltrace/ctf-ir/stream-class-internal.h deleted file mode 100644 index 844a0c71..00000000 --- a/include/babeltrace/ctf-ir/stream-class-internal.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_STREAM_CLASS_INTERNAL_H -#define BABELTRACE_CTF_IR_STREAM_CLASS_INTERNAL_H - -/* - * BabelTrace - CTF IR: Stream class internal - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct bt_stream_class { - struct bt_object base; - - struct { - GString *str; - - /* NULL or `str->str` above */ - const char *value; - } name; - - uint64_t id; - bool assigns_automatic_event_class_id; - bool assigns_automatic_stream_id; - bool packets_have_discarded_event_counter_snapshot; - bool packets_have_packet_counter_snapshot; - bool packets_have_default_beginning_cv; - bool packets_have_default_end_cv; - struct bt_field_type *packet_context_ft; - struct bt_field_type *event_header_ft; - struct bt_field_type *event_common_context_ft; - struct bt_clock_class *default_clock_class; - - /* Array of `struct bt_event_class *` */ - GPtrArray *event_classes; - - /* Pool of `struct bt_field_wrapper *` */ - struct bt_object_pool event_header_field_pool; - - /* Pool of `struct bt_field_wrapper *` */ - struct bt_object_pool packet_context_field_pool; - - bool frozen; -}; - -BT_HIDDEN -void _bt_stream_class_freeze(struct bt_stream_class *stream_class); - -#ifdef BT_DEV_MODE -# define bt_stream_class_freeze _bt_stream_class_freeze -#else -# define bt_stream_class_freeze(_sc) -#endif - -static inline -struct bt_trace *bt_stream_class_borrow_trace_inline( - struct bt_stream_class *stream_class) -{ - BT_ASSERT(stream_class); - return (void *) bt_object_borrow_parent(&stream_class->base); -} - -#endif /* BABELTRACE_CTF_IR_STREAM_CLASS_INTERNAL_H */ diff --git a/include/babeltrace/ctf-ir/stream-class.h b/include/babeltrace/ctf-ir/stream-class.h index ca0b9ef9..0322d671 100644 --- a/include/babeltrace/ctf-ir/stream-class.h +++ b/include/babeltrace/ctf-ir/stream-class.h @@ -1,147 +1,2 @@ -#ifndef BABELTRACE_CTF_IR_STREAM_CLASS_H -#define BABELTRACE_CTF_IR_STREAM_CLASS_H - -/* - * BabelTrace - CTF IR: Stream Class - * - * Copyright 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - -#include - -/* For bt_bool */ -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct bt_trace; -struct bt_stream_class; -struct bt_event_class; -struct bt_clock_class; -struct bt_event_header_field; -struct bt_packet_context_field; - -extern struct bt_stream_class *bt_stream_class_create(struct bt_trace *trace); - -extern struct bt_stream_class *bt_stream_class_create_with_id( - struct bt_trace *trace, uint64_t id); - -extern struct bt_trace *bt_stream_class_borrow_trace( - struct bt_stream_class *stream_class); - -extern const char *bt_stream_class_get_name( - struct bt_stream_class *stream_class); - -extern int bt_stream_class_set_name(struct bt_stream_class *stream_class, - const char *name); - -extern bt_bool bt_stream_class_assigns_automatic_event_class_id( - struct bt_stream_class *stream_class); - -extern int bt_stream_class_set_assigns_automatic_event_class_id( - struct bt_stream_class *stream_class, bt_bool value); - -extern bt_bool bt_stream_class_assigns_automatic_stream_id( - struct bt_stream_class *stream_class); - -extern int bt_stream_class_set_assigns_automatic_stream_id( - struct bt_stream_class *stream_class, bt_bool value); - -extern uint64_t bt_stream_class_get_id(struct bt_stream_class *stream_class); - -extern struct bt_field_type *bt_stream_class_borrow_packet_context_field_type( - struct bt_stream_class *stream_class); - -extern int bt_stream_class_set_packet_context_field_type( - struct bt_stream_class *stream_class, - struct bt_field_type *field_type); - -extern struct bt_field_type * -bt_stream_class_borrow_event_header_field_type( - struct bt_stream_class *stream_class); - -extern int bt_stream_class_set_event_header_field_type( - struct bt_stream_class *stream_class, - struct bt_field_type *field_type); - -extern struct bt_field_type * -bt_stream_class_borrow_event_common_context_field_type( - struct bt_stream_class *stream_class); - -extern int bt_stream_class_set_event_common_context_field_type( - struct bt_stream_class *stream_class, - struct bt_field_type *field_type); - -extern uint64_t bt_stream_class_get_event_class_count( - struct bt_stream_class *stream_class); - -extern struct bt_event_class *bt_stream_class_borrow_event_class_by_index( - struct bt_stream_class *stream_class, uint64_t index); - -extern struct bt_event_class *bt_stream_class_borrow_event_class_by_id( - struct bt_stream_class *stream_class, uint64_t id); - -extern int bt_stream_class_set_default_clock_class( - struct bt_stream_class *stream_class, - struct bt_clock_class *clock_class); - -extern struct bt_clock_class *bt_stream_class_borrow_default_clock_class( - struct bt_stream_class *stream_class); - -extern bt_bool bt_stream_class_default_clock_is_always_known( - struct bt_stream_class *stream_class); - -extern bt_bool bt_stream_class_packets_have_discarded_event_counter_snapshot( - struct bt_stream_class *stream_class); - -extern int bt_stream_class_set_packets_have_discarded_event_counter_snapshot( - struct bt_stream_class *stream_class, bt_bool value); - -extern bt_bool bt_stream_class_packets_have_packet_counter_snapshot( - struct bt_stream_class *stream_class); - -extern int bt_stream_class_set_packets_have_packet_counter_snapshot( - struct bt_stream_class *stream_class, bt_bool value); - -extern bt_bool bt_stream_class_packets_have_default_beginning_clock_value( - struct bt_stream_class *stream_class); - -extern int bt_stream_class_set_packets_have_default_beginning_clock_value( - struct bt_stream_class *stream_class, bt_bool value); - -extern bt_bool bt_stream_class_packets_have_default_end_clock_value( - struct bt_stream_class *stream_class); - -extern int bt_stream_class_set_packets_have_default_end_clock_value( - struct bt_stream_class *stream_class, bt_bool value); - -#ifdef __cplusplus -} -#endif - -#endif /* BABELTRACE_CTF_IR_STREAM_CLASS_H */ +/* Pre-2.0 CTF writer backward compatibility */ +#include diff --git a/include/babeltrace/ctf-ir/stream-internal.h b/include/babeltrace/ctf-ir/stream-internal.h deleted file mode 100644 index 0cbd18b5..00000000 --- a/include/babeltrace/ctf-ir/stream-internal.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_STREAM_INTERNAL_H -#define BABELTRACE_CTF_IR_STREAM_INTERNAL_H - -/* - * BabelTrace - CTF Writer: Stream internal - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -struct bt_stream_class; -struct bt_stream; - -struct bt_stream { - struct bt_object base; - - /* Weak: parent is this class's trace */ - struct bt_stream_class *class; - - struct { - GString *str; - - /* NULL or `str->str` above */ - const char *value; - } name; - - uint64_t id; - - /* Pool of `struct bt_packet *` */ - struct bt_object_pool packet_pool; - - bool frozen; -}; - -BT_HIDDEN -void _bt_stream_freeze(struct bt_stream *stream); - -#ifdef BT_DEV_MODE -# define bt_stream_freeze _bt_stream_freeze -#else -# define bt_stream_freeze(_stream) -#endif - -#endif /* BABELTRACE_CTF_IR_STREAM_INTERNAL_H */ diff --git a/include/babeltrace/ctf-ir/stream.h b/include/babeltrace/ctf-ir/stream.h index 69829280..eb7d57fe 100644 --- a/include/babeltrace/ctf-ir/stream.h +++ b/include/babeltrace/ctf-ir/stream.h @@ -1,62 +1,2 @@ -#ifndef BABELTRACE_CTF_IR_STREAM_H -#define BABELTRACE_CTF_IR_STREAM_H - -/* - * BabelTrace - CTF IR: Stream - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - -/* For enum bt_property_availability */ -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct bt_stream; -struct bt_stream_class; - -extern struct bt_stream *bt_stream_create(struct bt_stream_class *stream_class); - -extern struct bt_stream *bt_stream_create_with_id( - struct bt_stream_class *stream_class, uint64_t id); - -extern struct bt_stream_class *bt_stream_borrow_class(struct bt_stream *stream); - -extern const char *bt_stream_get_name(struct bt_stream *stream); - -extern int bt_stream_set_name(struct bt_stream *stream, const char *name); - -extern uint64_t bt_stream_get_id(struct bt_stream *stream); - -#ifdef __cplusplus -} -#endif - -#endif /* BABELTRACE_CTF_IR_STREAM_H */ +/* Pre-2.0 CTF writer backward compatibility */ +#include diff --git a/include/babeltrace/ctf-ir/trace-internal.h b/include/babeltrace/ctf-ir/trace-internal.h deleted file mode 100644 index 30b0ba4f..00000000 --- a/include/babeltrace/ctf-ir/trace-internal.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_TRACE_INTERNAL_H -#define BABELTRACE_CTF_IR_TRACE_INTERNAL_H - -/* - * BabelTrace - CTF IR: Trace internal - * - * Copyright 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct bt_trace { - struct bt_object base; - - struct { - GString *str; - - /* NULL or `str->str` above */ - const char *value; - } name; - - struct { - uint8_t uuid[BABELTRACE_UUID_LEN]; - - /* NULL or `uuid` above */ - bt_uuid value; - } uuid; - - struct bt_value *environment; - - /* Array of `struct bt_stream_class *` */ - GPtrArray *stream_classes; - - /* Array of `struct bt_stream *` */ - GPtrArray *streams; - - /* - * Stream class (weak) to number of instantiated streams, used - * to automatically assign stream IDs per stream class. - */ - GHashTable *stream_classes_stream_count; - - struct bt_field_type *packet_header_ft; - bool assigns_automatic_stream_class_id; - - GArray *is_static_listeners; - bool is_static; - bool in_remove_listener; - - /* Pool of `struct bt_field_wrapper *` */ - struct bt_object_pool packet_header_field_pool; - - bool frozen; -}; - -BT_HIDDEN -void _bt_trace_freeze(struct bt_trace *trace); - -#ifdef BT_DEV_MODE -# define bt_trace_freeze _bt_trace_freeze -#else -# define bt_trace_freeze(_trace) -#endif - -BT_HIDDEN -void bt_trace_add_stream(struct bt_trace *trace, struct bt_stream *stream); - -BT_HIDDEN -uint64_t bt_trace_get_automatic_stream_id(struct bt_trace *trace, - struct bt_stream_class *stream_class); - -#endif /* BABELTRACE_CTF_IR_TRACE_INTERNAL_H */ diff --git a/include/babeltrace/ctf-ir/trace.h b/include/babeltrace/ctf-ir/trace.h index 690c88a3..84b9b7a9 100644 --- a/include/babeltrace/ctf-ir/trace.h +++ b/include/babeltrace/ctf-ir/trace.h @@ -1,127 +1,2 @@ -#ifndef BABELTRACE_CTF_IR_TRACE_H -#define BABELTRACE_CTF_IR_TRACE_H - -/* - * BabelTrace - CTF IR: Trace - * - * Copyright 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - -/* For bt_bool, bt_uuid */ -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct bt_trace; -struct bt_stream; -struct bt_stream_class; -struct bt_field_type; -struct bt_value; -struct bt_packet_header_field; - -typedef void (* bt_trace_is_static_listener)( - struct bt_trace *trace, void *data); - -typedef void (* bt_trace_listener_removed)( - struct bt_trace *trace, void *data); - -extern struct bt_trace *bt_trace_create(void); - -extern bt_bool bt_trace_assigns_automatic_stream_class_id( - struct bt_trace *trace); - -extern int bt_trace_set_assigns_automatic_stream_class_id( - struct bt_trace *trace, bt_bool value); - -extern const char *bt_trace_get_name(struct bt_trace *trace); - -extern int bt_trace_set_name(struct bt_trace *trace, const char *name); - -extern bt_uuid bt_trace_get_uuid(struct bt_trace *trace); - -extern int bt_trace_set_uuid(struct bt_trace *trace, bt_uuid uuid); - -extern uint64_t bt_trace_get_environment_entry_count(struct bt_trace *trace); - -extern void bt_trace_borrow_environment_entry_by_index( - struct bt_trace *trace, uint64_t index, - const char **name, struct bt_value **value); - -extern struct bt_value *bt_trace_borrow_environment_entry_value_by_name( - struct bt_trace *trace, const char *name); - -extern int bt_trace_set_environment_entry_integer( - struct bt_trace *trace, const char *name, - int64_t value); - -extern int bt_trace_set_environment_entry_string( - struct bt_trace *trace, const char *name, - const char *value); - -extern struct bt_field_type *bt_trace_borrow_packet_header_field_type( - struct bt_trace *trace); - -extern int bt_trace_set_packet_header_field_type(struct bt_trace *trace, - struct bt_field_type *packet_header_type); - -extern uint64_t bt_trace_get_stream_class_count(struct bt_trace *trace); - -extern struct bt_stream_class *bt_trace_borrow_stream_class_by_index( - struct bt_trace *trace, uint64_t index); - -extern struct bt_stream_class *bt_trace_borrow_stream_class_by_id( - struct bt_trace *trace, uint64_t id); - -extern uint64_t bt_trace_get_stream_count(struct bt_trace *trace); - -extern struct bt_stream *bt_trace_borrow_stream_by_index( - struct bt_trace *trace, uint64_t index); - -extern struct bt_stream *bt_trace_borrow_stream_by_id( - struct bt_trace *trace, uint64_t id); - -extern bt_bool bt_trace_is_static(struct bt_trace *trace); - -extern int bt_trace_make_static(struct bt_trace *trace); - -extern int bt_trace_add_is_static_listener( - struct bt_trace *trace, - bt_trace_is_static_listener listener, - bt_trace_listener_removed listener_removed, void *data, - uint64_t *listener_id); - -extern int bt_trace_remove_is_static_listener( - struct bt_trace *trace, uint64_t listener_id); - -#ifdef __cplusplus -} -#endif - -#endif /* BABELTRACE_CTF_IR_TRACE_H */ +/* Pre-2.0 CTF writer backward compatibility */ +#include diff --git a/include/babeltrace/ctf-ir/utils-internal.h b/include/babeltrace/ctf-ir/utils-internal.h deleted file mode 100644 index 3c539429..00000000 --- a/include/babeltrace/ctf-ir/utils-internal.h +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef BABELTRACE_CTF_IR_UTILS_INTERNAL_H -#define BABELTRACE_CTF_IR_UTILS_INTERNAL_H - -/* - * Babeltrace - Internal CTF IR utilities - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include - -struct search_query { - gpointer value; - int found; -}; - -static inline -uint64_t bt_util_ns_from_value(uint64_t frequency, uint64_t value_cycles) -{ - uint64_t ns; - - if (frequency == UINT64_C(1000000000)) { - ns = value_cycles; - } else { - double dblres = ((1e9 * (double) value_cycles) / (double) frequency); - - if (dblres >= (double) UINT64_MAX) { - /* Overflows uint64_t */ - ns = UINT64_C(-1); - } else { - ns = (uint64_t) dblres; - } - } - - return ns; -} - -static inline -int bt_util_ns_from_origin(struct bt_clock_class *clock_class, uint64_t value, - int64_t *ns_from_origin) -{ - int ret = 0; - uint64_t value_ns_unsigned; - int64_t value_ns_signed; - - if (clock_class->base_offset.overflows) { - ret = -1; - goto end; - } - - /* Initialize to clock class's base offset */ - *ns_from_origin = clock_class->base_offset.value_ns; - - /* Add given value in cycles */ - value_ns_unsigned = bt_util_ns_from_value(clock_class->frequency, value); - if (value_ns_unsigned >= (uint64_t) INT64_MAX) { - /* - * FIXME: `value_ns_unsigned` could be greater than - * `INT64_MAX` in fact: in this case, we need to - * subtract `INT64_MAX` from `value_ns_unsigned`, make - * sure that the difference is less than `INT64_MAX`, - * and try to add them one after the other to - * `*ns_from_origin`. - */ - ret = -1; - goto end; - } - - value_ns_signed = (int64_t) value_ns_unsigned; - BT_ASSERT(value_ns_signed >= 0); - - if (*ns_from_origin <= 0) { - goto add_value; - } - - if (value_ns_signed > INT64_MAX - *ns_from_origin) { - ret = -1; - goto end; - } - -add_value: - *ns_from_origin += value_ns_signed; - -end: - return ret; -} - -static inline -bool bt_util_value_is_in_range_signed(uint64_t size, int64_t value) -{ - int64_t min_value = UINT64_C(-1) << (size - 1); - int64_t max_value = (UINT64_C(1) << (size - 1)) - 1; - return value >= min_value && value <= max_value; -} - -static inline -bool bt_util_value_is_in_range_unsigned(unsigned int size, uint64_t value) -{ - uint64_t max_value = (size == 64) ? UINT64_MAX : - (UINT64_C(1) << size) - 1; - return value <= max_value; -} - -#endif /* BABELTRACE_CTF_IR_UTILS_INTERNAL_H */ diff --git a/include/babeltrace/ctf-ir/utils.h b/include/babeltrace/ctf-ir/utils.h new file mode 100644 index 00000000..ce14a424 --- /dev/null +++ b/include/babeltrace/ctf-ir/utils.h @@ -0,0 +1,2 @@ +/* Pre-2.0 CTF writer backward compatibility */ +#include diff --git a/include/babeltrace/ctf-writer/visitor.h b/include/babeltrace/ctf-writer/visitor.h index b6583a93..0020e7b2 100644 --- a/include/babeltrace/ctf-writer/visitor.h +++ b/include/babeltrace/ctf-writer/visitor.h @@ -40,7 +40,7 @@ extern "C" { @brief CTF IR visitor. @code -#include +#include @endcode A CTF IR visitor is a function that you diff --git a/include/babeltrace/ctf/events.h b/include/babeltrace/ctf/events.h index 2fd1ffeb..68ec9a6e 100644 --- a/include/babeltrace/ctf/events.h +++ b/include/babeltrace/ctf/events.h @@ -1,41 +1,7 @@ -#ifndef BABELTRACE_CTF_EVENTS_H -#define BABELTRACE_CTF_EVENTS_H - -/* - * Copyright 2017 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The Common Trace Format (CTF) Specification is available at - * http://www.efficios.com/ctf - */ - -/* - * This header still exists for backward compatibility reasons because - * CTF writer needed it to be included. - */ - +/* Pre-2.0 CTF writer backward compatibility */ #include #include #include #include #include #include - -#endif /* BABELTRACE_CTF_EVENTS_H */ diff --git a/include/babeltrace/graph/notification-event-internal.h b/include/babeltrace/graph/notification-event-internal.h index 83a02069..2b401f20 100644 --- a/include/babeltrace/graph/notification-event-internal.h +++ b/include/babeltrace/graph/notification-event-internal.h @@ -28,8 +28,8 @@ */ #include -#include -#include +#include +#include #include #include diff --git a/include/babeltrace/graph/notification-inactivity-internal.h b/include/babeltrace/graph/notification-inactivity-internal.h index 42551c6f..9a74e8fd 100644 --- a/include/babeltrace/graph/notification-inactivity-internal.h +++ b/include/babeltrace/graph/notification-inactivity-internal.h @@ -24,7 +24,7 @@ */ #include -#include +#include #include struct bt_notification_inactivity { diff --git a/include/babeltrace/graph/notification-internal.h b/include/babeltrace/graph/notification-internal.h index 206c110b..81f7d660 100644 --- a/include/babeltrace/graph/notification-internal.h +++ b/include/babeltrace/graph/notification-internal.h @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/babeltrace/graph/notification-packet-internal.h b/include/babeltrace/graph/notification-packet-internal.h index 639925b4..18f6db95 100644 --- a/include/babeltrace/graph/notification-packet-internal.h +++ b/include/babeltrace/graph/notification-packet-internal.h @@ -28,7 +28,7 @@ */ #include -#include +#include #include #include diff --git a/include/babeltrace/graph/notification-stream-internal.h b/include/babeltrace/graph/notification-stream-internal.h index 15dd0847..818fc431 100644 --- a/include/babeltrace/graph/notification-stream-internal.h +++ b/include/babeltrace/graph/notification-stream-internal.h @@ -28,9 +28,9 @@ */ #include -#include +#include #include -#include +#include #include struct bt_notification_stream_begin { diff --git a/include/babeltrace/lib-logging-internal.h b/include/babeltrace/lib-logging-internal.h index e2483b29..6e04f9a2 100644 --- a/include/babeltrace/lib-logging-internal.h +++ b/include/babeltrace/lib-logging-internal.h @@ -79,31 +79,34 @@ int bt_lib_log_level; * The available format specifiers are: * * `F`: - * CTF IR field type. The parameter type is `struct bt_field_type *`. + * Trace IR field type. The parameter type is `struct + * bt_field_type *`. * * `f`: - * CTF IR field. The parameter type is `struct bt_field *`. + * Trace IR field. The parameter type is `struct bt_field *`. * * `P`: * Field path. The parameter type is `struct bt_field_path *`. * * `E`: - * CTF IR event class. The parameter type is `struct bt_event_class *`. + * Trace IR event class. The parameter type is `struct + * bt_event_class *`. * * `e`: - * CTF IR event. The parameter type is `struct bt_event *`. + * Trace IR event. The parameter type is `struct bt_event *`. * * `S`: - * CTF IR stream class. The parameter type is `struct bt_stream_class *`. + * Trace IR stream class. The parameter type is `struct + * bt_stream_class *`. * * `s`: - * CTF IR stream. The parameter type is `struct bt_stream *`. + * Trace IR stream. The parameter type is `struct bt_stream *`. * * `a`: * Packet. The parameter type is `struct bt_packet *`. * * `t`: - * CTF IR trace. The parameter type is `struct bt_trace *`. + * Trace IR trace. The parameter type is `struct bt_trace *`. * * `K`: * Clock class. The parameter type is `struct bt_clock_class *`. @@ -122,7 +125,8 @@ int bt_lib_log_level; * `struct bt_notification_iterator *`. * * `C`: - * Component class. The parameter type is `struct bt_component_class *`. + * Component class. The parameter type is `struct + * bt_component_class *`. * * `c`: * Component. The parameter type is `struct bt_component *`. diff --git a/include/babeltrace/trace-ir/attributes-internal.h b/include/babeltrace/trace-ir/attributes-internal.h new file mode 100644 index 00000000..3820abd7 --- /dev/null +++ b/include/babeltrace/trace-ir/attributes-internal.h @@ -0,0 +1,71 @@ +#ifndef BABELTRACE_TRACE_IR_ATTRIBUTES_H +#define BABELTRACE_TRACE_IR_ATTRIBUTES_H + +/* + * attributes.c + * + * Babeltrace - Trace IR: Attributes internal + * + * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation + * Copyright (c) 2015 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +BT_HIDDEN +struct bt_value *bt_attributes_create(void); + +BT_HIDDEN +void bt_attributes_destroy(struct bt_value *attr_obj); + +BT_HIDDEN +int64_t bt_attributes_get_count(struct bt_value *attr_obj); + +BT_HIDDEN +const char *bt_attributes_get_field_name(struct bt_value *attr_obj, + uint64_t index); + +BT_HIDDEN +struct bt_value *bt_attributes_borrow_field_value(struct bt_value *attr_obj, + uint64_t index); + +BT_HIDDEN +int bt_attributes_set_field_value(struct bt_value *attr_obj, + const char *name, struct bt_value *value_obj); + +BT_HIDDEN +struct bt_value *bt_attributes_borrow_field_value_by_name( + struct bt_value *attr_obj, const char *name); + +BT_HIDDEN +int bt_attributes_freeze(struct bt_value *attr_obj); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_TRACE_IR_ATTRIBUTES_H */ diff --git a/include/babeltrace/trace-ir/clock-class-internal.h b/include/babeltrace/trace-ir/clock-class-internal.h new file mode 100644 index 00000000..86e0e392 --- /dev/null +++ b/include/babeltrace/trace-ir/clock-class-internal.h @@ -0,0 +1,108 @@ +#ifndef BABELTRACE_TRACE_IR_CLOCK_CLASS_INTERNAL_H +#define BABELTRACE_TRACE_IR_CLOCK_CLASS_INTERNAL_H + +/* + * BabelTrace - Trace IR: Clock internal + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct bt_clock_class { + struct bt_object base; + + struct { + GString *str; + + /* NULL or `str->str` above */ + const char *value; + } name; + + struct { + GString *str; + + /* NULL or `str->str` above */ + const char *value; + } description; + + uint64_t frequency; + uint64_t precision; + int64_t offset_seconds; + uint64_t offset_cycles; + + struct { + uint8_t uuid[BABELTRACE_UUID_LEN]; + + /* NULL or `uuid` above */ + bt_uuid value; + } uuid; + + bool is_absolute; + + /* + * This is computed every time you call + * bt_clock_class_set_frequency() or + * bt_clock_class_set_offset(), as well as initially. It is the + * base offset in nanoseconds including both `offset_seconds` + * and `offset_cycles` above in the result. It is used to + * accelerate future calls to + * bt_clock_value_get_ns_from_origin() and + * bt_clock_class_cycles_to_ns_from_origin(). + * + * `overflows` is true if the base offset cannot be computed + * because of an overflow. + */ + struct { + int64_t value_ns; + bool overflows; + } base_offset; + + /* Pool of `struct bt_clock_value *` */ + struct bt_object_pool cv_pool; + + bool frozen; +}; + +BT_HIDDEN +void _bt_clock_class_freeze(struct bt_clock_class *clock_class); + +#ifdef BT_DEV_MODE +# define bt_clock_class_freeze _bt_clock_class_freeze +#else +# define bt_clock_class_freeze(_cc) +#endif + +BT_HIDDEN +bt_bool bt_clock_class_is_valid(struct bt_clock_class *clock_class); + +#endif /* BABELTRACE_TRACE_IR_CLOCK_CLASS_INTERNAL_H */ diff --git a/include/babeltrace/trace-ir/clock-class.h b/include/babeltrace/trace-ir/clock-class.h new file mode 100644 index 00000000..f06a2b00 --- /dev/null +++ b/include/babeltrace/trace-ir/clock-class.h @@ -0,0 +1,95 @@ +#ifndef BABELTRACE_TRACE_IR_CLOCK_CLASS_H +#define BABELTRACE_TRACE_IR_CLOCK_CLASS_H + +/* + * BabelTrace - Trace IR: Clock class + * + * Copyright 2013, 2014 Jérémie Galarneau + * Copyright 2017-2018 Philippe Proulx + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +#include + +/* For bt_bool, bt_uuid */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct bt_clock_class; +struct bt_clock_value; + +extern struct bt_clock_class *bt_clock_class_create(void); + +extern const char *bt_clock_class_get_name(struct bt_clock_class *clock_class); + +extern int bt_clock_class_set_name(struct bt_clock_class *clock_class, + const char *name); + +extern const char *bt_clock_class_get_description( + struct bt_clock_class *clock_class); + +extern int bt_clock_class_set_description(struct bt_clock_class *clock_class, + const char *description); + +extern uint64_t bt_clock_class_get_frequency( + struct bt_clock_class *clock_class); + +extern int bt_clock_class_set_frequency(struct bt_clock_class *clock_class, + uint64_t freq); + +extern uint64_t bt_clock_class_get_precision( + struct bt_clock_class *clock_class); + +extern int bt_clock_class_set_precision(struct bt_clock_class *clock_class, + uint64_t precision); + +extern void bt_clock_class_get_offset(struct bt_clock_class *clock_class, + int64_t *seconds, uint64_t *cycles); + +extern int bt_clock_class_set_offset(struct bt_clock_class *clock_class, + int64_t seconds, uint64_t cycles); + +extern bt_bool bt_clock_class_is_absolute(struct bt_clock_class *clock_class); + +extern int bt_clock_class_set_is_absolute(struct bt_clock_class *clock_class, + bt_bool is_absolute); + +extern bt_uuid bt_clock_class_get_uuid(struct bt_clock_class *clock_class); + +extern int bt_clock_class_set_uuid(struct bt_clock_class *clock_class, + bt_uuid uuid); + +extern int bt_clock_class_cycles_to_ns_from_origin( + struct bt_clock_class *clock_class, + uint64_t cycles, int64_t *ns_from_origin); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_TRACE_IR_CLOCK_CLASS_H */ diff --git a/include/babeltrace/trace-ir/clock-value-internal.h b/include/babeltrace/trace-ir/clock-value-internal.h new file mode 100644 index 00000000..8cb7802b --- /dev/null +++ b/include/babeltrace/trace-ir/clock-value-internal.h @@ -0,0 +1,102 @@ +#ifndef BABELTRACE_TRACE_IR_CLOCK_VALUE_INTERNAL_H +#define BABELTRACE_TRACE_IR_CLOCK_VALUE_INTERNAL_H + +/* + * Copyright 2017 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +struct bt_clock_class; + +struct bt_clock_value { + struct bt_object base; + struct bt_clock_class *clock_class; + uint64_t value_cycles; + bool ns_from_origin_overflows; + int64_t ns_from_origin; + bool is_set; +}; + +static inline +void bt_clock_value_set(struct bt_clock_value *clock_value) +{ + BT_ASSERT(clock_value); + clock_value->is_set = true; +} + +static inline +void bt_clock_value_reset(struct bt_clock_value *clock_value) +{ + BT_ASSERT(clock_value); + clock_value->is_set = false; +} + +static inline +void set_ns_from_origin(struct bt_clock_value *clock_value) +{ + if (bt_util_ns_from_origin(clock_value->clock_class, clock_value->value_cycles, + &clock_value->ns_from_origin)) { + clock_value->ns_from_origin_overflows = true; + } + +} + +static inline +void bt_clock_value_set_raw_value(struct bt_clock_value *clock_value, + uint64_t cycles) +{ + BT_ASSERT(clock_value); + clock_value->value_cycles = cycles; + set_ns_from_origin(clock_value); + bt_clock_value_set(clock_value); +} + +static inline +void bt_clock_value_set_value_inline(struct bt_clock_value *clock_value, + uint64_t raw_value) +{ + bt_clock_value_set_raw_value(clock_value, raw_value); +} + +BT_HIDDEN +void bt_clock_value_destroy(struct bt_clock_value *clock_value); + +BT_HIDDEN +struct bt_clock_value *bt_clock_value_new(struct bt_clock_class *clock_class); + +BT_HIDDEN +struct bt_clock_value *bt_clock_value_create( + struct bt_clock_class *clock_class); + +BT_HIDDEN +void bt_clock_value_recycle(struct bt_clock_value *clock_value); + +BT_HIDDEN +void bt_clock_value_set_raw_value(struct bt_clock_value *clock_value, + uint64_t cycles); + +#endif /* BABELTRACE_TRACE_IR_CLOCK_VALUE_INTERNAL_H */ diff --git a/include/babeltrace/trace-ir/clock-value-set-internal.h b/include/babeltrace/trace-ir/clock-value-set-internal.h new file mode 100644 index 00000000..5c7e7bd3 --- /dev/null +++ b/include/babeltrace/trace-ir/clock-value-set-internal.h @@ -0,0 +1,159 @@ +#ifndef BABELTRACE_GRAPH_CLOCK_VALUE_SET_H +#define BABELTRACE_GRAPH_CLOCK_VALUE_SET_H + +/* + * Copyright 2018 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include + +struct bt_clock_value_set { + /* Unique objects owned by this */ + GPtrArray *clock_values; + + /* Weak; points to one of the clock values above */ + struct bt_clock_value *default_cv; +}; + +static inline +int bt_clock_value_set_initialize(struct bt_clock_value_set *cv_set) +{ + int ret = 0; + + cv_set->clock_values = g_ptr_array_sized_new(1); + if (!cv_set->clock_values) { +#ifdef BT_LOGE_STR + BT_LOGE_STR("Failed to allocate one GPtrArray."); +#endif + + ret = -1; + goto end; + } + + cv_set->default_cv = NULL; + +end: + return ret; +} + +static inline +void bt_clock_value_set_reset(struct bt_clock_value_set *cv_set) +{ + uint64_t i; + + BT_ASSERT(cv_set); + BT_ASSERT(cv_set->clock_values); + + for (i = 0; i < cv_set->clock_values->len; i++) { + struct bt_clock_value *cv = cv_set->clock_values->pdata[i]; + + BT_ASSERT(cv); + bt_clock_value_reset(cv); + } + + cv_set->default_cv = NULL; +} + +static inline +void bt_clock_value_set_finalize(struct bt_clock_value_set *cv_set) +{ + uint64_t i; + + BT_ASSERT(cv_set); + + if (cv_set->clock_values) { + for (i = 0; i < cv_set->clock_values->len; i++) { + struct bt_clock_value *cv = + cv_set->clock_values->pdata[i]; + + BT_ASSERT(cv); + bt_clock_value_recycle(cv); + } + + g_ptr_array_free(cv_set->clock_values, TRUE); + } + + cv_set->default_cv = NULL; +} + +static inline +int bt_clock_value_set_set_clock_value(struct bt_clock_value_set *cv_set, + struct bt_clock_class *cc, uint64_t raw_value) +{ + int ret = 0; + struct bt_clock_value *clock_value = NULL; + uint64_t i; + + BT_ASSERT(cv_set); + BT_ASSERT(cc); + + /* + * Check if we already have a value for this clock class. + * + * TODO: When we have many clock classes, make this more + * efficient. + */ + for (i = 0; i < cv_set->clock_values->len; i++) { + struct bt_clock_value *cv = cv_set->clock_values->pdata[i]; + + BT_ASSERT(cv); + + if (cv->clock_class == cc) { + clock_value = cv; + break; + } + } + + if (!clock_value) { + clock_value = bt_clock_value_create(cc); + if (!clock_value) { +#ifdef BT_LIB_LOGE + BT_LIB_LOGE("Cannot create a clock value from a clock class: " + "%![cc-]+K", cc); +#endif + + ret = -1; + goto end; + } + + g_ptr_array_add(cv_set->clock_values, clock_value); + } + + bt_clock_value_set_value_inline(clock_value, raw_value); + +end: + return ret; +} + +static inline +void bt_clock_value_set_set_default_clock_value( + struct bt_clock_value_set *cv_set, uint64_t raw_value) +{ + BT_ASSERT(cv_set); + BT_ASSERT(cv_set->default_cv); + bt_clock_value_set_value_inline(cv_set->default_cv, raw_value); +} + +#endif /* BABELTRACE_GRAPH_CLOCK_VALUE_SET_H */ diff --git a/include/babeltrace/trace-ir/clock-value.h b/include/babeltrace/trace-ir/clock-value.h new file mode 100644 index 00000000..0676fa01 --- /dev/null +++ b/include/babeltrace/trace-ir/clock-value.h @@ -0,0 +1,61 @@ +#ifndef BABELTRACE_TRACE_IR_CLOCK_VALUE_H +#define BABELTRACE_TRACE_IR_CLOCK_VALUE_H + +/* + * BabelTrace - Trace IR: Clock class + * + * Copyright 2013, 2014 Jérémie Galarneau + * Copyright 2017 Philippe Proulx + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct bt_clock_class; +struct bt_clock_value; + +enum bt_clock_value_status { + BT_CLOCK_VALUE_STATUS_KNOWN, + BT_CLOCK_VALUE_STATUS_UNKNOWN, +}; + +extern struct bt_clock_class *bt_clock_value_borrow_clock_class( + struct bt_clock_value *clock_value); + +extern uint64_t bt_clock_value_get_value( + struct bt_clock_value *clock_value); + +extern int bt_clock_value_get_ns_from_origin( + struct bt_clock_value *clock_value, int64_t *ns_from_origin); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_TRACE_IR_CLOCK_VALUE_H */ diff --git a/include/babeltrace/trace-ir/clock.h b/include/babeltrace/trace-ir/clock.h new file mode 100644 index 00000000..2fcf48f8 --- /dev/null +++ b/include/babeltrace/trace-ir/clock.h @@ -0,0 +1,35 @@ +#ifndef BABELTRACE_TRACE_IR_CLOCK_H +#define BABELTRACE_TRACE_IR_CLOCK_H + +/* + * BabelTrace - Trace IR: Clock + * + * Copyright 2018 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +#include + +#endif /* BABELTRACE_TRACE_IR_CLOCK_H */ diff --git a/include/babeltrace/trace-ir/event-class-internal.h b/include/babeltrace/trace-ir/event-class-internal.h new file mode 100644 index 00000000..3f366dda --- /dev/null +++ b/include/babeltrace/trace-ir/event-class-internal.h @@ -0,0 +1,91 @@ +#ifndef BABELTRACE_TRACE_IR_EVENT_CLASS_INTERNAL_H +#define BABELTRACE_TRACE_IR_EVENT_CLASS_INTERNAL_H + +/* + * Babeltrace - Trace IR: Event class internal + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct bt_event_class { + struct bt_object base; + struct bt_field_type *specific_context_ft; + struct bt_field_type *payload_ft; + + struct { + GString *str; + + /* NULL or `str->str` above */ + const char *value; + } name; + + uint64_t id; + struct bt_property_uint log_level; + + struct { + GString *str; + + /* NULL or `str->str` above */ + const char *value; + } emf_uri; + + /* Pool of `struct bt_event *` */ + struct bt_object_pool event_pool; + + bool frozen; +}; + +BT_HIDDEN +void _bt_event_class_freeze(struct bt_event_class *event_class); + +#ifdef BT_DEV_MODE +# define bt_event_class_freeze _bt_event_class_freeze +#else +# define bt_event_class_freeze(_ec) +#endif + +static inline +struct bt_stream_class *bt_event_class_borrow_stream_class_inline( + struct bt_event_class *event_class) +{ + BT_ASSERT(event_class); + return (void *) bt_object_borrow_parent(&event_class->base); +} + +#endif /* BABELTRACE_TRACE_IR_EVENT_CLASS_INTERNAL_H */ diff --git a/include/babeltrace/trace-ir/event-class.h b/include/babeltrace/trace-ir/event-class.h new file mode 100644 index 00000000..ae052eea --- /dev/null +++ b/include/babeltrace/trace-ir/event-class.h @@ -0,0 +1,112 @@ +#ifndef BABELTRACE_TRACE_IR_EVENT_CLASS_H +#define BABELTRACE_TRACE_IR_EVENT_CLASS_H + +/* + * BabelTrace - Trace IR: Event class + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +/* For enum bt_property_availability */ +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct bt_event_class; +struct bt_field_type; +struct bt_stream_class; + +enum bt_event_class_log_level { + BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY, + BT_EVENT_CLASS_LOG_LEVEL_ALERT, + BT_EVENT_CLASS_LOG_LEVEL_CRITICAL, + BT_EVENT_CLASS_LOG_LEVEL_ERROR, + BT_EVENT_CLASS_LOG_LEVEL_WARNING, + BT_EVENT_CLASS_LOG_LEVEL_NOTICE, + BT_EVENT_CLASS_LOG_LEVEL_INFO, + BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM, + BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM, + BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS, + BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE, + BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT, + BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION, + BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE, + BT_EVENT_CLASS_LOG_LEVEL_DEBUG, +}; + +extern struct bt_event_class *bt_event_class_create( + struct bt_stream_class *stream_class); + +extern struct bt_event_class *bt_event_class_create_with_id( + struct bt_stream_class *stream_class, uint64_t id); + +extern struct bt_stream_class *bt_event_class_borrow_stream_class( + struct bt_event_class *event_class); + +extern const char *bt_event_class_get_name(struct bt_event_class *event_class); + +extern int bt_event_class_set_name(struct bt_event_class *event_class, + const char *name); + +extern uint64_t bt_event_class_get_id(struct bt_event_class *event_class); + +extern enum bt_property_availability bt_event_class_get_log_level( + struct bt_event_class *event_class, + enum bt_event_class_log_level *log_level); + +extern int bt_event_class_set_log_level(struct bt_event_class *event_class, + enum bt_event_class_log_level log_level); + +extern const char *bt_event_class_get_emf_uri( + struct bt_event_class *event_class); + +extern int bt_event_class_set_emf_uri(struct bt_event_class *event_class, + const char *emf_uri); + +extern struct bt_field_type *bt_event_class_borrow_specific_context_field_type( + struct bt_event_class *event_class); + +extern int bt_event_class_set_specific_context_field_type( + struct bt_event_class *event_class, + struct bt_field_type *field_type); + +extern struct bt_field_type *bt_event_class_borrow_payload_field_type( + struct bt_event_class *event_class); + +extern int bt_event_class_set_payload_field_type( + struct bt_event_class *event_class, + struct bt_field_type *field_type); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_TRACE_IR_EVENT_CLASS_H */ diff --git a/include/babeltrace/trace-ir/event-header-field.h b/include/babeltrace/trace-ir/event-header-field.h new file mode 100644 index 00000000..fa3719ed --- /dev/null +++ b/include/babeltrace/trace-ir/event-header-field.h @@ -0,0 +1,52 @@ +#ifndef BABELTRACE_TRACE_IR_EVENT_HEADER_FIELD_H +#define BABELTRACE_TRACE_IR_EVENT_HEADER_FIELD_H + +/* + * Copyright 2018 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct bt_stream_class; +struct bt_event_header_field; +struct bt_field; + +extern +struct bt_event_header_field *bt_event_header_field_create( + struct bt_stream_class *stream_class); + +extern +struct bt_field *bt_event_header_field_borrow_field( + struct bt_event_header_field *field); + +extern +void bt_event_header_field_release(struct bt_event_header_field *field); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_TRACE_IR_EVENT_HEADER_FIELD_H */ diff --git a/include/babeltrace/trace-ir/event-internal.h b/include/babeltrace/trace-ir/event-internal.h new file mode 100644 index 00000000..ef5bdf0b --- /dev/null +++ b/include/babeltrace/trace-ir/event-internal.h @@ -0,0 +1,219 @@ +#ifndef BABELTRACE_TRACE_IR_EVENT_INTERNAL_H +#define BABELTRACE_TRACE_IR_EVENT_INTERNAL_H + +/* + * Babeltrace - Trace IR: Event internal + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* Protection: this file uses BT_LIB_LOG*() macros directly */ +#ifndef BABELTRACE_LIB_LOGGING_INTERNAL_H +# error Please define include before including this file. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BT_ASSERT_PRE_EVENT_HOT(_event) \ + BT_ASSERT_PRE_HOT((_event), "Event", ": %!+e", (_event)) + +struct bt_event { + struct bt_object base; + struct bt_event_class *class; + struct bt_packet *packet; + struct bt_field_wrapper *header_field; + struct bt_field *common_context_field; + struct bt_field *specific_context_field; + struct bt_field *payload_field; + struct bt_clock_value *default_cv; + bool frozen; +}; + +BT_HIDDEN +void bt_event_destroy(struct bt_event *event); + +BT_HIDDEN +struct bt_event *bt_event_new(struct bt_event_class *event_class); + +BT_HIDDEN +void _bt_event_set_is_frozen(struct bt_event *event, bool is_frozen); + +#ifdef BT_DEV_MODE +# define bt_event_set_is_frozen _bt_event_set_is_frozen +#else +# define bt_event_set_is_frozen(_event, _is_frozen) +#endif + +BT_UNUSED +static inline +void _bt_event_reset_dev_mode(struct bt_event *event) +{ + BT_ASSERT(event); + + if (event->header_field) { + bt_field_set_is_frozen( + event->header_field->field, false); + bt_field_reset( + event->header_field->field); + } + + if (event->common_context_field) { + bt_field_set_is_frozen( + event->common_context_field, false); + bt_field_reset( + event->common_context_field); + } + + if (event->specific_context_field) { + bt_field_set_is_frozen( + event->specific_context_field, false); + bt_field_reset(event->specific_context_field); + } + + if (event->payload_field) { + bt_field_set_is_frozen( + event->payload_field, false); + bt_field_reset(event->payload_field); + } +} + +#ifdef BT_DEV_MODE +# define bt_event_reset_dev_mode _bt_event_reset_dev_mode +#else +# define bt_event_reset_dev_mode(_x) +#endif + +static inline +void bt_event_reset(struct bt_event *event) +{ + BT_ASSERT(event); + BT_LIB_LOGD("Resetting event: %!+e", event); + bt_event_set_is_frozen(event, false); + + if (event->default_cv) { + bt_clock_value_reset(event->default_cv); + } + + bt_object_put_no_null_check(&event->packet->base); + event->packet = NULL; +} + +static inline +void bt_event_recycle(struct bt_event *event) +{ + struct bt_event_class *event_class; + + BT_ASSERT(event); + BT_LIB_LOGD("Recycling event: %!+e", event); + + /* + * Those are the important ordered steps: + * + * 1. Reset the event object (put any permanent reference it + * has, unfreeze it and its fields in developer mode, etc.), + * but do NOT put its class's reference. This event class + * contains the pool to which we're about to recycle this + * event object, so we must guarantee its existence thanks + * to this existing reference. + * + * 2. Move the event class reference to our `event_class` + * variable so that we can set the event's class member + * to NULL before recycling it. We CANNOT do this after + * we put the event class reference because this bt_put() + * could destroy the event class, also destroying its + * event pool, thus also destroying our event object (this + * would result in an invalid write access). + * + * 3. Recycle the event object. + * + * 4. Put our event class reference. + */ + bt_event_reset(event); + event_class = event->class; + BT_ASSERT(event_class); + event->class = NULL; + bt_object_pool_recycle_object(&event_class->event_pool, event); + bt_object_put_no_null_check(&event_class->base); +} + +static inline +void bt_event_set_packet(struct bt_event *event, struct bt_packet *packet) +{ + BT_ASSERT_PRE_NON_NULL(event, "Event"); + BT_ASSERT_PRE_NON_NULL(packet, "Packet"); + BT_ASSERT_PRE_EVENT_HOT(event); + BT_ASSERT_PRE(bt_event_class_borrow_stream_class( + event->class) == packet->stream->class, + "Packet's stream class and event's stream class differ: " + "%![event-]+e, %![packet-]+a", event, packet); + + BT_ASSERT(!event->packet); + event->packet = packet; + bt_object_get_no_null_check_no_parent_check(&event->packet->base); + BT_LIB_LOGV("Set event's packet: %![event-]+e, %![packet-]+a", + event, packet); +} + +static inline +struct bt_event *bt_event_create(struct bt_event_class *event_class, + struct bt_packet *packet) +{ + struct bt_event *event = NULL; + + BT_ASSERT(event_class); + event = bt_object_pool_create_object(&event_class->event_pool); + if (unlikely(!event)) { + BT_LIB_LOGE("Cannot allocate one event from event class's event pool: " + "%![ec-]+E", event_class); + goto end; + } + + if (likely(!event->class)) { + event->class = event_class; + bt_object_get_no_null_check(&event_class->base); + } + + BT_ASSERT(packet); + bt_event_set_packet(event, packet); + goto end; + +end: + return event; +} + +#endif /* BABELTRACE_TRACE_IR_EVENT_INTERNAL_H */ diff --git a/include/babeltrace/trace-ir/event.h b/include/babeltrace/trace-ir/event.h new file mode 100644 index 00000000..574af841 --- /dev/null +++ b/include/babeltrace/trace-ir/event.h @@ -0,0 +1,79 @@ +#ifndef BABELTRACE_TRACE_IR_EVENT_H +#define BABELTRACE_TRACE_IR_EVENT_H + +/* + * BabelTrace - Trace IR: Event + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +#include +#include + +/* For enum bt_clock_value_status */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct bt_event; +struct bt_event_header_field; +struct bt_clock_value; +struct bt_event_class; +struct bt_field; +struct bt_packet; + +extern struct bt_event_class *bt_event_borrow_class(struct bt_event *event); + +extern struct bt_packet *bt_event_borrow_packet(struct bt_event *event); + +extern struct bt_stream *bt_event_borrow_stream(struct bt_event *event); + +extern struct bt_field *bt_event_borrow_header_field(struct bt_event *event); + +extern int bt_event_move_header(struct bt_event *event, + struct bt_event_header_field *header); + +extern struct bt_field *bt_event_borrow_common_context_field( + struct bt_event *event); + +extern struct bt_field *bt_event_borrow_specific_context_field( + struct bt_event *event); + +extern struct bt_field *bt_event_borrow_payload_field(struct bt_event *event); + +extern int bt_event_set_default_clock_value(struct bt_event *event, + uint64_t value_cycles); + +extern enum bt_clock_value_status bt_event_borrow_default_clock_value( + struct bt_event *event, struct bt_clock_value **clock_value); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_TRACE_IR_EVENT_H */ diff --git a/include/babeltrace/trace-ir/field-path-internal.h b/include/babeltrace/trace-ir/field-path-internal.h new file mode 100644 index 00000000..fd6ebc3c --- /dev/null +++ b/include/babeltrace/trace-ir/field-path-internal.h @@ -0,0 +1,56 @@ +#ifndef BABELTRACE_TRACE_IR_FIELD_PATH_INTERNAL +#define BABELTRACE_TRACE_IR_FIELD_PATH_INTERNAL + +/* + * BabelTrace - Trace IR: Field path + * + * Copyright 2016 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +#include +#include +#include +#include + +struct bt_field_path { + struct bt_object base; + enum bt_scope root; + + /* Array of `uint64_t` (indexes) */ + GArray *indexes; +}; + +BT_HIDDEN +struct bt_field_path *bt_field_path_create(void); + +static inline +uint64_t bt_field_path_get_index_by_index_inline( + struct bt_field_path *field_path, uint64_t index) +{ + BT_ASSERT(field_path); + BT_ASSERT(index < field_path->indexes->len); + return g_array_index(field_path->indexes, uint64_t, index); +} + +#endif /* BABELTRACE_TRACE_IR_FIELD_PATH_INTERNAL */ diff --git a/include/babeltrace/trace-ir/field-path.h b/include/babeltrace/trace-ir/field-path.h new file mode 100644 index 00000000..2556a6fb --- /dev/null +++ b/include/babeltrace/trace-ir/field-path.h @@ -0,0 +1,61 @@ +#ifndef BABELTRACE_TRACE_IR_FIELD_PATH_H +#define BABELTRACE_TRACE_IR_FIELD_PATH_H + +/* + * BabelTrace - Trace IR: Field path + * + * Copyright 2016-2018 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct bt_field_path; + +enum bt_scope { + BT_SCOPE_PACKET_HEADER, + BT_SCOPE_PACKET_CONTEXT, + BT_SCOPE_EVENT_HEADER, + BT_SCOPE_EVENT_COMMON_CONTEXT, + BT_SCOPE_EVENT_SPECIFIC_CONTEXT, + BT_SCOPE_EVENT_PAYLOAD, +}; + +extern enum bt_scope bt_field_path_get_root_scope( + struct bt_field_path *field_path); + +extern uint64_t bt_field_path_get_index_count( + struct bt_field_path *field_path); + +extern uint64_t bt_field_path_get_index_by_index( + struct bt_field_path *field_path, uint64_t index); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_TRACE_IR_FIELD_PATH_H */ diff --git a/include/babeltrace/trace-ir/field-types-internal.h b/include/babeltrace/trace-ir/field-types-internal.h new file mode 100644 index 00000000..82ec15ce --- /dev/null +++ b/include/babeltrace/trace-ir/field-types-internal.h @@ -0,0 +1,255 @@ +#ifndef BABELTRACE_TRACE_IR_FIELD_TYPES_INTERNAL_H +#define BABELTRACE_TRACE_IR_FIELD_TYPES_INTERNAL_H + +/* + * BabelTrace - Trace IR: Event field types internal + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define BT_ASSERT_PRE_FT_IS_INT(_ft, _name) \ + BT_ASSERT_PRE( \ + ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_UNSIGNED_INTEGER || \ + ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_SIGNED_INTEGER || \ + ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION || \ + ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, \ + _name " is not an integer field type: %![ft-]+F", (_ft)) + +#define BT_ASSERT_PRE_FT_IS_UNSIGNED_INT(_ft, _name) \ + BT_ASSERT_PRE( \ + ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_UNSIGNED_INTEGER || \ + ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION, \ + _name " is not an unsigned integer field type: %![ft-]+F", (_ft)) + +#define BT_ASSERT_PRE_FT_IS_ENUM(_ft, _name) \ + BT_ASSERT_PRE( \ + ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION || \ + ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, \ + _name " is not an enumeration field type: %![ft-]+F", (_ft)) + +#define BT_ASSERT_PRE_FT_IS_ARRAY(_ft, _name) \ + BT_ASSERT_PRE( \ + ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_STATIC_ARRAY || \ + ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_DYNAMIC_ARRAY, \ + _name " is not an array field type: %![ft-]+F", (_ft)) + +#define BT_ASSERT_PRE_FT_HAS_ID(_ft, _id, _name) \ + BT_ASSERT_PRE(((struct bt_field_type *) (_ft))->id == (_id), \ + _name " has the wrong ID: expected-id=%s, " \ + "%![ft-]+F", bt_common_field_type_id_string(_id), (_ft)) + +#define BT_ASSERT_PRE_FT_HOT(_ft, _name) \ + BT_ASSERT_PRE_HOT((struct bt_field_type *) (_ft), \ + (_name), ": %!+F", (_ft)) + +#define BT_FIELD_TYPE_NAMED_FT_AT_INDEX(_ft, _index) \ + (&g_array_index(((struct bt_field_type_named_field_types_container *) (_ft))->named_fts, \ + struct bt_named_field_type, (_index))) + +#define BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(_ft, _index) \ + (&g_array_index(((struct bt_field_type_enumeration *) (_ft))->mappings, \ + struct bt_field_type_enumeration_mapping, (_index))) + +#define BT_FIELD_TYPE_ENUM_MAPPING_RANGE_AT_INDEX(_mapping, _index) \ + (&g_array_index((_mapping)->ranges, \ + struct bt_field_type_enumeration_mapping_range, (_index))) + +struct bt_field; +struct bt_field_type; + +struct bt_field_type { + struct bt_object base; + enum bt_field_type_id id; + bool frozen; + + /* + * Only used in developer mode, this flag indicates whether or + * not this field type is part of a trace. + */ + bool part_of_trace; +}; + +struct bt_field_type_integer { + struct bt_field_type common; + + /* + * Value range of fields built from this integer field type: + * this is an equivalent integer size in bits. More formally, + * `range` is `n` in: + * + * Unsigned range: [0, 2^n - 1] + * Signed range: [-2^(n - 1), 2^(n - 1) - 1] + */ + uint64_t range; + + enum bt_field_type_integer_preferred_display_base base; +}; + +struct bt_field_type_enumeration_mapping_range { + union { + uint64_t u; + int64_t i; + } lower; + + union { + uint64_t u; + int64_t i; + } upper; +}; + +struct bt_field_type_enumeration_mapping { + GString *label; + + /* Array of `struct bt_field_type_enumeration_mapping_range` */ + GArray *ranges; +}; + +struct bt_field_type_enumeration { + struct bt_field_type_integer common; + + /* Array of `struct bt_field_type_enumeration_mapping *` */ + GArray *mappings; + + /* + * This is an array of `const char *` which acts as a temporary + * (potentially growing) buffer for + * bt_field_type_unsigned_enumeration_get_mapping_labels_by_value() + * and + * bt_field_type_signed_enumeration_get_mapping_labels_by_value(). + * + * The actual strings are owned by the mappings above. + */ + GPtrArray *label_buf; +}; + +struct bt_field_type_real { + struct bt_field_type common; + bool is_single_precision; +}; + +struct bt_field_type_string { + struct bt_field_type common; +}; + +/* A named field type is a (name, field type) pair */ +struct bt_named_field_type { + GString *name; + + /* Owned by this */ + struct bt_field_type *ft; +}; + +/* + * This is the base field type for a container of named field types. + * Structure and variant field types inherit this. + */ +struct bt_field_type_named_field_types_container { + struct bt_field_type common; + + /* + * Key: `const char *`, not owned by this (owned by named field + * type objects contained in `named_fts` below). + */ + GHashTable *name_to_index; + + /* Array of `struct bt_named_field_type` */ + GArray *named_fts; +}; + +struct bt_field_type_structure { + struct bt_field_type_named_field_types_container common; +}; + +struct bt_field_type_array { + struct bt_field_type common; + + /* Owned by this */ + struct bt_field_type *element_ft; +}; + +struct bt_field_type_static_array { + struct bt_field_type_array common; + uint64_t length; +}; + +struct bt_field_type_dynamic_array { + struct bt_field_type_array common; + + /* Weak: never dereferenced, only use to find it elsewhere */ + struct bt_field_type *length_ft; + + /* Owned by this */ + struct bt_field_path *length_field_path; +}; + +struct bt_field_type_variant { + struct bt_field_type_named_field_types_container common; + + /* Weak: never dereferenced, only use to find it elsewhere */ + struct bt_field_type *selector_ft; + + /* Owned by this */ + struct bt_field_path *selector_field_path; +}; + +static inline +bool bt_field_type_has_known_id(struct bt_field_type *ft) +{ + return ft->id >= BT_FIELD_TYPE_ID_UNSIGNED_INTEGER && + ft->id <= BT_FIELD_TYPE_ID_VARIANT; +} + +BT_HIDDEN +void _bt_field_type_freeze(struct bt_field_type *field_type); + +#ifdef BT_DEV_MODE +# define bt_field_type_freeze _bt_field_type_freeze +#else +# define bt_field_type_freeze(_ft) +#endif + +/* + * This function recursively marks `field_type` and its children as + * being part of a trace. This is used to validate that all field types + * are used at a single location within trace objects even if they are + * shared objects for other purposes. + */ +BT_HIDDEN +void _bt_field_type_make_part_of_trace(struct bt_field_type *field_type); + +#ifdef BT_DEV_MODE +# define bt_field_type_make_part_of_trace _bt_field_type_make_part_of_trace +#else +# define bt_field_type_make_part_of_trace(_ft) ((void) _ft) +#endif + +#endif /* BABELTRACE_TRACE_IR_FIELD_TYPES_INTERNAL_H */ diff --git a/include/babeltrace/trace-ir/field-types.h b/include/babeltrace/trace-ir/field-types.h new file mode 100644 index 00000000..58ce8a63 --- /dev/null +++ b/include/babeltrace/trace-ir/field-types.h @@ -0,0 +1,222 @@ +#ifndef BABELTRACE_TRACE_IR_FIELD_TYPES_H +#define BABELTRACE_TRACE_IR_FIELD_TYPES_H + +/* + * BabelTrace - Trace IR: Event field types + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +/* For bt_get() */ +#include + +/* For bt_bool */ +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct bt_field_type; +struct bt_field_path; +struct bt_field_type_signed_enumeration_mapping_ranges; +struct bt_field_type_unsigned_enumeration_mapping_ranges; + +typedef const char * const *bt_field_type_enumeration_mapping_label_array; + +enum bt_field_type_id { + BT_FIELD_TYPE_ID_UNSIGNED_INTEGER, + BT_FIELD_TYPE_ID_SIGNED_INTEGER, + BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION, + BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, + BT_FIELD_TYPE_ID_REAL, + BT_FIELD_TYPE_ID_STRING, + BT_FIELD_TYPE_ID_STRUCTURE, + BT_FIELD_TYPE_ID_STATIC_ARRAY, + BT_FIELD_TYPE_ID_DYNAMIC_ARRAY, + BT_FIELD_TYPE_ID_VARIANT, +}; + +enum bt_field_type_integer_preferred_display_base { + BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_BINARY, + BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL, + BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL, + BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL, +}; + +extern enum bt_field_type_id bt_field_type_get_type_id( + struct bt_field_type *field_type); + +extern struct bt_field_type *bt_field_type_unsigned_integer_create(void); + +extern struct bt_field_type *bt_field_type_signed_integer_create(void); + +extern uint64_t bt_field_type_integer_get_field_value_range( + struct bt_field_type *field_type); + +extern int bt_field_type_integer_set_field_value_range( + struct bt_field_type *field_type, uint64_t size); + +extern enum bt_field_type_integer_preferred_display_base +bt_field_type_integer_get_preferred_display_base( + struct bt_field_type *field_type); + +extern int bt_field_type_integer_set_preferred_display_base( + struct bt_field_type *field_type, + enum bt_field_type_integer_preferred_display_base base); + +extern struct bt_field_type *bt_field_type_real_create(void); + +extern bt_bool bt_field_type_real_is_single_precision( + struct bt_field_type *field_type); + +extern int bt_field_type_real_set_is_single_precision( + struct bt_field_type *field_type, + bt_bool is_single_precision); + +extern struct bt_field_type *bt_field_type_unsigned_enumeration_create(void); + +extern struct bt_field_type *bt_field_type_signed_enumeration_create(void); + +extern uint64_t bt_field_type_enumeration_get_mapping_count( + struct bt_field_type *field_type); + +extern void bt_field_type_unsigned_enumeration_borrow_mapping_by_index( + struct bt_field_type *field_type, uint64_t index, + const char **label, + struct bt_field_type_unsigned_enumeration_mapping_ranges **ranges); + +extern void bt_field_type_signed_enumeration_borrow_mapping_by_index( + struct bt_field_type *field_type, uint64_t index, + const char **label, + struct bt_field_type_signed_enumeration_mapping_ranges **ranges); + +extern uint64_t bt_field_type_unsigned_enumeration_mapping_ranges_get_range_count( + struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges); + +extern uint64_t bt_field_type_signed_enumeration_mapping_ranges_get_range_count( + struct bt_field_type_signed_enumeration_mapping_ranges *ranges); + +extern void bt_field_type_unsigned_enumeration_mapping_ranges_get_range_by_index( + struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges, + uint64_t index, uint64_t *lower, uint64_t *upper); + +extern void bt_field_type_signed_enumeration_mapping_ranges_get_range_by_index( + struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges, + uint64_t index, int64_t *lower, int64_t *upper); + +extern int bt_field_type_unsigned_enumeration_get_mapping_labels_by_value( + struct bt_field_type *field_type, uint64_t value, + bt_field_type_enumeration_mapping_label_array *label_array, + uint64_t *count); + +extern int bt_field_type_signed_enumeration_get_mapping_labels_by_value( + struct bt_field_type *field_type, int64_t value, + bt_field_type_enumeration_mapping_label_array *label_array, + uint64_t *count); + +extern int bt_field_type_unsigned_enumeration_map_range( + struct bt_field_type *field_type, const char *label, + uint64_t range_lower, uint64_t range_upper); + +extern int bt_field_type_signed_enumeration_map_range( + struct bt_field_type *field_type, const char *label, + int64_t range_lower, int64_t range_upper); + +extern struct bt_field_type *bt_field_type_string_create(void); + +extern struct bt_field_type *bt_field_type_structure_create(void); + +extern uint64_t bt_field_type_structure_get_member_count( + struct bt_field_type *field_type); + +extern void bt_field_type_structure_borrow_member_by_index( + struct bt_field_type *struct_field_type, uint64_t index, + const char **name, struct bt_field_type **field_type); + +extern +struct bt_field_type *bt_field_type_structure_borrow_member_field_type_by_name( + struct bt_field_type *field_type, const char *name); + +extern int bt_field_type_structure_append_member( + struct bt_field_type *struct_field_type, const char *name, + struct bt_field_type *field_type); + +extern struct bt_field_type *bt_field_type_static_array_create( + struct bt_field_type *elem_field_type, + uint64_t length); + +extern struct bt_field_type *bt_field_type_dynamic_array_create( + struct bt_field_type *elem_field_type); + +extern struct bt_field_type *bt_field_type_array_borrow_element_field_type( + struct bt_field_type *field_type); + +extern uint64_t bt_field_type_static_array_get_length( + struct bt_field_type *field_type); + +extern struct bt_field_path * +bt_field_type_dynamic_array_borrow_length_field_path( + struct bt_field_type *field_type); + +extern int bt_field_type_dynamic_array_set_length_field_type( + struct bt_field_type *field_type, + struct bt_field_type *length_field_type); + +extern struct bt_field_type *bt_field_type_variant_create(void); + +extern struct bt_field_path * +bt_field_type_variant_borrow_selector_field_path( + struct bt_field_type *field_type); + +extern int bt_field_type_variant_set_selector_field_type( + struct bt_field_type *field_type, + struct bt_field_type *selector_field_type); + +extern uint64_t bt_field_type_variant_get_option_count( + struct bt_field_type *field_type); + +extern void bt_field_type_variant_borrow_option_by_index( + struct bt_field_type *variant_field_type, uint64_t index, + const char **name, struct bt_field_type **field_type); + +extern +struct bt_field_type *bt_field_type_variant_borrow_option_field_type_by_name( + struct bt_field_type *field_type, + const char *name); + +extern int bt_field_type_variant_append_option( + struct bt_field_type *var_field_type, + const char *name, struct bt_field_type *field_type); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_TRACE_IR_FIELD_TYPES_H */ diff --git a/include/babeltrace/trace-ir/field-wrapper-internal.h b/include/babeltrace/trace-ir/field-wrapper-internal.h new file mode 100644 index 00000000..e2b69134 --- /dev/null +++ b/include/babeltrace/trace-ir/field-wrapper-internal.h @@ -0,0 +1,47 @@ +#ifndef BABELTRACE_TRACE_IR_FIELD_WRAPPER_INTERNAL_H +#define BABELTRACE_TRACE_IR_FIELD_WRAPPER_INTERNAL_H + +/* + * Copyright 2018 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + +struct bt_field_wrapper { + struct bt_object base; + + /* Owned by this */ + struct bt_field *field; +}; + +BT_HIDDEN +struct bt_field_wrapper *bt_field_wrapper_new(void *data); + +BT_HIDDEN +void bt_field_wrapper_destroy(struct bt_field_wrapper *field); + +BT_HIDDEN +struct bt_field_wrapper *bt_field_wrapper_create( + struct bt_object_pool *pool, struct bt_field_type *ft); + +#endif /* BABELTRACE_TRACE_IR_FIELD_WRAPPER_INTERNAL_H */ diff --git a/include/babeltrace/trace-ir/fields-internal.h b/include/babeltrace/trace-ir/fields-internal.h new file mode 100644 index 00000000..c8a1dcf9 --- /dev/null +++ b/include/babeltrace/trace-ir/fields-internal.h @@ -0,0 +1,206 @@ +#ifndef BABELTRACE_TRACE_IR_FIELDS_INTERNAL_H +#define BABELTRACE_TRACE_IR_FIELDS_INTERNAL_H + +/* + * Babeltrace - Trace IR: Event Fields internal + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(_field, _type_id, _name) \ + BT_ASSERT_PRE(((struct bt_field *) (_field))->type->id == (_type_id), \ + _name " has the wrong type ID: expected-type-id=%s, " \ + "%![field-]+f", \ + bt_common_field_type_id_string(_type_id), (_field)) + +#define BT_ASSERT_PRE_FIELD_IS_UNSIGNED_INT(_field, _name) \ + BT_ASSERT_PRE( \ + ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_UNSIGNED_INTEGER || \ + ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION, \ + _name " is not an unsigned integer field: %![field-]+f", \ + (_field)) + +#define BT_ASSERT_PRE_FIELD_IS_SIGNED_INT(_field, _name) \ + BT_ASSERT_PRE( \ + ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_SIGNED_INTEGER || \ + ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, \ + _name " is not a signed integer field: %![field-]+f", \ + (_field)) + +#define BT_ASSERT_PRE_FIELD_IS_ARRAY(_field, _name) \ + BT_ASSERT_PRE( \ + ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_STATIC_ARRAY || \ + ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_DYNAMIC_ARRAY, \ + _name " is not an array field: %![field-]+f", (_field)) + +#define BT_ASSERT_PRE_FIELD_IS_SET(_field, _name) \ + BT_ASSERT_PRE(bt_field_is_set(_field), \ + _name " is not set: %!+f", (_field)) + +#define BT_ASSERT_PRE_FIELD_HOT(_field, _name) \ + BT_ASSERT_PRE_HOT((struct bt_field *) (_field), (_name), \ + ": %!+f", (_field)) + +struct bt_field; + +typedef struct bt_field *(* bt_field_create_func)(struct bt_field_type *); +typedef void (*bt_field_method_set_is_frozen)(struct bt_field *, bool); +typedef bool (*bt_field_method_is_set)(struct bt_field *); +typedef void (*bt_field_method_reset)(struct bt_field *); + +struct bt_field_methods { + bt_field_method_set_is_frozen set_is_frozen; + bt_field_method_is_set is_set; + bt_field_method_reset reset; +}; + +struct bt_field { + struct bt_object base; + + /* Owned by this */ + struct bt_field_type *type; + + /* Virtual table for slow path (dev mode) operations */ + struct bt_field_methods *methods; + + bool is_set; + bool frozen; +}; + +struct bt_field_integer { + struct bt_field common; + + union { + uint64_t u; + int64_t i; + } value; +}; + +struct bt_field_real { + struct bt_field common; + double value; +}; + +struct bt_field_structure { + struct bt_field common; + + /* Array of `struct bt_field *`, owned by this */ + GPtrArray *fields; +}; + +struct bt_field_variant { + struct bt_field common; + + /* Weak: belongs to `fields` below */ + struct bt_field *selected_field; + + /* Index of currently selected field */ + uint64_t selected_index; + + /* Array of `struct bt_field *`, owned by this */ + GPtrArray *fields; +}; + +struct bt_field_array { + struct bt_field common; + + /* Array of `struct bt_field *`, owned by this */ + GPtrArray *fields; + + /* Current effective length */ + uint64_t length; +}; + +struct bt_field_string { + struct bt_field common; + GArray *buf; + uint64_t length; +}; + +#ifdef BT_DEV_MODE +# define bt_field_set_is_frozen _bt_field_set_is_frozen +# define bt_field_is_set _bt_field_is_set +# define bt_field_reset _bt_field_reset +# define bt_field_set_single _bt_field_set_single +#else +# define bt_field_set_is_frozen(_field, _is_frozen) +# define bt_field_is_set(_field) (BT_FALSE) +# define bt_field_reset(_field) +# define bt_field_set_single(_field, _val) +#endif + +BT_HIDDEN +void _bt_field_set_is_frozen(struct bt_field *field, bool is_frozen); + +static inline +void _bt_field_reset(struct bt_field *field) +{ + BT_ASSERT(field); + BT_ASSERT(field->methods->reset); + field->methods->reset(field); +} + +static inline +void _bt_field_set_single(struct bt_field *field, bool value) +{ + BT_ASSERT(field); + field->is_set = value; +} + +static inline +bt_bool _bt_field_is_set(struct bt_field *field) +{ + bt_bool is_set = BT_FALSE; + + if (!field) { + goto end; + } + + BT_ASSERT(bt_field_type_has_known_id(field->type)); + BT_ASSERT(field->methods->is_set); + is_set = field->methods->is_set(field); + +end: + return is_set; +} + +BT_HIDDEN +struct bt_field *bt_field_create(struct bt_field_type *type); + +BT_HIDDEN +void bt_field_destroy(struct bt_field *field); + +#endif /* BABELTRACE_TRACE_IR_FIELDS_INTERNAL_H */ diff --git a/include/babeltrace/trace-ir/fields.h b/include/babeltrace/trace-ir/fields.h new file mode 100644 index 00000000..99a6aa5a --- /dev/null +++ b/include/babeltrace/trace-ir/fields.h @@ -0,0 +1,117 @@ +#ifndef BABELTRACE_TRACE_IR_FIELDS_H +#define BABELTRACE_TRACE_IR_FIELDS_H + +/* + * Babeltrace - Trace IR: Event Fields + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +#include + +/* For bt_bool */ +#include + +/* For enum bt_field_type_id */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct bt_field; +struct bt_field_type; +struct bt_field_type_enumeration_mapping_iterator; + +extern struct bt_field_type *bt_field_borrow_type(struct bt_field *field); + +extern enum bt_field_type_id bt_field_get_type_id(struct bt_field *field); + +extern int64_t bt_field_signed_integer_get_value(struct bt_field *field); + +extern void bt_field_signed_integer_set_value(struct bt_field *field, + int64_t value); + +extern uint64_t bt_field_unsigned_integer_get_value(struct bt_field *field); + +extern void bt_field_unsigned_integer_set_value(struct bt_field *field, + uint64_t value); + +extern double bt_field_real_get_value(struct bt_field *field); + +extern void bt_field_real_set_value(struct bt_field *field, double value); + +extern int bt_field_unsigned_enumeration_get_mapping_labels( + struct bt_field *field, + bt_field_type_enumeration_mapping_label_array *label_array, + uint64_t *count); + +extern int bt_field_signed_enumeration_get_mapping_labels( + struct bt_field *field, + bt_field_type_enumeration_mapping_label_array *label_array, + uint64_t *count); + +extern const char *bt_field_string_get_value(struct bt_field *field); + +extern uint64_t bt_field_string_get_length(struct bt_field *field); + +extern int bt_field_string_set_value(struct bt_field *field, const char *value); + +extern int bt_field_string_append(struct bt_field *field, const char *value); + +extern int bt_field_string_append_with_length(struct bt_field *field, + const char *value, uint64_t length); + +extern int bt_field_string_clear(struct bt_field *field); + +extern struct bt_field *bt_field_structure_borrow_member_field_by_index( + struct bt_field *field, uint64_t index); + +extern struct bt_field *bt_field_structure_borrow_member_field_by_name( + struct bt_field *field, const char *name); + +extern uint64_t bt_field_array_get_length(struct bt_field *field); + +extern struct bt_field *bt_field_array_borrow_element_field_by_index( + struct bt_field *field, uint64_t index); + +extern int bt_field_dynamic_array_set_length(struct bt_field *field, + uint64_t length); + +extern int bt_field_variant_select_option_field(struct bt_field *field, + uint64_t index); + +extern uint64_t bt_field_variant_get_selected_option_field_index( + struct bt_field *field); + +extern struct bt_field *bt_field_variant_borrow_selected_option_field( + struct bt_field *field); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_TRACE_IR_FIELDS_H */ diff --git a/include/babeltrace/trace-ir/packet-context-field.h b/include/babeltrace/trace-ir/packet-context-field.h new file mode 100644 index 00000000..b21f82b9 --- /dev/null +++ b/include/babeltrace/trace-ir/packet-context-field.h @@ -0,0 +1,52 @@ +#ifndef BABELTRACE_TRACE_IR_PACKET_CONTEXT_FIELD_H +#define BABELTRACE_TRACE_IR_PACKET_CONTEXT_FIELD_H + +/* + * Copyright 2018 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct bt_stream_class; +struct bt_packet_context_field; +struct bt_field; + +extern +struct bt_packet_context_field *bt_packet_context_field_create( + struct bt_stream_class *stream_class); + +extern +struct bt_field *bt_packet_context_field_borrow_field( + struct bt_packet_context_field *field); + +extern +void bt_packet_context_field_release(struct bt_packet_context_field *field); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_TRACE_IR_PACKET_CONTEXT_FIELD_H */ diff --git a/include/babeltrace/trace-ir/packet-header-field.h b/include/babeltrace/trace-ir/packet-header-field.h new file mode 100644 index 00000000..605b1b8f --- /dev/null +++ b/include/babeltrace/trace-ir/packet-header-field.h @@ -0,0 +1,52 @@ +#ifndef BABELTRACE_TRACE_IR_PACKET_HEADER_FIELD_H +#define BABELTRACE_TRACE_IR_PACKET_HEADER_FIELD_H + +/* + * Copyright 2018 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct bt_trace; +struct bt_packet_header_field; +struct bt_field; + +extern +struct bt_packet_header_field *bt_packet_header_field_create( + struct bt_trace *trace); + +extern +struct bt_field *bt_packet_header_field_borrow_field( + struct bt_packet_header_field *field); + +extern +void bt_packet_header_field_release(struct bt_packet_header_field *field); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_TRACE_IR_PACKET_HEADER_FIELD_H */ diff --git a/include/babeltrace/trace-ir/packet-internal.h b/include/babeltrace/trace-ir/packet-internal.h new file mode 100644 index 00000000..ec709a35 --- /dev/null +++ b/include/babeltrace/trace-ir/packet-internal.h @@ -0,0 +1,69 @@ +#ifndef BABELTRACE_TRACE_IR_PACKET_INTERNAL_H +#define BABELTRACE_TRACE_IR_PACKET_INTERNAL_H + +/* + * Babeltrace - Trace IR: Stream packet internal + * + * Copyright 2016 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct bt_packet { + struct bt_object base; + struct bt_field_wrapper *header_field; + struct bt_field_wrapper *context_field; + struct bt_stream *stream; + struct bt_clock_value *default_beginning_cv; + struct bt_clock_value *default_end_cv; + struct bt_property_uint discarded_event_counter_snapshot; + struct bt_property_uint packet_counter_snapshot; + bool frozen; +}; + +BT_HIDDEN +void _bt_packet_set_is_frozen(struct bt_packet *packet, bool is_frozen); + +#ifdef BT_DEV_MODE +# define bt_packet_set_is_frozen _bt_packet_set_is_frozen +#else +# define bt_packet_set_is_frozen(_packet, _is_frozen) +#endif /* BT_DEV_MODE */ + +BT_HIDDEN +struct bt_packet *bt_packet_new(struct bt_stream *stream); + +BT_HIDDEN +void bt_packet_recycle(struct bt_packet *packet); + +BT_HIDDEN +void bt_packet_destroy(struct bt_packet *packet); + +#endif /* BABELTRACE_TRACE_IR_PACKET_INTERNAL_H */ diff --git a/include/babeltrace/trace-ir/packet.h b/include/babeltrace/trace-ir/packet.h new file mode 100644 index 00000000..15730161 --- /dev/null +++ b/include/babeltrace/trace-ir/packet.h @@ -0,0 +1,103 @@ +#ifndef BABELTRACE_TRACE_IR_PACKET_H +#define BABELTRACE_TRACE_IR_PACKET_H + +/* + * BabelTrace - Trace IR: Stream packet + * + * Copyright 2016 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +#include + +/* For enum bt_property_availability */ +#include + +/* For enum bt_clock_value_status */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct bt_packet; +struct bt_packet_header_field; +struct bt_packet_context_field; +struct bt_stream; +struct bt_clock_value; + +extern struct bt_packet *bt_packet_create(struct bt_stream *stream); + +extern struct bt_stream *bt_packet_borrow_stream(struct bt_packet *packet); + +extern +struct bt_field *bt_packet_borrow_header_field(struct bt_packet *packet); + +extern +int bt_packet_move_header_field(struct bt_packet *packet, + struct bt_packet_header_field *header); + +extern +struct bt_field *bt_packet_borrow_context_field(struct bt_packet *packet); + +extern +int bt_packet_move_context_field(struct bt_packet *packet, + struct bt_packet_context_field *context); + +extern +enum bt_clock_value_status bt_packet_borrow_default_beginning_clock_value( + struct bt_packet *packet, struct bt_clock_value **clock_value); + +extern +int bt_packet_set_default_beginning_clock_value(struct bt_packet *packet, + uint64_t value_cycles); + +extern +enum bt_clock_value_status bt_packet_borrow_default_end_clock_valeu( + struct bt_packet *packet, struct bt_clock_value **clock_value); + +extern +int bt_packet_set_default_end_clock_value(struct bt_packet *packet, + uint64_t value_cycles); + +extern +enum bt_property_availability bt_packet_get_discarded_event_counter_snapshot( + struct bt_packet *packet, uint64_t *value); + +extern +int bt_packet_set_discarded_event_counter_snapshot(struct bt_packet *packet, + uint64_t value); + +extern +enum bt_property_availability bt_packet_get_packet_counter_snapshot( + struct bt_packet *packet, uint64_t *value); + +extern +int bt_packet_set_packet_counter_snapshot(struct bt_packet *packet, + uint64_t value); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_TRACE_IR_PACKET_H */ diff --git a/include/babeltrace/trace-ir/resolve-field-path-internal.h b/include/babeltrace/trace-ir/resolve-field-path-internal.h new file mode 100644 index 00000000..dafe50d0 --- /dev/null +++ b/include/babeltrace/trace-ir/resolve-field-path-internal.h @@ -0,0 +1,49 @@ +#ifndef BABELTRACE_TRACE_IR_RESOLVE_FIELD_PATH_INTERNAL +#define BABELTRACE_TRACE_IR_RESOLVE_FIELD_PATH_INTERNAL + +/* + * BabelTrace - Trace IR: Field path + * + * Copyright 2016 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +#include +#include +#include +#include + +struct bt_resolve_field_path_context { + struct bt_field_type *packet_header; + struct bt_field_type *packet_context; + struct bt_field_type *event_header; + struct bt_field_type *event_common_context; + struct bt_field_type *event_specific_context; + struct bt_field_type *event_payload; +}; + +BT_HIDDEN +int bt_resolve_field_paths(struct bt_field_type *ft, + struct bt_resolve_field_path_context *ctx); + +#endif /* BABELTRACE_TRACE_IR_RESOLVE_FIELD_PATH_INTERNAL */ diff --git a/include/babeltrace/trace-ir/resolve-internal.h b/include/babeltrace/trace-ir/resolve-internal.h new file mode 100644 index 00000000..85c0c87b --- /dev/null +++ b/include/babeltrace/trace-ir/resolve-internal.h @@ -0,0 +1,72 @@ +#ifndef BABELTRACE_TRACE_IR_RESOLVE_INTERNAL_H +#define BABELTRACE_TRACE_IR_RESOLVE_INTERNAL_H + +/* + * Babeltrace - Trace IR: Type resolving internal + * + * Copyright 2015 Jérémie Galarneau + * Copyright 2016 Philippe Proulx + * + * Authors: Jérémie Galarneau + * Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include + +enum bt_resolve_flag { + BT_RESOLVE_FLAG_PACKET_HEADER = 0x01, + BT_RESOLVE_FLAG_PACKET_CONTEXT = 0x02, + BT_RESOLVE_FLAG_EVENT_HEADER = 0x04, + BT_RESOLVE_FLAG_STREAM_EVENT_CTX = 0x08, + BT_RESOLVE_FLAG_EVENT_CONTEXT = 0x10, + BT_RESOLVE_FLAG_EVENT_PAYLOAD = 0x20, +}; + +/* + * Resolves Trace IR field types: recursively locates the tag and length + * field types of resp. variant and sequence field types. + * + * All `*_type` parameters may be resolved, and may as well serve as + * resolving targets. + * + * Resolving is performed based on the flags in `flags`. + * + * It is expected that, amongst all the provided types, no common + * references to sequence variant field types exist. In other words, + * this function does not copy field types. + * + * All parameters are owned by the caller. + */ +BT_HIDDEN +int bt_resolve_types(struct bt_value *environment, + struct bt_field_type *packet_header_type, + struct bt_field_type *packet_context_type, + struct bt_field_type *event_header_type, + struct bt_field_type *stream_event_ctx_type, + struct bt_field_type *event_context_type, + struct bt_field_type *event_payload_type, + enum bt_resolve_flag flags); + +#endif /* BABELTRACE_TRACE_IR_RESOLVE_INTERNAL_H */ diff --git a/include/babeltrace/trace-ir/stream-class-internal.h b/include/babeltrace/trace-ir/stream-class-internal.h new file mode 100644 index 00000000..f3f8a626 --- /dev/null +++ b/include/babeltrace/trace-ir/stream-class-internal.h @@ -0,0 +1,92 @@ +#ifndef BABELTRACE_TRACE_IR_STREAM_CLASS_INTERNAL_H +#define BABELTRACE_TRACE_IR_STREAM_CLASS_INTERNAL_H + +/* + * BabelTrace - Trace IR: Stream class internal + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct bt_stream_class { + struct bt_object base; + + struct { + GString *str; + + /* NULL or `str->str` above */ + const char *value; + } name; + + uint64_t id; + bool assigns_automatic_event_class_id; + bool assigns_automatic_stream_id; + bool packets_have_discarded_event_counter_snapshot; + bool packets_have_packet_counter_snapshot; + bool packets_have_default_beginning_cv; + bool packets_have_default_end_cv; + struct bt_field_type *packet_context_ft; + struct bt_field_type *event_header_ft; + struct bt_field_type *event_common_context_ft; + struct bt_clock_class *default_clock_class; + + /* Array of `struct bt_event_class *` */ + GPtrArray *event_classes; + + /* Pool of `struct bt_field_wrapper *` */ + struct bt_object_pool event_header_field_pool; + + /* Pool of `struct bt_field_wrapper *` */ + struct bt_object_pool packet_context_field_pool; + + bool frozen; +}; + +BT_HIDDEN +void _bt_stream_class_freeze(struct bt_stream_class *stream_class); + +#ifdef BT_DEV_MODE +# define bt_stream_class_freeze _bt_stream_class_freeze +#else +# define bt_stream_class_freeze(_sc) +#endif + +static inline +struct bt_trace *bt_stream_class_borrow_trace_inline( + struct bt_stream_class *stream_class) +{ + BT_ASSERT(stream_class); + return (void *) bt_object_borrow_parent(&stream_class->base); +} + +#endif /* BABELTRACE_TRACE_IR_STREAM_CLASS_INTERNAL_H */ diff --git a/include/babeltrace/trace-ir/stream-class.h b/include/babeltrace/trace-ir/stream-class.h new file mode 100644 index 00000000..f071244e --- /dev/null +++ b/include/babeltrace/trace-ir/stream-class.h @@ -0,0 +1,147 @@ +#ifndef BABELTRACE_TRACE_IR_STREAM_CLASS_H +#define BABELTRACE_TRACE_IR_STREAM_CLASS_H + +/* + * BabelTrace - Trace IR: Stream Class + * + * Copyright 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +#include + +/* For bt_bool */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct bt_trace; +struct bt_stream_class; +struct bt_event_class; +struct bt_clock_class; +struct bt_event_header_field; +struct bt_packet_context_field; + +extern struct bt_stream_class *bt_stream_class_create(struct bt_trace *trace); + +extern struct bt_stream_class *bt_stream_class_create_with_id( + struct bt_trace *trace, uint64_t id); + +extern struct bt_trace *bt_stream_class_borrow_trace( + struct bt_stream_class *stream_class); + +extern const char *bt_stream_class_get_name( + struct bt_stream_class *stream_class); + +extern int bt_stream_class_set_name(struct bt_stream_class *stream_class, + const char *name); + +extern bt_bool bt_stream_class_assigns_automatic_event_class_id( + struct bt_stream_class *stream_class); + +extern int bt_stream_class_set_assigns_automatic_event_class_id( + struct bt_stream_class *stream_class, bt_bool value); + +extern bt_bool bt_stream_class_assigns_automatic_stream_id( + struct bt_stream_class *stream_class); + +extern int bt_stream_class_set_assigns_automatic_stream_id( + struct bt_stream_class *stream_class, bt_bool value); + +extern uint64_t bt_stream_class_get_id(struct bt_stream_class *stream_class); + +extern struct bt_field_type *bt_stream_class_borrow_packet_context_field_type( + struct bt_stream_class *stream_class); + +extern int bt_stream_class_set_packet_context_field_type( + struct bt_stream_class *stream_class, + struct bt_field_type *field_type); + +extern struct bt_field_type * +bt_stream_class_borrow_event_header_field_type( + struct bt_stream_class *stream_class); + +extern int bt_stream_class_set_event_header_field_type( + struct bt_stream_class *stream_class, + struct bt_field_type *field_type); + +extern struct bt_field_type * +bt_stream_class_borrow_event_common_context_field_type( + struct bt_stream_class *stream_class); + +extern int bt_stream_class_set_event_common_context_field_type( + struct bt_stream_class *stream_class, + struct bt_field_type *field_type); + +extern uint64_t bt_stream_class_get_event_class_count( + struct bt_stream_class *stream_class); + +extern struct bt_event_class *bt_stream_class_borrow_event_class_by_index( + struct bt_stream_class *stream_class, uint64_t index); + +extern struct bt_event_class *bt_stream_class_borrow_event_class_by_id( + struct bt_stream_class *stream_class, uint64_t id); + +extern int bt_stream_class_set_default_clock_class( + struct bt_stream_class *stream_class, + struct bt_clock_class *clock_class); + +extern struct bt_clock_class *bt_stream_class_borrow_default_clock_class( + struct bt_stream_class *stream_class); + +extern bt_bool bt_stream_class_default_clock_is_always_known( + struct bt_stream_class *stream_class); + +extern bt_bool bt_stream_class_packets_have_discarded_event_counter_snapshot( + struct bt_stream_class *stream_class); + +extern int bt_stream_class_set_packets_have_discarded_event_counter_snapshot( + struct bt_stream_class *stream_class, bt_bool value); + +extern bt_bool bt_stream_class_packets_have_packet_counter_snapshot( + struct bt_stream_class *stream_class); + +extern int bt_stream_class_set_packets_have_packet_counter_snapshot( + struct bt_stream_class *stream_class, bt_bool value); + +extern bt_bool bt_stream_class_packets_have_default_beginning_clock_value( + struct bt_stream_class *stream_class); + +extern int bt_stream_class_set_packets_have_default_beginning_clock_value( + struct bt_stream_class *stream_class, bt_bool value); + +extern bt_bool bt_stream_class_packets_have_default_end_clock_value( + struct bt_stream_class *stream_class); + +extern int bt_stream_class_set_packets_have_default_end_clock_value( + struct bt_stream_class *stream_class, bt_bool value); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_TRACE_IR_STREAM_CLASS_H */ diff --git a/include/babeltrace/trace-ir/stream-internal.h b/include/babeltrace/trace-ir/stream-internal.h new file mode 100644 index 00000000..cdb87aca --- /dev/null +++ b/include/babeltrace/trace-ir/stream-internal.h @@ -0,0 +1,70 @@ +#ifndef BABELTRACE_TRACE_IR_STREAM_INTERNAL_H +#define BABELTRACE_TRACE_IR_STREAM_INTERNAL_H + +/* + * BabelTrace - CTF Writer: Stream internal + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +struct bt_stream_class; +struct bt_stream; + +struct bt_stream { + struct bt_object base; + + /* Weak: parent is this class's trace */ + struct bt_stream_class *class; + + struct { + GString *str; + + /* NULL or `str->str` above */ + const char *value; + } name; + + uint64_t id; + + /* Pool of `struct bt_packet *` */ + struct bt_object_pool packet_pool; + + bool frozen; +}; + +BT_HIDDEN +void _bt_stream_freeze(struct bt_stream *stream); + +#ifdef BT_DEV_MODE +# define bt_stream_freeze _bt_stream_freeze +#else +# define bt_stream_freeze(_stream) +#endif + +#endif /* BABELTRACE_TRACE_IR_STREAM_INTERNAL_H */ diff --git a/include/babeltrace/trace-ir/stream.h b/include/babeltrace/trace-ir/stream.h new file mode 100644 index 00000000..839c0a31 --- /dev/null +++ b/include/babeltrace/trace-ir/stream.h @@ -0,0 +1,62 @@ +#ifndef BABELTRACE_TRACE_IR_STREAM_H +#define BABELTRACE_TRACE_IR_STREAM_H + +/* + * BabelTrace - Trace IR: Stream + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +/* For enum bt_property_availability */ +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct bt_stream; +struct bt_stream_class; + +extern struct bt_stream *bt_stream_create(struct bt_stream_class *stream_class); + +extern struct bt_stream *bt_stream_create_with_id( + struct bt_stream_class *stream_class, uint64_t id); + +extern struct bt_stream_class *bt_stream_borrow_class(struct bt_stream *stream); + +extern const char *bt_stream_get_name(struct bt_stream *stream); + +extern int bt_stream_set_name(struct bt_stream *stream, const char *name); + +extern uint64_t bt_stream_get_id(struct bt_stream *stream); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_TRACE_IR_STREAM_H */ diff --git a/include/babeltrace/trace-ir/trace-internal.h b/include/babeltrace/trace-ir/trace-internal.h new file mode 100644 index 00000000..f829d59a --- /dev/null +++ b/include/babeltrace/trace-ir/trace-internal.h @@ -0,0 +1,106 @@ +#ifndef BABELTRACE_TRACE_IR_TRACE_INTERNAL_H +#define BABELTRACE_TRACE_IR_TRACE_INTERNAL_H + +/* + * BabelTrace - Trace IR: Trace internal + * + * Copyright 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct bt_trace { + struct bt_object base; + + struct { + GString *str; + + /* NULL or `str->str` above */ + const char *value; + } name; + + struct { + uint8_t uuid[BABELTRACE_UUID_LEN]; + + /* NULL or `uuid` above */ + bt_uuid value; + } uuid; + + struct bt_value *environment; + + /* Array of `struct bt_stream_class *` */ + GPtrArray *stream_classes; + + /* Array of `struct bt_stream *` */ + GPtrArray *streams; + + /* + * Stream class (weak) to number of instantiated streams, used + * to automatically assign stream IDs per stream class. + */ + GHashTable *stream_classes_stream_count; + + struct bt_field_type *packet_header_ft; + bool assigns_automatic_stream_class_id; + + GArray *is_static_listeners; + bool is_static; + bool in_remove_listener; + + /* Pool of `struct bt_field_wrapper *` */ + struct bt_object_pool packet_header_field_pool; + + bool frozen; +}; + +BT_HIDDEN +void _bt_trace_freeze(struct bt_trace *trace); + +#ifdef BT_DEV_MODE +# define bt_trace_freeze _bt_trace_freeze +#else +# define bt_trace_freeze(_trace) +#endif + +BT_HIDDEN +void bt_trace_add_stream(struct bt_trace *trace, struct bt_stream *stream); + +BT_HIDDEN +uint64_t bt_trace_get_automatic_stream_id(struct bt_trace *trace, + struct bt_stream_class *stream_class); + +#endif /* BABELTRACE_TRACE_IR_TRACE_INTERNAL_H */ diff --git a/include/babeltrace/trace-ir/trace.h b/include/babeltrace/trace-ir/trace.h new file mode 100644 index 00000000..cb340638 --- /dev/null +++ b/include/babeltrace/trace-ir/trace.h @@ -0,0 +1,127 @@ +#ifndef BABELTRACE_TRACE_IR_TRACE_H +#define BABELTRACE_TRACE_IR_TRACE_H + +/* + * BabelTrace - Trace IR: Trace + * + * Copyright 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +/* For bt_bool, bt_uuid */ +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct bt_trace; +struct bt_stream; +struct bt_stream_class; +struct bt_field_type; +struct bt_value; +struct bt_packet_header_field; + +typedef void (* bt_trace_is_static_listener)( + struct bt_trace *trace, void *data); + +typedef void (* bt_trace_listener_removed)( + struct bt_trace *trace, void *data); + +extern struct bt_trace *bt_trace_create(void); + +extern bt_bool bt_trace_assigns_automatic_stream_class_id( + struct bt_trace *trace); + +extern int bt_trace_set_assigns_automatic_stream_class_id( + struct bt_trace *trace, bt_bool value); + +extern const char *bt_trace_get_name(struct bt_trace *trace); + +extern int bt_trace_set_name(struct bt_trace *trace, const char *name); + +extern bt_uuid bt_trace_get_uuid(struct bt_trace *trace); + +extern int bt_trace_set_uuid(struct bt_trace *trace, bt_uuid uuid); + +extern uint64_t bt_trace_get_environment_entry_count(struct bt_trace *trace); + +extern void bt_trace_borrow_environment_entry_by_index( + struct bt_trace *trace, uint64_t index, + const char **name, struct bt_value **value); + +extern struct bt_value *bt_trace_borrow_environment_entry_value_by_name( + struct bt_trace *trace, const char *name); + +extern int bt_trace_set_environment_entry_integer( + struct bt_trace *trace, const char *name, + int64_t value); + +extern int bt_trace_set_environment_entry_string( + struct bt_trace *trace, const char *name, + const char *value); + +extern struct bt_field_type *bt_trace_borrow_packet_header_field_type( + struct bt_trace *trace); + +extern int bt_trace_set_packet_header_field_type(struct bt_trace *trace, + struct bt_field_type *packet_header_type); + +extern uint64_t bt_trace_get_stream_class_count(struct bt_trace *trace); + +extern struct bt_stream_class *bt_trace_borrow_stream_class_by_index( + struct bt_trace *trace, uint64_t index); + +extern struct bt_stream_class *bt_trace_borrow_stream_class_by_id( + struct bt_trace *trace, uint64_t id); + +extern uint64_t bt_trace_get_stream_count(struct bt_trace *trace); + +extern struct bt_stream *bt_trace_borrow_stream_by_index( + struct bt_trace *trace, uint64_t index); + +extern struct bt_stream *bt_trace_borrow_stream_by_id( + struct bt_trace *trace, uint64_t id); + +extern bt_bool bt_trace_is_static(struct bt_trace *trace); + +extern int bt_trace_make_static(struct bt_trace *trace); + +extern int bt_trace_add_is_static_listener( + struct bt_trace *trace, + bt_trace_is_static_listener listener, + bt_trace_listener_removed listener_removed, void *data, + uint64_t *listener_id); + +extern int bt_trace_remove_is_static_listener( + struct bt_trace *trace, uint64_t listener_id); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_TRACE_IR_TRACE_H */ diff --git a/include/babeltrace/trace-ir/utils-internal.h b/include/babeltrace/trace-ir/utils-internal.h new file mode 100644 index 00000000..4c3f8c03 --- /dev/null +++ b/include/babeltrace/trace-ir/utils-internal.h @@ -0,0 +1,123 @@ +#ifndef BABELTRACE_TRACE_IR_UTILS_INTERNAL_H +#define BABELTRACE_TRACE_IR_UTILS_INTERNAL_H + +/* + * Babeltrace - Internal Trace IR utilities + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include + +struct search_query { + gpointer value; + int found; +}; + +static inline +uint64_t bt_util_ns_from_value(uint64_t frequency, uint64_t value_cycles) +{ + uint64_t ns; + + if (frequency == UINT64_C(1000000000)) { + ns = value_cycles; + } else { + double dblres = ((1e9 * (double) value_cycles) / (double) frequency); + + if (dblres >= (double) UINT64_MAX) { + /* Overflows uint64_t */ + ns = UINT64_C(-1); + } else { + ns = (uint64_t) dblres; + } + } + + return ns; +} + +static inline +int bt_util_ns_from_origin(struct bt_clock_class *clock_class, uint64_t value, + int64_t *ns_from_origin) +{ + int ret = 0; + uint64_t value_ns_unsigned; + int64_t value_ns_signed; + + if (clock_class->base_offset.overflows) { + ret = -1; + goto end; + } + + /* Initialize to clock class's base offset */ + *ns_from_origin = clock_class->base_offset.value_ns; + + /* Add given value in cycles */ + value_ns_unsigned = bt_util_ns_from_value(clock_class->frequency, value); + if (value_ns_unsigned >= (uint64_t) INT64_MAX) { + /* + * FIXME: `value_ns_unsigned` could be greater than + * `INT64_MAX` in fact: in this case, we need to + * subtract `INT64_MAX` from `value_ns_unsigned`, make + * sure that the difference is less than `INT64_MAX`, + * and try to add them one after the other to + * `*ns_from_origin`. + */ + ret = -1; + goto end; + } + + value_ns_signed = (int64_t) value_ns_unsigned; + BT_ASSERT(value_ns_signed >= 0); + + if (*ns_from_origin <= 0) { + goto add_value; + } + + if (value_ns_signed > INT64_MAX - *ns_from_origin) { + ret = -1; + goto end; + } + +add_value: + *ns_from_origin += value_ns_signed; + +end: + return ret; +} + +static inline +bool bt_util_value_is_in_range_signed(uint64_t size, int64_t value) +{ + int64_t min_value = UINT64_C(-1) << (size - 1); + int64_t max_value = (UINT64_C(1) << (size - 1)) - 1; + return value >= min_value && value <= max_value; +} + +static inline +bool bt_util_value_is_in_range_unsigned(unsigned int size, uint64_t value) +{ + uint64_t max_value = (size == 64) ? UINT64_MAX : + (UINT64_C(1) << size) - 1; + return value <= max_value; +} + +#endif /* BABELTRACE_TRACE_IR_UTILS_INTERNAL_H */ diff --git a/lib/Makefile.am b/lib/Makefile.am index 121279a2..04ece474 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = ctf-ir ctf-writer prio_heap plugin graph . +SUBDIRS = trace-ir ctf-writer prio_heap plugin graph . lib_LTLIBRARIES = libbabeltrace.la libbabeltrace-ctf.la @@ -16,7 +16,7 @@ libbabeltrace_la_LIBADD = \ prio_heap/libprio_heap.la \ graph/libgraph.la \ plugin/libplugin.la \ - ctf-ir/libctf-ir.la \ + trace-ir/libtrace-ir.la \ ctf-writer/libctf-writer.la \ $(top_builddir)/logging/libbabeltrace-logging.la \ $(top_builddir)/common/libbabeltrace-common.la \ @@ -36,7 +36,7 @@ libbabeltrace_ctf_la_LDFLAGS = $(LT_NO_UNDEFINED) \ libbabeltrace_ctf_la_LIBADD = \ graph/libgraph.la \ - ctf-ir/libctf-ir.la \ + trace-ir/libtrace-ir.la \ ctf-writer/libctf-writer.la \ $(top_builddir)/logging/libbabeltrace-logging.la \ $(top_builddir)/common/libbabeltrace-common.la \ diff --git a/lib/ctf-ir/Makefile.am b/lib/ctf-ir/Makefile.am deleted file mode 100644 index dda79a6c..00000000 --- a/lib/ctf-ir/Makefile.am +++ /dev/null @@ -1,23 +0,0 @@ -noinst_LTLIBRARIES = libctf-ir.la - -libctf_ir_la_SOURCES = \ - attributes.c \ - clock-class.c \ - clock-value.c \ - event.c \ - event-class.c \ - event-header-field.c \ - field-wrapper.c \ - fields.c \ - field-types.c \ - field-path.c \ - packet.c \ - packet-context-field.c \ - packet-header-field.c \ - resolve-field-path.c \ - stream.c \ - stream-class.c \ - trace.c \ - utils.c - -libctf_ir_la_LIBADD = $(UUID_LIBS) diff --git a/lib/ctf-ir/attributes.c b/lib/ctf-ir/attributes.c deleted file mode 100644 index ccd93b17..00000000 --- a/lib/ctf-ir/attributes.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * attributes.c - * - * Babeltrace CTF IR - Attributes - * - * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation - * Copyright (c) 2015 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "ATTRS" -#include - -#include -#include -#include -#include -#include -#include -#include - -#define BT_ATTR_NAME_INDEX 0 -#define BT_ATTR_VALUE_INDEX 1 - -BT_HIDDEN -struct bt_value *bt_attributes_create(void) -{ - struct bt_value *attr_obj; - - /* - * Attributes: array value object of array value objects, each one - * containing two entries: a string value object (attributes - * field name), and a value object (attributes field value). - * - * Example (JSON representation): - * - * [ - * ["hostname", "eeppdesk"], - * ["sysname", "Linux"], - * ["tracer_major", 2], - * ["tracer_minor", 5] - * ] - */ - BT_LOGD_STR("Creating attributes object."); - attr_obj = bt_value_array_create(); - if (!attr_obj) { - BT_LOGE_STR("Failed to create array value."); - } else { - BT_LOGD("Created attributes object: addr=%p", - attr_obj); - } - - return attr_obj; -} - -BT_HIDDEN -void bt_attributes_destroy(struct bt_value *attr_obj) -{ - BT_LOGD("Destroying attributes object: addr=%p", attr_obj); - bt_put(attr_obj); -} - -BT_HIDDEN -int64_t bt_attributes_get_count(struct bt_value *attr_obj) -{ - return bt_value_array_size(attr_obj); -} - -BT_HIDDEN -const char *bt_attributes_get_field_name(struct bt_value *attr_obj, - uint64_t index) -{ - int rc; - const char *ret = NULL; - struct bt_value *attr_field_obj = NULL; - struct bt_value *attr_field_name_obj = NULL; - - if (!attr_obj) { - BT_LOGW_STR("Invalid parameter: attributes object is NULL."); - goto end; - } - - if (index >= bt_value_array_size(attr_obj)) { - BT_LOGW("Invalid parameter: index is out of bounds: " - "index=%" PRIu64 ", count=%" PRId64, - index, bt_value_array_size(attr_obj)); - goto end; - } - - attr_field_obj = bt_value_array_borrow(attr_obj, index); - if (!attr_field_obj) { - BT_LOGE("Cannot get attributes object's array value's element by index: " - "value-addr=%p, index=%" PRIu64, attr_obj, index); - goto end; - } - - attr_field_name_obj = bt_value_array_borrow(attr_field_obj, - BT_ATTR_NAME_INDEX); - if (!attr_field_name_obj) { - BT_LOGE("Cannot get attribute array value's element by index: " - "value-addr=%p, index=%" PRIu64, attr_field_obj, - (uint64_t) BT_ATTR_NAME_INDEX); - goto end; - } - - rc = bt_value_string_get(attr_field_name_obj, &ret); - if (rc) { - BT_LOGE("Cannot get raw value from string value: value-addr=%p", - attr_field_name_obj); - ret = NULL; - } - -end: - return ret; -} - -BT_HIDDEN -struct bt_value *bt_attributes_borrow_field_value(struct bt_value *attr_obj, - uint64_t index) -{ - struct bt_value *value_obj = NULL; - struct bt_value *attr_field_obj = NULL; - - if (!attr_obj) { - BT_LOGW_STR("Invalid parameter: attributes object is NULL."); - goto end; - } - - if (index >= bt_value_array_size(attr_obj)) { - BT_LOGW("Invalid parameter: index is out of bounds: " - "index=%" PRIu64 ", count=%" PRId64, - index, bt_value_array_size(attr_obj)); - goto end; - } - - attr_field_obj = bt_value_array_borrow(attr_obj, index); - if (!attr_field_obj) { - BT_LOGE("Cannot get attributes object's array value's element by index: " - "value-addr=%p, index=%" PRIu64, attr_obj, index); - goto end; - } - - value_obj = bt_value_array_borrow(attr_field_obj, - BT_ATTR_VALUE_INDEX); - if (!value_obj) { - BT_LOGE("Cannot get attribute array value's element by index: " - "value-addr=%p, index=%" PRIu64, attr_field_obj, - (uint64_t) BT_ATTR_VALUE_INDEX); - } - -end: - return value_obj; -} - -static -struct bt_value *bt_attributes_borrow_field_by_name( - struct bt_value *attr_obj, const char *name) -{ - uint64_t i; - int64_t attr_size; - struct bt_value *value_obj = NULL; - struct bt_value *attr_field_name_obj = NULL; - - attr_size = bt_value_array_size(attr_obj); - if (attr_size < 0) { - BT_LOGE("Cannot get array value's size: value-addr=%p", - attr_obj); - goto error; - } - - for (i = 0; i < attr_size; ++i) { - int ret; - const char *field_name; - - value_obj = bt_value_array_borrow(attr_obj, i); - if (!value_obj) { - BT_LOGE("Cannot get attributes object's array value's element by index: " - "value-addr=%p, index=%" PRIu64, attr_obj, i); - goto error; - } - - attr_field_name_obj = bt_value_array_borrow(value_obj, - BT_ATTR_NAME_INDEX); - if (!attr_field_name_obj) { - BT_LOGE("Cannot get attribute array value's element by index: " - "value-addr=%p, index=%" PRIu64, - value_obj, (int64_t) BT_ATTR_NAME_INDEX); - goto error; - } - - ret = bt_value_string_get(attr_field_name_obj, &field_name); - if (ret) { - BT_LOGE("Cannot get raw value from string value: value-addr=%p", - attr_field_name_obj); - goto error; - } - - if (!strcmp(field_name, name)) { - break; - } - - value_obj = NULL; - } - - return value_obj; - -error: - value_obj = NULL; - return value_obj; -} - -BT_HIDDEN -int bt_attributes_set_field_value(struct bt_value *attr_obj, - const char *name, struct bt_value *value_obj) -{ - int ret = 0; - struct bt_value *attr_field_obj = NULL; - - if (!attr_obj || !name || !value_obj) { - BT_LOGW("Invalid parameter: attributes object, name, or value object is NULL: " - "attr-value-addr=%p, name-addr=%p, value-addr=%p", - attr_obj, name, value_obj); - ret = -1; - goto end; - } - - attr_field_obj = bt_attributes_borrow_field_by_name(attr_obj, name); - if (attr_field_obj) { - ret = bt_value_array_set(attr_field_obj, - BT_ATTR_VALUE_INDEX, value_obj); - attr_field_obj = NULL; - goto end; - } - - attr_field_obj = bt_value_array_create(); - if (!attr_field_obj) { - BT_LOGE_STR("Failed to create empty array value."); - ret = -1; - goto end; - } - - ret = bt_value_array_append_string(attr_field_obj, name); - ret |= bt_value_array_append(attr_field_obj, value_obj); - if (ret) { - BT_LOGE("Cannot append elements to array value: addr=%p", - attr_field_obj); - goto end; - } - - ret = bt_value_array_append(attr_obj, attr_field_obj); - if (ret) { - BT_LOGE("Cannot append element to array value: " - "array-value-addr=%p, element-value-addr=%p", - attr_obj, attr_field_obj); - } - -end: - bt_put(attr_field_obj); - return ret; -} - -BT_HIDDEN -struct bt_value *bt_attributes_borrow_field_value_by_name( - struct bt_value *attr_obj, const char *name) -{ - struct bt_value *value_obj = NULL; - struct bt_value *attr_field_obj = NULL; - - if (!attr_obj || !name) { - BT_LOGW("Invalid parameter: attributes object or name is NULL: " - "value-addr=%p, name-addr=%p", attr_obj, name); - goto end; - } - - attr_field_obj = bt_attributes_borrow_field_by_name(attr_obj, name); - if (!attr_field_obj) { - BT_LOGD("Cannot find attributes object's field by name: " - "value-addr=%p, name=\"%s\"", attr_obj, name); - goto end; - } - - value_obj = bt_value_array_borrow(attr_field_obj, - BT_ATTR_VALUE_INDEX); - if (!value_obj) { - BT_LOGE("Cannot get attribute array value's element by index: " - "value-addr=%p, index=%" PRIu64, attr_field_obj, - (uint64_t) BT_ATTR_VALUE_INDEX); - } - -end: - return value_obj; -} - -BT_HIDDEN -int bt_attributes_freeze(struct bt_value *attr_obj) -{ - uint64_t i; - int64_t count; - int ret = 0; - - if (!attr_obj) { - BT_LOGW_STR("Invalid parameter: attributes object is NULL."); - ret = -1; - goto end; - } - - BT_LOGD("Freezing attributes object: value-addr=%p", attr_obj); - count = bt_value_array_size(attr_obj); - BT_ASSERT(count >= 0); - - /* - * We do not freeze the array value object itself here, since - * internal stuff could need to modify/add attributes. Each - * attribute is frozen one by one. - */ - for (i = 0; i < count; ++i) { - struct bt_value *obj = NULL; - - obj = bt_attributes_borrow_field_value(attr_obj, i); - if (!obj) { - BT_LOGE("Cannot get attributes object's field value by index: " - "value-addr=%p, index=%" PRIu64, - attr_obj, i); - ret = -1; - goto end; - } - - bt_value_freeze(obj); - } - -end: - return ret; -} diff --git a/lib/ctf-ir/clock-class.c b/lib/ctf-ir/clock-class.c deleted file mode 100644 index e4d53419..00000000 --- a/lib/ctf-ir/clock-class.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * clock-class.c - * - * Babeltrace CTF IR - Clock class - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "CLOCK-CLASS" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BT_ASSERT_PRE_CLOCK_CLASS_HOT(_cc) \ - BT_ASSERT_PRE_HOT((_cc), "Clock class", ": %!+K", (_cc)) - -static -void destroy_clock_class(struct bt_object *obj) -{ - struct bt_clock_class *clock_class = (void *) obj; - - BT_LIB_LOGD("Destroying clock class: %!+K", clock_class); - - if (clock_class->name.str) { - g_string_free(clock_class->name.str, TRUE); - } - - if (clock_class->description.str) { - g_string_free(clock_class->description.str, TRUE); - } - - bt_object_pool_finalize(&clock_class->cv_pool); - g_free(clock_class); -} - -static -void free_clock_value(struct bt_clock_value *clock_value, - struct bt_clock_class *clock_class) -{ - bt_clock_value_destroy(clock_value); -} - -static inline -void set_base_offset(struct bt_clock_class *clock_class) -{ - uint64_t offset_cycles_ns; - - /* Initialize nanosecond timestamp to clock's offset in seconds */ - if (clock_class->offset_seconds <= (INT64_MIN / INT64_C(1000000000) - 1) || - clock_class->offset_seconds >= (INT64_MAX / INT64_C(1000000000)) - 1) { - /* - * Overflow: offset in seconds converted to nanoseconds - * is outside the int64_t range. We also subtract 1 here - * to leave "space" for the offset in cycles converted - * to nanoseconds (which is always less than 1 second by - * contract). - */ - clock_class->base_offset.overflows = true; - goto end; - } - - /* Offset (seconds) to nanoseconds */ - clock_class->base_offset.value_ns = clock_class->offset_seconds * - INT64_C(1000000000); - - /* Add offset in cycles */ - BT_ASSERT(clock_class->offset_cycles < clock_class->frequency); - offset_cycles_ns = bt_util_ns_from_value(clock_class->frequency, - clock_class->offset_cycles); - BT_ASSERT(offset_cycles_ns < 1000000000); - clock_class->base_offset.value_ns += (int64_t) offset_cycles_ns; - clock_class->base_offset.overflows = false; - -end: - return; -} - -struct bt_clock_class *bt_clock_class_create(void) -{ - int ret; - struct bt_clock_class *clock_class = NULL; - - BT_LOGD_STR("Creating default clock class object"); - - clock_class = g_new0(struct bt_clock_class, 1); - if (!clock_class) { - BT_LOGE_STR("Failed to allocate one clock class."); - goto error; - } - - bt_object_init_shared(&clock_class->base, destroy_clock_class); - clock_class->name.str = g_string_new(NULL); - if (!clock_class->name.str) { - BT_LOGE_STR("Failed to allocate a GString."); - goto error; - } - - clock_class->description.str = g_string_new(NULL); - if (!clock_class->description.str) { - BT_LOGE_STR("Failed to allocate a GString."); - goto error; - } - - clock_class->frequency = UINT64_C(1000000000); - clock_class->is_absolute = BT_TRUE; - set_base_offset(clock_class); - ret = bt_object_pool_initialize(&clock_class->cv_pool, - (bt_object_pool_new_object_func) bt_clock_value_new, - (bt_object_pool_destroy_object_func) - free_clock_value, - clock_class); - if (ret) { - BT_LOGE("Failed to initialize clock value pool: ret=%d", - ret); - goto error; - } - - BT_LIB_LOGD("Created clock class object: %!+K", clock_class); - goto end; - -error: - BT_PUT(clock_class); - -end: - return clock_class; -} - -const char *bt_clock_class_get_name( - struct bt_clock_class *clock_class) -{ - BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); - return clock_class->name.value; -} - -int bt_clock_class_set_name(struct bt_clock_class *clock_class, - const char *name) -{ - BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); - BT_ASSERT_PRE_NON_NULL(name, "Name"); - BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class); - g_string_assign(clock_class->name.str, name); - clock_class->name.value = clock_class->name.str->str; - BT_LIB_LOGV("Set clock class's name: %!+K", clock_class); - return 0; -} - -const char *bt_clock_class_get_description(struct bt_clock_class *clock_class) -{ - BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); - return clock_class->description.value; -} - -int bt_clock_class_set_description(struct bt_clock_class *clock_class, - const char *descr) -{ - BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); - BT_ASSERT_PRE_NON_NULL(descr, "Description"); - BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class); - g_string_assign(clock_class->description.str, descr); - clock_class->description.value = clock_class->description.str->str; - BT_LIB_LOGV("Set clock class's description: %!+K", - clock_class); - return 0; -} - -uint64_t bt_clock_class_get_frequency(struct bt_clock_class *clock_class) -{ - BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); - return clock_class->frequency; -} - -int bt_clock_class_set_frequency(struct bt_clock_class *clock_class, - uint64_t frequency) -{ - BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); - BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class); - BT_ASSERT_PRE(frequency != UINT64_C(-1) && frequency != 0, - "Invalid frequency: %![cc-]+K, new-freq=%" PRIu64, - clock_class, frequency); - BT_ASSERT_PRE(clock_class->offset_cycles < frequency, - "Offset (cycles) is greater than clock class's frequency: " - "%![cc-]+K, new-freq=%" PRIu64, clock_class, frequency); - clock_class->frequency = frequency; - set_base_offset(clock_class); - BT_LIB_LOGV("Set clock class's frequency: %!+K", clock_class); - return 0; -} - -uint64_t bt_clock_class_get_precision(struct bt_clock_class *clock_class) -{ - BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); - return clock_class->precision; -} - -int bt_clock_class_set_precision(struct bt_clock_class *clock_class, - uint64_t precision) -{ - BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); - BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class); - BT_ASSERT_PRE(precision != UINT64_C(-1), - "Invalid precision: %![cc-]+K, new-precision=%" PRIu64, - clock_class, precision); - clock_class->precision = precision; - BT_LIB_LOGV("Set clock class's precision: %!+K", clock_class); - return 0; -} - -void bt_clock_class_get_offset(struct bt_clock_class *clock_class, - int64_t *seconds, uint64_t *cycles) -{ - BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); - BT_ASSERT_PRE_NON_NULL(seconds, "Seconds (output)"); - BT_ASSERT_PRE_NON_NULL(cycles, "Cycles (output)"); - *seconds = clock_class->offset_seconds; - *cycles = clock_class->offset_cycles; -} - -int bt_clock_class_set_offset(struct bt_clock_class *clock_class, - int64_t seconds, uint64_t cycles) -{ - BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); - BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class); - BT_ASSERT_PRE(cycles < clock_class->frequency, - "Offset (cycles) is greater than clock class's frequency: " - "%![cc-]+K, new-offset-cycles=%" PRIu64, clock_class, cycles); - clock_class->offset_seconds = seconds; - clock_class->offset_cycles = cycles; - set_base_offset(clock_class); - BT_LIB_LOGV("Set clock class's offset: %!+K", clock_class); - return 0; -} - -bt_bool bt_clock_class_is_absolute(struct bt_clock_class *clock_class) -{ - BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); - return (bool) clock_class->is_absolute; -} - -int bt_clock_class_set_is_absolute(struct bt_clock_class *clock_class, - bt_bool is_absolute) -{ - BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); - BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class); - clock_class->is_absolute = (bool) is_absolute; - BT_LIB_LOGV("Set clock class's absolute property: %!+K", - clock_class); - return 0; -} - -bt_uuid bt_clock_class_get_uuid(struct bt_clock_class *clock_class) -{ - BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); - return clock_class->uuid.value; -} - -int bt_clock_class_set_uuid(struct bt_clock_class *clock_class, - bt_uuid uuid) -{ - BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); - BT_ASSERT_PRE_NON_NULL(uuid, "UUID"); - BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class); - memcpy(clock_class->uuid.uuid, uuid, BABELTRACE_UUID_LEN); - clock_class->uuid.value = clock_class->uuid.uuid; - BT_LIB_LOGV("Set clock class's UUID: %!+K", clock_class); - return 0; -} - -BT_HIDDEN -void _bt_clock_class_freeze(struct bt_clock_class *clock_class) -{ - BT_ASSERT(clock_class); - - if (clock_class->frozen) { - return; - } - - BT_LIB_LOGD("Freezing clock class: %!+K", clock_class); - clock_class->frozen = 1; -} - -int bt_clock_class_cycles_to_ns_from_origin(struct bt_clock_class *clock_class, - uint64_t cycles, int64_t *ns) -{ - int ret; - - BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); - BT_ASSERT_PRE_NON_NULL(ns, "Nanoseconds (output)"); - ret = bt_util_ns_from_origin(clock_class, cycles, ns); - if (ret) { - BT_LIB_LOGW("Cannot convert cycles to nanoseconds " - "from origin for given clock class: " - "value overflows the signed 64-bit integer range: " - "%![cc-]+K, cycles=%" PRIu64, - clock_class, cycles); - } - - return ret; -} diff --git a/lib/ctf-ir/clock-value.c b/lib/ctf-ir/clock-value.c deleted file mode 100644 index 51c89ddd..00000000 --- a/lib/ctf-ir/clock-value.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2017-2018 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "CLOCK-VALUE" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -BT_HIDDEN -void bt_clock_value_destroy(struct bt_clock_value *clock_value) -{ - BT_LIB_LOGD("Destroying clock value: %!+k", clock_value); - bt_put(clock_value->clock_class); - g_free(clock_value); -} - -BT_HIDDEN -struct bt_clock_value *bt_clock_value_new(struct bt_clock_class *clock_class) -{ - struct bt_clock_value *ret = NULL; - - BT_ASSERT(clock_class); - BT_LIB_LOGD("Creating clock value object: %![cc-]+K=", - clock_class); - ret = g_new0(struct bt_clock_value, 1); - if (!ret) { - BT_LOGE_STR("Failed to allocate one clock value."); - goto end; - } - - bt_object_init_unique(&ret->base); - ret->clock_class = bt_get(clock_class); - bt_clock_class_freeze(clock_class); - BT_LIB_LOGD("Created clock value object: %!+k", ret); - -end: - return ret; -} - -BT_HIDDEN -struct bt_clock_value *bt_clock_value_create(struct bt_clock_class *clock_class) -{ - struct bt_clock_value *clock_value = NULL; - - BT_ASSERT(clock_class); - clock_value = bt_object_pool_create_object(&clock_class->cv_pool); - if (!clock_value) { - BT_LIB_LOGE("Cannot allocate one clock value from clock class's clock value pool: " - "%![cc-]+K", clock_class); - goto error; - } - - if (likely(!clock_value->clock_class)) { - clock_value->clock_class = bt_get(clock_class); - } - - goto end; - -error: - if (clock_value) { - bt_clock_value_recycle(clock_value); - clock_value = NULL; - } - -end: - return clock_value; -} - -BT_HIDDEN -void bt_clock_value_recycle(struct bt_clock_value *clock_value) -{ - struct bt_clock_class *clock_class; - - BT_ASSERT(clock_value); - BT_LIB_LOGD("Recycling clock value: %!+k", clock_value); - - /* - * Those are the important ordered steps: - * - * 1. Reset the clock value object, but do NOT put its clock - * class's reference. This clock class contains the pool to - * which we're about to recycle this clock value object, so - * we must guarantee its existence thanks to this existing - * reference. - * - * 2. Move the clock class reference to our `clock_class` - * variable so that we can set the clock value's clock class - * member to NULL before recycling it. We CANNOT do this - * after we put the clock class reference because this - * bt_put() could destroy the clock class, also destroying - * its clock value pool, thus also destroying our clock value - * object (this would result in an invalid write access). - * - * 3. Recycle the clock value object. - * - * 4. Put our clock class reference. - */ - bt_clock_value_reset(clock_value); - clock_class = clock_value->clock_class; - BT_ASSERT(clock_class); - clock_value->clock_class = NULL; - bt_object_pool_recycle_object(&clock_class->cv_pool, clock_value); - bt_put(clock_class); -} - -uint64_t bt_clock_value_get_value(struct bt_clock_value *clock_value) -{ - BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value"); - BT_ASSERT_PRE(clock_value->is_set, - "Clock value is not set: %!+k", clock_value); - return clock_value->value_cycles; -} - -int bt_clock_value_get_ns_from_origin(struct bt_clock_value *clock_value, - int64_t *ret_value_ns) -{ - int ret = 0; - BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value"); - BT_ASSERT_PRE_NON_NULL(ret_value_ns, "Value (ns) (output)"); - BT_ASSERT_PRE(clock_value->is_set, - "Clock value is not set: %!+k", clock_value); - - if (clock_value->ns_from_origin_overflows) { - BT_LIB_LOGD("Clock value, once converted to nanoseconds from origin, " - "overflows the signed 64-bit integer range: " - "%![cv-]+k", clock_value); - ret = -1; - goto end; - } - - *ret_value_ns = clock_value->ns_from_origin; - -end: - return ret; -} - -struct bt_clock_class *bt_clock_value_borrow_clock_class( - struct bt_clock_value *clock_value) -{ - BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value"); - return clock_value->clock_class; -} diff --git a/lib/ctf-ir/event-class.c b/lib/ctf-ir/event-class.c deleted file mode 100644 index b8824082..00000000 --- a/lib/ctf-ir/event-class.c +++ /dev/null @@ -1,377 +0,0 @@ -/* - * event-class.c - * - * Babeltrace CTF IR - Event class - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "EVENT-CLASS" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BT_ASSERT_PRE_EVENT_CLASS_HOT(_ec) \ - BT_ASSERT_PRE_HOT((_ec), "Event class", ": %!+E", (_ec)) - -static -void destroy_event_class(struct bt_object *obj) -{ - struct bt_event_class *event_class = (void *) obj; - - BT_LIB_LOGD("Destroying event class: %!+E", event_class); - - if (event_class->name.str) { - g_string_free(event_class->name.str, TRUE); - } - - if (event_class->emf_uri.str) { - g_string_free(event_class->emf_uri.str, TRUE); - } - - BT_LOGD_STR("Putting context field type."); - bt_put(event_class->specific_context_ft); - BT_LOGD_STR("Putting payload field type."); - bt_put(event_class->payload_ft); - bt_object_pool_finalize(&event_class->event_pool); - g_free(obj); -} - -static -void free_event(struct bt_event *event, - struct bt_event_class *event_class) -{ - bt_event_destroy(event); -} - -BT_ASSERT_PRE_FUNC -static -bool event_class_id_is_unique(struct bt_stream_class *stream_class, uint64_t id) -{ - uint64_t i; - bool is_unique = true; - - for (i = 0; i < stream_class->event_classes->len; i++) { - struct bt_event_class *ec = - stream_class->event_classes->pdata[i]; - - if (ec->id == id) { - is_unique = false; - goto end; - } - } - -end: - return is_unique; -} - -static -struct bt_event_class *create_event_class_with_id( - struct bt_stream_class *stream_class, uint64_t id) -{ - int ret; - struct bt_event_class *event_class; - - BT_ASSERT(stream_class); - BT_ASSERT_PRE(event_class_id_is_unique(stream_class, id), - "Duplicate event class ID: %![sc-]+S, id=%" PRIu64, - stream_class, id); - BT_LIB_LOGD("Creating event class object: %![sc-]+S, id=%" PRIu64, - stream_class, id); - event_class = g_new0(struct bt_event_class, 1); - if (!event_class) { - BT_LOGE_STR("Failed to allocate one event class."); - goto error; - } - - bt_object_init_shared_with_parent(&event_class->base, - destroy_event_class); - event_class->id = id; - bt_property_uint_init(&event_class->log_level, - BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE, 0); - event_class->name.str = g_string_new(NULL); - if (!event_class->name.str) { - BT_LOGE_STR("Failed to allocate a GString."); - ret = -1; - goto end; - } - - event_class->emf_uri.str = g_string_new(NULL); - if (!event_class->emf_uri.str) { - BT_LOGE_STR("Failed to allocate a GString."); - ret = -1; - goto end; - } - - ret = bt_object_pool_initialize(&event_class->event_pool, - (bt_object_pool_new_object_func) bt_event_new, - (bt_object_pool_destroy_object_func) free_event, - event_class); - if (ret) { - BT_LOGE("Failed to initialize event pool: ret=%d", - ret); - goto error; - } - - bt_object_set_parent(&event_class->base, &stream_class->base); - g_ptr_array_add(stream_class->event_classes, event_class); - bt_stream_class_freeze(stream_class); - BT_LIB_LOGD("Created event class object: %!+E", event_class); - goto end; - -error: - BT_PUT(event_class); - -end: - return event_class; -} - -struct bt_event_class *bt_event_class_create( - struct bt_stream_class *stream_class) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - BT_ASSERT_PRE(stream_class->assigns_automatic_event_class_id, - "Stream class does not automatically assigns event class IDs: " - "%![sc-]+S", stream_class); - return create_event_class_with_id(stream_class, - (uint64_t) stream_class->event_classes->len); -} - -struct bt_event_class *bt_event_class_create_with_id( - struct bt_stream_class *stream_class, uint64_t id) -{ - BT_ASSERT_PRE(!stream_class->assigns_automatic_event_class_id, - "Stream class automatically assigns event class IDs: " - "%![sc-]+S", stream_class); - return create_event_class_with_id(stream_class, id); -} - -const char *bt_event_class_get_name(struct bt_event_class *event_class) -{ - BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); - return event_class->name.value; -} - -int bt_event_class_set_name(struct bt_event_class *event_class, - const char *name) -{ - BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); - BT_ASSERT_PRE_NON_NULL(name, "Name"); - BT_ASSERT_PRE_EVENT_CLASS_HOT(event_class); - g_string_assign(event_class->name.str, name); - event_class->name.value = event_class->name.str->str; - BT_LIB_LOGV("Set event class's name: %!+E", event_class); - return 0; -} - -uint64_t bt_event_class_get_id(struct bt_event_class *event_class) -{ - BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); - return event_class->id; -} - -enum bt_property_availability bt_event_class_get_log_level( - struct bt_event_class *event_class, - enum bt_event_class_log_level *log_level) -{ - BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); - BT_ASSERT_PRE_NON_NULL(log_level, "Log level (output)"); - *log_level = (enum bt_event_class_log_level) - event_class->log_level.value; - return event_class->log_level.base.avail; -} - -int bt_event_class_set_log_level(struct bt_event_class *event_class, - enum bt_event_class_log_level log_level) -{ - BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); - BT_ASSERT_PRE_EVENT_CLASS_HOT(event_class); - bt_property_uint_set(&event_class->log_level, - (uint64_t) log_level); - BT_LIB_LOGV("Set event class's log level: %!+E", event_class); - return 0; -} - -const char *bt_event_class_get_emf_uri(struct bt_event_class *event_class) -{ - BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); - return event_class->emf_uri.value; -} - -int bt_event_class_set_emf_uri(struct bt_event_class *event_class, - const char *emf_uri) -{ - BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); - BT_ASSERT_PRE_NON_NULL(emf_uri, "EMF URI"); - BT_ASSERT_PRE_EVENT_CLASS_HOT(event_class); - g_string_assign(event_class->emf_uri.str, emf_uri); - event_class->emf_uri.value = event_class->emf_uri.str->str; - BT_LIB_LOGV("Set event class's EMF URI: %!+E", event_class); - return 0; -} - -struct bt_stream_class *bt_event_class_borrow_stream_class( - struct bt_event_class *event_class) -{ - BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); - return bt_event_class_borrow_stream_class_inline(event_class); -} - -struct bt_field_type *bt_event_class_borrow_specific_context_field_type( - struct bt_event_class *event_class) -{ - BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); - return event_class->specific_context_ft; -} - -int bt_event_class_set_specific_context_field_type( - struct bt_event_class *event_class, - struct bt_field_type *field_type) -{ - int ret; - struct bt_stream_class *stream_class; - struct bt_trace *trace; - struct bt_resolve_field_path_context resolve_ctx = { - .packet_header = NULL, - .packet_context = NULL, - .event_header = NULL, - .event_common_context = NULL, - .event_specific_context = field_type, - .event_payload = NULL, - }; - - BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); - BT_ASSERT_PRE_NON_NULL(field_type, "Field type"); - BT_ASSERT_PRE_EVENT_CLASS_HOT(event_class); - BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) == - BT_FIELD_TYPE_ID_STRUCTURE, - "Specific context field type is not a structure field type: " - "%!+F", field_type); - stream_class = bt_event_class_borrow_stream_class_inline( - event_class); - trace = bt_stream_class_borrow_trace_inline(stream_class); - resolve_ctx.packet_header = trace->packet_header_ft; - resolve_ctx.packet_context = stream_class->packet_context_ft; - resolve_ctx.event_header = stream_class->event_header_ft; - resolve_ctx.event_common_context = - stream_class->event_common_context_ft; - - ret = bt_resolve_field_paths(field_type, &resolve_ctx); - if (ret) { - goto end; - } - - bt_field_type_make_part_of_trace(field_type); - bt_put(event_class->specific_context_ft); - event_class->specific_context_ft = bt_get(field_type); - bt_field_type_freeze(field_type); - BT_LIB_LOGV("Set event class's specific context field type: %!+E", - event_class); - -end: - return ret; -} - -struct bt_field_type *bt_event_class_borrow_payload_field_type( - struct bt_event_class *event_class) -{ - BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); - return event_class->payload_ft; -} - -int bt_event_class_set_payload_field_type(struct bt_event_class *event_class, - struct bt_field_type *field_type) -{ - int ret; - struct bt_stream_class *stream_class; - struct bt_trace *trace; - struct bt_resolve_field_path_context resolve_ctx = { - .packet_header = NULL, - .packet_context = NULL, - .event_header = NULL, - .event_common_context = NULL, - .event_specific_context = NULL, - .event_payload = field_type, - }; - - BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); - BT_ASSERT_PRE_NON_NULL(field_type, "Field type"); - BT_ASSERT_PRE_EVENT_CLASS_HOT(event_class); - BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) == - BT_FIELD_TYPE_ID_STRUCTURE, - "Payload field type is not a structure field type: %!+F", - field_type); - stream_class = bt_event_class_borrow_stream_class_inline( - event_class); - trace = bt_stream_class_borrow_trace_inline(stream_class); - resolve_ctx.packet_header = trace->packet_header_ft; - resolve_ctx.packet_context = stream_class->packet_context_ft; - resolve_ctx.event_header = stream_class->event_header_ft; - resolve_ctx.event_common_context = - stream_class->event_common_context_ft; - resolve_ctx.event_specific_context = event_class->specific_context_ft; - - ret = bt_resolve_field_paths(field_type, &resolve_ctx); - if (ret) { - goto end; - } - - bt_field_type_make_part_of_trace(field_type); - bt_put(event_class->payload_ft); - event_class->payload_ft = bt_get(field_type); - bt_field_type_freeze(field_type); - BT_LIB_LOGV("Set event class's payload field type: %!+E", event_class); - -end: - return ret; -} - -BT_HIDDEN -void _bt_event_class_freeze(struct bt_event_class *event_class) -{ - /* The field types are already frozen */ - BT_ASSERT(event_class); - BT_LIB_LOGD("Freezing event class: %!+E", event_class); - event_class->frozen = true; -} diff --git a/lib/ctf-ir/event-header-field.c b/lib/ctf-ir/event-header-field.c deleted file mode 100644 index dd2b2fff..00000000 --- a/lib/ctf-ir/event-header-field.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2018 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "EVENT-HEADER-FIELD" -#include - -#include -#include -#include -#include -#include -#include - -struct bt_field *bt_event_header_field_borrow_field( - struct bt_event_header_field *header_field) -{ - struct bt_field_wrapper *field_wrapper = (void *) header_field; - - BT_ASSERT_PRE_NON_NULL(field_wrapper, "Event header field"); - return (void *) field_wrapper->field; -} - -void bt_event_header_field_release(struct bt_event_header_field *header_field) -{ - struct bt_field_wrapper *field_wrapper = (void *) header_field; - - BT_ASSERT_PRE_NON_NULL(field_wrapper, "Event header field"); - - /* - * Do not recycle because the pool could be destroyed at this - * point. This function is only called when there's an error - * anyway because the goal of an event header field wrapper is - * to eventually move it to an event with bt_event_move_header() - * after creating it. - */ - bt_field_wrapper_destroy(field_wrapper); -} - -struct bt_event_header_field *bt_event_header_field_create( - struct bt_stream_class *stream_class) -{ - struct bt_field_wrapper *field_wrapper; - - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - BT_ASSERT_PRE(bt_stream_class_borrow_trace_inline(stream_class), - "Stream class is not part of a trace: %!+S", stream_class); - BT_ASSERT_PRE(stream_class->event_header_ft, - "Stream class has no event header field type: %!+S", - stream_class); - field_wrapper = bt_field_wrapper_create( - &stream_class->event_header_field_pool, - (void *) stream_class->event_header_ft); - if (!field_wrapper) { - BT_LIB_LOGE("Cannot allocate one event header field from stream class: " - "%![sc-]+S", stream_class); - goto error; - } - - BT_ASSERT(field_wrapper->field); - bt_stream_class_freeze(stream_class); - goto end; - -error: - if (field_wrapper) { - bt_field_wrapper_destroy(field_wrapper); - field_wrapper = NULL; - } - -end: - return (void *) field_wrapper; -} diff --git a/lib/ctf-ir/event.c b/lib/ctf-ir/event.c deleted file mode 100644 index 91e6ed8f..00000000 --- a/lib/ctf-ir/event.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - * event.c - * - * Babeltrace CTF IR - Event - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "EVENT" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -BT_HIDDEN -void _bt_event_set_is_frozen(struct bt_event *event, bool is_frozen) -{ - BT_ASSERT(event); - BT_LIB_LOGD("Setting event's frozen state: %!+e, is-frozen=%d", - event, is_frozen); - - if (event->header_field) { - BT_LOGD_STR("Setting event's header field's frozen state."); - bt_field_set_is_frozen( - event->header_field->field, is_frozen); - } - - if (event->common_context_field) { - BT_LOGD_STR("Setting event's common context field's frozen state."); - bt_field_set_is_frozen( - event->common_context_field, is_frozen); - } - - if (event->specific_context_field) { - BT_LOGD_STR("Setting event's specific context field's frozen state."); - bt_field_set_is_frozen(event->specific_context_field, - is_frozen); - } - - if (event->payload_field) { - BT_LOGD_STR("Setting event's payload field's frozen state."); - bt_field_set_is_frozen(event->payload_field, - is_frozen); - } - - event->frozen = is_frozen; - BT_LOGD_STR("Setting event's packet's frozen state."); - bt_packet_set_is_frozen(event->packet, is_frozen); -} - -static -void recycle_event_header_field(struct bt_field_wrapper *field_wrapper, - struct bt_stream_class *stream_class) -{ - BT_ASSERT(field_wrapper); - BT_LIB_LOGD("Recycling event header field: " - "addr=%p, %![sc-]+S, %![field-]+f", field_wrapper, - stream_class, field_wrapper->field); - bt_object_pool_recycle_object( - &stream_class->event_header_field_pool, - field_wrapper); -} - -static inline -struct bt_field_wrapper *create_event_header_field( - struct bt_stream_class *stream_class) -{ - struct bt_field_wrapper *field_wrapper = NULL; - - field_wrapper = bt_field_wrapper_create( - &stream_class->event_header_field_pool, - bt_stream_class_borrow_event_header_field_type(stream_class)); - if (!field_wrapper) { - goto error; - } - - goto end; - -error: - if (field_wrapper) { - recycle_event_header_field(field_wrapper, stream_class); - field_wrapper = NULL; - } - -end: - return field_wrapper; -} - -BT_HIDDEN -struct bt_event *bt_event_new(struct bt_event_class *event_class) -{ - struct bt_event *event = NULL; - struct bt_stream_class *stream_class; - struct bt_field_type *ft; - - BT_ASSERT(event_class); - event = g_new0(struct bt_event, 1); - if (!event) { - BT_LOGE_STR("Failed to allocate one event."); - goto error; - } - - bt_object_init_unique(&event->base); - stream_class = bt_event_class_borrow_stream_class(event_class); - BT_ASSERT(stream_class); - - if (bt_stream_class_borrow_event_header_field_type(stream_class)) { - event->header_field = create_event_header_field(stream_class); - if (!event->header_field) { - BT_LOGE_STR("Cannot create event header field."); - goto error; - } - } - - ft = bt_stream_class_borrow_event_common_context_field_type( - stream_class); - if (ft) { - event->common_context_field = bt_field_create(ft); - if (!event->common_context_field) { - /* bt_field_create() logs errors */ - goto error; - } - } - - ft = bt_event_class_borrow_specific_context_field_type(event_class); - if (ft) { - event->specific_context_field = bt_field_create(ft); - if (!event->specific_context_field) { - /* bt_field_create() logs errors */ - goto error; - } - } - - ft = bt_event_class_borrow_payload_field_type(event_class); - if (ft) { - event->payload_field = bt_field_create(ft); - if (!event->payload_field) { - /* bt_field_create() logs errors */ - goto error; - } - } - - if (stream_class->default_clock_class) { - event->default_cv = bt_clock_value_create( - stream_class->default_clock_class); - if (!event->default_cv) { - /* bt_clock_value_create() logs errors */ - goto error; - } - } - - goto end; - -error: - if (event) { - bt_event_destroy(event); - event = NULL; - } - -end: - return event; -} - -struct bt_event_class *bt_event_borrow_class(struct bt_event *event) -{ - BT_ASSERT_PRE_NON_NULL(event, "Event"); - return event->class; -} - -struct bt_stream *bt_event_borrow_stream(struct bt_event *event) -{ - BT_ASSERT_PRE_NON_NULL(event, "Event"); - return event->packet ? event->packet->stream : NULL; -} - -struct bt_field *bt_event_borrow_header_field(struct bt_event *event) -{ - BT_ASSERT_PRE_NON_NULL(event, "Event"); - return event->header_field ? event->header_field->field : NULL; -} - -struct bt_field *bt_event_borrow_common_context_field(struct bt_event *event) -{ - BT_ASSERT_PRE_NON_NULL(event, "Event"); - return event->common_context_field; -} - -struct bt_field *bt_event_borrow_specific_context_field(struct bt_event *event) -{ - BT_ASSERT_PRE_NON_NULL(event, "Event"); - return event->specific_context_field; -} - -struct bt_field *bt_event_borrow_payload_field(struct bt_event *event) -{ - BT_ASSERT_PRE_NON_NULL(event, "Event"); - return event->payload_field; -} - -static -void release_event_header_field(struct bt_field_wrapper *field_wrapper, - struct bt_event *event) -{ - if (!event->class) { - bt_field_wrapper_destroy(field_wrapper); - } else { - struct bt_stream_class *stream_class = - bt_event_class_borrow_stream_class(event->class); - - BT_ASSERT(stream_class); - recycle_event_header_field(field_wrapper, stream_class); - } -} - -BT_HIDDEN -void bt_event_destroy(struct bt_event *event) -{ - BT_ASSERT(event); - BT_LIB_LOGD("Destroying event: %!+e", event); - - if (event->header_field) { - BT_LOGD_STR("Releasing event's header field."); - release_event_header_field(event->header_field, event); - } - - if (event->common_context_field) { - BT_LOGD_STR("Destroying event's stream event context field."); - bt_field_destroy(event->common_context_field); - } - - if (event->specific_context_field) { - BT_LOGD_STR("Destroying event's context field."); - bt_field_destroy(event->specific_context_field); - } - - if (event->payload_field) { - BT_LOGD_STR("Destroying event's payload field."); - bt_field_destroy(event->payload_field); - } - - BT_LOGD_STR("Putting event's class."); - bt_put(event->class); - - if (event->default_cv) { - bt_clock_value_recycle(event->default_cv); - } - - BT_LOGD_STR("Putting event's packet."); - bt_put(event->packet); - g_free(event); -} - -int bt_event_set_default_clock_value(struct bt_event *event, - uint64_t value_cycles) -{ - struct bt_stream_class *sc; - - BT_ASSERT_PRE_NON_NULL(event, "Event"); - BT_ASSERT_PRE_EVENT_HOT(event); - sc = bt_event_class_borrow_stream_class_inline(event->class); - BT_ASSERT(sc); - BT_ASSERT_PRE(sc->default_clock_class, - "Event's stream class has no default clock class: " - "%![ev-]+e, %![sc-]+S", event, sc); - BT_ASSERT(event->default_cv); - bt_clock_value_set_value_inline(event->default_cv, value_cycles); - BT_LIB_LOGV("Set event's default clock value: %![event-]+e, " - "value=%" PRIu64, event, value_cycles); - return 0; -} - -enum bt_clock_value_status bt_event_borrow_default_clock_value( - struct bt_event *event, struct bt_clock_value **clock_value) -{ - BT_ASSERT_PRE_NON_NULL(event, "Event"); - BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value (output)"); - *clock_value = event->default_cv; - return BT_CLOCK_VALUE_STATUS_KNOWN; -} - -struct bt_packet *bt_event_borrow_packet(struct bt_event *event) -{ - BT_ASSERT_PRE_NON_NULL(event, "Event"); - return event->packet; -} - -int bt_event_move_header(struct bt_event *event, - struct bt_event_header_field *header_field) -{ - struct bt_stream_class *stream_class; - struct bt_field_wrapper *field_wrapper = (void *) header_field; - - BT_ASSERT_PRE_NON_NULL(event, "Event"); - BT_ASSERT_PRE_NON_NULL(field_wrapper, "Header field"); - BT_ASSERT_PRE_EVENT_HOT(event); - stream_class = bt_event_class_borrow_stream_class_inline(event->class); - BT_ASSERT_PRE(stream_class->event_header_ft, - "Stream class has no event header field type: %!+S", - stream_class); - - /* Recycle current header field: always exists */ - BT_ASSERT(event->header_field); - recycle_event_header_field(event->header_field, stream_class); - - /* Move new field */ - event->header_field = field_wrapper; - return 0; -} diff --git a/lib/ctf-ir/field-path.c b/lib/ctf-ir/field-path.c deleted file mode 100644 index ceb54bf5..00000000 --- a/lib/ctf-ir/field-path.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * field-path.c - * - * Babeltrace CTF IR - Field path - * - * Copyright 2013, 2014 Jérémie Galarneau - * Copyright 2016 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "FIELD-PATH" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static -void destroy_field_path(struct bt_object *obj) -{ - struct bt_field_path *field_path = (struct bt_field_path *) obj; - - BT_ASSERT(field_path); - BT_LIB_LOGD("Destroying field path: %!+P", field_path); - g_array_free(field_path->indexes, TRUE); - g_free(field_path); -} - -BT_HIDDEN -struct bt_field_path *bt_field_path_create(void) -{ - struct bt_field_path *field_path = NULL; - - BT_LOGD_STR("Creating empty field path object."); - - field_path = g_new0(struct bt_field_path, 1); - if (!field_path) { - BT_LOGE_STR("Failed to allocate one field path."); - goto error; - } - - bt_object_init_shared(&field_path->base, destroy_field_path); - field_path->indexes = g_array_new(FALSE, FALSE, sizeof(uint64_t)); - if (!field_path->indexes) { - BT_LOGE_STR("Failed to allocate a GArray."); - goto error; - } - - BT_LIB_LOGD("Created empty field path object: %!+P", field_path); - goto end; - -error: - BT_PUT(field_path); - -end: - return field_path; -} - -enum bt_scope bt_field_path_get_root_scope(struct bt_field_path *field_path) -{ - BT_ASSERT_PRE_NON_NULL(field_path, "Field path"); - return field_path->root; -} - -uint64_t bt_field_path_get_index_count(struct bt_field_path *field_path) -{ - BT_ASSERT_PRE_NON_NULL(field_path, "Field path"); - return (uint64_t) field_path->indexes->len; -} - -uint64_t bt_field_path_get_index_by_index(struct bt_field_path *field_path, - uint64_t index) -{ - BT_ASSERT_PRE_NON_NULL(field_path, "Field path"); - BT_ASSERT_PRE_VALID_INDEX(index, field_path->indexes->len); - return bt_field_path_get_index_by_index_inline(field_path, index); -} diff --git a/lib/ctf-ir/field-types.c b/lib/ctf-ir/field-types.c deleted file mode 100644 index f71cf29f..00000000 --- a/lib/ctf-ir/field-types.c +++ /dev/null @@ -1,1164 +0,0 @@ -/* - * field-types.c - * - * Babeltrace CTF IR - Event Types - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "FIELD-TYPES" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum bt_field_type_id bt_field_type_get_type_id(struct bt_field_type *ft) -{ - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - return ft->id; -} - -static -void init_field_type(struct bt_field_type *ft, enum bt_field_type_id id, - bt_object_release_func release_func) -{ - BT_ASSERT(ft); - BT_ASSERT(bt_field_type_has_known_id(ft)); - BT_ASSERT(release_func); - bt_object_init_shared(&ft->base, release_func); - ft->id = id; -} - -static -void init_integer_field_type(struct bt_field_type_integer *ft, enum bt_field_type_id id, - bt_object_release_func release_func) -{ - init_field_type((void *) ft, id, release_func); - ft->range = 64; - ft->base = BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL; -} - -static -void destroy_integer_field_type(struct bt_object *obj) -{ - BT_ASSERT(obj); - BT_LIB_LOGD("Destroying integer field type object: %!+F", obj); - g_free(obj); -} - -static inline -struct bt_field_type *create_integer_field_type(enum bt_field_type_id id) -{ - struct bt_field_type_integer *int_ft = NULL; - - BT_LOGD("Creating default integer field type object: id=%s", - bt_common_field_type_id_string(id)); - int_ft = g_new0(struct bt_field_type_integer, 1); - if (!int_ft) { - BT_LOGE_STR("Failed to allocate one integer field type."); - goto error; - } - - init_integer_field_type(int_ft, id, destroy_integer_field_type); - BT_LIB_LOGD("Created integer field type object: %!+F", int_ft); - goto end; - -error: - BT_PUT(int_ft); - -end: - return (void *) int_ft; -} - -struct bt_field_type *bt_field_type_unsigned_integer_create(void) -{ - return create_integer_field_type(BT_FIELD_TYPE_ID_UNSIGNED_INTEGER); -} - -struct bt_field_type *bt_field_type_signed_integer_create(void) -{ - return create_integer_field_type(BT_FIELD_TYPE_ID_SIGNED_INTEGER); -} - -uint64_t bt_field_type_integer_get_field_value_range( - struct bt_field_type *ft) -{ - struct bt_field_type_integer *int_ft = (void *) ft; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_IS_INT(ft, "Field type"); - return int_ft->range; -} - -BT_ASSERT_PRE_FUNC -static -bool size_is_valid_for_enumeration_field_type(struct bt_field_type *ft, - uint64_t size) -{ - // TODO - return true; -} - -int bt_field_type_integer_set_field_value_range( - struct bt_field_type *ft, uint64_t size) -{ - struct bt_field_type_integer *int_ft = (void *) ft; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_IS_INT(ft, "Field type"); - BT_ASSERT_PRE_FT_HOT(ft, "Field type"); - BT_ASSERT_PRE(size <= 64, - "Unsupported size for integer field type's field value range " - "(maximum is 64): size=%" PRIu64, size); - BT_ASSERT_PRE(int_ft->common.id == BT_FIELD_TYPE_ID_UNSIGNED_INTEGER || - int_ft->common.id == BT_FIELD_TYPE_ID_SIGNED_INTEGER || - size_is_valid_for_enumeration_field_type(ft, size), - "Invalid field value range for enumeration field type: " - "at least one of the current mapping ranges contains values " - "which are outside this range: %!+F, size=%" PRIu64, ft, size); - int_ft->range = size; - BT_LIB_LOGV("Set integer field type's field value range: %!+F", ft); - return 0; -} - -enum bt_field_type_integer_preferred_display_base -bt_field_type_integer_get_preferred_display_base(struct bt_field_type *ft) -{ - struct bt_field_type_integer *int_ft = (void *) ft; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_IS_INT(ft, "Field type"); - return int_ft->base; -} - -int bt_field_type_integer_set_preferred_display_base(struct bt_field_type *ft, - enum bt_field_type_integer_preferred_display_base base) -{ - struct bt_field_type_integer *int_ft = (void *) ft; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_IS_INT(ft, "Field type"); - BT_ASSERT_PRE_FT_HOT(ft, "Field type"); - int_ft->base = base; - BT_LIB_LOGV("Set integer field type's preferred display base: %!+F", ft); - return 0; -} - -static -void finalize_enumeration_field_type_mapping( - struct bt_field_type_enumeration_mapping *mapping) -{ - BT_ASSERT(mapping); - - if (mapping->label) { - g_string_free(mapping->label, TRUE); - } - - if (mapping->ranges) { - g_array_free(mapping->ranges, TRUE); - } -} - -static -void destroy_enumeration_field_type(struct bt_object *obj) -{ - struct bt_field_type_enumeration *ft = (void *) obj; - - BT_ASSERT(ft); - BT_LIB_LOGD("Destroying enumeration field type object: %!+F", ft); - - if (ft->mappings) { - uint64_t i; - - for (i = 0; i < ft->mappings->len; i++) { - finalize_enumeration_field_type_mapping( - BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(ft, i)); - } - - g_array_free(ft->mappings, TRUE); - } - - if (ft->label_buf) { - g_ptr_array_free(ft->label_buf, TRUE); - } - - g_free(ft); -} - -static -struct bt_field_type *create_enumeration_field_type(enum bt_field_type_id id) -{ - struct bt_field_type_enumeration *enum_ft = NULL; - - BT_LOGD("Creating default enumeration field type object: id=%s", - bt_common_field_type_id_string(id)); - enum_ft = g_new0(struct bt_field_type_enumeration, 1); - if (!enum_ft) { - BT_LOGE_STR("Failed to allocate one enumeration field type."); - goto error; - } - - init_integer_field_type((void *) enum_ft, id, - destroy_enumeration_field_type); - enum_ft->mappings = g_array_new(FALSE, TRUE, - sizeof(struct bt_field_type_enumeration_mapping)); - if (!enum_ft->mappings) { - BT_LOGE_STR("Failed to allocate a GArray."); - goto error; - } - - enum_ft->label_buf = g_ptr_array_new(); - if (!enum_ft->label_buf) { - BT_LOGE_STR("Failed to allocate a GArray."); - goto error; - } - - BT_LIB_LOGD("Created enumeration field type object: %!+F", enum_ft); - goto end; - -error: - BT_PUT(enum_ft); - -end: - return (void *) enum_ft; -} - -struct bt_field_type *bt_field_type_unsigned_enumeration_create(void) -{ - return create_enumeration_field_type( - BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION); -} - -struct bt_field_type *bt_field_type_signed_enumeration_create(void) -{ - return create_enumeration_field_type( - BT_FIELD_TYPE_ID_SIGNED_ENUMERATION); -} - -uint64_t bt_field_type_enumeration_get_mapping_count(struct bt_field_type *ft) -{ - struct bt_field_type_enumeration *enum_ft = (void *) ft; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_IS_ENUM(ft, "Field type"); - return (uint64_t) enum_ft->mappings->len; -} - -void bt_field_type_unsigned_enumeration_borrow_mapping_by_index( - struct bt_field_type *ft, uint64_t index, - const char **name, - struct bt_field_type_unsigned_enumeration_mapping_ranges **ranges) -{ - struct bt_field_type_enumeration *enum_ft = (void *) ft; - struct bt_field_type_enumeration_mapping *mapping; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_NON_NULL(name, "Name (output)"); - BT_ASSERT_PRE_NON_NULL(ranges, "Ranges (output)"); - BT_ASSERT_PRE_VALID_INDEX(index, enum_ft->mappings->len); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION, - "Field type"); - mapping = BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(ft, index); - *name = mapping->label->str; - *ranges = (void *) mapping; -} - -void bt_field_type_signed_enumeration_borrow_mapping_by_index( - struct bt_field_type *ft, uint64_t index, - const char **name, - struct bt_field_type_signed_enumeration_mapping_ranges **ranges) -{ - struct bt_field_type_enumeration *enum_ft = (void *) ft; - struct bt_field_type_enumeration_mapping *mapping; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_NON_NULL(name, "Name (output)"); - BT_ASSERT_PRE_NON_NULL(ranges, "Ranges (output)"); - BT_ASSERT_PRE_VALID_INDEX(index, enum_ft->mappings->len); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, - "Field type"); - mapping = BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(ft, index); - *name = mapping->label->str; - *ranges = (void *) mapping; -} - -static inline -uint64_t get_enumeration_field_type_mapping_range_count( - struct bt_field_type_enumeration_mapping *mapping) -{ - BT_ASSERT_PRE_NON_NULL(mapping, "Ranges"); - return (uint64_t) mapping->ranges->len; -} - -uint64_t bt_field_type_unsigned_enumeration_mapping_ranges_get_range_count( - struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges) -{ - return get_enumeration_field_type_mapping_range_count((void *) ranges); -} - -uint64_t bt_field_type_signed_enumeration_mapping_ranges_get_range_count( - struct bt_field_type_signed_enumeration_mapping_ranges *ranges) -{ - return get_enumeration_field_type_mapping_range_count((void *) ranges); -} - -static inline -void get_enumeration_field_type_mapping_range_at_index( - struct bt_field_type_enumeration_mapping *mapping, - uint64_t index, uint64_t *lower, uint64_t *upper) -{ - struct bt_field_type_enumeration_mapping_range *range; - - BT_ASSERT_PRE_NON_NULL(mapping, "Ranges"); - BT_ASSERT_PRE_NON_NULL(lower, "Range's lower (output)"); - BT_ASSERT_PRE_NON_NULL(upper, "Range's upper (output)"); - BT_ASSERT_PRE_VALID_INDEX(index, mapping->ranges->len); - range = BT_FIELD_TYPE_ENUM_MAPPING_RANGE_AT_INDEX(mapping, index); - *lower = range->lower.u; - *upper = range->upper.u; -} - -void bt_field_type_unsigned_enumeration_mapping_ranges_get_range_by_index( - struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges, - uint64_t index, uint64_t *lower, uint64_t *upper) -{ - get_enumeration_field_type_mapping_range_at_index((void *) ranges, - index, lower, upper); -} - -void bt_field_type_signed_enumeration_mapping_ranges_get_range_by_index( - struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges, - uint64_t index, int64_t *lower, int64_t *upper) -{ - get_enumeration_field_type_mapping_range_at_index((void *) ranges, - index, (uint64_t *) lower, (uint64_t *) upper); -} - - - -int bt_field_type_unsigned_enumeration_get_mapping_labels_by_value( - struct bt_field_type *ft, uint64_t value, - bt_field_type_enumeration_mapping_label_array *label_array, - uint64_t *count) -{ - struct bt_field_type_enumeration *enum_ft = (void *) ft; - uint64_t i; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_NON_NULL(label_array, "Label array (output)"); - BT_ASSERT_PRE_NON_NULL(count, "Count (output)"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION, - "Field type"); - g_ptr_array_set_size(enum_ft->label_buf, 0); - - for (i = 0; i < enum_ft->mappings->len; i++) { - uint64_t j; - struct bt_field_type_enumeration_mapping *mapping = - BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(enum_ft, i); - - for (j = 0; j < mapping->ranges->len; j++) { - struct bt_field_type_enumeration_mapping_range *range = - BT_FIELD_TYPE_ENUM_MAPPING_RANGE_AT_INDEX( - mapping, j); - - if (value >= range->lower.u && - value <= range->upper.u) { - g_ptr_array_add(enum_ft->label_buf, - mapping->label->str); - break; - } - } - } - - *label_array = (void *) enum_ft->label_buf->pdata; - *count = (uint64_t) enum_ft->label_buf->len; - return 0; -} - -int bt_field_type_signed_enumeration_get_mapping_labels_by_value( - struct bt_field_type *ft, int64_t value, - bt_field_type_enumeration_mapping_label_array *label_array, - uint64_t *count) -{ - struct bt_field_type_enumeration *enum_ft = (void *) ft; - uint64_t i; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_NON_NULL(label_array, "Label array (output)"); - BT_ASSERT_PRE_NON_NULL(count, "Count (output)"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, - "Field type"); - g_ptr_array_set_size(enum_ft->label_buf, 0); - - for (i = 0; i < enum_ft->mappings->len; i++) { - uint64_t j; - struct bt_field_type_enumeration_mapping *mapping = - BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(enum_ft, i); - - for (j = 0; j < mapping->ranges->len; j++) { - struct bt_field_type_enumeration_mapping_range *range = - BT_FIELD_TYPE_ENUM_MAPPING_RANGE_AT_INDEX( - mapping, j); - - if (value >= range->lower.i && - value <= range->upper.i) { - g_ptr_array_add(enum_ft->label_buf, - mapping->label->str); - break; - } - } - } - - *label_array = (void *) enum_ft->label_buf->pdata; - *count = (uint64_t) enum_ft->label_buf->len; - return 0; -} - -static inline -int add_mapping_to_enumeration_field_type(struct bt_field_type *ft, - const char *label, uint64_t lower, uint64_t upper) -{ - int ret = 0; - uint64_t i; - struct bt_field_type_enumeration *enum_ft = (void *) ft; - struct bt_field_type_enumeration_mapping *mapping = NULL; - struct bt_field_type_enumeration_mapping_range *range; - - BT_ASSERT(ft); - BT_ASSERT_PRE_NON_NULL(label, "Label"); - - /* Find existing mapping identified by this label */ - for (i = 0; i < enum_ft->mappings->len; i++) { - struct bt_field_type_enumeration_mapping *mapping_candidate = - BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(enum_ft, i); - - if (strcmp(mapping_candidate->label->str, label) == 0) { - mapping = mapping_candidate; - break; - } - } - - if (!mapping) { - /* Create new mapping for this label */ - g_array_set_size(enum_ft->mappings, enum_ft->mappings->len + 1); - mapping = BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(enum_ft, - enum_ft->mappings->len - 1); - mapping->ranges = g_array_new(FALSE, TRUE, - sizeof(struct bt_field_type_enumeration_mapping_range)); - if (!mapping->ranges) { - finalize_enumeration_field_type_mapping(mapping); - g_array_set_size(enum_ft->mappings, - enum_ft->mappings->len - 1); - ret = -1; - goto end; - } - - mapping->label = g_string_new(label); - if (!mapping->label) { - finalize_enumeration_field_type_mapping(mapping); - g_array_set_size(enum_ft->mappings, - enum_ft->mappings->len - 1); - ret = -1; - goto end; - } - } - - /* Add range */ - BT_ASSERT(mapping); - g_array_set_size(mapping->ranges, mapping->ranges->len + 1); - range = BT_FIELD_TYPE_ENUM_MAPPING_RANGE_AT_INDEX(mapping, - mapping->ranges->len - 1); - range->lower.u = lower; - range->upper.u = upper; - BT_LIB_LOGV("Added mapping to enumeration field type: " - "%![ft-]+F, label=\"%s\", lower-unsigned=%" PRIu64 ", " - "upper-unsigned=%" PRIu64, ft, label, lower, upper); - -end: - return ret; -} - -int bt_field_type_unsigned_enumeration_map_range( - struct bt_field_type *ft, const char *label, - uint64_t range_lower, uint64_t range_upper) -{ - struct bt_field_type_enumeration *enum_ft = (void *) ft; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION, - "Field type"); - BT_ASSERT_PRE(range_lower <= range_upper, - "Range's upper bound is less than lower bound: " - "upper=%" PRIu64 ", lower=%" PRIu64, - range_lower, range_upper); - BT_ASSERT_PRE(bt_util_value_is_in_range_unsigned(enum_ft->common.range, - range_lower), - "Range's lower bound is outside the enumeration field type's value range: " - "%![ft-]+F, lower=%" PRIu64, ft, range_lower); - BT_ASSERT_PRE(bt_util_value_is_in_range_unsigned(enum_ft->common.range, - range_upper), - "Range's upper bound is outside the enumeration field type's value range: " - "%![ft-]+F, upper=%" PRIu64, ft, range_upper); - return add_mapping_to_enumeration_field_type(ft, label, range_lower, - range_upper); -} - -int bt_field_type_signed_enumeration_map_range( - struct bt_field_type *ft, const char *label, - int64_t range_lower, int64_t range_upper) -{ - struct bt_field_type_enumeration *enum_ft = (void *) ft; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, - "Field type"); - BT_ASSERT_PRE(range_lower <= range_upper, - "Range's upper bound is less than lower bound: " - "upper=%" PRId64 ", lower=%" PRId64, - range_lower, range_upper); - BT_ASSERT_PRE(bt_util_value_is_in_range_signed(enum_ft->common.range, - range_lower), - "Range's lower bound is outside the enumeration field type's value range: " - "%![ft-]+F, lower=%" PRId64, ft, range_lower); - BT_ASSERT_PRE(bt_util_value_is_in_range_signed(enum_ft->common.range, - range_upper), - "Range's upper bound is outside the enumeration field type's value range: " - "%![ft-]+F, upper=%" PRId64, ft, range_upper); - return add_mapping_to_enumeration_field_type(ft, label, range_lower, - range_upper); -} - -static -void destroy_real_field_type(struct bt_object *obj) -{ - BT_ASSERT(obj); - BT_LIB_LOGD("Destroying real field type object: %!+F", obj); - g_free(obj); -} - -struct bt_field_type *bt_field_type_real_create(void) -{ - struct bt_field_type_real *real_ft = NULL; - - BT_LOGD_STR("Creating default real field type object."); - real_ft = g_new0(struct bt_field_type_real, 1); - if (!real_ft) { - BT_LOGE_STR("Failed to allocate one real field type."); - goto error; - } - - init_field_type((void *) real_ft, BT_FIELD_TYPE_ID_REAL, - destroy_real_field_type); - BT_LIB_LOGD("Created real field type object: %!+F", real_ft); - goto end; - -error: - BT_PUT(real_ft); - -end: - return (void *) real_ft; -} - -bt_bool bt_field_type_real_is_single_precision(struct bt_field_type *ft) -{ - struct bt_field_type_real *real_ft = (void *) ft; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_REAL, "Field type"); - return real_ft->is_single_precision; -} - -int bt_field_type_real_set_is_single_precision(struct bt_field_type *ft, - bt_bool is_single_precision) -{ - struct bt_field_type_real *real_ft = (void *) ft; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_REAL, "Field type"); - BT_ASSERT_PRE_FT_HOT(ft, "Field type"); - real_ft->is_single_precision = (bool) is_single_precision; - BT_LIB_LOGV("Set real field type's \"is single precision\" property: " - "%!+F", ft); - return 0; -} - -static -int init_named_field_types_container( - struct bt_field_type_named_field_types_container *ft, - enum bt_field_type_id id, bt_object_release_func release_func) -{ - int ret = 0; - - init_field_type((void *) ft, id, release_func); - ft->named_fts = g_array_new(FALSE, TRUE, - sizeof(struct bt_named_field_type)); - if (!ft->named_fts) { - BT_LOGE_STR("Failed to allocate a GArray."); - ret = -1; - goto end; - } - - ft->name_to_index = g_hash_table_new(g_str_hash, g_str_equal); - if (!ft->name_to_index) { - BT_LOGE_STR("Failed to allocate a GHashTable."); - ret = -1; - goto end; - } - -end: - return ret; -} - -static -void finalize_named_field_type(struct bt_named_field_type *named_ft) -{ - BT_ASSERT(named_ft); - BT_LIB_LOGD("Finalizing named field type: " - "addr=%p, name=\"%s\", %![ft-]+F", - named_ft, named_ft->name ? named_ft->name->str : NULL, - named_ft->ft); - - if (named_ft->name) { - g_string_free(named_ft->name, TRUE); - } - - BT_LOGD_STR("Putting named field type's field type."); - bt_put(named_ft->ft); -} - -static -void finalize_named_field_types_container( - struct bt_field_type_named_field_types_container *ft) -{ - uint64_t i; - - BT_ASSERT(ft); - - if (ft->named_fts) { - for (i = 0; i < ft->named_fts->len; i++) { - finalize_named_field_type( - &g_array_index(ft->named_fts, - struct bt_named_field_type, i)); - } - - g_array_free(ft->named_fts, TRUE); - } - - if (ft->name_to_index) { - g_hash_table_destroy(ft->name_to_index); - } -} - -static -void destroy_structure_field_type(struct bt_object *obj) -{ - BT_ASSERT(obj); - BT_LIB_LOGD("Destroying string field type object: %!+F", obj); - finalize_named_field_types_container((void *) obj); - g_free(obj); -} - -struct bt_field_type *bt_field_type_structure_create(void) -{ - int ret; - struct bt_field_type_structure *struct_ft = NULL; - - BT_LOGD_STR("Creating default structure field type object."); - struct_ft = g_new0(struct bt_field_type_structure, 1); - if (!struct_ft) { - BT_LOGE_STR("Failed to allocate one structure field type."); - goto error; - } - - ret = init_named_field_types_container((void *) struct_ft, - BT_FIELD_TYPE_ID_STRUCTURE, destroy_structure_field_type); - if (ret) { - goto error; - } - - BT_LIB_LOGD("Created structure field type object: %!+F", struct_ft); - goto end; - -error: - BT_PUT(struct_ft); - -end: - return (void *) struct_ft; -} - -static -int append_named_field_type_to_container_field_type( - struct bt_field_type_named_field_types_container *container_ft, - const char *name, struct bt_field_type *ft) -{ - int ret = 0; - struct bt_named_field_type *named_ft; - GString *name_str; - - BT_ASSERT(container_ft); - BT_ASSERT_PRE_FT_HOT(container_ft, "Field type"); - BT_ASSERT_PRE_NON_NULL(name, "Name"); - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE(!bt_g_hash_table_contains(container_ft->name_to_index, - name), - "Duplicate member/option name in structure/variant field type: " - "%![container-ft-]+F, name=\"%s\"", container_ft, name); - name_str = g_string_new(name); - if (!name_str) { - BT_LOGE_STR("Failed to allocate a GString."); - ret = -1; - goto end; - } - - g_array_set_size(container_ft->named_fts, - container_ft->named_fts->len + 1); - named_ft = &g_array_index(container_ft->named_fts, - struct bt_named_field_type, container_ft->named_fts->len - 1); - named_ft->name = name_str; - named_ft->ft = bt_get(ft); - g_hash_table_insert(container_ft->name_to_index, named_ft->name->str, - GUINT_TO_POINTER(container_ft->named_fts->len - 1)); - bt_field_type_freeze(ft); - -end: - return ret; -} - -int bt_field_type_structure_append_member(struct bt_field_type *ft, - const char *name, struct bt_field_type *member_ft) -{ - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCTURE, "Field type"); - return append_named_field_type_to_container_field_type((void *) ft, - name, member_ft); -} - -uint64_t bt_field_type_structure_get_member_count(struct bt_field_type *ft) -{ - struct bt_field_type_structure *struct_ft = (void *) ft; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCTURE, "Field type"); - return (uint64_t) struct_ft->common.named_fts->len; -} - -static -void borrow_named_field_type_from_container_field_type_at_index( - struct bt_field_type_named_field_types_container *ft, - uint64_t index, const char **name, - struct bt_field_type **out_ft) -{ - struct bt_named_field_type *named_ft; - - BT_ASSERT(ft); - BT_ASSERT_PRE_NON_NULL(name, "Name"); - BT_ASSERT_PRE_NON_NULL(out_ft, "Field type (output)"); - BT_ASSERT_PRE_VALID_INDEX(index, ft->named_fts->len); - named_ft = BT_FIELD_TYPE_NAMED_FT_AT_INDEX(ft, index); - *name = named_ft->name->str; - *out_ft = named_ft->ft; -} - -void bt_field_type_structure_borrow_member_by_index( - struct bt_field_type *ft, uint64_t index, - const char **name, struct bt_field_type **out_ft) -{ - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCTURE, "Field type"); - borrow_named_field_type_from_container_field_type_at_index((void *) ft, - index, name, out_ft); -} - -static -struct bt_field_type *borrow_field_type_from_container_field_type_by_name( - struct bt_field_type_named_field_types_container *ft, - const char *name) -{ - struct bt_field_type *ret_ft = NULL; - struct bt_named_field_type *named_ft; - gpointer orig_key; - gpointer value; - - BT_ASSERT(ft); - BT_ASSERT_PRE_NON_NULL(name, "Name"); - if (!g_hash_table_lookup_extended(ft->name_to_index, name, &orig_key, - &value)) { - goto end; - } - - named_ft = BT_FIELD_TYPE_NAMED_FT_AT_INDEX(ft, - GPOINTER_TO_UINT(value)); - ret_ft = named_ft->ft; - -end: - return ret_ft; -} - -struct bt_field_type *bt_field_type_structure_borrow_member_field_type_by_name( - struct bt_field_type *ft, const char *name) -{ - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCTURE, "Field type"); - return borrow_field_type_from_container_field_type_by_name((void *) ft, - name); -} - -static -void destroy_variant_field_type(struct bt_object *obj) -{ - struct bt_field_type_variant *ft = (void *) obj; - - BT_ASSERT(ft); - BT_LIB_LOGD("Destroying variant field type object: %!+F", ft); - finalize_named_field_types_container((void *) ft); - BT_LOGD_STR("Putting selector field path."); - bt_put(ft->selector_field_path); - g_free(ft); -} - -struct bt_field_type *bt_field_type_variant_create(void) -{ - int ret; - struct bt_field_type_variant *var_ft = NULL; - - BT_LOGD_STR("Creating default variant field type object."); - var_ft = g_new0(struct bt_field_type_variant, 1); - if (!var_ft) { - BT_LOGE_STR("Failed to allocate one variant field type."); - goto error; - } - - ret = init_named_field_types_container((void *) var_ft, - BT_FIELD_TYPE_ID_VARIANT, destroy_variant_field_type); - if (ret) { - goto error; - } - - BT_LIB_LOGD("Created variant field type object: %!+F", var_ft); - goto end; - -error: - BT_PUT(var_ft); - -end: - return (void *) var_ft; -} - -int bt_field_type_variant_set_selector_field_type( - struct bt_field_type *ft, struct bt_field_type *selector_ft) -{ - struct bt_field_type_variant *var_ft = (void *) ft; - - BT_ASSERT_PRE_NON_NULL(ft, "Variant field type"); - BT_ASSERT_PRE_NON_NULL(selector_ft, "Selector field type"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT, "Field type"); - BT_ASSERT_PRE_FT_IS_ENUM(selector_ft, "Selector field type"); - BT_ASSERT_PRE_FT_HOT(ft, "Variant field type"); - var_ft->selector_ft = selector_ft; - bt_field_type_freeze(selector_ft); - return 0; -} - -int bt_field_type_variant_append_option(struct bt_field_type *ft, - const char *name, struct bt_field_type *option_ft) -{ - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT, "Field type"); - return append_named_field_type_to_container_field_type((void *) ft, - name, option_ft); -} - -struct bt_field_type *bt_field_type_variant_borrow_option_field_type_by_name( - struct bt_field_type *ft, const char *name) -{ - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT, "Field type"); - return borrow_field_type_from_container_field_type_by_name((void *) ft, - name); -} - -uint64_t bt_field_type_variant_get_option_count(struct bt_field_type *ft) -{ - struct bt_field_type_variant *var_ft = (void *) ft; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT, "Field type"); - return (uint64_t) var_ft->common.named_fts->len; -} - -void bt_field_type_variant_borrow_option_by_index( - struct bt_field_type *ft, uint64_t index, - const char **name, struct bt_field_type **out_ft) -{ - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT, "Field type"); - borrow_named_field_type_from_container_field_type_at_index((void *) ft, - index, name, out_ft); -} - -struct bt_field_path *bt_field_type_variant_borrow_selector_field_path( - struct bt_field_type *ft) -{ - struct bt_field_type_variant *var_ft = (void *) ft; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT, - "Field type"); - return var_ft->selector_field_path; -} - -static -void init_array_field_type(struct bt_field_type_array *ft, - enum bt_field_type_id id, bt_object_release_func release_func, - struct bt_field_type *element_ft) -{ - BT_ASSERT(element_ft); - init_field_type((void *) ft, id, release_func); - ft->element_ft = bt_get(element_ft); - bt_field_type_freeze(element_ft); -} - -static -void finalize_array_field_type(struct bt_field_type_array *array_ft) -{ - BT_ASSERT(array_ft); - BT_LOGD_STR("Putting element field type."); - bt_put(array_ft->element_ft); -} - -static -void destroy_static_array_field_type(struct bt_object *obj) -{ - BT_ASSERT(obj); - BT_LIB_LOGD("Destroying static array field type object: %!+F", obj); - finalize_array_field_type((void *) obj); - g_free(obj); -} - -struct bt_field_type *bt_field_type_static_array_create( - struct bt_field_type *element_ft, uint64_t length) -{ - struct bt_field_type_static_array *array_ft = NULL; - - BT_ASSERT_PRE_NON_NULL(element_ft, "Element field type"); - BT_LOGD_STR("Creating default static array field type object."); - array_ft = g_new0(struct bt_field_type_static_array, 1); - if (!array_ft) { - BT_LOGE_STR("Failed to allocate one static array field type."); - goto error; - } - - init_array_field_type((void *) array_ft, BT_FIELD_TYPE_ID_STATIC_ARRAY, - destroy_static_array_field_type, element_ft); - array_ft->length = length; - BT_LIB_LOGD("Created static array field type object: %!+F", array_ft); - goto end; - -error: - BT_PUT(array_ft); - -end: - return (void *) array_ft; -} - -struct bt_field_type *bt_field_type_array_borrow_element_field_type( - struct bt_field_type *ft) -{ - struct bt_field_type_array *array_ft = (void *) ft; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_IS_ARRAY(ft, "Field type"); - return array_ft->element_ft; -} - -uint64_t bt_field_type_static_array_get_length(struct bt_field_type *ft) -{ - struct bt_field_type_static_array *array_ft = (void *) ft; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STATIC_ARRAY, - "Field type"); - return (uint64_t) array_ft->length; -} - -static -void destroy_dynamic_array_field_type(struct bt_object *obj) -{ - struct bt_field_type_dynamic_array *ft = (void *) obj; - - BT_ASSERT(ft); - BT_LIB_LOGD("Destroying dynamic array field type object: %!+F", ft); - finalize_array_field_type((void *) ft); - BT_LOGD_STR("Putting length field path."); - bt_put(ft->length_field_path); - g_free(ft); -} - -struct bt_field_type *bt_field_type_dynamic_array_create( - struct bt_field_type *element_ft) -{ - struct bt_field_type_dynamic_array *array_ft = NULL; - - BT_ASSERT_PRE_NON_NULL(element_ft, "Element field type"); - BT_LOGD_STR("Creating default dynamic array field type object."); - array_ft = g_new0(struct bt_field_type_dynamic_array, 1); - if (!array_ft) { - BT_LOGE_STR("Failed to allocate one dynamic array field type."); - goto error; - } - - init_array_field_type((void *) array_ft, BT_FIELD_TYPE_ID_DYNAMIC_ARRAY, - destroy_dynamic_array_field_type, element_ft); - BT_LIB_LOGD("Created dynamic array field type object: %!+F", array_ft); - goto end; - -error: - BT_PUT(array_ft); - -end: - return (void *) array_ft; -} - -int bt_field_type_dynamic_array_set_length_field_type(struct bt_field_type *ft, - struct bt_field_type *length_ft) -{ - struct bt_field_type_dynamic_array *array_ft = (void *) ft; - - BT_ASSERT_PRE_NON_NULL(ft, "Dynamic array field type"); - BT_ASSERT_PRE_NON_NULL(length_ft, "Length field type"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_DYNAMIC_ARRAY, - "Field type"); - BT_ASSERT_PRE_FT_IS_UNSIGNED_INT(length_ft, "Length field type"); - BT_ASSERT_PRE_FT_HOT(ft, "Dynamic array field type"); - array_ft->length_ft = length_ft; - bt_field_type_freeze(length_ft); - return 0; -} - -struct bt_field_path *bt_field_type_dynamic_array_borrow_length_field_path( - struct bt_field_type *ft) -{ - struct bt_field_type_dynamic_array *seq_ft = (void *) ft; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_DYNAMIC_ARRAY, - "Field type"); - return seq_ft->length_field_path; -} - -static -void destroy_string_field_type(struct bt_object *obj) -{ - BT_ASSERT(obj); - BT_LIB_LOGD("Destroying string field type object: %!+F", obj); - g_free(obj); -} - -struct bt_field_type *bt_field_type_string_create(void) -{ - struct bt_field_type_string *string_ft = NULL; - - BT_LOGD_STR("Creating default string field type object."); - string_ft = g_new0(struct bt_field_type_string, 1); - if (!string_ft) { - BT_LOGE_STR("Failed to allocate one string field type."); - goto error; - } - - init_field_type((void *) string_ft, BT_FIELD_TYPE_ID_STRING, - destroy_string_field_type); - BT_LIB_LOGD("Created string field type object: %!+F", string_ft); - goto end; - -error: - BT_PUT(string_ft); - -end: - return (void *) string_ft; -} - -BT_HIDDEN -void _bt_field_type_freeze(struct bt_field_type *ft) -{ - /* - * Element/member/option field types are frozen when added to - * their owner. - */ - BT_ASSERT(ft); - ft->frozen = true; -} - -BT_HIDDEN -void _bt_field_type_make_part_of_trace(struct bt_field_type *ft) -{ - BT_ASSERT(ft); - BT_ASSERT_PRE(!ft->part_of_trace, - "Field type is already part of a trace: %!+F", ft); - ft->part_of_trace = true; - - switch (ft->id) { - case BT_FIELD_TYPE_ID_STRUCTURE: - case BT_FIELD_TYPE_ID_VARIANT: - { - struct bt_field_type_named_field_types_container *container_ft = - (void *) ft; - uint64_t i; - - for (i = 0; i < container_ft->named_fts->len; i++) { - struct bt_named_field_type *named_ft = - BT_FIELD_TYPE_NAMED_FT_AT_INDEX( - container_ft, i); - - bt_field_type_make_part_of_trace(named_ft->ft); - } - - break; - } - case BT_FIELD_TYPE_ID_STATIC_ARRAY: - case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY: - { - struct bt_field_type_array *array_ft = (void *) ft; - - bt_field_type_make_part_of_trace(array_ft->element_ft); - break; - } - default: - break; - } -} diff --git a/lib/ctf-ir/field-wrapper.c b/lib/ctf-ir/field-wrapper.c deleted file mode 100644 index ee28705f..00000000 --- a/lib/ctf-ir/field-wrapper.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2018 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "FIELD-WRAPPER" -#include - -#include -#include -#include -#include -#include - -BT_HIDDEN -struct bt_field_wrapper *bt_field_wrapper_new(void *data) -{ - struct bt_field_wrapper *field_wrapper = - g_new0(struct bt_field_wrapper, 1); - - BT_LOGD_STR("Creating empty field wrapper object."); - - if (!field_wrapper) { - BT_LOGE("Failed to allocate one field wrapper."); - goto end; - } - - bt_object_init_unique(&field_wrapper->base); - BT_LOGD("Created empty field wrapper object: addr=%p", - field_wrapper); - -end: - return field_wrapper; -} - -BT_HIDDEN -void bt_field_wrapper_destroy(struct bt_field_wrapper *field_wrapper) -{ - BT_LOGD("Destroying field wrapper: addr=%p", field_wrapper); - - if (field_wrapper->field) { - BT_LOGD_STR("Destroying field."); - bt_field_destroy((void *) field_wrapper->field); - } - - BT_LOGD_STR("Putting stream class."); - g_free(field_wrapper); -} - -BT_HIDDEN -struct bt_field_wrapper *bt_field_wrapper_create( - struct bt_object_pool *pool, struct bt_field_type *ft) -{ - struct bt_field_wrapper *field_wrapper = NULL; - - BT_ASSERT(pool); - BT_ASSERT(ft); - field_wrapper = bt_object_pool_create_object(pool); - if (!field_wrapper) { - BT_LIB_LOGE("Cannot allocate one field wrapper from field wrapper pool: " - "%![pool-]+o", pool); - goto error; - } - - if (!field_wrapper->field) { - field_wrapper->field = (void *) bt_field_create(ft); - if (!field_wrapper->field) { - BT_LIB_LOGE("Cannot create field wrapper from field type: " - "%![ft-]+F", ft); - goto error; - } - - BT_LIB_LOGD("Created initial field wrapper object: " - "wrapper-addr=%p, %![field-]+f", field_wrapper, - field_wrapper->field); - } - - goto end; - -error: - if (field_wrapper) { - bt_field_wrapper_destroy(field_wrapper); - field_wrapper = NULL; - } - -end: - return field_wrapper; -} diff --git a/lib/ctf-ir/fields.c b/lib/ctf-ir/fields.c deleted file mode 100644 index c0bd86b0..00000000 --- a/lib/ctf-ir/fields.c +++ /dev/null @@ -1,1104 +0,0 @@ -/* - * fields.c - * - * Babeltrace CTF IR - Event Fields - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "FIELDS" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static -void reset_single_field(struct bt_field *field); - -static -void reset_array_field(struct bt_field *field); - -static -void reset_structure_field(struct bt_field *field); - -static -void reset_variant_field(struct bt_field *field); - -static -void set_single_field_is_frozen(struct bt_field *field, bool is_frozen); - -static -void set_array_field_is_frozen(struct bt_field *field, bool is_frozen); - -static -void set_structure_field_is_frozen(struct bt_field *field, bool is_frozen); - -static -void set_variant_field_is_frozen(struct bt_field *field, bool is_frozen); - -static -bool single_field_is_set(struct bt_field *field); - -static -bool array_field_is_set(struct bt_field *field); - -static -bool structure_field_is_set(struct bt_field *field); - -static -bool variant_field_is_set(struct bt_field *field); - -static -struct bt_field_methods integer_field_methods = { - .set_is_frozen = set_single_field_is_frozen, - .is_set = single_field_is_set, - .reset = reset_single_field, -}; - -static -struct bt_field_methods real_field_methods = { - .set_is_frozen = set_single_field_is_frozen, - .is_set = single_field_is_set, - .reset = reset_single_field, -}; - -static -struct bt_field_methods string_field_methods = { - .set_is_frozen = set_single_field_is_frozen, - .is_set = single_field_is_set, - .reset = reset_single_field, -}; - -static -struct bt_field_methods structure_field_methods = { - .set_is_frozen = set_structure_field_is_frozen, - .is_set = structure_field_is_set, - .reset = reset_structure_field, -}; - -static -struct bt_field_methods array_field_methods = { - .set_is_frozen = set_array_field_is_frozen, - .is_set = array_field_is_set, - .reset = reset_array_field, -}; - -static -struct bt_field_methods variant_field_methods = { - .set_is_frozen = set_variant_field_is_frozen, - .is_set = variant_field_is_set, - .reset = reset_variant_field, -}; - -static -struct bt_field *create_integer_field(struct bt_field_type *); - -static -struct bt_field *create_real_field(struct bt_field_type *); - -static -struct bt_field *create_string_field(struct bt_field_type *); - -static -struct bt_field *create_structure_field(struct bt_field_type *); - -static -struct bt_field *create_static_array_field(struct bt_field_type *); - -static -struct bt_field *create_dynamic_array_field(struct bt_field_type *); - -static -struct bt_field *create_variant_field(struct bt_field_type *); - -static -struct bt_field *(* const field_create_funcs[])(struct bt_field_type *) = { - [BT_FIELD_TYPE_ID_UNSIGNED_INTEGER] = create_integer_field, - [BT_FIELD_TYPE_ID_SIGNED_INTEGER] = create_integer_field, - [BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION] = create_integer_field, - [BT_FIELD_TYPE_ID_SIGNED_ENUMERATION] = create_integer_field, - [BT_FIELD_TYPE_ID_REAL] = create_real_field, - [BT_FIELD_TYPE_ID_STRING] = create_string_field, - [BT_FIELD_TYPE_ID_STRUCTURE] = create_structure_field, - [BT_FIELD_TYPE_ID_STATIC_ARRAY] = create_static_array_field, - [BT_FIELD_TYPE_ID_DYNAMIC_ARRAY] = create_dynamic_array_field, - [BT_FIELD_TYPE_ID_VARIANT] = create_variant_field, -}; - -static -void destroy_integer_field(struct bt_field *field); - -static -void destroy_real_field(struct bt_field *field); - -static -void destroy_string_field(struct bt_field *field); - -static -void destroy_structure_field(struct bt_field *field); - -static -void destroy_array_field(struct bt_field *field); - -static -void destroy_variant_field(struct bt_field *field); - -static -void (* const field_destroy_funcs[])(struct bt_field *) = { - [BT_FIELD_TYPE_ID_UNSIGNED_INTEGER] = destroy_integer_field, - [BT_FIELD_TYPE_ID_SIGNED_INTEGER] = destroy_integer_field, - [BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION] = destroy_integer_field, - [BT_FIELD_TYPE_ID_SIGNED_ENUMERATION] = destroy_integer_field, - [BT_FIELD_TYPE_ID_REAL] = destroy_real_field, - [BT_FIELD_TYPE_ID_STRING] = destroy_string_field, - [BT_FIELD_TYPE_ID_STRUCTURE] = destroy_structure_field, - [BT_FIELD_TYPE_ID_STATIC_ARRAY] = destroy_array_field, - [BT_FIELD_TYPE_ID_DYNAMIC_ARRAY] = destroy_array_field, - [BT_FIELD_TYPE_ID_VARIANT] = destroy_variant_field, -}; - -struct bt_field_type *bt_field_borrow_type(struct bt_field *field) -{ - BT_ASSERT_PRE_NON_NULL(field, "Field"); - return field->type; -} - -enum bt_field_type_id bt_field_get_type_id(struct bt_field *field) -{ - BT_ASSERT_PRE_NON_NULL(field, "Field"); - return field->type->id; -} - -BT_HIDDEN -struct bt_field *bt_field_create(struct bt_field_type *ft) -{ - struct bt_field *field = NULL; - - BT_ASSERT_PRE_NON_NULL(ft, "Field type"); - BT_ASSERT(bt_field_type_has_known_id(ft)); - field = field_create_funcs[ft->id](ft); - if (!field) { - BT_LIB_LOGE("Cannot create field object from field type: " - "%![ft-]+F", ft); - goto end; - } - -end: - return field; -} - -static inline -void init_field(struct bt_field *field, struct bt_field_type *ft, - struct bt_field_methods *methods) -{ - BT_ASSERT(field); - BT_ASSERT(ft); - bt_object_init_unique(&field->base); - field->methods = methods; - field->type = bt_get(ft); -} - -static -struct bt_field *create_integer_field(struct bt_field_type *ft) -{ - struct bt_field_integer *int_field; - - BT_LIB_LOGD("Creating integer field object: %![ft-]+F", ft); - int_field = g_new0(struct bt_field_integer, 1); - if (!int_field) { - BT_LOGE_STR("Failed to allocate one integer field."); - goto end; - } - - init_field((void *) int_field, ft, &integer_field_methods); - BT_LIB_LOGD("Created integer field object: %!+f", int_field); - -end: - return (void *) int_field; -} - -static -struct bt_field *create_real_field(struct bt_field_type *ft) -{ - struct bt_field_real *real_field; - - BT_LIB_LOGD("Creating real field object: %![ft-]+F", ft); - real_field = g_new0(struct bt_field_real, 1); - if (!real_field) { - BT_LOGE_STR("Failed to allocate one real field."); - goto end; - } - - init_field((void *) real_field, ft, &real_field_methods); - BT_LIB_LOGD("Created real field object: %!+f", real_field); - -end: - return (void *) real_field; -} - -static -struct bt_field *create_string_field(struct bt_field_type *ft) -{ - struct bt_field_string *string_field; - - BT_LIB_LOGD("Creating string field object: %![ft-]+F", ft); - string_field = g_new0(struct bt_field_string, 1); - if (!string_field) { - BT_LOGE_STR("Failed to allocate one string field."); - goto end; - } - - init_field((void *) string_field, ft, &string_field_methods); - string_field->buf = g_array_sized_new(FALSE, FALSE, - sizeof(char), 1); - if (!string_field->buf) { - BT_LOGE_STR("Failed to allocate a GArray."); - BT_PUT(string_field); - goto end; - } - - g_array_index(string_field->buf, char, 0) = '\0'; - BT_LIB_LOGD("Created string field object: %!+f", string_field); - -end: - return (void *) string_field; -} - -static inline -int create_fields_from_named_field_types( - struct bt_field_type_named_field_types_container *ft, - GPtrArray **fields) -{ - int ret = 0; - uint64_t i; - - *fields = g_ptr_array_new_with_free_func( - (GDestroyNotify) bt_field_destroy); - if (!*fields) { - BT_LOGE_STR("Failed to allocate a GPtrArray."); - ret = -1; - goto end; - } - - g_ptr_array_set_size(*fields, ft->named_fts->len); - - for (i = 0; i < ft->named_fts->len; i++) { - struct bt_field *field; - struct bt_named_field_type *named_ft = - BT_FIELD_TYPE_NAMED_FT_AT_INDEX(ft, i); - - field = bt_field_create(named_ft->ft); - if (!field) { - BT_LIB_LOGE("Failed to create structure member or variant option field: " - "name=\"%s\", %![ft-]+F", - named_ft->name->str, named_ft->ft); - ret = -1; - goto end; - } - - g_ptr_array_index(*fields, i) = field; - } - -end: - return ret; -} - -static -struct bt_field *create_structure_field(struct bt_field_type *ft) -{ - struct bt_field_structure *struct_field; - - BT_LIB_LOGD("Creating structure field object: %![ft-]+F", ft); - struct_field = g_new0(struct bt_field_structure, 1); - if (!struct_field) { - BT_LOGE_STR("Failed to allocate one structure field."); - goto end; - } - - init_field((void *) struct_field, ft, &structure_field_methods); - - if (create_fields_from_named_field_types((void *) ft, - &struct_field->fields)) { - BT_LIB_LOGE("Cannot create structure member fields: " - "%![ft-]+F", ft); - BT_PUT(struct_field); - goto end; - } - - BT_LIB_LOGD("Created structure field object: %!+f", struct_field); - -end: - return (void *) struct_field; -} - -static -struct bt_field *create_variant_field(struct bt_field_type *ft) -{ - struct bt_field_variant *var_field; - - BT_LIB_LOGD("Creating variant field object: %![ft-]+F", ft); - var_field = g_new0(struct bt_field_variant, 1); - if (!var_field) { - BT_LOGE_STR("Failed to allocate one variant field."); - goto end; - } - - init_field((void *) var_field, ft, &variant_field_methods); - - if (create_fields_from_named_field_types((void *) ft, - &var_field->fields)) { - BT_LIB_LOGE("Cannot create variant member fields: " - "%![ft-]+F", ft); - BT_PUT(var_field); - goto end; - } - - BT_LIB_LOGD("Created variant field object: %!+f", var_field); - -end: - return (void *) var_field; -} - -static inline -int init_array_field_fields(struct bt_field_array *array_field) -{ - int ret = 0; - uint64_t i; - struct bt_field_type_array *array_ft; - - BT_ASSERT(array_field); - array_ft = (void *) array_field->common.type; - array_field->fields = g_ptr_array_sized_new(array_field->length); - if (!array_field->fields) { - BT_LOGE_STR("Failed to allocate a GPtrArray."); - ret = -1; - goto end; - } - - g_ptr_array_set_free_func(array_field->fields, - (GDestroyNotify) bt_field_destroy); - g_ptr_array_set_size(array_field->fields, array_field->length); - - for (i = 0; i < array_field->length; i++) { - array_field->fields->pdata[i] = bt_field_create( - array_ft->element_ft); - if (!array_field->fields->pdata[i]) { - BT_LIB_LOGE("Cannot create array field's element field: " - "index=%" PRIu64 ", %![ft-]+F", i, array_ft); - ret = -1; - goto end; - } - } - -end: - return ret; -} - -static -struct bt_field *create_static_array_field(struct bt_field_type *ft) -{ - struct bt_field_type_static_array *array_ft = (void *) ft; - struct bt_field_array *array_field; - - BT_LIB_LOGD("Creating static array field object: %![ft-]+F", ft); - array_field = g_new0(struct bt_field_array, 1); - if (!array_field) { - BT_LOGE_STR("Failed to allocate one static array field."); - goto end; - } - - init_field((void *) array_field, ft, &array_field_methods); - array_field->length = array_ft->length; - - if (init_array_field_fields(array_field)) { - BT_LIB_LOGE("Cannot create static array fields: " - "%![ft-]+F", ft); - BT_PUT(array_field); - goto end; - } - - BT_LIB_LOGD("Created static array field object: %!+f", array_field); - -end: - return (void *) array_field; -} - -static -struct bt_field *create_dynamic_array_field(struct bt_field_type *ft) -{ - struct bt_field_array *array_field; - - BT_LIB_LOGD("Creating dynamic array field object: %![ft-]+F", ft); - array_field = g_new0(struct bt_field_array, 1); - if (!array_field) { - BT_LOGE_STR("Failed to allocate one dynamic array field."); - goto end; - } - - init_field((void *) array_field, ft, &array_field_methods); - - if (init_array_field_fields(array_field)) { - BT_LIB_LOGE("Cannot create dynamic array fields: " - "%![ft-]+F", ft); - BT_PUT(array_field); - goto end; - } - - BT_LIB_LOGD("Created dynamic array field object: %!+f", array_field); - -end: - return (void *) array_field; -} - -int64_t bt_field_signed_integer_get_value(struct bt_field *field) -{ - struct bt_field_integer *int_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_FIELD_IS_SET(field, "Field"); - BT_ASSERT_PRE_FIELD_IS_SIGNED_INT(field, "Field"); - return int_field->value.i; -} - -void bt_field_signed_integer_set_value(struct bt_field *field, int64_t value) -{ - struct bt_field_integer *int_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_FIELD_IS_SIGNED_INT(field, "Field"); - BT_ASSERT_PRE_FIELD_HOT(field, "Field"); - BT_ASSERT_PRE(bt_util_value_is_in_range_signed( - ((struct bt_field_type_integer *) field->type)->range, value), - "Value is out of bounds: value=%" PRId64 ", %![field-]+f, " - "%![ft-]+F", value, field, field->type); - int_field->value.i = value; - bt_field_set_single(field, true); -} - -uint64_t bt_field_unsigned_integer_get_value(struct bt_field *field) -{ - struct bt_field_integer *int_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_FIELD_IS_SET(field, "Field"); - BT_ASSERT_PRE_FIELD_IS_UNSIGNED_INT(field, "Field"); - return int_field->value.u; -} - -void bt_field_unsigned_integer_set_value(struct bt_field *field, - uint64_t value) -{ - struct bt_field_integer *int_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_FIELD_IS_UNSIGNED_INT(field, "Field"); - BT_ASSERT_PRE_FIELD_HOT(field, "Field"); - BT_ASSERT_PRE(bt_util_value_is_in_range_unsigned( - ((struct bt_field_type_integer *) field->type)->range, value), - "Value is out of bounds: value=%" PRIu64 ", %![field-]+f, " - "%![ft-]+F", value, field, field->type); - int_field->value.u = value; - bt_field_set_single(field, true); -} - -double bt_field_real_get_value(struct bt_field *field) -{ - struct bt_field_real *real_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_FIELD_IS_SET(field, "Field"); - BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_REAL, "Field"); - return real_field->value; -} - -void bt_field_real_set_value(struct bt_field *field, double value) -{ - struct bt_field_real *real_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_REAL, "Field"); - BT_ASSERT_PRE_FIELD_HOT(field, "Field"); - BT_ASSERT_PRE( - !((struct bt_field_type_real *) field->type)->is_single_precision || - (double) (float) value == value, - "Invalid value for a single-precision real number: value=%f, " - "%![ft-]+F", value, field->type); - real_field->value = value; - bt_field_set_single(field, true); -} - -int bt_field_unsigned_enumeration_get_mapping_labels(struct bt_field *field, - bt_field_type_enumeration_mapping_label_array *label_array, - uint64_t *count) -{ - struct bt_field_integer *int_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_NON_NULL(label_array, "Label array (output)"); - BT_ASSERT_PRE_NON_NULL(label_array, "Count (output)"); - BT_ASSERT_PRE_FIELD_IS_SET(field, "Field"); - BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, - BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION, "Field"); - return bt_field_type_unsigned_enumeration_get_mapping_labels_by_value( - field->type, int_field->value.u, label_array, count); -} - -int bt_field_signed_enumeration_get_mapping_labels(struct bt_field *field, - bt_field_type_enumeration_mapping_label_array *label_array, - uint64_t *count) -{ - struct bt_field_integer *int_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_NON_NULL(label_array, "Label array (output)"); - BT_ASSERT_PRE_NON_NULL(label_array, "Count (output)"); - BT_ASSERT_PRE_FIELD_IS_SET(field, "Field"); - BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, - BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, "Field"); - return bt_field_type_signed_enumeration_get_mapping_labels_by_value( - field->type, int_field->value.i, label_array, count); -} - -const char *bt_field_string_get_value(struct bt_field *field) -{ - struct bt_field_string *string_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_FIELD_IS_SET(field, "Field"); - BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, - "Field"); - return (const char *) string_field->buf->data; -} - -uint64_t bt_field_string_get_length(struct bt_field *field) -{ - struct bt_field_string *string_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_FIELD_IS_SET(field, "Field"); - BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, - "Field"); - return string_field->length; -} - -int bt_field_string_set_value(struct bt_field *field, const char *value) -{ - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_NON_NULL(value, "Value"); - BT_ASSERT_PRE_FIELD_HOT(field, "Field"); - BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, - "Field"); - bt_field_string_clear(field); - return bt_field_string_append_with_length(field, value, - (uint64_t) strlen(value)); -} - -int bt_field_string_append(struct bt_field *field, const char *value) -{ - return bt_field_string_append_with_length(field, value, - (uint64_t) strlen(value)); -} - -int bt_field_string_append_with_length(struct bt_field *field, - const char *value, uint64_t length) -{ - struct bt_field_string *string_field = (void *) field; - char *data; - uint64_t new_length; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_NON_NULL(value, "Value"); - BT_ASSERT_PRE_FIELD_HOT(field, "Field"); - BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, - BT_FIELD_TYPE_ID_STRING, "Field"); - - /* Make sure no null bytes are appended */ - BT_ASSERT_PRE(memchr(value, '\0', length) == NULL, - "String value to append contains a null character: " - "partial-value=\"%.32s\", length=%" PRIu64, value, length); - - new_length = length + string_field->length; - - if (unlikely(new_length + 1 > string_field->buf->len)) { - g_array_set_size(string_field->buf, new_length + 1); - } - - data = string_field->buf->data; - memcpy(data + string_field->length, value, length); - ((char *) string_field->buf->data)[new_length] = '\0'; - string_field->length = new_length; - bt_field_set_single(field, true); - return 0; -} - -int bt_field_string_clear(struct bt_field *field) -{ - struct bt_field_string *string_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_FIELD_HOT(field, "Field"); - BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, - BT_FIELD_TYPE_ID_STRING, "Field"); - string_field->length = 0; - bt_field_set_single(field, true); - return 0; -} - -uint64_t bt_field_array_get_length(struct bt_field *field) -{ - struct bt_field_array *array_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_FIELD_IS_ARRAY(field, "Field"); - return array_field->length; -} - -int bt_field_dynamic_array_set_length(struct bt_field *field, - uint64_t length) -{ - int ret = 0; - struct bt_field_array *array_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, - BT_FIELD_TYPE_ID_DYNAMIC_ARRAY, "Field"); - BT_ASSERT_PRE_FIELD_HOT(field, "Field"); - - if (unlikely(length > array_field->fields->len)) { - /* Make more room */ - struct bt_field_type_array *array_ft; - uint64_t cur_len = array_field->fields->len; - uint64_t i; - - g_ptr_array_set_size(array_field->fields, length); - array_ft = (void *) field->type; - - for (i = cur_len; i < array_field->fields->len; i++) { - struct bt_field *elem_field = bt_field_create( - array_ft->element_ft); - - if (!elem_field) { - BT_LIB_LOGE("Cannot create element field for " - "dynamic array field: " - "index=%" PRIu64 ", " - "%![array-field-]+f", i, field); - ret = -1; - goto end; - } - - BT_ASSERT(!array_field->fields->pdata[i]); - array_field->fields->pdata[i] = elem_field; - } - } - - array_field->length = length; - -end: - return ret; -} - -struct bt_field *bt_field_array_borrow_element_field_by_index( - struct bt_field *field, uint64_t index) -{ - struct bt_field_array *array_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_FIELD_IS_ARRAY(field, "Field"); - BT_ASSERT_PRE_VALID_INDEX(index, array_field->length); - return array_field->fields->pdata[index]; -} - -struct bt_field *bt_field_structure_borrow_member_field_by_index( - struct bt_field *field, uint64_t index) -{ - struct bt_field_structure *struct_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, - BT_FIELD_TYPE_ID_STRUCTURE, "Field"); - BT_ASSERT_PRE_VALID_INDEX(index, struct_field->fields->len); - return struct_field->fields->pdata[index]; -} - -struct bt_field *bt_field_structure_borrow_member_field_by_name( - struct bt_field *field, const char *name) -{ - struct bt_field *ret_field = NULL; - struct bt_field_type_structure *struct_ft; - struct bt_field_structure *struct_field = (void *) field; - gpointer orig_key; - gpointer index; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_NON_NULL(name, "Field name"); - BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, - BT_FIELD_TYPE_ID_STRUCTURE, "Field"); - struct_ft = (void *) field->type; - - if (!g_hash_table_lookup_extended(struct_ft->common.name_to_index, name, - &orig_key, &index)) { - goto end; - } - - ret_field = struct_field->fields->pdata[GPOINTER_TO_UINT(index)]; - BT_ASSERT(ret_field); - -end: - return ret_field; -} - -struct bt_field *bt_field_variant_borrow_selected_option_field( - struct bt_field *field) -{ - struct bt_field_variant *var_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, - BT_FIELD_TYPE_ID_VARIANT, "Field"); - BT_ASSERT_PRE(var_field->selected_field, - "Variant field has no selected field: %!+f", field); - return var_field->selected_field; -} - -int bt_field_variant_select_option_field(struct bt_field *field, - uint64_t index) -{ - struct bt_field_variant *var_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, - BT_FIELD_TYPE_ID_VARIANT, "Field"); - BT_ASSERT_PRE_FIELD_HOT(field, "Field"); - BT_ASSERT_PRE_VALID_INDEX(index, var_field->fields->len); - var_field->selected_field = var_field->fields->pdata[index]; - var_field->selected_index = index; - return 0; -} - -uint64_t bt_field_variant_get_selected_option_field_index( - struct bt_field *field) -{ - struct bt_field_variant *var_field = (void *) field; - - BT_ASSERT_PRE_NON_NULL(field, "Field"); - BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, - BT_FIELD_TYPE_ID_VARIANT, "Field"); - BT_ASSERT_PRE(var_field->selected_field, - "Variant field has no selected field: %!+f", field); - return var_field->selected_index; -} - -static inline -void bt_field_finalize(struct bt_field *field) -{ - BT_ASSERT(field); - BT_LOGD_STR("Putting field's type."); - bt_put(field->type); -} - -static -void destroy_integer_field(struct bt_field *field) -{ - BT_ASSERT(field); - BT_LIB_LOGD("Destroying integer field object: %!+f", field); - bt_field_finalize(field); - g_free(field); -} - -static -void destroy_real_field(struct bt_field *field) -{ - BT_ASSERT(field); - BT_LIB_LOGD("Destroying real field object: %!+f", field); - bt_field_finalize(field); - g_free(field); -} - -static -void destroy_structure_field(struct bt_field *field) -{ - struct bt_field_structure *struct_field = (void *) field; - - BT_ASSERT(field); - BT_LIB_LOGD("Destroying structure field object: %!+f", field); - bt_field_finalize(field); - - if (struct_field->fields) { - g_ptr_array_free(struct_field->fields, TRUE); - } - - g_free(field); -} - -static -void destroy_variant_field(struct bt_field *field) -{ - struct bt_field_variant *var_field = (void *) field; - - BT_ASSERT(field); - BT_LIB_LOGD("Destroying variant field object: %!+f", field); - bt_field_finalize(field); - - if (var_field->fields) { - g_ptr_array_free(var_field->fields, TRUE); - } - - g_free(field); -} - -static -void destroy_array_field(struct bt_field *field) -{ - struct bt_field_array *array_field = (void *) field; - - BT_ASSERT(field); - BT_LIB_LOGD("Destroying array field object: %!+f", field); - bt_field_finalize(field); - - if (array_field->fields) { - g_ptr_array_free(array_field->fields, TRUE); - } - - g_free(field); -} - -static -void destroy_string_field(struct bt_field *field) -{ - struct bt_field_string *string_field = (void *) field; - - BT_ASSERT(field); - BT_LIB_LOGD("Destroying string field object: %!+f", field); - bt_field_finalize(field); - - if (string_field->buf) { - g_array_free(string_field->buf, TRUE); - } - - g_free(field); -} - -BT_HIDDEN -void bt_field_destroy(struct bt_field *field) -{ - BT_ASSERT(field); - BT_ASSERT(bt_field_type_has_known_id(field->type)); - field_destroy_funcs[field->type->id](field); -} - -static -void reset_single_field(struct bt_field *field) -{ - BT_ASSERT(field); - field->is_set = false; -} - -static -void reset_structure_field(struct bt_field *field) -{ - uint64_t i; - struct bt_field_structure *struct_field = (void *) field; - - BT_ASSERT(field); - - for (i = 0; i < struct_field->fields->len; i++) { - bt_field_reset(struct_field->fields->pdata[i]); - } -} - -static -void reset_variant_field(struct bt_field *field) -{ - uint64_t i; - struct bt_field_variant *var_field = (void *) field; - - BT_ASSERT(field); - - for (i = 0; i < var_field->fields->len; i++) { - bt_field_reset(var_field->fields->pdata[i]); - } -} - -static -void reset_array_field(struct bt_field *field) -{ - uint64_t i; - struct bt_field_array *array_field = (void *) field; - - BT_ASSERT(field); - - for (i = 0; i < array_field->fields->len; i++) { - bt_field_reset(array_field->fields->pdata[i]); - } -} - -static -void set_single_field_is_frozen(struct bt_field *field, bool is_frozen) -{ - field->frozen = is_frozen; -} - -static -void set_structure_field_is_frozen(struct bt_field *field, bool is_frozen) -{ - uint64_t i; - struct bt_field_structure *struct_field = (void *) field; - - BT_LIB_LOGD("Setting structure field's frozen state: " - "%![field-]+f, is-frozen=%d", field, is_frozen); - - for (i = 0; i < struct_field->fields->len; i++) { - struct bt_field *member_field = struct_field->fields->pdata[i]; - - BT_LIB_LOGD("Setting structure field's member field's " - "frozen state: %![field-]+f, index=%" PRIu64, - member_field, i); - bt_field_set_is_frozen(member_field, is_frozen); - } - - set_single_field_is_frozen(field, is_frozen); -} - -static -void set_variant_field_is_frozen(struct bt_field *field, bool is_frozen) -{ - uint64_t i; - struct bt_field_variant *var_field = (void *) field; - - BT_LIB_LOGD("Setting variant field's frozen state: " - "%![field-]+f, is-frozen=%d", field, is_frozen); - - for (i = 0; i < var_field->fields->len; i++) { - struct bt_field *option_field = var_field->fields->pdata[i]; - - BT_LIB_LOGD("Setting variant field's option field's " - "frozen state: %![field-]+f, index=%" PRIu64, - option_field, i); - bt_field_set_is_frozen(option_field, is_frozen); - } - - set_single_field_is_frozen(field, is_frozen); -} - -static -void set_array_field_is_frozen(struct bt_field *field, bool is_frozen) -{ - uint64_t i; - struct bt_field_array *array_field = (void *) field; - - BT_LIB_LOGD("Setting array field's frozen state: " - "%![field-]+f, is-frozen=%d", field, is_frozen); - - for (i = 0; i < array_field->fields->len; i++) { - struct bt_field *elem_field = array_field->fields->pdata[i]; - - BT_LIB_LOGD("Setting array field's element field's " - "frozen state: %![field-]+f, index=%" PRIu64, - elem_field, i); - bt_field_set_is_frozen(elem_field, is_frozen); - } - - set_single_field_is_frozen(field, is_frozen); -} - -BT_HIDDEN -void _bt_field_set_is_frozen(struct bt_field *field, - bool is_frozen) -{ - BT_ASSERT(field); - BT_LIB_LOGD("Setting field object's frozen state: %!+f, is-frozen=%d", - field, is_frozen); - BT_ASSERT(field->methods->set_is_frozen); - field->methods->set_is_frozen(field, is_frozen); -} - -static -bool single_field_is_set(struct bt_field *field) -{ - BT_ASSERT(field); - return field->is_set; -} - -static -bool structure_field_is_set(struct bt_field *field) -{ - bool is_set = true; - uint64_t i; - struct bt_field_structure *struct_field = (void *) field; - - BT_ASSERT(field); - - for (i = 0; i < struct_field->fields->len; i++) { - is_set = bt_field_is_set(struct_field->fields->pdata[i]); - if (!is_set) { - goto end; - } - } - -end: - return is_set; -} - -static -bool variant_field_is_set(struct bt_field *field) -{ - struct bt_field_variant *var_field = (void *) field; - bool is_set = false; - - BT_ASSERT(field); - - if (var_field->selected_field) { - is_set = bt_field_is_set(var_field->selected_field); - } - - return is_set; -} - -static -bool array_field_is_set(struct bt_field *field) -{ - bool is_set = true; - uint64_t i; - struct bt_field_array *array_field = (void *) field; - - BT_ASSERT(field); - - for (i = 0; i < array_field->length; i++) { - is_set = bt_field_is_set(array_field->fields->pdata[i]); - if (!is_set) { - goto end; - } - } - -end: - return is_set; -} diff --git a/lib/ctf-ir/packet-context-field.c b/lib/ctf-ir/packet-context-field.c deleted file mode 100644 index 55fdb7f4..00000000 --- a/lib/ctf-ir/packet-context-field.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2018 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "PACKET-CONTEXT-FIELD" -#include - -#include -#include -#include -#include -#include -#include - -struct bt_field *bt_packet_context_field_borrow_field( - struct bt_packet_context_field *context_field) -{ - struct bt_field_wrapper *field_wrapper = (void *) context_field; - - BT_ASSERT_PRE_NON_NULL(field_wrapper, "Packet context field"); - return field_wrapper->field; -} - -void bt_packet_context_field_release(struct bt_packet_context_field *context_field) -{ - struct bt_field_wrapper *field_wrapper = (void *) context_field; - - BT_ASSERT_PRE_NON_NULL(field_wrapper, "Packet context field"); - - /* - * Do not recycle because the pool could be destroyed at this - * point. This function is only called when there's an error - * anyway because the goal of a packet context field wrapper is - * to eventually move it to a packet with - * bt_packet_move_context() after creating it. - */ - bt_field_wrapper_destroy(field_wrapper); -} - -struct bt_packet_context_field *bt_packet_context_field_create( - struct bt_stream_class *stream_class) -{ - struct bt_field_wrapper *field_wrapper; - - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - BT_ASSERT_PRE(stream_class->frozen, - "Stream class is not part of a trace: %!+S", stream_class); - BT_ASSERT_PRE(stream_class->packet_context_ft, - "Stream class has no packet context field type: %!+S", - stream_class); - field_wrapper = bt_field_wrapper_create( - &stream_class->packet_context_field_pool, - (void *) stream_class->packet_context_ft); - if (!field_wrapper) { - BT_LIB_LOGE("Cannot allocate one packet context field from stream class: " - "%![sc-]+S", stream_class); - goto error; - } - - BT_ASSERT(field_wrapper->field); - bt_stream_class_freeze(stream_class); - goto end; - -error: - if (field_wrapper) { - bt_field_wrapper_destroy(field_wrapper); - field_wrapper = NULL; - } - -end: - return (void *) field_wrapper; -} diff --git a/lib/ctf-ir/packet-header-field.c b/lib/ctf-ir/packet-header-field.c deleted file mode 100644 index 17d88ad0..00000000 --- a/lib/ctf-ir/packet-header-field.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2018 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "PACKET-HEADER-FIELD" -#include - -#include -#include -#include -#include -#include -#include - -struct bt_field *bt_packet_header_field_borrow_field( - struct bt_packet_header_field *header_field) -{ - struct bt_field_wrapper *field_wrapper = (void *) header_field; - - BT_ASSERT_PRE_NON_NULL(field_wrapper, "Packet header field"); - return (void *) field_wrapper->field; -} - -void bt_packet_header_field_release(struct bt_packet_header_field *header_field) -{ - struct bt_field_wrapper *field_wrapper = (void *) header_field; - - BT_ASSERT_PRE_NON_NULL(field_wrapper, "Packet header field"); - - /* - * Do not recycle because the pool could be destroyed at this - * point. This function is only called when there's an error - * anyway because the goal of a packet header field wrapper is - * to eventually move it to a packet with - * bt_packet_move_header() after creating it. - */ - bt_field_wrapper_destroy(field_wrapper); -} - -struct bt_packet_header_field *bt_packet_header_field_create( - struct bt_trace *trace) -{ - struct bt_field_wrapper *field_wrapper; - - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - BT_ASSERT_PRE(trace->packet_header_ft, - "Trace has no packet header field type: %!+t", trace); - field_wrapper = bt_field_wrapper_create( - &trace->packet_header_field_pool, - (void *) trace->packet_header_ft); - if (!field_wrapper) { - BT_LIB_LOGE("Cannot allocate one packet header field from trace: " - "%![trace-]+t", trace); - goto error; - } - - BT_ASSERT(field_wrapper->field); - bt_trace_freeze(trace); - goto end; - -error: - if (field_wrapper) { - bt_field_wrapper_destroy(field_wrapper); - field_wrapper = NULL; - } - -end: - return (void *) field_wrapper; -} diff --git a/lib/ctf-ir/packet.c b/lib/ctf-ir/packet.c deleted file mode 100644 index d3fce47a..00000000 --- a/lib/ctf-ir/packet.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * packet.c - * - * Babeltrace CTF IR - Stream packet - * - * Copyright 2016 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "PACKET" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BT_ASSERT_PRE_PACKET_HOT(_packet) \ - BT_ASSERT_PRE_HOT((_packet), "Packet", ": %!+a", (_packet)) - -struct bt_stream *bt_packet_borrow_stream(struct bt_packet *packet) -{ - BT_ASSERT_PRE_NON_NULL(packet, "Packet"); - return packet->stream; -} - -struct bt_field *bt_packet_borrow_header_field(struct bt_packet *packet) -{ - BT_ASSERT_PRE_NON_NULL(packet, "Packet"); - return packet->header_field ? packet->header_field->field : NULL; -} - -struct bt_field *bt_packet_borrow_context_field(struct bt_packet *packet) -{ - BT_ASSERT_PRE_NON_NULL(packet, "Packet"); - return packet->context_field ? packet->context_field->field : NULL; -} - -BT_HIDDEN -void _bt_packet_set_is_frozen(struct bt_packet *packet, bool is_frozen) -{ - if (!packet) { - return; - } - - BT_LIB_LOGD("Setting packet's frozen state: %![packet-]+a, " - "is-frozen=%d", packet, is_frozen); - - if (packet->header_field) { - BT_LOGD_STR("Setting packet's header field's frozen state."); - bt_field_set_is_frozen(packet->header_field->field, - is_frozen); - } - - if (packet->context_field) { - BT_LOGD_STR("Setting packet's context field's frozen state."); - bt_field_set_is_frozen(packet->context_field->field, - is_frozen); - } - - packet->frozen = is_frozen; -} - -static inline -void reset_counter_snapshots(struct bt_packet *packet) -{ - packet->discarded_event_counter_snapshot.base.avail = - BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE; - packet->packet_counter_snapshot.base.avail = - BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE; -} - -static inline -void reset_packet(struct bt_packet *packet) -{ - BT_ASSERT(packet); - BT_LIB_LOGD("Resetting packet: %!+a", packet); - bt_packet_set_is_frozen(packet, false); - - if (packet->header_field) { - bt_field_set_is_frozen(packet->header_field->field, false); - bt_field_reset(packet->header_field->field); - } - - if (packet->context_field) { - bt_field_set_is_frozen(packet->context_field->field, false); - bt_field_reset(packet->context_field->field); - } - - if (packet->default_beginning_cv) { - bt_clock_value_reset(packet->default_beginning_cv); - } - - if (packet->default_end_cv) { - bt_clock_value_reset(packet->default_end_cv); - } - - reset_counter_snapshots(packet); -} - -static -void recycle_header_field(struct bt_field_wrapper *header_field, - struct bt_trace *trace) -{ - BT_ASSERT(header_field); - BT_LIB_LOGD("Recycling packet header field: " - "addr=%p, %![trace-]+t, %![field-]+f", header_field, - trace, header_field->field); - bt_object_pool_recycle_object(&trace->packet_header_field_pool, - header_field); -} - -static -void recycle_context_field(struct bt_field_wrapper *context_field, - struct bt_stream_class *stream_class) -{ - BT_ASSERT(context_field); - BT_LIB_LOGD("Recycling packet context field: " - "addr=%p, %![sc-]+S, %![field-]+f", context_field, - stream_class, context_field->field); - bt_object_pool_recycle_object(&stream_class->packet_context_field_pool, - context_field); -} - -BT_HIDDEN -void bt_packet_recycle(struct bt_packet *packet) -{ - struct bt_stream *stream; - - BT_ASSERT(packet); - BT_LIB_LOGD("Recycling packet: %!+a", packet); - - /* - * Those are the important ordered steps: - * - * 1. Reset the packet object (put any permanent reference it - * has, unfreeze it and its fields in developer mode, etc.), - * but do NOT put its stream's reference. This stream - * contains the pool to which we're about to recycle this - * packet object, so we must guarantee its existence thanks - * to this existing reference. - * - * 2. Move the stream reference to our `stream` - * variable so that we can set the packet's stream member - * to NULL before recycling it. We CANNOT do this after - * we put the stream reference because this bt_put() - * could destroy the stream, also destroying its - * packet pool, thus also destroying our packet object (this - * would result in an invalid write access). - * - * 3. Recycle the packet object. - * - * 4. Put our stream reference. - */ - reset_packet(packet); - stream = packet->stream; - BT_ASSERT(stream); - packet->stream = NULL; - bt_object_pool_recycle_object(&stream->packet_pool, packet); - bt_object_put_no_null_check(&stream->base); -} - -BT_HIDDEN -void bt_packet_destroy(struct bt_packet *packet) -{ - BT_LIB_LOGD("Destroying packet: %!+a", packet); - - if (packet->header_field) { - if (packet->stream) { - BT_LOGD_STR("Recycling packet's header field."); - recycle_header_field(packet->header_field, - bt_stream_class_borrow_trace_inline( - packet->stream->class)); - } else { - bt_field_wrapper_destroy(packet->header_field); - } - } - - if (packet->context_field) { - if (packet->stream) { - BT_LOGD_STR("Recycling packet's context field."); - recycle_context_field(packet->context_field, - packet->stream->class); - } else { - bt_field_wrapper_destroy(packet->context_field); - } - } - - if (packet->default_beginning_cv) { - BT_LOGD_STR("Recycling beginning clock value."); - bt_clock_value_recycle(packet->default_beginning_cv); - } - - if (packet->default_end_cv) { - BT_LOGD_STR("Recycling end clock value."); - bt_clock_value_recycle(packet->default_end_cv); - } - - BT_LOGD_STR("Putting packet's stream."); - bt_put(packet->stream); - g_free(packet); -} - -BT_HIDDEN -struct bt_packet *bt_packet_new(struct bt_stream *stream) -{ - struct bt_packet *packet = NULL; - struct bt_trace *trace = NULL; - - BT_ASSERT(stream); - BT_LIB_LOGD("Creating packet object: %![stream-]+s", stream); - packet = g_new0(struct bt_packet, 1); - if (!packet) { - BT_LOGE_STR("Failed to allocate one packet object."); - goto error; - } - - bt_object_init_shared(&packet->base, - (bt_object_release_func) bt_packet_recycle); - packet->stream = bt_get(stream); - trace = bt_stream_class_borrow_trace_inline(stream->class); - BT_ASSERT(trace); - - if (trace->packet_header_ft) { - BT_LOGD_STR("Creating initial packet header field."); - packet->header_field = bt_field_wrapper_create( - &trace->packet_header_field_pool, - trace->packet_header_ft); - if (!packet->header_field) { - BT_LOGE_STR("Cannot create packet header field wrapper."); - goto error; - } - } - - if (stream->class->packet_context_ft) { - BT_LOGD_STR("Creating initial packet context field."); - packet->context_field = bt_field_wrapper_create( - &stream->class->packet_context_field_pool, - stream->class->packet_context_ft); - if (!packet->context_field) { - BT_LOGE_STR("Cannot create packet context field wrapper."); - goto error; - } - } - - if (stream->class->default_clock_class) { - if (stream->class->packets_have_default_beginning_cv) { - packet->default_beginning_cv = bt_clock_value_create( - stream->class->default_clock_class); - if (!packet->default_beginning_cv) { - /* bt_clock_value_create() logs errors */ - goto error; - } - } - - if (stream->class->packets_have_default_end_cv) { - packet->default_end_cv = bt_clock_value_create( - stream->class->default_clock_class); - if (!packet->default_end_cv) { - /* bt_clock_value_create() logs errors */ - goto error; - } - } - } - - reset_counter_snapshots(packet); - BT_LIB_LOGD("Created packet object: %!+a", packet); - goto end; - -error: - BT_PUT(packet); - -end: - return packet; -} - -struct bt_packet *bt_packet_create(struct bt_stream *stream) -{ - struct bt_packet *packet = NULL; - - BT_ASSERT_PRE_NON_NULL(stream, "Stream"); - packet = bt_object_pool_create_object(&stream->packet_pool); - if (unlikely(!packet)) { - BT_LIB_LOGE("Cannot allocate one packet from stream's packet pool: " - "%![stream-]+s", stream); - goto end; - } - - if (likely(!packet->stream)) { - packet->stream = stream; - bt_object_get_no_null_check_no_parent_check( - &packet->stream->base); - } - -end: - return packet; -} - -int bt_packet_move_header_field(struct bt_packet *packet, - struct bt_packet_header_field *header_field) -{ - struct bt_trace *trace; - struct bt_field_wrapper *field_wrapper = (void *) header_field; - - BT_ASSERT_PRE_NON_NULL(packet, "Packet"); - BT_ASSERT_PRE_NON_NULL(field_wrapper, "Header field"); - BT_ASSERT_PRE_PACKET_HOT(packet); - trace = bt_stream_class_borrow_trace_inline(packet->stream->class); - BT_ASSERT_PRE(trace->packet_header_ft, - "Trace has no packet header field type: %!+t", - trace); - BT_ASSERT_PRE(field_wrapper->field->type == - trace->packet_header_ft, - "Unexpected packet header field's type: " - "%![ft-]+F, %![expected-ft-]+F", field_wrapper->field->type, - trace->packet_header_ft); - - /* Recycle current header field: always exists */ - BT_ASSERT(packet->header_field); - recycle_header_field(packet->header_field, trace); - - /* Move new field */ - packet->header_field = field_wrapper; - return 0; -} - -int bt_packet_move_context_field(struct bt_packet *packet, - struct bt_packet_context_field *context_field) -{ - struct bt_stream_class *stream_class; - struct bt_field_wrapper *field_wrapper = (void *) context_field; - - BT_ASSERT_PRE_NON_NULL(packet, "Packet"); - BT_ASSERT_PRE_NON_NULL(field_wrapper, "Context field"); - BT_ASSERT_PRE_HOT(packet, "Packet", ": %!+a", packet); - stream_class = packet->stream->class; - BT_ASSERT_PRE(stream_class->packet_context_ft, - "Stream class has no packet context field type: %!+S", - stream_class); - BT_ASSERT_PRE(field_wrapper->field->type == - stream_class->packet_context_ft, - "Unexpected packet header field's type: " - "%![ft-]+F, %![expected-ft-]+F", field_wrapper->field->type, - stream_class->packet_context_ft); - - /* Recycle current context field: always exists */ - BT_ASSERT(packet->context_field); - recycle_context_field(packet->context_field, stream_class); - - /* Move new field */ - packet->context_field = field_wrapper; - return 0; -} - -int bt_packet_set_default_beginning_clock_value(struct bt_packet *packet, - uint64_t value_cycles) -{ - struct bt_stream_class *sc; - - BT_ASSERT_PRE_NON_NULL(packet, "Packet"); - BT_ASSERT_PRE_PACKET_HOT(packet); - sc = packet->stream->class; - BT_ASSERT(sc); - BT_ASSERT_PRE(sc->default_clock_class, - "Packet's stream class has no default clock class: " - "%![packet-]+a, %![sc-]+S", packet, sc); - BT_ASSERT_PRE(sc->packets_have_default_beginning_cv, - "Packet's stream class indicates that its packets have " - "no default beginning clock value: %![packet-]+a, %![sc-]+S", - packet, sc); - BT_ASSERT(packet->default_beginning_cv); - bt_clock_value_set_value_inline(packet->default_beginning_cv, value_cycles); - BT_LIB_LOGV("Set packet's default beginning clock value: " - "%![packet-]+a, value=%" PRIu64, value_cycles); - return 0; -} - -enum bt_clock_value_status bt_packet_borrow_default_beginning_clock_value( - struct bt_packet *packet, struct bt_clock_value **clock_value) -{ - BT_ASSERT_PRE_NON_NULL(packet, "Packet"); - BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value (output)"); - *clock_value = packet->default_beginning_cv; - return BT_CLOCK_VALUE_STATUS_KNOWN; -} - -int bt_packet_set_default_end_clock_value(struct bt_packet *packet, - uint64_t value_cycles) -{ - struct bt_stream_class *sc; - - BT_ASSERT_PRE_NON_NULL(packet, "Packet"); - BT_ASSERT_PRE_PACKET_HOT(packet); - sc = packet->stream->class; - BT_ASSERT(sc); - BT_ASSERT_PRE(sc->default_clock_class, - "Packet's stream class has no default clock class: " - "%![packet-]+a, %![sc-]+S", packet, sc); - BT_ASSERT_PRE(sc->packets_have_default_end_cv, - "Packet's stream class indicates that its packets have " - "no default end clock value: %![packet-]+a, %![sc-]+S", - packet, sc); - BT_ASSERT(packet->default_end_cv); - bt_clock_value_set_value_inline(packet->default_end_cv, value_cycles); - BT_LIB_LOGV("Set packet's default end clock value: " - "%![packet-]+a, value=%" PRIu64, value_cycles); - return 0; -} - -enum bt_clock_value_status bt_packet_borrow_default_end_clock_value( - struct bt_packet *packet, struct bt_clock_value **clock_value) -{ - BT_ASSERT_PRE_NON_NULL(packet, "Packet"); - BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value (output)"); - *clock_value = packet->default_end_cv; - return BT_CLOCK_VALUE_STATUS_KNOWN; -} - -enum bt_property_availability bt_packet_get_discarded_event_counter_snapshot( - struct bt_packet *packet, uint64_t *value) -{ - BT_ASSERT_PRE_NON_NULL(packet, "Packet"); - BT_ASSERT_PRE_NON_NULL(value, "Value (output)"); - *value = packet->discarded_event_counter_snapshot.value; - return packet->discarded_event_counter_snapshot.base.avail; -} - -int bt_packet_set_discarded_event_counter_snapshot(struct bt_packet *packet, - uint64_t value) -{ - BT_ASSERT_PRE_NON_NULL(packet, "Packet"); - BT_ASSERT_PRE_PACKET_HOT(packet); - BT_ASSERT_PRE(packet->stream->class->packets_have_discarded_event_counter_snapshot, - "Packet's stream's discarded event counter is not enabled: " - "%![packet-]+a", packet); - bt_property_uint_set(&packet->discarded_event_counter_snapshot, value); - return 0; -} - -enum bt_property_availability bt_packet_get_packet_counter_snapshot( - struct bt_packet *packet, uint64_t *value) -{ - BT_ASSERT_PRE_NON_NULL(packet, "Packet"); - BT_ASSERT_PRE_NON_NULL(value, "Value (output)"); - *value = packet->packet_counter_snapshot.value; - return packet->packet_counter_snapshot.base.avail; -} - -int bt_packet_set_packet_counter_snapshot(struct bt_packet *packet, - uint64_t value) -{ - BT_ASSERT_PRE_NON_NULL(packet, "Packet"); - BT_ASSERT_PRE_PACKET_HOT(packet); - BT_ASSERT_PRE(packet->stream->class->packets_have_packet_counter_snapshot, - "Packet's stream's packet counter is not enabled: " - "%![packet-]+a", packet); - bt_property_uint_set(&packet->packet_counter_snapshot, value); - return 0; -} diff --git a/lib/ctf-ir/resolve-field-path.c b/lib/ctf-ir/resolve-field-path.c deleted file mode 100644 index 60367589..00000000 --- a/lib/ctf-ir/resolve-field-path.c +++ /dev/null @@ -1,610 +0,0 @@ -/* - * Copyright 2018 Philippe Proulx - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "RESOLVE-FIELD-PATH" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static -bool find_field_type_recursive(struct bt_field_type *ft, - struct bt_field_type *tgt_ft, struct bt_field_path *field_path) -{ - bool found = false; - - if (tgt_ft == ft) { - found = true; - goto end; - } - - switch (ft->id) { - case BT_FIELD_TYPE_ID_STRUCTURE: - case BT_FIELD_TYPE_ID_VARIANT: - { - struct bt_field_type_named_field_types_container *container_ft = - (void *) ft; - uint64_t i; - - for (i = 0; i < container_ft->named_fts->len; i++) { - struct bt_named_field_type *named_ft = - BT_FIELD_TYPE_NAMED_FT_AT_INDEX( - container_ft, i); - - g_array_append_val(field_path->indexes, i); - found = find_field_type_recursive(named_ft->ft, - tgt_ft, field_path); - if (found) { - goto end; - } - - g_array_set_size(field_path->indexes, - field_path->indexes->len - 1); - } - - break; - } - case BT_FIELD_TYPE_ID_STATIC_ARRAY: - case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY: - { - struct bt_field_type_array *array_ft = (void *) ft; - - found = find_field_type_recursive(array_ft->element_ft, - tgt_ft, field_path); - break; - } - default: - break; - } - -end: - return found; -} - -static -int find_field_type(struct bt_field_type *root_ft, - enum bt_scope root_scope, struct bt_field_type *tgt_ft, - struct bt_field_path **ret_field_path) -{ - int ret = 0; - struct bt_field_path *field_path = NULL; - - if (!root_ft) { - goto end; - } - - field_path = bt_field_path_create(); - if (!field_path) { - ret = -1; - goto end; - } - - field_path->root = root_scope; - if (!find_field_type_recursive(root_ft, tgt_ft, field_path)) { - /* Not found here */ - BT_PUT(field_path); - } - -end: - *ret_field_path = field_path; - return ret; -} - -static -struct bt_field_path *find_field_type_in_ctx(struct bt_field_type *ft, - struct bt_resolve_field_path_context *ctx) -{ - struct bt_field_path *field_path = NULL; - int ret; - - ret = find_field_type(ctx->packet_header, BT_SCOPE_PACKET_HEADER, - ft, &field_path); - if (ret || field_path) { - goto end; - } - - ret = find_field_type(ctx->packet_context, BT_SCOPE_PACKET_CONTEXT, - ft, &field_path); - if (ret || field_path) { - goto end; - } - - ret = find_field_type(ctx->event_header, BT_SCOPE_EVENT_HEADER, - ft, &field_path); - if (ret || field_path) { - goto end; - } - - ret = find_field_type(ctx->event_common_context, - BT_SCOPE_EVENT_COMMON_CONTEXT, ft, &field_path); - if (ret || field_path) { - goto end; - } - - ret = find_field_type(ctx->event_specific_context, - BT_SCOPE_EVENT_SPECIFIC_CONTEXT, ft, &field_path); - if (ret || field_path) { - goto end; - } - - ret = find_field_type(ctx->event_payload, BT_SCOPE_EVENT_PAYLOAD, - ft, &field_path); - if (ret || field_path) { - goto end; - } - -end: - return field_path; -} - -BT_ASSERT_PRE_FUNC -static inline -bool target_is_before_source(struct bt_field_path *src_field_path, - struct bt_field_path *tgt_field_path) -{ - bool is_valid = true; - uint64_t src_i = 0, tgt_i = 0; - - if (tgt_field_path->root < src_field_path->root) { - goto end; - } - - if (tgt_field_path->root > src_field_path->root) { - is_valid = false; - goto end; - } - - BT_ASSERT(tgt_field_path->root == src_field_path->root); - - while (src_i < src_field_path->indexes->len && - tgt_i < tgt_field_path->indexes->len) { - uint64_t src_index = bt_field_path_get_index_by_index_inline( - src_field_path, src_i); - uint64_t tgt_index = bt_field_path_get_index_by_index_inline( - tgt_field_path, tgt_i); - - if (tgt_index > src_index) { - is_valid = false; - goto end; - } - - src_i++; - tgt_i++; - } - -end: - return is_valid; -} - -BT_ASSERT_PRE_FUNC -static inline -struct bt_field_type *borrow_root_field_type( - struct bt_resolve_field_path_context *ctx, enum bt_scope scope) -{ - switch (scope) { - case BT_SCOPE_PACKET_HEADER: - return ctx->packet_header; - case BT_SCOPE_PACKET_CONTEXT: - return ctx->packet_context; - case BT_SCOPE_EVENT_HEADER: - return ctx->event_header; - case BT_SCOPE_EVENT_COMMON_CONTEXT: - return ctx->event_common_context; - case BT_SCOPE_EVENT_SPECIFIC_CONTEXT: - return ctx->event_specific_context; - case BT_SCOPE_EVENT_PAYLOAD: - return ctx->event_payload; - default: - abort(); - } - - return NULL; -} - -BT_ASSERT_PRE_FUNC -static inline -struct bt_field_type *borrow_child_field_type(struct bt_field_type *parent_ft, - uint64_t index, bool *advance) -{ - struct bt_field_type *child_ft = NULL; - - switch (parent_ft->id) { - case BT_FIELD_TYPE_ID_STRUCTURE: - case BT_FIELD_TYPE_ID_VARIANT: - { - struct bt_named_field_type *named_ft = - BT_FIELD_TYPE_NAMED_FT_AT_INDEX(parent_ft, index); - - child_ft = named_ft->ft; - *advance = true; - break; - } - case BT_FIELD_TYPE_ID_STATIC_ARRAY: - case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY: - { - struct bt_field_type_array *array_ft = (void *) parent_ft; - - child_ft = array_ft->element_ft; - *advance = false; - break; - } - default: - break; - } - - return child_ft; -} - -BT_ASSERT_PRE_FUNC -static inline -bool target_field_path_in_different_scope_has_struct_ft_only( - struct bt_field_path *src_field_path, - struct bt_field_path *tgt_field_path, - struct bt_resolve_field_path_context *ctx) -{ - bool is_valid = true; - uint64_t i = 0; - struct bt_field_type *ft; - - if (src_field_path->root == tgt_field_path->root) { - goto end; - } - - ft = borrow_root_field_type(ctx, tgt_field_path->root); - - while (i < tgt_field_path->indexes->len) { - uint64_t index = bt_field_path_get_index_by_index_inline( - tgt_field_path, i); - bool advance; - - if (ft->id == BT_FIELD_TYPE_ID_STATIC_ARRAY || - ft->id == BT_FIELD_TYPE_ID_DYNAMIC_ARRAY || - ft->id == BT_FIELD_TYPE_ID_VARIANT) { - is_valid = false; - goto end; - } - - ft = borrow_child_field_type(ft, index, &advance); - - if (advance) { - i++; - } - } - -end: - return is_valid; -} - -BT_ASSERT_PRE_FUNC -static inline -bool lca_is_structure_field_type(struct bt_field_path *src_field_path, - struct bt_field_path *tgt_field_path, - struct bt_resolve_field_path_context *ctx) -{ - bool is_valid = true; - struct bt_field_type *src_ft; - struct bt_field_type *tgt_ft; - struct bt_field_type *prev_ft = NULL; - uint64_t src_i = 0, tgt_i = 0; - - if (src_field_path->root != tgt_field_path->root) { - goto end; - } - - src_ft = borrow_root_field_type(ctx, src_field_path->root); - tgt_ft = borrow_root_field_type(ctx, tgt_field_path->root); - BT_ASSERT(src_ft); - BT_ASSERT(tgt_ft); - - while (src_i < src_field_path->indexes->len && - tgt_i < tgt_field_path->indexes->len) { - bool advance; - uint64_t src_index = bt_field_path_get_index_by_index_inline( - src_field_path, src_i); - uint64_t tgt_index = bt_field_path_get_index_by_index_inline( - tgt_field_path, tgt_i); - - if (src_ft != tgt_ft) { - if (!prev_ft) { - /* - * This is correct: the LCA is the root - * scope field type, which must be a - * structure field type. - */ - break; - } - - if (prev_ft->id != BT_FIELD_TYPE_ID_STRUCTURE) { - is_valid = false; - } - - break; - } - - prev_ft = src_ft; - src_ft = borrow_child_field_type(src_ft, src_index, &advance); - - if (advance) { - src_i++; - } - - tgt_ft = borrow_child_field_type(tgt_ft, tgt_index, &advance); - - if (advance) { - tgt_i++; - } - } - -end: - return is_valid; -} - -BT_ASSERT_PRE_FUNC -static inline -bool lca_to_target_has_struct_ft_only(struct bt_field_path *src_field_path, - struct bt_field_path *tgt_field_path, - struct bt_resolve_field_path_context *ctx) -{ - bool is_valid = true; - struct bt_field_type *src_ft; - struct bt_field_type *tgt_ft; - uint64_t src_i = 0, tgt_i = 0; - - if (src_field_path->root != tgt_field_path->root) { - goto end; - } - - src_ft = borrow_root_field_type(ctx, src_field_path->root); - tgt_ft = borrow_root_field_type(ctx, tgt_field_path->root); - BT_ASSERT(src_ft); - BT_ASSERT(tgt_ft); - BT_ASSERT(src_ft == tgt_ft); - - /* Find LCA */ - while (src_i < src_field_path->indexes->len && - tgt_i < tgt_field_path->indexes->len) { - bool advance; - uint64_t src_index = bt_field_path_get_index_by_index_inline( - src_field_path, src_i); - uint64_t tgt_index = bt_field_path_get_index_by_index_inline( - tgt_field_path, tgt_i); - - if (src_i != tgt_i) { - /* Next FT is different: LCA is `tgt_ft` */ - break; - } - - src_ft = borrow_child_field_type(src_ft, src_index, &advance); - - if (advance) { - src_i++; - } - - tgt_ft = borrow_child_field_type(tgt_ft, tgt_index, &advance); - - if (advance) { - tgt_i++; - } - } - - /* Only structure field types to the target */ - while (tgt_i < tgt_field_path->indexes->len) { - bool advance; - uint64_t tgt_index = bt_field_path_get_index_by_index_inline( - tgt_field_path, tgt_i); - - if (tgt_ft->id == BT_FIELD_TYPE_ID_STATIC_ARRAY || - tgt_ft->id == BT_FIELD_TYPE_ID_DYNAMIC_ARRAY || - tgt_ft->id == BT_FIELD_TYPE_ID_VARIANT) { - is_valid = false; - goto end; - } - - tgt_ft = borrow_child_field_type(tgt_ft, tgt_index, &advance); - - if (advance) { - tgt_i++; - } - } - -end: - return is_valid; -} - -BT_ASSERT_PRE_FUNC -static inline -bool field_path_is_valid(struct bt_field_type *src_ft, - struct bt_field_type *tgt_ft, - struct bt_resolve_field_path_context *ctx) -{ - bool is_valid = true; - struct bt_field_path *src_field_path = find_field_type_in_ctx( - src_ft, ctx); - struct bt_field_path *tgt_field_path = find_field_type_in_ctx( - tgt_ft, ctx); - - if (!src_field_path) { - BT_ASSERT_PRE_MSG("Cannot find requesting field type in " - "resolving context: %!+F", src_ft); - is_valid = false; - goto end; - } - - if (!tgt_field_path) { - BT_ASSERT_PRE_MSG("Cannot find target field type in " - "resolving context: %!+F", tgt_ft); - is_valid = false; - goto end; - } - - /* Target must be before source */ - if (!target_is_before_source(src_field_path, tgt_field_path)) { - BT_ASSERT_PRE_MSG("Target field type is located after " - "requesting field type: %![req-ft-]+F, %![tgt-ft-]+F", - src_ft, tgt_ft); - is_valid = false; - goto end; - } - - /* - * If target is in a different scope than source, there are no - * array or variant field types on the way to the target. - */ - if (!target_field_path_in_different_scope_has_struct_ft_only( - src_field_path, tgt_field_path, ctx)) { - BT_ASSERT_PRE_MSG("Target field type is located in a " - "different scope than requesting field type, " - "but within an array or a variant field type: " - "%![req-ft-]+F, %![tgt-ft-]+F", - src_ft, tgt_ft); - is_valid = false; - goto end; - } - - /* Same scope: LCA must be a structure field type */ - if (!lca_is_structure_field_type(src_field_path, tgt_field_path, ctx)) { - BT_ASSERT_PRE_MSG("Lowest common ancestor of target and " - "requesting field types is not a structure field type: " - "%![req-ft-]+F, %![tgt-ft-]+F", - src_ft, tgt_ft); - is_valid = false; - goto end; - } - - /* Same scope: path from LCA to target has no array/variant FTs */ - if (!lca_to_target_has_struct_ft_only(src_field_path, tgt_field_path, - ctx)) { - BT_ASSERT_PRE_MSG("Path from lowest common ancestor of target " - "and requesting field types to target field type " - "contains an array or a variant field type: " - "%![req-ft-]+F, %![tgt-ft-]+F", src_ft, tgt_ft); - is_valid = false; - goto end; - } - -end: - bt_put(src_field_path); - bt_put(tgt_field_path); - return is_valid; -} - -static -struct bt_field_path *resolve_field_path(struct bt_field_type *src_ft, - struct bt_field_type *tgt_ft, - struct bt_resolve_field_path_context *ctx) -{ - BT_ASSERT_PRE(field_path_is_valid(src_ft, tgt_ft, ctx), - "Invalid target field type: %![req-ft-]+F, %![tgt-ft-]+F", - src_ft, tgt_ft); - return find_field_type_in_ctx(tgt_ft, ctx); -} - -BT_HIDDEN -int bt_resolve_field_paths(struct bt_field_type *ft, - struct bt_resolve_field_path_context *ctx) -{ - int ret = 0; - - BT_ASSERT(ft); - - /* Resolving part for dynamic array and variant field types */ - switch (ft->id) { - case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY: - { - struct bt_field_type_dynamic_array *dyn_array_ft = (void *) ft; - - if (dyn_array_ft->length_ft) { - BT_ASSERT(!dyn_array_ft->length_field_path); - dyn_array_ft->length_field_path = resolve_field_path( - ft, dyn_array_ft->length_ft, ctx); - if (!dyn_array_ft->length_field_path) { - ret = -1; - goto end; - } - } - - break; - } - case BT_FIELD_TYPE_ID_VARIANT: - { - struct bt_field_type_variant *var_ft = (void *) ft; - - if (var_ft->selector_ft) { - BT_ASSERT(!var_ft->selector_field_path); - var_ft->selector_field_path = - resolve_field_path(ft, - var_ft->selector_ft, ctx); - if (!var_ft->selector_field_path) { - ret = -1; - goto end; - } - } - } - default: - break; - } - - /* Recursive part */ - switch (ft->id) { - case BT_FIELD_TYPE_ID_STRUCTURE: - case BT_FIELD_TYPE_ID_VARIANT: - { - struct bt_field_type_named_field_types_container *container_ft = - (void *) ft; - uint64_t i; - - for (i = 0; i < container_ft->named_fts->len; i++) { - struct bt_named_field_type *named_ft = - BT_FIELD_TYPE_NAMED_FT_AT_INDEX( - container_ft, i); - - ret = bt_resolve_field_paths(named_ft->ft, ctx); - if (ret) { - goto end; - } - } - - break; - } - case BT_FIELD_TYPE_ID_STATIC_ARRAY: - case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY: - { - struct bt_field_type_array *array_ft = (void *) ft; - - ret = bt_resolve_field_paths(array_ft->element_ft, ctx); - break; - } - default: - break; - } - -end: - return ret; -} diff --git a/lib/ctf-ir/stream-class.c b/lib/ctf-ir/stream-class.c deleted file mode 100644 index 69b9d5c3..00000000 --- a/lib/ctf-ir/stream-class.c +++ /dev/null @@ -1,567 +0,0 @@ -/* - * stream-class.c - * - * Babeltrace CTF IR - Stream Class - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "STREAM-CLASS" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BT_ASSERT_PRE_STREAM_CLASS_HOT(_sc) \ - BT_ASSERT_PRE_HOT((_sc), "Stream class", ": %!+S", (_sc)) - -static -void destroy_stream_class(struct bt_object *obj) -{ - struct bt_stream_class *stream_class = (void *) obj; - - BT_LIB_LOGD("Destroying stream class: %!+S", stream_class); - BT_LOGD_STR("Putting default clock class."); - bt_put(stream_class->default_clock_class); - - if (stream_class->event_classes) { - BT_LOGD_STR("Destroying event classes."); - g_ptr_array_free(stream_class->event_classes, TRUE); - } - - if (stream_class->name.str) { - g_string_free(stream_class->name.str, TRUE); - } - - BT_LOGD_STR("Putting event header field type."); - bt_put(stream_class->event_header_ft); - BT_LOGD_STR("Putting packet context field type."); - bt_put(stream_class->packet_context_ft); - BT_LOGD_STR("Putting event common context field type."); - bt_put(stream_class->event_common_context_ft); - bt_object_pool_finalize(&stream_class->event_header_field_pool); - bt_object_pool_finalize(&stream_class->packet_context_field_pool); - g_free(stream_class); -} - -static -void free_field_wrapper(struct bt_field_wrapper *field_wrapper, - struct bt_stream_class *stream_class) -{ - bt_field_wrapper_destroy((void *) field_wrapper); -} - -BT_ASSERT_PRE_FUNC -static -bool stream_class_id_is_unique(struct bt_trace *trace, uint64_t id) -{ - uint64_t i; - bool is_unique = true; - - for (i = 0; i < trace->stream_classes->len; i++) { - struct bt_stream_class *sc = - trace->stream_classes->pdata[i]; - - if (sc->id == id) { - is_unique = false; - goto end; - } - } - -end: - return is_unique; -} - -static -struct bt_stream_class *create_stream_class_with_id(struct bt_trace *trace, - uint64_t id) -{ - struct bt_stream_class *stream_class = NULL; - int ret; - - BT_ASSERT(trace); - BT_ASSERT_PRE(stream_class_id_is_unique(trace, id), - "Duplicate stream class ID: %![trace-]+t, id=%" PRIu64, - trace, id); - BT_LIB_LOGD("Creating stream class object: %![trace-]+t, id=%" PRIu64, - trace, id); - stream_class = g_new0(struct bt_stream_class, 1); - if (!stream_class) { - BT_LOGE_STR("Failed to allocate one stream class."); - goto error; - } - - bt_object_init_shared_with_parent(&stream_class->base, - destroy_stream_class); - - stream_class->name.str = g_string_new(NULL); - if (!stream_class->name.str) { - BT_LOGE_STR("Failed to allocate a GString."); - ret = -1; - goto end; - } - - stream_class->id = id; - stream_class->assigns_automatic_event_class_id = true; - stream_class->assigns_automatic_stream_id = true; - stream_class->event_classes = g_ptr_array_new_with_free_func( - (GDestroyNotify) bt_object_try_spec_release); - if (!stream_class->event_classes) { - BT_LOGE_STR("Failed to allocate a GPtrArray."); - goto error; - } - - ret = bt_object_pool_initialize(&stream_class->event_header_field_pool, - (bt_object_pool_new_object_func) bt_field_wrapper_new, - (bt_object_pool_destroy_object_func) free_field_wrapper, - stream_class); - if (ret) { - BT_LOGE("Failed to initialize event header field pool: ret=%d", - ret); - goto error; - } - - ret = bt_object_pool_initialize(&stream_class->packet_context_field_pool, - (bt_object_pool_new_object_func) bt_field_wrapper_new, - (bt_object_pool_destroy_object_func) free_field_wrapper, - stream_class); - if (ret) { - BT_LOGE("Failed to initialize packet context field pool: ret=%d", - ret); - goto error; - } - - bt_object_set_parent(&stream_class->base, &trace->base); - g_ptr_array_add(trace->stream_classes, stream_class); - bt_trace_freeze(trace); - BT_LIB_LOGD("Created stream class object: %!+S", stream_class); - goto end; - -error: - BT_PUT(stream_class); - -end: - return stream_class; -} - -struct bt_stream_class *bt_stream_class_create(struct bt_trace *trace) -{ - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - BT_ASSERT_PRE(trace->assigns_automatic_stream_class_id, - "Trace does not automatically assigns stream class IDs: " - "%![sc-]+t", trace); - return create_stream_class_with_id(trace, - (uint64_t) trace->stream_classes->len); -} - -struct bt_stream_class *bt_stream_class_create_with_id( - struct bt_trace *trace, uint64_t id) -{ - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - BT_ASSERT_PRE(!trace->assigns_automatic_stream_class_id, - "Trace automatically assigns stream class IDs: " - "%![sc-]+t", trace); - return create_stream_class_with_id(trace, id); -} - -struct bt_trace *bt_stream_class_borrow_trace(struct bt_stream_class *stream_class) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - return bt_stream_class_borrow_trace_inline(stream_class); -} - -const char *bt_stream_class_get_name(struct bt_stream_class *stream_class) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - return stream_class->name.value; -} - -int bt_stream_class_set_name(struct bt_stream_class *stream_class, - const char *name) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - BT_ASSERT_PRE_NON_NULL(name, "Name"); - BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); - g_string_assign(stream_class->name.str, name); - stream_class->name.value = stream_class->name.str->str; - BT_LIB_LOGV("Set stream class's name: %!+S", stream_class); - return 0; -} - -uint64_t bt_stream_class_get_id(struct bt_stream_class *stream_class) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - return stream_class->id; -} - -uint64_t bt_stream_class_get_event_class_count( - struct bt_stream_class *stream_class) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - return (uint64_t) stream_class->event_classes->len; -} - -struct bt_event_class *bt_stream_class_borrow_event_class_by_index( - struct bt_stream_class *stream_class, uint64_t index) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - BT_ASSERT_PRE_VALID_INDEX(index, stream_class->event_classes->len); - return g_ptr_array_index(stream_class->event_classes, index); -} - -struct bt_event_class *bt_stream_class_borrow_event_class_by_id( - struct bt_stream_class *trace, uint64_t id) -{ - struct bt_event_class *event_class = NULL; - uint64_t i; - - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - - for (i = 0; i < trace->event_classes->len; i++) { - struct bt_event_class *event_class_candidate = - g_ptr_array_index(trace->event_classes, i); - - if (event_class_candidate->id == id) { - event_class = event_class_candidate; - goto end; - } - } - -end: - return event_class; -} - -struct bt_field_type *bt_stream_class_borrow_packet_context_field_type( - struct bt_stream_class *stream_class) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - return stream_class->packet_context_ft; -} - -int bt_stream_class_set_packet_context_field_type( - struct bt_stream_class *stream_class, - struct bt_field_type *field_type) -{ - int ret; - struct bt_resolve_field_path_context resolve_ctx = { - .packet_header = NULL, - .packet_context = field_type, - .event_header = NULL, - .event_common_context = NULL, - .event_specific_context = NULL, - .event_payload = NULL, - }; - - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - BT_ASSERT_PRE_NON_NULL(field_type, "Field type"); - BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); - BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) == - BT_FIELD_TYPE_ID_STRUCTURE, - "Packet context field type is not a structure field type: %!+F", - field_type); - resolve_ctx.packet_header = - bt_stream_class_borrow_trace_inline(stream_class)->packet_header_ft; - ret = bt_resolve_field_paths(field_type, &resolve_ctx); - if (ret) { - goto end; - } - - bt_field_type_make_part_of_trace(field_type); - bt_put(stream_class->packet_context_ft); - stream_class->packet_context_ft = bt_get(field_type); - bt_field_type_freeze(field_type); - BT_LIB_LOGV("Set stream class's packet context field type: %!+S", - stream_class); - -end: - return ret; -} - -struct bt_field_type *bt_stream_class_borrow_event_header_field_type( - struct bt_stream_class *stream_class) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - return stream_class->event_header_ft; -} - -int bt_stream_class_set_event_header_field_type( - struct bt_stream_class *stream_class, - struct bt_field_type *field_type) -{ - int ret; - struct bt_resolve_field_path_context resolve_ctx = { - .packet_header = NULL, - .packet_context = NULL, - .event_header = field_type, - .event_common_context = NULL, - .event_specific_context = NULL, - .event_payload = NULL, - }; - - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - BT_ASSERT_PRE_NON_NULL(field_type, "Field type"); - BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); - BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) == - BT_FIELD_TYPE_ID_STRUCTURE, - "Event header field type is not a structure field type: %!+F", - field_type); - resolve_ctx.packet_header = - bt_stream_class_borrow_trace_inline(stream_class)->packet_header_ft; - resolve_ctx.packet_context = stream_class->packet_context_ft; - ret = bt_resolve_field_paths(field_type, &resolve_ctx); - if (ret) { - goto end; - } - - bt_field_type_make_part_of_trace(field_type); - bt_put(stream_class->event_header_ft); - stream_class->event_header_ft = bt_get(field_type); - bt_field_type_freeze(field_type); - BT_LIB_LOGV("Set stream class's event header field type: %!+S", - stream_class); - -end: - return ret; -} - -struct bt_field_type *bt_stream_class_borrow_event_common_context_field_type( - struct bt_stream_class *stream_class) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - return stream_class->event_common_context_ft; -} - -int bt_stream_class_set_event_common_context_field_type( - struct bt_stream_class *stream_class, - struct bt_field_type *field_type) -{ - int ret; - struct bt_resolve_field_path_context resolve_ctx = { - .packet_header = NULL, - .packet_context = NULL, - .event_header = NULL, - .event_common_context = field_type, - .event_specific_context = NULL, - .event_payload = NULL, - }; - - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - BT_ASSERT_PRE_NON_NULL(field_type, "Field type"); - BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); - BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) == - BT_FIELD_TYPE_ID_STRUCTURE, - "Event common context field type is not a structure field type: %!+F", - field_type); - resolve_ctx.packet_header = - bt_stream_class_borrow_trace_inline(stream_class)->packet_header_ft; - resolve_ctx.packet_context = stream_class->packet_context_ft; - resolve_ctx.event_header = stream_class->event_header_ft; - ret = bt_resolve_field_paths(field_type, &resolve_ctx); - if (ret) { - goto end; - } - - bt_field_type_make_part_of_trace(field_type); - bt_put(stream_class->event_common_context_ft); - stream_class->event_common_context_ft = bt_get(field_type); - bt_field_type_freeze(field_type); - BT_LIB_LOGV("Set stream class's event common context field type: %!+S", - stream_class); - -end: - return ret; -} - -BT_HIDDEN -void _bt_stream_class_freeze(struct bt_stream_class *stream_class) -{ - /* The field types and default clock class are already frozen */ - BT_ASSERT(stream_class); - BT_LIB_LOGD("Freezing stream class: %!+S", stream_class); - stream_class->frozen = true; -} - -int bt_stream_class_set_default_clock_class( - struct bt_stream_class *stream_class, - struct bt_clock_class *clock_class) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); - BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); - bt_put(stream_class->default_clock_class); - stream_class->default_clock_class = bt_get(clock_class); - bt_clock_class_freeze(clock_class); - BT_LIB_LOGV("Set stream class's default clock class: %!+S", - stream_class); - return 0; -} - -struct bt_clock_class *bt_stream_class_borrow_default_clock_class( - struct bt_stream_class *stream_class) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - return stream_class->default_clock_class; -} - -bt_bool bt_stream_class_assigns_automatic_event_class_id( - struct bt_stream_class *stream_class) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - return (bt_bool) stream_class->assigns_automatic_event_class_id; -} - -int bt_stream_class_set_assigns_automatic_event_class_id( - struct bt_stream_class *stream_class, bt_bool value) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); - stream_class->assigns_automatic_event_class_id = (bool) value; - BT_LIB_LOGV("Set stream class's automatic event class ID " - "assignment property: %!+S", stream_class); - return 0; -} - -bt_bool bt_stream_class_assigns_automatic_stream_id( - struct bt_stream_class *stream_class) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - return (bt_bool) stream_class->assigns_automatic_stream_id; -} - -int bt_stream_class_set_assigns_automatic_stream_id( - struct bt_stream_class *stream_class, bt_bool value) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); - stream_class->assigns_automatic_stream_id = (bool) value; - BT_LIB_LOGV("Set stream class's automatic stream ID " - "assignment property: %!+S", stream_class); - return 0; -} - -bt_bool bt_stream_class_packets_have_discarded_event_counter_snapshot( - struct bt_stream_class *stream_class) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - return (bt_bool) stream_class->packets_have_discarded_event_counter_snapshot; -} - -int bt_stream_class_set_packets_have_discarded_event_counter_snapshot( - struct bt_stream_class *stream_class, bt_bool value) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); - stream_class->packets_have_discarded_event_counter_snapshot = - (bool) value; - BT_LIB_LOGV("Set stream class's " - "\"packets have discarded event counter snapshot\" property: " - "%!+S", stream_class); - return 0; -} - -bt_bool bt_stream_class_packets_have_packet_counter_snapshot( - struct bt_stream_class *stream_class) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - return (bt_bool) stream_class->packets_have_packet_counter_snapshot; -} - -int bt_stream_class_set_packets_have_packet_counter_snapshot( - struct bt_stream_class *stream_class, bt_bool value) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); - stream_class->packets_have_packet_counter_snapshot = - (bool) value; - BT_LIB_LOGV("Set stream class's " - "\"packets have packet counter snapshot\" property: " - "%!+S", stream_class); - return 0; -} - -bt_bool bt_stream_class_packets_have_default_beginning_clock_value( - struct bt_stream_class *stream_class) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - return (bt_bool) stream_class->packets_have_default_beginning_cv; -} - -int bt_stream_class_set_packets_have_default_beginning_clock_value( - struct bt_stream_class *stream_class, bt_bool value) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); - BT_ASSERT_PRE(!value || stream_class->default_clock_class, - "Stream class does not have a default clock class: %!+S", - stream_class); - stream_class->packets_have_default_beginning_cv = (bool) value; - BT_LIB_LOGV("Set stream class's " - "\"packets have default beginning clock value\" property: " - "%!+S", stream_class); - return 0; -} - -bt_bool bt_stream_class_packets_have_default_end_clock_value( - struct bt_stream_class *stream_class) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - return (bt_bool) stream_class->packets_have_default_end_cv; -} - -int bt_stream_class_set_packets_have_default_end_clock_value( - struct bt_stream_class *stream_class, bt_bool value) -{ - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); - BT_ASSERT_PRE(!value || stream_class->default_clock_class, - "Stream class does not have a default clock class: %!+S", - stream_class); - stream_class->packets_have_default_end_cv = (bool) value; - BT_LIB_LOGV("Set stream class's " - "\"packets have default end clock value\" property: " - "%!+S", stream_class); - return 0; -} - -bt_bool bt_stream_class_default_clock_is_always_known( - struct bt_stream_class *stream_class) -{ - /* BT_CLOCK_VALUE_STATUS_UNKNOWN is not supported as of 2.0 */ - return BT_TRUE; -} diff --git a/lib/ctf-ir/stream.c b/lib/ctf-ir/stream.c deleted file mode 100644 index 665347a2..00000000 --- a/lib/ctf-ir/stream.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * stream.c - * - * Babeltrace CTF IR - Stream - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "STREAM" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BT_ASSERT_PRE_STREAM_HOT(_stream) \ - BT_ASSERT_PRE_HOT((_stream), "Stream", ": %!+s", (_stream)) - -static -void destroy_stream(struct bt_object *obj) -{ - struct bt_stream *stream = (void *) obj; - - BT_LIB_LOGD("Destroying stream object: %!+s", stream); - - if (stream->name.str) { - g_string_free(stream->name.str, TRUE); - } - - bt_object_pool_finalize(&stream->packet_pool); - g_free(stream); -} - -static -void bt_stream_free_packet(struct bt_packet *packet, struct bt_stream *stream) -{ - bt_packet_destroy(packet); -} - -BT_ASSERT_PRE_FUNC -static inline -bool stream_id_is_unique(struct bt_trace *trace, - struct bt_stream_class *stream_class, uint64_t id) -{ - uint64_t i; - bool is_unique = true; - - for (i = 0; i < trace->streams->len; i++) { - struct bt_stream *stream = trace->streams->pdata[i]; - - if (stream->class != stream_class) { - continue; - } - - if (stream->id == id) { - is_unique = false; - goto end; - } - } - -end: - return is_unique; -} - -static -struct bt_stream *create_stream_with_id(struct bt_stream_class *stream_class, - uint64_t id) -{ - int ret; - struct bt_stream *stream; - struct bt_trace *trace; - - BT_ASSERT(stream_class); - trace = bt_stream_class_borrow_trace_inline(stream_class); - BT_ASSERT_PRE(stream_id_is_unique(trace, stream_class, id), - "Duplicate stream ID: %![trace-]+t, id=%" PRIu64, trace, id); - BT_ASSERT_PRE(!trace->is_static, - "Trace is static: %![trace-]+t", trace); - BT_LIB_LOGD("Creating stream object: %![trace-]+t, id=%" PRIu64, - trace, id); - stream = g_new0(struct bt_stream, 1); - if (!stream) { - BT_LOGE_STR("Failed to allocate one stream."); - goto error; - } - - bt_object_init_shared_with_parent(&stream->base, destroy_stream); - stream->name.str = g_string_new(NULL); - if (!stream->name.str) { - BT_LOGE_STR("Failed to allocate a GString."); - goto error; - } - - stream->id = id; - ret = bt_object_pool_initialize(&stream->packet_pool, - (bt_object_pool_new_object_func) bt_packet_new, - (bt_object_pool_destroy_object_func) bt_stream_free_packet, - stream); - if (ret) { - BT_LOGE("Failed to initialize packet pool: ret=%d", ret); - goto error; - } - - stream->class = stream_class; - bt_trace_add_stream(trace, stream); - bt_stream_class_freeze(stream_class); - BT_LIB_LOGD("Created stream object: %!+s", stream); - goto end; - -error: - BT_PUT(stream); - -end: - return stream; -} - -struct bt_stream *bt_stream_create(struct bt_stream_class *stream_class) -{ - uint64_t id; - - BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); - BT_ASSERT_PRE(stream_class->assigns_automatic_stream_id, - "Stream class does not automatically assigns stream IDs: " - "%![sc-]+S", stream_class); - id = bt_trace_get_automatic_stream_id( - bt_stream_class_borrow_trace_inline(stream_class), - stream_class); - return create_stream_with_id(stream_class, id); -} - -struct bt_stream *bt_stream_create_with_id(struct bt_stream_class *stream_class, - uint64_t id) -{ - BT_ASSERT_PRE(!stream_class->assigns_automatic_stream_id, - "Stream class automatically assigns stream IDs: " - "%![sc-]+S", stream_class); - return create_stream_with_id(stream_class, id); -} - -struct bt_stream_class *bt_stream_borrow_class(struct bt_stream *stream) -{ - BT_ASSERT_PRE_NON_NULL(stream, "Stream"); - return stream->class; -} - -const char *bt_stream_get_name(struct bt_stream *stream) -{ - BT_ASSERT_PRE_NON_NULL(stream, "Stream class"); - return stream->name.value; -} - -int bt_stream_set_name(struct bt_stream *stream, const char *name) -{ - BT_ASSERT_PRE_NON_NULL(stream, "Clock class"); - BT_ASSERT_PRE_NON_NULL(name, "Name"); - BT_ASSERT_PRE_STREAM_HOT(stream); - g_string_assign(stream->name.str, name); - stream->name.value = stream->name.str->str; - BT_LIB_LOGV("Set stream class's name: %!+S", stream); - return 0; -} - -uint64_t bt_stream_get_id(struct bt_stream *stream) -{ - BT_ASSERT_PRE_NON_NULL(stream, "Stream class"); - return stream->id; -} - -BT_HIDDEN -void _bt_stream_freeze(struct bt_stream *stream) -{ - /* The field types and default clock class are already frozen */ - BT_ASSERT(stream); - BT_LIB_LOGD("Freezing stream: %!+s", stream); - stream->frozen = true; -} diff --git a/lib/ctf-ir/trace.c b/lib/ctf-ir/trace.c deleted file mode 100644 index 69189c44..00000000 --- a/lib/ctf-ir/trace.c +++ /dev/null @@ -1,660 +0,0 @@ -/* - * trace.c - * - * Babeltrace CTF IR - Trace - * - * Copyright 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "TRACE" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct bt_trace_is_static_listener_elem { - bt_trace_is_static_listener func; - bt_trace_listener_removed removed; - void *data; -}; - -#define BT_ASSERT_PRE_TRACE_HOT(_trace) \ - BT_ASSERT_PRE_HOT((_trace), "Trace", ": %!+t", (_trace)) - -static -void destroy_trace(struct bt_object *obj) -{ - struct bt_trace *trace = (void *) obj; - - BT_LIB_LOGD("Destroying trace object: %!+t", trace); - - /* - * Call remove listeners first so that everything else still - * exists in the trace. - */ - if (trace->is_static_listeners) { - size_t i; - - for (i = 0; i < trace->is_static_listeners->len; i++) { - struct bt_trace_is_static_listener_elem elem = - g_array_index(trace->is_static_listeners, - struct bt_trace_is_static_listener_elem, i); - - if (elem.removed) { - elem.removed(trace, elem.data); - } - } - - g_array_free(trace->is_static_listeners, TRUE); - } - - bt_object_pool_finalize(&trace->packet_header_field_pool); - - if (trace->environment) { - BT_LOGD_STR("Destroying environment attributes."); - bt_attributes_destroy(trace->environment); - } - - if (trace->name.str) { - g_string_free(trace->name.str, TRUE); - } - - if (trace->streams) { - BT_LOGD_STR("Destroying streams."); - g_ptr_array_free(trace->streams, TRUE); - } - - if (trace->stream_classes) { - BT_LOGD_STR("Destroying stream classes."); - g_ptr_array_free(trace->stream_classes, TRUE); - } - - if (trace->stream_classes_stream_count) { - g_hash_table_destroy(trace->stream_classes_stream_count); - } - - BT_LOGD_STR("Putting packet header field type."); - bt_put(trace->packet_header_ft); - g_free(trace); -} - -static -void free_packet_header_field(struct bt_field_wrapper *field_wrapper, - struct bt_trace *trace) -{ - bt_field_wrapper_destroy(field_wrapper); -} - -struct bt_trace *bt_trace_create(void) -{ - struct bt_trace *trace = NULL; - int ret; - - BT_LOGD_STR("Creating default trace object."); - trace = g_new0(struct bt_trace, 1); - if (!trace) { - BT_LOGE_STR("Failed to allocate one trace."); - goto error; - } - - bt_object_init_shared_with_parent(&trace->base, destroy_trace); - trace->streams = g_ptr_array_new_with_free_func( - (GDestroyNotify) bt_object_try_spec_release); - if (!trace->streams) { - BT_LOGE_STR("Failed to allocate one GPtrArray."); - goto error; - } - - trace->stream_classes = g_ptr_array_new_with_free_func( - (GDestroyNotify) bt_object_try_spec_release); - if (!trace->stream_classes) { - BT_LOGE_STR("Failed to allocate one GPtrArray."); - goto error; - } - - trace->stream_classes_stream_count = g_hash_table_new(g_direct_hash, - g_direct_equal); - if (!trace->stream_classes_stream_count) { - BT_LOGE_STR("Failed to allocate one GHashTable."); - goto error; - } - - trace->name.str = g_string_new(NULL); - if (!trace->name.str) { - BT_LOGE_STR("Failed to allocate one GString."); - goto error; - } - - trace->environment = bt_attributes_create(); - if (!trace->environment) { - BT_LOGE_STR("Cannot create empty attributes object."); - goto error; - } - - trace->is_static_listeners = g_array_new(FALSE, TRUE, - sizeof(struct bt_trace_is_static_listener_elem)); - if (!trace->is_static_listeners) { - BT_LOGE_STR("Failed to allocate one GArray."); - goto error; - } - - trace->assigns_automatic_stream_class_id = true; - ret = bt_object_pool_initialize(&trace->packet_header_field_pool, - (bt_object_pool_new_object_func) bt_field_wrapper_new, - (bt_object_pool_destroy_object_func) free_packet_header_field, - trace); - if (ret) { - BT_LOGE("Failed to initialize packet header field pool: ret=%d", - ret); - goto error; - } - - BT_LIB_LOGD("Created trace object: %!+t", trace); - goto end; - -error: - BT_PUT(trace); - -end: - return trace; -} - -const char *bt_trace_get_name(struct bt_trace *trace) -{ - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - return trace->name.value; -} - -int bt_trace_set_name(struct bt_trace *trace, const char *name) -{ - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - BT_ASSERT_PRE_NON_NULL(name, "Name"); - BT_ASSERT_PRE_TRACE_HOT(trace); - g_string_assign(trace->name.str, name); - trace->name.value = trace->name.str->str; - BT_LIB_LOGV("Set trace's name: %!+t", trace); - return 0; -} - -bt_uuid bt_trace_get_uuid(struct bt_trace *trace) -{ - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - return trace->uuid.value; -} - -int bt_trace_set_uuid(struct bt_trace *trace, bt_uuid uuid) -{ - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - BT_ASSERT_PRE_NON_NULL(uuid, "UUID"); - BT_ASSERT_PRE_TRACE_HOT(trace); - memcpy(trace->uuid.uuid, uuid, BABELTRACE_UUID_LEN); - trace->uuid.value = trace->uuid.uuid; - BT_LIB_LOGV("Set trace's UUID: %!+t", trace); - return 0; -} - -BT_ASSERT_FUNC -static -bool trace_has_environment_entry(struct bt_trace *trace, const char *name) -{ - struct bt_value *attribute; - - BT_ASSERT(trace); - - attribute = bt_attributes_borrow_field_value_by_name( - trace->environment, name); - return attribute != NULL; -} - -static -int set_environment_entry(struct bt_trace *trace, const char *name, - struct bt_value *value) -{ - int ret; - - BT_ASSERT(trace); - BT_ASSERT(name); - BT_ASSERT(value); - BT_ASSERT_PRE(!trace->frozen || - !trace_has_environment_entry(trace, name), - "Trace is frozen: cannot replace environment entry: " - "%![trace-]+t, entry-name=\"%s\"", trace, name); - ret = bt_attributes_set_field_value(trace->environment, name, - value); - bt_value_freeze(value); - if (ret) { - BT_LIB_LOGE("Cannot set trace's environment entry: " - "%![trace-]+t, entry-name=\"%s\"", trace, name); - } else { - BT_LIB_LOGV("Set trace's environment entry: " - "%![trace-]+t, entry-name=\"%s\"", trace, name); - } - - return ret; -} - -int bt_trace_set_environment_entry_string(struct bt_trace *trace, - const char *name, const char *value) -{ - int ret; - struct bt_value *value_obj; - - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - BT_ASSERT_PRE_NON_NULL(name, "Name"); - BT_ASSERT_PRE_NON_NULL(value, "Value"); - value_obj = bt_value_string_create_init(value); - if (!value_obj) { - BT_LOGE_STR("Cannot create a string value object."); - ret = -1; - goto end; - } - - /* set_environment_entry() logs errors */ - ret = set_environment_entry(trace, name, value_obj); - -end: - bt_put(value_obj); - return ret; -} - -int bt_trace_set_environment_entry_integer( - struct bt_trace *trace, const char *name, int64_t value) -{ - int ret; - struct bt_value *value_obj; - - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - BT_ASSERT_PRE_NON_NULL(name, "Name"); - value_obj = bt_value_integer_create_init(value); - if (!value_obj) { - BT_LOGE_STR("Cannot create an integer value object."); - ret = -1; - goto end; - } - - /* set_environment_entry() logs errors */ - ret = set_environment_entry(trace, name, value_obj); - -end: - bt_put(value_obj); - return ret; -} - -uint64_t bt_trace_get_environment_entry_count(struct bt_trace *trace) -{ - int64_t ret; - - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - ret = bt_attributes_get_count(trace->environment); - BT_ASSERT(ret >= 0); - return (uint64_t) ret; -} - -void bt_trace_borrow_environment_entry_by_index( - struct bt_trace *trace, uint64_t index, - const char **name, struct bt_value **value) -{ - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - BT_ASSERT_PRE_NON_NULL(name, "Name"); - BT_ASSERT_PRE_NON_NULL(value, "Value"); - BT_ASSERT_PRE_VALID_INDEX(index, - bt_attributes_get_count(trace->environment)); - *value = bt_attributes_borrow_field_value(trace->environment, index); - BT_ASSERT(*value); - *name = bt_attributes_get_field_name(trace->environment, index); - BT_ASSERT(*name); -} - -struct bt_value *bt_trace_borrow_environment_entry_value_by_name( - struct bt_trace *trace, const char *name) -{ - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - BT_ASSERT_PRE_NON_NULL(name, "Name"); - return bt_attributes_borrow_field_value_by_name(trace->environment, - name); -} - -uint64_t bt_trace_get_stream_count(struct bt_trace *trace) -{ - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - return (uint64_t) trace->streams->len; -} - -struct bt_stream *bt_trace_borrow_stream_by_index( - struct bt_trace *trace, uint64_t index) -{ - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - BT_ASSERT_PRE_VALID_INDEX(index, trace->streams->len); - return g_ptr_array_index(trace->streams, index); -} - -struct bt_stream *bt_trace_borrow_stream_by_id( - struct bt_trace *trace, uint64_t id) -{ - struct bt_stream *stream = NULL; - uint64_t i; - - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - - for (i = 0; i < trace->streams->len; i++) { - struct bt_stream *stream_candidate = - g_ptr_array_index(trace->streams, i); - - if (stream_candidate->id == id) { - stream = stream_candidate; - goto end; - } - } - -end: - return stream; -} - -uint64_t bt_trace_get_stream_class_count(struct bt_trace *trace) -{ - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - return (uint64_t) trace->stream_classes->len; -} - -struct bt_stream_class *bt_trace_borrow_stream_class_by_index( - struct bt_trace *trace, uint64_t index) -{ - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - BT_ASSERT_PRE_VALID_INDEX(index, trace->stream_classes->len); - return g_ptr_array_index(trace->stream_classes, index); -} - -struct bt_stream_class *bt_trace_borrow_stream_class_by_id( - struct bt_trace *trace, uint64_t id) -{ - struct bt_stream_class *stream_class = NULL; - uint64_t i; - - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - - for (i = 0; i < trace->stream_classes->len; i++) { - struct bt_stream_class *stream_class_candidate = - g_ptr_array_index(trace->stream_classes, i); - - if (stream_class_candidate->id == id) { - stream_class = stream_class_candidate; - goto end; - } - } - -end: - return stream_class; -} - -struct bt_field_type *bt_trace_borrow_packet_header_field_type( - struct bt_trace *trace) -{ - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - return trace->packet_header_ft; -} - -int bt_trace_set_packet_header_field_type(struct bt_trace *trace, - struct bt_field_type *field_type) -{ - int ret; - struct bt_resolve_field_path_context resolve_ctx = { - .packet_header = field_type, - .packet_context = NULL, - .event_header = NULL, - .event_common_context = NULL, - .event_specific_context = NULL, - .event_payload = NULL, - }; - - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - BT_ASSERT_PRE_NON_NULL(field_type, "Field type"); - BT_ASSERT_PRE_TRACE_HOT(trace); - BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) == - BT_FIELD_TYPE_ID_STRUCTURE, - "Packet header field type is not a structure field type: %!+F", - field_type); - ret = bt_resolve_field_paths(field_type, &resolve_ctx); - if (ret) { - goto end; - } - - bt_field_type_make_part_of_trace(field_type); - bt_put(trace->packet_header_ft); - trace->packet_header_ft = bt_get(field_type); - bt_field_type_freeze(field_type); - BT_LIB_LOGV("Set trace's packet header field type: %!+t", trace); - -end: - return ret; -} - -bt_bool bt_trace_is_static(struct bt_trace *trace) -{ - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - return (bt_bool) trace->is_static; -} - -int bt_trace_make_static(struct bt_trace *trace) -{ - uint64_t i; - - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - trace->is_static = true; - bt_trace_freeze(trace); - BT_LIB_LOGV("Trace is now static: %!+t", trace); - - /* Call all the "trace is static" listeners */ - for (i = 0; i < trace->is_static_listeners->len; i++) { - struct bt_trace_is_static_listener_elem elem = - g_array_index(trace->is_static_listeners, - struct bt_trace_is_static_listener_elem, i); - - if (elem.func) { - elem.func(trace, elem.data); - } - } - - return 0; -} - -int bt_trace_add_is_static_listener(struct bt_trace *trace, - bt_trace_is_static_listener listener, - bt_trace_listener_removed listener_removed, void *data, - uint64_t *listener_id) -{ - uint64_t i; - struct bt_trace_is_static_listener_elem new_elem = { - .func = listener, - .removed = listener_removed, - .data = data, - }; - - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - BT_ASSERT_PRE_NON_NULL(listener, "Listener"); - BT_ASSERT_PRE(!trace->is_static, - "Trace is already static: %!+t", trace); - BT_ASSERT_PRE(trace->in_remove_listener, - "Cannot call this function while executing a " - "remove listener: %!+t", trace); - - /* Find the next available spot */ - for (i = 0; i < trace->is_static_listeners->len; i++) { - struct bt_trace_is_static_listener_elem elem = - g_array_index(trace->is_static_listeners, - struct bt_trace_is_static_listener_elem, i); - - if (!elem.func) { - break; - } - } - - if (i == trace->is_static_listeners->len) { - g_array_append_val(trace->is_static_listeners, new_elem); - } else { - g_array_insert_val(trace->is_static_listeners, i, new_elem); - } - - if (listener_id) { - *listener_id = i; - } - - BT_LIB_LOGV("Added \"trace is static\" listener: " - "%![trace-]+t, listener-id=%" PRIu64, trace, i); - return 0; -} - -BT_ASSERT_PRE_FUNC -static -bool has_listener_id(struct bt_trace *trace, uint64_t listener_id) -{ - BT_ASSERT(listener_id < trace->is_static_listeners->len); - return (&g_array_index(trace->is_static_listeners, - struct bt_trace_is_static_listener_elem, - listener_id))->func != NULL; -} - -int bt_trace_remove_is_static_listener( - struct bt_trace *trace, uint64_t listener_id) -{ - struct bt_trace_is_static_listener_elem *elem; - - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - BT_ASSERT_PRE(!trace->is_static, - "Trace is already static: %!+t", trace); - BT_ASSERT_PRE(trace->in_remove_listener, - "Cannot call this function while executing a " - "remove listener: %!+t", trace); - BT_ASSERT_PRE(has_listener_id(trace, listener_id), - "Trace has no such \"trace is static\" listener ID: " - "%![trace-]+t, %" PRIu64, trace, listener_id); - elem = &g_array_index(trace->is_static_listeners, - struct bt_trace_is_static_listener_elem, - listener_id); - BT_ASSERT(elem->func); - - if (elem->removed) { - /* Call remove listener */ - BT_LIB_LOGV("Calling remove listener: " - "%![trace-]+t, listener-id=%" PRIu64, - trace, listener_id); - trace->in_remove_listener = true; - elem->removed(trace, elem->data); - trace->in_remove_listener = false; - } - - elem->func = NULL; - elem->removed = NULL; - elem->data = NULL; - BT_LIB_LOGV("Removed \"trace is static\" listener: " - "%![trace-]+t, listener-id=%" PRIu64, - trace, listener_id); - return 0; -} - -BT_HIDDEN -void _bt_trace_freeze(struct bt_trace *trace) -{ - /* The packet header field type is already frozen */ - BT_ASSERT(trace); - BT_LIB_LOGD("Freezing trace: %!+t", trace); - trace->frozen = true; -} - -bt_bool bt_trace_assigns_automatic_stream_class_id(struct bt_trace *trace) -{ - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - return (bt_bool) trace->assigns_automatic_stream_class_id; -} - -int bt_trace_set_assigns_automatic_stream_class_id( - struct bt_trace *trace, bt_bool value) -{ - BT_ASSERT_PRE_NON_NULL(trace, "Trace"); - BT_ASSERT_PRE_TRACE_HOT(trace); - trace->assigns_automatic_stream_class_id = (bool) value; - BT_LIB_LOGV("Set trace's automatic stream class ID " - "assignment property: %!+t", trace); - return 0; -} - -BT_HIDDEN -void bt_trace_add_stream(struct bt_trace *trace, struct bt_stream *stream) -{ - guint count = 0; - - bt_object_set_parent(&stream->base, &trace->base); - g_ptr_array_add(trace->streams, stream); - bt_trace_freeze(trace); - - if (bt_g_hash_table_contains(trace->stream_classes_stream_count, - stream->class)) { - count = GPOINTER_TO_UINT(g_hash_table_lookup( - trace->stream_classes_stream_count, stream->class)); - } - - g_hash_table_insert(trace->stream_classes_stream_count, - stream->class, GUINT_TO_POINTER(count + 1)); -} - -BT_HIDDEN -uint64_t bt_trace_get_automatic_stream_id(struct bt_trace *trace, - struct bt_stream_class *stream_class) -{ - gpointer orig_key; - gpointer value; - uint64_t id = 0; - - BT_ASSERT(stream_class); - BT_ASSERT(trace); - if (g_hash_table_lookup_extended(trace->stream_classes_stream_count, - stream_class, &orig_key, &value)) { - id = (uint64_t) GPOINTER_TO_UINT(value); - } - - return id; -} diff --git a/lib/ctf-ir/utils.c b/lib/ctf-ir/utils.c deleted file mode 100644 index 41337cfd..00000000 --- a/lib/ctf-ir/utils.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * utils.c - * - * Babeltrace CTF IR - Utilities - * - * Copyright 2015 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define BT_LOG_TAG "CTF-IR-UTILS" -#include - -#include -#include -#include -#include -#include -#include diff --git a/lib/graph/iterator.c b/lib/graph/iterator.c index fcc00100..a2111746 100644 --- a/lib/graph/iterator.c +++ b/lib/graph/iterator.c @@ -30,12 +30,12 @@ #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include diff --git a/lib/graph/notification/event.c b/lib/graph/notification/event.c index 4b50d7fe..d8178eca 100644 --- a/lib/graph/notification/event.c +++ b/lib/graph/notification/event.c @@ -29,11 +29,11 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include #include diff --git a/lib/graph/notification/inactivity.c b/lib/graph/notification/inactivity.c index 9523bb86..becf17e0 100644 --- a/lib/graph/notification/inactivity.c +++ b/lib/graph/notification/inactivity.c @@ -25,8 +25,8 @@ #include #include -#include -#include +#include +#include #include #include #include diff --git a/lib/graph/notification/packet.c b/lib/graph/notification/packet.c index 70694e96..8e02201d 100644 --- a/lib/graph/notification/packet.c +++ b/lib/graph/notification/packet.c @@ -28,11 +28,11 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include #include diff --git a/lib/graph/notification/stream.c b/lib/graph/notification/stream.c index e6015c25..fbb0cc78 100644 --- a/lib/graph/notification/stream.c +++ b/lib/graph/notification/stream.c @@ -29,9 +29,9 @@ #include #include -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/lib/lib-logging.c b/lib/lib-logging.c index d09b176d..56b41fc6 100644 --- a/lib/lib-logging.c +++ b/lib/lib-logging.c @@ -34,18 +34,18 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include diff --git a/lib/trace-ir/Makefile.am b/lib/trace-ir/Makefile.am new file mode 100644 index 00000000..f2e1c3d0 --- /dev/null +++ b/lib/trace-ir/Makefile.am @@ -0,0 +1,23 @@ +noinst_LTLIBRARIES = libtrace-ir.la + +libtrace_ir_la_SOURCES = \ + attributes.c \ + clock-class.c \ + clock-value.c \ + event.c \ + event-class.c \ + event-header-field.c \ + field-wrapper.c \ + fields.c \ + field-types.c \ + field-path.c \ + packet.c \ + packet-context-field.c \ + packet-header-field.c \ + resolve-field-path.c \ + stream.c \ + stream-class.c \ + trace.c \ + utils.c + +libtrace_ir_la_LIBADD = $(UUID_LIBS) diff --git a/lib/trace-ir/attributes.c b/lib/trace-ir/attributes.c new file mode 100644 index 00000000..d43fd649 --- /dev/null +++ b/lib/trace-ir/attributes.c @@ -0,0 +1,350 @@ +/* + * attributes.c + * + * Babeltrace trace IR - Attributes + * + * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation + * Copyright (c) 2015 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "ATTRS" +#include + +#include +#include +#include +#include +#include +#include +#include + +#define BT_ATTR_NAME_INDEX 0 +#define BT_ATTR_VALUE_INDEX 1 + +BT_HIDDEN +struct bt_value *bt_attributes_create(void) +{ + struct bt_value *attr_obj; + + /* + * Attributes: array value object of array value objects, each one + * containing two entries: a string value object (attributes + * field name), and a value object (attributes field value). + * + * Example (JSON representation): + * + * [ + * ["hostname", "eeppdesk"], + * ["sysname", "Linux"], + * ["tracer_major", 2], + * ["tracer_minor", 5] + * ] + */ + BT_LOGD_STR("Creating attributes object."); + attr_obj = bt_value_array_create(); + if (!attr_obj) { + BT_LOGE_STR("Failed to create array value."); + } else { + BT_LOGD("Created attributes object: addr=%p", + attr_obj); + } + + return attr_obj; +} + +BT_HIDDEN +void bt_attributes_destroy(struct bt_value *attr_obj) +{ + BT_LOGD("Destroying attributes object: addr=%p", attr_obj); + bt_put(attr_obj); +} + +BT_HIDDEN +int64_t bt_attributes_get_count(struct bt_value *attr_obj) +{ + return bt_value_array_size(attr_obj); +} + +BT_HIDDEN +const char *bt_attributes_get_field_name(struct bt_value *attr_obj, + uint64_t index) +{ + int rc; + const char *ret = NULL; + struct bt_value *attr_field_obj = NULL; + struct bt_value *attr_field_name_obj = NULL; + + if (!attr_obj) { + BT_LOGW_STR("Invalid parameter: attributes object is NULL."); + goto end; + } + + if (index >= bt_value_array_size(attr_obj)) { + BT_LOGW("Invalid parameter: index is out of bounds: " + "index=%" PRIu64 ", count=%" PRId64, + index, bt_value_array_size(attr_obj)); + goto end; + } + + attr_field_obj = bt_value_array_borrow(attr_obj, index); + if (!attr_field_obj) { + BT_LOGE("Cannot get attributes object's array value's element by index: " + "value-addr=%p, index=%" PRIu64, attr_obj, index); + goto end; + } + + attr_field_name_obj = bt_value_array_borrow(attr_field_obj, + BT_ATTR_NAME_INDEX); + if (!attr_field_name_obj) { + BT_LOGE("Cannot get attribute array value's element by index: " + "value-addr=%p, index=%" PRIu64, attr_field_obj, + (uint64_t) BT_ATTR_NAME_INDEX); + goto end; + } + + rc = bt_value_string_get(attr_field_name_obj, &ret); + if (rc) { + BT_LOGE("Cannot get raw value from string value: value-addr=%p", + attr_field_name_obj); + ret = NULL; + } + +end: + return ret; +} + +BT_HIDDEN +struct bt_value *bt_attributes_borrow_field_value(struct bt_value *attr_obj, + uint64_t index) +{ + struct bt_value *value_obj = NULL; + struct bt_value *attr_field_obj = NULL; + + if (!attr_obj) { + BT_LOGW_STR("Invalid parameter: attributes object is NULL."); + goto end; + } + + if (index >= bt_value_array_size(attr_obj)) { + BT_LOGW("Invalid parameter: index is out of bounds: " + "index=%" PRIu64 ", count=%" PRId64, + index, bt_value_array_size(attr_obj)); + goto end; + } + + attr_field_obj = bt_value_array_borrow(attr_obj, index); + if (!attr_field_obj) { + BT_LOGE("Cannot get attributes object's array value's element by index: " + "value-addr=%p, index=%" PRIu64, attr_obj, index); + goto end; + } + + value_obj = bt_value_array_borrow(attr_field_obj, + BT_ATTR_VALUE_INDEX); + if (!value_obj) { + BT_LOGE("Cannot get attribute array value's element by index: " + "value-addr=%p, index=%" PRIu64, attr_field_obj, + (uint64_t) BT_ATTR_VALUE_INDEX); + } + +end: + return value_obj; +} + +static +struct bt_value *bt_attributes_borrow_field_by_name( + struct bt_value *attr_obj, const char *name) +{ + uint64_t i; + int64_t attr_size; + struct bt_value *value_obj = NULL; + struct bt_value *attr_field_name_obj = NULL; + + attr_size = bt_value_array_size(attr_obj); + if (attr_size < 0) { + BT_LOGE("Cannot get array value's size: value-addr=%p", + attr_obj); + goto error; + } + + for (i = 0; i < attr_size; ++i) { + int ret; + const char *field_name; + + value_obj = bt_value_array_borrow(attr_obj, i); + if (!value_obj) { + BT_LOGE("Cannot get attributes object's array value's element by index: " + "value-addr=%p, index=%" PRIu64, attr_obj, i); + goto error; + } + + attr_field_name_obj = bt_value_array_borrow(value_obj, + BT_ATTR_NAME_INDEX); + if (!attr_field_name_obj) { + BT_LOGE("Cannot get attribute array value's element by index: " + "value-addr=%p, index=%" PRIu64, + value_obj, (int64_t) BT_ATTR_NAME_INDEX); + goto error; + } + + ret = bt_value_string_get(attr_field_name_obj, &field_name); + if (ret) { + BT_LOGE("Cannot get raw value from string value: value-addr=%p", + attr_field_name_obj); + goto error; + } + + if (!strcmp(field_name, name)) { + break; + } + + value_obj = NULL; + } + + return value_obj; + +error: + value_obj = NULL; + return value_obj; +} + +BT_HIDDEN +int bt_attributes_set_field_value(struct bt_value *attr_obj, + const char *name, struct bt_value *value_obj) +{ + int ret = 0; + struct bt_value *attr_field_obj = NULL; + + if (!attr_obj || !name || !value_obj) { + BT_LOGW("Invalid parameter: attributes object, name, or value object is NULL: " + "attr-value-addr=%p, name-addr=%p, value-addr=%p", + attr_obj, name, value_obj); + ret = -1; + goto end; + } + + attr_field_obj = bt_attributes_borrow_field_by_name(attr_obj, name); + if (attr_field_obj) { + ret = bt_value_array_set(attr_field_obj, + BT_ATTR_VALUE_INDEX, value_obj); + attr_field_obj = NULL; + goto end; + } + + attr_field_obj = bt_value_array_create(); + if (!attr_field_obj) { + BT_LOGE_STR("Failed to create empty array value."); + ret = -1; + goto end; + } + + ret = bt_value_array_append_string(attr_field_obj, name); + ret |= bt_value_array_append(attr_field_obj, value_obj); + if (ret) { + BT_LOGE("Cannot append elements to array value: addr=%p", + attr_field_obj); + goto end; + } + + ret = bt_value_array_append(attr_obj, attr_field_obj); + if (ret) { + BT_LOGE("Cannot append element to array value: " + "array-value-addr=%p, element-value-addr=%p", + attr_obj, attr_field_obj); + } + +end: + bt_put(attr_field_obj); + return ret; +} + +BT_HIDDEN +struct bt_value *bt_attributes_borrow_field_value_by_name( + struct bt_value *attr_obj, const char *name) +{ + struct bt_value *value_obj = NULL; + struct bt_value *attr_field_obj = NULL; + + if (!attr_obj || !name) { + BT_LOGW("Invalid parameter: attributes object or name is NULL: " + "value-addr=%p, name-addr=%p", attr_obj, name); + goto end; + } + + attr_field_obj = bt_attributes_borrow_field_by_name(attr_obj, name); + if (!attr_field_obj) { + BT_LOGD("Cannot find attributes object's field by name: " + "value-addr=%p, name=\"%s\"", attr_obj, name); + goto end; + } + + value_obj = bt_value_array_borrow(attr_field_obj, + BT_ATTR_VALUE_INDEX); + if (!value_obj) { + BT_LOGE("Cannot get attribute array value's element by index: " + "value-addr=%p, index=%" PRIu64, attr_field_obj, + (uint64_t) BT_ATTR_VALUE_INDEX); + } + +end: + return value_obj; +} + +BT_HIDDEN +int bt_attributes_freeze(struct bt_value *attr_obj) +{ + uint64_t i; + int64_t count; + int ret = 0; + + if (!attr_obj) { + BT_LOGW_STR("Invalid parameter: attributes object is NULL."); + ret = -1; + goto end; + } + + BT_LOGD("Freezing attributes object: value-addr=%p", attr_obj); + count = bt_value_array_size(attr_obj); + BT_ASSERT(count >= 0); + + /* + * We do not freeze the array value object itself here, since + * internal stuff could need to modify/add attributes. Each + * attribute is frozen one by one. + */ + for (i = 0; i < count; ++i) { + struct bt_value *obj = NULL; + + obj = bt_attributes_borrow_field_value(attr_obj, i); + if (!obj) { + BT_LOGE("Cannot get attributes object's field value by index: " + "value-addr=%p, index=%" PRIu64, + attr_obj, i); + ret = -1; + goto end; + } + + bt_value_freeze(obj); + } + +end: + return ret; +} diff --git a/lib/trace-ir/clock-class.c b/lib/trace-ir/clock-class.c new file mode 100644 index 00000000..c8e5f3fd --- /dev/null +++ b/lib/trace-ir/clock-class.c @@ -0,0 +1,329 @@ +/* + * clock-class.c + * + * Babeltrace trace IR - Clock class + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "CLOCK-CLASS" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BT_ASSERT_PRE_CLOCK_CLASS_HOT(_cc) \ + BT_ASSERT_PRE_HOT((_cc), "Clock class", ": %!+K", (_cc)) + +static +void destroy_clock_class(struct bt_object *obj) +{ + struct bt_clock_class *clock_class = (void *) obj; + + BT_LIB_LOGD("Destroying clock class: %!+K", clock_class); + + if (clock_class->name.str) { + g_string_free(clock_class->name.str, TRUE); + } + + if (clock_class->description.str) { + g_string_free(clock_class->description.str, TRUE); + } + + bt_object_pool_finalize(&clock_class->cv_pool); + g_free(clock_class); +} + +static +void free_clock_value(struct bt_clock_value *clock_value, + struct bt_clock_class *clock_class) +{ + bt_clock_value_destroy(clock_value); +} + +static inline +void set_base_offset(struct bt_clock_class *clock_class) +{ + uint64_t offset_cycles_ns; + + /* Initialize nanosecond timestamp to clock's offset in seconds */ + if (clock_class->offset_seconds <= (INT64_MIN / INT64_C(1000000000) - 1) || + clock_class->offset_seconds >= (INT64_MAX / INT64_C(1000000000)) - 1) { + /* + * Overflow: offset in seconds converted to nanoseconds + * is outside the int64_t range. We also subtract 1 here + * to leave "space" for the offset in cycles converted + * to nanoseconds (which is always less than 1 second by + * contract). + */ + clock_class->base_offset.overflows = true; + goto end; + } + + /* Offset (seconds) to nanoseconds */ + clock_class->base_offset.value_ns = clock_class->offset_seconds * + INT64_C(1000000000); + + /* Add offset in cycles */ + BT_ASSERT(clock_class->offset_cycles < clock_class->frequency); + offset_cycles_ns = bt_util_ns_from_value(clock_class->frequency, + clock_class->offset_cycles); + BT_ASSERT(offset_cycles_ns < 1000000000); + clock_class->base_offset.value_ns += (int64_t) offset_cycles_ns; + clock_class->base_offset.overflows = false; + +end: + return; +} + +struct bt_clock_class *bt_clock_class_create(void) +{ + int ret; + struct bt_clock_class *clock_class = NULL; + + BT_LOGD_STR("Creating default clock class object"); + + clock_class = g_new0(struct bt_clock_class, 1); + if (!clock_class) { + BT_LOGE_STR("Failed to allocate one clock class."); + goto error; + } + + bt_object_init_shared(&clock_class->base, destroy_clock_class); + clock_class->name.str = g_string_new(NULL); + if (!clock_class->name.str) { + BT_LOGE_STR("Failed to allocate a GString."); + goto error; + } + + clock_class->description.str = g_string_new(NULL); + if (!clock_class->description.str) { + BT_LOGE_STR("Failed to allocate a GString."); + goto error; + } + + clock_class->frequency = UINT64_C(1000000000); + clock_class->is_absolute = BT_TRUE; + set_base_offset(clock_class); + ret = bt_object_pool_initialize(&clock_class->cv_pool, + (bt_object_pool_new_object_func) bt_clock_value_new, + (bt_object_pool_destroy_object_func) + free_clock_value, + clock_class); + if (ret) { + BT_LOGE("Failed to initialize clock value pool: ret=%d", + ret); + goto error; + } + + BT_LIB_LOGD("Created clock class object: %!+K", clock_class); + goto end; + +error: + BT_PUT(clock_class); + +end: + return clock_class; +} + +const char *bt_clock_class_get_name( + struct bt_clock_class *clock_class) +{ + BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); + return clock_class->name.value; +} + +int bt_clock_class_set_name(struct bt_clock_class *clock_class, + const char *name) +{ + BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); + BT_ASSERT_PRE_NON_NULL(name, "Name"); + BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class); + g_string_assign(clock_class->name.str, name); + clock_class->name.value = clock_class->name.str->str; + BT_LIB_LOGV("Set clock class's name: %!+K", clock_class); + return 0; +} + +const char *bt_clock_class_get_description(struct bt_clock_class *clock_class) +{ + BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); + return clock_class->description.value; +} + +int bt_clock_class_set_description(struct bt_clock_class *clock_class, + const char *descr) +{ + BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); + BT_ASSERT_PRE_NON_NULL(descr, "Description"); + BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class); + g_string_assign(clock_class->description.str, descr); + clock_class->description.value = clock_class->description.str->str; + BT_LIB_LOGV("Set clock class's description: %!+K", + clock_class); + return 0; +} + +uint64_t bt_clock_class_get_frequency(struct bt_clock_class *clock_class) +{ + BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); + return clock_class->frequency; +} + +int bt_clock_class_set_frequency(struct bt_clock_class *clock_class, + uint64_t frequency) +{ + BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); + BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class); + BT_ASSERT_PRE(frequency != UINT64_C(-1) && frequency != 0, + "Invalid frequency: %![cc-]+K, new-freq=%" PRIu64, + clock_class, frequency); + BT_ASSERT_PRE(clock_class->offset_cycles < frequency, + "Offset (cycles) is greater than clock class's frequency: " + "%![cc-]+K, new-freq=%" PRIu64, clock_class, frequency); + clock_class->frequency = frequency; + set_base_offset(clock_class); + BT_LIB_LOGV("Set clock class's frequency: %!+K", clock_class); + return 0; +} + +uint64_t bt_clock_class_get_precision(struct bt_clock_class *clock_class) +{ + BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); + return clock_class->precision; +} + +int bt_clock_class_set_precision(struct bt_clock_class *clock_class, + uint64_t precision) +{ + BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); + BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class); + BT_ASSERT_PRE(precision != UINT64_C(-1), + "Invalid precision: %![cc-]+K, new-precision=%" PRIu64, + clock_class, precision); + clock_class->precision = precision; + BT_LIB_LOGV("Set clock class's precision: %!+K", clock_class); + return 0; +} + +void bt_clock_class_get_offset(struct bt_clock_class *clock_class, + int64_t *seconds, uint64_t *cycles) +{ + BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); + BT_ASSERT_PRE_NON_NULL(seconds, "Seconds (output)"); + BT_ASSERT_PRE_NON_NULL(cycles, "Cycles (output)"); + *seconds = clock_class->offset_seconds; + *cycles = clock_class->offset_cycles; +} + +int bt_clock_class_set_offset(struct bt_clock_class *clock_class, + int64_t seconds, uint64_t cycles) +{ + BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); + BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class); + BT_ASSERT_PRE(cycles < clock_class->frequency, + "Offset (cycles) is greater than clock class's frequency: " + "%![cc-]+K, new-offset-cycles=%" PRIu64, clock_class, cycles); + clock_class->offset_seconds = seconds; + clock_class->offset_cycles = cycles; + set_base_offset(clock_class); + BT_LIB_LOGV("Set clock class's offset: %!+K", clock_class); + return 0; +} + +bt_bool bt_clock_class_is_absolute(struct bt_clock_class *clock_class) +{ + BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); + return (bool) clock_class->is_absolute; +} + +int bt_clock_class_set_is_absolute(struct bt_clock_class *clock_class, + bt_bool is_absolute) +{ + BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); + BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class); + clock_class->is_absolute = (bool) is_absolute; + BT_LIB_LOGV("Set clock class's absolute property: %!+K", + clock_class); + return 0; +} + +bt_uuid bt_clock_class_get_uuid(struct bt_clock_class *clock_class) +{ + BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); + return clock_class->uuid.value; +} + +int bt_clock_class_set_uuid(struct bt_clock_class *clock_class, + bt_uuid uuid) +{ + BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); + BT_ASSERT_PRE_NON_NULL(uuid, "UUID"); + BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class); + memcpy(clock_class->uuid.uuid, uuid, BABELTRACE_UUID_LEN); + clock_class->uuid.value = clock_class->uuid.uuid; + BT_LIB_LOGV("Set clock class's UUID: %!+K", clock_class); + return 0; +} + +BT_HIDDEN +void _bt_clock_class_freeze(struct bt_clock_class *clock_class) +{ + BT_ASSERT(clock_class); + + if (clock_class->frozen) { + return; + } + + BT_LIB_LOGD("Freezing clock class: %!+K", clock_class); + clock_class->frozen = 1; +} + +int bt_clock_class_cycles_to_ns_from_origin(struct bt_clock_class *clock_class, + uint64_t cycles, int64_t *ns) +{ + int ret; + + BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); + BT_ASSERT_PRE_NON_NULL(ns, "Nanoseconds (output)"); + ret = bt_util_ns_from_origin(clock_class, cycles, ns); + if (ret) { + BT_LIB_LOGW("Cannot convert cycles to nanoseconds " + "from origin for given clock class: " + "value overflows the signed 64-bit integer range: " + "%![cc-]+K, cycles=%" PRIu64, + clock_class, cycles); + } + + return ret; +} diff --git a/lib/trace-ir/clock-value.c b/lib/trace-ir/clock-value.c new file mode 100644 index 00000000..97242118 --- /dev/null +++ b/lib/trace-ir/clock-value.c @@ -0,0 +1,171 @@ +/* + * Copyright 2017-2018 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "CLOCK-VALUE" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +BT_HIDDEN +void bt_clock_value_destroy(struct bt_clock_value *clock_value) +{ + BT_LIB_LOGD("Destroying clock value: %!+k", clock_value); + bt_put(clock_value->clock_class); + g_free(clock_value); +} + +BT_HIDDEN +struct bt_clock_value *bt_clock_value_new(struct bt_clock_class *clock_class) +{ + struct bt_clock_value *ret = NULL; + + BT_ASSERT(clock_class); + BT_LIB_LOGD("Creating clock value object: %![cc-]+K=", + clock_class); + ret = g_new0(struct bt_clock_value, 1); + if (!ret) { + BT_LOGE_STR("Failed to allocate one clock value."); + goto end; + } + + bt_object_init_unique(&ret->base); + ret->clock_class = bt_get(clock_class); + bt_clock_class_freeze(clock_class); + BT_LIB_LOGD("Created clock value object: %!+k", ret); + +end: + return ret; +} + +BT_HIDDEN +struct bt_clock_value *bt_clock_value_create(struct bt_clock_class *clock_class) +{ + struct bt_clock_value *clock_value = NULL; + + BT_ASSERT(clock_class); + clock_value = bt_object_pool_create_object(&clock_class->cv_pool); + if (!clock_value) { + BT_LIB_LOGE("Cannot allocate one clock value from clock class's clock value pool: " + "%![cc-]+K", clock_class); + goto error; + } + + if (likely(!clock_value->clock_class)) { + clock_value->clock_class = bt_get(clock_class); + } + + goto end; + +error: + if (clock_value) { + bt_clock_value_recycle(clock_value); + clock_value = NULL; + } + +end: + return clock_value; +} + +BT_HIDDEN +void bt_clock_value_recycle(struct bt_clock_value *clock_value) +{ + struct bt_clock_class *clock_class; + + BT_ASSERT(clock_value); + BT_LIB_LOGD("Recycling clock value: %!+k", clock_value); + + /* + * Those are the important ordered steps: + * + * 1. Reset the clock value object, but do NOT put its clock + * class's reference. This clock class contains the pool to + * which we're about to recycle this clock value object, so + * we must guarantee its existence thanks to this existing + * reference. + * + * 2. Move the clock class reference to our `clock_class` + * variable so that we can set the clock value's clock class + * member to NULL before recycling it. We CANNOT do this + * after we put the clock class reference because this + * bt_put() could destroy the clock class, also destroying + * its clock value pool, thus also destroying our clock value + * object (this would result in an invalid write access). + * + * 3. Recycle the clock value object. + * + * 4. Put our clock class reference. + */ + bt_clock_value_reset(clock_value); + clock_class = clock_value->clock_class; + BT_ASSERT(clock_class); + clock_value->clock_class = NULL; + bt_object_pool_recycle_object(&clock_class->cv_pool, clock_value); + bt_put(clock_class); +} + +uint64_t bt_clock_value_get_value(struct bt_clock_value *clock_value) +{ + BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value"); + BT_ASSERT_PRE(clock_value->is_set, + "Clock value is not set: %!+k", clock_value); + return clock_value->value_cycles; +} + +int bt_clock_value_get_ns_from_origin(struct bt_clock_value *clock_value, + int64_t *ret_value_ns) +{ + int ret = 0; + BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value"); + BT_ASSERT_PRE_NON_NULL(ret_value_ns, "Value (ns) (output)"); + BT_ASSERT_PRE(clock_value->is_set, + "Clock value is not set: %!+k", clock_value); + + if (clock_value->ns_from_origin_overflows) { + BT_LIB_LOGD("Clock value, once converted to nanoseconds from origin, " + "overflows the signed 64-bit integer range: " + "%![cv-]+k", clock_value); + ret = -1; + goto end; + } + + *ret_value_ns = clock_value->ns_from_origin; + +end: + return ret; +} + +struct bt_clock_class *bt_clock_value_borrow_clock_class( + struct bt_clock_value *clock_value) +{ + BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value"); + return clock_value->clock_class; +} diff --git a/lib/trace-ir/event-class.c b/lib/trace-ir/event-class.c new file mode 100644 index 00000000..18a72f70 --- /dev/null +++ b/lib/trace-ir/event-class.c @@ -0,0 +1,377 @@ +/* + * event-class.c + * + * Babeltrace trace IR - Event class + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "EVENT-CLASS" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BT_ASSERT_PRE_EVENT_CLASS_HOT(_ec) \ + BT_ASSERT_PRE_HOT((_ec), "Event class", ": %!+E", (_ec)) + +static +void destroy_event_class(struct bt_object *obj) +{ + struct bt_event_class *event_class = (void *) obj; + + BT_LIB_LOGD("Destroying event class: %!+E", event_class); + + if (event_class->name.str) { + g_string_free(event_class->name.str, TRUE); + } + + if (event_class->emf_uri.str) { + g_string_free(event_class->emf_uri.str, TRUE); + } + + BT_LOGD_STR("Putting context field type."); + bt_put(event_class->specific_context_ft); + BT_LOGD_STR("Putting payload field type."); + bt_put(event_class->payload_ft); + bt_object_pool_finalize(&event_class->event_pool); + g_free(obj); +} + +static +void free_event(struct bt_event *event, + struct bt_event_class *event_class) +{ + bt_event_destroy(event); +} + +BT_ASSERT_PRE_FUNC +static +bool event_class_id_is_unique(struct bt_stream_class *stream_class, uint64_t id) +{ + uint64_t i; + bool is_unique = true; + + for (i = 0; i < stream_class->event_classes->len; i++) { + struct bt_event_class *ec = + stream_class->event_classes->pdata[i]; + + if (ec->id == id) { + is_unique = false; + goto end; + } + } + +end: + return is_unique; +} + +static +struct bt_event_class *create_event_class_with_id( + struct bt_stream_class *stream_class, uint64_t id) +{ + int ret; + struct bt_event_class *event_class; + + BT_ASSERT(stream_class); + BT_ASSERT_PRE(event_class_id_is_unique(stream_class, id), + "Duplicate event class ID: %![sc-]+S, id=%" PRIu64, + stream_class, id); + BT_LIB_LOGD("Creating event class object: %![sc-]+S, id=%" PRIu64, + stream_class, id); + event_class = g_new0(struct bt_event_class, 1); + if (!event_class) { + BT_LOGE_STR("Failed to allocate one event class."); + goto error; + } + + bt_object_init_shared_with_parent(&event_class->base, + destroy_event_class); + event_class->id = id; + bt_property_uint_init(&event_class->log_level, + BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE, 0); + event_class->name.str = g_string_new(NULL); + if (!event_class->name.str) { + BT_LOGE_STR("Failed to allocate a GString."); + ret = -1; + goto end; + } + + event_class->emf_uri.str = g_string_new(NULL); + if (!event_class->emf_uri.str) { + BT_LOGE_STR("Failed to allocate a GString."); + ret = -1; + goto end; + } + + ret = bt_object_pool_initialize(&event_class->event_pool, + (bt_object_pool_new_object_func) bt_event_new, + (bt_object_pool_destroy_object_func) free_event, + event_class); + if (ret) { + BT_LOGE("Failed to initialize event pool: ret=%d", + ret); + goto error; + } + + bt_object_set_parent(&event_class->base, &stream_class->base); + g_ptr_array_add(stream_class->event_classes, event_class); + bt_stream_class_freeze(stream_class); + BT_LIB_LOGD("Created event class object: %!+E", event_class); + goto end; + +error: + BT_PUT(event_class); + +end: + return event_class; +} + +struct bt_event_class *bt_event_class_create( + struct bt_stream_class *stream_class) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE(stream_class->assigns_automatic_event_class_id, + "Stream class does not automatically assigns event class IDs: " + "%![sc-]+S", stream_class); + return create_event_class_with_id(stream_class, + (uint64_t) stream_class->event_classes->len); +} + +struct bt_event_class *bt_event_class_create_with_id( + struct bt_stream_class *stream_class, uint64_t id) +{ + BT_ASSERT_PRE(!stream_class->assigns_automatic_event_class_id, + "Stream class automatically assigns event class IDs: " + "%![sc-]+S", stream_class); + return create_event_class_with_id(stream_class, id); +} + +const char *bt_event_class_get_name(struct bt_event_class *event_class) +{ + BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); + return event_class->name.value; +} + +int bt_event_class_set_name(struct bt_event_class *event_class, + const char *name) +{ + BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); + BT_ASSERT_PRE_NON_NULL(name, "Name"); + BT_ASSERT_PRE_EVENT_CLASS_HOT(event_class); + g_string_assign(event_class->name.str, name); + event_class->name.value = event_class->name.str->str; + BT_LIB_LOGV("Set event class's name: %!+E", event_class); + return 0; +} + +uint64_t bt_event_class_get_id(struct bt_event_class *event_class) +{ + BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); + return event_class->id; +} + +enum bt_property_availability bt_event_class_get_log_level( + struct bt_event_class *event_class, + enum bt_event_class_log_level *log_level) +{ + BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); + BT_ASSERT_PRE_NON_NULL(log_level, "Log level (output)"); + *log_level = (enum bt_event_class_log_level) + event_class->log_level.value; + return event_class->log_level.base.avail; +} + +int bt_event_class_set_log_level(struct bt_event_class *event_class, + enum bt_event_class_log_level log_level) +{ + BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); + BT_ASSERT_PRE_EVENT_CLASS_HOT(event_class); + bt_property_uint_set(&event_class->log_level, + (uint64_t) log_level); + BT_LIB_LOGV("Set event class's log level: %!+E", event_class); + return 0; +} + +const char *bt_event_class_get_emf_uri(struct bt_event_class *event_class) +{ + BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); + return event_class->emf_uri.value; +} + +int bt_event_class_set_emf_uri(struct bt_event_class *event_class, + const char *emf_uri) +{ + BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); + BT_ASSERT_PRE_NON_NULL(emf_uri, "EMF URI"); + BT_ASSERT_PRE_EVENT_CLASS_HOT(event_class); + g_string_assign(event_class->emf_uri.str, emf_uri); + event_class->emf_uri.value = event_class->emf_uri.str->str; + BT_LIB_LOGV("Set event class's EMF URI: %!+E", event_class); + return 0; +} + +struct bt_stream_class *bt_event_class_borrow_stream_class( + struct bt_event_class *event_class) +{ + BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); + return bt_event_class_borrow_stream_class_inline(event_class); +} + +struct bt_field_type *bt_event_class_borrow_specific_context_field_type( + struct bt_event_class *event_class) +{ + BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); + return event_class->specific_context_ft; +} + +int bt_event_class_set_specific_context_field_type( + struct bt_event_class *event_class, + struct bt_field_type *field_type) +{ + int ret; + struct bt_stream_class *stream_class; + struct bt_trace *trace; + struct bt_resolve_field_path_context resolve_ctx = { + .packet_header = NULL, + .packet_context = NULL, + .event_header = NULL, + .event_common_context = NULL, + .event_specific_context = field_type, + .event_payload = NULL, + }; + + BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); + BT_ASSERT_PRE_NON_NULL(field_type, "Field type"); + BT_ASSERT_PRE_EVENT_CLASS_HOT(event_class); + BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) == + BT_FIELD_TYPE_ID_STRUCTURE, + "Specific context field type is not a structure field type: " + "%!+F", field_type); + stream_class = bt_event_class_borrow_stream_class_inline( + event_class); + trace = bt_stream_class_borrow_trace_inline(stream_class); + resolve_ctx.packet_header = trace->packet_header_ft; + resolve_ctx.packet_context = stream_class->packet_context_ft; + resolve_ctx.event_header = stream_class->event_header_ft; + resolve_ctx.event_common_context = + stream_class->event_common_context_ft; + + ret = bt_resolve_field_paths(field_type, &resolve_ctx); + if (ret) { + goto end; + } + + bt_field_type_make_part_of_trace(field_type); + bt_put(event_class->specific_context_ft); + event_class->specific_context_ft = bt_get(field_type); + bt_field_type_freeze(field_type); + BT_LIB_LOGV("Set event class's specific context field type: %!+E", + event_class); + +end: + return ret; +} + +struct bt_field_type *bt_event_class_borrow_payload_field_type( + struct bt_event_class *event_class) +{ + BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); + return event_class->payload_ft; +} + +int bt_event_class_set_payload_field_type(struct bt_event_class *event_class, + struct bt_field_type *field_type) +{ + int ret; + struct bt_stream_class *stream_class; + struct bt_trace *trace; + struct bt_resolve_field_path_context resolve_ctx = { + .packet_header = NULL, + .packet_context = NULL, + .event_header = NULL, + .event_common_context = NULL, + .event_specific_context = NULL, + .event_payload = field_type, + }; + + BT_ASSERT_PRE_NON_NULL(event_class, "Event class"); + BT_ASSERT_PRE_NON_NULL(field_type, "Field type"); + BT_ASSERT_PRE_EVENT_CLASS_HOT(event_class); + BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) == + BT_FIELD_TYPE_ID_STRUCTURE, + "Payload field type is not a structure field type: %!+F", + field_type); + stream_class = bt_event_class_borrow_stream_class_inline( + event_class); + trace = bt_stream_class_borrow_trace_inline(stream_class); + resolve_ctx.packet_header = trace->packet_header_ft; + resolve_ctx.packet_context = stream_class->packet_context_ft; + resolve_ctx.event_header = stream_class->event_header_ft; + resolve_ctx.event_common_context = + stream_class->event_common_context_ft; + resolve_ctx.event_specific_context = event_class->specific_context_ft; + + ret = bt_resolve_field_paths(field_type, &resolve_ctx); + if (ret) { + goto end; + } + + bt_field_type_make_part_of_trace(field_type); + bt_put(event_class->payload_ft); + event_class->payload_ft = bt_get(field_type); + bt_field_type_freeze(field_type); + BT_LIB_LOGV("Set event class's payload field type: %!+E", event_class); + +end: + return ret; +} + +BT_HIDDEN +void _bt_event_class_freeze(struct bt_event_class *event_class) +{ + /* The field types are already frozen */ + BT_ASSERT(event_class); + BT_LIB_LOGD("Freezing event class: %!+E", event_class); + event_class->frozen = true; +} diff --git a/lib/trace-ir/event-header-field.c b/lib/trace-ir/event-header-field.c new file mode 100644 index 00000000..a84e9995 --- /dev/null +++ b/lib/trace-ir/event-header-field.c @@ -0,0 +1,90 @@ +/* + * Copyright 2018 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "EVENT-HEADER-FIELD" +#include + +#include +#include +#include +#include +#include +#include + +struct bt_field *bt_event_header_field_borrow_field( + struct bt_event_header_field *header_field) +{ + struct bt_field_wrapper *field_wrapper = (void *) header_field; + + BT_ASSERT_PRE_NON_NULL(field_wrapper, "Event header field"); + return (void *) field_wrapper->field; +} + +void bt_event_header_field_release(struct bt_event_header_field *header_field) +{ + struct bt_field_wrapper *field_wrapper = (void *) header_field; + + BT_ASSERT_PRE_NON_NULL(field_wrapper, "Event header field"); + + /* + * Do not recycle because the pool could be destroyed at this + * point. This function is only called when there's an error + * anyway because the goal of an event header field wrapper is + * to eventually move it to an event with bt_event_move_header() + * after creating it. + */ + bt_field_wrapper_destroy(field_wrapper); +} + +struct bt_event_header_field *bt_event_header_field_create( + struct bt_stream_class *stream_class) +{ + struct bt_field_wrapper *field_wrapper; + + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE(bt_stream_class_borrow_trace_inline(stream_class), + "Stream class is not part of a trace: %!+S", stream_class); + BT_ASSERT_PRE(stream_class->event_header_ft, + "Stream class has no event header field type: %!+S", + stream_class); + field_wrapper = bt_field_wrapper_create( + &stream_class->event_header_field_pool, + (void *) stream_class->event_header_ft); + if (!field_wrapper) { + BT_LIB_LOGE("Cannot allocate one event header field from stream class: " + "%![sc-]+S", stream_class); + goto error; + } + + BT_ASSERT(field_wrapper->field); + bt_stream_class_freeze(stream_class); + goto end; + +error: + if (field_wrapper) { + bt_field_wrapper_destroy(field_wrapper); + field_wrapper = NULL; + } + +end: + return (void *) field_wrapper; +} diff --git a/lib/trace-ir/event.c b/lib/trace-ir/event.c new file mode 100644 index 00000000..b997f209 --- /dev/null +++ b/lib/trace-ir/event.c @@ -0,0 +1,349 @@ +/* + * event.c + * + * Babeltrace trace IR - Event + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "EVENT" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +BT_HIDDEN +void _bt_event_set_is_frozen(struct bt_event *event, bool is_frozen) +{ + BT_ASSERT(event); + BT_LIB_LOGD("Setting event's frozen state: %!+e, is-frozen=%d", + event, is_frozen); + + if (event->header_field) { + BT_LOGD_STR("Setting event's header field's frozen state."); + bt_field_set_is_frozen( + event->header_field->field, is_frozen); + } + + if (event->common_context_field) { + BT_LOGD_STR("Setting event's common context field's frozen state."); + bt_field_set_is_frozen( + event->common_context_field, is_frozen); + } + + if (event->specific_context_field) { + BT_LOGD_STR("Setting event's specific context field's frozen state."); + bt_field_set_is_frozen(event->specific_context_field, + is_frozen); + } + + if (event->payload_field) { + BT_LOGD_STR("Setting event's payload field's frozen state."); + bt_field_set_is_frozen(event->payload_field, + is_frozen); + } + + event->frozen = is_frozen; + BT_LOGD_STR("Setting event's packet's frozen state."); + bt_packet_set_is_frozen(event->packet, is_frozen); +} + +static +void recycle_event_header_field(struct bt_field_wrapper *field_wrapper, + struct bt_stream_class *stream_class) +{ + BT_ASSERT(field_wrapper); + BT_LIB_LOGD("Recycling event header field: " + "addr=%p, %![sc-]+S, %![field-]+f", field_wrapper, + stream_class, field_wrapper->field); + bt_object_pool_recycle_object( + &stream_class->event_header_field_pool, + field_wrapper); +} + +static inline +struct bt_field_wrapper *create_event_header_field( + struct bt_stream_class *stream_class) +{ + struct bt_field_wrapper *field_wrapper = NULL; + + field_wrapper = bt_field_wrapper_create( + &stream_class->event_header_field_pool, + bt_stream_class_borrow_event_header_field_type(stream_class)); + if (!field_wrapper) { + goto error; + } + + goto end; + +error: + if (field_wrapper) { + recycle_event_header_field(field_wrapper, stream_class); + field_wrapper = NULL; + } + +end: + return field_wrapper; +} + +BT_HIDDEN +struct bt_event *bt_event_new(struct bt_event_class *event_class) +{ + struct bt_event *event = NULL; + struct bt_stream_class *stream_class; + struct bt_field_type *ft; + + BT_ASSERT(event_class); + event = g_new0(struct bt_event, 1); + if (!event) { + BT_LOGE_STR("Failed to allocate one event."); + goto error; + } + + bt_object_init_unique(&event->base); + stream_class = bt_event_class_borrow_stream_class(event_class); + BT_ASSERT(stream_class); + + if (bt_stream_class_borrow_event_header_field_type(stream_class)) { + event->header_field = create_event_header_field(stream_class); + if (!event->header_field) { + BT_LOGE_STR("Cannot create event header field."); + goto error; + } + } + + ft = bt_stream_class_borrow_event_common_context_field_type( + stream_class); + if (ft) { + event->common_context_field = bt_field_create(ft); + if (!event->common_context_field) { + /* bt_field_create() logs errors */ + goto error; + } + } + + ft = bt_event_class_borrow_specific_context_field_type(event_class); + if (ft) { + event->specific_context_field = bt_field_create(ft); + if (!event->specific_context_field) { + /* bt_field_create() logs errors */ + goto error; + } + } + + ft = bt_event_class_borrow_payload_field_type(event_class); + if (ft) { + event->payload_field = bt_field_create(ft); + if (!event->payload_field) { + /* bt_field_create() logs errors */ + goto error; + } + } + + if (stream_class->default_clock_class) { + event->default_cv = bt_clock_value_create( + stream_class->default_clock_class); + if (!event->default_cv) { + /* bt_clock_value_create() logs errors */ + goto error; + } + } + + goto end; + +error: + if (event) { + bt_event_destroy(event); + event = NULL; + } + +end: + return event; +} + +struct bt_event_class *bt_event_borrow_class(struct bt_event *event) +{ + BT_ASSERT_PRE_NON_NULL(event, "Event"); + return event->class; +} + +struct bt_stream *bt_event_borrow_stream(struct bt_event *event) +{ + BT_ASSERT_PRE_NON_NULL(event, "Event"); + return event->packet ? event->packet->stream : NULL; +} + +struct bt_field *bt_event_borrow_header_field(struct bt_event *event) +{ + BT_ASSERT_PRE_NON_NULL(event, "Event"); + return event->header_field ? event->header_field->field : NULL; +} + +struct bt_field *bt_event_borrow_common_context_field(struct bt_event *event) +{ + BT_ASSERT_PRE_NON_NULL(event, "Event"); + return event->common_context_field; +} + +struct bt_field *bt_event_borrow_specific_context_field(struct bt_event *event) +{ + BT_ASSERT_PRE_NON_NULL(event, "Event"); + return event->specific_context_field; +} + +struct bt_field *bt_event_borrow_payload_field(struct bt_event *event) +{ + BT_ASSERT_PRE_NON_NULL(event, "Event"); + return event->payload_field; +} + +static +void release_event_header_field(struct bt_field_wrapper *field_wrapper, + struct bt_event *event) +{ + if (!event->class) { + bt_field_wrapper_destroy(field_wrapper); + } else { + struct bt_stream_class *stream_class = + bt_event_class_borrow_stream_class(event->class); + + BT_ASSERT(stream_class); + recycle_event_header_field(field_wrapper, stream_class); + } +} + +BT_HIDDEN +void bt_event_destroy(struct bt_event *event) +{ + BT_ASSERT(event); + BT_LIB_LOGD("Destroying event: %!+e", event); + + if (event->header_field) { + BT_LOGD_STR("Releasing event's header field."); + release_event_header_field(event->header_field, event); + } + + if (event->common_context_field) { + BT_LOGD_STR("Destroying event's stream event context field."); + bt_field_destroy(event->common_context_field); + } + + if (event->specific_context_field) { + BT_LOGD_STR("Destroying event's context field."); + bt_field_destroy(event->specific_context_field); + } + + if (event->payload_field) { + BT_LOGD_STR("Destroying event's payload field."); + bt_field_destroy(event->payload_field); + } + + BT_LOGD_STR("Putting event's class."); + bt_put(event->class); + + if (event->default_cv) { + bt_clock_value_recycle(event->default_cv); + } + + BT_LOGD_STR("Putting event's packet."); + bt_put(event->packet); + g_free(event); +} + +int bt_event_set_default_clock_value(struct bt_event *event, + uint64_t value_cycles) +{ + struct bt_stream_class *sc; + + BT_ASSERT_PRE_NON_NULL(event, "Event"); + BT_ASSERT_PRE_EVENT_HOT(event); + sc = bt_event_class_borrow_stream_class_inline(event->class); + BT_ASSERT(sc); + BT_ASSERT_PRE(sc->default_clock_class, + "Event's stream class has no default clock class: " + "%![ev-]+e, %![sc-]+S", event, sc); + BT_ASSERT(event->default_cv); + bt_clock_value_set_value_inline(event->default_cv, value_cycles); + BT_LIB_LOGV("Set event's default clock value: %![event-]+e, " + "value=%" PRIu64, event, value_cycles); + return 0; +} + +enum bt_clock_value_status bt_event_borrow_default_clock_value( + struct bt_event *event, struct bt_clock_value **clock_value) +{ + BT_ASSERT_PRE_NON_NULL(event, "Event"); + BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value (output)"); + *clock_value = event->default_cv; + return BT_CLOCK_VALUE_STATUS_KNOWN; +} + +struct bt_packet *bt_event_borrow_packet(struct bt_event *event) +{ + BT_ASSERT_PRE_NON_NULL(event, "Event"); + return event->packet; +} + +int bt_event_move_header(struct bt_event *event, + struct bt_event_header_field *header_field) +{ + struct bt_stream_class *stream_class; + struct bt_field_wrapper *field_wrapper = (void *) header_field; + + BT_ASSERT_PRE_NON_NULL(event, "Event"); + BT_ASSERT_PRE_NON_NULL(field_wrapper, "Header field"); + BT_ASSERT_PRE_EVENT_HOT(event); + stream_class = bt_event_class_borrow_stream_class_inline(event->class); + BT_ASSERT_PRE(stream_class->event_header_ft, + "Stream class has no event header field type: %!+S", + stream_class); + + /* Recycle current header field: always exists */ + BT_ASSERT(event->header_field); + recycle_event_header_field(event->header_field, stream_class); + + /* Move new field */ + event->header_field = field_wrapper; + return 0; +} diff --git a/lib/trace-ir/field-path.c b/lib/trace-ir/field-path.c new file mode 100644 index 00000000..65d2f721 --- /dev/null +++ b/lib/trace-ir/field-path.c @@ -0,0 +1,101 @@ +/* + * field-path.c + * + * Babeltrace trace IR - Field path + * + * Copyright 2013, 2014 Jérémie Galarneau + * Copyright 2016 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "FIELD-PATH" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static +void destroy_field_path(struct bt_object *obj) +{ + struct bt_field_path *field_path = (struct bt_field_path *) obj; + + BT_ASSERT(field_path); + BT_LIB_LOGD("Destroying field path: %!+P", field_path); + g_array_free(field_path->indexes, TRUE); + g_free(field_path); +} + +BT_HIDDEN +struct bt_field_path *bt_field_path_create(void) +{ + struct bt_field_path *field_path = NULL; + + BT_LOGD_STR("Creating empty field path object."); + + field_path = g_new0(struct bt_field_path, 1); + if (!field_path) { + BT_LOGE_STR("Failed to allocate one field path."); + goto error; + } + + bt_object_init_shared(&field_path->base, destroy_field_path); + field_path->indexes = g_array_new(FALSE, FALSE, sizeof(uint64_t)); + if (!field_path->indexes) { + BT_LOGE_STR("Failed to allocate a GArray."); + goto error; + } + + BT_LIB_LOGD("Created empty field path object: %!+P", field_path); + goto end; + +error: + BT_PUT(field_path); + +end: + return field_path; +} + +enum bt_scope bt_field_path_get_root_scope(struct bt_field_path *field_path) +{ + BT_ASSERT_PRE_NON_NULL(field_path, "Field path"); + return field_path->root; +} + +uint64_t bt_field_path_get_index_count(struct bt_field_path *field_path) +{ + BT_ASSERT_PRE_NON_NULL(field_path, "Field path"); + return (uint64_t) field_path->indexes->len; +} + +uint64_t bt_field_path_get_index_by_index(struct bt_field_path *field_path, + uint64_t index) +{ + BT_ASSERT_PRE_NON_NULL(field_path, "Field path"); + BT_ASSERT_PRE_VALID_INDEX(index, field_path->indexes->len); + return bt_field_path_get_index_by_index_inline(field_path, index); +} diff --git a/lib/trace-ir/field-types.c b/lib/trace-ir/field-types.c new file mode 100644 index 00000000..3953d85d --- /dev/null +++ b/lib/trace-ir/field-types.c @@ -0,0 +1,1164 @@ +/* + * field-types.c + * + * Babeltrace trace IR - Event Types + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "FIELD-TYPES" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum bt_field_type_id bt_field_type_get_type_id(struct bt_field_type *ft) +{ + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + return ft->id; +} + +static +void init_field_type(struct bt_field_type *ft, enum bt_field_type_id id, + bt_object_release_func release_func) +{ + BT_ASSERT(ft); + BT_ASSERT(bt_field_type_has_known_id(ft)); + BT_ASSERT(release_func); + bt_object_init_shared(&ft->base, release_func); + ft->id = id; +} + +static +void init_integer_field_type(struct bt_field_type_integer *ft, enum bt_field_type_id id, + bt_object_release_func release_func) +{ + init_field_type((void *) ft, id, release_func); + ft->range = 64; + ft->base = BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL; +} + +static +void destroy_integer_field_type(struct bt_object *obj) +{ + BT_ASSERT(obj); + BT_LIB_LOGD("Destroying integer field type object: %!+F", obj); + g_free(obj); +} + +static inline +struct bt_field_type *create_integer_field_type(enum bt_field_type_id id) +{ + struct bt_field_type_integer *int_ft = NULL; + + BT_LOGD("Creating default integer field type object: id=%s", + bt_common_field_type_id_string(id)); + int_ft = g_new0(struct bt_field_type_integer, 1); + if (!int_ft) { + BT_LOGE_STR("Failed to allocate one integer field type."); + goto error; + } + + init_integer_field_type(int_ft, id, destroy_integer_field_type); + BT_LIB_LOGD("Created integer field type object: %!+F", int_ft); + goto end; + +error: + BT_PUT(int_ft); + +end: + return (void *) int_ft; +} + +struct bt_field_type *bt_field_type_unsigned_integer_create(void) +{ + return create_integer_field_type(BT_FIELD_TYPE_ID_UNSIGNED_INTEGER); +} + +struct bt_field_type *bt_field_type_signed_integer_create(void) +{ + return create_integer_field_type(BT_FIELD_TYPE_ID_SIGNED_INTEGER); +} + +uint64_t bt_field_type_integer_get_field_value_range( + struct bt_field_type *ft) +{ + struct bt_field_type_integer *int_ft = (void *) ft; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_IS_INT(ft, "Field type"); + return int_ft->range; +} + +BT_ASSERT_PRE_FUNC +static +bool size_is_valid_for_enumeration_field_type(struct bt_field_type *ft, + uint64_t size) +{ + // TODO + return true; +} + +int bt_field_type_integer_set_field_value_range( + struct bt_field_type *ft, uint64_t size) +{ + struct bt_field_type_integer *int_ft = (void *) ft; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_IS_INT(ft, "Field type"); + BT_ASSERT_PRE_FT_HOT(ft, "Field type"); + BT_ASSERT_PRE(size <= 64, + "Unsupported size for integer field type's field value range " + "(maximum is 64): size=%" PRIu64, size); + BT_ASSERT_PRE(int_ft->common.id == BT_FIELD_TYPE_ID_UNSIGNED_INTEGER || + int_ft->common.id == BT_FIELD_TYPE_ID_SIGNED_INTEGER || + size_is_valid_for_enumeration_field_type(ft, size), + "Invalid field value range for enumeration field type: " + "at least one of the current mapping ranges contains values " + "which are outside this range: %!+F, size=%" PRIu64, ft, size); + int_ft->range = size; + BT_LIB_LOGV("Set integer field type's field value range: %!+F", ft); + return 0; +} + +enum bt_field_type_integer_preferred_display_base +bt_field_type_integer_get_preferred_display_base(struct bt_field_type *ft) +{ + struct bt_field_type_integer *int_ft = (void *) ft; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_IS_INT(ft, "Field type"); + return int_ft->base; +} + +int bt_field_type_integer_set_preferred_display_base(struct bt_field_type *ft, + enum bt_field_type_integer_preferred_display_base base) +{ + struct bt_field_type_integer *int_ft = (void *) ft; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_IS_INT(ft, "Field type"); + BT_ASSERT_PRE_FT_HOT(ft, "Field type"); + int_ft->base = base; + BT_LIB_LOGV("Set integer field type's preferred display base: %!+F", ft); + return 0; +} + +static +void finalize_enumeration_field_type_mapping( + struct bt_field_type_enumeration_mapping *mapping) +{ + BT_ASSERT(mapping); + + if (mapping->label) { + g_string_free(mapping->label, TRUE); + } + + if (mapping->ranges) { + g_array_free(mapping->ranges, TRUE); + } +} + +static +void destroy_enumeration_field_type(struct bt_object *obj) +{ + struct bt_field_type_enumeration *ft = (void *) obj; + + BT_ASSERT(ft); + BT_LIB_LOGD("Destroying enumeration field type object: %!+F", ft); + + if (ft->mappings) { + uint64_t i; + + for (i = 0; i < ft->mappings->len; i++) { + finalize_enumeration_field_type_mapping( + BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(ft, i)); + } + + g_array_free(ft->mappings, TRUE); + } + + if (ft->label_buf) { + g_ptr_array_free(ft->label_buf, TRUE); + } + + g_free(ft); +} + +static +struct bt_field_type *create_enumeration_field_type(enum bt_field_type_id id) +{ + struct bt_field_type_enumeration *enum_ft = NULL; + + BT_LOGD("Creating default enumeration field type object: id=%s", + bt_common_field_type_id_string(id)); + enum_ft = g_new0(struct bt_field_type_enumeration, 1); + if (!enum_ft) { + BT_LOGE_STR("Failed to allocate one enumeration field type."); + goto error; + } + + init_integer_field_type((void *) enum_ft, id, + destroy_enumeration_field_type); + enum_ft->mappings = g_array_new(FALSE, TRUE, + sizeof(struct bt_field_type_enumeration_mapping)); + if (!enum_ft->mappings) { + BT_LOGE_STR("Failed to allocate a GArray."); + goto error; + } + + enum_ft->label_buf = g_ptr_array_new(); + if (!enum_ft->label_buf) { + BT_LOGE_STR("Failed to allocate a GArray."); + goto error; + } + + BT_LIB_LOGD("Created enumeration field type object: %!+F", enum_ft); + goto end; + +error: + BT_PUT(enum_ft); + +end: + return (void *) enum_ft; +} + +struct bt_field_type *bt_field_type_unsigned_enumeration_create(void) +{ + return create_enumeration_field_type( + BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION); +} + +struct bt_field_type *bt_field_type_signed_enumeration_create(void) +{ + return create_enumeration_field_type( + BT_FIELD_TYPE_ID_SIGNED_ENUMERATION); +} + +uint64_t bt_field_type_enumeration_get_mapping_count(struct bt_field_type *ft) +{ + struct bt_field_type_enumeration *enum_ft = (void *) ft; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_IS_ENUM(ft, "Field type"); + return (uint64_t) enum_ft->mappings->len; +} + +void bt_field_type_unsigned_enumeration_borrow_mapping_by_index( + struct bt_field_type *ft, uint64_t index, + const char **name, + struct bt_field_type_unsigned_enumeration_mapping_ranges **ranges) +{ + struct bt_field_type_enumeration *enum_ft = (void *) ft; + struct bt_field_type_enumeration_mapping *mapping; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_NON_NULL(name, "Name (output)"); + BT_ASSERT_PRE_NON_NULL(ranges, "Ranges (output)"); + BT_ASSERT_PRE_VALID_INDEX(index, enum_ft->mappings->len); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION, + "Field type"); + mapping = BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(ft, index); + *name = mapping->label->str; + *ranges = (void *) mapping; +} + +void bt_field_type_signed_enumeration_borrow_mapping_by_index( + struct bt_field_type *ft, uint64_t index, + const char **name, + struct bt_field_type_signed_enumeration_mapping_ranges **ranges) +{ + struct bt_field_type_enumeration *enum_ft = (void *) ft; + struct bt_field_type_enumeration_mapping *mapping; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_NON_NULL(name, "Name (output)"); + BT_ASSERT_PRE_NON_NULL(ranges, "Ranges (output)"); + BT_ASSERT_PRE_VALID_INDEX(index, enum_ft->mappings->len); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, + "Field type"); + mapping = BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(ft, index); + *name = mapping->label->str; + *ranges = (void *) mapping; +} + +static inline +uint64_t get_enumeration_field_type_mapping_range_count( + struct bt_field_type_enumeration_mapping *mapping) +{ + BT_ASSERT_PRE_NON_NULL(mapping, "Ranges"); + return (uint64_t) mapping->ranges->len; +} + +uint64_t bt_field_type_unsigned_enumeration_mapping_ranges_get_range_count( + struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges) +{ + return get_enumeration_field_type_mapping_range_count((void *) ranges); +} + +uint64_t bt_field_type_signed_enumeration_mapping_ranges_get_range_count( + struct bt_field_type_signed_enumeration_mapping_ranges *ranges) +{ + return get_enumeration_field_type_mapping_range_count((void *) ranges); +} + +static inline +void get_enumeration_field_type_mapping_range_at_index( + struct bt_field_type_enumeration_mapping *mapping, + uint64_t index, uint64_t *lower, uint64_t *upper) +{ + struct bt_field_type_enumeration_mapping_range *range; + + BT_ASSERT_PRE_NON_NULL(mapping, "Ranges"); + BT_ASSERT_PRE_NON_NULL(lower, "Range's lower (output)"); + BT_ASSERT_PRE_NON_NULL(upper, "Range's upper (output)"); + BT_ASSERT_PRE_VALID_INDEX(index, mapping->ranges->len); + range = BT_FIELD_TYPE_ENUM_MAPPING_RANGE_AT_INDEX(mapping, index); + *lower = range->lower.u; + *upper = range->upper.u; +} + +void bt_field_type_unsigned_enumeration_mapping_ranges_get_range_by_index( + struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges, + uint64_t index, uint64_t *lower, uint64_t *upper) +{ + get_enumeration_field_type_mapping_range_at_index((void *) ranges, + index, lower, upper); +} + +void bt_field_type_signed_enumeration_mapping_ranges_get_range_by_index( + struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges, + uint64_t index, int64_t *lower, int64_t *upper) +{ + get_enumeration_field_type_mapping_range_at_index((void *) ranges, + index, (uint64_t *) lower, (uint64_t *) upper); +} + + + +int bt_field_type_unsigned_enumeration_get_mapping_labels_by_value( + struct bt_field_type *ft, uint64_t value, + bt_field_type_enumeration_mapping_label_array *label_array, + uint64_t *count) +{ + struct bt_field_type_enumeration *enum_ft = (void *) ft; + uint64_t i; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_NON_NULL(label_array, "Label array (output)"); + BT_ASSERT_PRE_NON_NULL(count, "Count (output)"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION, + "Field type"); + g_ptr_array_set_size(enum_ft->label_buf, 0); + + for (i = 0; i < enum_ft->mappings->len; i++) { + uint64_t j; + struct bt_field_type_enumeration_mapping *mapping = + BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(enum_ft, i); + + for (j = 0; j < mapping->ranges->len; j++) { + struct bt_field_type_enumeration_mapping_range *range = + BT_FIELD_TYPE_ENUM_MAPPING_RANGE_AT_INDEX( + mapping, j); + + if (value >= range->lower.u && + value <= range->upper.u) { + g_ptr_array_add(enum_ft->label_buf, + mapping->label->str); + break; + } + } + } + + *label_array = (void *) enum_ft->label_buf->pdata; + *count = (uint64_t) enum_ft->label_buf->len; + return 0; +} + +int bt_field_type_signed_enumeration_get_mapping_labels_by_value( + struct bt_field_type *ft, int64_t value, + bt_field_type_enumeration_mapping_label_array *label_array, + uint64_t *count) +{ + struct bt_field_type_enumeration *enum_ft = (void *) ft; + uint64_t i; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_NON_NULL(label_array, "Label array (output)"); + BT_ASSERT_PRE_NON_NULL(count, "Count (output)"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, + "Field type"); + g_ptr_array_set_size(enum_ft->label_buf, 0); + + for (i = 0; i < enum_ft->mappings->len; i++) { + uint64_t j; + struct bt_field_type_enumeration_mapping *mapping = + BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(enum_ft, i); + + for (j = 0; j < mapping->ranges->len; j++) { + struct bt_field_type_enumeration_mapping_range *range = + BT_FIELD_TYPE_ENUM_MAPPING_RANGE_AT_INDEX( + mapping, j); + + if (value >= range->lower.i && + value <= range->upper.i) { + g_ptr_array_add(enum_ft->label_buf, + mapping->label->str); + break; + } + } + } + + *label_array = (void *) enum_ft->label_buf->pdata; + *count = (uint64_t) enum_ft->label_buf->len; + return 0; +} + +static inline +int add_mapping_to_enumeration_field_type(struct bt_field_type *ft, + const char *label, uint64_t lower, uint64_t upper) +{ + int ret = 0; + uint64_t i; + struct bt_field_type_enumeration *enum_ft = (void *) ft; + struct bt_field_type_enumeration_mapping *mapping = NULL; + struct bt_field_type_enumeration_mapping_range *range; + + BT_ASSERT(ft); + BT_ASSERT_PRE_NON_NULL(label, "Label"); + + /* Find existing mapping identified by this label */ + for (i = 0; i < enum_ft->mappings->len; i++) { + struct bt_field_type_enumeration_mapping *mapping_candidate = + BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(enum_ft, i); + + if (strcmp(mapping_candidate->label->str, label) == 0) { + mapping = mapping_candidate; + break; + } + } + + if (!mapping) { + /* Create new mapping for this label */ + g_array_set_size(enum_ft->mappings, enum_ft->mappings->len + 1); + mapping = BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(enum_ft, + enum_ft->mappings->len - 1); + mapping->ranges = g_array_new(FALSE, TRUE, + sizeof(struct bt_field_type_enumeration_mapping_range)); + if (!mapping->ranges) { + finalize_enumeration_field_type_mapping(mapping); + g_array_set_size(enum_ft->mappings, + enum_ft->mappings->len - 1); + ret = -1; + goto end; + } + + mapping->label = g_string_new(label); + if (!mapping->label) { + finalize_enumeration_field_type_mapping(mapping); + g_array_set_size(enum_ft->mappings, + enum_ft->mappings->len - 1); + ret = -1; + goto end; + } + } + + /* Add range */ + BT_ASSERT(mapping); + g_array_set_size(mapping->ranges, mapping->ranges->len + 1); + range = BT_FIELD_TYPE_ENUM_MAPPING_RANGE_AT_INDEX(mapping, + mapping->ranges->len - 1); + range->lower.u = lower; + range->upper.u = upper; + BT_LIB_LOGV("Added mapping to enumeration field type: " + "%![ft-]+F, label=\"%s\", lower-unsigned=%" PRIu64 ", " + "upper-unsigned=%" PRIu64, ft, label, lower, upper); + +end: + return ret; +} + +int bt_field_type_unsigned_enumeration_map_range( + struct bt_field_type *ft, const char *label, + uint64_t range_lower, uint64_t range_upper) +{ + struct bt_field_type_enumeration *enum_ft = (void *) ft; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION, + "Field type"); + BT_ASSERT_PRE(range_lower <= range_upper, + "Range's upper bound is less than lower bound: " + "upper=%" PRIu64 ", lower=%" PRIu64, + range_lower, range_upper); + BT_ASSERT_PRE(bt_util_value_is_in_range_unsigned(enum_ft->common.range, + range_lower), + "Range's lower bound is outside the enumeration field type's value range: " + "%![ft-]+F, lower=%" PRIu64, ft, range_lower); + BT_ASSERT_PRE(bt_util_value_is_in_range_unsigned(enum_ft->common.range, + range_upper), + "Range's upper bound is outside the enumeration field type's value range: " + "%![ft-]+F, upper=%" PRIu64, ft, range_upper); + return add_mapping_to_enumeration_field_type(ft, label, range_lower, + range_upper); +} + +int bt_field_type_signed_enumeration_map_range( + struct bt_field_type *ft, const char *label, + int64_t range_lower, int64_t range_upper) +{ + struct bt_field_type_enumeration *enum_ft = (void *) ft; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, + "Field type"); + BT_ASSERT_PRE(range_lower <= range_upper, + "Range's upper bound is less than lower bound: " + "upper=%" PRId64 ", lower=%" PRId64, + range_lower, range_upper); + BT_ASSERT_PRE(bt_util_value_is_in_range_signed(enum_ft->common.range, + range_lower), + "Range's lower bound is outside the enumeration field type's value range: " + "%![ft-]+F, lower=%" PRId64, ft, range_lower); + BT_ASSERT_PRE(bt_util_value_is_in_range_signed(enum_ft->common.range, + range_upper), + "Range's upper bound is outside the enumeration field type's value range: " + "%![ft-]+F, upper=%" PRId64, ft, range_upper); + return add_mapping_to_enumeration_field_type(ft, label, range_lower, + range_upper); +} + +static +void destroy_real_field_type(struct bt_object *obj) +{ + BT_ASSERT(obj); + BT_LIB_LOGD("Destroying real field type object: %!+F", obj); + g_free(obj); +} + +struct bt_field_type *bt_field_type_real_create(void) +{ + struct bt_field_type_real *real_ft = NULL; + + BT_LOGD_STR("Creating default real field type object."); + real_ft = g_new0(struct bt_field_type_real, 1); + if (!real_ft) { + BT_LOGE_STR("Failed to allocate one real field type."); + goto error; + } + + init_field_type((void *) real_ft, BT_FIELD_TYPE_ID_REAL, + destroy_real_field_type); + BT_LIB_LOGD("Created real field type object: %!+F", real_ft); + goto end; + +error: + BT_PUT(real_ft); + +end: + return (void *) real_ft; +} + +bt_bool bt_field_type_real_is_single_precision(struct bt_field_type *ft) +{ + struct bt_field_type_real *real_ft = (void *) ft; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_REAL, "Field type"); + return real_ft->is_single_precision; +} + +int bt_field_type_real_set_is_single_precision(struct bt_field_type *ft, + bt_bool is_single_precision) +{ + struct bt_field_type_real *real_ft = (void *) ft; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_REAL, "Field type"); + BT_ASSERT_PRE_FT_HOT(ft, "Field type"); + real_ft->is_single_precision = (bool) is_single_precision; + BT_LIB_LOGV("Set real field type's \"is single precision\" property: " + "%!+F", ft); + return 0; +} + +static +int init_named_field_types_container( + struct bt_field_type_named_field_types_container *ft, + enum bt_field_type_id id, bt_object_release_func release_func) +{ + int ret = 0; + + init_field_type((void *) ft, id, release_func); + ft->named_fts = g_array_new(FALSE, TRUE, + sizeof(struct bt_named_field_type)); + if (!ft->named_fts) { + BT_LOGE_STR("Failed to allocate a GArray."); + ret = -1; + goto end; + } + + ft->name_to_index = g_hash_table_new(g_str_hash, g_str_equal); + if (!ft->name_to_index) { + BT_LOGE_STR("Failed to allocate a GHashTable."); + ret = -1; + goto end; + } + +end: + return ret; +} + +static +void finalize_named_field_type(struct bt_named_field_type *named_ft) +{ + BT_ASSERT(named_ft); + BT_LIB_LOGD("Finalizing named field type: " + "addr=%p, name=\"%s\", %![ft-]+F", + named_ft, named_ft->name ? named_ft->name->str : NULL, + named_ft->ft); + + if (named_ft->name) { + g_string_free(named_ft->name, TRUE); + } + + BT_LOGD_STR("Putting named field type's field type."); + bt_put(named_ft->ft); +} + +static +void finalize_named_field_types_container( + struct bt_field_type_named_field_types_container *ft) +{ + uint64_t i; + + BT_ASSERT(ft); + + if (ft->named_fts) { + for (i = 0; i < ft->named_fts->len; i++) { + finalize_named_field_type( + &g_array_index(ft->named_fts, + struct bt_named_field_type, i)); + } + + g_array_free(ft->named_fts, TRUE); + } + + if (ft->name_to_index) { + g_hash_table_destroy(ft->name_to_index); + } +} + +static +void destroy_structure_field_type(struct bt_object *obj) +{ + BT_ASSERT(obj); + BT_LIB_LOGD("Destroying string field type object: %!+F", obj); + finalize_named_field_types_container((void *) obj); + g_free(obj); +} + +struct bt_field_type *bt_field_type_structure_create(void) +{ + int ret; + struct bt_field_type_structure *struct_ft = NULL; + + BT_LOGD_STR("Creating default structure field type object."); + struct_ft = g_new0(struct bt_field_type_structure, 1); + if (!struct_ft) { + BT_LOGE_STR("Failed to allocate one structure field type."); + goto error; + } + + ret = init_named_field_types_container((void *) struct_ft, + BT_FIELD_TYPE_ID_STRUCTURE, destroy_structure_field_type); + if (ret) { + goto error; + } + + BT_LIB_LOGD("Created structure field type object: %!+F", struct_ft); + goto end; + +error: + BT_PUT(struct_ft); + +end: + return (void *) struct_ft; +} + +static +int append_named_field_type_to_container_field_type( + struct bt_field_type_named_field_types_container *container_ft, + const char *name, struct bt_field_type *ft) +{ + int ret = 0; + struct bt_named_field_type *named_ft; + GString *name_str; + + BT_ASSERT(container_ft); + BT_ASSERT_PRE_FT_HOT(container_ft, "Field type"); + BT_ASSERT_PRE_NON_NULL(name, "Name"); + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE(!bt_g_hash_table_contains(container_ft->name_to_index, + name), + "Duplicate member/option name in structure/variant field type: " + "%![container-ft-]+F, name=\"%s\"", container_ft, name); + name_str = g_string_new(name); + if (!name_str) { + BT_LOGE_STR("Failed to allocate a GString."); + ret = -1; + goto end; + } + + g_array_set_size(container_ft->named_fts, + container_ft->named_fts->len + 1); + named_ft = &g_array_index(container_ft->named_fts, + struct bt_named_field_type, container_ft->named_fts->len - 1); + named_ft->name = name_str; + named_ft->ft = bt_get(ft); + g_hash_table_insert(container_ft->name_to_index, named_ft->name->str, + GUINT_TO_POINTER(container_ft->named_fts->len - 1)); + bt_field_type_freeze(ft); + +end: + return ret; +} + +int bt_field_type_structure_append_member(struct bt_field_type *ft, + const char *name, struct bt_field_type *member_ft) +{ + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCTURE, "Field type"); + return append_named_field_type_to_container_field_type((void *) ft, + name, member_ft); +} + +uint64_t bt_field_type_structure_get_member_count(struct bt_field_type *ft) +{ + struct bt_field_type_structure *struct_ft = (void *) ft; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCTURE, "Field type"); + return (uint64_t) struct_ft->common.named_fts->len; +} + +static +void borrow_named_field_type_from_container_field_type_at_index( + struct bt_field_type_named_field_types_container *ft, + uint64_t index, const char **name, + struct bt_field_type **out_ft) +{ + struct bt_named_field_type *named_ft; + + BT_ASSERT(ft); + BT_ASSERT_PRE_NON_NULL(name, "Name"); + BT_ASSERT_PRE_NON_NULL(out_ft, "Field type (output)"); + BT_ASSERT_PRE_VALID_INDEX(index, ft->named_fts->len); + named_ft = BT_FIELD_TYPE_NAMED_FT_AT_INDEX(ft, index); + *name = named_ft->name->str; + *out_ft = named_ft->ft; +} + +void bt_field_type_structure_borrow_member_by_index( + struct bt_field_type *ft, uint64_t index, + const char **name, struct bt_field_type **out_ft) +{ + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCTURE, "Field type"); + borrow_named_field_type_from_container_field_type_at_index((void *) ft, + index, name, out_ft); +} + +static +struct bt_field_type *borrow_field_type_from_container_field_type_by_name( + struct bt_field_type_named_field_types_container *ft, + const char *name) +{ + struct bt_field_type *ret_ft = NULL; + struct bt_named_field_type *named_ft; + gpointer orig_key; + gpointer value; + + BT_ASSERT(ft); + BT_ASSERT_PRE_NON_NULL(name, "Name"); + if (!g_hash_table_lookup_extended(ft->name_to_index, name, &orig_key, + &value)) { + goto end; + } + + named_ft = BT_FIELD_TYPE_NAMED_FT_AT_INDEX(ft, + GPOINTER_TO_UINT(value)); + ret_ft = named_ft->ft; + +end: + return ret_ft; +} + +struct bt_field_type *bt_field_type_structure_borrow_member_field_type_by_name( + struct bt_field_type *ft, const char *name) +{ + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCTURE, "Field type"); + return borrow_field_type_from_container_field_type_by_name((void *) ft, + name); +} + +static +void destroy_variant_field_type(struct bt_object *obj) +{ + struct bt_field_type_variant *ft = (void *) obj; + + BT_ASSERT(ft); + BT_LIB_LOGD("Destroying variant field type object: %!+F", ft); + finalize_named_field_types_container((void *) ft); + BT_LOGD_STR("Putting selector field path."); + bt_put(ft->selector_field_path); + g_free(ft); +} + +struct bt_field_type *bt_field_type_variant_create(void) +{ + int ret; + struct bt_field_type_variant *var_ft = NULL; + + BT_LOGD_STR("Creating default variant field type object."); + var_ft = g_new0(struct bt_field_type_variant, 1); + if (!var_ft) { + BT_LOGE_STR("Failed to allocate one variant field type."); + goto error; + } + + ret = init_named_field_types_container((void *) var_ft, + BT_FIELD_TYPE_ID_VARIANT, destroy_variant_field_type); + if (ret) { + goto error; + } + + BT_LIB_LOGD("Created variant field type object: %!+F", var_ft); + goto end; + +error: + BT_PUT(var_ft); + +end: + return (void *) var_ft; +} + +int bt_field_type_variant_set_selector_field_type( + struct bt_field_type *ft, struct bt_field_type *selector_ft) +{ + struct bt_field_type_variant *var_ft = (void *) ft; + + BT_ASSERT_PRE_NON_NULL(ft, "Variant field type"); + BT_ASSERT_PRE_NON_NULL(selector_ft, "Selector field type"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT, "Field type"); + BT_ASSERT_PRE_FT_IS_ENUM(selector_ft, "Selector field type"); + BT_ASSERT_PRE_FT_HOT(ft, "Variant field type"); + var_ft->selector_ft = selector_ft; + bt_field_type_freeze(selector_ft); + return 0; +} + +int bt_field_type_variant_append_option(struct bt_field_type *ft, + const char *name, struct bt_field_type *option_ft) +{ + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT, "Field type"); + return append_named_field_type_to_container_field_type((void *) ft, + name, option_ft); +} + +struct bt_field_type *bt_field_type_variant_borrow_option_field_type_by_name( + struct bt_field_type *ft, const char *name) +{ + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT, "Field type"); + return borrow_field_type_from_container_field_type_by_name((void *) ft, + name); +} + +uint64_t bt_field_type_variant_get_option_count(struct bt_field_type *ft) +{ + struct bt_field_type_variant *var_ft = (void *) ft; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT, "Field type"); + return (uint64_t) var_ft->common.named_fts->len; +} + +void bt_field_type_variant_borrow_option_by_index( + struct bt_field_type *ft, uint64_t index, + const char **name, struct bt_field_type **out_ft) +{ + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT, "Field type"); + borrow_named_field_type_from_container_field_type_at_index((void *) ft, + index, name, out_ft); +} + +struct bt_field_path *bt_field_type_variant_borrow_selector_field_path( + struct bt_field_type *ft) +{ + struct bt_field_type_variant *var_ft = (void *) ft; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT, + "Field type"); + return var_ft->selector_field_path; +} + +static +void init_array_field_type(struct bt_field_type_array *ft, + enum bt_field_type_id id, bt_object_release_func release_func, + struct bt_field_type *element_ft) +{ + BT_ASSERT(element_ft); + init_field_type((void *) ft, id, release_func); + ft->element_ft = bt_get(element_ft); + bt_field_type_freeze(element_ft); +} + +static +void finalize_array_field_type(struct bt_field_type_array *array_ft) +{ + BT_ASSERT(array_ft); + BT_LOGD_STR("Putting element field type."); + bt_put(array_ft->element_ft); +} + +static +void destroy_static_array_field_type(struct bt_object *obj) +{ + BT_ASSERT(obj); + BT_LIB_LOGD("Destroying static array field type object: %!+F", obj); + finalize_array_field_type((void *) obj); + g_free(obj); +} + +struct bt_field_type *bt_field_type_static_array_create( + struct bt_field_type *element_ft, uint64_t length) +{ + struct bt_field_type_static_array *array_ft = NULL; + + BT_ASSERT_PRE_NON_NULL(element_ft, "Element field type"); + BT_LOGD_STR("Creating default static array field type object."); + array_ft = g_new0(struct bt_field_type_static_array, 1); + if (!array_ft) { + BT_LOGE_STR("Failed to allocate one static array field type."); + goto error; + } + + init_array_field_type((void *) array_ft, BT_FIELD_TYPE_ID_STATIC_ARRAY, + destroy_static_array_field_type, element_ft); + array_ft->length = length; + BT_LIB_LOGD("Created static array field type object: %!+F", array_ft); + goto end; + +error: + BT_PUT(array_ft); + +end: + return (void *) array_ft; +} + +struct bt_field_type *bt_field_type_array_borrow_element_field_type( + struct bt_field_type *ft) +{ + struct bt_field_type_array *array_ft = (void *) ft; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_IS_ARRAY(ft, "Field type"); + return array_ft->element_ft; +} + +uint64_t bt_field_type_static_array_get_length(struct bt_field_type *ft) +{ + struct bt_field_type_static_array *array_ft = (void *) ft; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STATIC_ARRAY, + "Field type"); + return (uint64_t) array_ft->length; +} + +static +void destroy_dynamic_array_field_type(struct bt_object *obj) +{ + struct bt_field_type_dynamic_array *ft = (void *) obj; + + BT_ASSERT(ft); + BT_LIB_LOGD("Destroying dynamic array field type object: %!+F", ft); + finalize_array_field_type((void *) ft); + BT_LOGD_STR("Putting length field path."); + bt_put(ft->length_field_path); + g_free(ft); +} + +struct bt_field_type *bt_field_type_dynamic_array_create( + struct bt_field_type *element_ft) +{ + struct bt_field_type_dynamic_array *array_ft = NULL; + + BT_ASSERT_PRE_NON_NULL(element_ft, "Element field type"); + BT_LOGD_STR("Creating default dynamic array field type object."); + array_ft = g_new0(struct bt_field_type_dynamic_array, 1); + if (!array_ft) { + BT_LOGE_STR("Failed to allocate one dynamic array field type."); + goto error; + } + + init_array_field_type((void *) array_ft, BT_FIELD_TYPE_ID_DYNAMIC_ARRAY, + destroy_dynamic_array_field_type, element_ft); + BT_LIB_LOGD("Created dynamic array field type object: %!+F", array_ft); + goto end; + +error: + BT_PUT(array_ft); + +end: + return (void *) array_ft; +} + +int bt_field_type_dynamic_array_set_length_field_type(struct bt_field_type *ft, + struct bt_field_type *length_ft) +{ + struct bt_field_type_dynamic_array *array_ft = (void *) ft; + + BT_ASSERT_PRE_NON_NULL(ft, "Dynamic array field type"); + BT_ASSERT_PRE_NON_NULL(length_ft, "Length field type"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_DYNAMIC_ARRAY, + "Field type"); + BT_ASSERT_PRE_FT_IS_UNSIGNED_INT(length_ft, "Length field type"); + BT_ASSERT_PRE_FT_HOT(ft, "Dynamic array field type"); + array_ft->length_ft = length_ft; + bt_field_type_freeze(length_ft); + return 0; +} + +struct bt_field_path *bt_field_type_dynamic_array_borrow_length_field_path( + struct bt_field_type *ft) +{ + struct bt_field_type_dynamic_array *seq_ft = (void *) ft; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_DYNAMIC_ARRAY, + "Field type"); + return seq_ft->length_field_path; +} + +static +void destroy_string_field_type(struct bt_object *obj) +{ + BT_ASSERT(obj); + BT_LIB_LOGD("Destroying string field type object: %!+F", obj); + g_free(obj); +} + +struct bt_field_type *bt_field_type_string_create(void) +{ + struct bt_field_type_string *string_ft = NULL; + + BT_LOGD_STR("Creating default string field type object."); + string_ft = g_new0(struct bt_field_type_string, 1); + if (!string_ft) { + BT_LOGE_STR("Failed to allocate one string field type."); + goto error; + } + + init_field_type((void *) string_ft, BT_FIELD_TYPE_ID_STRING, + destroy_string_field_type); + BT_LIB_LOGD("Created string field type object: %!+F", string_ft); + goto end; + +error: + BT_PUT(string_ft); + +end: + return (void *) string_ft; +} + +BT_HIDDEN +void _bt_field_type_freeze(struct bt_field_type *ft) +{ + /* + * Element/member/option field types are frozen when added to + * their owner. + */ + BT_ASSERT(ft); + ft->frozen = true; +} + +BT_HIDDEN +void _bt_field_type_make_part_of_trace(struct bt_field_type *ft) +{ + BT_ASSERT(ft); + BT_ASSERT_PRE(!ft->part_of_trace, + "Field type is already part of a trace: %!+F", ft); + ft->part_of_trace = true; + + switch (ft->id) { + case BT_FIELD_TYPE_ID_STRUCTURE: + case BT_FIELD_TYPE_ID_VARIANT: + { + struct bt_field_type_named_field_types_container *container_ft = + (void *) ft; + uint64_t i; + + for (i = 0; i < container_ft->named_fts->len; i++) { + struct bt_named_field_type *named_ft = + BT_FIELD_TYPE_NAMED_FT_AT_INDEX( + container_ft, i); + + bt_field_type_make_part_of_trace(named_ft->ft); + } + + break; + } + case BT_FIELD_TYPE_ID_STATIC_ARRAY: + case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY: + { + struct bt_field_type_array *array_ft = (void *) ft; + + bt_field_type_make_part_of_trace(array_ft->element_ft); + break; + } + default: + break; + } +} diff --git a/lib/trace-ir/field-wrapper.c b/lib/trace-ir/field-wrapper.c new file mode 100644 index 00000000..7b13202a --- /dev/null +++ b/lib/trace-ir/field-wrapper.c @@ -0,0 +1,105 @@ +/* + * Copyright 2018 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "FIELD-WRAPPER" +#include + +#include +#include +#include +#include +#include + +BT_HIDDEN +struct bt_field_wrapper *bt_field_wrapper_new(void *data) +{ + struct bt_field_wrapper *field_wrapper = + g_new0(struct bt_field_wrapper, 1); + + BT_LOGD_STR("Creating empty field wrapper object."); + + if (!field_wrapper) { + BT_LOGE("Failed to allocate one field wrapper."); + goto end; + } + + bt_object_init_unique(&field_wrapper->base); + BT_LOGD("Created empty field wrapper object: addr=%p", + field_wrapper); + +end: + return field_wrapper; +} + +BT_HIDDEN +void bt_field_wrapper_destroy(struct bt_field_wrapper *field_wrapper) +{ + BT_LOGD("Destroying field wrapper: addr=%p", field_wrapper); + + if (field_wrapper->field) { + BT_LOGD_STR("Destroying field."); + bt_field_destroy((void *) field_wrapper->field); + } + + BT_LOGD_STR("Putting stream class."); + g_free(field_wrapper); +} + +BT_HIDDEN +struct bt_field_wrapper *bt_field_wrapper_create( + struct bt_object_pool *pool, struct bt_field_type *ft) +{ + struct bt_field_wrapper *field_wrapper = NULL; + + BT_ASSERT(pool); + BT_ASSERT(ft); + field_wrapper = bt_object_pool_create_object(pool); + if (!field_wrapper) { + BT_LIB_LOGE("Cannot allocate one field wrapper from field wrapper pool: " + "%![pool-]+o", pool); + goto error; + } + + if (!field_wrapper->field) { + field_wrapper->field = (void *) bt_field_create(ft); + if (!field_wrapper->field) { + BT_LIB_LOGE("Cannot create field wrapper from field type: " + "%![ft-]+F", ft); + goto error; + } + + BT_LIB_LOGD("Created initial field wrapper object: " + "wrapper-addr=%p, %![field-]+f", field_wrapper, + field_wrapper->field); + } + + goto end; + +error: + if (field_wrapper) { + bt_field_wrapper_destroy(field_wrapper); + field_wrapper = NULL; + } + +end: + return field_wrapper; +} diff --git a/lib/trace-ir/fields.c b/lib/trace-ir/fields.c new file mode 100644 index 00000000..ee37ede0 --- /dev/null +++ b/lib/trace-ir/fields.c @@ -0,0 +1,1104 @@ +/* + * fields.c + * + * Babeltrace trace IR - Event Fields + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "FIELDS" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static +void reset_single_field(struct bt_field *field); + +static +void reset_array_field(struct bt_field *field); + +static +void reset_structure_field(struct bt_field *field); + +static +void reset_variant_field(struct bt_field *field); + +static +void set_single_field_is_frozen(struct bt_field *field, bool is_frozen); + +static +void set_array_field_is_frozen(struct bt_field *field, bool is_frozen); + +static +void set_structure_field_is_frozen(struct bt_field *field, bool is_frozen); + +static +void set_variant_field_is_frozen(struct bt_field *field, bool is_frozen); + +static +bool single_field_is_set(struct bt_field *field); + +static +bool array_field_is_set(struct bt_field *field); + +static +bool structure_field_is_set(struct bt_field *field); + +static +bool variant_field_is_set(struct bt_field *field); + +static +struct bt_field_methods integer_field_methods = { + .set_is_frozen = set_single_field_is_frozen, + .is_set = single_field_is_set, + .reset = reset_single_field, +}; + +static +struct bt_field_methods real_field_methods = { + .set_is_frozen = set_single_field_is_frozen, + .is_set = single_field_is_set, + .reset = reset_single_field, +}; + +static +struct bt_field_methods string_field_methods = { + .set_is_frozen = set_single_field_is_frozen, + .is_set = single_field_is_set, + .reset = reset_single_field, +}; + +static +struct bt_field_methods structure_field_methods = { + .set_is_frozen = set_structure_field_is_frozen, + .is_set = structure_field_is_set, + .reset = reset_structure_field, +}; + +static +struct bt_field_methods array_field_methods = { + .set_is_frozen = set_array_field_is_frozen, + .is_set = array_field_is_set, + .reset = reset_array_field, +}; + +static +struct bt_field_methods variant_field_methods = { + .set_is_frozen = set_variant_field_is_frozen, + .is_set = variant_field_is_set, + .reset = reset_variant_field, +}; + +static +struct bt_field *create_integer_field(struct bt_field_type *); + +static +struct bt_field *create_real_field(struct bt_field_type *); + +static +struct bt_field *create_string_field(struct bt_field_type *); + +static +struct bt_field *create_structure_field(struct bt_field_type *); + +static +struct bt_field *create_static_array_field(struct bt_field_type *); + +static +struct bt_field *create_dynamic_array_field(struct bt_field_type *); + +static +struct bt_field *create_variant_field(struct bt_field_type *); + +static +struct bt_field *(* const field_create_funcs[])(struct bt_field_type *) = { + [BT_FIELD_TYPE_ID_UNSIGNED_INTEGER] = create_integer_field, + [BT_FIELD_TYPE_ID_SIGNED_INTEGER] = create_integer_field, + [BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION] = create_integer_field, + [BT_FIELD_TYPE_ID_SIGNED_ENUMERATION] = create_integer_field, + [BT_FIELD_TYPE_ID_REAL] = create_real_field, + [BT_FIELD_TYPE_ID_STRING] = create_string_field, + [BT_FIELD_TYPE_ID_STRUCTURE] = create_structure_field, + [BT_FIELD_TYPE_ID_STATIC_ARRAY] = create_static_array_field, + [BT_FIELD_TYPE_ID_DYNAMIC_ARRAY] = create_dynamic_array_field, + [BT_FIELD_TYPE_ID_VARIANT] = create_variant_field, +}; + +static +void destroy_integer_field(struct bt_field *field); + +static +void destroy_real_field(struct bt_field *field); + +static +void destroy_string_field(struct bt_field *field); + +static +void destroy_structure_field(struct bt_field *field); + +static +void destroy_array_field(struct bt_field *field); + +static +void destroy_variant_field(struct bt_field *field); + +static +void (* const field_destroy_funcs[])(struct bt_field *) = { + [BT_FIELD_TYPE_ID_UNSIGNED_INTEGER] = destroy_integer_field, + [BT_FIELD_TYPE_ID_SIGNED_INTEGER] = destroy_integer_field, + [BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION] = destroy_integer_field, + [BT_FIELD_TYPE_ID_SIGNED_ENUMERATION] = destroy_integer_field, + [BT_FIELD_TYPE_ID_REAL] = destroy_real_field, + [BT_FIELD_TYPE_ID_STRING] = destroy_string_field, + [BT_FIELD_TYPE_ID_STRUCTURE] = destroy_structure_field, + [BT_FIELD_TYPE_ID_STATIC_ARRAY] = destroy_array_field, + [BT_FIELD_TYPE_ID_DYNAMIC_ARRAY] = destroy_array_field, + [BT_FIELD_TYPE_ID_VARIANT] = destroy_variant_field, +}; + +struct bt_field_type *bt_field_borrow_type(struct bt_field *field) +{ + BT_ASSERT_PRE_NON_NULL(field, "Field"); + return field->type; +} + +enum bt_field_type_id bt_field_get_type_id(struct bt_field *field) +{ + BT_ASSERT_PRE_NON_NULL(field, "Field"); + return field->type->id; +} + +BT_HIDDEN +struct bt_field *bt_field_create(struct bt_field_type *ft) +{ + struct bt_field *field = NULL; + + BT_ASSERT_PRE_NON_NULL(ft, "Field type"); + BT_ASSERT(bt_field_type_has_known_id(ft)); + field = field_create_funcs[ft->id](ft); + if (!field) { + BT_LIB_LOGE("Cannot create field object from field type: " + "%![ft-]+F", ft); + goto end; + } + +end: + return field; +} + +static inline +void init_field(struct bt_field *field, struct bt_field_type *ft, + struct bt_field_methods *methods) +{ + BT_ASSERT(field); + BT_ASSERT(ft); + bt_object_init_unique(&field->base); + field->methods = methods; + field->type = bt_get(ft); +} + +static +struct bt_field *create_integer_field(struct bt_field_type *ft) +{ + struct bt_field_integer *int_field; + + BT_LIB_LOGD("Creating integer field object: %![ft-]+F", ft); + int_field = g_new0(struct bt_field_integer, 1); + if (!int_field) { + BT_LOGE_STR("Failed to allocate one integer field."); + goto end; + } + + init_field((void *) int_field, ft, &integer_field_methods); + BT_LIB_LOGD("Created integer field object: %!+f", int_field); + +end: + return (void *) int_field; +} + +static +struct bt_field *create_real_field(struct bt_field_type *ft) +{ + struct bt_field_real *real_field; + + BT_LIB_LOGD("Creating real field object: %![ft-]+F", ft); + real_field = g_new0(struct bt_field_real, 1); + if (!real_field) { + BT_LOGE_STR("Failed to allocate one real field."); + goto end; + } + + init_field((void *) real_field, ft, &real_field_methods); + BT_LIB_LOGD("Created real field object: %!+f", real_field); + +end: + return (void *) real_field; +} + +static +struct bt_field *create_string_field(struct bt_field_type *ft) +{ + struct bt_field_string *string_field; + + BT_LIB_LOGD("Creating string field object: %![ft-]+F", ft); + string_field = g_new0(struct bt_field_string, 1); + if (!string_field) { + BT_LOGE_STR("Failed to allocate one string field."); + goto end; + } + + init_field((void *) string_field, ft, &string_field_methods); + string_field->buf = g_array_sized_new(FALSE, FALSE, + sizeof(char), 1); + if (!string_field->buf) { + BT_LOGE_STR("Failed to allocate a GArray."); + BT_PUT(string_field); + goto end; + } + + g_array_index(string_field->buf, char, 0) = '\0'; + BT_LIB_LOGD("Created string field object: %!+f", string_field); + +end: + return (void *) string_field; +} + +static inline +int create_fields_from_named_field_types( + struct bt_field_type_named_field_types_container *ft, + GPtrArray **fields) +{ + int ret = 0; + uint64_t i; + + *fields = g_ptr_array_new_with_free_func( + (GDestroyNotify) bt_field_destroy); + if (!*fields) { + BT_LOGE_STR("Failed to allocate a GPtrArray."); + ret = -1; + goto end; + } + + g_ptr_array_set_size(*fields, ft->named_fts->len); + + for (i = 0; i < ft->named_fts->len; i++) { + struct bt_field *field; + struct bt_named_field_type *named_ft = + BT_FIELD_TYPE_NAMED_FT_AT_INDEX(ft, i); + + field = bt_field_create(named_ft->ft); + if (!field) { + BT_LIB_LOGE("Failed to create structure member or variant option field: " + "name=\"%s\", %![ft-]+F", + named_ft->name->str, named_ft->ft); + ret = -1; + goto end; + } + + g_ptr_array_index(*fields, i) = field; + } + +end: + return ret; +} + +static +struct bt_field *create_structure_field(struct bt_field_type *ft) +{ + struct bt_field_structure *struct_field; + + BT_LIB_LOGD("Creating structure field object: %![ft-]+F", ft); + struct_field = g_new0(struct bt_field_structure, 1); + if (!struct_field) { + BT_LOGE_STR("Failed to allocate one structure field."); + goto end; + } + + init_field((void *) struct_field, ft, &structure_field_methods); + + if (create_fields_from_named_field_types((void *) ft, + &struct_field->fields)) { + BT_LIB_LOGE("Cannot create structure member fields: " + "%![ft-]+F", ft); + BT_PUT(struct_field); + goto end; + } + + BT_LIB_LOGD("Created structure field object: %!+f", struct_field); + +end: + return (void *) struct_field; +} + +static +struct bt_field *create_variant_field(struct bt_field_type *ft) +{ + struct bt_field_variant *var_field; + + BT_LIB_LOGD("Creating variant field object: %![ft-]+F", ft); + var_field = g_new0(struct bt_field_variant, 1); + if (!var_field) { + BT_LOGE_STR("Failed to allocate one variant field."); + goto end; + } + + init_field((void *) var_field, ft, &variant_field_methods); + + if (create_fields_from_named_field_types((void *) ft, + &var_field->fields)) { + BT_LIB_LOGE("Cannot create variant member fields: " + "%![ft-]+F", ft); + BT_PUT(var_field); + goto end; + } + + BT_LIB_LOGD("Created variant field object: %!+f", var_field); + +end: + return (void *) var_field; +} + +static inline +int init_array_field_fields(struct bt_field_array *array_field) +{ + int ret = 0; + uint64_t i; + struct bt_field_type_array *array_ft; + + BT_ASSERT(array_field); + array_ft = (void *) array_field->common.type; + array_field->fields = g_ptr_array_sized_new(array_field->length); + if (!array_field->fields) { + BT_LOGE_STR("Failed to allocate a GPtrArray."); + ret = -1; + goto end; + } + + g_ptr_array_set_free_func(array_field->fields, + (GDestroyNotify) bt_field_destroy); + g_ptr_array_set_size(array_field->fields, array_field->length); + + for (i = 0; i < array_field->length; i++) { + array_field->fields->pdata[i] = bt_field_create( + array_ft->element_ft); + if (!array_field->fields->pdata[i]) { + BT_LIB_LOGE("Cannot create array field's element field: " + "index=%" PRIu64 ", %![ft-]+F", i, array_ft); + ret = -1; + goto end; + } + } + +end: + return ret; +} + +static +struct bt_field *create_static_array_field(struct bt_field_type *ft) +{ + struct bt_field_type_static_array *array_ft = (void *) ft; + struct bt_field_array *array_field; + + BT_LIB_LOGD("Creating static array field object: %![ft-]+F", ft); + array_field = g_new0(struct bt_field_array, 1); + if (!array_field) { + BT_LOGE_STR("Failed to allocate one static array field."); + goto end; + } + + init_field((void *) array_field, ft, &array_field_methods); + array_field->length = array_ft->length; + + if (init_array_field_fields(array_field)) { + BT_LIB_LOGE("Cannot create static array fields: " + "%![ft-]+F", ft); + BT_PUT(array_field); + goto end; + } + + BT_LIB_LOGD("Created static array field object: %!+f", array_field); + +end: + return (void *) array_field; +} + +static +struct bt_field *create_dynamic_array_field(struct bt_field_type *ft) +{ + struct bt_field_array *array_field; + + BT_LIB_LOGD("Creating dynamic array field object: %![ft-]+F", ft); + array_field = g_new0(struct bt_field_array, 1); + if (!array_field) { + BT_LOGE_STR("Failed to allocate one dynamic array field."); + goto end; + } + + init_field((void *) array_field, ft, &array_field_methods); + + if (init_array_field_fields(array_field)) { + BT_LIB_LOGE("Cannot create dynamic array fields: " + "%![ft-]+F", ft); + BT_PUT(array_field); + goto end; + } + + BT_LIB_LOGD("Created dynamic array field object: %!+f", array_field); + +end: + return (void *) array_field; +} + +int64_t bt_field_signed_integer_get_value(struct bt_field *field) +{ + struct bt_field_integer *int_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_FIELD_IS_SET(field, "Field"); + BT_ASSERT_PRE_FIELD_IS_SIGNED_INT(field, "Field"); + return int_field->value.i; +} + +void bt_field_signed_integer_set_value(struct bt_field *field, int64_t value) +{ + struct bt_field_integer *int_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_FIELD_IS_SIGNED_INT(field, "Field"); + BT_ASSERT_PRE_FIELD_HOT(field, "Field"); + BT_ASSERT_PRE(bt_util_value_is_in_range_signed( + ((struct bt_field_type_integer *) field->type)->range, value), + "Value is out of bounds: value=%" PRId64 ", %![field-]+f, " + "%![ft-]+F", value, field, field->type); + int_field->value.i = value; + bt_field_set_single(field, true); +} + +uint64_t bt_field_unsigned_integer_get_value(struct bt_field *field) +{ + struct bt_field_integer *int_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_FIELD_IS_SET(field, "Field"); + BT_ASSERT_PRE_FIELD_IS_UNSIGNED_INT(field, "Field"); + return int_field->value.u; +} + +void bt_field_unsigned_integer_set_value(struct bt_field *field, + uint64_t value) +{ + struct bt_field_integer *int_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_FIELD_IS_UNSIGNED_INT(field, "Field"); + BT_ASSERT_PRE_FIELD_HOT(field, "Field"); + BT_ASSERT_PRE(bt_util_value_is_in_range_unsigned( + ((struct bt_field_type_integer *) field->type)->range, value), + "Value is out of bounds: value=%" PRIu64 ", %![field-]+f, " + "%![ft-]+F", value, field, field->type); + int_field->value.u = value; + bt_field_set_single(field, true); +} + +double bt_field_real_get_value(struct bt_field *field) +{ + struct bt_field_real *real_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_FIELD_IS_SET(field, "Field"); + BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_REAL, "Field"); + return real_field->value; +} + +void bt_field_real_set_value(struct bt_field *field, double value) +{ + struct bt_field_real *real_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_REAL, "Field"); + BT_ASSERT_PRE_FIELD_HOT(field, "Field"); + BT_ASSERT_PRE( + !((struct bt_field_type_real *) field->type)->is_single_precision || + (double) (float) value == value, + "Invalid value for a single-precision real number: value=%f, " + "%![ft-]+F", value, field->type); + real_field->value = value; + bt_field_set_single(field, true); +} + +int bt_field_unsigned_enumeration_get_mapping_labels(struct bt_field *field, + bt_field_type_enumeration_mapping_label_array *label_array, + uint64_t *count) +{ + struct bt_field_integer *int_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_NON_NULL(label_array, "Label array (output)"); + BT_ASSERT_PRE_NON_NULL(label_array, "Count (output)"); + BT_ASSERT_PRE_FIELD_IS_SET(field, "Field"); + BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, + BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION, "Field"); + return bt_field_type_unsigned_enumeration_get_mapping_labels_by_value( + field->type, int_field->value.u, label_array, count); +} + +int bt_field_signed_enumeration_get_mapping_labels(struct bt_field *field, + bt_field_type_enumeration_mapping_label_array *label_array, + uint64_t *count) +{ + struct bt_field_integer *int_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_NON_NULL(label_array, "Label array (output)"); + BT_ASSERT_PRE_NON_NULL(label_array, "Count (output)"); + BT_ASSERT_PRE_FIELD_IS_SET(field, "Field"); + BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, + BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, "Field"); + return bt_field_type_signed_enumeration_get_mapping_labels_by_value( + field->type, int_field->value.i, label_array, count); +} + +const char *bt_field_string_get_value(struct bt_field *field) +{ + struct bt_field_string *string_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_FIELD_IS_SET(field, "Field"); + BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, + "Field"); + return (const char *) string_field->buf->data; +} + +uint64_t bt_field_string_get_length(struct bt_field *field) +{ + struct bt_field_string *string_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_FIELD_IS_SET(field, "Field"); + BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, + "Field"); + return string_field->length; +} + +int bt_field_string_set_value(struct bt_field *field, const char *value) +{ + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_NON_NULL(value, "Value"); + BT_ASSERT_PRE_FIELD_HOT(field, "Field"); + BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, + "Field"); + bt_field_string_clear(field); + return bt_field_string_append_with_length(field, value, + (uint64_t) strlen(value)); +} + +int bt_field_string_append(struct bt_field *field, const char *value) +{ + return bt_field_string_append_with_length(field, value, + (uint64_t) strlen(value)); +} + +int bt_field_string_append_with_length(struct bt_field *field, + const char *value, uint64_t length) +{ + struct bt_field_string *string_field = (void *) field; + char *data; + uint64_t new_length; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_NON_NULL(value, "Value"); + BT_ASSERT_PRE_FIELD_HOT(field, "Field"); + BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, + BT_FIELD_TYPE_ID_STRING, "Field"); + + /* Make sure no null bytes are appended */ + BT_ASSERT_PRE(memchr(value, '\0', length) == NULL, + "String value to append contains a null character: " + "partial-value=\"%.32s\", length=%" PRIu64, value, length); + + new_length = length + string_field->length; + + if (unlikely(new_length + 1 > string_field->buf->len)) { + g_array_set_size(string_field->buf, new_length + 1); + } + + data = string_field->buf->data; + memcpy(data + string_field->length, value, length); + ((char *) string_field->buf->data)[new_length] = '\0'; + string_field->length = new_length; + bt_field_set_single(field, true); + return 0; +} + +int bt_field_string_clear(struct bt_field *field) +{ + struct bt_field_string *string_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_FIELD_HOT(field, "Field"); + BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, + BT_FIELD_TYPE_ID_STRING, "Field"); + string_field->length = 0; + bt_field_set_single(field, true); + return 0; +} + +uint64_t bt_field_array_get_length(struct bt_field *field) +{ + struct bt_field_array *array_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_FIELD_IS_ARRAY(field, "Field"); + return array_field->length; +} + +int bt_field_dynamic_array_set_length(struct bt_field *field, + uint64_t length) +{ + int ret = 0; + struct bt_field_array *array_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, + BT_FIELD_TYPE_ID_DYNAMIC_ARRAY, "Field"); + BT_ASSERT_PRE_FIELD_HOT(field, "Field"); + + if (unlikely(length > array_field->fields->len)) { + /* Make more room */ + struct bt_field_type_array *array_ft; + uint64_t cur_len = array_field->fields->len; + uint64_t i; + + g_ptr_array_set_size(array_field->fields, length); + array_ft = (void *) field->type; + + for (i = cur_len; i < array_field->fields->len; i++) { + struct bt_field *elem_field = bt_field_create( + array_ft->element_ft); + + if (!elem_field) { + BT_LIB_LOGE("Cannot create element field for " + "dynamic array field: " + "index=%" PRIu64 ", " + "%![array-field-]+f", i, field); + ret = -1; + goto end; + } + + BT_ASSERT(!array_field->fields->pdata[i]); + array_field->fields->pdata[i] = elem_field; + } + } + + array_field->length = length; + +end: + return ret; +} + +struct bt_field *bt_field_array_borrow_element_field_by_index( + struct bt_field *field, uint64_t index) +{ + struct bt_field_array *array_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_FIELD_IS_ARRAY(field, "Field"); + BT_ASSERT_PRE_VALID_INDEX(index, array_field->length); + return array_field->fields->pdata[index]; +} + +struct bt_field *bt_field_structure_borrow_member_field_by_index( + struct bt_field *field, uint64_t index) +{ + struct bt_field_structure *struct_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, + BT_FIELD_TYPE_ID_STRUCTURE, "Field"); + BT_ASSERT_PRE_VALID_INDEX(index, struct_field->fields->len); + return struct_field->fields->pdata[index]; +} + +struct bt_field *bt_field_structure_borrow_member_field_by_name( + struct bt_field *field, const char *name) +{ + struct bt_field *ret_field = NULL; + struct bt_field_type_structure *struct_ft; + struct bt_field_structure *struct_field = (void *) field; + gpointer orig_key; + gpointer index; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_NON_NULL(name, "Field name"); + BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, + BT_FIELD_TYPE_ID_STRUCTURE, "Field"); + struct_ft = (void *) field->type; + + if (!g_hash_table_lookup_extended(struct_ft->common.name_to_index, name, + &orig_key, &index)) { + goto end; + } + + ret_field = struct_field->fields->pdata[GPOINTER_TO_UINT(index)]; + BT_ASSERT(ret_field); + +end: + return ret_field; +} + +struct bt_field *bt_field_variant_borrow_selected_option_field( + struct bt_field *field) +{ + struct bt_field_variant *var_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, + BT_FIELD_TYPE_ID_VARIANT, "Field"); + BT_ASSERT_PRE(var_field->selected_field, + "Variant field has no selected field: %!+f", field); + return var_field->selected_field; +} + +int bt_field_variant_select_option_field(struct bt_field *field, + uint64_t index) +{ + struct bt_field_variant *var_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, + BT_FIELD_TYPE_ID_VARIANT, "Field"); + BT_ASSERT_PRE_FIELD_HOT(field, "Field"); + BT_ASSERT_PRE_VALID_INDEX(index, var_field->fields->len); + var_field->selected_field = var_field->fields->pdata[index]; + var_field->selected_index = index; + return 0; +} + +uint64_t bt_field_variant_get_selected_option_field_index( + struct bt_field *field) +{ + struct bt_field_variant *var_field = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, + BT_FIELD_TYPE_ID_VARIANT, "Field"); + BT_ASSERT_PRE(var_field->selected_field, + "Variant field has no selected field: %!+f", field); + return var_field->selected_index; +} + +static inline +void bt_field_finalize(struct bt_field *field) +{ + BT_ASSERT(field); + BT_LOGD_STR("Putting field's type."); + bt_put(field->type); +} + +static +void destroy_integer_field(struct bt_field *field) +{ + BT_ASSERT(field); + BT_LIB_LOGD("Destroying integer field object: %!+f", field); + bt_field_finalize(field); + g_free(field); +} + +static +void destroy_real_field(struct bt_field *field) +{ + BT_ASSERT(field); + BT_LIB_LOGD("Destroying real field object: %!+f", field); + bt_field_finalize(field); + g_free(field); +} + +static +void destroy_structure_field(struct bt_field *field) +{ + struct bt_field_structure *struct_field = (void *) field; + + BT_ASSERT(field); + BT_LIB_LOGD("Destroying structure field object: %!+f", field); + bt_field_finalize(field); + + if (struct_field->fields) { + g_ptr_array_free(struct_field->fields, TRUE); + } + + g_free(field); +} + +static +void destroy_variant_field(struct bt_field *field) +{ + struct bt_field_variant *var_field = (void *) field; + + BT_ASSERT(field); + BT_LIB_LOGD("Destroying variant field object: %!+f", field); + bt_field_finalize(field); + + if (var_field->fields) { + g_ptr_array_free(var_field->fields, TRUE); + } + + g_free(field); +} + +static +void destroy_array_field(struct bt_field *field) +{ + struct bt_field_array *array_field = (void *) field; + + BT_ASSERT(field); + BT_LIB_LOGD("Destroying array field object: %!+f", field); + bt_field_finalize(field); + + if (array_field->fields) { + g_ptr_array_free(array_field->fields, TRUE); + } + + g_free(field); +} + +static +void destroy_string_field(struct bt_field *field) +{ + struct bt_field_string *string_field = (void *) field; + + BT_ASSERT(field); + BT_LIB_LOGD("Destroying string field object: %!+f", field); + bt_field_finalize(field); + + if (string_field->buf) { + g_array_free(string_field->buf, TRUE); + } + + g_free(field); +} + +BT_HIDDEN +void bt_field_destroy(struct bt_field *field) +{ + BT_ASSERT(field); + BT_ASSERT(bt_field_type_has_known_id(field->type)); + field_destroy_funcs[field->type->id](field); +} + +static +void reset_single_field(struct bt_field *field) +{ + BT_ASSERT(field); + field->is_set = false; +} + +static +void reset_structure_field(struct bt_field *field) +{ + uint64_t i; + struct bt_field_structure *struct_field = (void *) field; + + BT_ASSERT(field); + + for (i = 0; i < struct_field->fields->len; i++) { + bt_field_reset(struct_field->fields->pdata[i]); + } +} + +static +void reset_variant_field(struct bt_field *field) +{ + uint64_t i; + struct bt_field_variant *var_field = (void *) field; + + BT_ASSERT(field); + + for (i = 0; i < var_field->fields->len; i++) { + bt_field_reset(var_field->fields->pdata[i]); + } +} + +static +void reset_array_field(struct bt_field *field) +{ + uint64_t i; + struct bt_field_array *array_field = (void *) field; + + BT_ASSERT(field); + + for (i = 0; i < array_field->fields->len; i++) { + bt_field_reset(array_field->fields->pdata[i]); + } +} + +static +void set_single_field_is_frozen(struct bt_field *field, bool is_frozen) +{ + field->frozen = is_frozen; +} + +static +void set_structure_field_is_frozen(struct bt_field *field, bool is_frozen) +{ + uint64_t i; + struct bt_field_structure *struct_field = (void *) field; + + BT_LIB_LOGD("Setting structure field's frozen state: " + "%![field-]+f, is-frozen=%d", field, is_frozen); + + for (i = 0; i < struct_field->fields->len; i++) { + struct bt_field *member_field = struct_field->fields->pdata[i]; + + BT_LIB_LOGD("Setting structure field's member field's " + "frozen state: %![field-]+f, index=%" PRIu64, + member_field, i); + bt_field_set_is_frozen(member_field, is_frozen); + } + + set_single_field_is_frozen(field, is_frozen); +} + +static +void set_variant_field_is_frozen(struct bt_field *field, bool is_frozen) +{ + uint64_t i; + struct bt_field_variant *var_field = (void *) field; + + BT_LIB_LOGD("Setting variant field's frozen state: " + "%![field-]+f, is-frozen=%d", field, is_frozen); + + for (i = 0; i < var_field->fields->len; i++) { + struct bt_field *option_field = var_field->fields->pdata[i]; + + BT_LIB_LOGD("Setting variant field's option field's " + "frozen state: %![field-]+f, index=%" PRIu64, + option_field, i); + bt_field_set_is_frozen(option_field, is_frozen); + } + + set_single_field_is_frozen(field, is_frozen); +} + +static +void set_array_field_is_frozen(struct bt_field *field, bool is_frozen) +{ + uint64_t i; + struct bt_field_array *array_field = (void *) field; + + BT_LIB_LOGD("Setting array field's frozen state: " + "%![field-]+f, is-frozen=%d", field, is_frozen); + + for (i = 0; i < array_field->fields->len; i++) { + struct bt_field *elem_field = array_field->fields->pdata[i]; + + BT_LIB_LOGD("Setting array field's element field's " + "frozen state: %![field-]+f, index=%" PRIu64, + elem_field, i); + bt_field_set_is_frozen(elem_field, is_frozen); + } + + set_single_field_is_frozen(field, is_frozen); +} + +BT_HIDDEN +void _bt_field_set_is_frozen(struct bt_field *field, + bool is_frozen) +{ + BT_ASSERT(field); + BT_LIB_LOGD("Setting field object's frozen state: %!+f, is-frozen=%d", + field, is_frozen); + BT_ASSERT(field->methods->set_is_frozen); + field->methods->set_is_frozen(field, is_frozen); +} + +static +bool single_field_is_set(struct bt_field *field) +{ + BT_ASSERT(field); + return field->is_set; +} + +static +bool structure_field_is_set(struct bt_field *field) +{ + bool is_set = true; + uint64_t i; + struct bt_field_structure *struct_field = (void *) field; + + BT_ASSERT(field); + + for (i = 0; i < struct_field->fields->len; i++) { + is_set = bt_field_is_set(struct_field->fields->pdata[i]); + if (!is_set) { + goto end; + } + } + +end: + return is_set; +} + +static +bool variant_field_is_set(struct bt_field *field) +{ + struct bt_field_variant *var_field = (void *) field; + bool is_set = false; + + BT_ASSERT(field); + + if (var_field->selected_field) { + is_set = bt_field_is_set(var_field->selected_field); + } + + return is_set; +} + +static +bool array_field_is_set(struct bt_field *field) +{ + bool is_set = true; + uint64_t i; + struct bt_field_array *array_field = (void *) field; + + BT_ASSERT(field); + + for (i = 0; i < array_field->length; i++) { + is_set = bt_field_is_set(array_field->fields->pdata[i]); + if (!is_set) { + goto end; + } + } + +end: + return is_set; +} diff --git a/lib/trace-ir/packet-context-field.c b/lib/trace-ir/packet-context-field.c new file mode 100644 index 00000000..b3827435 --- /dev/null +++ b/lib/trace-ir/packet-context-field.c @@ -0,0 +1,90 @@ +/* + * Copyright 2018 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "PACKET-CONTEXT-FIELD" +#include + +#include +#include +#include +#include +#include +#include + +struct bt_field *bt_packet_context_field_borrow_field( + struct bt_packet_context_field *context_field) +{ + struct bt_field_wrapper *field_wrapper = (void *) context_field; + + BT_ASSERT_PRE_NON_NULL(field_wrapper, "Packet context field"); + return field_wrapper->field; +} + +void bt_packet_context_field_release(struct bt_packet_context_field *context_field) +{ + struct bt_field_wrapper *field_wrapper = (void *) context_field; + + BT_ASSERT_PRE_NON_NULL(field_wrapper, "Packet context field"); + + /* + * Do not recycle because the pool could be destroyed at this + * point. This function is only called when there's an error + * anyway because the goal of a packet context field wrapper is + * to eventually move it to a packet with + * bt_packet_move_context() after creating it. + */ + bt_field_wrapper_destroy(field_wrapper); +} + +struct bt_packet_context_field *bt_packet_context_field_create( + struct bt_stream_class *stream_class) +{ + struct bt_field_wrapper *field_wrapper; + + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE(stream_class->frozen, + "Stream class is not part of a trace: %!+S", stream_class); + BT_ASSERT_PRE(stream_class->packet_context_ft, + "Stream class has no packet context field type: %!+S", + stream_class); + field_wrapper = bt_field_wrapper_create( + &stream_class->packet_context_field_pool, + (void *) stream_class->packet_context_ft); + if (!field_wrapper) { + BT_LIB_LOGE("Cannot allocate one packet context field from stream class: " + "%![sc-]+S", stream_class); + goto error; + } + + BT_ASSERT(field_wrapper->field); + bt_stream_class_freeze(stream_class); + goto end; + +error: + if (field_wrapper) { + bt_field_wrapper_destroy(field_wrapper); + field_wrapper = NULL; + } + +end: + return (void *) field_wrapper; +} diff --git a/lib/trace-ir/packet-header-field.c b/lib/trace-ir/packet-header-field.c new file mode 100644 index 00000000..7f9519eb --- /dev/null +++ b/lib/trace-ir/packet-header-field.c @@ -0,0 +1,87 @@ +/* + * Copyright 2018 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "PACKET-HEADER-FIELD" +#include + +#include +#include +#include +#include +#include +#include + +struct bt_field *bt_packet_header_field_borrow_field( + struct bt_packet_header_field *header_field) +{ + struct bt_field_wrapper *field_wrapper = (void *) header_field; + + BT_ASSERT_PRE_NON_NULL(field_wrapper, "Packet header field"); + return (void *) field_wrapper->field; +} + +void bt_packet_header_field_release(struct bt_packet_header_field *header_field) +{ + struct bt_field_wrapper *field_wrapper = (void *) header_field; + + BT_ASSERT_PRE_NON_NULL(field_wrapper, "Packet header field"); + + /* + * Do not recycle because the pool could be destroyed at this + * point. This function is only called when there's an error + * anyway because the goal of a packet header field wrapper is + * to eventually move it to a packet with + * bt_packet_move_header() after creating it. + */ + bt_field_wrapper_destroy(field_wrapper); +} + +struct bt_packet_header_field *bt_packet_header_field_create( + struct bt_trace *trace) +{ + struct bt_field_wrapper *field_wrapper; + + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE(trace->packet_header_ft, + "Trace has no packet header field type: %!+t", trace); + field_wrapper = bt_field_wrapper_create( + &trace->packet_header_field_pool, + (void *) trace->packet_header_ft); + if (!field_wrapper) { + BT_LIB_LOGE("Cannot allocate one packet header field from trace: " + "%![trace-]+t", trace); + goto error; + } + + BT_ASSERT(field_wrapper->field); + bt_trace_freeze(trace); + goto end; + +error: + if (field_wrapper) { + bt_field_wrapper_destroy(field_wrapper); + field_wrapper = NULL; + } + +end: + return (void *) field_wrapper; +} diff --git a/lib/trace-ir/packet.c b/lib/trace-ir/packet.c new file mode 100644 index 00000000..d6677212 --- /dev/null +++ b/lib/trace-ir/packet.c @@ -0,0 +1,488 @@ +/* + * packet.c + * + * Babeltrace trace IR - Stream packet + * + * Copyright 2016 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "PACKET" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BT_ASSERT_PRE_PACKET_HOT(_packet) \ + BT_ASSERT_PRE_HOT((_packet), "Packet", ": %!+a", (_packet)) + +struct bt_stream *bt_packet_borrow_stream(struct bt_packet *packet) +{ + BT_ASSERT_PRE_NON_NULL(packet, "Packet"); + return packet->stream; +} + +struct bt_field *bt_packet_borrow_header_field(struct bt_packet *packet) +{ + BT_ASSERT_PRE_NON_NULL(packet, "Packet"); + return packet->header_field ? packet->header_field->field : NULL; +} + +struct bt_field *bt_packet_borrow_context_field(struct bt_packet *packet) +{ + BT_ASSERT_PRE_NON_NULL(packet, "Packet"); + return packet->context_field ? packet->context_field->field : NULL; +} + +BT_HIDDEN +void _bt_packet_set_is_frozen(struct bt_packet *packet, bool is_frozen) +{ + if (!packet) { + return; + } + + BT_LIB_LOGD("Setting packet's frozen state: %![packet-]+a, " + "is-frozen=%d", packet, is_frozen); + + if (packet->header_field) { + BT_LOGD_STR("Setting packet's header field's frozen state."); + bt_field_set_is_frozen(packet->header_field->field, + is_frozen); + } + + if (packet->context_field) { + BT_LOGD_STR("Setting packet's context field's frozen state."); + bt_field_set_is_frozen(packet->context_field->field, + is_frozen); + } + + packet->frozen = is_frozen; +} + +static inline +void reset_counter_snapshots(struct bt_packet *packet) +{ + packet->discarded_event_counter_snapshot.base.avail = + BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE; + packet->packet_counter_snapshot.base.avail = + BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE; +} + +static inline +void reset_packet(struct bt_packet *packet) +{ + BT_ASSERT(packet); + BT_LIB_LOGD("Resetting packet: %!+a", packet); + bt_packet_set_is_frozen(packet, false); + + if (packet->header_field) { + bt_field_set_is_frozen(packet->header_field->field, false); + bt_field_reset(packet->header_field->field); + } + + if (packet->context_field) { + bt_field_set_is_frozen(packet->context_field->field, false); + bt_field_reset(packet->context_field->field); + } + + if (packet->default_beginning_cv) { + bt_clock_value_reset(packet->default_beginning_cv); + } + + if (packet->default_end_cv) { + bt_clock_value_reset(packet->default_end_cv); + } + + reset_counter_snapshots(packet); +} + +static +void recycle_header_field(struct bt_field_wrapper *header_field, + struct bt_trace *trace) +{ + BT_ASSERT(header_field); + BT_LIB_LOGD("Recycling packet header field: " + "addr=%p, %![trace-]+t, %![field-]+f", header_field, + trace, header_field->field); + bt_object_pool_recycle_object(&trace->packet_header_field_pool, + header_field); +} + +static +void recycle_context_field(struct bt_field_wrapper *context_field, + struct bt_stream_class *stream_class) +{ + BT_ASSERT(context_field); + BT_LIB_LOGD("Recycling packet context field: " + "addr=%p, %![sc-]+S, %![field-]+f", context_field, + stream_class, context_field->field); + bt_object_pool_recycle_object(&stream_class->packet_context_field_pool, + context_field); +} + +BT_HIDDEN +void bt_packet_recycle(struct bt_packet *packet) +{ + struct bt_stream *stream; + + BT_ASSERT(packet); + BT_LIB_LOGD("Recycling packet: %!+a", packet); + + /* + * Those are the important ordered steps: + * + * 1. Reset the packet object (put any permanent reference it + * has, unfreeze it and its fields in developer mode, etc.), + * but do NOT put its stream's reference. This stream + * contains the pool to which we're about to recycle this + * packet object, so we must guarantee its existence thanks + * to this existing reference. + * + * 2. Move the stream reference to our `stream` + * variable so that we can set the packet's stream member + * to NULL before recycling it. We CANNOT do this after + * we put the stream reference because this bt_put() + * could destroy the stream, also destroying its + * packet pool, thus also destroying our packet object (this + * would result in an invalid write access). + * + * 3. Recycle the packet object. + * + * 4. Put our stream reference. + */ + reset_packet(packet); + stream = packet->stream; + BT_ASSERT(stream); + packet->stream = NULL; + bt_object_pool_recycle_object(&stream->packet_pool, packet); + bt_object_put_no_null_check(&stream->base); +} + +BT_HIDDEN +void bt_packet_destroy(struct bt_packet *packet) +{ + BT_LIB_LOGD("Destroying packet: %!+a", packet); + + if (packet->header_field) { + if (packet->stream) { + BT_LOGD_STR("Recycling packet's header field."); + recycle_header_field(packet->header_field, + bt_stream_class_borrow_trace_inline( + packet->stream->class)); + } else { + bt_field_wrapper_destroy(packet->header_field); + } + } + + if (packet->context_field) { + if (packet->stream) { + BT_LOGD_STR("Recycling packet's context field."); + recycle_context_field(packet->context_field, + packet->stream->class); + } else { + bt_field_wrapper_destroy(packet->context_field); + } + } + + if (packet->default_beginning_cv) { + BT_LOGD_STR("Recycling beginning clock value."); + bt_clock_value_recycle(packet->default_beginning_cv); + } + + if (packet->default_end_cv) { + BT_LOGD_STR("Recycling end clock value."); + bt_clock_value_recycle(packet->default_end_cv); + } + + BT_LOGD_STR("Putting packet's stream."); + bt_put(packet->stream); + g_free(packet); +} + +BT_HIDDEN +struct bt_packet *bt_packet_new(struct bt_stream *stream) +{ + struct bt_packet *packet = NULL; + struct bt_trace *trace = NULL; + + BT_ASSERT(stream); + BT_LIB_LOGD("Creating packet object: %![stream-]+s", stream); + packet = g_new0(struct bt_packet, 1); + if (!packet) { + BT_LOGE_STR("Failed to allocate one packet object."); + goto error; + } + + bt_object_init_shared(&packet->base, + (bt_object_release_func) bt_packet_recycle); + packet->stream = bt_get(stream); + trace = bt_stream_class_borrow_trace_inline(stream->class); + BT_ASSERT(trace); + + if (trace->packet_header_ft) { + BT_LOGD_STR("Creating initial packet header field."); + packet->header_field = bt_field_wrapper_create( + &trace->packet_header_field_pool, + trace->packet_header_ft); + if (!packet->header_field) { + BT_LOGE_STR("Cannot create packet header field wrapper."); + goto error; + } + } + + if (stream->class->packet_context_ft) { + BT_LOGD_STR("Creating initial packet context field."); + packet->context_field = bt_field_wrapper_create( + &stream->class->packet_context_field_pool, + stream->class->packet_context_ft); + if (!packet->context_field) { + BT_LOGE_STR("Cannot create packet context field wrapper."); + goto error; + } + } + + if (stream->class->default_clock_class) { + if (stream->class->packets_have_default_beginning_cv) { + packet->default_beginning_cv = bt_clock_value_create( + stream->class->default_clock_class); + if (!packet->default_beginning_cv) { + /* bt_clock_value_create() logs errors */ + goto error; + } + } + + if (stream->class->packets_have_default_end_cv) { + packet->default_end_cv = bt_clock_value_create( + stream->class->default_clock_class); + if (!packet->default_end_cv) { + /* bt_clock_value_create() logs errors */ + goto error; + } + } + } + + reset_counter_snapshots(packet); + BT_LIB_LOGD("Created packet object: %!+a", packet); + goto end; + +error: + BT_PUT(packet); + +end: + return packet; +} + +struct bt_packet *bt_packet_create(struct bt_stream *stream) +{ + struct bt_packet *packet = NULL; + + BT_ASSERT_PRE_NON_NULL(stream, "Stream"); + packet = bt_object_pool_create_object(&stream->packet_pool); + if (unlikely(!packet)) { + BT_LIB_LOGE("Cannot allocate one packet from stream's packet pool: " + "%![stream-]+s", stream); + goto end; + } + + if (likely(!packet->stream)) { + packet->stream = stream; + bt_object_get_no_null_check_no_parent_check( + &packet->stream->base); + } + +end: + return packet; +} + +int bt_packet_move_header_field(struct bt_packet *packet, + struct bt_packet_header_field *header_field) +{ + struct bt_trace *trace; + struct bt_field_wrapper *field_wrapper = (void *) header_field; + + BT_ASSERT_PRE_NON_NULL(packet, "Packet"); + BT_ASSERT_PRE_NON_NULL(field_wrapper, "Header field"); + BT_ASSERT_PRE_PACKET_HOT(packet); + trace = bt_stream_class_borrow_trace_inline(packet->stream->class); + BT_ASSERT_PRE(trace->packet_header_ft, + "Trace has no packet header field type: %!+t", + trace); + BT_ASSERT_PRE(field_wrapper->field->type == + trace->packet_header_ft, + "Unexpected packet header field's type: " + "%![ft-]+F, %![expected-ft-]+F", field_wrapper->field->type, + trace->packet_header_ft); + + /* Recycle current header field: always exists */ + BT_ASSERT(packet->header_field); + recycle_header_field(packet->header_field, trace); + + /* Move new field */ + packet->header_field = field_wrapper; + return 0; +} + +int bt_packet_move_context_field(struct bt_packet *packet, + struct bt_packet_context_field *context_field) +{ + struct bt_stream_class *stream_class; + struct bt_field_wrapper *field_wrapper = (void *) context_field; + + BT_ASSERT_PRE_NON_NULL(packet, "Packet"); + BT_ASSERT_PRE_NON_NULL(field_wrapper, "Context field"); + BT_ASSERT_PRE_HOT(packet, "Packet", ": %!+a", packet); + stream_class = packet->stream->class; + BT_ASSERT_PRE(stream_class->packet_context_ft, + "Stream class has no packet context field type: %!+S", + stream_class); + BT_ASSERT_PRE(field_wrapper->field->type == + stream_class->packet_context_ft, + "Unexpected packet header field's type: " + "%![ft-]+F, %![expected-ft-]+F", field_wrapper->field->type, + stream_class->packet_context_ft); + + /* Recycle current context field: always exists */ + BT_ASSERT(packet->context_field); + recycle_context_field(packet->context_field, stream_class); + + /* Move new field */ + packet->context_field = field_wrapper; + return 0; +} + +int bt_packet_set_default_beginning_clock_value(struct bt_packet *packet, + uint64_t value_cycles) +{ + struct bt_stream_class *sc; + + BT_ASSERT_PRE_NON_NULL(packet, "Packet"); + BT_ASSERT_PRE_PACKET_HOT(packet); + sc = packet->stream->class; + BT_ASSERT(sc); + BT_ASSERT_PRE(sc->default_clock_class, + "Packet's stream class has no default clock class: " + "%![packet-]+a, %![sc-]+S", packet, sc); + BT_ASSERT_PRE(sc->packets_have_default_beginning_cv, + "Packet's stream class indicates that its packets have " + "no default beginning clock value: %![packet-]+a, %![sc-]+S", + packet, sc); + BT_ASSERT(packet->default_beginning_cv); + bt_clock_value_set_value_inline(packet->default_beginning_cv, value_cycles); + BT_LIB_LOGV("Set packet's default beginning clock value: " + "%![packet-]+a, value=%" PRIu64, value_cycles); + return 0; +} + +enum bt_clock_value_status bt_packet_borrow_default_beginning_clock_value( + struct bt_packet *packet, struct bt_clock_value **clock_value) +{ + BT_ASSERT_PRE_NON_NULL(packet, "Packet"); + BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value (output)"); + *clock_value = packet->default_beginning_cv; + return BT_CLOCK_VALUE_STATUS_KNOWN; +} + +int bt_packet_set_default_end_clock_value(struct bt_packet *packet, + uint64_t value_cycles) +{ + struct bt_stream_class *sc; + + BT_ASSERT_PRE_NON_NULL(packet, "Packet"); + BT_ASSERT_PRE_PACKET_HOT(packet); + sc = packet->stream->class; + BT_ASSERT(sc); + BT_ASSERT_PRE(sc->default_clock_class, + "Packet's stream class has no default clock class: " + "%![packet-]+a, %![sc-]+S", packet, sc); + BT_ASSERT_PRE(sc->packets_have_default_end_cv, + "Packet's stream class indicates that its packets have " + "no default end clock value: %![packet-]+a, %![sc-]+S", + packet, sc); + BT_ASSERT(packet->default_end_cv); + bt_clock_value_set_value_inline(packet->default_end_cv, value_cycles); + BT_LIB_LOGV("Set packet's default end clock value: " + "%![packet-]+a, value=%" PRIu64, value_cycles); + return 0; +} + +enum bt_clock_value_status bt_packet_borrow_default_end_clock_value( + struct bt_packet *packet, struct bt_clock_value **clock_value) +{ + BT_ASSERT_PRE_NON_NULL(packet, "Packet"); + BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value (output)"); + *clock_value = packet->default_end_cv; + return BT_CLOCK_VALUE_STATUS_KNOWN; +} + +enum bt_property_availability bt_packet_get_discarded_event_counter_snapshot( + struct bt_packet *packet, uint64_t *value) +{ + BT_ASSERT_PRE_NON_NULL(packet, "Packet"); + BT_ASSERT_PRE_NON_NULL(value, "Value (output)"); + *value = packet->discarded_event_counter_snapshot.value; + return packet->discarded_event_counter_snapshot.base.avail; +} + +int bt_packet_set_discarded_event_counter_snapshot(struct bt_packet *packet, + uint64_t value) +{ + BT_ASSERT_PRE_NON_NULL(packet, "Packet"); + BT_ASSERT_PRE_PACKET_HOT(packet); + BT_ASSERT_PRE(packet->stream->class->packets_have_discarded_event_counter_snapshot, + "Packet's stream's discarded event counter is not enabled: " + "%![packet-]+a", packet); + bt_property_uint_set(&packet->discarded_event_counter_snapshot, value); + return 0; +} + +enum bt_property_availability bt_packet_get_packet_counter_snapshot( + struct bt_packet *packet, uint64_t *value) +{ + BT_ASSERT_PRE_NON_NULL(packet, "Packet"); + BT_ASSERT_PRE_NON_NULL(value, "Value (output)"); + *value = packet->packet_counter_snapshot.value; + return packet->packet_counter_snapshot.base.avail; +} + +int bt_packet_set_packet_counter_snapshot(struct bt_packet *packet, + uint64_t value) +{ + BT_ASSERT_PRE_NON_NULL(packet, "Packet"); + BT_ASSERT_PRE_PACKET_HOT(packet); + BT_ASSERT_PRE(packet->stream->class->packets_have_packet_counter_snapshot, + "Packet's stream's packet counter is not enabled: " + "%![packet-]+a", packet); + bt_property_uint_set(&packet->packet_counter_snapshot, value); + return 0; +} diff --git a/lib/trace-ir/resolve-field-path.c b/lib/trace-ir/resolve-field-path.c new file mode 100644 index 00000000..02150f49 --- /dev/null +++ b/lib/trace-ir/resolve-field-path.c @@ -0,0 +1,610 @@ +/* + * Copyright 2018 Philippe Proulx + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "RESOLVE-FIELD-PATH" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static +bool find_field_type_recursive(struct bt_field_type *ft, + struct bt_field_type *tgt_ft, struct bt_field_path *field_path) +{ + bool found = false; + + if (tgt_ft == ft) { + found = true; + goto end; + } + + switch (ft->id) { + case BT_FIELD_TYPE_ID_STRUCTURE: + case BT_FIELD_TYPE_ID_VARIANT: + { + struct bt_field_type_named_field_types_container *container_ft = + (void *) ft; + uint64_t i; + + for (i = 0; i < container_ft->named_fts->len; i++) { + struct bt_named_field_type *named_ft = + BT_FIELD_TYPE_NAMED_FT_AT_INDEX( + container_ft, i); + + g_array_append_val(field_path->indexes, i); + found = find_field_type_recursive(named_ft->ft, + tgt_ft, field_path); + if (found) { + goto end; + } + + g_array_set_size(field_path->indexes, + field_path->indexes->len - 1); + } + + break; + } + case BT_FIELD_TYPE_ID_STATIC_ARRAY: + case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY: + { + struct bt_field_type_array *array_ft = (void *) ft; + + found = find_field_type_recursive(array_ft->element_ft, + tgt_ft, field_path); + break; + } + default: + break; + } + +end: + return found; +} + +static +int find_field_type(struct bt_field_type *root_ft, + enum bt_scope root_scope, struct bt_field_type *tgt_ft, + struct bt_field_path **ret_field_path) +{ + int ret = 0; + struct bt_field_path *field_path = NULL; + + if (!root_ft) { + goto end; + } + + field_path = bt_field_path_create(); + if (!field_path) { + ret = -1; + goto end; + } + + field_path->root = root_scope; + if (!find_field_type_recursive(root_ft, tgt_ft, field_path)) { + /* Not found here */ + BT_PUT(field_path); + } + +end: + *ret_field_path = field_path; + return ret; +} + +static +struct bt_field_path *find_field_type_in_ctx(struct bt_field_type *ft, + struct bt_resolve_field_path_context *ctx) +{ + struct bt_field_path *field_path = NULL; + int ret; + + ret = find_field_type(ctx->packet_header, BT_SCOPE_PACKET_HEADER, + ft, &field_path); + if (ret || field_path) { + goto end; + } + + ret = find_field_type(ctx->packet_context, BT_SCOPE_PACKET_CONTEXT, + ft, &field_path); + if (ret || field_path) { + goto end; + } + + ret = find_field_type(ctx->event_header, BT_SCOPE_EVENT_HEADER, + ft, &field_path); + if (ret || field_path) { + goto end; + } + + ret = find_field_type(ctx->event_common_context, + BT_SCOPE_EVENT_COMMON_CONTEXT, ft, &field_path); + if (ret || field_path) { + goto end; + } + + ret = find_field_type(ctx->event_specific_context, + BT_SCOPE_EVENT_SPECIFIC_CONTEXT, ft, &field_path); + if (ret || field_path) { + goto end; + } + + ret = find_field_type(ctx->event_payload, BT_SCOPE_EVENT_PAYLOAD, + ft, &field_path); + if (ret || field_path) { + goto end; + } + +end: + return field_path; +} + +BT_ASSERT_PRE_FUNC +static inline +bool target_is_before_source(struct bt_field_path *src_field_path, + struct bt_field_path *tgt_field_path) +{ + bool is_valid = true; + uint64_t src_i = 0, tgt_i = 0; + + if (tgt_field_path->root < src_field_path->root) { + goto end; + } + + if (tgt_field_path->root > src_field_path->root) { + is_valid = false; + goto end; + } + + BT_ASSERT(tgt_field_path->root == src_field_path->root); + + while (src_i < src_field_path->indexes->len && + tgt_i < tgt_field_path->indexes->len) { + uint64_t src_index = bt_field_path_get_index_by_index_inline( + src_field_path, src_i); + uint64_t tgt_index = bt_field_path_get_index_by_index_inline( + tgt_field_path, tgt_i); + + if (tgt_index > src_index) { + is_valid = false; + goto end; + } + + src_i++; + tgt_i++; + } + +end: + return is_valid; +} + +BT_ASSERT_PRE_FUNC +static inline +struct bt_field_type *borrow_root_field_type( + struct bt_resolve_field_path_context *ctx, enum bt_scope scope) +{ + switch (scope) { + case BT_SCOPE_PACKET_HEADER: + return ctx->packet_header; + case BT_SCOPE_PACKET_CONTEXT: + return ctx->packet_context; + case BT_SCOPE_EVENT_HEADER: + return ctx->event_header; + case BT_SCOPE_EVENT_COMMON_CONTEXT: + return ctx->event_common_context; + case BT_SCOPE_EVENT_SPECIFIC_CONTEXT: + return ctx->event_specific_context; + case BT_SCOPE_EVENT_PAYLOAD: + return ctx->event_payload; + default: + abort(); + } + + return NULL; +} + +BT_ASSERT_PRE_FUNC +static inline +struct bt_field_type *borrow_child_field_type(struct bt_field_type *parent_ft, + uint64_t index, bool *advance) +{ + struct bt_field_type *child_ft = NULL; + + switch (parent_ft->id) { + case BT_FIELD_TYPE_ID_STRUCTURE: + case BT_FIELD_TYPE_ID_VARIANT: + { + struct bt_named_field_type *named_ft = + BT_FIELD_TYPE_NAMED_FT_AT_INDEX(parent_ft, index); + + child_ft = named_ft->ft; + *advance = true; + break; + } + case BT_FIELD_TYPE_ID_STATIC_ARRAY: + case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY: + { + struct bt_field_type_array *array_ft = (void *) parent_ft; + + child_ft = array_ft->element_ft; + *advance = false; + break; + } + default: + break; + } + + return child_ft; +} + +BT_ASSERT_PRE_FUNC +static inline +bool target_field_path_in_different_scope_has_struct_ft_only( + struct bt_field_path *src_field_path, + struct bt_field_path *tgt_field_path, + struct bt_resolve_field_path_context *ctx) +{ + bool is_valid = true; + uint64_t i = 0; + struct bt_field_type *ft; + + if (src_field_path->root == tgt_field_path->root) { + goto end; + } + + ft = borrow_root_field_type(ctx, tgt_field_path->root); + + while (i < tgt_field_path->indexes->len) { + uint64_t index = bt_field_path_get_index_by_index_inline( + tgt_field_path, i); + bool advance; + + if (ft->id == BT_FIELD_TYPE_ID_STATIC_ARRAY || + ft->id == BT_FIELD_TYPE_ID_DYNAMIC_ARRAY || + ft->id == BT_FIELD_TYPE_ID_VARIANT) { + is_valid = false; + goto end; + } + + ft = borrow_child_field_type(ft, index, &advance); + + if (advance) { + i++; + } + } + +end: + return is_valid; +} + +BT_ASSERT_PRE_FUNC +static inline +bool lca_is_structure_field_type(struct bt_field_path *src_field_path, + struct bt_field_path *tgt_field_path, + struct bt_resolve_field_path_context *ctx) +{ + bool is_valid = true; + struct bt_field_type *src_ft; + struct bt_field_type *tgt_ft; + struct bt_field_type *prev_ft = NULL; + uint64_t src_i = 0, tgt_i = 0; + + if (src_field_path->root != tgt_field_path->root) { + goto end; + } + + src_ft = borrow_root_field_type(ctx, src_field_path->root); + tgt_ft = borrow_root_field_type(ctx, tgt_field_path->root); + BT_ASSERT(src_ft); + BT_ASSERT(tgt_ft); + + while (src_i < src_field_path->indexes->len && + tgt_i < tgt_field_path->indexes->len) { + bool advance; + uint64_t src_index = bt_field_path_get_index_by_index_inline( + src_field_path, src_i); + uint64_t tgt_index = bt_field_path_get_index_by_index_inline( + tgt_field_path, tgt_i); + + if (src_ft != tgt_ft) { + if (!prev_ft) { + /* + * This is correct: the LCA is the root + * scope field type, which must be a + * structure field type. + */ + break; + } + + if (prev_ft->id != BT_FIELD_TYPE_ID_STRUCTURE) { + is_valid = false; + } + + break; + } + + prev_ft = src_ft; + src_ft = borrow_child_field_type(src_ft, src_index, &advance); + + if (advance) { + src_i++; + } + + tgt_ft = borrow_child_field_type(tgt_ft, tgt_index, &advance); + + if (advance) { + tgt_i++; + } + } + +end: + return is_valid; +} + +BT_ASSERT_PRE_FUNC +static inline +bool lca_to_target_has_struct_ft_only(struct bt_field_path *src_field_path, + struct bt_field_path *tgt_field_path, + struct bt_resolve_field_path_context *ctx) +{ + bool is_valid = true; + struct bt_field_type *src_ft; + struct bt_field_type *tgt_ft; + uint64_t src_i = 0, tgt_i = 0; + + if (src_field_path->root != tgt_field_path->root) { + goto end; + } + + src_ft = borrow_root_field_type(ctx, src_field_path->root); + tgt_ft = borrow_root_field_type(ctx, tgt_field_path->root); + BT_ASSERT(src_ft); + BT_ASSERT(tgt_ft); + BT_ASSERT(src_ft == tgt_ft); + + /* Find LCA */ + while (src_i < src_field_path->indexes->len && + tgt_i < tgt_field_path->indexes->len) { + bool advance; + uint64_t src_index = bt_field_path_get_index_by_index_inline( + src_field_path, src_i); + uint64_t tgt_index = bt_field_path_get_index_by_index_inline( + tgt_field_path, tgt_i); + + if (src_i != tgt_i) { + /* Next FT is different: LCA is `tgt_ft` */ + break; + } + + src_ft = borrow_child_field_type(src_ft, src_index, &advance); + + if (advance) { + src_i++; + } + + tgt_ft = borrow_child_field_type(tgt_ft, tgt_index, &advance); + + if (advance) { + tgt_i++; + } + } + + /* Only structure field types to the target */ + while (tgt_i < tgt_field_path->indexes->len) { + bool advance; + uint64_t tgt_index = bt_field_path_get_index_by_index_inline( + tgt_field_path, tgt_i); + + if (tgt_ft->id == BT_FIELD_TYPE_ID_STATIC_ARRAY || + tgt_ft->id == BT_FIELD_TYPE_ID_DYNAMIC_ARRAY || + tgt_ft->id == BT_FIELD_TYPE_ID_VARIANT) { + is_valid = false; + goto end; + } + + tgt_ft = borrow_child_field_type(tgt_ft, tgt_index, &advance); + + if (advance) { + tgt_i++; + } + } + +end: + return is_valid; +} + +BT_ASSERT_PRE_FUNC +static inline +bool field_path_is_valid(struct bt_field_type *src_ft, + struct bt_field_type *tgt_ft, + struct bt_resolve_field_path_context *ctx) +{ + bool is_valid = true; + struct bt_field_path *src_field_path = find_field_type_in_ctx( + src_ft, ctx); + struct bt_field_path *tgt_field_path = find_field_type_in_ctx( + tgt_ft, ctx); + + if (!src_field_path) { + BT_ASSERT_PRE_MSG("Cannot find requesting field type in " + "resolving context: %!+F", src_ft); + is_valid = false; + goto end; + } + + if (!tgt_field_path) { + BT_ASSERT_PRE_MSG("Cannot find target field type in " + "resolving context: %!+F", tgt_ft); + is_valid = false; + goto end; + } + + /* Target must be before source */ + if (!target_is_before_source(src_field_path, tgt_field_path)) { + BT_ASSERT_PRE_MSG("Target field type is located after " + "requesting field type: %![req-ft-]+F, %![tgt-ft-]+F", + src_ft, tgt_ft); + is_valid = false; + goto end; + } + + /* + * If target is in a different scope than source, there are no + * array or variant field types on the way to the target. + */ + if (!target_field_path_in_different_scope_has_struct_ft_only( + src_field_path, tgt_field_path, ctx)) { + BT_ASSERT_PRE_MSG("Target field type is located in a " + "different scope than requesting field type, " + "but within an array or a variant field type: " + "%![req-ft-]+F, %![tgt-ft-]+F", + src_ft, tgt_ft); + is_valid = false; + goto end; + } + + /* Same scope: LCA must be a structure field type */ + if (!lca_is_structure_field_type(src_field_path, tgt_field_path, ctx)) { + BT_ASSERT_PRE_MSG("Lowest common ancestor of target and " + "requesting field types is not a structure field type: " + "%![req-ft-]+F, %![tgt-ft-]+F", + src_ft, tgt_ft); + is_valid = false; + goto end; + } + + /* Same scope: path from LCA to target has no array/variant FTs */ + if (!lca_to_target_has_struct_ft_only(src_field_path, tgt_field_path, + ctx)) { + BT_ASSERT_PRE_MSG("Path from lowest common ancestor of target " + "and requesting field types to target field type " + "contains an array or a variant field type: " + "%![req-ft-]+F, %![tgt-ft-]+F", src_ft, tgt_ft); + is_valid = false; + goto end; + } + +end: + bt_put(src_field_path); + bt_put(tgt_field_path); + return is_valid; +} + +static +struct bt_field_path *resolve_field_path(struct bt_field_type *src_ft, + struct bt_field_type *tgt_ft, + struct bt_resolve_field_path_context *ctx) +{ + BT_ASSERT_PRE(field_path_is_valid(src_ft, tgt_ft, ctx), + "Invalid target field type: %![req-ft-]+F, %![tgt-ft-]+F", + src_ft, tgt_ft); + return find_field_type_in_ctx(tgt_ft, ctx); +} + +BT_HIDDEN +int bt_resolve_field_paths(struct bt_field_type *ft, + struct bt_resolve_field_path_context *ctx) +{ + int ret = 0; + + BT_ASSERT(ft); + + /* Resolving part for dynamic array and variant field types */ + switch (ft->id) { + case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY: + { + struct bt_field_type_dynamic_array *dyn_array_ft = (void *) ft; + + if (dyn_array_ft->length_ft) { + BT_ASSERT(!dyn_array_ft->length_field_path); + dyn_array_ft->length_field_path = resolve_field_path( + ft, dyn_array_ft->length_ft, ctx); + if (!dyn_array_ft->length_field_path) { + ret = -1; + goto end; + } + } + + break; + } + case BT_FIELD_TYPE_ID_VARIANT: + { + struct bt_field_type_variant *var_ft = (void *) ft; + + if (var_ft->selector_ft) { + BT_ASSERT(!var_ft->selector_field_path); + var_ft->selector_field_path = + resolve_field_path(ft, + var_ft->selector_ft, ctx); + if (!var_ft->selector_field_path) { + ret = -1; + goto end; + } + } + } + default: + break; + } + + /* Recursive part */ + switch (ft->id) { + case BT_FIELD_TYPE_ID_STRUCTURE: + case BT_FIELD_TYPE_ID_VARIANT: + { + struct bt_field_type_named_field_types_container *container_ft = + (void *) ft; + uint64_t i; + + for (i = 0; i < container_ft->named_fts->len; i++) { + struct bt_named_field_type *named_ft = + BT_FIELD_TYPE_NAMED_FT_AT_INDEX( + container_ft, i); + + ret = bt_resolve_field_paths(named_ft->ft, ctx); + if (ret) { + goto end; + } + } + + break; + } + case BT_FIELD_TYPE_ID_STATIC_ARRAY: + case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY: + { + struct bt_field_type_array *array_ft = (void *) ft; + + ret = bt_resolve_field_paths(array_ft->element_ft, ctx); + break; + } + default: + break; + } + +end: + return ret; +} diff --git a/lib/trace-ir/stream-class.c b/lib/trace-ir/stream-class.c new file mode 100644 index 00000000..7fd1a80b --- /dev/null +++ b/lib/trace-ir/stream-class.c @@ -0,0 +1,567 @@ +/* + * stream-class.c + * + * Babeltrace trace IR - Stream Class + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "STREAM-CLASS" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BT_ASSERT_PRE_STREAM_CLASS_HOT(_sc) \ + BT_ASSERT_PRE_HOT((_sc), "Stream class", ": %!+S", (_sc)) + +static +void destroy_stream_class(struct bt_object *obj) +{ + struct bt_stream_class *stream_class = (void *) obj; + + BT_LIB_LOGD("Destroying stream class: %!+S", stream_class); + BT_LOGD_STR("Putting default clock class."); + bt_put(stream_class->default_clock_class); + + if (stream_class->event_classes) { + BT_LOGD_STR("Destroying event classes."); + g_ptr_array_free(stream_class->event_classes, TRUE); + } + + if (stream_class->name.str) { + g_string_free(stream_class->name.str, TRUE); + } + + BT_LOGD_STR("Putting event header field type."); + bt_put(stream_class->event_header_ft); + BT_LOGD_STR("Putting packet context field type."); + bt_put(stream_class->packet_context_ft); + BT_LOGD_STR("Putting event common context field type."); + bt_put(stream_class->event_common_context_ft); + bt_object_pool_finalize(&stream_class->event_header_field_pool); + bt_object_pool_finalize(&stream_class->packet_context_field_pool); + g_free(stream_class); +} + +static +void free_field_wrapper(struct bt_field_wrapper *field_wrapper, + struct bt_stream_class *stream_class) +{ + bt_field_wrapper_destroy((void *) field_wrapper); +} + +BT_ASSERT_PRE_FUNC +static +bool stream_class_id_is_unique(struct bt_trace *trace, uint64_t id) +{ + uint64_t i; + bool is_unique = true; + + for (i = 0; i < trace->stream_classes->len; i++) { + struct bt_stream_class *sc = + trace->stream_classes->pdata[i]; + + if (sc->id == id) { + is_unique = false; + goto end; + } + } + +end: + return is_unique; +} + +static +struct bt_stream_class *create_stream_class_with_id(struct bt_trace *trace, + uint64_t id) +{ + struct bt_stream_class *stream_class = NULL; + int ret; + + BT_ASSERT(trace); + BT_ASSERT_PRE(stream_class_id_is_unique(trace, id), + "Duplicate stream class ID: %![trace-]+t, id=%" PRIu64, + trace, id); + BT_LIB_LOGD("Creating stream class object: %![trace-]+t, id=%" PRIu64, + trace, id); + stream_class = g_new0(struct bt_stream_class, 1); + if (!stream_class) { + BT_LOGE_STR("Failed to allocate one stream class."); + goto error; + } + + bt_object_init_shared_with_parent(&stream_class->base, + destroy_stream_class); + + stream_class->name.str = g_string_new(NULL); + if (!stream_class->name.str) { + BT_LOGE_STR("Failed to allocate a GString."); + ret = -1; + goto end; + } + + stream_class->id = id; + stream_class->assigns_automatic_event_class_id = true; + stream_class->assigns_automatic_stream_id = true; + stream_class->event_classes = g_ptr_array_new_with_free_func( + (GDestroyNotify) bt_object_try_spec_release); + if (!stream_class->event_classes) { + BT_LOGE_STR("Failed to allocate a GPtrArray."); + goto error; + } + + ret = bt_object_pool_initialize(&stream_class->event_header_field_pool, + (bt_object_pool_new_object_func) bt_field_wrapper_new, + (bt_object_pool_destroy_object_func) free_field_wrapper, + stream_class); + if (ret) { + BT_LOGE("Failed to initialize event header field pool: ret=%d", + ret); + goto error; + } + + ret = bt_object_pool_initialize(&stream_class->packet_context_field_pool, + (bt_object_pool_new_object_func) bt_field_wrapper_new, + (bt_object_pool_destroy_object_func) free_field_wrapper, + stream_class); + if (ret) { + BT_LOGE("Failed to initialize packet context field pool: ret=%d", + ret); + goto error; + } + + bt_object_set_parent(&stream_class->base, &trace->base); + g_ptr_array_add(trace->stream_classes, stream_class); + bt_trace_freeze(trace); + BT_LIB_LOGD("Created stream class object: %!+S", stream_class); + goto end; + +error: + BT_PUT(stream_class); + +end: + return stream_class; +} + +struct bt_stream_class *bt_stream_class_create(struct bt_trace *trace) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE(trace->assigns_automatic_stream_class_id, + "Trace does not automatically assigns stream class IDs: " + "%![sc-]+t", trace); + return create_stream_class_with_id(trace, + (uint64_t) trace->stream_classes->len); +} + +struct bt_stream_class *bt_stream_class_create_with_id( + struct bt_trace *trace, uint64_t id) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE(!trace->assigns_automatic_stream_class_id, + "Trace automatically assigns stream class IDs: " + "%![sc-]+t", trace); + return create_stream_class_with_id(trace, id); +} + +struct bt_trace *bt_stream_class_borrow_trace(struct bt_stream_class *stream_class) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + return bt_stream_class_borrow_trace_inline(stream_class); +} + +const char *bt_stream_class_get_name(struct bt_stream_class *stream_class) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + return stream_class->name.value; +} + +int bt_stream_class_set_name(struct bt_stream_class *stream_class, + const char *name) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE_NON_NULL(name, "Name"); + BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); + g_string_assign(stream_class->name.str, name); + stream_class->name.value = stream_class->name.str->str; + BT_LIB_LOGV("Set stream class's name: %!+S", stream_class); + return 0; +} + +uint64_t bt_stream_class_get_id(struct bt_stream_class *stream_class) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + return stream_class->id; +} + +uint64_t bt_stream_class_get_event_class_count( + struct bt_stream_class *stream_class) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + return (uint64_t) stream_class->event_classes->len; +} + +struct bt_event_class *bt_stream_class_borrow_event_class_by_index( + struct bt_stream_class *stream_class, uint64_t index) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE_VALID_INDEX(index, stream_class->event_classes->len); + return g_ptr_array_index(stream_class->event_classes, index); +} + +struct bt_event_class *bt_stream_class_borrow_event_class_by_id( + struct bt_stream_class *trace, uint64_t id) +{ + struct bt_event_class *event_class = NULL; + uint64_t i; + + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + + for (i = 0; i < trace->event_classes->len; i++) { + struct bt_event_class *event_class_candidate = + g_ptr_array_index(trace->event_classes, i); + + if (event_class_candidate->id == id) { + event_class = event_class_candidate; + goto end; + } + } + +end: + return event_class; +} + +struct bt_field_type *bt_stream_class_borrow_packet_context_field_type( + struct bt_stream_class *stream_class) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + return stream_class->packet_context_ft; +} + +int bt_stream_class_set_packet_context_field_type( + struct bt_stream_class *stream_class, + struct bt_field_type *field_type) +{ + int ret; + struct bt_resolve_field_path_context resolve_ctx = { + .packet_header = NULL, + .packet_context = field_type, + .event_header = NULL, + .event_common_context = NULL, + .event_specific_context = NULL, + .event_payload = NULL, + }; + + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE_NON_NULL(field_type, "Field type"); + BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); + BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) == + BT_FIELD_TYPE_ID_STRUCTURE, + "Packet context field type is not a structure field type: %!+F", + field_type); + resolve_ctx.packet_header = + bt_stream_class_borrow_trace_inline(stream_class)->packet_header_ft; + ret = bt_resolve_field_paths(field_type, &resolve_ctx); + if (ret) { + goto end; + } + + bt_field_type_make_part_of_trace(field_type); + bt_put(stream_class->packet_context_ft); + stream_class->packet_context_ft = bt_get(field_type); + bt_field_type_freeze(field_type); + BT_LIB_LOGV("Set stream class's packet context field type: %!+S", + stream_class); + +end: + return ret; +} + +struct bt_field_type *bt_stream_class_borrow_event_header_field_type( + struct bt_stream_class *stream_class) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + return stream_class->event_header_ft; +} + +int bt_stream_class_set_event_header_field_type( + struct bt_stream_class *stream_class, + struct bt_field_type *field_type) +{ + int ret; + struct bt_resolve_field_path_context resolve_ctx = { + .packet_header = NULL, + .packet_context = NULL, + .event_header = field_type, + .event_common_context = NULL, + .event_specific_context = NULL, + .event_payload = NULL, + }; + + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE_NON_NULL(field_type, "Field type"); + BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); + BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) == + BT_FIELD_TYPE_ID_STRUCTURE, + "Event header field type is not a structure field type: %!+F", + field_type); + resolve_ctx.packet_header = + bt_stream_class_borrow_trace_inline(stream_class)->packet_header_ft; + resolve_ctx.packet_context = stream_class->packet_context_ft; + ret = bt_resolve_field_paths(field_type, &resolve_ctx); + if (ret) { + goto end; + } + + bt_field_type_make_part_of_trace(field_type); + bt_put(stream_class->event_header_ft); + stream_class->event_header_ft = bt_get(field_type); + bt_field_type_freeze(field_type); + BT_LIB_LOGV("Set stream class's event header field type: %!+S", + stream_class); + +end: + return ret; +} + +struct bt_field_type *bt_stream_class_borrow_event_common_context_field_type( + struct bt_stream_class *stream_class) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + return stream_class->event_common_context_ft; +} + +int bt_stream_class_set_event_common_context_field_type( + struct bt_stream_class *stream_class, + struct bt_field_type *field_type) +{ + int ret; + struct bt_resolve_field_path_context resolve_ctx = { + .packet_header = NULL, + .packet_context = NULL, + .event_header = NULL, + .event_common_context = field_type, + .event_specific_context = NULL, + .event_payload = NULL, + }; + + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE_NON_NULL(field_type, "Field type"); + BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); + BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) == + BT_FIELD_TYPE_ID_STRUCTURE, + "Event common context field type is not a structure field type: %!+F", + field_type); + resolve_ctx.packet_header = + bt_stream_class_borrow_trace_inline(stream_class)->packet_header_ft; + resolve_ctx.packet_context = stream_class->packet_context_ft; + resolve_ctx.event_header = stream_class->event_header_ft; + ret = bt_resolve_field_paths(field_type, &resolve_ctx); + if (ret) { + goto end; + } + + bt_field_type_make_part_of_trace(field_type); + bt_put(stream_class->event_common_context_ft); + stream_class->event_common_context_ft = bt_get(field_type); + bt_field_type_freeze(field_type); + BT_LIB_LOGV("Set stream class's event common context field type: %!+S", + stream_class); + +end: + return ret; +} + +BT_HIDDEN +void _bt_stream_class_freeze(struct bt_stream_class *stream_class) +{ + /* The field types and default clock class are already frozen */ + BT_ASSERT(stream_class); + BT_LIB_LOGD("Freezing stream class: %!+S", stream_class); + stream_class->frozen = true; +} + +int bt_stream_class_set_default_clock_class( + struct bt_stream_class *stream_class, + struct bt_clock_class *clock_class) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); + BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); + bt_put(stream_class->default_clock_class); + stream_class->default_clock_class = bt_get(clock_class); + bt_clock_class_freeze(clock_class); + BT_LIB_LOGV("Set stream class's default clock class: %!+S", + stream_class); + return 0; +} + +struct bt_clock_class *bt_stream_class_borrow_default_clock_class( + struct bt_stream_class *stream_class) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + return stream_class->default_clock_class; +} + +bt_bool bt_stream_class_assigns_automatic_event_class_id( + struct bt_stream_class *stream_class) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + return (bt_bool) stream_class->assigns_automatic_event_class_id; +} + +int bt_stream_class_set_assigns_automatic_event_class_id( + struct bt_stream_class *stream_class, bt_bool value) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); + stream_class->assigns_automatic_event_class_id = (bool) value; + BT_LIB_LOGV("Set stream class's automatic event class ID " + "assignment property: %!+S", stream_class); + return 0; +} + +bt_bool bt_stream_class_assigns_automatic_stream_id( + struct bt_stream_class *stream_class) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + return (bt_bool) stream_class->assigns_automatic_stream_id; +} + +int bt_stream_class_set_assigns_automatic_stream_id( + struct bt_stream_class *stream_class, bt_bool value) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); + stream_class->assigns_automatic_stream_id = (bool) value; + BT_LIB_LOGV("Set stream class's automatic stream ID " + "assignment property: %!+S", stream_class); + return 0; +} + +bt_bool bt_stream_class_packets_have_discarded_event_counter_snapshot( + struct bt_stream_class *stream_class) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + return (bt_bool) stream_class->packets_have_discarded_event_counter_snapshot; +} + +int bt_stream_class_set_packets_have_discarded_event_counter_snapshot( + struct bt_stream_class *stream_class, bt_bool value) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); + stream_class->packets_have_discarded_event_counter_snapshot = + (bool) value; + BT_LIB_LOGV("Set stream class's " + "\"packets have discarded event counter snapshot\" property: " + "%!+S", stream_class); + return 0; +} + +bt_bool bt_stream_class_packets_have_packet_counter_snapshot( + struct bt_stream_class *stream_class) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + return (bt_bool) stream_class->packets_have_packet_counter_snapshot; +} + +int bt_stream_class_set_packets_have_packet_counter_snapshot( + struct bt_stream_class *stream_class, bt_bool value) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); + stream_class->packets_have_packet_counter_snapshot = + (bool) value; + BT_LIB_LOGV("Set stream class's " + "\"packets have packet counter snapshot\" property: " + "%!+S", stream_class); + return 0; +} + +bt_bool bt_stream_class_packets_have_default_beginning_clock_value( + struct bt_stream_class *stream_class) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + return (bt_bool) stream_class->packets_have_default_beginning_cv; +} + +int bt_stream_class_set_packets_have_default_beginning_clock_value( + struct bt_stream_class *stream_class, bt_bool value) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); + BT_ASSERT_PRE(!value || stream_class->default_clock_class, + "Stream class does not have a default clock class: %!+S", + stream_class); + stream_class->packets_have_default_beginning_cv = (bool) value; + BT_LIB_LOGV("Set stream class's " + "\"packets have default beginning clock value\" property: " + "%!+S", stream_class); + return 0; +} + +bt_bool bt_stream_class_packets_have_default_end_clock_value( + struct bt_stream_class *stream_class) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + return (bt_bool) stream_class->packets_have_default_end_cv; +} + +int bt_stream_class_set_packets_have_default_end_clock_value( + struct bt_stream_class *stream_class, bt_bool value) +{ + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class); + BT_ASSERT_PRE(!value || stream_class->default_clock_class, + "Stream class does not have a default clock class: %!+S", + stream_class); + stream_class->packets_have_default_end_cv = (bool) value; + BT_LIB_LOGV("Set stream class's " + "\"packets have default end clock value\" property: " + "%!+S", stream_class); + return 0; +} + +bt_bool bt_stream_class_default_clock_is_always_known( + struct bt_stream_class *stream_class) +{ + /* BT_CLOCK_VALUE_STATUS_UNKNOWN is not supported as of 2.0 */ + return BT_TRUE; +} diff --git a/lib/trace-ir/stream.c b/lib/trace-ir/stream.c new file mode 100644 index 00000000..7d37f4ee --- /dev/null +++ b/lib/trace-ir/stream.c @@ -0,0 +1,208 @@ +/* + * stream.c + * + * Babeltrace trace IR - Stream + * + * Copyright 2013, 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "STREAM" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BT_ASSERT_PRE_STREAM_HOT(_stream) \ + BT_ASSERT_PRE_HOT((_stream), "Stream", ": %!+s", (_stream)) + +static +void destroy_stream(struct bt_object *obj) +{ + struct bt_stream *stream = (void *) obj; + + BT_LIB_LOGD("Destroying stream object: %!+s", stream); + + if (stream->name.str) { + g_string_free(stream->name.str, TRUE); + } + + bt_object_pool_finalize(&stream->packet_pool); + g_free(stream); +} + +static +void bt_stream_free_packet(struct bt_packet *packet, struct bt_stream *stream) +{ + bt_packet_destroy(packet); +} + +BT_ASSERT_PRE_FUNC +static inline +bool stream_id_is_unique(struct bt_trace *trace, + struct bt_stream_class *stream_class, uint64_t id) +{ + uint64_t i; + bool is_unique = true; + + for (i = 0; i < trace->streams->len; i++) { + struct bt_stream *stream = trace->streams->pdata[i]; + + if (stream->class != stream_class) { + continue; + } + + if (stream->id == id) { + is_unique = false; + goto end; + } + } + +end: + return is_unique; +} + +static +struct bt_stream *create_stream_with_id(struct bt_stream_class *stream_class, + uint64_t id) +{ + int ret; + struct bt_stream *stream; + struct bt_trace *trace; + + BT_ASSERT(stream_class); + trace = bt_stream_class_borrow_trace_inline(stream_class); + BT_ASSERT_PRE(stream_id_is_unique(trace, stream_class, id), + "Duplicate stream ID: %![trace-]+t, id=%" PRIu64, trace, id); + BT_ASSERT_PRE(!trace->is_static, + "Trace is static: %![trace-]+t", trace); + BT_LIB_LOGD("Creating stream object: %![trace-]+t, id=%" PRIu64, + trace, id); + stream = g_new0(struct bt_stream, 1); + if (!stream) { + BT_LOGE_STR("Failed to allocate one stream."); + goto error; + } + + bt_object_init_shared_with_parent(&stream->base, destroy_stream); + stream->name.str = g_string_new(NULL); + if (!stream->name.str) { + BT_LOGE_STR("Failed to allocate a GString."); + goto error; + } + + stream->id = id; + ret = bt_object_pool_initialize(&stream->packet_pool, + (bt_object_pool_new_object_func) bt_packet_new, + (bt_object_pool_destroy_object_func) bt_stream_free_packet, + stream); + if (ret) { + BT_LOGE("Failed to initialize packet pool: ret=%d", ret); + goto error; + } + + stream->class = stream_class; + bt_trace_add_stream(trace, stream); + bt_stream_class_freeze(stream_class); + BT_LIB_LOGD("Created stream object: %!+s", stream); + goto end; + +error: + BT_PUT(stream); + +end: + return stream; +} + +struct bt_stream *bt_stream_create(struct bt_stream_class *stream_class) +{ + uint64_t id; + + BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class"); + BT_ASSERT_PRE(stream_class->assigns_automatic_stream_id, + "Stream class does not automatically assigns stream IDs: " + "%![sc-]+S", stream_class); + id = bt_trace_get_automatic_stream_id( + bt_stream_class_borrow_trace_inline(stream_class), + stream_class); + return create_stream_with_id(stream_class, id); +} + +struct bt_stream *bt_stream_create_with_id(struct bt_stream_class *stream_class, + uint64_t id) +{ + BT_ASSERT_PRE(!stream_class->assigns_automatic_stream_id, + "Stream class automatically assigns stream IDs: " + "%![sc-]+S", stream_class); + return create_stream_with_id(stream_class, id); +} + +struct bt_stream_class *bt_stream_borrow_class(struct bt_stream *stream) +{ + BT_ASSERT_PRE_NON_NULL(stream, "Stream"); + return stream->class; +} + +const char *bt_stream_get_name(struct bt_stream *stream) +{ + BT_ASSERT_PRE_NON_NULL(stream, "Stream class"); + return stream->name.value; +} + +int bt_stream_set_name(struct bt_stream *stream, const char *name) +{ + BT_ASSERT_PRE_NON_NULL(stream, "Clock class"); + BT_ASSERT_PRE_NON_NULL(name, "Name"); + BT_ASSERT_PRE_STREAM_HOT(stream); + g_string_assign(stream->name.str, name); + stream->name.value = stream->name.str->str; + BT_LIB_LOGV("Set stream class's name: %!+S", stream); + return 0; +} + +uint64_t bt_stream_get_id(struct bt_stream *stream) +{ + BT_ASSERT_PRE_NON_NULL(stream, "Stream class"); + return stream->id; +} + +BT_HIDDEN +void _bt_stream_freeze(struct bt_stream *stream) +{ + /* The field types and default clock class are already frozen */ + BT_ASSERT(stream); + BT_LIB_LOGD("Freezing stream: %!+s", stream); + stream->frozen = true; +} diff --git a/lib/trace-ir/trace.c b/lib/trace-ir/trace.c new file mode 100644 index 00000000..e5ae5132 --- /dev/null +++ b/lib/trace-ir/trace.c @@ -0,0 +1,660 @@ +/* + * trace.c + * + * Babeltrace trace IR - Trace + * + * Copyright 2014 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "TRACE" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct bt_trace_is_static_listener_elem { + bt_trace_is_static_listener func; + bt_trace_listener_removed removed; + void *data; +}; + +#define BT_ASSERT_PRE_TRACE_HOT(_trace) \ + BT_ASSERT_PRE_HOT((_trace), "Trace", ": %!+t", (_trace)) + +static +void destroy_trace(struct bt_object *obj) +{ + struct bt_trace *trace = (void *) obj; + + BT_LIB_LOGD("Destroying trace object: %!+t", trace); + + /* + * Call remove listeners first so that everything else still + * exists in the trace. + */ + if (trace->is_static_listeners) { + size_t i; + + for (i = 0; i < trace->is_static_listeners->len; i++) { + struct bt_trace_is_static_listener_elem elem = + g_array_index(trace->is_static_listeners, + struct bt_trace_is_static_listener_elem, i); + + if (elem.removed) { + elem.removed(trace, elem.data); + } + } + + g_array_free(trace->is_static_listeners, TRUE); + } + + bt_object_pool_finalize(&trace->packet_header_field_pool); + + if (trace->environment) { + BT_LOGD_STR("Destroying environment attributes."); + bt_attributes_destroy(trace->environment); + } + + if (trace->name.str) { + g_string_free(trace->name.str, TRUE); + } + + if (trace->streams) { + BT_LOGD_STR("Destroying streams."); + g_ptr_array_free(trace->streams, TRUE); + } + + if (trace->stream_classes) { + BT_LOGD_STR("Destroying stream classes."); + g_ptr_array_free(trace->stream_classes, TRUE); + } + + if (trace->stream_classes_stream_count) { + g_hash_table_destroy(trace->stream_classes_stream_count); + } + + BT_LOGD_STR("Putting packet header field type."); + bt_put(trace->packet_header_ft); + g_free(trace); +} + +static +void free_packet_header_field(struct bt_field_wrapper *field_wrapper, + struct bt_trace *trace) +{ + bt_field_wrapper_destroy(field_wrapper); +} + +struct bt_trace *bt_trace_create(void) +{ + struct bt_trace *trace = NULL; + int ret; + + BT_LOGD_STR("Creating default trace object."); + trace = g_new0(struct bt_trace, 1); + if (!trace) { + BT_LOGE_STR("Failed to allocate one trace."); + goto error; + } + + bt_object_init_shared_with_parent(&trace->base, destroy_trace); + trace->streams = g_ptr_array_new_with_free_func( + (GDestroyNotify) bt_object_try_spec_release); + if (!trace->streams) { + BT_LOGE_STR("Failed to allocate one GPtrArray."); + goto error; + } + + trace->stream_classes = g_ptr_array_new_with_free_func( + (GDestroyNotify) bt_object_try_spec_release); + if (!trace->stream_classes) { + BT_LOGE_STR("Failed to allocate one GPtrArray."); + goto error; + } + + trace->stream_classes_stream_count = g_hash_table_new(g_direct_hash, + g_direct_equal); + if (!trace->stream_classes_stream_count) { + BT_LOGE_STR("Failed to allocate one GHashTable."); + goto error; + } + + trace->name.str = g_string_new(NULL); + if (!trace->name.str) { + BT_LOGE_STR("Failed to allocate one GString."); + goto error; + } + + trace->environment = bt_attributes_create(); + if (!trace->environment) { + BT_LOGE_STR("Cannot create empty attributes object."); + goto error; + } + + trace->is_static_listeners = g_array_new(FALSE, TRUE, + sizeof(struct bt_trace_is_static_listener_elem)); + if (!trace->is_static_listeners) { + BT_LOGE_STR("Failed to allocate one GArray."); + goto error; + } + + trace->assigns_automatic_stream_class_id = true; + ret = bt_object_pool_initialize(&trace->packet_header_field_pool, + (bt_object_pool_new_object_func) bt_field_wrapper_new, + (bt_object_pool_destroy_object_func) free_packet_header_field, + trace); + if (ret) { + BT_LOGE("Failed to initialize packet header field pool: ret=%d", + ret); + goto error; + } + + BT_LIB_LOGD("Created trace object: %!+t", trace); + goto end; + +error: + BT_PUT(trace); + +end: + return trace; +} + +const char *bt_trace_get_name(struct bt_trace *trace) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + return trace->name.value; +} + +int bt_trace_set_name(struct bt_trace *trace, const char *name) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_NON_NULL(name, "Name"); + BT_ASSERT_PRE_TRACE_HOT(trace); + g_string_assign(trace->name.str, name); + trace->name.value = trace->name.str->str; + BT_LIB_LOGV("Set trace's name: %!+t", trace); + return 0; +} + +bt_uuid bt_trace_get_uuid(struct bt_trace *trace) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + return trace->uuid.value; +} + +int bt_trace_set_uuid(struct bt_trace *trace, bt_uuid uuid) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_NON_NULL(uuid, "UUID"); + BT_ASSERT_PRE_TRACE_HOT(trace); + memcpy(trace->uuid.uuid, uuid, BABELTRACE_UUID_LEN); + trace->uuid.value = trace->uuid.uuid; + BT_LIB_LOGV("Set trace's UUID: %!+t", trace); + return 0; +} + +BT_ASSERT_FUNC +static +bool trace_has_environment_entry(struct bt_trace *trace, const char *name) +{ + struct bt_value *attribute; + + BT_ASSERT(trace); + + attribute = bt_attributes_borrow_field_value_by_name( + trace->environment, name); + return attribute != NULL; +} + +static +int set_environment_entry(struct bt_trace *trace, const char *name, + struct bt_value *value) +{ + int ret; + + BT_ASSERT(trace); + BT_ASSERT(name); + BT_ASSERT(value); + BT_ASSERT_PRE(!trace->frozen || + !trace_has_environment_entry(trace, name), + "Trace is frozen: cannot replace environment entry: " + "%![trace-]+t, entry-name=\"%s\"", trace, name); + ret = bt_attributes_set_field_value(trace->environment, name, + value); + bt_value_freeze(value); + if (ret) { + BT_LIB_LOGE("Cannot set trace's environment entry: " + "%![trace-]+t, entry-name=\"%s\"", trace, name); + } else { + BT_LIB_LOGV("Set trace's environment entry: " + "%![trace-]+t, entry-name=\"%s\"", trace, name); + } + + return ret; +} + +int bt_trace_set_environment_entry_string(struct bt_trace *trace, + const char *name, const char *value) +{ + int ret; + struct bt_value *value_obj; + + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_NON_NULL(name, "Name"); + BT_ASSERT_PRE_NON_NULL(value, "Value"); + value_obj = bt_value_string_create_init(value); + if (!value_obj) { + BT_LOGE_STR("Cannot create a string value object."); + ret = -1; + goto end; + } + + /* set_environment_entry() logs errors */ + ret = set_environment_entry(trace, name, value_obj); + +end: + bt_put(value_obj); + return ret; +} + +int bt_trace_set_environment_entry_integer( + struct bt_trace *trace, const char *name, int64_t value) +{ + int ret; + struct bt_value *value_obj; + + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_NON_NULL(name, "Name"); + value_obj = bt_value_integer_create_init(value); + if (!value_obj) { + BT_LOGE_STR("Cannot create an integer value object."); + ret = -1; + goto end; + } + + /* set_environment_entry() logs errors */ + ret = set_environment_entry(trace, name, value_obj); + +end: + bt_put(value_obj); + return ret; +} + +uint64_t bt_trace_get_environment_entry_count(struct bt_trace *trace) +{ + int64_t ret; + + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + ret = bt_attributes_get_count(trace->environment); + BT_ASSERT(ret >= 0); + return (uint64_t) ret; +} + +void bt_trace_borrow_environment_entry_by_index( + struct bt_trace *trace, uint64_t index, + const char **name, struct bt_value **value) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_NON_NULL(name, "Name"); + BT_ASSERT_PRE_NON_NULL(value, "Value"); + BT_ASSERT_PRE_VALID_INDEX(index, + bt_attributes_get_count(trace->environment)); + *value = bt_attributes_borrow_field_value(trace->environment, index); + BT_ASSERT(*value); + *name = bt_attributes_get_field_name(trace->environment, index); + BT_ASSERT(*name); +} + +struct bt_value *bt_trace_borrow_environment_entry_value_by_name( + struct bt_trace *trace, const char *name) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_NON_NULL(name, "Name"); + return bt_attributes_borrow_field_value_by_name(trace->environment, + name); +} + +uint64_t bt_trace_get_stream_count(struct bt_trace *trace) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + return (uint64_t) trace->streams->len; +} + +struct bt_stream *bt_trace_borrow_stream_by_index( + struct bt_trace *trace, uint64_t index) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_VALID_INDEX(index, trace->streams->len); + return g_ptr_array_index(trace->streams, index); +} + +struct bt_stream *bt_trace_borrow_stream_by_id( + struct bt_trace *trace, uint64_t id) +{ + struct bt_stream *stream = NULL; + uint64_t i; + + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + + for (i = 0; i < trace->streams->len; i++) { + struct bt_stream *stream_candidate = + g_ptr_array_index(trace->streams, i); + + if (stream_candidate->id == id) { + stream = stream_candidate; + goto end; + } + } + +end: + return stream; +} + +uint64_t bt_trace_get_stream_class_count(struct bt_trace *trace) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + return (uint64_t) trace->stream_classes->len; +} + +struct bt_stream_class *bt_trace_borrow_stream_class_by_index( + struct bt_trace *trace, uint64_t index) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_VALID_INDEX(index, trace->stream_classes->len); + return g_ptr_array_index(trace->stream_classes, index); +} + +struct bt_stream_class *bt_trace_borrow_stream_class_by_id( + struct bt_trace *trace, uint64_t id) +{ + struct bt_stream_class *stream_class = NULL; + uint64_t i; + + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + + for (i = 0; i < trace->stream_classes->len; i++) { + struct bt_stream_class *stream_class_candidate = + g_ptr_array_index(trace->stream_classes, i); + + if (stream_class_candidate->id == id) { + stream_class = stream_class_candidate; + goto end; + } + } + +end: + return stream_class; +} + +struct bt_field_type *bt_trace_borrow_packet_header_field_type( + struct bt_trace *trace) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + return trace->packet_header_ft; +} + +int bt_trace_set_packet_header_field_type(struct bt_trace *trace, + struct bt_field_type *field_type) +{ + int ret; + struct bt_resolve_field_path_context resolve_ctx = { + .packet_header = field_type, + .packet_context = NULL, + .event_header = NULL, + .event_common_context = NULL, + .event_specific_context = NULL, + .event_payload = NULL, + }; + + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_NON_NULL(field_type, "Field type"); + BT_ASSERT_PRE_TRACE_HOT(trace); + BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) == + BT_FIELD_TYPE_ID_STRUCTURE, + "Packet header field type is not a structure field type: %!+F", + field_type); + ret = bt_resolve_field_paths(field_type, &resolve_ctx); + if (ret) { + goto end; + } + + bt_field_type_make_part_of_trace(field_type); + bt_put(trace->packet_header_ft); + trace->packet_header_ft = bt_get(field_type); + bt_field_type_freeze(field_type); + BT_LIB_LOGV("Set trace's packet header field type: %!+t", trace); + +end: + return ret; +} + +bt_bool bt_trace_is_static(struct bt_trace *trace) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + return (bt_bool) trace->is_static; +} + +int bt_trace_make_static(struct bt_trace *trace) +{ + uint64_t i; + + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + trace->is_static = true; + bt_trace_freeze(trace); + BT_LIB_LOGV("Trace is now static: %!+t", trace); + + /* Call all the "trace is static" listeners */ + for (i = 0; i < trace->is_static_listeners->len; i++) { + struct bt_trace_is_static_listener_elem elem = + g_array_index(trace->is_static_listeners, + struct bt_trace_is_static_listener_elem, i); + + if (elem.func) { + elem.func(trace, elem.data); + } + } + + return 0; +} + +int bt_trace_add_is_static_listener(struct bt_trace *trace, + bt_trace_is_static_listener listener, + bt_trace_listener_removed listener_removed, void *data, + uint64_t *listener_id) +{ + uint64_t i; + struct bt_trace_is_static_listener_elem new_elem = { + .func = listener, + .removed = listener_removed, + .data = data, + }; + + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_NON_NULL(listener, "Listener"); + BT_ASSERT_PRE(!trace->is_static, + "Trace is already static: %!+t", trace); + BT_ASSERT_PRE(trace->in_remove_listener, + "Cannot call this function while executing a " + "remove listener: %!+t", trace); + + /* Find the next available spot */ + for (i = 0; i < trace->is_static_listeners->len; i++) { + struct bt_trace_is_static_listener_elem elem = + g_array_index(trace->is_static_listeners, + struct bt_trace_is_static_listener_elem, i); + + if (!elem.func) { + break; + } + } + + if (i == trace->is_static_listeners->len) { + g_array_append_val(trace->is_static_listeners, new_elem); + } else { + g_array_insert_val(trace->is_static_listeners, i, new_elem); + } + + if (listener_id) { + *listener_id = i; + } + + BT_LIB_LOGV("Added \"trace is static\" listener: " + "%![trace-]+t, listener-id=%" PRIu64, trace, i); + return 0; +} + +BT_ASSERT_PRE_FUNC +static +bool has_listener_id(struct bt_trace *trace, uint64_t listener_id) +{ + BT_ASSERT(listener_id < trace->is_static_listeners->len); + return (&g_array_index(trace->is_static_listeners, + struct bt_trace_is_static_listener_elem, + listener_id))->func != NULL; +} + +int bt_trace_remove_is_static_listener( + struct bt_trace *trace, uint64_t listener_id) +{ + struct bt_trace_is_static_listener_elem *elem; + + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE(!trace->is_static, + "Trace is already static: %!+t", trace); + BT_ASSERT_PRE(trace->in_remove_listener, + "Cannot call this function while executing a " + "remove listener: %!+t", trace); + BT_ASSERT_PRE(has_listener_id(trace, listener_id), + "Trace has no such \"trace is static\" listener ID: " + "%![trace-]+t, %" PRIu64, trace, listener_id); + elem = &g_array_index(trace->is_static_listeners, + struct bt_trace_is_static_listener_elem, + listener_id); + BT_ASSERT(elem->func); + + if (elem->removed) { + /* Call remove listener */ + BT_LIB_LOGV("Calling remove listener: " + "%![trace-]+t, listener-id=%" PRIu64, + trace, listener_id); + trace->in_remove_listener = true; + elem->removed(trace, elem->data); + trace->in_remove_listener = false; + } + + elem->func = NULL; + elem->removed = NULL; + elem->data = NULL; + BT_LIB_LOGV("Removed \"trace is static\" listener: " + "%![trace-]+t, listener-id=%" PRIu64, + trace, listener_id); + return 0; +} + +BT_HIDDEN +void _bt_trace_freeze(struct bt_trace *trace) +{ + /* The packet header field type is already frozen */ + BT_ASSERT(trace); + BT_LIB_LOGD("Freezing trace: %!+t", trace); + trace->frozen = true; +} + +bt_bool bt_trace_assigns_automatic_stream_class_id(struct bt_trace *trace) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + return (bt_bool) trace->assigns_automatic_stream_class_id; +} + +int bt_trace_set_assigns_automatic_stream_class_id( + struct bt_trace *trace, bt_bool value) +{ + BT_ASSERT_PRE_NON_NULL(trace, "Trace"); + BT_ASSERT_PRE_TRACE_HOT(trace); + trace->assigns_automatic_stream_class_id = (bool) value; + BT_LIB_LOGV("Set trace's automatic stream class ID " + "assignment property: %!+t", trace); + return 0; +} + +BT_HIDDEN +void bt_trace_add_stream(struct bt_trace *trace, struct bt_stream *stream) +{ + guint count = 0; + + bt_object_set_parent(&stream->base, &trace->base); + g_ptr_array_add(trace->streams, stream); + bt_trace_freeze(trace); + + if (bt_g_hash_table_contains(trace->stream_classes_stream_count, + stream->class)) { + count = GPOINTER_TO_UINT(g_hash_table_lookup( + trace->stream_classes_stream_count, stream->class)); + } + + g_hash_table_insert(trace->stream_classes_stream_count, + stream->class, GUINT_TO_POINTER(count + 1)); +} + +BT_HIDDEN +uint64_t bt_trace_get_automatic_stream_id(struct bt_trace *trace, + struct bt_stream_class *stream_class) +{ + gpointer orig_key; + gpointer value; + uint64_t id = 0; + + BT_ASSERT(stream_class); + BT_ASSERT(trace); + if (g_hash_table_lookup_extended(trace->stream_classes_stream_count, + stream_class, &orig_key, &value)) { + id = (uint64_t) GPOINTER_TO_UINT(value); + } + + return id; +} diff --git a/lib/trace-ir/utils.c b/lib/trace-ir/utils.c new file mode 100644 index 00000000..76906a68 --- /dev/null +++ b/lib/trace-ir/utils.c @@ -0,0 +1,37 @@ +/* + * utils.c + * + * Babeltrace trace IR - Utilities + * + * Copyright 2015 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_TAG "TRACE-IR-UTILS" +#include + +#include +#include +#include +#include +#include +#include diff --git a/plugins/ctf/fs-src/fs.h b/plugins/ctf/fs-src/fs.h index c72be5e0..26e796a7 100644 --- a/plugins/ctf/fs-src/fs.h +++ b/plugins/ctf/fs-src/fs.h @@ -106,7 +106,7 @@ struct ctf_fs_ds_file_group { * belong to this group (a single stream instance). * * You can call ctf_fs_ds_file_create() with one of those paths - * and the CTF IR stream below. + * and the trace IR stream below. */ GPtrArray *ds_file_infos; diff --git a/tests/Makefile.am b/tests/Makefile.am index 05e9439e..c5ac2d77 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -26,7 +26,7 @@ TESTS_CLI = \ TESTS_LIB = \ lib/test_ctf_writer_complete \ lib/test_bt_values \ - lib/test_ctf_ir_ref \ + lib/test_trace_ir_ref \ lib/test_bt_ctf_field_type_validation \ lib/test_ir_visit \ lib/test_graph_topo \ @@ -38,7 +38,7 @@ TESTS_LIB += lib/test_plugin_complete endif if ENABLE_PYTHON_BINDINGS -TESTS_LIB += lib/ctf-ir/test_ctf_ir +TESTS_LIB += lib/trace-ir/test_trace_ir TESTS_LIB += lib/ctf-writer/test_ctf_writer endif diff --git a/tests/lib/Makefile.am b/tests/lib/Makefile.am index b2b34642..39ad76e0 100644 --- a/tests/lib/Makefile.am +++ b/tests/lib/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = ctf-ir ctf-writer +SUBDIRS = trace-ir ctf-writer AM_CPPFLAGS += -I$(top_srcdir)/tests/utils @@ -19,19 +19,19 @@ test_ctf_writer_LDADD = $(COMMON_TEST_LDADD) test_bt_values_LDADD = $(COMMON_TEST_LDADD) -test_ctf_ir_ref_LDADD = $(COMMON_TEST_LDADD) +test_trace_ir_ref_LDADD = $(COMMON_TEST_LDADD) test_graph_topo_LDADD = $(COMMON_TEST_LDADD) test_bt_notification_iterator_LDADD = $(COMMON_TEST_LDADD) noinst_PROGRAMS = test_bitfield test_ctf_writer test_bt_values \ - test_ctf_ir_ref test_graph_topo test_bt_notification_iterator + test_trace_ir_ref test_graph_topo test_bt_notification_iterator test_bitfield_SOURCES = test_bitfield.c test_ctf_writer_SOURCES = test_ctf_writer.c test_bt_values_SOURCES = test_bt_values.c -test_ctf_ir_ref_SOURCES = test_ctf_ir_ref.c +test_trace_ir_ref_SOURCES = test_trace_ir_ref.c test_graph_topo_SOURCES = test_graph_topo.c test_bt_notification_iterator_SOURCES = test_bt_notification_iterator.c diff --git a/tests/lib/ctf-ir/Makefile.am b/tests/lib/ctf-ir/Makefile.am deleted file mode 100644 index 0c4adbe7..00000000 --- a/tests/lib/ctf-ir/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -if ENABLE_PYTHON_BINDINGS -check_SCRIPTS = test_ctf_ir -endif - -EXTRA_DIST = test_trace.py test_stream_class.py diff --git a/tests/lib/ctf-ir/test_ctf_ir.in b/tests/lib/ctf-ir/test_ctf_ir.in deleted file mode 100644 index c3ff375c..00000000 --- a/tests/lib/ctf-ir/test_ctf_ir.in +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2017 - Philippe Proulx -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; only version 2 -# of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# - -NO_SH_TAP=1 -. "@abs_top_builddir@/tests/utils/common.sh" - -PYTHON_BUILD_DIR="${BT_BUILD_PATH}/bindings/python/bt2/build/build_lib" -TESTS_UTILS_PYTHON_DIR="${BT_SRC_PATH}/tests/utils/python" -TESTRUNNER_PY="${BT_SRC_PATH}/tests/utils/python/testrunner.py" -THIS_DIR="${BT_SRC_PATH}/tests/lib/ctf-ir" - -if [ "x${MSYSTEM}" != "x" ]; then - export PATH="${BT_BUILD_PATH}/lib/.libs:${PATH}" -else - export LD_LIBRARY_PATH="${BT_BUILD_PATH}/lib/.libs:${LD_LIBRARY_PATH}" -fi - -PYTHONPATH="${PYTHON_BUILD_DIR}:${TESTS_UTILS_PYTHON_DIR}" \ - "@PYTHON@" "${TESTRUNNER_PY}" "${THIS_DIR}" -exit $? diff --git a/tests/lib/ctf-ir/test_stream_class.py b/tests/lib/ctf-ir/test_stream_class.py deleted file mode 100644 index 0841848b..00000000 --- a/tests/lib/ctf-ir/test_stream_class.py +++ /dev/null @@ -1,197 +0,0 @@ -import unittest -import bt2 - - -class StreamClassSingleClockClassTestCase(unittest.TestCase): - def setUp(self): - self._sc = bt2.StreamClass() - - def tearDown(self): - del self._sc - - def _test_add_sc_ft_vs_event_class(self, set_ft_func): - cc = bt2.ClockClass('first_cc', 1000) - scft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - scft.append_field('salut', ft) - set_ft_func(scft) - cc = bt2.ClockClass('second_cc', 1000) - payloadft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - payloadft.append_field('zorg', ft) - ec = bt2.EventClass('ec', payload_field_type=payloadft) - self._sc.add_event_class(ec) - trace = bt2.Trace() - - with self.assertRaises(bt2.Error): - trace.add_stream_class(self._sc) - - def test_add_sc_packet_context_vs_event_class(self): - def func(ft): - self._sc.packet_context_field_type = ft - - self._test_add_sc_ft_vs_event_class(func) - - def test_add_sc_event_context_vs_event_class(self): - def func(ft): - self._sc.event_context_field_type = ft - - self._test_add_sc_ft_vs_event_class(func) - - def test_add_sc_event_header_vs_event_class(self): - def func(ft): - self._sc.event_header_field_type = ft - - self._test_add_sc_ft_vs_event_class(func) - - def test_add_sc_event_class_vs_event_class(self): - ehft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32) - ehft.append_field('id', ft) - self._sc.event_header_field_type = ehft - cc = bt2.ClockClass('first_cc', 1000) - payloadft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - payloadft.append_field('zorg', ft) - ec1 = bt2.EventClass('ec', payload_field_type=payloadft) - cc = bt2.ClockClass('second_cc', 1000) - payloadft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - payloadft.append_field('logi', ft) - ec2 = bt2.EventClass('ec', payload_field_type=payloadft) - self._sc.add_event_class(ec1) - self._sc.add_event_class(ec2) - trace = bt2.Trace() - - with self.assertRaises(bt2.Error): - trace.add_stream_class(self._sc) - - def _test_create_event_ft_vs_event_class(self, set_ft_func): - cc = bt2.ClockClass('first_cc', 1000) - scft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - scft.append_field('salut', ft) - set_ft_func(scft) - cc = bt2.ClockClass('second_cc', 1000) - payloadft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - payloadft.append_field('zorg', ft) - ec = bt2.EventClass('ec', payload_field_type=payloadft) - self._sc.add_event_class(ec) - - with self.assertRaises(bt2.Error): - ev = ec() - - def test_create_event_packet_context_vs_event_class(self): - def func(ft): - self._sc.packet_context_field_type = ft - - self._test_create_event_ft_vs_event_class(func) - - def test_create_event_event_context_vs_event_class(self): - def func(ft): - self._sc.event_context_field_type = ft - - self._test_create_event_ft_vs_event_class(func) - - def test_create_event_event_header_vs_event_class(self): - def func(ft): - self._sc.event_header_field_type = ft - - self._test_create_event_ft_vs_event_class(func) - - def test_create_event_event_class_vs_event_class(self): - ehft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32) - ehft.append_field('id', ft) - self._sc.event_header_field_type = ehft - cc = bt2.ClockClass('first_cc', 1000) - payloadft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - payloadft.append_field('zorg', ft) - ec1 = bt2.EventClass('ec', payload_field_type=payloadft) - cc = bt2.ClockClass('second_cc', 1000) - payloadft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - payloadft.append_field('logi', ft) - ec2 = bt2.EventClass('ec', payload_field_type=payloadft) - self._sc.add_event_class(ec1) - self._sc.add_event_class(ec2) - - with self.assertRaises(bt2.Error): - ev = ec1() - - def test_add_ec_after_add_sc(self): - cc = bt2.ClockClass('first_cc', 1000) - scft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - scft.append_field('salut', ft) - self._sc.packet_context_field_type = scft - trace = bt2.Trace() - trace.add_stream_class(self._sc) - cc = bt2.ClockClass('second_cc', 1000) - payloadft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - payloadft.append_field('zorg', ft) - ec = bt2.EventClass('ec', payload_field_type=payloadft) - - with self.assertRaises(bt2.Error): - self._sc.add_event_class(ec) - - def test_add_ec_after_add_sc_single_cc(self): - ehft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32) - ehft.append_field('id', ft) - self._sc.event_header_field_type = ehft - trace = bt2.Trace() - trace.add_stream_class(self._sc) - cc = bt2.ClockClass('first_cc', 1000) - payloadft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - payloadft.append_field('zorg', ft) - ec = bt2.EventClass('ec', payload_field_type=payloadft) - self._sc.add_event_class(ec) - cc = bt2.ClockClass('second_cc', 1000) - payloadft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - payloadft.append_field('lel', ft) - ec = bt2.EventClass('ec', payload_field_type=payloadft) - - with self.assertRaises(bt2.Error): - self._sc.add_event_class(ec) - - def test_add_ec_after_create_event(self): - ehft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32) - ehft.append_field('id', ft) - self._sc.event_header_field_type = ehft - cc = bt2.ClockClass('first_cc', 1000) - payloadft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - payloadft.append_field('zorg', ft) - ec1 = bt2.EventClass('ec', payload_field_type=payloadft) - self._sc.add_event_class(ec1) - ev = ec1() - cc = bt2.ClockClass('second_cc', 1000) - payloadft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - payloadft.append_field('logi', ft) - ec2 = bt2.EventClass('ec', payload_field_type=payloadft) - - with self.assertRaises(bt2.Error): - self._sc.add_event_class(ec2) - - def test_sc_clock_matches_expected_clock_class(self): - clock = bt2.CtfWriterClock('sc_clock') - self._sc.clock = clock - writer = bt2.CtfWriter('/tmp') - writer.add_clock(clock) - writer.trace.add_stream_class(self._sc) - cc = bt2.ClockClass('other_cc', 1000) - payloadft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - payloadft.append_field('zorg', ft) - ec = bt2.EventClass('ec', payload_field_type=payloadft) - - with self.assertRaises(bt2.Error): - self._sc.add_event_class(ec) diff --git a/tests/lib/ctf-ir/test_trace.py b/tests/lib/ctf-ir/test_trace.py deleted file mode 100644 index 116f7ba2..00000000 --- a/tests/lib/ctf-ir/test_trace.py +++ /dev/null @@ -1,91 +0,0 @@ -import unittest -import bt2 - - -class TraceTestCase(unittest.TestCase): - def setUp(self): - self._trace = bt2.Trace() - - def tearDown(self): - del self._trace - - def _add_stream_class(self): - sc = bt2.StreamClass() - self._trace.add_stream_class(sc) - - def test_packet_header_ft_no_clock_class_simple(self): - cc = bt2.ClockClass('hello', 1000) - phft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - phft.append_field('salut', ft) - self._trace.add_clock_class(cc) - self._trace.packet_header_field_type = phft - - with self.assertRaises(bt2.Error): - self._add_stream_class() - - def test_packet_header_ft_no_clock_class_struct(self): - cc = bt2.ClockClass('hello', 1000) - phft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - struct_ft = bt2.StructureFieldType() - struct_ft.append_field('salut', ft) - phft.append_field('boucane', struct_ft) - self._trace.add_clock_class(cc) - self._trace.packet_header_field_type = phft - - with self.assertRaises(bt2.Error): - self._add_stream_class() - - def test_packet_header_ft_no_clock_class_variant(self): - cc = bt2.ClockClass('hello', 1000) - phft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - tag_ft = bt2.EnumerationFieldType(size=32) - tag_ft.add_mapping('heille', 12) - variant_ft = bt2.VariantFieldType('tag', tag_ft) - variant_ft.append_field('heille', ft) - phft.append_field('tag', tag_ft) - phft.append_field('boucane', variant_ft) - self._trace.add_clock_class(cc) - self._trace.packet_header_field_type = phft - - with self.assertRaises(bt2.Error): - self._add_stream_class() - - def test_packet_header_ft_no_clock_class_array(self): - cc = bt2.ClockClass('hello', 1000) - phft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - array_ft = bt2.ArrayFieldType(ft, 23) - phft.append_field('boucane', array_ft) - self._trace.add_clock_class(cc) - self._trace.packet_header_field_type = phft - - with self.assertRaises(bt2.Error): - self._add_stream_class() - - def test_packet_header_ft_no_clock_class_sequence(self): - cc = bt2.ClockClass('hello', 1000) - phft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - len_ft = bt2.IntegerFieldType(32) - seq_ft = bt2.SequenceFieldType(ft, 'len') - phft.append_field('len', len_ft) - phft.append_field('boucane', seq_ft) - self._trace.add_clock_class(cc) - self._trace.packet_header_field_type = phft - - with self.assertRaises(bt2.Error): - self._add_stream_class() - - def test_packet_header_ft_no_clock_class_set_static(self): - cc = bt2.ClockClass('hello', 1000) - phft = bt2.StructureFieldType() - ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) - phft.append_field('salut', ft) - self._trace.add_clock_class(cc) - self._trace.packet_header_field_type = phft - - with self.assertRaises(bt2.Error): - self._trace.set_is_static() diff --git a/tests/lib/test_bt_notification_iterator.c b/tests/lib/test_bt_notification_iterator.c index 3cfa4745..645b8850 100644 --- a/tests/lib/test_bt_notification_iterator.c +++ b/tests/lib/test_bt_notification_iterator.c @@ -22,14 +22,14 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include diff --git a/tests/lib/test_ctf_ir_ref.c b/tests/lib/test_ctf_ir_ref.c deleted file mode 100644 index e618a269..00000000 --- a/tests/lib/test_ctf_ir_ref.c +++ /dev/null @@ -1,625 +0,0 @@ -/* - * test_ctf_ir_ref.c - * - * CTF IR Reference Count test - * - * Copyright 2016 - Jérémie Galarneau - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; under version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "tap/tap.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "common.h" - -#define NR_TESTS 37 - -struct user { - struct bt_trace *tc; - struct bt_stream_class *sc; - struct bt_event_class *ec; - struct bt_stream *stream; - struct bt_event *event; -}; - -struct writer_user { - struct bt_ctf_writer *writer; - struct bt_ctf_trace *tc; - struct bt_ctf_stream_class *sc; - struct bt_ctf_event_class *ec; - struct bt_ctf_stream *stream; - struct bt_ctf_event *event; -}; - -const char *writer_user_names[] = { - "writer", - "trace", - "stream class", - "event class", - "stream", - "event", -}; - -static const size_t WRITER_USER_NR_ELEMENTS = - sizeof(struct writer_user) / sizeof(void *); - -/** - * Returns a structure containing the following fields: - * - uint8_t payload_8; - * - uint16_t payload_16; - * - uint32_t payload_32; - */ -static struct bt_field_type *create_integer_struct(void) -{ - int ret; - struct bt_field_type *structure = NULL; - struct bt_field_type *ui8 = NULL, *ui16 = NULL, *ui32 = NULL; - - structure = bt_field_type_structure_create(); - BT_ASSERT(structure); - ui8 = bt_field_type_unsigned_integer_create(); - BT_ASSERT(ui8); - ret = bt_field_type_integer_set_field_value_range(ui8, 8); - BT_ASSERT(ret == 0); - ret = bt_field_type_structure_append_member(structure, - "payload_8", ui8); - BT_ASSERT(ret == 0); - ui16 = bt_field_type_unsigned_integer_create(); - BT_ASSERT(ui16); - ret = bt_field_type_integer_set_field_value_range(ui16, 16); - BT_ASSERT(ret == 0); - ret = bt_field_type_structure_append_member(structure, - "payload_16", ui16); - BT_ASSERT(ret == 0); - ui32 = bt_field_type_unsigned_integer_create(); - BT_ASSERT(ui32); - ret = bt_field_type_integer_set_field_value_range(ui32, 32); - BT_ASSERT(ret == 0); - ret = bt_field_type_structure_append_member(structure, - "payload_32", ui32); - BT_ASSERT(ret == 0); - BT_PUT(ui8); - BT_PUT(ui16); - BT_PUT(ui32); - return structure; -} - -static struct bt_ctf_field_type *create_writer_integer_struct(void) -{ - int ret; - struct bt_ctf_field_type *structure = NULL; - struct bt_ctf_field_type *ui8 = NULL, *ui16 = NULL, *ui32 = NULL; - - structure = bt_ctf_field_type_structure_create(); - BT_ASSERT(structure); - ui8 = bt_ctf_field_type_integer_create(8); - BT_ASSERT(ui8); - ret = bt_ctf_field_type_structure_add_field(structure, ui8, - "payload_8"); - BT_ASSERT(ret == 0); - ui16 = bt_ctf_field_type_integer_create(16); - BT_ASSERT(ui16); - ret = bt_ctf_field_type_structure_add_field(structure, ui16, - "payload_16"); - BT_ASSERT(ret == 0); - ui32 = bt_ctf_field_type_integer_create(32); - BT_ASSERT(ui32); - ret = bt_ctf_field_type_structure_add_field(structure, ui32, - "payload_32"); - BT_ASSERT(ret == 0); - BT_PUT(ui8); - BT_PUT(ui16); - BT_PUT(ui32); - return structure; -} - -/** - * A simple event has the following payload: - * - uint8_t payload_8; - * - uint16_t payload_16; - * - uint32_t payload_32; - */ -static struct bt_event_class *create_simple_event(struct bt_stream_class *sc, - const char *name) -{ - int ret; - struct bt_event_class *event = NULL; - struct bt_field_type *payload = NULL; - - BT_ASSERT(name); - event = bt_event_class_create(sc); - BT_ASSERT(event); - ret = bt_event_class_set_name(event, name); - BT_ASSERT(ret == 0); - payload = create_integer_struct(); - BT_ASSERT(payload); - ret = bt_event_class_set_payload_field_type(event, payload); - BT_ASSERT(ret == 0); - BT_PUT(payload); - return event; -} - -/** - * A complex event has the following payload: - * - uint8_t payload_8; - * - uint16_t payload_16; - * - uint32_t payload_32; - * - struct payload_struct: - * - uint8_t payload_8; - * - uint16_t payload_16; - * - uint32_t payload_32; - */ -static struct bt_event_class *create_complex_event(struct bt_stream_class *sc, - const char *name) -{ - int ret; - struct bt_event_class *event = NULL; - struct bt_field_type *inner = NULL, *outer = NULL; - - BT_ASSERT(name); - event = bt_event_class_create(sc); - BT_ASSERT(event); - ret = bt_event_class_set_name(event, name); - BT_ASSERT(ret == 0); - outer = create_integer_struct(); - BT_ASSERT(outer); - inner = create_integer_struct(); - BT_ASSERT(inner); - ret = bt_field_type_structure_append_member(outer, - "payload_struct", inner); - BT_ASSERT(ret == 0); - ret = bt_event_class_set_payload_field_type(event, outer); - BT_ASSERT(ret == 0); - BT_PUT(inner); - BT_PUT(outer); - return event; -} - -static void set_stream_class_field_types( - struct bt_stream_class *stream_class) -{ - struct bt_field_type *packet_context_type; - struct bt_field_type *event_header_type; - struct bt_field_type *ft; - int ret; - - packet_context_type = bt_field_type_structure_create(); - BT_ASSERT(packet_context_type); - ft = bt_field_type_unsigned_integer_create(); - BT_ASSERT(ft); - ret = bt_field_type_integer_set_field_value_range(ft, 32); - BT_ASSERT(ret == 0); - ret = bt_field_type_structure_append_member(packet_context_type, - "packet_size", ft); - BT_ASSERT(ret == 0); - bt_put(ft); - ft = bt_field_type_unsigned_integer_create(); - BT_ASSERT(ft); - ret = bt_field_type_integer_set_field_value_range(ft, 32); - BT_ASSERT(ret == 0); - ret = bt_field_type_structure_append_member(packet_context_type, - "content_size", ft); - BT_ASSERT(ret == 0); - bt_put(ft); - event_header_type = bt_field_type_structure_create(); - BT_ASSERT(event_header_type); - ft = bt_field_type_unsigned_integer_create(); - BT_ASSERT(ft); - ret = bt_field_type_integer_set_field_value_range(ft, 32); - BT_ASSERT(ret == 0); - ret = bt_field_type_structure_append_member(event_header_type, - "id", ft); - BT_ASSERT(ret == 0); - bt_put(ft); - ret = bt_stream_class_set_packet_context_field_type(stream_class, - packet_context_type); - BT_ASSERT(ret == 0); - ret = bt_stream_class_set_event_header_field_type(stream_class, - event_header_type); - BT_ASSERT(ret == 0); - bt_put(packet_context_type); - bt_put(event_header_type); -} - -static void create_sc1(struct bt_trace *trace) -{ - int ret; - struct bt_event_class *ec1 = NULL, *ec2 = NULL; - struct bt_stream_class *sc1 = NULL, *ret_stream = NULL; - - sc1 = bt_stream_class_create(trace); - BT_ASSERT(sc1); - ret = bt_stream_class_set_name(sc1, "sc1"); - BT_ASSERT(ret == 0); - set_stream_class_field_types(sc1); - ec1 = create_complex_event(sc1, "ec1"); - BT_ASSERT(ec1); - ec2 = create_simple_event(sc1, "ec2"); - BT_ASSERT(ec2); - ret_stream = bt_event_class_borrow_stream_class(ec1); - ok(ret_stream == sc1, "Borrow parent stream SC1 from EC1"); - ret_stream = bt_event_class_borrow_stream_class(ec2); - ok(ret_stream == sc1, "Borrow parent stream SC1 from EC2"); - BT_PUT(ec1); - BT_PUT(ec2); - BT_PUT(sc1); -} - -static void create_sc2(struct bt_trace *trace) -{ - int ret; - struct bt_event_class *ec3 = NULL; - struct bt_stream_class *sc2 = NULL, *ret_stream = NULL; - - sc2 = bt_stream_class_create(trace); - BT_ASSERT(sc2); - ret = bt_stream_class_set_name(sc2, "sc2"); - BT_ASSERT(ret == 0); - set_stream_class_field_types(sc2); - ec3 = create_simple_event(sc2, "ec3"); - ret_stream = bt_event_class_borrow_stream_class(ec3); - ok(ret_stream == sc2, "Borrow parent stream SC2 from EC3"); - BT_PUT(ec3); - BT_PUT(sc2); -} - -static void set_trace_packet_header(struct bt_trace *trace) -{ - struct bt_field_type *packet_header_type; - struct bt_field_type *ft; - int ret; - - packet_header_type = bt_field_type_structure_create(); - BT_ASSERT(packet_header_type); - ft = bt_field_type_unsigned_integer_create(); - BT_ASSERT(ft); - ret = bt_field_type_integer_set_field_value_range(ft, 32); - BT_ASSERT(ret == 0); - ret = bt_field_type_structure_append_member(packet_header_type, - "stream_id", ft); - BT_ASSERT(ret == 0); - bt_put(ft); - ret = bt_trace_set_packet_header_field_type(trace, - packet_header_type); - BT_ASSERT(ret == 0); - - bt_put(packet_header_type); -} - -static struct bt_trace *create_tc1(void) -{ - struct bt_trace *tc1 = NULL; - - tc1 = bt_trace_create(); - BT_ASSERT(tc1); - set_trace_packet_header(tc1); - create_sc1(tc1); - create_sc2(tc1); - return tc1; -} - -static void init_weak_refs(struct bt_trace *tc, - struct bt_trace **tc1, - struct bt_stream_class **sc1, - struct bt_stream_class **sc2, - struct bt_event_class **ec1, - struct bt_event_class **ec2, - struct bt_event_class **ec3) -{ - *tc1 = tc; - *sc1 = bt_trace_borrow_stream_class_by_index(tc, 0); - *sc2 = bt_trace_borrow_stream_class_by_index(tc, 1); - *ec1 = bt_stream_class_borrow_event_class_by_index(*sc1, 0); - *ec2 = bt_stream_class_borrow_event_class_by_index(*sc1, 1); - *ec3 = bt_stream_class_borrow_event_class_by_index(*sc2, 0); -} - -static void test_example_scenario(void) -{ - /** - * Weak pointers to CTF-IR objects are to be used very carefully. - * This is NOT a good practice and is strongly discouraged; this - * is only done to facilitate the validation of expected reference - * counts without affecting them by taking "real" references to the - * objects. - */ - struct bt_trace *tc1 = NULL, *weak_tc1 = NULL; - struct bt_stream_class *weak_sc1 = NULL, *weak_sc2 = NULL; - struct bt_event_class *weak_ec1 = NULL, *weak_ec2 = NULL, - *weak_ec3 = NULL; - struct user user_a = { 0 }, user_b = { 0 }, user_c = { 0 }; - - /* The only reference which exists at this point is on TC1. */ - tc1 = create_tc1(); - ok(tc1, "Initialize trace"); - BT_ASSERT(tc1); - init_weak_refs(tc1, &weak_tc1, &weak_sc1, &weak_sc2, &weak_ec1, - &weak_ec2, &weak_ec3); - ok(bt_object_get_ref_count((void *) weak_sc1) == 0, - "Initial SC1 reference count is 0"); - ok(bt_object_get_ref_count((void *) weak_sc2) == 0, - "Initial SC2 reference count is 0"); - ok(bt_object_get_ref_count((void *) weak_ec1) == 0, - "Initial EC1 reference count is 0"); - ok(bt_object_get_ref_count((void *) weak_ec2) == 0, - "Initial EC2 reference count is 0"); - ok(bt_object_get_ref_count((void *) weak_ec3) == 0, - "Initial EC3 reference count is 0"); - - /* User A has ownership of the trace. */ - BT_MOVE(user_a.tc, tc1); - ok(bt_object_get_ref_count((void *) user_a.tc) == 1, - "TC1 reference count is 1"); - - /* User A acquires a reference to SC2 from TC1. */ - user_a.sc = bt_get(bt_trace_borrow_stream_class_by_index(user_a.tc, 1)); - ok(user_a.sc, "User A acquires SC2 from TC1"); - ok(bt_object_get_ref_count((void *) weak_tc1) == 2, - "TC1 reference count is 2"); - ok(bt_object_get_ref_count((void *) weak_sc2) == 1, - "SC2 reference count is 1"); - - /* User A acquires a reference to EC3 from SC2. */ - user_a.ec = bt_get( - bt_stream_class_borrow_event_class_by_index(user_a.sc, 0)); - ok(user_a.ec, "User A acquires EC3 from SC2"); - ok(bt_object_get_ref_count((void *) weak_tc1) == 2, - "TC1 reference count is 2"); - ok(bt_object_get_ref_count((void *) weak_sc2) == 2, - "SC2 reference count is 2"); - ok(bt_object_get_ref_count((void *) weak_ec3) == 1, - "EC3 reference count is 1"); - - /* User A releases its reference to SC2. */ - diag("User A releases SC2"); - BT_PUT(user_a.sc); - /* - * We keep the pointer to SC2 around to validate its reference - * count. - */ - ok(bt_object_get_ref_count((void *) weak_tc1) == 2, - "TC1 reference count is 2"); - ok(bt_object_get_ref_count((void *) weak_sc2) == 1, - "SC2 reference count is 1"); - ok(bt_object_get_ref_count((void *) weak_ec3) == 1, - "EC3 reference count is 1"); - - /* User A releases its reference to TC1. */ - diag("User A releases TC1"); - BT_PUT(user_a.tc); - /* - * We keep the pointer to TC1 around to validate its reference - * count. - */ - ok(bt_object_get_ref_count((void *) weak_tc1) == 1, - "TC1 reference count is 1"); - ok(bt_object_get_ref_count((void *) weak_sc2) == 1, - "SC2 reference count is 1"); - ok(bt_object_get_ref_count((void *) weak_ec3) == 1, - "EC3 reference count is 1"); - - /* User B acquires a reference to SC1. */ - diag("User B acquires a reference to SC1"); - user_b.sc = bt_get(weak_sc1); - ok(bt_object_get_ref_count((void *) weak_tc1) == 2, - "TC1 reference count is 2"); - ok(bt_object_get_ref_count((void *) weak_sc1) == 1, - "SC1 reference count is 1"); - - /* User C acquires a reference to EC1. */ - diag("User C acquires a reference to EC1"); - user_c.ec = bt_get( - bt_stream_class_borrow_event_class_by_index(user_b.sc, 0)); - ok(bt_object_get_ref_count((void *) weak_ec1) == 1, - "EC1 reference count is 1"); - ok(bt_object_get_ref_count((void *) weak_sc1) == 2, - "SC1 reference count is 2"); - - /* User A releases its reference on EC3. */ - diag("User A releases its reference on EC3"); - BT_PUT(user_a.ec); - ok(bt_object_get_ref_count((void *) weak_ec3) == 0, - "EC3 reference count is 1"); - ok(bt_object_get_ref_count((void *) weak_sc2) == 0, - "SC2 reference count is 0"); - ok(bt_object_get_ref_count((void *) weak_tc1) == 1, - "TC1 reference count is 1"); - - /* User B releases its reference on SC1. */ - diag("User B releases its reference on SC1"); - BT_PUT(user_b.sc); - ok(bt_object_get_ref_count((void *) weak_sc1) == 1, - "SC1 reference count is 1"); - - /* - * User C is the sole owner of an object and is keeping the whole - * trace hierarchy "alive" by holding a reference to EC1. - */ - ok(bt_object_get_ref_count((void *) weak_tc1) == 1, - "TC1 reference count is 1"); - ok(bt_object_get_ref_count((void *) weak_sc1) == 1, - "SC1 reference count is 1"); - ok(bt_object_get_ref_count((void *) weak_sc2) == 0, - "SC2 reference count is 0"); - ok(bt_object_get_ref_count((void *) weak_ec1) == 1, - "EC1 reference count is 1"); - ok(bt_object_get_ref_count((void *) weak_ec2) == 0, - "EC2 reference count is 0"); - ok(bt_object_get_ref_count((void *) weak_ec3) == 0, - "EC3 reference count is 0"); - - /* Reclaim last reference held by User C. */ - BT_PUT(user_c.ec); -} - -static void create_writer_user_full(struct writer_user *user) -{ - gchar *trace_path; - struct bt_ctf_field_type *ft; - struct bt_ctf_field *field; - struct bt_ctf_clock *clock; - int ret; - - trace_path = g_build_filename(g_get_tmp_dir(), "ctfwriter_XXXXXX", NULL); - if (!bt_mkdtemp(trace_path)) { - perror("# perror"); - } - - user->writer = bt_ctf_writer_create(trace_path); - BT_ASSERT(user->writer); - ret = bt_ctf_writer_set_byte_order(user->writer, - BT_CTF_BYTE_ORDER_LITTLE_ENDIAN); - BT_ASSERT(ret == 0); - user->tc = bt_ctf_writer_get_trace(user->writer); - BT_ASSERT(user->tc); - user->sc = bt_ctf_stream_class_create("sc"); - BT_ASSERT(user->sc); - clock = bt_ctf_clock_create("the_clock"); - BT_ASSERT(clock); - ret = bt_ctf_writer_add_clock(user->writer, clock); - BT_ASSERT(!ret); - ret = bt_ctf_stream_class_set_clock(user->sc, clock); - BT_ASSERT(!ret); - BT_PUT(clock); - user->stream = bt_ctf_writer_create_stream(user->writer, user->sc); - BT_ASSERT(user->stream); - user->ec = bt_ctf_event_class_create("ec"); - BT_ASSERT(user->ec); - ft = create_writer_integer_struct(); - BT_ASSERT(ft); - ret = bt_ctf_event_class_set_payload_field_type(user->ec, ft); - BT_PUT(ft); - BT_ASSERT(!ret); - ret = bt_ctf_stream_class_add_event_class(user->sc, user->ec); - BT_ASSERT(!ret); - user->event = bt_ctf_event_create(user->ec); - BT_ASSERT(user->event); - field = bt_ctf_event_get_payload(user->event, "payload_8"); - BT_ASSERT(field); - ret = bt_ctf_field_integer_unsigned_set_value(field, 10); - BT_ASSERT(!ret); - BT_PUT(field); - field = bt_ctf_event_get_payload(user->event, "payload_16"); - BT_ASSERT(field); - ret = bt_ctf_field_integer_unsigned_set_value(field, 20); - BT_ASSERT(!ret); - BT_PUT(field); - field = bt_ctf_event_get_payload(user->event, "payload_32"); - BT_ASSERT(field); - ret = bt_ctf_field_integer_unsigned_set_value(field, 30); - BT_ASSERT(!ret); - BT_PUT(field); - ret = bt_ctf_stream_append_event(user->stream, user->event); - BT_ASSERT(!ret); - recursive_rmdir(trace_path); - g_free(trace_path); -} - -static void test_put_order_swap(size_t *array, size_t a, size_t b) -{ - size_t temp = array[a]; - - array[a] = array[b]; - array[b] = temp; -} - -static void test_put_order_put_objects(size_t *array, size_t size) -{ - size_t i; - struct writer_user user = { 0 }; - void **objects = (void *) &user; - - create_writer_user_full(&user); - printf("# "); - - for (i = 0; i < size; ++i) { - void *obj = objects[array[i]]; - - printf("%s", writer_user_names[array[i]]); - BT_PUT(obj); - - if (i < size - 1) { - printf(" -> "); - } - } - - puts(""); -} - -static void test_put_order_permute(size_t *array, int k, size_t size) -{ - if (k == 0) { - test_put_order_put_objects(array, size); - } else { - int i; - - for (i = k - 1; i >= 0; i--) { - size_t next_k = k - 1; - - test_put_order_swap(array, i, next_k); - test_put_order_permute(array, next_k, size); - test_put_order_swap(array, i, next_k); - } - } -} - -static void test_put_order(void) -{ - size_t i; - size_t array[WRITER_USER_NR_ELEMENTS]; - - /* Initialize array of indexes */ - for (i = 0; i < WRITER_USER_NR_ELEMENTS; ++i) { - array[i] = i; - } - - test_put_order_permute(array, WRITER_USER_NR_ELEMENTS, - WRITER_USER_NR_ELEMENTS); -} - -/** - * The objective of this test is to implement and expand upon the scenario - * described in the reference counting documentation and ensure that any node of - * the Trace, Stream Class, Event Class, Stream and Event hiearchy keeps all - * other "alive" and reachable. - * - * External tools (e.g. valgrind) should be used to confirm that this - * known-good test does not leak memory. - */ -int main(int argc, char **argv) -{ - /* Initialize tap harness before any tests */ - plan_tests(NR_TESTS); - - test_example_scenario(); - test_put_order(); - - return exit_status(); -} diff --git a/tests/lib/test_ir_visit.c b/tests/lib/test_ir_visit.c index bc2da8e7..fa2046bb 100644 --- a/tests/lib/test_ir_visit.c +++ b/tests/lib/test_ir_visit.c @@ -1,7 +1,7 @@ /* * test_ir_visit.c * - * CTF IR visitor interface test + * Trace IR visitor interface test * * Copyright 2016 - Jérémie Galarneau * @@ -21,11 +21,11 @@ #include "tap/tap.h" #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include #include diff --git a/tests/lib/test_plugin.c b/tests/lib/test_plugin.c index c8578827..2cba9547 100644 --- a/tests/lib/test_plugin.c +++ b/tests/lib/test_plugin.c @@ -1,7 +1,7 @@ /* * test_plugin.c * - * CTF IR Reference Count test + * Trace IR Reference Count test * * Copyright (c) 2017 Philippe Proulx * diff --git a/tests/lib/test_trace_ir_ref.c b/tests/lib/test_trace_ir_ref.c new file mode 100644 index 00000000..bf970246 --- /dev/null +++ b/tests/lib/test_trace_ir_ref.c @@ -0,0 +1,625 @@ +/* + * test_trace_ir_ref.c + * + * Trace IR Reference Count test + * + * Copyright 2016 - Jérémie Galarneau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "tap/tap.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + +#define NR_TESTS 37 + +struct user { + struct bt_trace *tc; + struct bt_stream_class *sc; + struct bt_event_class *ec; + struct bt_stream *stream; + struct bt_event *event; +}; + +struct writer_user { + struct bt_ctf_writer *writer; + struct bt_ctf_trace *tc; + struct bt_ctf_stream_class *sc; + struct bt_ctf_event_class *ec; + struct bt_ctf_stream *stream; + struct bt_ctf_event *event; +}; + +const char *writer_user_names[] = { + "writer", + "trace", + "stream class", + "event class", + "stream", + "event", +}; + +static const size_t WRITER_USER_NR_ELEMENTS = + sizeof(struct writer_user) / sizeof(void *); + +/** + * Returns a structure containing the following fields: + * - uint8_t payload_8; + * - uint16_t payload_16; + * - uint32_t payload_32; + */ +static struct bt_field_type *create_integer_struct(void) +{ + int ret; + struct bt_field_type *structure = NULL; + struct bt_field_type *ui8 = NULL, *ui16 = NULL, *ui32 = NULL; + + structure = bt_field_type_structure_create(); + BT_ASSERT(structure); + ui8 = bt_field_type_unsigned_integer_create(); + BT_ASSERT(ui8); + ret = bt_field_type_integer_set_field_value_range(ui8, 8); + BT_ASSERT(ret == 0); + ret = bt_field_type_structure_append_member(structure, + "payload_8", ui8); + BT_ASSERT(ret == 0); + ui16 = bt_field_type_unsigned_integer_create(); + BT_ASSERT(ui16); + ret = bt_field_type_integer_set_field_value_range(ui16, 16); + BT_ASSERT(ret == 0); + ret = bt_field_type_structure_append_member(structure, + "payload_16", ui16); + BT_ASSERT(ret == 0); + ui32 = bt_field_type_unsigned_integer_create(); + BT_ASSERT(ui32); + ret = bt_field_type_integer_set_field_value_range(ui32, 32); + BT_ASSERT(ret == 0); + ret = bt_field_type_structure_append_member(structure, + "payload_32", ui32); + BT_ASSERT(ret == 0); + BT_PUT(ui8); + BT_PUT(ui16); + BT_PUT(ui32); + return structure; +} + +static struct bt_ctf_field_type *create_writer_integer_struct(void) +{ + int ret; + struct bt_ctf_field_type *structure = NULL; + struct bt_ctf_field_type *ui8 = NULL, *ui16 = NULL, *ui32 = NULL; + + structure = bt_ctf_field_type_structure_create(); + BT_ASSERT(structure); + ui8 = bt_ctf_field_type_integer_create(8); + BT_ASSERT(ui8); + ret = bt_ctf_field_type_structure_add_field(structure, ui8, + "payload_8"); + BT_ASSERT(ret == 0); + ui16 = bt_ctf_field_type_integer_create(16); + BT_ASSERT(ui16); + ret = bt_ctf_field_type_structure_add_field(structure, ui16, + "payload_16"); + BT_ASSERT(ret == 0); + ui32 = bt_ctf_field_type_integer_create(32); + BT_ASSERT(ui32); + ret = bt_ctf_field_type_structure_add_field(structure, ui32, + "payload_32"); + BT_ASSERT(ret == 0); + BT_PUT(ui8); + BT_PUT(ui16); + BT_PUT(ui32); + return structure; +} + +/** + * A simple event has the following payload: + * - uint8_t payload_8; + * - uint16_t payload_16; + * - uint32_t payload_32; + */ +static struct bt_event_class *create_simple_event(struct bt_stream_class *sc, + const char *name) +{ + int ret; + struct bt_event_class *event = NULL; + struct bt_field_type *payload = NULL; + + BT_ASSERT(name); + event = bt_event_class_create(sc); + BT_ASSERT(event); + ret = bt_event_class_set_name(event, name); + BT_ASSERT(ret == 0); + payload = create_integer_struct(); + BT_ASSERT(payload); + ret = bt_event_class_set_payload_field_type(event, payload); + BT_ASSERT(ret == 0); + BT_PUT(payload); + return event; +} + +/** + * A complex event has the following payload: + * - uint8_t payload_8; + * - uint16_t payload_16; + * - uint32_t payload_32; + * - struct payload_struct: + * - uint8_t payload_8; + * - uint16_t payload_16; + * - uint32_t payload_32; + */ +static struct bt_event_class *create_complex_event(struct bt_stream_class *sc, + const char *name) +{ + int ret; + struct bt_event_class *event = NULL; + struct bt_field_type *inner = NULL, *outer = NULL; + + BT_ASSERT(name); + event = bt_event_class_create(sc); + BT_ASSERT(event); + ret = bt_event_class_set_name(event, name); + BT_ASSERT(ret == 0); + outer = create_integer_struct(); + BT_ASSERT(outer); + inner = create_integer_struct(); + BT_ASSERT(inner); + ret = bt_field_type_structure_append_member(outer, + "payload_struct", inner); + BT_ASSERT(ret == 0); + ret = bt_event_class_set_payload_field_type(event, outer); + BT_ASSERT(ret == 0); + BT_PUT(inner); + BT_PUT(outer); + return event; +} + +static void set_stream_class_field_types( + struct bt_stream_class *stream_class) +{ + struct bt_field_type *packet_context_type; + struct bt_field_type *event_header_type; + struct bt_field_type *ft; + int ret; + + packet_context_type = bt_field_type_structure_create(); + BT_ASSERT(packet_context_type); + ft = bt_field_type_unsigned_integer_create(); + BT_ASSERT(ft); + ret = bt_field_type_integer_set_field_value_range(ft, 32); + BT_ASSERT(ret == 0); + ret = bt_field_type_structure_append_member(packet_context_type, + "packet_size", ft); + BT_ASSERT(ret == 0); + bt_put(ft); + ft = bt_field_type_unsigned_integer_create(); + BT_ASSERT(ft); + ret = bt_field_type_integer_set_field_value_range(ft, 32); + BT_ASSERT(ret == 0); + ret = bt_field_type_structure_append_member(packet_context_type, + "content_size", ft); + BT_ASSERT(ret == 0); + bt_put(ft); + event_header_type = bt_field_type_structure_create(); + BT_ASSERT(event_header_type); + ft = bt_field_type_unsigned_integer_create(); + BT_ASSERT(ft); + ret = bt_field_type_integer_set_field_value_range(ft, 32); + BT_ASSERT(ret == 0); + ret = bt_field_type_structure_append_member(event_header_type, + "id", ft); + BT_ASSERT(ret == 0); + bt_put(ft); + ret = bt_stream_class_set_packet_context_field_type(stream_class, + packet_context_type); + BT_ASSERT(ret == 0); + ret = bt_stream_class_set_event_header_field_type(stream_class, + event_header_type); + BT_ASSERT(ret == 0); + bt_put(packet_context_type); + bt_put(event_header_type); +} + +static void create_sc1(struct bt_trace *trace) +{ + int ret; + struct bt_event_class *ec1 = NULL, *ec2 = NULL; + struct bt_stream_class *sc1 = NULL, *ret_stream = NULL; + + sc1 = bt_stream_class_create(trace); + BT_ASSERT(sc1); + ret = bt_stream_class_set_name(sc1, "sc1"); + BT_ASSERT(ret == 0); + set_stream_class_field_types(sc1); + ec1 = create_complex_event(sc1, "ec1"); + BT_ASSERT(ec1); + ec2 = create_simple_event(sc1, "ec2"); + BT_ASSERT(ec2); + ret_stream = bt_event_class_borrow_stream_class(ec1); + ok(ret_stream == sc1, "Borrow parent stream SC1 from EC1"); + ret_stream = bt_event_class_borrow_stream_class(ec2); + ok(ret_stream == sc1, "Borrow parent stream SC1 from EC2"); + BT_PUT(ec1); + BT_PUT(ec2); + BT_PUT(sc1); +} + +static void create_sc2(struct bt_trace *trace) +{ + int ret; + struct bt_event_class *ec3 = NULL; + struct bt_stream_class *sc2 = NULL, *ret_stream = NULL; + + sc2 = bt_stream_class_create(trace); + BT_ASSERT(sc2); + ret = bt_stream_class_set_name(sc2, "sc2"); + BT_ASSERT(ret == 0); + set_stream_class_field_types(sc2); + ec3 = create_simple_event(sc2, "ec3"); + ret_stream = bt_event_class_borrow_stream_class(ec3); + ok(ret_stream == sc2, "Borrow parent stream SC2 from EC3"); + BT_PUT(ec3); + BT_PUT(sc2); +} + +static void set_trace_packet_header(struct bt_trace *trace) +{ + struct bt_field_type *packet_header_type; + struct bt_field_type *ft; + int ret; + + packet_header_type = bt_field_type_structure_create(); + BT_ASSERT(packet_header_type); + ft = bt_field_type_unsigned_integer_create(); + BT_ASSERT(ft); + ret = bt_field_type_integer_set_field_value_range(ft, 32); + BT_ASSERT(ret == 0); + ret = bt_field_type_structure_append_member(packet_header_type, + "stream_id", ft); + BT_ASSERT(ret == 0); + bt_put(ft); + ret = bt_trace_set_packet_header_field_type(trace, + packet_header_type); + BT_ASSERT(ret == 0); + + bt_put(packet_header_type); +} + +static struct bt_trace *create_tc1(void) +{ + struct bt_trace *tc1 = NULL; + + tc1 = bt_trace_create(); + BT_ASSERT(tc1); + set_trace_packet_header(tc1); + create_sc1(tc1); + create_sc2(tc1); + return tc1; +} + +static void init_weak_refs(struct bt_trace *tc, + struct bt_trace **tc1, + struct bt_stream_class **sc1, + struct bt_stream_class **sc2, + struct bt_event_class **ec1, + struct bt_event_class **ec2, + struct bt_event_class **ec3) +{ + *tc1 = tc; + *sc1 = bt_trace_borrow_stream_class_by_index(tc, 0); + *sc2 = bt_trace_borrow_stream_class_by_index(tc, 1); + *ec1 = bt_stream_class_borrow_event_class_by_index(*sc1, 0); + *ec2 = bt_stream_class_borrow_event_class_by_index(*sc1, 1); + *ec3 = bt_stream_class_borrow_event_class_by_index(*sc2, 0); +} + +static void test_example_scenario(void) +{ + /* + * Weak pointers to trace IR objects are to be used very + * carefully. This is NOT a good practice and is strongly + * discouraged; this is only done to facilitate the validation + * of expected reference counts without affecting them by taking + * "real" references to the objects. + */ + struct bt_trace *tc1 = NULL, *weak_tc1 = NULL; + struct bt_stream_class *weak_sc1 = NULL, *weak_sc2 = NULL; + struct bt_event_class *weak_ec1 = NULL, *weak_ec2 = NULL, + *weak_ec3 = NULL; + struct user user_a = { 0 }, user_b = { 0 }, user_c = { 0 }; + + /* The only reference which exists at this point is on TC1. */ + tc1 = create_tc1(); + ok(tc1, "Initialize trace"); + BT_ASSERT(tc1); + init_weak_refs(tc1, &weak_tc1, &weak_sc1, &weak_sc2, &weak_ec1, + &weak_ec2, &weak_ec3); + ok(bt_object_get_ref_count((void *) weak_sc1) == 0, + "Initial SC1 reference count is 0"); + ok(bt_object_get_ref_count((void *) weak_sc2) == 0, + "Initial SC2 reference count is 0"); + ok(bt_object_get_ref_count((void *) weak_ec1) == 0, + "Initial EC1 reference count is 0"); + ok(bt_object_get_ref_count((void *) weak_ec2) == 0, + "Initial EC2 reference count is 0"); + ok(bt_object_get_ref_count((void *) weak_ec3) == 0, + "Initial EC3 reference count is 0"); + + /* User A has ownership of the trace. */ + BT_MOVE(user_a.tc, tc1); + ok(bt_object_get_ref_count((void *) user_a.tc) == 1, + "TC1 reference count is 1"); + + /* User A acquires a reference to SC2 from TC1. */ + user_a.sc = bt_get(bt_trace_borrow_stream_class_by_index(user_a.tc, 1)); + ok(user_a.sc, "User A acquires SC2 from TC1"); + ok(bt_object_get_ref_count((void *) weak_tc1) == 2, + "TC1 reference count is 2"); + ok(bt_object_get_ref_count((void *) weak_sc2) == 1, + "SC2 reference count is 1"); + + /* User A acquires a reference to EC3 from SC2. */ + user_a.ec = bt_get( + bt_stream_class_borrow_event_class_by_index(user_a.sc, 0)); + ok(user_a.ec, "User A acquires EC3 from SC2"); + ok(bt_object_get_ref_count((void *) weak_tc1) == 2, + "TC1 reference count is 2"); + ok(bt_object_get_ref_count((void *) weak_sc2) == 2, + "SC2 reference count is 2"); + ok(bt_object_get_ref_count((void *) weak_ec3) == 1, + "EC3 reference count is 1"); + + /* User A releases its reference to SC2. */ + diag("User A releases SC2"); + BT_PUT(user_a.sc); + /* + * We keep the pointer to SC2 around to validate its reference + * count. + */ + ok(bt_object_get_ref_count((void *) weak_tc1) == 2, + "TC1 reference count is 2"); + ok(bt_object_get_ref_count((void *) weak_sc2) == 1, + "SC2 reference count is 1"); + ok(bt_object_get_ref_count((void *) weak_ec3) == 1, + "EC3 reference count is 1"); + + /* User A releases its reference to TC1. */ + diag("User A releases TC1"); + BT_PUT(user_a.tc); + /* + * We keep the pointer to TC1 around to validate its reference + * count. + */ + ok(bt_object_get_ref_count((void *) weak_tc1) == 1, + "TC1 reference count is 1"); + ok(bt_object_get_ref_count((void *) weak_sc2) == 1, + "SC2 reference count is 1"); + ok(bt_object_get_ref_count((void *) weak_ec3) == 1, + "EC3 reference count is 1"); + + /* User B acquires a reference to SC1. */ + diag("User B acquires a reference to SC1"); + user_b.sc = bt_get(weak_sc1); + ok(bt_object_get_ref_count((void *) weak_tc1) == 2, + "TC1 reference count is 2"); + ok(bt_object_get_ref_count((void *) weak_sc1) == 1, + "SC1 reference count is 1"); + + /* User C acquires a reference to EC1. */ + diag("User C acquires a reference to EC1"); + user_c.ec = bt_get( + bt_stream_class_borrow_event_class_by_index(user_b.sc, 0)); + ok(bt_object_get_ref_count((void *) weak_ec1) == 1, + "EC1 reference count is 1"); + ok(bt_object_get_ref_count((void *) weak_sc1) == 2, + "SC1 reference count is 2"); + + /* User A releases its reference on EC3. */ + diag("User A releases its reference on EC3"); + BT_PUT(user_a.ec); + ok(bt_object_get_ref_count((void *) weak_ec3) == 0, + "EC3 reference count is 1"); + ok(bt_object_get_ref_count((void *) weak_sc2) == 0, + "SC2 reference count is 0"); + ok(bt_object_get_ref_count((void *) weak_tc1) == 1, + "TC1 reference count is 1"); + + /* User B releases its reference on SC1. */ + diag("User B releases its reference on SC1"); + BT_PUT(user_b.sc); + ok(bt_object_get_ref_count((void *) weak_sc1) == 1, + "SC1 reference count is 1"); + + /* + * User C is the sole owner of an object and is keeping the whole + * trace hierarchy "alive" by holding a reference to EC1. + */ + ok(bt_object_get_ref_count((void *) weak_tc1) == 1, + "TC1 reference count is 1"); + ok(bt_object_get_ref_count((void *) weak_sc1) == 1, + "SC1 reference count is 1"); + ok(bt_object_get_ref_count((void *) weak_sc2) == 0, + "SC2 reference count is 0"); + ok(bt_object_get_ref_count((void *) weak_ec1) == 1, + "EC1 reference count is 1"); + ok(bt_object_get_ref_count((void *) weak_ec2) == 0, + "EC2 reference count is 0"); + ok(bt_object_get_ref_count((void *) weak_ec3) == 0, + "EC3 reference count is 0"); + + /* Reclaim last reference held by User C. */ + BT_PUT(user_c.ec); +} + +static void create_writer_user_full(struct writer_user *user) +{ + gchar *trace_path; + struct bt_ctf_field_type *ft; + struct bt_ctf_field *field; + struct bt_ctf_clock *clock; + int ret; + + trace_path = g_build_filename(g_get_tmp_dir(), "ctfwriter_XXXXXX", NULL); + if (!bt_mkdtemp(trace_path)) { + perror("# perror"); + } + + user->writer = bt_ctf_writer_create(trace_path); + BT_ASSERT(user->writer); + ret = bt_ctf_writer_set_byte_order(user->writer, + BT_CTF_BYTE_ORDER_LITTLE_ENDIAN); + BT_ASSERT(ret == 0); + user->tc = bt_ctf_writer_get_trace(user->writer); + BT_ASSERT(user->tc); + user->sc = bt_ctf_stream_class_create("sc"); + BT_ASSERT(user->sc); + clock = bt_ctf_clock_create("the_clock"); + BT_ASSERT(clock); + ret = bt_ctf_writer_add_clock(user->writer, clock); + BT_ASSERT(!ret); + ret = bt_ctf_stream_class_set_clock(user->sc, clock); + BT_ASSERT(!ret); + BT_PUT(clock); + user->stream = bt_ctf_writer_create_stream(user->writer, user->sc); + BT_ASSERT(user->stream); + user->ec = bt_ctf_event_class_create("ec"); + BT_ASSERT(user->ec); + ft = create_writer_integer_struct(); + BT_ASSERT(ft); + ret = bt_ctf_event_class_set_payload_field_type(user->ec, ft); + BT_PUT(ft); + BT_ASSERT(!ret); + ret = bt_ctf_stream_class_add_event_class(user->sc, user->ec); + BT_ASSERT(!ret); + user->event = bt_ctf_event_create(user->ec); + BT_ASSERT(user->event); + field = bt_ctf_event_get_payload(user->event, "payload_8"); + BT_ASSERT(field); + ret = bt_ctf_field_integer_unsigned_set_value(field, 10); + BT_ASSERT(!ret); + BT_PUT(field); + field = bt_ctf_event_get_payload(user->event, "payload_16"); + BT_ASSERT(field); + ret = bt_ctf_field_integer_unsigned_set_value(field, 20); + BT_ASSERT(!ret); + BT_PUT(field); + field = bt_ctf_event_get_payload(user->event, "payload_32"); + BT_ASSERT(field); + ret = bt_ctf_field_integer_unsigned_set_value(field, 30); + BT_ASSERT(!ret); + BT_PUT(field); + ret = bt_ctf_stream_append_event(user->stream, user->event); + BT_ASSERT(!ret); + recursive_rmdir(trace_path); + g_free(trace_path); +} + +static void test_put_order_swap(size_t *array, size_t a, size_t b) +{ + size_t temp = array[a]; + + array[a] = array[b]; + array[b] = temp; +} + +static void test_put_order_put_objects(size_t *array, size_t size) +{ + size_t i; + struct writer_user user = { 0 }; + void **objects = (void *) &user; + + create_writer_user_full(&user); + printf("# "); + + for (i = 0; i < size; ++i) { + void *obj = objects[array[i]]; + + printf("%s", writer_user_names[array[i]]); + BT_PUT(obj); + + if (i < size - 1) { + printf(" -> "); + } + } + + puts(""); +} + +static void test_put_order_permute(size_t *array, int k, size_t size) +{ + if (k == 0) { + test_put_order_put_objects(array, size); + } else { + int i; + + for (i = k - 1; i >= 0; i--) { + size_t next_k = k - 1; + + test_put_order_swap(array, i, next_k); + test_put_order_permute(array, next_k, size); + test_put_order_swap(array, i, next_k); + } + } +} + +static void test_put_order(void) +{ + size_t i; + size_t array[WRITER_USER_NR_ELEMENTS]; + + /* Initialize array of indexes */ + for (i = 0; i < WRITER_USER_NR_ELEMENTS; ++i) { + array[i] = i; + } + + test_put_order_permute(array, WRITER_USER_NR_ELEMENTS, + WRITER_USER_NR_ELEMENTS); +} + +/** + * The objective of this test is to implement and expand upon the scenario + * described in the reference counting documentation and ensure that any node of + * the Trace, Stream Class, Event Class, Stream and Event hiearchy keeps all + * other "alive" and reachable. + * + * External tools (e.g. valgrind) should be used to confirm that this + * known-good test does not leak memory. + */ +int main(int argc, char **argv) +{ + /* Initialize tap harness before any tests */ + plan_tests(NR_TESTS); + + test_example_scenario(); + test_put_order(); + + return exit_status(); +} diff --git a/tests/lib/trace-ir/Makefile.am b/tests/lib/trace-ir/Makefile.am new file mode 100644 index 00000000..3c946c13 --- /dev/null +++ b/tests/lib/trace-ir/Makefile.am @@ -0,0 +1,5 @@ +if ENABLE_PYTHON_BINDINGS +check_SCRIPTS = test_trace_ir +endif + +EXTRA_DIST = test_trace.py test_stream_class.py diff --git a/tests/lib/trace-ir/test_stream_class.py b/tests/lib/trace-ir/test_stream_class.py new file mode 100644 index 00000000..0841848b --- /dev/null +++ b/tests/lib/trace-ir/test_stream_class.py @@ -0,0 +1,197 @@ +import unittest +import bt2 + + +class StreamClassSingleClockClassTestCase(unittest.TestCase): + def setUp(self): + self._sc = bt2.StreamClass() + + def tearDown(self): + del self._sc + + def _test_add_sc_ft_vs_event_class(self, set_ft_func): + cc = bt2.ClockClass('first_cc', 1000) + scft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + scft.append_field('salut', ft) + set_ft_func(scft) + cc = bt2.ClockClass('second_cc', 1000) + payloadft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + payloadft.append_field('zorg', ft) + ec = bt2.EventClass('ec', payload_field_type=payloadft) + self._sc.add_event_class(ec) + trace = bt2.Trace() + + with self.assertRaises(bt2.Error): + trace.add_stream_class(self._sc) + + def test_add_sc_packet_context_vs_event_class(self): + def func(ft): + self._sc.packet_context_field_type = ft + + self._test_add_sc_ft_vs_event_class(func) + + def test_add_sc_event_context_vs_event_class(self): + def func(ft): + self._sc.event_context_field_type = ft + + self._test_add_sc_ft_vs_event_class(func) + + def test_add_sc_event_header_vs_event_class(self): + def func(ft): + self._sc.event_header_field_type = ft + + self._test_add_sc_ft_vs_event_class(func) + + def test_add_sc_event_class_vs_event_class(self): + ehft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32) + ehft.append_field('id', ft) + self._sc.event_header_field_type = ehft + cc = bt2.ClockClass('first_cc', 1000) + payloadft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + payloadft.append_field('zorg', ft) + ec1 = bt2.EventClass('ec', payload_field_type=payloadft) + cc = bt2.ClockClass('second_cc', 1000) + payloadft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + payloadft.append_field('logi', ft) + ec2 = bt2.EventClass('ec', payload_field_type=payloadft) + self._sc.add_event_class(ec1) + self._sc.add_event_class(ec2) + trace = bt2.Trace() + + with self.assertRaises(bt2.Error): + trace.add_stream_class(self._sc) + + def _test_create_event_ft_vs_event_class(self, set_ft_func): + cc = bt2.ClockClass('first_cc', 1000) + scft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + scft.append_field('salut', ft) + set_ft_func(scft) + cc = bt2.ClockClass('second_cc', 1000) + payloadft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + payloadft.append_field('zorg', ft) + ec = bt2.EventClass('ec', payload_field_type=payloadft) + self._sc.add_event_class(ec) + + with self.assertRaises(bt2.Error): + ev = ec() + + def test_create_event_packet_context_vs_event_class(self): + def func(ft): + self._sc.packet_context_field_type = ft + + self._test_create_event_ft_vs_event_class(func) + + def test_create_event_event_context_vs_event_class(self): + def func(ft): + self._sc.event_context_field_type = ft + + self._test_create_event_ft_vs_event_class(func) + + def test_create_event_event_header_vs_event_class(self): + def func(ft): + self._sc.event_header_field_type = ft + + self._test_create_event_ft_vs_event_class(func) + + def test_create_event_event_class_vs_event_class(self): + ehft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32) + ehft.append_field('id', ft) + self._sc.event_header_field_type = ehft + cc = bt2.ClockClass('first_cc', 1000) + payloadft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + payloadft.append_field('zorg', ft) + ec1 = bt2.EventClass('ec', payload_field_type=payloadft) + cc = bt2.ClockClass('second_cc', 1000) + payloadft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + payloadft.append_field('logi', ft) + ec2 = bt2.EventClass('ec', payload_field_type=payloadft) + self._sc.add_event_class(ec1) + self._sc.add_event_class(ec2) + + with self.assertRaises(bt2.Error): + ev = ec1() + + def test_add_ec_after_add_sc(self): + cc = bt2.ClockClass('first_cc', 1000) + scft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + scft.append_field('salut', ft) + self._sc.packet_context_field_type = scft + trace = bt2.Trace() + trace.add_stream_class(self._sc) + cc = bt2.ClockClass('second_cc', 1000) + payloadft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + payloadft.append_field('zorg', ft) + ec = bt2.EventClass('ec', payload_field_type=payloadft) + + with self.assertRaises(bt2.Error): + self._sc.add_event_class(ec) + + def test_add_ec_after_add_sc_single_cc(self): + ehft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32) + ehft.append_field('id', ft) + self._sc.event_header_field_type = ehft + trace = bt2.Trace() + trace.add_stream_class(self._sc) + cc = bt2.ClockClass('first_cc', 1000) + payloadft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + payloadft.append_field('zorg', ft) + ec = bt2.EventClass('ec', payload_field_type=payloadft) + self._sc.add_event_class(ec) + cc = bt2.ClockClass('second_cc', 1000) + payloadft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + payloadft.append_field('lel', ft) + ec = bt2.EventClass('ec', payload_field_type=payloadft) + + with self.assertRaises(bt2.Error): + self._sc.add_event_class(ec) + + def test_add_ec_after_create_event(self): + ehft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32) + ehft.append_field('id', ft) + self._sc.event_header_field_type = ehft + cc = bt2.ClockClass('first_cc', 1000) + payloadft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + payloadft.append_field('zorg', ft) + ec1 = bt2.EventClass('ec', payload_field_type=payloadft) + self._sc.add_event_class(ec1) + ev = ec1() + cc = bt2.ClockClass('second_cc', 1000) + payloadft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + payloadft.append_field('logi', ft) + ec2 = bt2.EventClass('ec', payload_field_type=payloadft) + + with self.assertRaises(bt2.Error): + self._sc.add_event_class(ec2) + + def test_sc_clock_matches_expected_clock_class(self): + clock = bt2.CtfWriterClock('sc_clock') + self._sc.clock = clock + writer = bt2.CtfWriter('/tmp') + writer.add_clock(clock) + writer.trace.add_stream_class(self._sc) + cc = bt2.ClockClass('other_cc', 1000) + payloadft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + payloadft.append_field('zorg', ft) + ec = bt2.EventClass('ec', payload_field_type=payloadft) + + with self.assertRaises(bt2.Error): + self._sc.add_event_class(ec) diff --git a/tests/lib/trace-ir/test_trace.py b/tests/lib/trace-ir/test_trace.py new file mode 100644 index 00000000..116f7ba2 --- /dev/null +++ b/tests/lib/trace-ir/test_trace.py @@ -0,0 +1,91 @@ +import unittest +import bt2 + + +class TraceTestCase(unittest.TestCase): + def setUp(self): + self._trace = bt2.Trace() + + def tearDown(self): + del self._trace + + def _add_stream_class(self): + sc = bt2.StreamClass() + self._trace.add_stream_class(sc) + + def test_packet_header_ft_no_clock_class_simple(self): + cc = bt2.ClockClass('hello', 1000) + phft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + phft.append_field('salut', ft) + self._trace.add_clock_class(cc) + self._trace.packet_header_field_type = phft + + with self.assertRaises(bt2.Error): + self._add_stream_class() + + def test_packet_header_ft_no_clock_class_struct(self): + cc = bt2.ClockClass('hello', 1000) + phft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + struct_ft = bt2.StructureFieldType() + struct_ft.append_field('salut', ft) + phft.append_field('boucane', struct_ft) + self._trace.add_clock_class(cc) + self._trace.packet_header_field_type = phft + + with self.assertRaises(bt2.Error): + self._add_stream_class() + + def test_packet_header_ft_no_clock_class_variant(self): + cc = bt2.ClockClass('hello', 1000) + phft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + tag_ft = bt2.EnumerationFieldType(size=32) + tag_ft.add_mapping('heille', 12) + variant_ft = bt2.VariantFieldType('tag', tag_ft) + variant_ft.append_field('heille', ft) + phft.append_field('tag', tag_ft) + phft.append_field('boucane', variant_ft) + self._trace.add_clock_class(cc) + self._trace.packet_header_field_type = phft + + with self.assertRaises(bt2.Error): + self._add_stream_class() + + def test_packet_header_ft_no_clock_class_array(self): + cc = bt2.ClockClass('hello', 1000) + phft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + array_ft = bt2.ArrayFieldType(ft, 23) + phft.append_field('boucane', array_ft) + self._trace.add_clock_class(cc) + self._trace.packet_header_field_type = phft + + with self.assertRaises(bt2.Error): + self._add_stream_class() + + def test_packet_header_ft_no_clock_class_sequence(self): + cc = bt2.ClockClass('hello', 1000) + phft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + len_ft = bt2.IntegerFieldType(32) + seq_ft = bt2.SequenceFieldType(ft, 'len') + phft.append_field('len', len_ft) + phft.append_field('boucane', seq_ft) + self._trace.add_clock_class(cc) + self._trace.packet_header_field_type = phft + + with self.assertRaises(bt2.Error): + self._add_stream_class() + + def test_packet_header_ft_no_clock_class_set_static(self): + cc = bt2.ClockClass('hello', 1000) + phft = bt2.StructureFieldType() + ft = bt2.IntegerFieldType(32, mapped_clock_class=cc) + phft.append_field('salut', ft) + self._trace.add_clock_class(cc) + self._trace.packet_header_field_type = phft + + with self.assertRaises(bt2.Error): + self._trace.set_is_static() diff --git a/tests/lib/trace-ir/test_trace_ir.in b/tests/lib/trace-ir/test_trace_ir.in new file mode 100644 index 00000000..e78b3445 --- /dev/null +++ b/tests/lib/trace-ir/test_trace_ir.in @@ -0,0 +1,36 @@ +#!/bin/bash +# +# Copyright (C) 2017 - Philippe Proulx +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; only version 2 +# of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +NO_SH_TAP=1 +. "@abs_top_builddir@/tests/utils/common.sh" + +PYTHON_BUILD_DIR="${BT_BUILD_PATH}/bindings/python/bt2/build/build_lib" +TESTS_UTILS_PYTHON_DIR="${BT_SRC_PATH}/tests/utils/python" +TESTRUNNER_PY="${BT_SRC_PATH}/tests/utils/python/testrunner.py" +THIS_DIR="${BT_SRC_PATH}/tests/lib/trace-ir" + +if [ "x${MSYSTEM}" != "x" ]; then + export PATH="${BT_BUILD_PATH}/lib/.libs:${PATH}" +else + export LD_LIBRARY_PATH="${BT_BUILD_PATH}/lib/.libs:${LD_LIBRARY_PATH}" +fi + +PYTHONPATH="${PYTHON_BUILD_DIR}:${TESTS_UTILS_PYTHON_DIR}" \ + "@PYTHON@" "${TESTRUNNER_PY}" "${THIS_DIR}" +exit $?