2 * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
9 #include <common/error.h>
10 #include <common/macros.h>
12 #include <lttng/condition/condition-internal.h>
13 #include <lttng/condition/event-rule-internal.h>
14 #include <lttng/condition/event-rule.h>
15 #include <lttng/event-expr-internal.h>
16 #include <lttng/event-expr.h>
17 #include <lttng/event-rule/event-rule-internal.h>
20 #include <vendor/msgpack/msgpack.h>
22 #define IS_EVENT_RULE_CONDITION(condition) \
23 (lttng_condition_get_type(condition) == \
24 LTTNG_CONDITION_TYPE_EVENT_RULE_HIT)
26 static bool is_event_rule_evaluation(const struct lttng_evaluation
*evaluation
)
28 enum lttng_condition_type type
= lttng_evaluation_get_type(evaluation
);
30 return type
== LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
;
33 static bool lttng_condition_event_rule_validate(
34 const struct lttng_condition
*condition
);
35 static int lttng_condition_event_rule_serialize(
36 const struct lttng_condition
*condition
,
37 struct lttng_payload
*payload
);
38 static bool lttng_condition_event_rule_is_equal(
39 const struct lttng_condition
*_a
,
40 const struct lttng_condition
*_b
);
41 static void lttng_condition_event_rule_destroy(
42 struct lttng_condition
*condition
);
44 static bool lttng_condition_event_rule_validate(
45 const struct lttng_condition
*condition
)
48 struct lttng_condition_event_rule
*event_rule
;
54 event_rule
= container_of(
55 condition
, struct lttng_condition_event_rule
, parent
);
56 if (!event_rule
->rule
) {
57 ERR("Invalid event rule condition: a rule must be set.");
61 valid
= lttng_event_rule_validate(event_rule
->rule
);
67 * Serializes the C string `str` into `buf`.
69 * Encoding is the length of `str` plus one (for the null character),
70 * and then the string, including its null terminator.
73 int serialize_cstr(const char *str
, struct lttng_dynamic_buffer
*buf
)
76 const uint32_t len
= strlen(str
) + 1;
78 /* Serialize the length, including the null terminator. */
79 DBG("Serializing C string's length (including null terminator): "
81 ret
= lttng_dynamic_buffer_append(buf
, &len
, sizeof(len
));
86 /* Serialize the string. */
87 DBG("Serializing C string: '%s'", str
);
88 ret
= lttng_dynamic_buffer_append(buf
, str
, len
);
98 * Serializes the event expression `expr` into `buf`.
101 int serialize_event_expr(const struct lttng_event_expr
*expr
,
102 struct lttng_payload
*payload
)
104 const uint8_t type
= expr
->type
;
107 /* Serialize the expression's type. */
108 DBG("Serializing event expression's type: %d", expr
->type
);
109 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &type
, sizeof(type
));
114 /* Serialize the expression */
115 switch (expr
->type
) {
116 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
117 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
119 const struct lttng_event_expr_field
*field_expr
=
121 const struct lttng_event_expr_field
,
124 /* Serialize the field name. */
125 DBG("Serializing field event expression's field name: '%s'",
127 ret
= serialize_cstr(field_expr
->name
, &payload
->buffer
);
134 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
136 const struct lttng_event_expr_app_specific_context_field
*field_expr
=
138 const struct lttng_event_expr_app_specific_context_field
,
141 /* Serialize the provider name. */
142 DBG("Serializing app-specific context field event expression's "
143 "provider name: '%s'",
144 field_expr
->provider_name
);
145 ret
= serialize_cstr(field_expr
->provider_name
, &payload
->buffer
);
150 /* Serialize the type name. */
151 DBG("Serializing app-specific context field event expression's "
153 field_expr
->provider_name
);
154 ret
= serialize_cstr(field_expr
->type_name
, &payload
->buffer
);
161 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
163 const struct lttng_event_expr_array_field_element
*elem_expr
=
165 const struct lttng_event_expr_array_field_element
,
167 const uint32_t index
= elem_expr
->index
;
169 /* Serialize the index. */
170 DBG("Serializing array field element event expression's "
171 "index: %u", elem_expr
->index
);
172 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &index
, sizeof(index
));
177 /* Serialize the parent array field expression. */
178 DBG("Serializing array field element event expression's "
179 "parent array field event expression.");
180 ret
= serialize_event_expr(elem_expr
->array_field_expr
, payload
);
196 struct lttng_capture_descriptor
*
197 lttng_condition_event_rule_get_internal_capture_descriptor_at_index(
198 const struct lttng_condition
*condition
, unsigned int index
)
200 const struct lttng_condition_event_rule
*event_rule_cond
=
201 container_of(condition
,
202 const struct lttng_condition_event_rule
,
204 struct lttng_capture_descriptor
*desc
= NULL
;
206 enum lttng_condition_status status
;
208 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
)) {
212 status
= lttng_condition_event_rule_get_capture_descriptor_count(
214 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
218 if (index
>= count
) {
222 desc
= lttng_dynamic_pointer_array_get_pointer(
223 &event_rule_cond
->capture_descriptors
, index
);
228 static int lttng_condition_event_rule_serialize(
229 const struct lttng_condition
*condition
,
230 struct lttng_payload
*payload
)
233 struct lttng_condition_event_rule
*event_rule
;
234 enum lttng_condition_status status
;
235 /* Used for iteration and communication (size matters). */
236 uint32_t i
, capture_descr_count
;
238 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
)) {
243 DBG("Serializing event rule condition");
244 event_rule
= container_of(
245 condition
, struct lttng_condition_event_rule
, parent
);
247 DBG("Serializing event rule condition's event rule");
248 ret
= lttng_event_rule_serialize(event_rule
->rule
, payload
);
253 status
= lttng_condition_event_rule_get_capture_descriptor_count(
254 condition
, &capture_descr_count
);
255 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
260 DBG("Serializing event rule condition's capture descriptor count: %" PRIu32
,
261 capture_descr_count
);
262 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &capture_descr_count
,
263 sizeof(capture_descr_count
));
268 for (i
= 0; i
< capture_descr_count
; i
++) {
269 const struct lttng_capture_descriptor
*desc
=
270 lttng_condition_event_rule_get_internal_capture_descriptor_at_index(
273 DBG("Serializing event rule condition's capture descriptor %" PRIu32
,
275 ret
= serialize_event_expr(desc
->event_expression
, payload
);
286 bool capture_descriptors_are_equal(
287 const struct lttng_condition
*condition_a
,
288 const struct lttng_condition
*condition_b
)
290 bool is_equal
= true;
291 unsigned int capture_descr_count_a
;
292 unsigned int capture_descr_count_b
;
294 enum lttng_condition_status status
;
296 status
= lttng_condition_event_rule_get_capture_descriptor_count(
297 condition_a
, &capture_descr_count_a
);
298 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
302 status
= lttng_condition_event_rule_get_capture_descriptor_count(
303 condition_b
, &capture_descr_count_b
);
304 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
308 if (capture_descr_count_a
!= capture_descr_count_b
) {
312 for (i
= 0; i
< capture_descr_count_a
; i
++) {
313 const struct lttng_event_expr
*expr_a
=
314 lttng_condition_event_rule_get_capture_descriptor_at_index(
317 const struct lttng_event_expr
*expr_b
=
318 lttng_condition_event_rule_get_capture_descriptor_at_index(
322 if (!lttng_event_expr_is_equal(expr_a
, expr_b
)) {
336 static bool lttng_condition_event_rule_is_equal(
337 const struct lttng_condition
*_a
,
338 const struct lttng_condition
*_b
)
340 bool is_equal
= false;
341 struct lttng_condition_event_rule
*a
, *b
;
343 a
= container_of(_a
, struct lttng_condition_event_rule
, parent
);
344 b
= container_of(_b
, struct lttng_condition_event_rule
, parent
);
346 /* Both event rules must be set or both must be unset. */
347 if ((a
->rule
&& !b
->rule
) || (!a
->rule
&& b
->rule
)) {
348 WARN("Comparing event_rule conditions with uninitialized rule");
352 is_equal
= lttng_event_rule_is_equal(a
->rule
, b
->rule
);
357 is_equal
= capture_descriptors_are_equal(_a
, _b
);
363 static void lttng_condition_event_rule_destroy(
364 struct lttng_condition
*condition
)
366 struct lttng_condition_event_rule
*event_rule
;
368 event_rule
= container_of(
369 condition
, struct lttng_condition_event_rule
, parent
);
371 lttng_event_rule_put(event_rule
->rule
);
372 lttng_dynamic_pointer_array_reset(&event_rule
->capture_descriptors
);
377 void destroy_capture_descriptor(void *ptr
)
379 struct lttng_capture_descriptor
*desc
=
380 (struct lttng_capture_descriptor
*) ptr
;
382 lttng_event_expr_destroy(desc
->event_expression
);
383 free(desc
->bytecode
);
387 struct lttng_condition
*lttng_condition_event_rule_create(
388 struct lttng_event_rule
*rule
)
390 struct lttng_condition
*parent
= NULL
;
391 struct lttng_condition_event_rule
*condition
= NULL
;
397 condition
= zmalloc(sizeof(struct lttng_condition_event_rule
));
402 lttng_condition_init(&condition
->parent
,
403 LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
);
404 condition
->parent
.validate
= lttng_condition_event_rule_validate
,
405 condition
->parent
.serialize
= lttng_condition_event_rule_serialize
,
406 condition
->parent
.equal
= lttng_condition_event_rule_is_equal
,
407 condition
->parent
.destroy
= lttng_condition_event_rule_destroy
,
409 lttng_event_rule_get(rule
);
410 condition
->rule
= rule
;
413 lttng_dynamic_pointer_array_init(&condition
->capture_descriptors
,
414 destroy_capture_descriptor
);
416 parent
= &condition
->parent
;
422 uint64_t uint_from_buffer(const struct lttng_buffer_view
*view
, size_t size
,
426 const struct lttng_buffer_view uint_view
=
427 lttng_buffer_view_from_view(view
, *offset
, size
);
429 if (!lttng_buffer_view_is_valid(&uint_view
)) {
436 ret
= (uint64_t) *uint_view
.data
;
438 case sizeof(uint32_t):
442 memcpy(&u32
, uint_view
.data
, sizeof(u32
));
443 ret
= (uint64_t) u32
;
447 memcpy(&ret
, uint_view
.data
, sizeof(ret
));
460 const char *str_from_buffer(const struct lttng_buffer_view
*view
,
466 len
= uint_from_buffer(view
, sizeof(uint32_t), offset
);
467 if (len
== UINT64_C(-1)) {
471 ret
= &view
->data
[*offset
];
473 if (!lttng_buffer_view_contains_string(view
, ret
, len
)) {
488 struct lttng_event_expr
*event_expr_from_payload(
489 struct lttng_payload_view
*view
, size_t *offset
)
491 struct lttng_event_expr
*expr
= NULL
;
495 type
= uint_from_buffer(&view
->buffer
, sizeof(uint8_t), offset
);
496 if (type
== UINT64_C(-1)) {
501 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
502 str
= str_from_buffer(&view
->buffer
, offset
);
507 expr
= lttng_event_expr_event_payload_field_create(str
);
509 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
510 str
= str_from_buffer(&view
->buffer
, offset
);
515 expr
= lttng_event_expr_channel_context_field_create(str
);
517 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
519 const char *provider_name
;
520 const char *type_name
;
522 provider_name
= str_from_buffer(&view
->buffer
, offset
);
523 if (!provider_name
) {
527 type_name
= str_from_buffer(&view
->buffer
, offset
);
532 expr
= lttng_event_expr_app_specific_context_field_create(
533 provider_name
, type_name
);
536 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
538 struct lttng_event_expr
*array_field_expr
;
539 const uint64_t index
= uint_from_buffer(
540 &view
->buffer
, sizeof(uint32_t), offset
);
542 if (index
== UINT64_C(-1)) {
546 /* Array field expression is the encoded after this. */
547 array_field_expr
= event_expr_from_payload(view
, offset
);
548 if (!array_field_expr
) {
552 /* Move ownership of `array_field_expr` to new expression. */
553 expr
= lttng_event_expr_array_field_element_create(
554 array_field_expr
, (unsigned int) index
);
556 /* `array_field_expr` not moved: destroy it. */
557 lttng_event_expr_destroy(array_field_expr
);
569 lttng_event_expr_destroy(expr
);
577 ssize_t
lttng_condition_event_rule_create_from_payload(
578 struct lttng_payload_view
*view
,
579 struct lttng_condition
**_condition
)
581 ssize_t consumed_length
;
583 ssize_t event_rule_length
;
584 uint32_t i
, capture_descr_count
;
585 struct lttng_condition
*condition
= NULL
;
586 struct lttng_event_rule
*event_rule
= NULL
;
588 if (!view
|| !_condition
) {
592 /* Struct lttng_event_rule. */
594 struct lttng_payload_view event_rule_view
=
595 lttng_payload_view_from_view(view
, offset
, -1);
597 event_rule_length
= lttng_event_rule_create_from_payload(
598 &event_rule_view
, &event_rule
);
601 if (event_rule_length
< 0 || !event_rule
) {
605 /* Create condition (no capture descriptors yet) at this point. */
606 condition
= lttng_condition_event_rule_create(event_rule
);
612 /* Capture descriptor count. */
613 assert(event_rule_length
>= 0);
614 offset
+= (size_t) event_rule_length
;
615 capture_descr_count
= uint_from_buffer(&view
->buffer
, sizeof(uint32_t), &offset
);
616 if (capture_descr_count
== UINT32_C(-1)) {
620 /* Capture descriptors. */
621 for (i
= 0; i
< capture_descr_count
; i
++) {
622 enum lttng_condition_status status
;
623 struct lttng_event_expr
*expr
= event_expr_from_payload(
630 /* Move ownership of `expr` to `condition`. */
631 status
= lttng_condition_event_rule_append_capture_descriptor(
633 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
634 /* `expr` not moved: destroy it. */
635 lttng_event_expr_destroy(expr
);
640 consumed_length
= (ssize_t
) offset
;
641 *_condition
= condition
;
646 consumed_length
= -1;
649 lttng_event_rule_put(event_rule
);
650 lttng_condition_put(condition
);
651 return consumed_length
;
655 enum lttng_condition_status
lttng_condition_event_rule_borrow_rule_mutable(
656 const struct lttng_condition
*condition
,
657 struct lttng_event_rule
**rule
)
659 struct lttng_condition_event_rule
*event_rule
;
660 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
662 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
) || !rule
) {
663 status
= LTTNG_CONDITION_STATUS_INVALID
;
667 event_rule
= container_of(
668 condition
, struct lttng_condition_event_rule
, parent
);
669 if (!event_rule
->rule
) {
670 status
= LTTNG_CONDITION_STATUS_UNSET
;
674 *rule
= event_rule
->rule
;
679 enum lttng_condition_status
lttng_condition_event_rule_get_rule(
680 const struct lttng_condition
*condition
,
681 const struct lttng_event_rule
**rule
)
683 struct lttng_event_rule
*mutable_rule
= NULL
;
684 const enum lttng_condition_status status
=
685 lttng_condition_event_rule_borrow_rule_mutable(
686 condition
, &mutable_rule
);
688 *rule
= mutable_rule
;
692 enum lttng_condition_status
693 lttng_condition_event_rule_append_capture_descriptor(
694 struct lttng_condition
*condition
,
695 struct lttng_event_expr
*expr
)
698 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
699 struct lttng_condition_event_rule
*event_rule_cond
=
700 container_of(condition
,
701 struct lttng_condition_event_rule
, parent
);
702 struct lttng_capture_descriptor
*descriptor
= NULL
;
704 /* Only accept l-values. */
705 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
) || !expr
||
706 !lttng_event_expr_is_lvalue(expr
)) {
707 status
= LTTNG_CONDITION_STATUS_INVALID
;
711 descriptor
= malloc(sizeof(*descriptor
));
712 if (descriptor
== NULL
) {
713 status
= LTTNG_CONDITION_STATUS_ERROR
;
717 descriptor
->event_expression
= expr
;
718 descriptor
->bytecode
= NULL
;
720 ret
= lttng_dynamic_pointer_array_add_pointer(
721 &event_rule_cond
->capture_descriptors
, descriptor
);
723 status
= LTTNG_CONDITION_STATUS_ERROR
;
727 /* Ownership is transfered to the internal capture_descriptors array */
734 enum lttng_condition_status
735 lttng_condition_event_rule_get_capture_descriptor_count(
736 const struct lttng_condition
*condition
, unsigned int *count
)
738 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
739 const struct lttng_condition_event_rule
*event_rule_cond
=
740 container_of(condition
,
741 const struct lttng_condition_event_rule
,
744 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
) || !count
) {
745 status
= LTTNG_CONDITION_STATUS_INVALID
;
749 *count
= lttng_dynamic_pointer_array_get_count(
750 &event_rule_cond
->capture_descriptors
);
756 const struct lttng_event_expr
*
757 lttng_condition_event_rule_get_capture_descriptor_at_index(
758 const struct lttng_condition
*condition
, unsigned int index
)
760 const struct lttng_event_expr
*expr
= NULL
;
761 const struct lttng_capture_descriptor
*desc
= NULL
;
763 desc
= lttng_condition_event_rule_get_internal_capture_descriptor_at_index(
768 expr
= desc
->event_expression
;
775 ssize_t
lttng_evaluation_event_rule_create_from_payload(
776 struct lttng_payload_view
*view
,
777 struct lttng_evaluation
**_evaluation
)
779 ssize_t ret
, offset
= 0;
780 const char *trigger_name
;
781 struct lttng_evaluation
*evaluation
= NULL
;
782 const struct lttng_evaluation_event_rule_comm
*header
;
783 const struct lttng_payload_view header_view
=
784 lttng_payload_view_from_view(
785 view
, 0, sizeof(*header
));
792 if (!lttng_payload_view_is_valid(&header_view
)) {
793 ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain header");
798 header
= (typeof(header
)) header_view
.buffer
.data
;
800 /* Map the originating trigger's name. */
801 offset
+= sizeof(*header
);
803 struct lttng_payload_view current_view
=
804 lttng_payload_view_from_view(view
, offset
,
805 header
->trigger_name_length
);
807 if (!lttng_payload_view_is_valid(¤t_view
)) {
808 ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain trigger name");
813 trigger_name
= current_view
.buffer
.data
;
814 if (!lttng_buffer_view_contains_string(¤t_view
.buffer
,
815 trigger_name
, header
->trigger_name_length
)) {
816 ERR("Failed to initialize from malformed event rule evaluation: invalid trigger name");
822 offset
+= header
->trigger_name_length
;
824 evaluation
= lttng_evaluation_event_rule_create(trigger_name
);
830 *_evaluation
= evaluation
;
835 lttng_evaluation_destroy(evaluation
);
839 static int lttng_evaluation_event_rule_serialize(
840 const struct lttng_evaluation
*evaluation
,
841 struct lttng_payload
*payload
)
844 struct lttng_evaluation_event_rule
*hit
;
845 struct lttng_evaluation_event_rule_comm comm
;
848 evaluation
, struct lttng_evaluation_event_rule
, parent
);
851 comm
.trigger_name_length
= strlen(hit
->name
) + 1;
853 ret
= lttng_dynamic_buffer_append(
854 &payload
->buffer
, &comm
, sizeof(comm
));
859 ret
= lttng_dynamic_buffer_append(
860 &payload
->buffer
, hit
->name
, comm
.trigger_name_length
);
865 static void lttng_evaluation_event_rule_destroy(
866 struct lttng_evaluation
*evaluation
)
868 struct lttng_evaluation_event_rule
*hit
;
871 evaluation
, struct lttng_evaluation_event_rule
, parent
);
877 struct lttng_evaluation
*lttng_evaluation_event_rule_create(
878 const char *trigger_name
)
880 struct lttng_evaluation_event_rule
*hit
;
881 struct lttng_evaluation
*evaluation
= NULL
;
883 hit
= zmalloc(sizeof(struct lttng_evaluation_event_rule
));
888 hit
->name
= strdup(trigger_name
);
893 hit
->parent
.type
= LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
;
894 hit
->parent
.serialize
= lttng_evaluation_event_rule_serialize
;
895 hit
->parent
.destroy
= lttng_evaluation_event_rule_destroy
;
897 evaluation
= &hit
->parent
;
902 lttng_evaluation_event_rule_destroy(&hit
->parent
);
908 enum lttng_evaluation_status
lttng_evaluation_event_rule_get_trigger_name(
909 const struct lttng_evaluation
*evaluation
, const char **name
)
911 struct lttng_evaluation_event_rule
*hit
;
912 enum lttng_evaluation_status status
= LTTNG_EVALUATION_STATUS_OK
;
914 if (!evaluation
|| !is_event_rule_evaluation(evaluation
) || !name
) {
915 status
= LTTNG_EVALUATION_STATUS_INVALID
;
920 evaluation
, struct lttng_evaluation_event_rule
, parent
);