ffd09259e4ebb0240b928cd08d390e12df6e78cb
[babeltrace.git] / src / plugins / ctf / common / metadata / ctf-meta-update-in-ir.c
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright 2018 Philippe Proulx <pproulx@efficios.com>
5 */
6
7 #include <babeltrace2/babeltrace.h>
8 #include "common/macros.h"
9 #include "common/assert.h"
10 #include "compat/glib.h"
11 #include <glib.h>
12 #include <stdbool.h>
13 #include <stdint.h>
14 #include <string.h>
15 #include <inttypes.h>
16 #include "common/assert.h"
17
18 #include "ctf-meta-visitors.h"
19
20 static
21 void force_update_field_class_in_ir(struct ctf_field_class *fc, bool in_ir)
22 {
23 uint64_t i;
24
25 if (!fc) {
26 goto end;
27 }
28
29 fc->in_ir = in_ir;
30
31 switch (fc->type) {
32 case CTF_FIELD_CLASS_TYPE_STRUCT:
33 {
34 struct ctf_field_class_struct *struct_fc = (void *) fc;
35
36 for (i = 0; i < struct_fc->members->len; i++) {
37 struct ctf_named_field_class *named_fc =
38 ctf_field_class_struct_borrow_member_by_index(
39 struct_fc, i);
40
41 force_update_field_class_in_ir(named_fc->fc, in_ir);
42 }
43
44 break;
45 }
46 case CTF_FIELD_CLASS_TYPE_VARIANT:
47 {
48 struct ctf_named_field_class *named_fc;
49 struct ctf_field_class_variant *var_fc = (void *) fc;
50
51 for (i = 0; i < var_fc->options->len; i++) {
52 named_fc =
53 ctf_field_class_variant_borrow_option_by_index(
54 var_fc, i);
55
56 force_update_field_class_in_ir(named_fc->fc, in_ir);
57 }
58
59 break;
60 }
61 case CTF_FIELD_CLASS_TYPE_ARRAY:
62 case CTF_FIELD_CLASS_TYPE_SEQUENCE:
63 {
64 struct ctf_field_class_array_base *array_fc = (void *) fc;
65
66 force_update_field_class_in_ir(array_fc->elem_fc, in_ir);
67 break;
68 }
69 default:
70 break;
71 }
72
73 end:
74 return;
75 }
76
77 static
78 void update_field_class_in_ir(struct ctf_field_class *fc,
79 GHashTable *ft_dependents)
80 {
81 int64_t i;
82
83 if (!fc) {
84 goto end;
85 }
86
87 switch (fc->type) {
88 case CTF_FIELD_CLASS_TYPE_INT:
89 case CTF_FIELD_CLASS_TYPE_ENUM:
90 {
91 struct ctf_field_class_int *int_fc = (void *) fc;
92
93 /*
94 * Conditions to be in trace IR; one of:
95 *
96 * 1. Does NOT have a mapped clock class AND does not
97 * have a special meaning.
98 * 2. Another field class depends on it.
99 */
100 if ((!int_fc->mapped_clock_class &&
101 int_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE) ||
102 bt_g_hash_table_contains(ft_dependents, fc)) {
103 fc->in_ir = true;
104 }
105
106 break;
107 }
108 case CTF_FIELD_CLASS_TYPE_STRUCT:
109 {
110 struct ctf_field_class_struct *struct_fc = (void *) fc;
111
112 /*
113 * Make it part of IR if it's empty because it was
114 * originally empty.
115 */
116 if (struct_fc->members->len == 0) {
117 fc->in_ir = true;
118 }
119
120 /* Reverse order */
121 for (i = (int64_t) struct_fc->members->len - 1; i >= 0; i--) {
122 struct ctf_named_field_class *named_fc =
123 ctf_field_class_struct_borrow_member_by_index(
124 struct_fc, i);
125
126 update_field_class_in_ir(named_fc->fc, ft_dependents);
127
128 if (named_fc->fc->in_ir) {
129 /* At least one member is part of IR */
130 fc->in_ir = true;
131 }
132 }
133
134 break;
135 }
136 case CTF_FIELD_CLASS_TYPE_VARIANT:
137 {
138 struct ctf_named_field_class *named_fc;
139 struct ctf_field_class_variant *var_fc = (void *) fc;
140
141 /*
142 * Reverse order, although it is not important for this
143 * loop because a field class within a variant field
144 * type's option cannot depend on a field class in
145 * another option of the same variant field class.
146 */
147 for (i = (int64_t) var_fc->options->len - 1; i >= 0; i--) {
148 named_fc =
149 ctf_field_class_variant_borrow_option_by_index(
150 var_fc, i);
151
152 update_field_class_in_ir(named_fc->fc, ft_dependents);
153
154 if (named_fc->fc->in_ir) {
155 /* At least one option is part of IR */
156 fc->in_ir = true;
157 }
158 }
159
160 if (fc->in_ir) {
161 /*
162 * At least one option will make it to IR. In
163 * this case, make all options part of IR
164 * because the variant's tag could still select
165 * (dynamically) a removed option. This can mean
166 * having an empty structure as an option, for
167 * example, but at least all the options are
168 * selectable.
169 */
170 for (i = 0; i < var_fc->options->len; i++) {
171 ctf_field_class_variant_borrow_option_by_index(
172 var_fc, i)->fc->in_ir = true;
173 }
174
175 /*
176 * This variant field class is part of IR and
177 * depends on a tag field class (which must also
178 * be part of IR).
179 */
180 g_hash_table_insert(ft_dependents, var_fc->tag_fc,
181 var_fc->tag_fc);
182 }
183
184 break;
185 }
186 case CTF_FIELD_CLASS_TYPE_ARRAY:
187 case CTF_FIELD_CLASS_TYPE_SEQUENCE:
188 {
189 struct ctf_field_class_array_base *array_fc = (void *) fc;
190
191 update_field_class_in_ir(array_fc->elem_fc, ft_dependents);
192 fc->in_ir = array_fc->elem_fc->in_ir;
193
194 if (fc->type == CTF_FIELD_CLASS_TYPE_ARRAY) {
195 struct ctf_field_class_array *arr_fc = (void *) fc;
196
197 assert(arr_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE ||
198 arr_fc->meaning == CTF_FIELD_CLASS_MEANING_UUID);
199
200 /*
201 * UUID field class: nothing depends on this, so
202 * it's not part of IR.
203 */
204 if (arr_fc->meaning == CTF_FIELD_CLASS_MEANING_UUID) {
205 fc->in_ir = false;
206 array_fc->elem_fc->in_ir = false;
207 }
208 } else if (fc->type == CTF_FIELD_CLASS_TYPE_SEQUENCE) {
209 if (fc->in_ir) {
210 struct ctf_field_class_sequence *seq_fc = (void *) fc;
211
212 /*
213 * This sequence field class is part of
214 * IR and depends on a length field class
215 * (which must also be part of IR).
216 */
217 g_hash_table_insert(ft_dependents,
218 seq_fc->length_fc, seq_fc->length_fc);
219 }
220 }
221
222 break;
223 }
224 default:
225 fc->in_ir = true;
226 break;
227 }
228
229 end:
230 return;
231 }
232
233 /*
234 * Scopes and field classes are processed in reverse order because we need
235 * to know if a given integer field class has dependents (sequence or
236 * variant field classes) when we reach it. Dependents can only be located
237 * after the length/tag field class in the metadata tree.
238 */
239 BT_HIDDEN
240 int ctf_trace_class_update_in_ir(struct ctf_trace_class *ctf_tc)
241 {
242 int ret = 0;
243 uint64_t i;
244
245 GHashTable *ft_dependents = g_hash_table_new(g_direct_hash,
246 g_direct_equal);
247
248 BT_ASSERT(ft_dependents);
249
250 for (i = 0; i < ctf_tc->stream_classes->len; i++) {
251 struct ctf_stream_class *sc = ctf_tc->stream_classes->pdata[i];
252 uint64_t j;
253
254 for (j = 0; j < sc->event_classes->len; j++) {
255 struct ctf_event_class *ec = sc->event_classes->pdata[j];
256
257 if (ec->is_translated) {
258 continue;
259 }
260
261 update_field_class_in_ir(ec->payload_fc, ft_dependents);
262 update_field_class_in_ir(ec->spec_context_fc,
263 ft_dependents);
264 }
265
266 if (!sc->is_translated) {
267 update_field_class_in_ir(sc->event_common_context_fc,
268 ft_dependents);
269 force_update_field_class_in_ir(sc->event_header_fc,
270 false);
271 update_field_class_in_ir(sc->packet_context_fc,
272 ft_dependents);
273 }
274 }
275
276 if (!ctf_tc->is_translated) {
277 force_update_field_class_in_ir(ctf_tc->packet_header_fc,
278 false);
279 }
280
281 g_hash_table_destroy(ft_dependents);
282 return ret;
283 }
This page took 0.034988 seconds and 4 git commands to generate.