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