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 | ||
094ff7c0 | 150 | struct bt_trace *bt_stream_class_borrow_trace(struct bt_stream_class *stream_class) |
11b0cdc8 | 151 | { |
094ff7c0 | 152 | return BT_FROM_COMMON(bt_stream_class_common_borrow_trace( |
3dca2276 | 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)); | |
094ff7c0 | 255 | trace = bt_stream_class_common_borrow_trace(stream_class); |
5acf2ae6 | 256 | |
2a3ced3c PP |
257 | if (stream_class->frozen) { |
258 | /* | |
259 | * We only check that the event class to be added has a | |
260 | * single class which matches the stream class's | |
261 | * expected clock class if the stream class is frozen. | |
262 | * If it's not, then this event class is added "as is" | |
263 | * and the validation will be performed when calling | |
264 | * either bt_trace_add_stream_class() or | |
265 | * bt_event_create(). This is because the stream class's | |
266 | * field types (packet context, event header, event | |
267 | * context) could change before the next call to one of | |
268 | * those two functions. | |
269 | */ | |
270 | expected_clock_class = bt_get(stream_class->clock_class); | |
271 | ||
272 | /* | |
273 | * At this point, `expected_clock_class` can be NULL, | |
274 | * and bt_event_class_validate_single_clock_class() | |
275 | * below can set it. | |
276 | */ | |
3dca2276 | 277 | ret = bt_event_class_common_validate_single_clock_class( |
2a3ced3c PP |
278 | event_class, &expected_clock_class); |
279 | if (ret) { | |
280 | BT_LOGW("Event class contains a field type which is not " | |
281 | "recursively mapped to its stream class's " | |
282 | "expected clock class: " | |
283 | "stream-class-addr=%p, " | |
284 | "stream-class-id=%" PRId64 ", " | |
285 | "stream-class-name=\"%s\", " | |
286 | "expected-clock-class-addr=%p, " | |
287 | "expected-clock-class-name=\"%s\"", | |
288 | stream_class, | |
3dca2276 PP |
289 | bt_stream_class_common_get_id(stream_class), |
290 | bt_stream_class_common_get_name(stream_class), | |
2a3ced3c PP |
291 | expected_clock_class, |
292 | expected_clock_class ? | |
293 | bt_clock_class_get_name(expected_clock_class) : | |
294 | NULL); | |
295 | goto end; | |
296 | } | |
297 | } | |
298 | ||
0b9ce69f JG |
299 | event_id = g_new(int64_t, 1); |
300 | if (!event_id) { | |
d2f71f12 | 301 | BT_LOGE_STR("Failed to allocate one int64_t."); |
0b9ce69f JG |
302 | ret = -1; |
303 | goto end; | |
304 | } | |
305 | ||
11b0cdc8 JG |
306 | /* Check for duplicate event classes */ |
307 | struct search_query query = { .value = event_class, .found = 0 }; | |
0d23acbe PP |
308 | g_ptr_array_foreach(stream_class->event_classes, event_class_exists, |
309 | &query); | |
11b0cdc8 | 310 | if (query.found) { |
d2f71f12 | 311 | BT_LOGW_STR("Another event class part of this stream class has the same ID."); |
11b0cdc8 JG |
312 | ret = -1; |
313 | goto end; | |
314 | } | |
315 | ||
3dca2276 | 316 | old_stream_class = bt_event_class_common_borrow_stream_class(event_class); |
e6a8e8e4 JG |
317 | if (old_stream_class) { |
318 | /* Event class is already associated to a stream class. */ | |
d2f71f12 PP |
319 | BT_LOGW("Event class is already part of another stream class: " |
320 | "event-class-stream-class-addr=%p, " | |
321 | "event-class-stream-class-name=\"%s\", " | |
322 | "event-class-stream-class-id=%" PRId64, | |
323 | old_stream_class, | |
3dca2276 PP |
324 | bt_stream_class_common_get_name(old_stream_class), |
325 | bt_stream_class_common_get_id(old_stream_class)); | |
e6a8e8e4 JG |
326 | ret = -1; |
327 | goto end; | |
328 | } | |
329 | ||
e6a8e8e4 | 330 | if (trace) { |
09840de5 PP |
331 | /* |
332 | * If the stream class is associated with a trace, then | |
333 | * both those objects are frozen. Also, this event class | |
334 | * is about to be frozen. | |
335 | * | |
336 | * Therefore the event class must be validated here. | |
337 | * The trace and stream class should be valid at this | |
338 | * point. | |
339 | */ | |
f6ccaed9 PP |
340 | BT_ASSERT(trace->valid); |
341 | BT_ASSERT(stream_class->valid); | |
09840de5 | 342 | packet_header_type = |
094ff7c0 | 343 | bt_trace_common_borrow_packet_header_field_type(trace); |
09840de5 | 344 | packet_context_type = |
094ff7c0 | 345 | bt_stream_class_common_borrow_packet_context_field_type( |
09840de5 PP |
346 | stream_class); |
347 | event_header_type = | |
094ff7c0 | 348 | bt_stream_class_common_borrow_event_header_field_type( |
3dca2276 | 349 | stream_class); |
09840de5 | 350 | stream_event_ctx_type = |
094ff7c0 | 351 | bt_stream_class_common_borrow_event_context_field_type( |
09840de5 PP |
352 | stream_class); |
353 | event_context_type = | |
094ff7c0 PP |
354 | bt_event_class_common_borrow_context_field_type( |
355 | event_class); | |
09840de5 | 356 | event_payload_type = |
094ff7c0 PP |
357 | bt_event_class_common_borrow_payload_field_type( |
358 | event_class); | |
50842bdc | 359 | ret = bt_validate_class_types( |
09840de5 PP |
360 | trace->environment, packet_header_type, |
361 | packet_context_type, event_header_type, | |
362 | stream_event_ctx_type, event_context_type, | |
363 | event_payload_type, trace->valid, | |
364 | stream_class->valid, event_class->valid, | |
3dca2276 PP |
365 | &validation_output, validation_flags, |
366 | copy_field_type_func); | |
09840de5 | 367 | |
26079216 | 368 | if (ret) { |
09840de5 PP |
369 | /* |
370 | * This means something went wrong during the | |
371 | * validation process, not that the objects are | |
372 | * invalid. | |
373 | */ | |
d2f71f12 | 374 | BT_LOGE("Failed to validate event class: ret=%d", ret); |
09840de5 PP |
375 | goto end; |
376 | } | |
377 | ||
378 | if ((validation_output.valid_flags & validation_flags) != | |
379 | validation_flags) { | |
380 | /* Invalid event class */ | |
66871d36 | 381 | BT_LOGW("Invalid trace, stream class, or event class: " |
d2f71f12 PP |
382 | "valid-flags=0x%x", |
383 | validation_output.valid_flags); | |
09840de5 | 384 | ret = -1; |
26079216 JG |
385 | goto end; |
386 | } | |
387 | } | |
388 | ||
09840de5 | 389 | /* Only set an event ID if none was explicitly set before */ |
3dca2276 | 390 | *event_id = bt_event_class_common_get_id(event_class); |
24626e8b | 391 | if (*event_id < 0) { |
d2f71f12 PP |
392 | BT_LOGV("Event class has no ID: automatically setting it: " |
393 | "id=%" PRId64, stream_class->next_event_id); | |
394 | ||
3dca2276 | 395 | if (bt_event_class_common_set_id(event_class, |
d2f71f12 PP |
396 | stream_class->next_event_id)) { |
397 | BT_LOGE("Cannot set event class's ID: id=%" PRId64, | |
398 | stream_class->next_event_id); | |
2f100782 JG |
399 | ret = -1; |
400 | goto end; | |
401 | } | |
d2f71f12 | 402 | stream_class->next_event_id++; |
0b9ce69f | 403 | *event_id = stream_class->next_event_id; |
2f100782 JG |
404 | } |
405 | ||
e6a8e8e4 | 406 | bt_object_set_parent(event_class, stream_class); |
09840de5 PP |
407 | |
408 | if (trace) { | |
409 | /* | |
410 | * At this point we know that the function will be | |
411 | * successful. Therefore we can replace the event | |
412 | * class's field types with what's in the validation | |
413 | * output structure and mark this event class as valid. | |
414 | */ | |
50842bdc | 415 | bt_validation_replace_types(NULL, NULL, event_class, |
09840de5 PP |
416 | &validation_output, validation_flags); |
417 | event_class->valid = 1; | |
418 | ||
419 | /* | |
420 | * Put what was not moved in | |
50842bdc | 421 | * bt_validation_replace_types(). |
09840de5 | 422 | */ |
50842bdc | 423 | bt_validation_output_put_types(&validation_output); |
09840de5 PP |
424 | } |
425 | ||
426 | /* Add to the event classes of the stream class */ | |
11b0cdc8 | 427 | g_ptr_array_add(stream_class->event_classes, event_class); |
0b9ce69f JG |
428 | g_hash_table_insert(stream_class->event_classes_ht, event_id, |
429 | event_class); | |
430 | event_id = NULL; | |
09840de5 PP |
431 | |
432 | /* Freeze the event class */ | |
3dca2276 | 433 | bt_event_class_common_freeze(event_class); |
5ca83563 | 434 | |
2a3ced3c PP |
435 | /* |
436 | * It is safe to set the stream class's unique clock class | |
437 | * now if the stream class is frozen. | |
438 | */ | |
439 | if (stream_class->frozen && expected_clock_class) { | |
f6ccaed9 | 440 | BT_ASSERT(!stream_class->clock_class || |
2a3ced3c PP |
441 | stream_class->clock_class == expected_clock_class); |
442 | BT_MOVE(stream_class->clock_class, expected_clock_class); | |
443 | } | |
444 | ||
d2f71f12 PP |
445 | BT_LOGD("Added event class to stream class: " |
446 | "stream-class-addr=%p, stream-class-name=\"%s\", " | |
447 | "stream-class-id=%" PRId64 ", event-class-addr=%p, " | |
448 | "event-class-name=\"%s\", event-class-id=%" PRId64, | |
3dca2276 PP |
449 | stream_class, bt_stream_class_common_get_name(stream_class), |
450 | bt_stream_class_common_get_id(stream_class), | |
d2f71f12 | 451 | event_class, |
3dca2276 PP |
452 | bt_event_class_common_get_name(event_class), |
453 | bt_event_class_common_get_id(event_class)); | |
d2f71f12 | 454 | |
11b0cdc8 | 455 | end: |
50842bdc | 456 | bt_validation_output_put_types(&validation_output); |
2a3ced3c | 457 | bt_put(expected_clock_class); |
0b9ce69f | 458 | g_free(event_id); |
11b0cdc8 JG |
459 | return ret; |
460 | } | |
461 | ||
3dca2276 PP |
462 | int bt_stream_class_add_event_class( |
463 | struct bt_stream_class *stream_class, | |
464 | struct bt_event_class *event_class) | |
69dc4535 | 465 | { |
3dca2276 PP |
466 | struct bt_trace *trace; |
467 | int ret = 0; | |
69dc4535 JG |
468 | |
469 | if (!stream_class) { | |
3dca2276 PP |
470 | BT_LOGW("Invalid parameter: stream class is NULL: " |
471 | "stream-class-addr=%p", stream_class); | |
472 | ret = -1; | |
473 | goto end; | |
474 | } | |
475 | ||
476 | trace = BT_FROM_COMMON(bt_stream_class_common_borrow_trace( | |
477 | BT_TO_COMMON(stream_class))); | |
478 | if (trace && trace->is_static) { | |
479 | BT_LOGW("Invalid parameter: stream class's trace is static: " | |
480 | "trace-addr=%p, trace-name=\"%s\"", | |
481 | trace, bt_trace_get_name(trace)); | |
482 | ret = -1; | |
483 | goto end; | |
484 | } | |
485 | ||
486 | ret = bt_stream_class_common_add_event_class( | |
487 | BT_TO_COMMON(stream_class), BT_TO_COMMON(event_class), | |
488 | (bt_validation_flag_copy_field_type_func) bt_field_type_copy); | |
489 | if (ret) { | |
69dc4535 JG |
490 | goto end; |
491 | } | |
492 | ||
3dca2276 PP |
493 | /* Notifiy listeners of the trace's schema modification. */ |
494 | if (trace) { | |
495 | struct bt_visitor_object obj = { .object = event_class, | |
496 | .type = BT_VISITOR_OBJECT_TYPE_EVENT_CLASS }; | |
497 | ||
498 | (void) bt_trace_object_modification(&obj, trace); | |
499 | } | |
500 | ||
69dc4535 JG |
501 | end: |
502 | return ret; | |
503 | } | |
504 | ||
3dca2276 PP |
505 | int64_t bt_stream_class_get_event_class_count( |
506 | struct bt_stream_class *stream_class) | |
507 | { | |
508 | return bt_stream_class_common_get_event_class_count( | |
509 | BT_TO_COMMON(stream_class)); | |
510 | } | |
511 | ||
094ff7c0 | 512 | struct bt_event_class *bt_stream_class_borrow_event_class_by_index( |
50842bdc | 513 | struct bt_stream_class *stream_class, uint64_t index) |
69dc4535 | 514 | { |
094ff7c0 | 515 | return BT_FROM_COMMON(bt_stream_class_common_borrow_event_class_by_index( |
3dca2276 | 516 | BT_TO_COMMON(stream_class), index)); |
69dc4535 JG |
517 | } |
518 | ||
094ff7c0 | 519 | struct bt_event_class *bt_stream_class_borrow_event_class_by_id( |
50842bdc | 520 | struct bt_stream_class *stream_class, uint64_t id) |
0863f950 | 521 | { |
094ff7c0 | 522 | return BT_FROM_COMMON(bt_stream_class_common_borrow_event_class_by_id( |
3dca2276 | 523 | BT_TO_COMMON(stream_class), id)); |
0863f950 PP |
524 | } |
525 | ||
094ff7c0 | 526 | struct bt_field_type *bt_stream_class_borrow_packet_context_field_type( |
50842bdc | 527 | struct bt_stream_class *stream_class) |
12c8a1a3 | 528 | { |
094ff7c0 | 529 | return BT_FROM_COMMON(bt_stream_class_common_borrow_packet_context_field_type( |
3dca2276 | 530 | BT_TO_COMMON(stream_class))); |
12c8a1a3 JG |
531 | } |
532 | ||
3dca2276 | 533 | int bt_stream_class_set_packet_context_field_type( |
50842bdc PP |
534 | struct bt_stream_class *stream_class, |
535 | struct bt_field_type *packet_context_type) | |
12c8a1a3 | 536 | { |
3dca2276 PP |
537 | return bt_stream_class_common_set_packet_context_field_type( |
538 | BT_TO_COMMON(stream_class), (void *) packet_context_type); | |
12c8a1a3 JG |
539 | } |
540 | ||
094ff7c0 | 541 | struct bt_field_type *bt_stream_class_borrow_event_header_field_type( |
50842bdc | 542 | struct bt_stream_class *stream_class) |
662e778c | 543 | { |
094ff7c0 | 544 | return BT_FROM_COMMON(bt_stream_class_common_borrow_event_header_field_type( |
3dca2276 | 545 | BT_TO_COMMON(stream_class))); |
662e778c JG |
546 | } |
547 | ||
3dca2276 | 548 | int bt_stream_class_set_event_header_field_type( |
50842bdc PP |
549 | struct bt_stream_class *stream_class, |
550 | struct bt_field_type *event_header_type) | |
662e778c | 551 | { |
3dca2276 PP |
552 | return bt_stream_class_common_set_event_header_field_type( |
553 | BT_TO_COMMON(stream_class), (void *) event_header_type); | |
662e778c JG |
554 | } |
555 | ||
094ff7c0 | 556 | struct bt_field_type *bt_stream_class_borrow_event_context_field_type( |
50842bdc | 557 | struct bt_stream_class *stream_class) |
af181248 | 558 | { |
094ff7c0 | 559 | return BT_FROM_COMMON(bt_stream_class_common_borrow_event_context_field_type( |
3dca2276 | 560 | BT_TO_COMMON(stream_class))); |
af181248 JG |
561 | } |
562 | ||
3dca2276 | 563 | int bt_stream_class_set_event_context_field_type( |
50842bdc PP |
564 | struct bt_stream_class *stream_class, |
565 | struct bt_field_type *event_context_type) | |
af181248 | 566 | { |
3dca2276 PP |
567 | return bt_stream_class_common_set_event_context_field_type( |
568 | BT_TO_COMMON(stream_class), (void *) event_context_type); | |
11b0cdc8 JG |
569 | } |
570 | ||
8bf65fbd | 571 | static |
544d0515 | 572 | int64_t get_event_class_count(void *element) |
8bf65fbd | 573 | { |
50842bdc PP |
574 | return bt_stream_class_get_event_class_count( |
575 | (struct bt_stream_class *) element); | |
8bf65fbd JG |
576 | } |
577 | ||
578 | static | |
579 | void *get_event_class(void *element, int i) | |
580 | { | |
50842bdc PP |
581 | return bt_stream_class_get_event_class_by_index( |
582 | (struct bt_stream_class *) element, i); | |
8bf65fbd JG |
583 | } |
584 | ||
585 | static | |
50842bdc | 586 | int visit_event_class(void *object, bt_visitor visitor,void *data) |
8bf65fbd | 587 | { |
3dca2276 PP |
588 | struct bt_visitor_object obj = { |
589 | .object = object, | |
590 | .type = BT_VISITOR_OBJECT_TYPE_EVENT_CLASS | |
591 | }; | |
8bf65fbd | 592 | |
d9a13d86 | 593 | return visitor(&obj, data); |
8bf65fbd JG |
594 | } |
595 | ||
3dca2276 PP |
596 | BT_HIDDEN |
597 | int bt_stream_class_common_visit(struct bt_stream_class_common *stream_class, | |
50842bdc | 598 | bt_visitor visitor, void *data) |
8bf65fbd JG |
599 | { |
600 | int ret; | |
3dca2276 PP |
601 | struct bt_visitor_object obj = { |
602 | .object = stream_class, | |
603 | .type = BT_VISITOR_OBJECT_TYPE_STREAM_CLASS | |
604 | }; | |
8bf65fbd JG |
605 | |
606 | if (!stream_class || !visitor) { | |
d2f71f12 PP |
607 | BT_LOGW("Invalid parameter: stream class or visitor is NULL: " |
608 | "stream-class-addr=%p, visitor=%p", | |
609 | stream_class, visitor); | |
8bf65fbd JG |
610 | ret = -1; |
611 | goto end; | |
612 | } | |
613 | ||
d9a13d86 | 614 | ret = visitor_helper(&obj, get_event_class_count, |
8bf65fbd JG |
615 | get_event_class, |
616 | visit_event_class, visitor, data); | |
d2f71f12 | 617 | BT_LOGV("visitor_helper() returned: ret=%d", ret); |
3dca2276 | 618 | |
8bf65fbd JG |
619 | end: |
620 | return ret; | |
621 | } | |
622 | ||
3dca2276 PP |
623 | int bt_stream_class_visit(struct bt_stream_class *stream_class, |
624 | bt_visitor visitor, void *data) | |
625 | { | |
626 | return bt_stream_class_common_visit(BT_FROM_COMMON(stream_class), | |
627 | visitor, data); | |
628 | } | |
629 | ||
11b0cdc8 | 630 | BT_HIDDEN |
3dca2276 | 631 | void bt_stream_class_common_freeze(struct bt_stream_class_common *stream_class) |
11b0cdc8 | 632 | { |
d2f71f12 | 633 | if (!stream_class || stream_class->frozen) { |
11b0cdc8 JG |
634 | return; |
635 | } | |
636 | ||
d2f71f12 | 637 | BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64, |
3dca2276 PP |
638 | stream_class, bt_stream_class_common_get_name(stream_class), |
639 | bt_stream_class_common_get_id(stream_class)); | |
11b0cdc8 | 640 | stream_class->frozen = 1; |
3dca2276 PP |
641 | bt_field_type_common_freeze(stream_class->event_header_field_type); |
642 | bt_field_type_common_freeze(stream_class->packet_context_field_type); | |
643 | bt_field_type_common_freeze(stream_class->event_context_field_type); | |
644 | bt_clock_class_freeze(stream_class->clock_class); | |
11b0cdc8 JG |
645 | } |
646 | ||
3dca2276 | 647 | void bt_stream_class_freeze(struct bt_stream_class *stream_class) |
e011d2c1 | 648 | { |
3dca2276 | 649 | bt_stream_class_common_freeze(BT_TO_COMMON(stream_class)); |
11b0cdc8 | 650 | } |
2a3ced3c PP |
651 | |
652 | BT_HIDDEN | |
3dca2276 PP |
653 | int bt_stream_class_common_validate_single_clock_class( |
654 | struct bt_stream_class_common *stream_class, | |
2a3ced3c PP |
655 | struct bt_clock_class **expected_clock_class) |
656 | { | |
657 | int ret; | |
658 | uint64_t i; | |
659 | ||
f6ccaed9 PP |
660 | BT_ASSERT(stream_class); |
661 | BT_ASSERT(expected_clock_class); | |
3dca2276 PP |
662 | ret = bt_field_type_common_validate_single_clock_class( |
663 | stream_class->packet_context_field_type, | |
2a3ced3c PP |
664 | expected_clock_class); |
665 | if (ret) { | |
666 | BT_LOGW("Stream class's packet context field type " | |
667 | "is not recursively mapped to the " | |
668 | "expected clock class: " | |
669 | "stream-class-addr=%p, " | |
670 | "stream-class-name=\"%s\", " | |
671 | "stream-class-id=%" PRId64 ", " | |
672 | "ft-addr=%p", | |
673 | stream_class, | |
3dca2276 | 674 | bt_stream_class_common_get_name(stream_class), |
2a3ced3c | 675 | stream_class->id, |
3dca2276 | 676 | stream_class->packet_context_field_type); |
2a3ced3c PP |
677 | goto end; |
678 | } | |
679 | ||
3dca2276 PP |
680 | ret = bt_field_type_common_validate_single_clock_class( |
681 | stream_class->event_header_field_type, | |
2a3ced3c PP |
682 | expected_clock_class); |
683 | if (ret) { | |
684 | BT_LOGW("Stream class's event header field type " | |
685 | "is not recursively mapped to the " | |
686 | "expected clock class: " | |
687 | "stream-class-addr=%p, " | |
688 | "stream-class-name=\"%s\", " | |
689 | "stream-class-id=%" PRId64 ", " | |
690 | "ft-addr=%p", | |
691 | stream_class, | |
3dca2276 | 692 | bt_stream_class_common_get_name(stream_class), |
2a3ced3c | 693 | stream_class->id, |
3dca2276 | 694 | stream_class->event_header_field_type); |
2a3ced3c PP |
695 | goto end; |
696 | } | |
697 | ||
3dca2276 PP |
698 | ret = bt_field_type_common_validate_single_clock_class( |
699 | stream_class->event_context_field_type, | |
2a3ced3c PP |
700 | expected_clock_class); |
701 | if (ret) { | |
702 | BT_LOGW("Stream class's event context field type " | |
703 | "is not recursively mapped to the " | |
704 | "expected clock class: " | |
705 | "stream-class-addr=%p, " | |
706 | "stream-class-name=\"%s\", " | |
707 | "stream-class-id=%" PRId64 ", " | |
708 | "ft-addr=%p", | |
709 | stream_class, | |
3dca2276 | 710 | bt_stream_class_common_get_name(stream_class), |
2a3ced3c | 711 | stream_class->id, |
3dca2276 | 712 | stream_class->event_context_field_type); |
2a3ced3c PP |
713 | goto end; |
714 | } | |
715 | ||
716 | for (i = 0; i < stream_class->event_classes->len; i++) { | |
3dca2276 | 717 | struct bt_event_class_common *event_class = |
2a3ced3c PP |
718 | g_ptr_array_index(stream_class->event_classes, i); |
719 | ||
f6ccaed9 | 720 | BT_ASSERT(event_class); |
3dca2276 PP |
721 | ret = bt_event_class_common_validate_single_clock_class( |
722 | event_class, expected_clock_class); | |
2a3ced3c PP |
723 | if (ret) { |
724 | BT_LOGW("Stream class's event class contains a " | |
725 | "field type which is not recursively mapped to " | |
726 | "the expected clock class: " | |
727 | "stream-class-addr=%p, " | |
728 | "stream-class-name=\"%s\", " | |
729 | "stream-class-id=%" PRId64, | |
730 | stream_class, | |
3dca2276 | 731 | bt_stream_class_common_get_name(stream_class), |
2a3ced3c PP |
732 | stream_class->id); |
733 | goto end; | |
734 | } | |
735 | } | |
736 | ||
737 | end: | |
738 | return ret; | |
739 | } |