Fix: futex wait: handle spurious futex wakeups
[lttng-tools.git] / src / common / event-expr / event-expr.cpp
1 /*
2 * event-expr.c
3 *
4 * Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
5 *
6 * SPDX-License-Identifier: LGPL-2.1-only
7 *
8 */
9
10 #define _LGPL_SOURCE
11 #include <stddef.h>
12
13 #include <common/bytecode/bytecode.hpp>
14 #include <common/error.hpp>
15 #include <common/macros.hpp>
16 #include <common/mi-lttng.hpp>
17 #include <lttng/event-expr-internal.hpp>
18 #include <lttng/event-expr.h>
19 #include <stdio.h>
20
21 enum lttng_event_expr_type lttng_event_expr_get_type(
22 const struct lttng_event_expr *expr)
23 {
24 enum lttng_event_expr_type type;
25
26 if (!expr) {
27 type = LTTNG_EVENT_EXPR_TYPE_INVALID;
28 goto end;
29 }
30
31 type = expr->type;
32
33 end:
34 return type;
35 }
36
37 static
38 struct lttng_event_expr *create_empty_expr(enum lttng_event_expr_type type,
39 size_t size)
40 {
41 struct lttng_event_expr *expr;
42
43 expr = zmalloc<lttng_event_expr>(size);
44 if (!expr) {
45 goto end;
46 }
47
48 expr->type = type;
49
50 end:
51 return expr;
52 }
53
54 static
55 struct lttng_event_expr_field *create_field_event_expr(
56 enum lttng_event_expr_type type,
57 const char *name)
58 {
59 struct lttng_event_expr_field *expr = lttng::utils::container_of(
60 create_empty_expr(type, sizeof(*expr)), &lttng_event_expr_field::parent);
61
62 if (!expr) {
63 goto error;
64 }
65
66 LTTNG_ASSERT(name);
67 expr->name = strdup(name);
68 if (!expr->name) {
69 goto error;
70 }
71
72 goto end;
73
74 error:
75 if (expr) {
76 lttng_event_expr_destroy(&expr->parent);
77 }
78 expr = NULL;
79
80 end:
81 return expr;
82 }
83
84 struct lttng_event_expr *lttng_event_expr_event_payload_field_create(
85 const char *field_name)
86 {
87 struct lttng_event_expr *expr = NULL;
88
89 if (!field_name) {
90 goto end;
91 }
92
93 expr = &create_field_event_expr(
94 LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD,
95 field_name)->parent;
96
97 end:
98 return expr;
99 }
100
101 struct lttng_event_expr *lttng_event_expr_channel_context_field_create(
102 const char *field_name)
103 {
104 struct lttng_event_expr *expr = NULL;
105
106 if (!field_name) {
107 goto end;
108 }
109
110 expr = &create_field_event_expr(
111 LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD,
112 field_name)->parent;
113
114 end:
115 return expr;
116 }
117
118 struct lttng_event_expr *lttng_event_expr_app_specific_context_field_create(
119 const char *provider_name, const char *type_name)
120 {
121 struct lttng_event_expr_app_specific_context_field *expr = NULL;
122 struct lttng_event_expr *ret_parent_expr;
123
124 if (!type_name || !provider_name) {
125 goto error;
126 }
127
128 expr = lttng::utils::container_of(create_empty_expr(
129 LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD,
130 sizeof(*expr)),
131 &lttng_event_expr_app_specific_context_field::parent);
132 if (!expr) {
133 goto error;
134 }
135
136 expr->provider_name = strdup(provider_name);
137 if (!expr->provider_name) {
138 goto error;
139 }
140
141 expr->type_name = strdup(type_name);
142 if (!expr->type_name) {
143 goto error;
144 }
145
146 ret_parent_expr = &expr->parent;
147 goto end;
148
149 error:
150 if (expr) {
151 lttng_event_expr_destroy(&expr->parent);
152 }
153 ret_parent_expr = NULL;
154
155 end:
156 return ret_parent_expr;
157 }
158
159 struct lttng_event_expr *lttng_event_expr_array_field_element_create(
160 struct lttng_event_expr *array_field_expr,
161 unsigned int index)
162 {
163 struct lttng_event_expr_array_field_element *expr = NULL;
164 struct lttng_event_expr *ret_parent_expr;
165
166 /* The parent array field expression must be an l-value */
167 if (!array_field_expr ||
168 !lttng_event_expr_is_lvalue(array_field_expr)) {
169 goto error;
170 }
171
172 expr = lttng::utils::container_of(create_empty_expr(
173 LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT,
174 sizeof(*expr)),
175 &lttng_event_expr_array_field_element::parent);
176 if (!expr) {
177 goto error;
178 }
179
180 expr->array_field_expr = array_field_expr;
181 expr->index = index;
182 ret_parent_expr = &expr->parent;
183 goto end;
184
185 error:
186 ret_parent_expr = NULL;
187
188 end:
189 return ret_parent_expr;
190 }
191
192 const char *lttng_event_expr_event_payload_field_get_name(
193 const struct lttng_event_expr *expr)
194 {
195 const char *ret = NULL;
196
197 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD) {
198 goto end;
199 }
200
201 ret = lttng::utils::container_of(expr,
202 &lttng_event_expr_field::parent)->name;
203
204 end:
205 return ret;
206 }
207
208 const char *lttng_event_expr_channel_context_field_get_name(
209 const struct lttng_event_expr *expr)
210 {
211 const char *ret = NULL;
212
213 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD) {
214 goto end;
215 }
216
217 ret = lttng::utils::container_of(expr,
218 &lttng_event_expr_field::parent)->name;
219
220 end:
221 return ret;
222 }
223
224 const char *lttng_event_expr_app_specific_context_field_get_provider_name(
225 const struct lttng_event_expr *expr)
226 {
227 const char *ret = NULL;
228
229 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD) {
230 goto end;
231 }
232
233 ret = lttng::utils::container_of(expr,
234 &lttng_event_expr_app_specific_context_field::parent)->provider_name;
235
236 end:
237 return ret;
238 }
239
240 const char *lttng_event_expr_app_specific_context_field_get_type_name(
241 const struct lttng_event_expr *expr)
242 {
243 const char *ret = NULL;
244
245 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD) {
246 goto end;
247 }
248
249 ret = lttng::utils::container_of(expr,
250 &lttng_event_expr_app_specific_context_field::parent)->type_name;
251
252 end:
253 return ret;
254 }
255
256 const struct lttng_event_expr *
257 lttng_event_expr_array_field_element_get_parent_expr(
258 const struct lttng_event_expr *expr)
259 {
260 const struct lttng_event_expr *ret = NULL;
261
262 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT) {
263 goto end;
264 }
265
266 ret = lttng::utils::container_of(expr,
267 &lttng_event_expr_array_field_element::parent)->array_field_expr;
268
269 end:
270 return ret;
271 }
272
273 enum lttng_event_expr_status lttng_event_expr_array_field_element_get_index(
274 const struct lttng_event_expr *expr, unsigned int *index)
275 {
276 enum lttng_event_expr_status ret = LTTNG_EVENT_EXPR_STATUS_OK;
277
278 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT ||
279 !index) {
280 ret = LTTNG_EVENT_EXPR_STATUS_INVALID;
281 goto end;
282 }
283
284 *index = lttng::utils::container_of(expr,
285 &lttng_event_expr_array_field_element::parent)->index;
286
287 end:
288 return ret;
289 }
290
291 bool lttng_event_expr_is_equal(const struct lttng_event_expr *expr_a,
292 const struct lttng_event_expr *expr_b)
293 {
294 bool is_equal = true;
295
296 if (!expr_a && !expr_b) {
297 /* Both `NULL`: equal */
298 goto end;
299 }
300
301 if (!expr_a || !expr_b) {
302 /* Only one `NULL`: not equal */
303 goto not_equal;
304 }
305
306 if (expr_a->type != expr_b->type) {
307 /* Different types: not equal */
308 goto not_equal;
309 }
310
311 switch (expr_a->type) {
312 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
313 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
314 {
315 const struct lttng_event_expr_field *field_expr_a =
316 lttng::utils::container_of(expr_a,
317 &lttng_event_expr_field::parent);
318 const struct lttng_event_expr_field *field_expr_b =
319 lttng::utils::container_of(expr_b,
320 &lttng_event_expr_field::parent);
321
322 if (strcmp(field_expr_a->name, field_expr_b->name) != 0) {
323 goto not_equal;
324 }
325
326 break;
327 }
328 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
329 {
330 const struct lttng_event_expr_app_specific_context_field *field_expr_a =
331 lttng::utils::container_of(expr_a,
332 &lttng_event_expr_app_specific_context_field::parent);
333 const struct lttng_event_expr_app_specific_context_field *field_expr_b =
334 lttng::utils::container_of(expr_b,
335 &lttng_event_expr_app_specific_context_field::parent);
336
337 if (strcmp(field_expr_a->provider_name,
338 field_expr_b->provider_name) != 0) {
339 goto not_equal;
340 }
341
342 if (strcmp(field_expr_a->type_name,
343 field_expr_b->type_name) != 0) {
344 goto not_equal;
345 }
346
347 break;
348 }
349 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
350 {
351 const struct lttng_event_expr_array_field_element *elem_expr_a =
352 lttng::utils::container_of(expr_a,
353 &lttng_event_expr_array_field_element::parent);
354 const struct lttng_event_expr_array_field_element *elem_expr_b =
355 lttng::utils::container_of(expr_b,
356 &lttng_event_expr_array_field_element::parent);
357
358 if (!lttng_event_expr_is_equal(elem_expr_a->array_field_expr,
359 elem_expr_b->array_field_expr)) {
360 goto not_equal;
361 }
362
363 if (elem_expr_a->index != elem_expr_b->index) {
364 goto not_equal;
365 }
366
367 break;
368 }
369 default:
370 break;
371 }
372
373 goto end;
374
375 not_equal:
376 is_equal = false;
377
378 end:
379 return is_equal;
380 }
381
382 void lttng_event_expr_destroy(struct lttng_event_expr *expr)
383 {
384 if (!expr) {
385 goto end;
386 }
387
388 switch (expr->type) {
389 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
390 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
391 {
392 struct lttng_event_expr_field *field_expr =
393 lttng::utils::container_of(expr,
394 &lttng_event_expr_field::parent);
395
396 free(field_expr->name);
397 break;
398 }
399 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
400 {
401 struct lttng_event_expr_app_specific_context_field *field_expr =
402 lttng::utils::container_of(expr,
403 &lttng_event_expr_app_specific_context_field::parent);
404
405 free(field_expr->provider_name);
406 free(field_expr->type_name);
407 break;
408 }
409 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
410 {
411 struct lttng_event_expr_array_field_element *elem_expr =
412 lttng::utils::container_of(expr,
413 &lttng_event_expr_array_field_element::parent);
414
415 lttng_event_expr_destroy(elem_expr->array_field_expr);
416 break;
417 }
418 default:
419 break;
420 }
421
422 free(expr);
423
424 end:
425 return;
426 }
427
428 static int event_expr_to_bytecode_recursive(const struct lttng_event_expr *expr,
429 struct lttng_bytecode_alloc **bytecode,
430 struct lttng_bytecode_alloc **bytecode_reloc)
431 {
432 int status;
433 enum lttng_event_expr_status event_expr_status;
434
435 switch (lttng_event_expr_get_type(expr)) {
436 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
437 {
438 const char *name;
439
440 status = bytecode_push_get_payload_root(bytecode);
441 if (status) {
442 ERR("Failed to get payload root from bytecode");
443 goto end;
444 }
445
446 name = lttng_event_expr_event_payload_field_get_name(expr);
447 if (!name) {
448 ERR("Failed to get payload field name from event expression");
449 status = -1;
450 goto end;
451 }
452
453 status = bytecode_push_get_symbol(
454 bytecode, bytecode_reloc, name);
455 if (status) {
456 ERR("Failed to push 'get symbol %s' in bytecode", name);
457 goto end;
458 }
459
460 break;
461 }
462 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
463 {
464 const char *name;
465
466 status = bytecode_push_get_context_root(bytecode);
467 if (status) {
468 ERR("Failed to get context root from bytecode");
469 goto end;
470 }
471
472 name = lttng_event_expr_channel_context_field_get_name(expr);
473 if (!name) {
474 ERR("Failed to get channel context field name from event expression");
475 status = -1;
476 goto end;
477 }
478
479 status = bytecode_push_get_symbol(
480 bytecode, bytecode_reloc, name);
481 if (status) {
482 ERR("Failed to push 'get symbol %s' in bytecode", name);
483 goto end;
484 }
485
486 break;
487 }
488 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
489 {
490 int ret;
491 char *name = NULL;
492 const char *provider_name, *type_name;
493
494 status = bytecode_push_get_app_context_root(bytecode);
495 if (status) {
496 ERR("Failed to get application context root from bytecode");
497 goto end;
498 }
499
500 provider_name = lttng_event_expr_app_specific_context_field_get_provider_name(
501 expr);
502 if (!provider_name) {
503 ERR("Failed to get application context provider name from event expression");
504 status = -1;
505 goto end;
506 }
507
508 type_name = lttng_event_expr_app_specific_context_field_get_type_name(
509 expr);
510 if (!type_name) {
511 ERR("Failed to get application context type name from event expression");
512 status = -1;
513 goto end;
514 }
515
516 /*
517 * Reconstitute the app context field name from its two parts.
518 */
519 ret = asprintf(&name, "%s:%s", provider_name, type_name);
520 if (ret < 0) {
521 PERROR("Failed to format application specific context: provider_name = '%s', type_name = '%s'",
522 provider_name, type_name);
523 status = -1;
524 goto end;
525 }
526
527 status = bytecode_push_get_symbol(
528 bytecode, bytecode_reloc, name);
529 free(name);
530 if (status) {
531 ERR("Failed to push 'get symbol %s:%s' in bytecode",
532 provider_name, type_name);
533 goto end;
534 }
535
536 break;
537 }
538 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
539 {
540 unsigned int index;
541 const struct lttng_event_expr *parent;
542
543 parent = lttng_event_expr_array_field_element_get_parent_expr(
544 expr);
545 if (!parent) {
546 ERR("Failed to get parent expression from array event expression");
547 status = -1;
548 goto end;
549 }
550
551 status = event_expr_to_bytecode_recursive(
552 parent, bytecode, bytecode_reloc);
553 if (status) {
554 goto end;
555 }
556
557 event_expr_status =
558 lttng_event_expr_array_field_element_get_index(
559 expr, &index);
560 if (event_expr_status != LTTNG_EVENT_EXPR_STATUS_OK) {
561 ERR("Failed to get array field element index from event expression");
562 status = -1;
563 goto end;
564 }
565
566 status = bytecode_push_get_index_u64(bytecode, index);
567 if (status) {
568 ERR("Failed to push 'get index %u' in bytecode", index);
569 goto end;
570 }
571
572 break;
573 }
574 default:
575 abort();
576 }
577
578 status = 0;
579 end:
580 return status;
581 }
582
583 int lttng_event_expr_to_bytecode(const struct lttng_event_expr *expr,
584 struct lttng_bytecode **bytecode_out)
585 {
586 int status;
587 struct return_op ret_insn;
588 struct lttng_bytecode_alloc *bytecode = NULL;
589 struct lttng_bytecode_alloc *bytecode_reloc = NULL;
590
591 status = bytecode_init(&bytecode);
592 if (status) {
593 ERR("Failed to initialize bytecode");
594 goto end;
595 }
596
597 status = bytecode_init(&bytecode_reloc);
598 if (status) {
599 ERR("Failed to initialize relocation bytecode");
600 goto end;
601 }
602
603 status = event_expr_to_bytecode_recursive(
604 expr, &bytecode, &bytecode_reloc);
605 if (status) {
606 /* Errors already logged. */
607 goto end;
608 }
609
610 ret_insn.op = BYTECODE_OP_RETURN;
611 bytecode_push(&bytecode, &ret_insn, 1, sizeof(ret_insn));
612
613 /* Append symbol table to bytecode. */
614 bytecode->b.reloc_table_offset = bytecode_get_len(&bytecode->b);
615 status = bytecode_push(&bytecode, bytecode_reloc->b.data, 1,
616 bytecode_get_len(&bytecode_reloc->b));
617 if (status) {
618 ERR("Failed to push symbol table to bytecode");
619 goto end;
620 }
621
622 /* Copy the `lttng_bytecode` out of the `lttng_bytecode_alloc`. */
623 *bytecode_out = lttng_bytecode_copy(&bytecode->b);
624 if (!*bytecode_out) {
625 status = -1;
626 goto end;
627 }
628
629 end:
630 if (bytecode) {
631 free(bytecode);
632 }
633
634 if (bytecode_reloc) {
635 free(bytecode_reloc);
636 }
637
638 return status;
639 }
640
641 static
642 enum lttng_error_code lttng_event_expr_event_payload_field_mi_serialize(
643 const struct lttng_event_expr *expression,
644 struct mi_writer *writer)
645 {
646 int ret;
647 enum lttng_error_code ret_code;
648 const char *name = NULL;
649
650 LTTNG_ASSERT(expression);
651 LTTNG_ASSERT(writer);
652 LTTNG_ASSERT(expression->type == LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD);
653
654 name = lttng_event_expr_event_payload_field_get_name(expression);
655 LTTNG_ASSERT(name);
656
657 /* Open event expr payload field element. */
658 ret = mi_lttng_writer_open_element(
659 writer, mi_lttng_element_event_expr_payload_field);
660 if (ret) {
661 goto mi_error;
662 }
663
664 /* Name. */
665 ret = mi_lttng_writer_write_element_string(
666 writer, config_element_name, name);
667 if (ret) {
668 goto mi_error;
669 }
670
671 /* Close event expr payload field element. */
672 ret = mi_lttng_writer_close_element(writer);
673 if (ret) {
674 goto mi_error;
675 }
676
677 ret_code = LTTNG_OK;
678 goto end;
679
680 mi_error:
681 ret_code = LTTNG_ERR_MI_IO_FAIL;
682 end:
683 return ret_code;
684 }
685
686 static
687 enum lttng_error_code lttng_event_expr_channel_context_field_mi_serialize(
688 const struct lttng_event_expr *expression,
689 struct mi_writer *writer)
690 {
691 int ret;
692 enum lttng_error_code ret_code;
693 const char *name = NULL;
694
695 LTTNG_ASSERT(expression);
696 LTTNG_ASSERT(writer);
697 LTTNG_ASSERT(expression->type == LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD);
698
699 name = lttng_event_expr_channel_context_field_get_name(expression);
700 LTTNG_ASSERT(name);
701
702 /* Open event expr channel context field element. */
703 ret = mi_lttng_writer_open_element(writer,
704 mi_lttng_element_event_expr_channel_context_field);
705 if (ret) {
706 goto mi_error;
707 }
708
709 /* Name. */
710 ret = mi_lttng_writer_write_element_string(
711 writer, config_element_name, name);
712 if (ret) {
713 goto mi_error;
714 }
715
716 /* Close event expr channel context field element. */
717 ret = mi_lttng_writer_close_element(writer);
718 if (ret) {
719 goto mi_error;
720 }
721
722 ret_code = LTTNG_OK;
723 goto end;
724
725 mi_error:
726 ret_code = LTTNG_ERR_MI_IO_FAIL;
727 end:
728 return ret_code;
729 }
730
731 static
732 enum lttng_error_code lttng_event_expr_app_specific_context_field_mi_serialize(
733 const struct lttng_event_expr *expression,
734 struct mi_writer *writer)
735 {
736 int ret;
737 enum lttng_error_code ret_code;
738 const char *provider_name = NULL;
739 const char *type_name = NULL;
740
741 LTTNG_ASSERT(expression);
742 LTTNG_ASSERT(writer);
743 LTTNG_ASSERT(expression->type ==
744 LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD);
745
746 provider_name = lttng_event_expr_app_specific_context_field_get_provider_name(
747 expression);
748 LTTNG_ASSERT(provider_name);
749
750 type_name = lttng_event_expr_app_specific_context_field_get_type_name(
751 expression);
752 LTTNG_ASSERT(provider_name);
753
754 /* Open event expr app specific context field element. */
755 ret = mi_lttng_writer_open_element(writer,
756 mi_lttng_element_event_expr_app_specific_context_field);
757 if (ret) {
758 goto mi_error;
759 }
760
761 /* Provider name. */
762 ret = mi_lttng_writer_write_element_string(writer,
763 mi_lttng_element_event_expr_provider_name,
764 provider_name);
765 if (ret) {
766 goto mi_error;
767 }
768
769 /* Type name. */
770 ret = mi_lttng_writer_write_element_string(writer,
771 mi_lttng_element_event_expr_type_name, type_name);
772 if (ret) {
773 goto mi_error;
774 }
775
776 /* Close event expr app specific context field element. */
777 ret = mi_lttng_writer_close_element(writer);
778 if (ret) {
779 goto mi_error;
780 }
781
782 ret_code = LTTNG_OK;
783 goto end;
784
785 mi_error:
786 ret_code = LTTNG_ERR_MI_IO_FAIL;
787 end:
788 return ret_code;
789 }
790
791 static
792 enum lttng_error_code lttng_event_expr_array_field_element_mi_serialize(
793 const struct lttng_event_expr *expression,
794 struct mi_writer *writer)
795 {
796 int ret;
797 enum lttng_error_code ret_code;
798 enum lttng_event_expr_status status;
799 const struct lttng_event_expr *parent_expr = NULL;
800 unsigned int index;
801
802 LTTNG_ASSERT(expression);
803 LTTNG_ASSERT(writer);
804 LTTNG_ASSERT(expression->type == LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT);
805
806 status = lttng_event_expr_array_field_element_get_index(
807 expression, &index);
808 LTTNG_ASSERT(status == LTTNG_EVENT_EXPR_STATUS_OK);
809
810 parent_expr = lttng_event_expr_array_field_element_get_parent_expr(
811 expression);
812 LTTNG_ASSERT(parent_expr != NULL);
813
814 /* Open event expr array field element. */
815 ret = mi_lttng_writer_open_element(writer,
816 mi_lttng_element_event_expr_array_field_element);
817 if (ret) {
818 goto mi_error;
819 }
820
821 /* Index. */
822 ret = mi_lttng_writer_write_element_unsigned_int(
823 writer, mi_lttng_element_event_expr_index, index);
824 if (ret) {
825 goto mi_error;
826 }
827
828 /* Parent expression. */
829 ret_code = lttng_event_expr_mi_serialize(parent_expr, writer);
830 if (ret_code != LTTNG_OK) {
831 goto end;
832 }
833
834 /* Close event expr array field element. */
835 ret = mi_lttng_writer_close_element(writer);
836 if (ret) {
837 goto mi_error;
838 }
839
840 ret_code = LTTNG_OK;
841 goto end;
842
843 mi_error:
844 ret_code = LTTNG_ERR_MI_IO_FAIL;
845 end:
846 return ret_code;
847 }
848
849 enum lttng_error_code lttng_event_expr_mi_serialize(
850 const struct lttng_event_expr *expression,
851 struct mi_writer *writer)
852 {
853 int ret;
854 enum lttng_error_code ret_code;
855
856 LTTNG_ASSERT(expression);
857 LTTNG_ASSERT(writer);
858
859 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_event_expr);
860 if (ret) {
861 goto mi_error;
862 }
863
864 switch (expression->type) {
865 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
866 ret_code = lttng_event_expr_event_payload_field_mi_serialize(
867 expression, writer);
868 break;
869 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
870 ret_code = lttng_event_expr_channel_context_field_mi_serialize(
871 expression, writer);
872 break;
873 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
874 ret_code = lttng_event_expr_app_specific_context_field_mi_serialize(
875 expression, writer);
876 break;
877 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
878 ret_code = lttng_event_expr_array_field_element_mi_serialize(
879 expression, writer);
880 break;
881 default:
882 abort();
883 }
884
885 if (ret_code != LTTNG_OK) {
886 goto end;
887 }
888
889 ret = mi_lttng_writer_close_element(writer);
890 if (ret) {
891 goto mi_error;
892 }
893
894 ret_code = LTTNG_OK;
895 goto end;
896
897 mi_error:
898 ret_code = LTTNG_ERR_MI_IO_FAIL;
899
900 end:
901 return ret_code;
902 }
This page took 0.047068 seconds and 4 git commands to generate.