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