Make API CTF-agnostic
[babeltrace.git] / plugins / ctf / common / metadata / ctf-meta-update-in-ir.c
1 /*
2 * Copyright 2018 - Philippe Proulx <pproulx@efficios.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 */
14
15 #define BT_LOG_TAG "PLUGIN-CTF-METADATA-META-UPDATE-IN-IR"
16 #include "logging.h"
17
18 #include <babeltrace/babeltrace.h>
19 #include <babeltrace/babeltrace-internal.h>
20 #include <babeltrace/assert-internal.h>
21 #include <babeltrace/compat/glib-internal.h>
22 #include <glib.h>
23 #include <stdint.h>
24 #include <string.h>
25 #include <inttypes.h>
26
27 #include "ctf-meta-visitors.h"
28
29 static
30 void update_field_type_in_ir(struct ctf_field_type *ft,
31 GHashTable *ft_dependents)
32 {
33 int64_t i;
34
35 if (!ft) {
36 goto end;
37 }
38
39 switch (ft->id) {
40 case CTF_FIELD_TYPE_ID_INT:
41 case CTF_FIELD_TYPE_ID_ENUM:
42 {
43 struct ctf_field_type_int *int_ft = (void *) ft;
44
45 if (int_ft->mapped_clock_class ||
46 int_ft->meaning == CTF_FIELD_TYPE_MEANING_NONE ||
47 bt_g_hash_table_contains(ft_dependents, ft)) {
48 /*
49 * Field type does not update a clock, has no
50 * special meaning, and no sequence/variant
51 * field type which is part of IR depends on it.
52 */
53 ft->in_ir = true;
54 }
55
56 break;
57 }
58 case CTF_FIELD_TYPE_ID_STRUCT:
59 {
60 struct ctf_field_type_struct *struct_ft = (void *) ft;
61
62 /* Reverse order */
63 for (i = (int64_t) struct_ft->members->len - 1; i >= 0; i--) {
64 struct ctf_named_field_type *named_ft =
65 ctf_field_type_struct_borrow_member_by_index(
66 struct_ft, i);
67
68 update_field_type_in_ir(named_ft->ft, ft_dependents);
69
70 if (named_ft->ft->in_ir) {
71 /* At least one member is part of IR */
72 ft->in_ir = true;
73 }
74 }
75
76 break;
77 }
78 case CTF_FIELD_TYPE_ID_VARIANT:
79 {
80 struct ctf_named_field_type *named_ft;
81 struct ctf_field_type_variant *var_ft = (void *) ft;
82
83 /*
84 * Reverse order, although it is not important for this
85 * loop because a field type within a variant field
86 * type's option cannot depend on a field type in
87 * another option of the same variant field type.
88 */
89 for (i = (int64_t) var_ft->options->len - 1; i >= 0; i--) {
90 named_ft =
91 ctf_field_type_variant_borrow_option_by_index(
92 var_ft, i);
93
94 update_field_type_in_ir(named_ft->ft, ft_dependents);
95
96 if (named_ft->ft->in_ir) {
97 /* At least one option is part of IR */
98 ft->in_ir = true;
99 }
100 }
101
102 if (ft->in_ir) {
103 /*
104 * At least one option will make it to IR. In
105 * this case, make all options part of IR
106 * because the variant's tag could still select
107 * (dynamically) a removed option. This can mean
108 * having an empty structure as an option, for
109 * example, but at least all the options are
110 * selectable.
111 */
112 for (i = 0; i < var_ft->options->len; i++) {
113 ctf_field_type_variant_borrow_option_by_index(
114 var_ft, i)->ft->in_ir = true;
115 }
116
117 /*
118 * This variant field type is part of IR and
119 * depends on a tag field type (which must also
120 * be part of IR).
121 */
122 g_hash_table_insert(ft_dependents, var_ft->tag_ft,
123 var_ft->tag_ft);
124 }
125
126 break;
127 }
128 case CTF_FIELD_TYPE_ID_ARRAY:
129 case CTF_FIELD_TYPE_ID_SEQUENCE:
130 {
131 struct ctf_field_type_array_base *array_ft = (void *) ft;
132
133 update_field_type_in_ir(array_ft->elem_ft, ft_dependents);
134 ft->in_ir = array_ft->elem_ft->in_ir;
135
136 if (ft->id == CTF_FIELD_TYPE_ID_ARRAY) {
137 struct ctf_field_type_array *arr_ft = (void *) ft;
138
139 assert(arr_ft->meaning == CTF_FIELD_TYPE_MEANING_NONE ||
140 arr_ft->meaning == CTF_FIELD_TYPE_MEANING_UUID);
141
142 /*
143 * UUID field type: nothing depends on this, so
144 * it's not part of IR.
145 */
146 if (arr_ft->meaning == CTF_FIELD_TYPE_MEANING_UUID) {
147 ft->in_ir = false;
148 array_ft->elem_ft->in_ir = false;
149 }
150 } else if (ft->id == CTF_FIELD_TYPE_ID_SEQUENCE) {
151 if (ft->in_ir) {
152 struct ctf_field_type_sequence *seq_ft = (void *) ft;
153
154 /*
155 * This sequence field type is part of
156 * IR and depends on a length field type
157 * (which must also be part of IR).
158 */
159 g_hash_table_insert(ft_dependents,
160 seq_ft->length_ft, seq_ft->length_ft);
161 }
162 }
163
164 break;
165 }
166 default:
167 ft->in_ir = true;
168 break;
169 }
170
171 end:
172 return;
173 }
174
175 /*
176 * Scopes and field types are processed in reverse order because we need
177 * to know if a given integer field type has dependents (sequence or
178 * variant field types) when we reach it. Dependents can only be located
179 * after the length/tag field type in the metadata tree.
180 */
181 BT_HIDDEN
182 int ctf_trace_class_update_in_ir(struct ctf_trace_class *ctf_tc)
183 {
184 int ret = 0;
185 uint64_t i;
186
187 GHashTable *ft_dependents = g_hash_table_new(g_direct_hash,
188 g_direct_equal);
189
190 BT_ASSERT(ft_dependents);
191
192 for (i = 0; i < ctf_tc->stream_classes->len; i++) {
193 struct ctf_stream_class *sc = ctf_tc->stream_classes->pdata[i];
194 uint64_t j;
195
196 for (j = 0; j < sc->event_classes->len; j++) {
197 struct ctf_event_class *ec = sc->event_classes->pdata[j];
198
199 if (ec->is_translated) {
200 continue;
201 }
202
203 update_field_type_in_ir(ec->payload_ft, ft_dependents);
204 update_field_type_in_ir(ec->spec_context_ft,
205 ft_dependents);
206 }
207
208 if (!sc->is_translated) {
209 update_field_type_in_ir(sc->event_common_context_ft,
210 ft_dependents);
211 update_field_type_in_ir(sc->event_header_ft,
212 ft_dependents);
213 update_field_type_in_ir(sc->packet_context_ft,
214 ft_dependents);
215 }
216 }
217
218 if (!ctf_tc->is_translated) {
219 update_field_type_in_ir(ctf_tc->packet_header_ft,
220 ft_dependents);
221 }
222
223 g_hash_table_destroy(ft_dependents);
224 return ret;
225 }
This page took 0.034463 seconds and 4 git commands to generate.