ca93a8d9a0ed78798d75cfd6a37dc0082ac56618
[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_class_in_ir(struct ctf_field_class *fc,
31 GHashTable *ft_dependents)
32 {
33 int64_t i;
34
35 if (!fc) {
36 goto end;
37 }
38
39 switch (fc->id) {
40 case CTF_FIELD_CLASS_ID_INT:
41 case CTF_FIELD_CLASS_ID_ENUM:
42 {
43 struct ctf_field_class_int *int_fc = (void *) fc;
44
45 if (int_fc->mapped_clock_class ||
46 int_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE ||
47 bt_g_hash_table_contains(ft_dependents, fc)) {
48 /*
49 * Field class does not update a clock, has no
50 * special meaning, and no sequence/variant
51 * field class which is part of IR depends on it.
52 */
53 fc->in_ir = true;
54 }
55
56 break;
57 }
58 case CTF_FIELD_CLASS_ID_STRUCT:
59 {
60 struct ctf_field_class_struct *struct_fc = (void *) fc;
61
62 /* Reverse order */
63 for (i = (int64_t) struct_fc->members->len - 1; i >= 0; i--) {
64 struct ctf_named_field_class *named_fc =
65 ctf_field_class_struct_borrow_member_by_index(
66 struct_fc, i);
67
68 update_field_class_in_ir(named_fc->fc, ft_dependents);
69
70 if (named_fc->fc->in_ir) {
71 /* At least one member is part of IR */
72 fc->in_ir = true;
73 }
74 }
75
76 break;
77 }
78 case CTF_FIELD_CLASS_ID_VARIANT:
79 {
80 struct ctf_named_field_class *named_fc;
81 struct ctf_field_class_variant *var_fc = (void *) fc;
82
83 /*
84 * Reverse order, although it is not important for this
85 * loop because a field class within a variant field
86 * type's option cannot depend on a field class in
87 * another option of the same variant field class.
88 */
89 for (i = (int64_t) var_fc->options->len - 1; i >= 0; i--) {
90 named_fc =
91 ctf_field_class_variant_borrow_option_by_index(
92 var_fc, i);
93
94 update_field_class_in_ir(named_fc->fc, ft_dependents);
95
96 if (named_fc->fc->in_ir) {
97 /* At least one option is part of IR */
98 fc->in_ir = true;
99 }
100 }
101
102 if (fc->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_fc->options->len; i++) {
113 ctf_field_class_variant_borrow_option_by_index(
114 var_fc, i)->fc->in_ir = true;
115 }
116
117 /*
118 * This variant field class is part of IR and
119 * depends on a tag field class (which must also
120 * be part of IR).
121 */
122 g_hash_table_insert(ft_dependents, var_fc->tag_fc,
123 var_fc->tag_fc);
124 }
125
126 break;
127 }
128 case CTF_FIELD_CLASS_ID_ARRAY:
129 case CTF_FIELD_CLASS_ID_SEQUENCE:
130 {
131 struct ctf_field_class_array_base *array_fc = (void *) fc;
132
133 update_field_class_in_ir(array_fc->elem_fc, ft_dependents);
134 fc->in_ir = array_fc->elem_fc->in_ir;
135
136 if (fc->id == CTF_FIELD_CLASS_ID_ARRAY) {
137 struct ctf_field_class_array *arr_fc = (void *) fc;
138
139 assert(arr_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE ||
140 arr_fc->meaning == CTF_FIELD_CLASS_MEANING_UUID);
141
142 /*
143 * UUID field class: nothing depends on this, so
144 * it's not part of IR.
145 */
146 if (arr_fc->meaning == CTF_FIELD_CLASS_MEANING_UUID) {
147 fc->in_ir = false;
148 array_fc->elem_fc->in_ir = false;
149 }
150 } else if (fc->id == CTF_FIELD_CLASS_ID_SEQUENCE) {
151 if (fc->in_ir) {
152 struct ctf_field_class_sequence *seq_fc = (void *) fc;
153
154 /*
155 * This sequence field class is part of
156 * IR and depends on a length field class
157 * (which must also be part of IR).
158 */
159 g_hash_table_insert(ft_dependents,
160 seq_fc->length_fc, seq_fc->length_fc);
161 }
162 }
163
164 break;
165 }
166 default:
167 fc->in_ir = true;
168 break;
169 }
170
171 end:
172 return;
173 }
174
175 /*
176 * Scopes and field classes are processed in reverse order because we need
177 * to know if a given integer field class has dependents (sequence or
178 * variant field classes) when we reach it. Dependents can only be located
179 * after the length/tag field class 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_class_in_ir(ec->payload_fc, ft_dependents);
204 update_field_class_in_ir(ec->spec_context_fc,
205 ft_dependents);
206 }
207
208 if (!sc->is_translated) {
209 update_field_class_in_ir(sc->event_common_context_fc,
210 ft_dependents);
211 update_field_class_in_ir(sc->event_header_fc,
212 ft_dependents);
213 update_field_class_in_ir(sc->packet_context_fc,
214 ft_dependents);
215 }
216 }
217
218 if (!ctf_tc->is_translated) {
219 update_field_class_in_ir(ctf_tc->packet_header_fc,
220 ft_dependents);
221 }
222
223 g_hash_table_destroy(ft_dependents);
224 return ret;
225 }
This page took 0.034062 seconds and 3 git commands to generate.