tests: Use `--no-wait` when destroying sessions in relayd-grouping
[lttng-tools.git] / src / common / event-field-value.cpp
1 /*
2 * event-field-value.c
3 *
4 * Linux Trace Toolkit Control Library
5 *
6 * Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
7 *
8 * SPDX-License-Identifier: LGPL-2.1-only
9 *
10 */
11
12 #define _LGPL_SOURCE
13 #include <common/error.hpp>
14 #include <common/macros.hpp>
15
16 #include <lttng/event-field-value-internal.hpp>
17
18 #include <stdbool.h>
19 #include <stddef.h>
20
21 static struct lttng_event_field_value *
22 create_empty_field_val(enum lttng_event_field_value_type type, size_t size)
23 {
24 struct lttng_event_field_value *field_val;
25
26 field_val = zmalloc<lttng_event_field_value>(size);
27 if (!field_val) {
28 goto end;
29 }
30
31 field_val->type = type;
32
33 end:
34 return field_val;
35 }
36
37 struct lttng_event_field_value *lttng_event_field_value_uint_create(uint64_t val)
38 {
39 struct lttng_event_field_value_uint *field_val;
40
41 field_val = lttng::utils::container_of(
42 create_empty_field_val(LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT,
43 sizeof(*field_val)),
44 &lttng_event_field_value_uint::parent);
45 if (!field_val) {
46 goto error;
47 }
48
49 field_val->val = val;
50 goto end;
51
52 error:
53 lttng_event_field_value_destroy(&field_val->parent);
54
55 end:
56 return &field_val->parent;
57 }
58
59 struct lttng_event_field_value *lttng_event_field_value_int_create(int64_t val)
60 {
61 struct lttng_event_field_value_int *field_val;
62
63 field_val = lttng::utils::container_of(
64 create_empty_field_val(LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT, sizeof(*field_val)),
65 &lttng_event_field_value_int::parent);
66 if (!field_val) {
67 goto error;
68 }
69
70 field_val->val = val;
71 goto end;
72
73 error:
74 lttng_event_field_value_destroy(&field_val->parent);
75
76 end:
77 return &field_val->parent;
78 }
79
80 static struct lttng_event_field_value_enum *
81 create_enum_field_val(enum lttng_event_field_value_type type, size_t size)
82 {
83 struct lttng_event_field_value_enum *field_val;
84
85 field_val = lttng::utils::container_of(create_empty_field_val(type, size),
86 &lttng_event_field_value_enum::parent);
87 if (!field_val) {
88 goto error;
89 }
90
91 lttng_dynamic_pointer_array_init(&field_val->labels, free);
92 goto end;
93
94 error:
95 lttng_event_field_value_destroy(&field_val->parent);
96
97 end:
98 return field_val;
99 }
100
101 struct lttng_event_field_value *lttng_event_field_value_enum_uint_create(uint64_t val)
102 {
103 struct lttng_event_field_value_enum_uint *field_val;
104
105 field_val = lttng::utils::container_of(
106 create_enum_field_val(LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM,
107 sizeof(*field_val)),
108 &lttng_event_field_value_enum_uint::parent);
109 if (!field_val) {
110 goto error;
111 }
112
113 field_val->val = val;
114 goto end;
115
116 error:
117 lttng_event_field_value_destroy(&field_val->parent.parent);
118
119 end:
120 return &field_val->parent.parent;
121 }
122
123 struct lttng_event_field_value *lttng_event_field_value_enum_int_create(int64_t val)
124 {
125 struct lttng_event_field_value_enum_int *field_val;
126
127 field_val = lttng::utils::container_of(
128 create_enum_field_val(LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM, sizeof(*field_val)),
129 &lttng_event_field_value_enum_int::parent);
130 if (!field_val) {
131 goto error;
132 }
133
134 field_val->val = val;
135 goto end;
136
137 error:
138 lttng_event_field_value_destroy(&field_val->parent.parent);
139
140 end:
141 return &field_val->parent.parent;
142 }
143
144 struct lttng_event_field_value *lttng_event_field_value_real_create(double val)
145 {
146 struct lttng_event_field_value_real *field_val = lttng::utils::container_of(
147 create_empty_field_val(LTTNG_EVENT_FIELD_VALUE_TYPE_REAL, sizeof(*field_val)),
148 &lttng_event_field_value_real::parent);
149
150 if (!field_val) {
151 goto error;
152 }
153
154 field_val->val = val;
155 goto end;
156
157 error:
158 lttng_event_field_value_destroy(&field_val->parent);
159
160 end:
161 return &field_val->parent;
162 }
163
164 struct lttng_event_field_value *lttng_event_field_value_string_create_with_size(const char *val,
165 size_t size)
166 {
167 struct lttng_event_field_value_string *field_val = lttng::utils::container_of(
168 create_empty_field_val(LTTNG_EVENT_FIELD_VALUE_TYPE_STRING, sizeof(*field_val)),
169 &lttng_event_field_value_string::parent);
170
171 if (!field_val) {
172 goto error;
173 }
174
175 if (size) {
176 LTTNG_ASSERT(val);
177 field_val->val = strndup(val, size);
178 } else {
179 /*
180 * User code do not expect a NULL string pointer. Populate with
181 * an empty string when length is 0.
182 */
183 field_val->val = strdup("");
184 }
185 if (!field_val->val) {
186 goto error;
187 }
188
189 goto end;
190
191 error:
192 lttng_event_field_value_destroy(&field_val->parent);
193
194 end:
195 return &field_val->parent;
196 }
197
198 struct lttng_event_field_value *lttng_event_field_value_string_create(const char *val)
199 {
200 LTTNG_ASSERT(val);
201 return lttng_event_field_value_string_create_with_size(val, strlen(val));
202 }
203
204 static void destroy_field_val(void *field_val)
205 {
206 lttng_event_field_value_destroy((lttng_event_field_value *) field_val);
207 }
208
209 struct lttng_event_field_value *lttng_event_field_value_array_create()
210 {
211 struct lttng_event_field_value_array *field_val = lttng::utils::container_of(
212 create_empty_field_val(LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY, sizeof(*field_val)),
213 &lttng_event_field_value_array::parent);
214
215 if (!field_val) {
216 goto error;
217 }
218
219 lttng_dynamic_pointer_array_init(&field_val->elems, destroy_field_val);
220 goto end;
221
222 error:
223 lttng_event_field_value_destroy(&field_val->parent);
224
225 end:
226 return &field_val->parent;
227 }
228
229 void lttng_event_field_value_destroy(struct lttng_event_field_value *field_val)
230 {
231 if (!field_val) {
232 goto end;
233 }
234
235 switch (field_val->type) {
236 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM:
237 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM:
238 {
239 struct lttng_event_field_value_enum *enum_field_val = lttng::utils::container_of(
240 field_val, &lttng_event_field_value_enum::parent);
241
242 lttng_dynamic_pointer_array_reset(&enum_field_val->labels);
243 break;
244 }
245 case LTTNG_EVENT_FIELD_VALUE_TYPE_STRING:
246 {
247 struct lttng_event_field_value_string *str_field_val = lttng::utils::container_of(
248 field_val, &lttng_event_field_value_string::parent);
249
250 free(str_field_val->val);
251 break;
252 }
253 case LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY:
254 {
255 struct lttng_event_field_value_array *array_field_expr = lttng::utils::container_of(
256 field_val, &lttng_event_field_value_array::parent);
257
258 lttng_dynamic_pointer_array_reset(&array_field_expr->elems);
259 break;
260 }
261 default:
262 break;
263 }
264
265 free(field_val);
266
267 end:
268 return;
269 }
270
271 int lttng_event_field_value_enum_append_label_with_size(struct lttng_event_field_value *field_val,
272 const char *label,
273 size_t size)
274 {
275 int ret;
276 char *new_label;
277
278 LTTNG_ASSERT(field_val);
279 LTTNG_ASSERT(label);
280 new_label = strndup(label, size);
281 if (!new_label) {
282 ret = -1;
283 goto end;
284 }
285
286 ret = lttng_dynamic_pointer_array_add_pointer(
287 &lttng::utils::container_of(field_val, &lttng_event_field_value_enum::parent)
288 ->labels,
289 new_label);
290 if (ret == 0) {
291 new_label = nullptr;
292 }
293
294 end:
295 free(new_label);
296 return ret;
297 }
298
299 int lttng_event_field_value_enum_append_label(struct lttng_event_field_value *field_val,
300 const char *label)
301 {
302 LTTNG_ASSERT(label);
303 return lttng_event_field_value_enum_append_label_with_size(field_val, label, strlen(label));
304 }
305
306 int lttng_event_field_value_array_append(struct lttng_event_field_value *array_field_val,
307 struct lttng_event_field_value *field_val)
308 {
309 LTTNG_ASSERT(array_field_val);
310 LTTNG_ASSERT(field_val);
311 return lttng_dynamic_pointer_array_add_pointer(
312 &lttng::utils::container_of(array_field_val, &lttng_event_field_value_array::parent)
313 ->elems,
314 field_val);
315 }
316
317 int lttng_event_field_value_array_append_unavailable(struct lttng_event_field_value *array_field_val)
318 {
319 LTTNG_ASSERT(array_field_val);
320 return lttng_dynamic_pointer_array_add_pointer(
321 &lttng::utils::container_of(array_field_val, &lttng_event_field_value_array::parent)
322 ->elems,
323 nullptr);
324 }
325
326 enum lttng_event_field_value_type
327 lttng_event_field_value_get_type(const struct lttng_event_field_value *field_val)
328 {
329 enum lttng_event_field_value_type type;
330
331 if (!field_val) {
332 type = LTTNG_EVENT_FIELD_VALUE_TYPE_INVALID;
333 goto end;
334 }
335
336 type = field_val->type;
337
338 end:
339 return type;
340 }
341
342 enum lttng_event_field_value_status
343 lttng_event_field_value_unsigned_int_get_value(const struct lttng_event_field_value *field_val,
344 uint64_t *val)
345 {
346 enum lttng_event_field_value_status status;
347
348 if (!field_val || !val) {
349 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
350 goto end;
351 }
352
353 switch (field_val->type) {
354 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT:
355 *val = lttng::utils::container_of(field_val, &lttng_event_field_value_uint::parent)
356 ->val;
357 break;
358 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM:
359 {
360 const struct lttng_event_field_value_enum *field_val_enum =
361 lttng::utils::container_of(field_val,
362 &lttng_event_field_value_enum::parent);
363 const struct lttng_event_field_value_enum_uint *field_val_enum_uint =
364 lttng::utils::container_of(field_val_enum,
365 &lttng_event_field_value_enum_uint::parent);
366 *val = field_val_enum_uint->val;
367 break;
368 }
369 default:
370 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
371 goto end;
372 }
373
374 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
375
376 end:
377 return status;
378 }
379
380 enum lttng_event_field_value_status
381 lttng_event_field_value_signed_int_get_value(const struct lttng_event_field_value *field_val,
382 int64_t *val)
383 {
384 enum lttng_event_field_value_status status;
385
386 if (!field_val || !val) {
387 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
388 goto end;
389 }
390
391 switch (field_val->type) {
392 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT:
393 *val = lttng::utils::container_of(field_val, &lttng_event_field_value_int::parent)
394 ->val;
395 break;
396 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM:
397 {
398 const struct lttng_event_field_value_enum *field_val_enum =
399 lttng::utils::container_of(field_val,
400 &lttng_event_field_value_enum::parent);
401 const struct lttng_event_field_value_enum_int *field_val_enum_uint =
402 lttng::utils::container_of(field_val_enum,
403 &lttng_event_field_value_enum_int::parent);
404 *val = field_val_enum_uint->val;
405 break;
406 }
407 default:
408 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
409 goto end;
410 }
411
412 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
413
414 end:
415 return status;
416 }
417
418 enum lttng_event_field_value_status
419 lttng_event_field_value_real_get_value(const struct lttng_event_field_value *field_val, double *val)
420 {
421 enum lttng_event_field_value_status status;
422
423 if (!field_val || field_val->type != LTTNG_EVENT_FIELD_VALUE_TYPE_REAL || !val) {
424 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
425 goto end;
426 }
427
428 *val = lttng::utils::container_of(field_val, &lttng_event_field_value_real::parent)->val;
429 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
430
431 end:
432 return status;
433 }
434
435 static bool is_enum_field_val(const struct lttng_event_field_value *field_val)
436 {
437 return field_val->type == LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM ||
438 field_val->type == LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM;
439 }
440
441 enum lttng_event_field_value_status
442 lttng_event_field_value_enum_get_label_count(const struct lttng_event_field_value *field_val,
443 unsigned int *count)
444 {
445 enum lttng_event_field_value_status status;
446
447 if (!field_val || !is_enum_field_val(field_val) || !count) {
448 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
449 goto end;
450 }
451
452 *count = (unsigned int) lttng_dynamic_pointer_array_get_count(
453 &lttng::utils::container_of(field_val, &lttng_event_field_value_enum::parent)
454 ->labels);
455 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
456
457 end:
458 return status;
459 }
460
461 const char *
462 lttng_event_field_value_enum_get_label_at_index(const struct lttng_event_field_value *field_val,
463 unsigned int index)
464 {
465 const char *ret;
466 const struct lttng_event_field_value_enum *enum_field_val;
467
468 if (!field_val || !is_enum_field_val(field_val)) {
469 ret = nullptr;
470 goto end;
471 }
472
473 enum_field_val =
474 lttng::utils::container_of(field_val, &lttng_event_field_value_enum::parent);
475
476 if (index >= lttng_dynamic_pointer_array_get_count(&enum_field_val->labels)) {
477 ret = nullptr;
478 goto end;
479 }
480
481 ret = (const char *) lttng_dynamic_pointer_array_get_pointer(&enum_field_val->labels,
482 index);
483
484 end:
485 return ret;
486 }
487
488 enum lttng_event_field_value_status
489 lttng_event_field_value_string_get_value(const struct lttng_event_field_value *field_val,
490 const char **value)
491 {
492 enum lttng_event_field_value_status status;
493
494 if (!field_val || field_val->type != LTTNG_EVENT_FIELD_VALUE_TYPE_STRING) {
495 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
496 goto end;
497 }
498
499 *value =
500 lttng::utils::container_of(field_val, &lttng_event_field_value_string::parent)->val;
501 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
502
503 end:
504 return status;
505 }
506
507 enum lttng_event_field_value_status
508 lttng_event_field_value_array_get_length(const struct lttng_event_field_value *field_val,
509 unsigned int *length)
510 {
511 enum lttng_event_field_value_status status;
512
513 if (!field_val || field_val->type != LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY || !length) {
514 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
515 goto end;
516 }
517
518 *length = (unsigned int) lttng_dynamic_pointer_array_get_count(
519 &lttng::utils::container_of(field_val, &lttng_event_field_value_array::parent)
520 ->elems);
521 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
522
523 end:
524 return status;
525 }
526
527 enum lttng_event_field_value_status lttng_event_field_value_array_get_element_at_index(
528 const struct lttng_event_field_value *field_val,
529 unsigned int index,
530 const struct lttng_event_field_value **elem_field_val)
531 {
532 enum lttng_event_field_value_status status;
533 const struct lttng_event_field_value_array *array_field_val;
534
535 if (!field_val || field_val->type != LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY ||
536 !elem_field_val) {
537 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
538 goto end;
539 }
540
541 array_field_val =
542 lttng::utils::container_of(field_val, &lttng_event_field_value_array::parent);
543
544 if (index >= lttng_dynamic_pointer_array_get_count(&array_field_val->elems)) {
545 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
546 goto end;
547 }
548
549 *elem_field_val = (lttng_event_field_value *) lttng_dynamic_pointer_array_get_pointer(
550 &array_field_val->elems, index);
551 if (*elem_field_val) {
552 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
553 } else {
554 status = LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE;
555 }
556
557 end:
558 return status;
559 }
This page took 0.052137 seconds and 4 git commands to generate.