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