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