on-event: add error counter fields to condition
[lttng-tools.git] / src / common / conditions / on-event.c
1 /*
2 * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <assert.h>
9 #include <common/error.h>
10 #include <common/event-expr-to-bytecode.h>
11 #include <common/macros.h>
12 #include <inttypes.h>
13 #include <limits.h>
14 #include <lttng/condition/condition-internal.h>
15 #include <lttng/condition/on-event-internal.h>
16 #include <lttng/condition/on-event.h>
17 #include <lttng/event-expr-internal.h>
18 #include <lttng/event-expr.h>
19 #include <lttng/event-field-value-internal.h>
20 #include <lttng/event-rule/event-rule-internal.h>
21 #include <lttng/lttng-error.h>
22 #include <stdbool.h>
23 #include <stdint.h>
24 #include <vendor/msgpack/msgpack.h>
25
26 #define IS_ON_EVENT_CONDITION(condition) \
27 (lttng_condition_get_type(condition) == \
28 LTTNG_CONDITION_TYPE_ON_EVENT)
29
30 typedef LTTNG_OPTIONAL(uint64_t) optional_uint64;
31
32 static bool is_on_event_evaluation(const struct lttng_evaluation *evaluation)
33 {
34 enum lttng_condition_type type = lttng_evaluation_get_type(evaluation);
35
36 return type == LTTNG_CONDITION_TYPE_ON_EVENT;
37 }
38
39 static bool lttng_condition_on_event_validate(
40 const struct lttng_condition *condition);
41 static int lttng_condition_on_event_serialize(
42 const struct lttng_condition *condition,
43 struct lttng_payload *payload);
44 static bool lttng_condition_on_event_is_equal(
45 const struct lttng_condition *_a,
46 const struct lttng_condition *_b);
47 static void lttng_condition_on_event_destroy(
48 struct lttng_condition *condition);
49
50 static bool lttng_condition_on_event_validate(
51 const struct lttng_condition *condition)
52 {
53 bool valid = false;
54 struct lttng_condition_on_event *event_rule;
55
56 if (!condition) {
57 goto end;
58 }
59
60 event_rule = container_of(
61 condition, struct lttng_condition_on_event, parent);
62 if (!event_rule->rule) {
63 ERR("Invalid on event condition: a rule must be set");
64 goto end;
65 }
66
67 valid = lttng_event_rule_validate(event_rule->rule);
68 end:
69 return valid;
70 }
71
72 static const char *msgpack_object_type_str(msgpack_object_type type)
73 {
74 const char *name;
75
76 switch (type) {
77 case MSGPACK_OBJECT_NIL:
78 name = "MSGPACK_OBJECT_NIL";
79 break;
80 case MSGPACK_OBJECT_BOOLEAN:
81 name = "MSGPACK_OBJECT_BOOLEAN";
82 break;
83 case MSGPACK_OBJECT_POSITIVE_INTEGER:
84 name = "MSGPACK_OBJECT_POSITIVE_INTEGER";
85 break;
86 case MSGPACK_OBJECT_NEGATIVE_INTEGER:
87 name = "MSGPACK_OBJECT_NEGATIVE_INTEGER";
88 break;
89 case MSGPACK_OBJECT_FLOAT32:
90 name = "MSGPACK_OBJECT_FLOAT32";
91 break;
92 case MSGPACK_OBJECT_FLOAT:
93 /* Same value as MSGPACK_OBJECT_FLOAT64 */
94 name = "MSGPACK_OBJECT_FLOAT(64)";
95 break;
96 case MSGPACK_OBJECT_STR:
97 name = "MSGPACK_OBJECT_STR";
98 break;
99 case MSGPACK_OBJECT_ARRAY:
100 name = "MSGPACK_OBJECT_ARRAY";
101 break;
102 case MSGPACK_OBJECT_MAP:
103 name = "MSGPACK_OBJECT_MAP";
104 break;
105 case MSGPACK_OBJECT_BIN:
106 name = "MSGPACK_OBJECT_BIN";
107 break;
108 case MSGPACK_OBJECT_EXT:
109 name = "MSGPACK_OBJECT_EXT";
110 break;
111 default:
112 abort();
113 }
114
115 return name;
116 }
117
118 /*
119 * Serializes the C string `str` into `buf`.
120 *
121 * Encoding is the length of `str` plus one (for the null character),
122 * and then the string, including its null terminator.
123 */
124 static
125 int serialize_cstr(const char *str, struct lttng_dynamic_buffer *buf)
126 {
127 int ret;
128 const uint32_t len = strlen(str) + 1;
129
130 /* Serialize the length, including the null terminator. */
131 DBG("Serializing C string's length (including null terminator): "
132 "%" PRIu32, len);
133 ret = lttng_dynamic_buffer_append(buf, &len, sizeof(len));
134 if (ret) {
135 goto end;
136 }
137
138 /* Serialize the string. */
139 DBG("Serializing C string: '%s'", str);
140 ret = lttng_dynamic_buffer_append(buf, str, len);
141 if (ret) {
142 goto end;
143 }
144
145 end:
146 return ret;
147 }
148
149 /*
150 * Serializes the event expression `expr` into `buf`.
151 */
152 static
153 int serialize_event_expr(const struct lttng_event_expr *expr,
154 struct lttng_payload *payload)
155 {
156 const uint8_t type = expr->type;
157 int ret;
158
159 /* Serialize the expression's type. */
160 DBG("Serializing event expression's type: %d", expr->type);
161 ret = lttng_dynamic_buffer_append(&payload->buffer, &type, sizeof(type));
162 if (ret) {
163 goto end;
164 }
165
166 /* Serialize the expression */
167 switch (expr->type) {
168 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
169 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
170 {
171 const struct lttng_event_expr_field *field_expr =
172 container_of(expr,
173 const struct lttng_event_expr_field,
174 parent);
175
176 /* Serialize the field name. */
177 DBG("Serializing field event expression's field name: '%s'",
178 field_expr->name);
179 ret = serialize_cstr(field_expr->name, &payload->buffer);
180 if (ret) {
181 goto end;
182 }
183
184 break;
185 }
186 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
187 {
188 const struct lttng_event_expr_app_specific_context_field *field_expr =
189 container_of(expr,
190 const struct lttng_event_expr_app_specific_context_field,
191 parent);
192
193 /* Serialize the provider name. */
194 DBG("Serializing app-specific context field event expression's "
195 "provider name: '%s'",
196 field_expr->provider_name);
197 ret = serialize_cstr(field_expr->provider_name, &payload->buffer);
198 if (ret) {
199 goto end;
200 }
201
202 /* Serialize the type name. */
203 DBG("Serializing app-specific context field event expression's "
204 "type name: '%s'",
205 field_expr->provider_name);
206 ret = serialize_cstr(field_expr->type_name, &payload->buffer);
207 if (ret) {
208 goto end;
209 }
210
211 break;
212 }
213 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
214 {
215 const struct lttng_event_expr_array_field_element *elem_expr =
216 container_of(expr,
217 const struct lttng_event_expr_array_field_element,
218 parent);
219 const uint32_t index = elem_expr->index;
220
221 /* Serialize the index. */
222 DBG("Serializing array field element event expression's "
223 "index: %u", elem_expr->index);
224 ret = lttng_dynamic_buffer_append(&payload->buffer, &index, sizeof(index));
225 if (ret) {
226 goto end;
227 }
228
229 /* Serialize the parent array field expression. */
230 DBG("Serializing array field element event expression's "
231 "parent array field event expression");
232 ret = serialize_event_expr(elem_expr->array_field_expr, payload);
233 if (ret) {
234 goto end;
235 }
236
237 break;
238 }
239 default:
240 break;
241 }
242
243 end:
244 return ret;
245 }
246
247 static
248 struct lttng_capture_descriptor *
249 lttng_condition_on_event_get_internal_capture_descriptor_at_index(
250 const struct lttng_condition *condition, unsigned int index)
251 {
252 const struct lttng_condition_on_event *on_event_cond =
253 container_of(condition,
254 const struct lttng_condition_on_event,
255 parent);
256 struct lttng_capture_descriptor *desc = NULL;
257 unsigned int count;
258 enum lttng_condition_status status;
259
260 if (!condition || !IS_ON_EVENT_CONDITION(condition)) {
261 goto end;
262 }
263
264 status = lttng_condition_on_event_get_capture_descriptor_count(
265 condition, &count);
266 if (status != LTTNG_CONDITION_STATUS_OK) {
267 goto end;
268 }
269
270 if (index >= count) {
271 goto end;
272 }
273
274 desc = lttng_dynamic_pointer_array_get_pointer(
275 &on_event_cond->capture_descriptors, index);
276 end:
277 return desc;
278 }
279
280 static int lttng_condition_on_event_serialize(
281 const struct lttng_condition *condition,
282 struct lttng_payload *payload)
283 {
284 int ret;
285 struct lttng_condition_on_event *on_event_condition;
286 enum lttng_condition_status status;
287 /* Used for iteration and communication (size matters). */
288 uint32_t i, capture_descr_count;
289 LTTNG_OPTIONAL_COMM(typeof(on_event_condition->error_count.value)) error_count_comm;
290
291 if (!condition || !IS_ON_EVENT_CONDITION(condition)) {
292 ret = -1;
293 goto end;
294 }
295
296 DBG("Serializing on event condition");
297 on_event_condition = container_of(
298 condition, struct lttng_condition_on_event, parent);
299
300 DBG("Serializing on event condition's event rule");
301 ret = lttng_event_rule_serialize(on_event_condition->rule, payload);
302 if (ret) {
303 goto end;
304 }
305
306 error_count_comm = (typeof(error_count_comm)) {
307 .is_set = on_event_condition->error_count.is_set,
308 .value = on_event_condition->error_count.value,
309 };
310
311 {
312 char error_count_value_str[MAX_INT_DEC_LEN(on_event_condition->error_count.value)];
313 const int fmt_ret = snprintf(error_count_value_str,
314 sizeof(error_count_value_str), "%" PRIu64,
315 on_event_condition->error_count.value);
316
317 assert(fmt_ret > 0);
318 DBG("Serializing event rule condition's error count: value = %s",
319 on_event_condition->error_count.is_set ?
320 error_count_value_str :
321 "(unset)");
322 }
323
324 ret = lttng_dynamic_buffer_append(&payload->buffer, &error_count_comm,
325 sizeof(error_count_comm));
326 if (ret) {
327 goto end;
328 }
329
330 status = lttng_condition_on_event_get_capture_descriptor_count(
331 condition, &capture_descr_count);
332 if (status != LTTNG_CONDITION_STATUS_OK) {
333 ret = -1;
334 goto end;
335 };
336
337 DBG("Serializing on event condition's capture descriptor count: %" PRIu32,
338 capture_descr_count);
339 ret = lttng_dynamic_buffer_append(&payload->buffer, &capture_descr_count,
340 sizeof(capture_descr_count));
341 if (ret) {
342 goto end;
343 }
344
345 for (i = 0; i < capture_descr_count; i++) {
346 const struct lttng_capture_descriptor *desc =
347 lttng_condition_on_event_get_internal_capture_descriptor_at_index(
348 condition, i);
349
350 DBG("Serializing on event condition's capture descriptor %" PRIu32,
351 i);
352 ret = serialize_event_expr(desc->event_expression, payload);
353 if (ret) {
354 goto end;
355 }
356 }
357
358 end:
359 return ret;
360 }
361
362 static
363 bool capture_descriptors_are_equal(
364 const struct lttng_condition *condition_a,
365 const struct lttng_condition *condition_b)
366 {
367 bool is_equal = true;
368 unsigned int capture_descr_count_a;
369 unsigned int capture_descr_count_b;
370 size_t i;
371 enum lttng_condition_status status;
372
373 status = lttng_condition_on_event_get_capture_descriptor_count(
374 condition_a, &capture_descr_count_a);
375 if (status != LTTNG_CONDITION_STATUS_OK) {
376 goto not_equal;
377 }
378
379 status = lttng_condition_on_event_get_capture_descriptor_count(
380 condition_b, &capture_descr_count_b);
381 if (status != LTTNG_CONDITION_STATUS_OK) {
382 goto not_equal;
383 }
384
385 if (capture_descr_count_a != capture_descr_count_b) {
386 goto not_equal;
387 }
388
389 for (i = 0; i < capture_descr_count_a; i++) {
390 const struct lttng_event_expr *expr_a =
391 lttng_condition_on_event_get_capture_descriptor_at_index(
392 condition_a,
393 i);
394 const struct lttng_event_expr *expr_b =
395 lttng_condition_on_event_get_capture_descriptor_at_index(
396 condition_b,
397 i);
398
399 if (!lttng_event_expr_is_equal(expr_a, expr_b)) {
400 goto not_equal;
401 }
402 }
403
404 goto end;
405
406 not_equal:
407 is_equal = false;
408
409 end:
410 return is_equal;
411 }
412
413 static bool lttng_condition_on_event_is_equal(
414 const struct lttng_condition *_a,
415 const struct lttng_condition *_b)
416 {
417 bool is_equal = false;
418 struct lttng_condition_on_event *a, *b;
419
420 a = container_of(_a, struct lttng_condition_on_event, parent);
421 b = container_of(_b, struct lttng_condition_on_event, parent);
422
423 /* Both event rules must be set or both must be unset. */
424 if ((a->rule && !b->rule) || (!a->rule && b->rule)) {
425 WARN("Comparing event_rule conditions with uninitialized rule");
426 goto end;
427 }
428
429 is_equal = lttng_event_rule_is_equal(a->rule, b->rule);
430 if (!is_equal) {
431 goto end;
432 }
433
434 is_equal = capture_descriptors_are_equal(_a, _b);
435
436 end:
437 return is_equal;
438 }
439
440 static void lttng_condition_on_event_destroy(
441 struct lttng_condition *condition)
442 {
443 struct lttng_condition_on_event *on_event_condition;
444
445 on_event_condition = container_of(
446 condition, struct lttng_condition_on_event, parent);
447
448 lttng_event_rule_put(on_event_condition->rule);
449 lttng_dynamic_pointer_array_reset(&on_event_condition->capture_descriptors);
450 free(on_event_condition);
451 }
452
453 static
454 void destroy_capture_descriptor(void *ptr)
455 {
456 struct lttng_capture_descriptor *desc =
457 (struct lttng_capture_descriptor *) ptr;
458
459 lttng_event_expr_destroy(desc->event_expression);
460 free(desc->bytecode);
461 free(desc);
462 }
463
464 struct lttng_condition *lttng_condition_on_event_create(
465 struct lttng_event_rule *rule)
466 {
467 struct lttng_condition *parent = NULL;
468 struct lttng_condition_on_event *condition = NULL;
469
470 if (!rule) {
471 goto end;
472 }
473
474 condition = zmalloc(sizeof(struct lttng_condition_on_event));
475 if (!condition) {
476 return NULL;
477 }
478
479 lttng_condition_init(&condition->parent,
480 LTTNG_CONDITION_TYPE_ON_EVENT);
481 condition->parent.validate = lttng_condition_on_event_validate,
482 condition->parent.serialize = lttng_condition_on_event_serialize,
483 condition->parent.equal = lttng_condition_on_event_is_equal,
484 condition->parent.destroy = lttng_condition_on_event_destroy,
485
486 lttng_event_rule_get(rule);
487 condition->rule = rule;
488 rule = NULL;
489
490 lttng_dynamic_pointer_array_init(&condition->capture_descriptors,
491 destroy_capture_descriptor);
492
493 parent = &condition->parent;
494 end:
495 return parent;
496 }
497
498 static
499 uint64_t uint_from_buffer(const struct lttng_buffer_view *view, size_t size,
500 size_t *offset)
501 {
502 uint64_t ret;
503 const struct lttng_buffer_view uint_view =
504 lttng_buffer_view_from_view(view, *offset, size);
505
506 if (!lttng_buffer_view_is_valid(&uint_view)) {
507 ret = UINT64_C(-1);
508 goto end;
509 }
510
511 switch (size) {
512 case 1:
513 ret = (uint64_t) *uint_view.data;
514 break;
515 case sizeof(uint32_t):
516 {
517 uint32_t u32;
518
519 memcpy(&u32, uint_view.data, sizeof(u32));
520 ret = (uint64_t) u32;
521 break;
522 }
523 case sizeof(ret):
524 memcpy(&ret, uint_view.data, sizeof(ret));
525 break;
526 default:
527 abort();
528 }
529
530 *offset += size;
531
532 end:
533 return ret;
534 }
535
536 static
537 int optional_uint_from_buffer(
538 const struct lttng_buffer_view *view,
539 size_t inner_value_size,
540 size_t *offset,
541 optional_uint64 *value)
542 {
543 int ret;
544
545 /*
546 * Those cases are identical except for the optional's inner type width.
547 */
548 switch (inner_value_size) {
549 case sizeof(uint8_t):
550 {
551 LTTNG_OPTIONAL_COMM(uint8_t) *value_comm;
552 const struct lttng_buffer_view optional_uint_view =
553 lttng_buffer_view_from_view(view, *offset,
554 sizeof(*value_comm));
555
556 if (!lttng_buffer_view_is_valid(&optional_uint_view)) {
557 ret = -1;
558 goto end;
559 }
560
561 value_comm = (typeof(value_comm)) optional_uint_view.data;
562 *value = (typeof(*value)) {
563 .is_set = value_comm->is_set,
564 .value = (uint64_t) value_comm->value,
565 };
566
567 *offset += sizeof(*value_comm);
568 break;
569 }
570 case sizeof(uint16_t):
571 {
572 LTTNG_OPTIONAL_COMM(uint16_t) *value_comm;
573 const struct lttng_buffer_view optional_uint_view =
574 lttng_buffer_view_from_view(view, *offset,
575 sizeof(*value_comm));
576
577 if (!lttng_buffer_view_is_valid(&optional_uint_view)) {
578 ret = -1;
579 goto end;
580 }
581
582 value_comm = (typeof(value_comm)) optional_uint_view.data;
583 *value = (typeof(*value)) {
584 .is_set = value_comm->is_set,
585 .value = (uint64_t) value_comm->value,
586 };
587
588 *offset += sizeof(*value_comm);
589 break;
590 }
591 case sizeof(uint32_t):
592 {
593 LTTNG_OPTIONAL_COMM(uint32_t) *value_comm;
594 const struct lttng_buffer_view optional_uint_view =
595 lttng_buffer_view_from_view(view, *offset,
596 sizeof(*value_comm));
597
598 if (!lttng_buffer_view_is_valid(&optional_uint_view)) {
599 ret = -1;
600 goto end;
601 }
602
603 value_comm = (typeof(value_comm)) optional_uint_view.data;
604 *value = (typeof(*value)) {
605 .is_set = value_comm->is_set,
606 .value = (uint64_t) value_comm->value,
607 };
608
609 *offset += sizeof(*value_comm);
610 break;
611 }
612 case sizeof(uint64_t):
613 {
614 LTTNG_OPTIONAL_COMM(uint64_t) *value_comm;
615 const struct lttng_buffer_view optional_uint_view =
616 lttng_buffer_view_from_view(view, *offset,
617 sizeof(*value_comm));
618
619 if (!lttng_buffer_view_is_valid(&optional_uint_view)) {
620 ret = -1;
621 goto end;
622 }
623
624 value_comm = (typeof(value_comm)) optional_uint_view.data;
625 *value = (typeof(*value)) {
626 .is_set = value_comm->is_set,
627 .value = (uint64_t) value_comm->value,
628 };
629
630 *offset += sizeof(*value_comm);
631 break;
632 }
633 default:
634 abort();
635 }
636
637 ret = 0;
638 end:
639 return ret;
640 }
641
642 static
643 const char *str_from_buffer(const struct lttng_buffer_view *view,
644 size_t *offset)
645 {
646 uint64_t len;
647 const char *ret;
648
649 len = uint_from_buffer(view, sizeof(uint32_t), offset);
650 if (len == UINT64_C(-1)) {
651 goto error;
652 }
653
654 ret = &view->data[*offset];
655
656 if (!lttng_buffer_view_contains_string(view, ret, len)) {
657 goto error;
658 }
659
660 *offset += len;
661 goto end;
662
663 error:
664 ret = NULL;
665
666 end:
667 return ret;
668 }
669
670 static
671 struct lttng_event_expr *event_expr_from_payload(
672 struct lttng_payload_view *view, size_t *offset)
673 {
674 struct lttng_event_expr *expr = NULL;
675 const char *str;
676 uint64_t type;
677
678 type = uint_from_buffer(&view->buffer, sizeof(uint8_t), offset);
679 if (type == UINT64_C(-1)) {
680 goto error;
681 }
682
683 switch (type) {
684 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
685 str = str_from_buffer(&view->buffer, offset);
686 if (!str) {
687 goto error;
688 }
689
690 expr = lttng_event_expr_event_payload_field_create(str);
691 break;
692 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
693 str = str_from_buffer(&view->buffer, offset);
694 if (!str) {
695 goto error;
696 }
697
698 expr = lttng_event_expr_channel_context_field_create(str);
699 break;
700 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
701 {
702 const char *provider_name;
703 const char *type_name;
704
705 provider_name = str_from_buffer(&view->buffer, offset);
706 if (!provider_name) {
707 goto error;
708 }
709
710 type_name = str_from_buffer(&view->buffer, offset);
711 if (!type_name) {
712 goto error;
713 }
714
715 expr = lttng_event_expr_app_specific_context_field_create(
716 provider_name, type_name);
717 break;
718 }
719 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
720 {
721 struct lttng_event_expr *array_field_expr;
722 const uint64_t index = uint_from_buffer(
723 &view->buffer, sizeof(uint32_t), offset);
724
725 if (index == UINT64_C(-1)) {
726 goto error;
727 }
728
729 /* Array field expression is the encoded after this. */
730 array_field_expr = event_expr_from_payload(view, offset);
731 if (!array_field_expr) {
732 goto error;
733 }
734
735 /* Move ownership of `array_field_expr` to new expression. */
736 expr = lttng_event_expr_array_field_element_create(
737 array_field_expr, (unsigned int) index);
738 if (!expr) {
739 /* `array_field_expr` not moved: destroy it. */
740 lttng_event_expr_destroy(array_field_expr);
741 }
742
743 break;
744 }
745 default:
746 abort();
747 }
748
749 goto end;
750
751 error:
752 lttng_event_expr_destroy(expr);
753 expr = NULL;
754
755 end:
756 return expr;
757 }
758
759 LTTNG_HIDDEN
760 ssize_t lttng_condition_on_event_create_from_payload(
761 struct lttng_payload_view *view,
762 struct lttng_condition **_condition)
763 {
764 int optional_ret;
765 ssize_t consumed_length;
766 size_t offset = 0;
767 ssize_t event_rule_length;
768 uint32_t i, capture_descr_count;
769 optional_uint64 error_count;
770 struct lttng_condition *condition = NULL;
771 struct lttng_event_rule *event_rule = NULL;
772
773 if (!view || !_condition) {
774 goto error;
775 }
776
777 /* Struct lttng_event_rule. */
778 {
779 struct lttng_payload_view event_rule_view =
780 lttng_payload_view_from_view(view, offset, -1);
781
782 event_rule_length = lttng_event_rule_create_from_payload(
783 &event_rule_view, &event_rule);
784 }
785
786 if (event_rule_length < 0 || !event_rule) {
787 goto error;
788 }
789
790 offset += event_rule_length;
791
792 /* Error count. */
793 optional_ret = optional_uint_from_buffer(&view->buffer,
794 sizeof(error_count.value), &offset,
795 &error_count);
796 if (optional_ret) {
797 goto error;
798 }
799
800 /* Create condition (no capture descriptors yet) at this point */
801 condition = lttng_condition_on_event_create(event_rule);
802 if (!condition) {
803 goto error;
804 }
805
806 if (error_count.is_set) {
807 lttng_condition_on_event_set_error_count(
808 condition, error_count.value);
809 }
810
811 /* Capture descriptor count. */
812 assert(event_rule_length >= 0);
813 capture_descr_count = uint_from_buffer(&view->buffer, sizeof(uint32_t), &offset);
814 if (capture_descr_count == UINT32_C(-1)) {
815 goto error;
816 }
817
818 /* Capture descriptors. */
819 for (i = 0; i < capture_descr_count; i++) {
820 enum lttng_condition_status status;
821 struct lttng_event_expr *expr = event_expr_from_payload(
822 view, &offset);
823
824 if (!expr) {
825 goto error;
826 }
827
828 /* Move ownership of `expr` to `condition`. */
829 status = lttng_condition_on_event_append_capture_descriptor(
830 condition, expr);
831 if (status != LTTNG_CONDITION_STATUS_OK) {
832 /* `expr` not moved: destroy it. */
833 lttng_event_expr_destroy(expr);
834 goto error;
835 }
836 }
837
838 consumed_length = (ssize_t) offset;
839 *_condition = condition;
840 condition = NULL;
841 goto end;
842
843 error:
844 consumed_length = -1;
845
846 end:
847 lttng_event_rule_put(event_rule);
848 lttng_condition_put(condition);
849 return consumed_length;
850 }
851
852 LTTNG_HIDDEN
853 enum lttng_condition_status lttng_condition_on_event_borrow_rule_mutable(
854 const struct lttng_condition *condition,
855 struct lttng_event_rule **rule)
856 {
857 struct lttng_condition_on_event *event_rule;
858 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
859
860 if (!condition || !IS_ON_EVENT_CONDITION(condition) || !rule) {
861 status = LTTNG_CONDITION_STATUS_INVALID;
862 goto end;
863 }
864
865 event_rule = container_of(
866 condition, struct lttng_condition_on_event, parent);
867 if (!event_rule->rule) {
868 status = LTTNG_CONDITION_STATUS_UNSET;
869 goto end;
870 }
871
872 *rule = event_rule->rule;
873 end:
874 return status;
875 }
876
877 enum lttng_condition_status lttng_condition_on_event_get_rule(
878 const struct lttng_condition *condition,
879 const struct lttng_event_rule **rule)
880 {
881 struct lttng_event_rule *mutable_rule = NULL;
882 const enum lttng_condition_status status =
883 lttng_condition_on_event_borrow_rule_mutable(
884 condition, &mutable_rule);
885
886 *rule = mutable_rule;
887 return status;
888 }
889
890 LTTNG_HIDDEN
891 void lttng_condition_on_event_set_error_counter_index(
892 struct lttng_condition *condition, uint64_t error_counter_index)
893 {
894 struct lttng_condition_on_event *on_event_cond =
895 container_of(condition,
896 struct lttng_condition_on_event, parent);
897
898 LTTNG_OPTIONAL_SET(&on_event_cond->error_counter_index, error_counter_index);
899 }
900
901 LTTNG_HIDDEN
902 uint64_t lttng_condition_on_event_get_error_counter_index(
903 const struct lttng_condition *condition)
904 {
905 const struct lttng_condition_on_event *on_event_cond =
906 container_of(condition,
907 const struct lttng_condition_on_event, parent);
908
909 return LTTNG_OPTIONAL_GET(on_event_cond->error_counter_index);
910 }
911
912 LTTNG_HIDDEN
913 void lttng_condition_on_event_set_error_count(struct lttng_condition *condition,
914 uint64_t error_count)
915 {
916 struct lttng_condition_on_event *on_event_cond =
917 container_of(condition,
918 struct lttng_condition_on_event, parent);
919
920 LTTNG_OPTIONAL_SET(&on_event_cond->error_count, error_count);
921 }
922
923 uint64_t lttng_condition_on_event_get_error_count(
924 const struct lttng_condition *condition)
925 {
926 const struct lttng_condition_on_event *on_event_cond =
927 container_of(condition,
928 const struct lttng_condition_on_event, parent);
929
930 return LTTNG_OPTIONAL_GET(on_event_cond->error_count);
931 }
932
933 enum lttng_condition_status
934 lttng_condition_on_event_append_capture_descriptor(
935 struct lttng_condition *condition,
936 struct lttng_event_expr *expr)
937 {
938 int ret;
939 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
940 struct lttng_condition_on_event *on_event_cond =
941 container_of(condition,
942 struct lttng_condition_on_event, parent);
943 struct lttng_capture_descriptor *descriptor = NULL;
944 const struct lttng_event_rule *rule = NULL;
945
946 /* Only accept l-values. */
947 if (!condition || !IS_ON_EVENT_CONDITION(condition) || !expr ||
948 !lttng_event_expr_is_lvalue(expr)) {
949 status = LTTNG_CONDITION_STATUS_INVALID;
950 goto end;
951 }
952
953 status = lttng_condition_on_event_get_rule(condition, &rule);
954 if (status != LTTNG_CONDITION_STATUS_OK) {
955 goto end;
956 }
957
958 switch(lttng_event_rule_get_type(rule)) {
959 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
960 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
961 /* Supported. */
962 status = LTTNG_CONDITION_STATUS_OK;
963 break;
964 case LTTNG_EVENT_RULE_TYPE_UNKNOWN:
965 status = LTTNG_CONDITION_STATUS_INVALID;
966 break;
967 default:
968 status = LTTNG_CONDITION_STATUS_UNSUPPORTED;
969 break;
970 }
971
972 if (status != LTTNG_CONDITION_STATUS_OK) {
973 goto end;
974 }
975
976 descriptor = malloc(sizeof(*descriptor));
977 if (descriptor == NULL) {
978 status = LTTNG_CONDITION_STATUS_ERROR;
979 goto end;
980 }
981
982 descriptor->event_expression = expr;
983 descriptor->bytecode = NULL;
984
985 ret = lttng_dynamic_pointer_array_add_pointer(
986 &on_event_cond->capture_descriptors, descriptor);
987 if (ret) {
988 status = LTTNG_CONDITION_STATUS_ERROR;
989 goto end;
990 }
991
992 /* Ownership is transfered to the internal capture_descriptors array */
993 descriptor = NULL;
994 end:
995 free(descriptor);
996 return status;
997 }
998
999 enum lttng_condition_status
1000 lttng_condition_on_event_get_capture_descriptor_count(
1001 const struct lttng_condition *condition, unsigned int *count)
1002 {
1003 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
1004 const struct lttng_condition_on_event *on_event_condition =
1005 container_of(condition,
1006 const struct lttng_condition_on_event,
1007 parent);
1008
1009 if (!condition || !IS_ON_EVENT_CONDITION(condition) || !count) {
1010 status = LTTNG_CONDITION_STATUS_INVALID;
1011 goto end;
1012 }
1013
1014 *count = lttng_dynamic_pointer_array_get_count(
1015 &on_event_condition->capture_descriptors);
1016
1017 end:
1018 return status;
1019 }
1020
1021 const struct lttng_event_expr *
1022 lttng_condition_on_event_get_capture_descriptor_at_index(
1023 const struct lttng_condition *condition, unsigned int index)
1024 {
1025 const struct lttng_event_expr *expr = NULL;
1026 const struct lttng_capture_descriptor *desc = NULL;
1027
1028 desc = lttng_condition_on_event_get_internal_capture_descriptor_at_index(
1029 condition, index);
1030 if (desc == NULL) {
1031 goto end;
1032 }
1033 expr = desc->event_expression;
1034
1035 end:
1036 return expr;
1037 }
1038
1039 LTTNG_HIDDEN
1040 ssize_t lttng_evaluation_on_event_create_from_payload(
1041 const struct lttng_condition_on_event *condition,
1042 struct lttng_payload_view *view,
1043 struct lttng_evaluation **_evaluation)
1044 {
1045 ssize_t ret, offset = 0;
1046 const char *trigger_name;
1047 struct lttng_evaluation *evaluation = NULL;
1048 const struct lttng_evaluation_on_event_comm *header;
1049 const struct lttng_payload_view header_view =
1050 lttng_payload_view_from_view(
1051 view, 0, sizeof(*header));
1052 uint32_t capture_payload_size;
1053 const char *capture_payload = NULL;
1054
1055 if (!_evaluation) {
1056 ret = -1;
1057 goto error;
1058 }
1059
1060 if (!lttng_payload_view_is_valid(&header_view)) {
1061 ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain header");
1062 ret = -1;
1063 goto error;
1064 }
1065
1066 header = (typeof(header)) header_view.buffer.data;
1067
1068 /* Map the originating trigger's name. */
1069 offset += sizeof(*header);
1070 {
1071 const struct lttng_payload_view current_view =
1072 lttng_payload_view_from_view(view, offset,
1073 header->trigger_name_length);
1074
1075 if (!lttng_payload_view_is_valid(&current_view)) {
1076 ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain trigger name");
1077 ret = -1;
1078 goto error;
1079 }
1080
1081 trigger_name = current_view.buffer.data;
1082 if (!lttng_buffer_view_contains_string(&current_view.buffer,
1083 trigger_name, header->trigger_name_length)) {
1084 ERR("Failed to initialize from malformed event rule evaluation: invalid trigger name");
1085 ret = -1;
1086 goto error;
1087 }
1088 }
1089
1090 offset += header->trigger_name_length;
1091 {
1092 const struct lttng_payload_view current_view =
1093 lttng_payload_view_from_view(view, offset, -1);
1094
1095 if (current_view.buffer.size < sizeof(capture_payload_size)) {
1096 ret = -1;
1097 goto error;
1098 }
1099
1100 memcpy(&capture_payload_size, current_view.buffer.data,
1101 sizeof(capture_payload_size));
1102 }
1103 offset += sizeof(capture_payload_size);
1104
1105 if (capture_payload_size > 0) {
1106 const struct lttng_payload_view current_view =
1107 lttng_payload_view_from_view(view, offset, -1);
1108
1109 if (current_view.buffer.size < capture_payload_size) {
1110 ret = -1;
1111 goto error;
1112 }
1113
1114 capture_payload = current_view.buffer.data;
1115 }
1116
1117 evaluation = lttng_evaluation_on_event_create(condition, trigger_name,
1118 capture_payload, capture_payload_size, true);
1119 if (!evaluation) {
1120 ret = -1;
1121 goto error;
1122 }
1123
1124 offset += capture_payload_size;
1125 *_evaluation = evaluation;
1126 evaluation = NULL;
1127 ret = offset;
1128
1129 error:
1130 lttng_evaluation_destroy(evaluation);
1131 return ret;
1132 }
1133
1134 static int lttng_evaluation_on_event_serialize(
1135 const struct lttng_evaluation *evaluation,
1136 struct lttng_payload *payload)
1137 {
1138 int ret = 0;
1139 struct lttng_evaluation_on_event *hit;
1140 struct lttng_evaluation_on_event_comm comm;
1141 uint32_t capture_payload_size;
1142
1143 hit = container_of(
1144 evaluation, struct lttng_evaluation_on_event, parent);
1145
1146 assert(hit->name);
1147 comm.trigger_name_length = strlen(hit->name) + 1;
1148
1149 ret = lttng_dynamic_buffer_append(
1150 &payload->buffer, &comm, sizeof(comm));
1151 if (ret) {
1152 goto end;
1153 }
1154
1155 ret = lttng_dynamic_buffer_append(
1156 &payload->buffer, hit->name, comm.trigger_name_length);
1157 if (ret) {
1158 goto end;
1159 }
1160
1161 capture_payload_size = (uint32_t) hit->capture_payload.size;
1162 ret = lttng_dynamic_buffer_append(&payload->buffer, &capture_payload_size,
1163 sizeof(capture_payload_size));
1164 if (ret) {
1165 goto end;
1166 }
1167
1168 ret = lttng_dynamic_buffer_append(&payload->buffer, hit->capture_payload.data,
1169 hit->capture_payload.size);
1170 if (ret) {
1171 goto end;
1172 }
1173
1174 end:
1175 return ret;
1176 }
1177
1178 static
1179 bool msgpack_str_is_equal(const struct msgpack_object *obj, const char *str)
1180 {
1181 bool is_equal = true;
1182
1183 assert(obj->type == MSGPACK_OBJECT_STR);
1184
1185 if (obj->via.str.size != strlen(str)) {
1186 is_equal = false;
1187 goto end;
1188 }
1189
1190 if (strncmp(obj->via.str.ptr, str, obj->via.str.size) != 0) {
1191 is_equal = false;
1192 goto end;
1193 }
1194
1195 end:
1196 return is_equal;
1197 }
1198
1199 static
1200 const msgpack_object *get_msgpack_map_obj(const struct msgpack_object *map_obj,
1201 const char *name)
1202 {
1203 const msgpack_object *ret = NULL;
1204 size_t i;
1205
1206 assert(map_obj->type == MSGPACK_OBJECT_MAP);
1207
1208 for (i = 0; i < map_obj->via.map.size; i++) {
1209 const struct msgpack_object_kv *kv = &map_obj->via.map.ptr[i];
1210
1211 assert(kv->key.type == MSGPACK_OBJECT_STR);
1212
1213 if (msgpack_str_is_equal(&kv->key, name)) {
1214 ret = &kv->val;
1215 goto end;
1216 }
1217 }
1218
1219 end:
1220 return ret;
1221 }
1222
1223 static void lttng_evaluation_on_event_destroy(
1224 struct lttng_evaluation *evaluation)
1225 {
1226 struct lttng_evaluation_on_event *hit;
1227
1228 hit = container_of(
1229 evaluation, struct lttng_evaluation_on_event, parent);
1230 free(hit->name);
1231 lttng_dynamic_buffer_reset(&hit->capture_payload);
1232 lttng_event_field_value_destroy(hit->captured_values);
1233 free(hit);
1234 }
1235
1236 static
1237 int event_field_value_from_obj(const msgpack_object *obj,
1238 struct lttng_event_field_value **field_val)
1239 {
1240 int ret = 0;
1241
1242 assert(obj);
1243 assert(field_val);
1244
1245 switch (obj->type) {
1246 case MSGPACK_OBJECT_NIL:
1247 /* Unavailable. */
1248 *field_val = NULL;
1249 goto end;
1250 case MSGPACK_OBJECT_POSITIVE_INTEGER:
1251 *field_val = lttng_event_field_value_uint_create(
1252 obj->via.u64);
1253 break;
1254 case MSGPACK_OBJECT_NEGATIVE_INTEGER:
1255 *field_val = lttng_event_field_value_int_create(
1256 obj->via.i64);
1257 break;
1258 case MSGPACK_OBJECT_FLOAT32:
1259 case MSGPACK_OBJECT_FLOAT64:
1260 *field_val = lttng_event_field_value_real_create(
1261 obj->via.f64);
1262 break;
1263 case MSGPACK_OBJECT_STR:
1264 *field_val = lttng_event_field_value_string_create_with_size(
1265 obj->via.str.ptr, obj->via.str.size);
1266 break;
1267 case MSGPACK_OBJECT_ARRAY:
1268 {
1269 size_t i;
1270
1271 *field_val = lttng_event_field_value_array_create();
1272 if (!*field_val) {
1273 goto error;
1274 }
1275
1276 for (i = 0; i < obj->via.array.size; i++) {
1277 const msgpack_object *elem_obj = &obj->via.array.ptr[i];
1278 struct lttng_event_field_value *elem_field_val;
1279
1280 ret = event_field_value_from_obj(elem_obj,
1281 &elem_field_val);
1282 if (ret) {
1283 goto error;
1284 }
1285
1286 if (elem_field_val) {
1287 ret = lttng_event_field_value_array_append(
1288 *field_val, elem_field_val);
1289 } else {
1290 ret = lttng_event_field_value_array_append_unavailable(
1291 *field_val);
1292 }
1293
1294 if (ret) {
1295 lttng_event_field_value_destroy(elem_field_val);
1296 goto error;
1297 }
1298 }
1299
1300 break;
1301 }
1302 case MSGPACK_OBJECT_MAP:
1303 {
1304 /*
1305 * As of this version, the only valid map object is
1306 * for an enumeration value, for example:
1307 *
1308 * type: enum
1309 * value: 177
1310 * labels:
1311 * - Labatt 50
1312 * - Molson Dry
1313 * - Carling Black Label
1314 */
1315 const msgpack_object *inner_obj;
1316 size_t label_i;
1317
1318 inner_obj = get_msgpack_map_obj(obj, "type");
1319 if (!inner_obj) {
1320 ERR("Missing `type` entry in map object");
1321 goto error;
1322 }
1323
1324 if (inner_obj->type != MSGPACK_OBJECT_STR) {
1325 ERR("Map object's `type` entry is not a string: type = %s",
1326 msgpack_object_type_str(inner_obj->type));
1327 goto error;
1328 }
1329
1330 if (!msgpack_str_is_equal(inner_obj, "enum")) {
1331 ERR("Map object's `type` entry: expecting `enum`");
1332 goto error;
1333 }
1334
1335 inner_obj = get_msgpack_map_obj(obj, "value");
1336 if (!inner_obj) {
1337 ERR("Missing `value` entry in map object");
1338 goto error;
1339 }
1340
1341 if (inner_obj->type == MSGPACK_OBJECT_POSITIVE_INTEGER) {
1342 *field_val = lttng_event_field_value_enum_uint_create(
1343 inner_obj->via.u64);
1344 } else if (inner_obj->type == MSGPACK_OBJECT_NEGATIVE_INTEGER) {
1345 *field_val = lttng_event_field_value_enum_int_create(
1346 inner_obj->via.i64);
1347 } else {
1348 ERR("Map object's `value` entry is not an integer: type = %s",
1349 msgpack_object_type_str(inner_obj->type));
1350 goto error;
1351 }
1352
1353 if (!*field_val) {
1354 goto error;
1355 }
1356
1357 inner_obj = get_msgpack_map_obj(obj, "labels");
1358 if (!inner_obj) {
1359 /* No labels */
1360 goto end;
1361 }
1362
1363 if (inner_obj->type != MSGPACK_OBJECT_ARRAY) {
1364 ERR("Map object's `labels` entry is not an array: type = %s",
1365 msgpack_object_type_str(inner_obj->type));
1366 goto error;
1367 }
1368
1369 for (label_i = 0; label_i < inner_obj->via.array.size;
1370 label_i++) {
1371 int iret;
1372 const msgpack_object *elem_obj =
1373 &inner_obj->via.array.ptr[label_i];
1374
1375 if (elem_obj->type != MSGPACK_OBJECT_STR) {
1376 ERR("Map object's `labels` entry's type is not a string: type = %s",
1377 msgpack_object_type_str(elem_obj->type));
1378 goto error;
1379 }
1380
1381 iret = lttng_event_field_value_enum_append_label_with_size(
1382 *field_val, elem_obj->via.str.ptr,
1383 elem_obj->via.str.size);
1384 if (iret) {
1385 goto error;
1386 }
1387 }
1388
1389 break;
1390 }
1391 default:
1392 ERR("Unexpected object type: type = %s",
1393 msgpack_object_type_str(obj->type));
1394 goto error;
1395 }
1396
1397 if (!*field_val) {
1398 goto error;
1399 }
1400
1401 goto end;
1402
1403 error:
1404 lttng_event_field_value_destroy(*field_val);
1405 *field_val = NULL;
1406 ret = -1;
1407
1408 end:
1409 return ret;
1410 }
1411
1412 static
1413 struct lttng_event_field_value *event_field_value_from_capture_payload(
1414 const struct lttng_condition_on_event *condition,
1415 const char *capture_payload, size_t capture_payload_size)
1416 {
1417 struct lttng_event_field_value *ret = NULL;
1418 msgpack_unpacked unpacked;
1419 msgpack_unpack_return unpack_return;
1420 const msgpack_object *root_obj;
1421 const msgpack_object_array *root_array_obj;
1422 size_t i;
1423 size_t count;
1424
1425 assert(condition);
1426 assert(capture_payload);
1427
1428 /* Initialize value. */
1429 msgpack_unpacked_init(&unpacked);
1430
1431 /* Decode. */
1432 unpack_return = msgpack_unpack_next(&unpacked, capture_payload,
1433 capture_payload_size, NULL);
1434 if (unpack_return != MSGPACK_UNPACK_SUCCESS) {
1435 ERR("msgpack_unpack_next() failed to decode the "
1436 "MessagePack-encoded capture payload: "
1437 "size = %zu, ret = %d",
1438 capture_payload_size, unpack_return);
1439 goto error;
1440 }
1441
1442 /* Get root array. */
1443 root_obj = &unpacked.data;
1444
1445 if (root_obj->type != MSGPACK_OBJECT_ARRAY) {
1446 ERR("Expecting an array as the root object: type = %s",
1447 msgpack_object_type_str(root_obj->type));
1448 goto error;
1449 }
1450
1451 root_array_obj = &root_obj->via.array;
1452
1453 /* Create an empty root array event field value. */
1454 ret = lttng_event_field_value_array_create();
1455 if (!ret) {
1456 goto error;
1457 }
1458
1459 /*
1460 * For each capture descriptor in the condition object:
1461 *
1462 * 1. Get its corresponding captured field value MessagePack
1463 * object.
1464 *
1465 * 2. Create a corresponding event field value.
1466 *
1467 * 3. Append it to `ret` (the root array event field value).
1468 */
1469 count = lttng_dynamic_pointer_array_get_count(
1470 &condition->capture_descriptors);
1471 assert(count > 0);
1472
1473 for (i = 0; i < count; i++) {
1474 const struct lttng_capture_descriptor *capture_descriptor =
1475 lttng_condition_on_event_get_internal_capture_descriptor_at_index(
1476 &condition->parent, i);
1477 const msgpack_object *elem_obj;
1478 struct lttng_event_field_value *elem_field_val;
1479 int iret;
1480
1481 assert(capture_descriptor);
1482
1483 elem_obj = &root_array_obj->ptr[i];
1484 iret = event_field_value_from_obj(elem_obj,
1485 &elem_field_val);
1486 if (iret) {
1487 goto error;
1488 }
1489
1490 if (elem_field_val) {
1491 iret = lttng_event_field_value_array_append(ret,
1492 elem_field_val);
1493 } else {
1494 iret = lttng_event_field_value_array_append_unavailable(
1495 ret);
1496 }
1497
1498 if (iret) {
1499 lttng_event_field_value_destroy(elem_field_val);
1500 goto error;
1501 }
1502 }
1503
1504 goto end;
1505
1506 error:
1507 lttng_event_field_value_destroy(ret);
1508 ret = NULL;
1509
1510 end:
1511 msgpack_unpacked_destroy(&unpacked);
1512 return ret;
1513 }
1514
1515 LTTNG_HIDDEN
1516 struct lttng_evaluation *lttng_evaluation_on_event_create(
1517 const struct lttng_condition_on_event *condition,
1518 const char *trigger_name,
1519 const char *capture_payload, size_t capture_payload_size,
1520 bool decode_capture_payload)
1521 {
1522 struct lttng_evaluation_on_event *hit;
1523 struct lttng_evaluation *evaluation = NULL;
1524
1525 hit = zmalloc(sizeof(struct lttng_evaluation_on_event));
1526 if (!hit) {
1527 goto error;
1528 }
1529
1530 hit->name = strdup(trigger_name);
1531 if (!hit->name) {
1532 goto error;
1533 }
1534
1535 lttng_dynamic_buffer_init(&hit->capture_payload);
1536
1537 if (capture_payload) {
1538 const int ret = lttng_dynamic_buffer_append(
1539 &hit->capture_payload, capture_payload,
1540 capture_payload_size);
1541 if (ret) {
1542 ERR("Failed to initialize capture payload of event rule evaluation");
1543 goto error;
1544 }
1545
1546 if (decode_capture_payload) {
1547 hit->captured_values =
1548 event_field_value_from_capture_payload(
1549 condition,
1550 capture_payload,
1551 capture_payload_size);
1552 if (!hit->captured_values) {
1553 ERR("Failed to decode the capture payload: size = %zu",
1554 capture_payload_size);
1555 goto error;
1556 }
1557 }
1558 }
1559
1560 hit->parent.type = LTTNG_CONDITION_TYPE_ON_EVENT;
1561 hit->parent.serialize = lttng_evaluation_on_event_serialize;
1562 hit->parent.destroy = lttng_evaluation_on_event_destroy;
1563
1564 evaluation = &hit->parent;
1565 hit = NULL;
1566
1567 error:
1568 if (hit) {
1569 lttng_evaluation_on_event_destroy(&hit->parent);
1570 }
1571
1572 return evaluation;
1573 }
1574
1575 enum lttng_evaluation_on_event_status
1576 lttng_evaluation_on_event_get_captured_values(
1577 const struct lttng_evaluation *evaluation,
1578 const struct lttng_event_field_value **field_val)
1579 {
1580 struct lttng_evaluation_on_event *hit;
1581 enum lttng_evaluation_on_event_status status =
1582 LTTNG_EVALUATION_ON_EVENT_STATUS_OK;
1583
1584 if (!evaluation || !is_on_event_evaluation(evaluation) ||
1585 !field_val) {
1586 status = LTTNG_EVALUATION_ON_EVENT_STATUS_INVALID;
1587 goto end;
1588 }
1589
1590 hit = container_of(evaluation, struct lttng_evaluation_on_event,
1591 parent);
1592 if (!hit->captured_values) {
1593 status = LTTNG_EVALUATION_ON_EVENT_STATUS_NONE;
1594 goto end;
1595 }
1596
1597 *field_val = hit->captured_values;
1598
1599 end:
1600 return status;
1601 }
1602
1603 enum lttng_evaluation_status lttng_evaluation_on_event_get_trigger_name(
1604 const struct lttng_evaluation *evaluation, const char **name)
1605 {
1606 struct lttng_evaluation_on_event *hit;
1607 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
1608
1609 if (!evaluation || !is_on_event_evaluation(evaluation) || !name) {
1610 status = LTTNG_EVALUATION_STATUS_INVALID;
1611 goto end;
1612 }
1613
1614 hit = container_of(
1615 evaluation, struct lttng_evaluation_on_event, parent);
1616 *name = hit->name;
1617 end:
1618 return status;
1619 }
1620
1621 LTTNG_HIDDEN
1622 enum lttng_error_code
1623 lttng_condition_on_event_generate_capture_descriptor_bytecode(
1624 struct lttng_condition *condition)
1625 {
1626 enum lttng_error_code ret;
1627 enum lttng_condition_status status;
1628 unsigned int capture_count, i;
1629
1630 if (!condition || !IS_ON_EVENT_CONDITION(condition)) {
1631 ret = LTTNG_ERR_FATAL;
1632 goto end;
1633 }
1634
1635 status = lttng_condition_on_event_get_capture_descriptor_count(
1636 condition, &capture_count);
1637 if (status != LTTNG_CONDITION_STATUS_OK) {
1638 ret = LTTNG_ERR_FATAL;
1639 goto end;
1640 }
1641
1642 for (i = 0; i < capture_count; i++) {
1643 struct lttng_capture_descriptor *local_capture_desc =
1644 lttng_condition_on_event_get_internal_capture_descriptor_at_index(
1645 condition, i);
1646
1647 if (local_capture_desc == NULL) {
1648 ret = LTTNG_ERR_FATAL;
1649 goto end;
1650 }
1651
1652 /* Generate the bytecode. */
1653 status = lttng_event_expr_to_bytecode(
1654 local_capture_desc->event_expression,
1655 &local_capture_desc->bytecode);
1656 if (status < 0 || local_capture_desc->bytecode == NULL) {
1657 ret = LTTNG_ERR_INVALID_CAPTURE_EXPRESSION;
1658 goto end;
1659 }
1660 }
1661
1662 /* Everything went better than expected */
1663 ret = LTTNG_OK;
1664
1665 end:
1666 return ret;
1667 }
1668
1669 LTTNG_HIDDEN
1670 const struct lttng_bytecode *
1671 lttng_condition_on_event_get_capture_bytecode_at_index(
1672 const struct lttng_condition *condition, unsigned int index)
1673 {
1674 const struct lttng_condition_on_event *on_event_cond =
1675 container_of(condition,
1676 const struct lttng_condition_on_event,
1677 parent);
1678 struct lttng_capture_descriptor *desc = NULL;
1679 struct lttng_bytecode *bytecode = NULL;
1680 unsigned int count;
1681 enum lttng_condition_status status;
1682
1683 if (!condition || !IS_ON_EVENT_CONDITION(condition)) {
1684 goto end;
1685 }
1686
1687 status = lttng_condition_on_event_get_capture_descriptor_count(
1688 condition, &count);
1689 if (status != LTTNG_CONDITION_STATUS_OK) {
1690 goto end;
1691 }
1692
1693 if (index >= count) {
1694 goto end;
1695 }
1696
1697 desc = lttng_dynamic_pointer_array_get_pointer(
1698 &on_event_cond->capture_descriptors, index);
1699 if (desc == NULL) {
1700 goto end;
1701 }
1702
1703 bytecode = desc->bytecode;
1704 end:
1705 return bytecode;
1706 }
This page took 0.098554 seconds and 5 git commands to generate.