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