Commit | Line | Data |
---|---|---|
11b0cdc8 | 1 | /* |
3f043b05 | 2 | * stream-class.c |
11b0cdc8 | 3 | * |
d2dc44b6 | 4 | * Babeltrace CTF IR - Stream Class |
11b0cdc8 | 5 | * |
de9dd397 | 6 | * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com> |
11b0cdc8 JG |
7 | * |
8 | * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
9 | * | |
10 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
11 | * of this software and associated documentation files (the "Software"), to deal | |
12 | * in the Software without restriction, including without limitation the rights | |
13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
14 | * copies of the Software, and to permit persons to whom the Software is | |
15 | * furnished to do so, subject to the following conditions: | |
16 | * | |
17 | * The above copyright notice and this permission notice shall be included in | |
18 | * all copies or substantial portions of the Software. | |
19 | * | |
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
26 | * SOFTWARE. | |
27 | */ | |
28 | ||
d2f71f12 PP |
29 | #define BT_LOG_TAG "STREAM-CLASS" |
30 | #include <babeltrace/lib-logging-internal.h> | |
31 | ||
3dca2276 | 32 | #include <babeltrace/assert-pre-internal.h> |
ac0c6bdd | 33 | #include <babeltrace/ctf-ir/clock-class-internal.h> |
272df73e | 34 | #include <babeltrace/ctf-ir/event-class-internal.h> |
2e33ac5a PP |
35 | #include <babeltrace/ctf-ir/field-types-internal.h> |
36 | #include <babeltrace/ctf-ir/fields-internal.h> | |
11b0cdc8 | 37 | #include <babeltrace/ctf-ir/stream-class-internal.h> |
09840de5 | 38 | #include <babeltrace/ctf-ir/validation-internal.h> |
8bf65fbd | 39 | #include <babeltrace/ctf-ir/visitor-internal.h> |
654c1444 | 40 | #include <babeltrace/ctf-ir/utils.h> |
2a3ced3c | 41 | #include <babeltrace/ctf-ir/utils-internal.h> |
83509119 | 42 | #include <babeltrace/ref.h> |
3d9990ac PP |
43 | #include <babeltrace/compiler-internal.h> |
44 | #include <babeltrace/align-internal.h> | |
45 | #include <babeltrace/endian-internal.h> | |
f6ccaed9 | 46 | #include <babeltrace/assert-internal.h> |
dc3fffef | 47 | #include <inttypes.h> |
544d0515 | 48 | #include <stdint.h> |
e011d2c1 | 49 | #include <stdbool.h> |
11b0cdc8 | 50 | |
3dca2276 PP |
51 | BT_HIDDEN |
52 | int bt_stream_class_common_initialize(struct bt_stream_class_common *stream_class, | |
53 | const char *name, bt_object_release_func release_func) | |
e0e2946b | 54 | { |
3dca2276 | 55 | BT_LOGD("Initializing common stream class object: name=\"%s\"", name); |
11b0cdc8 | 56 | |
3dca2276 | 57 | bt_object_init(stream_class, release_func); |
11b0cdc8 JG |
58 | stream_class->name = g_string_new(name); |
59 | stream_class->event_classes = g_ptr_array_new_with_free_func( | |
e6a8e8e4 | 60 | (GDestroyNotify) bt_object_release); |
11b0cdc8 | 61 | if (!stream_class->event_classes) { |
d2f71f12 | 62 | BT_LOGE_STR("Failed to allocate a GPtrArray."); |
83509119 | 63 | goto error; |
11b0cdc8 JG |
64 | } |
65 | ||
0b9ce69f JG |
66 | stream_class->event_classes_ht = g_hash_table_new_full(g_int64_hash, |
67 | g_int64_equal, g_free, NULL); | |
d2f71f12 PP |
68 | if (!stream_class->event_classes_ht) { |
69 | BT_LOGE_STR("Failed to allocate a GHashTable."); | |
70 | goto error; | |
71 | } | |
0b9ce69f | 72 | |
3dca2276 | 73 | BT_LOGD("Initialized common stream class object: addr=%p, name=\"%s\"", |
d2f71f12 | 74 | stream_class, name); |
3dca2276 | 75 | return 0; |
11b0cdc8 | 76 | |
11b0cdc8 | 77 | error: |
3dca2276 | 78 | return -1; |
142c5610 JG |
79 | } |
80 | ||
3dca2276 PP |
81 | BT_HIDDEN |
82 | void bt_stream_class_common_finalize(struct bt_stream_class_common *stream_class) | |
3ea33115 | 83 | { |
3dca2276 PP |
84 | BT_LOGD("Finalizing common stream class: addr=%p, name=\"%s\", id=%" PRId64, |
85 | stream_class, bt_stream_class_common_get_name(stream_class), | |
86 | bt_stream_class_common_get_id(stream_class)); | |
87 | bt_put(stream_class->clock_class); | |
3ea33115 | 88 | |
3dca2276 PP |
89 | if (stream_class->event_classes_ht) { |
90 | g_hash_table_destroy(stream_class->event_classes_ht); | |
91 | } | |
92 | if (stream_class->event_classes) { | |
93 | BT_LOGD_STR("Destroying event classes."); | |
94 | g_ptr_array_free(stream_class->event_classes, TRUE); | |
d2f71f12 PP |
95 | } |
96 | ||
3dca2276 PP |
97 | if (stream_class->name) { |
98 | g_string_free(stream_class->name, TRUE); | |
3ea33115 JG |
99 | } |
100 | ||
3dca2276 PP |
101 | BT_LOGD_STR("Putting event header field type."); |
102 | bt_put(stream_class->event_header_field_type); | |
103 | BT_LOGD_STR("Putting packet context field type."); | |
104 | bt_put(stream_class->packet_context_field_type); | |
105 | BT_LOGD_STR("Putting event context field type."); | |
106 | bt_put(stream_class->event_context_field_type); | |
107 | } | |
03be3bcd | 108 | |
3dca2276 PP |
109 | static |
110 | void bt_stream_class_destroy(struct bt_object *obj) | |
111 | { | |
112 | struct bt_stream_class *stream_class; | |
03be3bcd | 113 | |
3dca2276 PP |
114 | stream_class = (void *) obj; |
115 | BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64, | |
50842bdc PP |
116 | stream_class, bt_stream_class_get_name(stream_class), |
117 | bt_stream_class_get_id(stream_class)); | |
3dca2276 PP |
118 | bt_stream_class_common_finalize(BT_TO_COMMON(stream_class)); |
119 | g_free(stream_class); | |
3ea33115 JG |
120 | } |
121 | ||
3dca2276 | 122 | struct bt_stream_class *bt_stream_class_create(const char *name) |
2f100782 | 123 | { |
3dca2276 PP |
124 | struct bt_stream_class *stream_class = NULL; |
125 | int ret; | |
2f100782 | 126 | |
3dca2276 PP |
127 | BT_LOGD("Creating stream class object: name=\"%s\"", name); |
128 | stream_class = g_new0(struct bt_stream_class, 1); | |
d2f71f12 | 129 | if (!stream_class) { |
3dca2276 PP |
130 | BT_LOGE_STR("Failed to allocate one stream class."); |
131 | goto error; | |
d2f71f12 PP |
132 | } |
133 | ||
3dca2276 PP |
134 | ret = bt_stream_class_common_initialize(BT_TO_COMMON(stream_class), |
135 | name, bt_stream_class_destroy); | |
136 | if (ret) { | |
137 | /* bt_stream_class_common_initialize() logs errors */ | |
138 | goto error; | |
2f100782 JG |
139 | } |
140 | ||
3dca2276 PP |
141 | BT_LOGD("Created stream class object: addr=%p, name=\"%s\"", |
142 | stream_class, name); | |
143 | return stream_class; | |
144 | ||
145 | error: | |
146 | bt_put(stream_class); | |
147 | return NULL; | |
2f100782 JG |
148 | } |
149 | ||
3dca2276 | 150 | struct bt_trace *bt_stream_class_get_trace(struct bt_stream_class *stream_class) |
11b0cdc8 | 151 | { |
3dca2276 PP |
152 | return BT_FROM_COMMON(bt_stream_class_common_get_trace( |
153 | BT_TO_COMMON(stream_class))); | |
11b0cdc8 JG |
154 | } |
155 | ||
3dca2276 | 156 | const char *bt_stream_class_get_name(struct bt_stream_class *stream_class) |
2f100782 | 157 | { |
3dca2276 | 158 | return bt_stream_class_common_get_name(BT_TO_COMMON(stream_class)); |
2f100782 JG |
159 | } |
160 | ||
3dca2276 PP |
161 | int bt_stream_class_set_name(struct bt_stream_class *stream_class, |
162 | const char *name) | |
5ca83563 | 163 | { |
3dca2276 PP |
164 | return bt_stream_class_common_set_name(BT_TO_COMMON(stream_class), |
165 | name); | |
5ca83563 JG |
166 | } |
167 | ||
3dca2276 | 168 | int64_t bt_stream_class_get_id(struct bt_stream_class *stream_class) |
2f100782 | 169 | { |
3dca2276 | 170 | return bt_stream_class_common_get_id(BT_TO_COMMON(stream_class)); |
2f100782 JG |
171 | } |
172 | ||
3dca2276 | 173 | int bt_stream_class_set_id(struct bt_stream_class *stream_class, uint64_t id) |
29664b2a | 174 | { |
3dca2276 | 175 | return bt_stream_class_common_set_id(BT_TO_COMMON(stream_class), id); |
29664b2a PP |
176 | } |
177 | ||
0d23acbe PP |
178 | static |
179 | void event_class_exists(gpointer element, gpointer query) | |
180 | { | |
3dca2276 | 181 | struct bt_event_class_common *event_class_a = element; |
0d23acbe | 182 | struct search_query *search_query = query; |
3dca2276 | 183 | struct bt_event_class_common *event_class_b = search_query->value; |
0d23acbe PP |
184 | int64_t id_a, id_b; |
185 | ||
186 | if (search_query->value == element) { | |
187 | search_query->found = 1; | |
188 | goto end; | |
189 | } | |
190 | ||
0d23acbe PP |
191 | /* |
192 | * Two event classes cannot share the same ID in a given | |
193 | * stream class. | |
194 | */ | |
3dca2276 PP |
195 | id_a = bt_event_class_common_get_id(event_class_a); |
196 | id_b = bt_event_class_common_get_id(event_class_b); | |
0d23acbe PP |
197 | |
198 | if (id_a < 0 || id_b < 0) { | |
199 | /* at least one ID is not set: will be automatically set later */ | |
200 | goto end; | |
201 | } | |
202 | ||
203 | if (id_a == id_b) { | |
66871d36 | 204 | BT_LOGW("Event class with this ID already exists in the stream class: " |
d2f71f12 | 205 | "id=%" PRId64 ", name=\"%s\"", |
3dca2276 | 206 | id_a, bt_event_class_common_get_name(event_class_a)); |
0d23acbe PP |
207 | search_query->found = 1; |
208 | goto end; | |
209 | } | |
210 | ||
211 | end: | |
212 | return; | |
213 | } | |
214 | ||
3dca2276 PP |
215 | BT_HIDDEN |
216 | int bt_stream_class_common_add_event_class( | |
217 | struct bt_stream_class_common *stream_class, | |
218 | struct bt_event_class_common *event_class, | |
219 | bt_validation_flag_copy_field_type_func copy_field_type_func) | |
11b0cdc8 JG |
220 | { |
221 | int ret = 0; | |
0b9ce69f | 222 | int64_t *event_id = NULL; |
3dca2276 PP |
223 | struct bt_trace_common *trace = NULL; |
224 | struct bt_stream_class_common *old_stream_class = NULL; | |
50842bdc | 225 | struct bt_validation_output validation_output = { 0 }; |
3dca2276 PP |
226 | struct bt_field_type_common *packet_header_type = NULL; |
227 | struct bt_field_type_common *packet_context_type = NULL; | |
228 | struct bt_field_type_common *event_header_type = NULL; | |
229 | struct bt_field_type_common *stream_event_ctx_type = NULL; | |
230 | struct bt_field_type_common *event_context_type = NULL; | |
231 | struct bt_field_type_common *event_payload_type = NULL; | |
50842bdc PP |
232 | const enum bt_validation_flag validation_flags = |
233 | BT_VALIDATION_FLAG_EVENT; | |
2a3ced3c | 234 | struct bt_clock_class *expected_clock_class = NULL; |
11b0cdc8 | 235 | |
3dca2276 PP |
236 | BT_ASSERT(copy_field_type_func); |
237 | ||
e011d2c1 PP |
238 | if (!stream_class || !event_class) { |
239 | BT_LOGW("Invalid parameter: stream class or event class is NULL: " | |
240 | "stream-class-addr=%p, event-class-addr=%p", | |
241 | stream_class, event_class); | |
242 | ret = -1; | |
243 | goto end; | |
244 | } | |
245 | ||
d2f71f12 PP |
246 | BT_LOGD("Adding event class to stream class: " |
247 | "stream-class-addr=%p, stream-class-name=\"%s\", " | |
248 | "stream-class-id=%" PRId64 ", event-class-addr=%p, " | |
249 | "event-class-name=\"%s\", event-class-id=%" PRId64, | |
3dca2276 PP |
250 | stream_class, bt_stream_class_common_get_name(stream_class), |
251 | bt_stream_class_common_get_id(stream_class), | |
d2f71f12 | 252 | event_class, |
3dca2276 PP |
253 | bt_event_class_common_get_name(event_class), |
254 | bt_event_class_common_get_id(event_class)); | |
d2f71f12 | 255 | |
3dca2276 | 256 | trace = bt_stream_class_common_get_trace(stream_class); |
5acf2ae6 | 257 | |
2a3ced3c PP |
258 | if (stream_class->frozen) { |
259 | /* | |
260 | * We only check that the event class to be added has a | |
261 | * single class which matches the stream class's | |
262 | * expected clock class if the stream class is frozen. | |
263 | * If it's not, then this event class is added "as is" | |
264 | * and the validation will be performed when calling | |
265 | * either bt_trace_add_stream_class() or | |
266 | * bt_event_create(). This is because the stream class's | |
267 | * field types (packet context, event header, event | |
268 | * context) could change before the next call to one of | |
269 | * those two functions. | |
270 | */ | |
271 | expected_clock_class = bt_get(stream_class->clock_class); | |
272 | ||
273 | /* | |
274 | * At this point, `expected_clock_class` can be NULL, | |
275 | * and bt_event_class_validate_single_clock_class() | |
276 | * below can set it. | |
277 | */ | |
3dca2276 | 278 | ret = bt_event_class_common_validate_single_clock_class( |
2a3ced3c PP |
279 | event_class, &expected_clock_class); |
280 | if (ret) { | |
281 | BT_LOGW("Event class contains a field type which is not " | |
282 | "recursively mapped to its stream class's " | |
283 | "expected clock class: " | |
284 | "stream-class-addr=%p, " | |
285 | "stream-class-id=%" PRId64 ", " | |
286 | "stream-class-name=\"%s\", " | |
287 | "expected-clock-class-addr=%p, " | |
288 | "expected-clock-class-name=\"%s\"", | |
289 | stream_class, | |
3dca2276 PP |
290 | bt_stream_class_common_get_id(stream_class), |
291 | bt_stream_class_common_get_name(stream_class), | |
2a3ced3c PP |
292 | expected_clock_class, |
293 | expected_clock_class ? | |
294 | bt_clock_class_get_name(expected_clock_class) : | |
295 | NULL); | |
296 | goto end; | |
297 | } | |
298 | } | |
299 | ||
0b9ce69f JG |
300 | event_id = g_new(int64_t, 1); |
301 | if (!event_id) { | |
d2f71f12 | 302 | BT_LOGE_STR("Failed to allocate one int64_t."); |
0b9ce69f JG |
303 | ret = -1; |
304 | goto end; | |
305 | } | |
306 | ||
11b0cdc8 JG |
307 | /* Check for duplicate event classes */ |
308 | struct search_query query = { .value = event_class, .found = 0 }; | |
0d23acbe PP |
309 | g_ptr_array_foreach(stream_class->event_classes, event_class_exists, |
310 | &query); | |
11b0cdc8 | 311 | if (query.found) { |
d2f71f12 | 312 | BT_LOGW_STR("Another event class part of this stream class has the same ID."); |
11b0cdc8 JG |
313 | ret = -1; |
314 | goto end; | |
315 | } | |
316 | ||
3dca2276 | 317 | old_stream_class = bt_event_class_common_borrow_stream_class(event_class); |
e6a8e8e4 JG |
318 | if (old_stream_class) { |
319 | /* Event class is already associated to a stream class. */ | |
d2f71f12 PP |
320 | BT_LOGW("Event class is already part of another stream class: " |
321 | "event-class-stream-class-addr=%p, " | |
322 | "event-class-stream-class-name=\"%s\", " | |
323 | "event-class-stream-class-id=%" PRId64, | |
324 | old_stream_class, | |
3dca2276 PP |
325 | bt_stream_class_common_get_name(old_stream_class), |
326 | bt_stream_class_common_get_id(old_stream_class)); | |
e6a8e8e4 JG |
327 | ret = -1; |
328 | goto end; | |
329 | } | |
330 | ||
e6a8e8e4 | 331 | if (trace) { |
09840de5 PP |
332 | /* |
333 | * If the stream class is associated with a trace, then | |
334 | * both those objects are frozen. Also, this event class | |
335 | * is about to be frozen. | |
336 | * | |
337 | * Therefore the event class must be validated here. | |
338 | * The trace and stream class should be valid at this | |
339 | * point. | |
340 | */ | |
f6ccaed9 PP |
341 | BT_ASSERT(trace->valid); |
342 | BT_ASSERT(stream_class->valid); | |
09840de5 | 343 | packet_header_type = |
3dca2276 | 344 | bt_trace_common_get_packet_header_field_type(trace); |
09840de5 | 345 | packet_context_type = |
3dca2276 | 346 | bt_stream_class_common_get_packet_context_field_type( |
09840de5 PP |
347 | stream_class); |
348 | event_header_type = | |
3dca2276 PP |
349 | bt_stream_class_common_get_event_header_field_type( |
350 | stream_class); | |
09840de5 | 351 | stream_event_ctx_type = |
3dca2276 | 352 | bt_stream_class_common_get_event_context_field_type( |
09840de5 PP |
353 | stream_class); |
354 | event_context_type = | |
3dca2276 | 355 | bt_event_class_common_get_context_field_type(event_class); |
09840de5 | 356 | event_payload_type = |
3dca2276 | 357 | bt_event_class_common_get_payload_field_type(event_class); |
50842bdc | 358 | ret = bt_validate_class_types( |
09840de5 PP |
359 | trace->environment, packet_header_type, |
360 | packet_context_type, event_header_type, | |
361 | stream_event_ctx_type, event_context_type, | |
362 | event_payload_type, trace->valid, | |
363 | stream_class->valid, event_class->valid, | |
3dca2276 PP |
364 | &validation_output, validation_flags, |
365 | copy_field_type_func); | |
09840de5 PP |
366 | BT_PUT(packet_header_type); |
367 | BT_PUT(packet_context_type); | |
368 | BT_PUT(event_header_type); | |
369 | BT_PUT(stream_event_ctx_type); | |
370 | BT_PUT(event_context_type); | |
371 | BT_PUT(event_payload_type); | |
372 | ||
26079216 | 373 | if (ret) { |
09840de5 PP |
374 | /* |
375 | * This means something went wrong during the | |
376 | * validation process, not that the objects are | |
377 | * invalid. | |
378 | */ | |
d2f71f12 | 379 | BT_LOGE("Failed to validate event class: ret=%d", ret); |
09840de5 PP |
380 | goto end; |
381 | } | |
382 | ||
383 | if ((validation_output.valid_flags & validation_flags) != | |
384 | validation_flags) { | |
385 | /* Invalid event class */ | |
66871d36 | 386 | BT_LOGW("Invalid trace, stream class, or event class: " |
d2f71f12 PP |
387 | "valid-flags=0x%x", |
388 | validation_output.valid_flags); | |
09840de5 | 389 | ret = -1; |
26079216 JG |
390 | goto end; |
391 | } | |
392 | } | |
393 | ||
09840de5 | 394 | /* Only set an event ID if none was explicitly set before */ |
3dca2276 | 395 | *event_id = bt_event_class_common_get_id(event_class); |
24626e8b | 396 | if (*event_id < 0) { |
d2f71f12 PP |
397 | BT_LOGV("Event class has no ID: automatically setting it: " |
398 | "id=%" PRId64, stream_class->next_event_id); | |
399 | ||
3dca2276 | 400 | if (bt_event_class_common_set_id(event_class, |
d2f71f12 PP |
401 | stream_class->next_event_id)) { |
402 | BT_LOGE("Cannot set event class's ID: id=%" PRId64, | |
403 | stream_class->next_event_id); | |
2f100782 JG |
404 | ret = -1; |
405 | goto end; | |
406 | } | |
d2f71f12 | 407 | stream_class->next_event_id++; |
0b9ce69f | 408 | *event_id = stream_class->next_event_id; |
2f100782 JG |
409 | } |
410 | ||
e6a8e8e4 | 411 | bt_object_set_parent(event_class, stream_class); |
09840de5 PP |
412 | |
413 | if (trace) { | |
414 | /* | |
415 | * At this point we know that the function will be | |
416 | * successful. Therefore we can replace the event | |
417 | * class's field types with what's in the validation | |
418 | * output structure and mark this event class as valid. | |
419 | */ | |
50842bdc | 420 | bt_validation_replace_types(NULL, NULL, event_class, |
09840de5 PP |
421 | &validation_output, validation_flags); |
422 | event_class->valid = 1; | |
423 | ||
424 | /* | |
425 | * Put what was not moved in | |
50842bdc | 426 | * bt_validation_replace_types(). |
09840de5 | 427 | */ |
50842bdc | 428 | bt_validation_output_put_types(&validation_output); |
09840de5 PP |
429 | } |
430 | ||
431 | /* Add to the event classes of the stream class */ | |
11b0cdc8 | 432 | g_ptr_array_add(stream_class->event_classes, event_class); |
0b9ce69f JG |
433 | g_hash_table_insert(stream_class->event_classes_ht, event_id, |
434 | event_class); | |
435 | event_id = NULL; | |
09840de5 PP |
436 | |
437 | /* Freeze the event class */ | |
3dca2276 | 438 | bt_event_class_common_freeze(event_class); |
5ca83563 | 439 | |
2a3ced3c PP |
440 | /* |
441 | * It is safe to set the stream class's unique clock class | |
442 | * now if the stream class is frozen. | |
443 | */ | |
444 | if (stream_class->frozen && expected_clock_class) { | |
f6ccaed9 | 445 | BT_ASSERT(!stream_class->clock_class || |
2a3ced3c PP |
446 | stream_class->clock_class == expected_clock_class); |
447 | BT_MOVE(stream_class->clock_class, expected_clock_class); | |
448 | } | |
449 | ||
d2f71f12 PP |
450 | BT_LOGD("Added event class to stream class: " |
451 | "stream-class-addr=%p, stream-class-name=\"%s\", " | |
452 | "stream-class-id=%" PRId64 ", event-class-addr=%p, " | |
453 | "event-class-name=\"%s\", event-class-id=%" PRId64, | |
3dca2276 PP |
454 | stream_class, bt_stream_class_common_get_name(stream_class), |
455 | bt_stream_class_common_get_id(stream_class), | |
d2f71f12 | 456 | event_class, |
3dca2276 PP |
457 | bt_event_class_common_get_name(event_class), |
458 | bt_event_class_common_get_id(event_class)); | |
d2f71f12 | 459 | |
11b0cdc8 | 460 | end: |
e6a8e8e4 | 461 | BT_PUT(trace); |
50842bdc | 462 | bt_validation_output_put_types(&validation_output); |
2a3ced3c | 463 | bt_put(expected_clock_class); |
f6ccaed9 PP |
464 | BT_ASSERT(!packet_header_type); |
465 | BT_ASSERT(!packet_context_type); | |
466 | BT_ASSERT(!event_header_type); | |
467 | BT_ASSERT(!stream_event_ctx_type); | |
468 | BT_ASSERT(!event_context_type); | |
469 | BT_ASSERT(!event_payload_type); | |
0b9ce69f | 470 | g_free(event_id); |
11b0cdc8 JG |
471 | return ret; |
472 | } | |
473 | ||
3dca2276 PP |
474 | int bt_stream_class_add_event_class( |
475 | struct bt_stream_class *stream_class, | |
476 | struct bt_event_class *event_class) | |
69dc4535 | 477 | { |
3dca2276 PP |
478 | struct bt_trace *trace; |
479 | int ret = 0; | |
69dc4535 JG |
480 | |
481 | if (!stream_class) { | |
3dca2276 PP |
482 | BT_LOGW("Invalid parameter: stream class is NULL: " |
483 | "stream-class-addr=%p", stream_class); | |
484 | ret = -1; | |
485 | goto end; | |
486 | } | |
487 | ||
488 | trace = BT_FROM_COMMON(bt_stream_class_common_borrow_trace( | |
489 | BT_TO_COMMON(stream_class))); | |
490 | if (trace && trace->is_static) { | |
491 | BT_LOGW("Invalid parameter: stream class's trace is static: " | |
492 | "trace-addr=%p, trace-name=\"%s\"", | |
493 | trace, bt_trace_get_name(trace)); | |
494 | ret = -1; | |
495 | goto end; | |
496 | } | |
497 | ||
498 | ret = bt_stream_class_common_add_event_class( | |
499 | BT_TO_COMMON(stream_class), BT_TO_COMMON(event_class), | |
500 | (bt_validation_flag_copy_field_type_func) bt_field_type_copy); | |
501 | if (ret) { | |
69dc4535 JG |
502 | goto end; |
503 | } | |
504 | ||
3dca2276 PP |
505 | /* Notifiy listeners of the trace's schema modification. */ |
506 | if (trace) { | |
507 | struct bt_visitor_object obj = { .object = event_class, | |
508 | .type = BT_VISITOR_OBJECT_TYPE_EVENT_CLASS }; | |
509 | ||
510 | (void) bt_trace_object_modification(&obj, trace); | |
511 | } | |
512 | ||
69dc4535 JG |
513 | end: |
514 | return ret; | |
515 | } | |
516 | ||
3dca2276 PP |
517 | int64_t bt_stream_class_get_event_class_count( |
518 | struct bt_stream_class *stream_class) | |
519 | { | |
520 | return bt_stream_class_common_get_event_class_count( | |
521 | BT_TO_COMMON(stream_class)); | |
522 | } | |
523 | ||
50842bdc PP |
524 | struct bt_event_class *bt_stream_class_get_event_class_by_index( |
525 | struct bt_stream_class *stream_class, uint64_t index) | |
69dc4535 | 526 | { |
3dca2276 PP |
527 | return BT_FROM_COMMON(bt_stream_class_common_get_event_class_by_index( |
528 | BT_TO_COMMON(stream_class), index)); | |
69dc4535 JG |
529 | } |
530 | ||
50842bdc PP |
531 | struct bt_event_class *bt_stream_class_get_event_class_by_id( |
532 | struct bt_stream_class *stream_class, uint64_t id) | |
0863f950 | 533 | { |
3dca2276 PP |
534 | return BT_FROM_COMMON(bt_stream_class_common_get_event_class_by_id( |
535 | BT_TO_COMMON(stream_class), id)); | |
0863f950 PP |
536 | } |
537 | ||
3dca2276 | 538 | struct bt_field_type *bt_stream_class_get_packet_context_field_type( |
50842bdc | 539 | struct bt_stream_class *stream_class) |
12c8a1a3 | 540 | { |
3dca2276 PP |
541 | return BT_FROM_COMMON(bt_stream_class_common_get_packet_context_field_type( |
542 | BT_TO_COMMON(stream_class))); | |
12c8a1a3 JG |
543 | } |
544 | ||
3dca2276 | 545 | int bt_stream_class_set_packet_context_field_type( |
50842bdc PP |
546 | struct bt_stream_class *stream_class, |
547 | struct bt_field_type *packet_context_type) | |
12c8a1a3 | 548 | { |
3dca2276 PP |
549 | return bt_stream_class_common_set_packet_context_field_type( |
550 | BT_TO_COMMON(stream_class), (void *) packet_context_type); | |
12c8a1a3 JG |
551 | } |
552 | ||
3dca2276 | 553 | struct bt_field_type *bt_stream_class_get_event_header_field_type( |
50842bdc | 554 | struct bt_stream_class *stream_class) |
662e778c | 555 | { |
3dca2276 PP |
556 | return BT_FROM_COMMON(bt_stream_class_common_get_event_header_field_type( |
557 | BT_TO_COMMON(stream_class))); | |
662e778c JG |
558 | } |
559 | ||
3dca2276 | 560 | int bt_stream_class_set_event_header_field_type( |
50842bdc PP |
561 | struct bt_stream_class *stream_class, |
562 | struct bt_field_type *event_header_type) | |
662e778c | 563 | { |
3dca2276 PP |
564 | return bt_stream_class_common_set_event_header_field_type( |
565 | BT_TO_COMMON(stream_class), (void *) event_header_type); | |
662e778c JG |
566 | } |
567 | ||
3dca2276 | 568 | struct bt_field_type *bt_stream_class_get_event_context_field_type( |
50842bdc | 569 | struct bt_stream_class *stream_class) |
af181248 | 570 | { |
3dca2276 PP |
571 | return BT_FROM_COMMON(bt_stream_class_common_get_event_context_field_type( |
572 | BT_TO_COMMON(stream_class))); | |
af181248 JG |
573 | } |
574 | ||
3dca2276 | 575 | int bt_stream_class_set_event_context_field_type( |
50842bdc PP |
576 | struct bt_stream_class *stream_class, |
577 | struct bt_field_type *event_context_type) | |
af181248 | 578 | { |
3dca2276 PP |
579 | return bt_stream_class_common_set_event_context_field_type( |
580 | BT_TO_COMMON(stream_class), (void *) event_context_type); | |
11b0cdc8 JG |
581 | } |
582 | ||
8bf65fbd | 583 | static |
544d0515 | 584 | int64_t get_event_class_count(void *element) |
8bf65fbd | 585 | { |
50842bdc PP |
586 | return bt_stream_class_get_event_class_count( |
587 | (struct bt_stream_class *) element); | |
8bf65fbd JG |
588 | } |
589 | ||
590 | static | |
591 | void *get_event_class(void *element, int i) | |
592 | { | |
50842bdc PP |
593 | return bt_stream_class_get_event_class_by_index( |
594 | (struct bt_stream_class *) element, i); | |
8bf65fbd JG |
595 | } |
596 | ||
597 | static | |
50842bdc | 598 | int visit_event_class(void *object, bt_visitor visitor,void *data) |
8bf65fbd | 599 | { |
3dca2276 PP |
600 | struct bt_visitor_object obj = { |
601 | .object = object, | |
602 | .type = BT_VISITOR_OBJECT_TYPE_EVENT_CLASS | |
603 | }; | |
8bf65fbd | 604 | |
d9a13d86 | 605 | return visitor(&obj, data); |
8bf65fbd JG |
606 | } |
607 | ||
3dca2276 PP |
608 | BT_HIDDEN |
609 | int bt_stream_class_common_visit(struct bt_stream_class_common *stream_class, | |
50842bdc | 610 | bt_visitor visitor, void *data) |
8bf65fbd JG |
611 | { |
612 | int ret; | |
3dca2276 PP |
613 | struct bt_visitor_object obj = { |
614 | .object = stream_class, | |
615 | .type = BT_VISITOR_OBJECT_TYPE_STREAM_CLASS | |
616 | }; | |
8bf65fbd JG |
617 | |
618 | if (!stream_class || !visitor) { | |
d2f71f12 PP |
619 | BT_LOGW("Invalid parameter: stream class or visitor is NULL: " |
620 | "stream-class-addr=%p, visitor=%p", | |
621 | stream_class, visitor); | |
8bf65fbd JG |
622 | ret = -1; |
623 | goto end; | |
624 | } | |
625 | ||
d9a13d86 | 626 | ret = visitor_helper(&obj, get_event_class_count, |
8bf65fbd JG |
627 | get_event_class, |
628 | visit_event_class, visitor, data); | |
d2f71f12 | 629 | BT_LOGV("visitor_helper() returned: ret=%d", ret); |
3dca2276 | 630 | |
8bf65fbd JG |
631 | end: |
632 | return ret; | |
633 | } | |
634 | ||
3dca2276 PP |
635 | int bt_stream_class_visit(struct bt_stream_class *stream_class, |
636 | bt_visitor visitor, void *data) | |
637 | { | |
638 | return bt_stream_class_common_visit(BT_FROM_COMMON(stream_class), | |
639 | visitor, data); | |
640 | } | |
641 | ||
11b0cdc8 | 642 | BT_HIDDEN |
3dca2276 | 643 | void bt_stream_class_common_freeze(struct bt_stream_class_common *stream_class) |
11b0cdc8 | 644 | { |
d2f71f12 | 645 | if (!stream_class || stream_class->frozen) { |
11b0cdc8 JG |
646 | return; |
647 | } | |
648 | ||
d2f71f12 | 649 | BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64, |
3dca2276 PP |
650 | stream_class, bt_stream_class_common_get_name(stream_class), |
651 | bt_stream_class_common_get_id(stream_class)); | |
11b0cdc8 | 652 | stream_class->frozen = 1; |
3dca2276 PP |
653 | bt_field_type_common_freeze(stream_class->event_header_field_type); |
654 | bt_field_type_common_freeze(stream_class->packet_context_field_type); | |
655 | bt_field_type_common_freeze(stream_class->event_context_field_type); | |
656 | bt_clock_class_freeze(stream_class->clock_class); | |
11b0cdc8 JG |
657 | } |
658 | ||
3dca2276 | 659 | void bt_stream_class_freeze(struct bt_stream_class *stream_class) |
e011d2c1 | 660 | { |
3dca2276 | 661 | bt_stream_class_common_freeze(BT_TO_COMMON(stream_class)); |
11b0cdc8 | 662 | } |
2a3ced3c PP |
663 | |
664 | BT_HIDDEN | |
3dca2276 PP |
665 | int bt_stream_class_common_validate_single_clock_class( |
666 | struct bt_stream_class_common *stream_class, | |
2a3ced3c PP |
667 | struct bt_clock_class **expected_clock_class) |
668 | { | |
669 | int ret; | |
670 | uint64_t i; | |
671 | ||
f6ccaed9 PP |
672 | BT_ASSERT(stream_class); |
673 | BT_ASSERT(expected_clock_class); | |
3dca2276 PP |
674 | ret = bt_field_type_common_validate_single_clock_class( |
675 | stream_class->packet_context_field_type, | |
2a3ced3c PP |
676 | expected_clock_class); |
677 | if (ret) { | |
678 | BT_LOGW("Stream class's packet context field type " | |
679 | "is not recursively mapped to the " | |
680 | "expected clock class: " | |
681 | "stream-class-addr=%p, " | |
682 | "stream-class-name=\"%s\", " | |
683 | "stream-class-id=%" PRId64 ", " | |
684 | "ft-addr=%p", | |
685 | stream_class, | |
3dca2276 | 686 | bt_stream_class_common_get_name(stream_class), |
2a3ced3c | 687 | stream_class->id, |
3dca2276 | 688 | stream_class->packet_context_field_type); |
2a3ced3c PP |
689 | goto end; |
690 | } | |
691 | ||
3dca2276 PP |
692 | ret = bt_field_type_common_validate_single_clock_class( |
693 | stream_class->event_header_field_type, | |
2a3ced3c PP |
694 | expected_clock_class); |
695 | if (ret) { | |
696 | BT_LOGW("Stream class's event header field type " | |
697 | "is not recursively mapped to the " | |
698 | "expected clock class: " | |
699 | "stream-class-addr=%p, " | |
700 | "stream-class-name=\"%s\", " | |
701 | "stream-class-id=%" PRId64 ", " | |
702 | "ft-addr=%p", | |
703 | stream_class, | |
3dca2276 | 704 | bt_stream_class_common_get_name(stream_class), |
2a3ced3c | 705 | stream_class->id, |
3dca2276 | 706 | stream_class->event_header_field_type); |
2a3ced3c PP |
707 | goto end; |
708 | } | |
709 | ||
3dca2276 PP |
710 | ret = bt_field_type_common_validate_single_clock_class( |
711 | stream_class->event_context_field_type, | |
2a3ced3c PP |
712 | expected_clock_class); |
713 | if (ret) { | |
714 | BT_LOGW("Stream class's event context field type " | |
715 | "is not recursively mapped to the " | |
716 | "expected clock class: " | |
717 | "stream-class-addr=%p, " | |
718 | "stream-class-name=\"%s\", " | |
719 | "stream-class-id=%" PRId64 ", " | |
720 | "ft-addr=%p", | |
721 | stream_class, | |
3dca2276 | 722 | bt_stream_class_common_get_name(stream_class), |
2a3ced3c | 723 | stream_class->id, |
3dca2276 | 724 | stream_class->event_context_field_type); |
2a3ced3c PP |
725 | goto end; |
726 | } | |
727 | ||
728 | for (i = 0; i < stream_class->event_classes->len; i++) { | |
3dca2276 | 729 | struct bt_event_class_common *event_class = |
2a3ced3c PP |
730 | g_ptr_array_index(stream_class->event_classes, i); |
731 | ||
f6ccaed9 | 732 | BT_ASSERT(event_class); |
3dca2276 PP |
733 | ret = bt_event_class_common_validate_single_clock_class( |
734 | event_class, expected_clock_class); | |
2a3ced3c PP |
735 | if (ret) { |
736 | BT_LOGW("Stream class's event class contains a " | |
737 | "field type which is not recursively mapped to " | |
738 | "the expected clock class: " | |
739 | "stream-class-addr=%p, " | |
740 | "stream-class-name=\"%s\", " | |
741 | "stream-class-id=%" PRId64, | |
742 | stream_class, | |
3dca2276 | 743 | bt_stream_class_common_get_name(stream_class), |
2a3ced3c PP |
744 | stream_class->id); |
745 | goto end; | |
746 | } | |
747 | } | |
748 | ||
749 | end: | |
750 | return ret; | |
751 | } |