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>
21 #define IS_EVENT_RULE_CONDITION(condition) \
22 (lttng_condition_get_type(condition) == \
23 LTTNG_CONDITION_TYPE_EVENT_RULE_HIT)
25 static bool is_event_rule_evaluation(const struct lttng_evaluation
*evaluation
)
27 enum lttng_condition_type type
= lttng_evaluation_get_type(evaluation
);
29 return type
== LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
;
32 static bool lttng_condition_event_rule_validate(
33 const struct lttng_condition
*condition
);
34 static int lttng_condition_event_rule_serialize(
35 const struct lttng_condition
*condition
,
36 struct lttng_payload
*payload
);
37 static bool lttng_condition_event_rule_is_equal(
38 const struct lttng_condition
*_a
,
39 const struct lttng_condition
*_b
);
40 static void lttng_condition_event_rule_destroy(
41 struct lttng_condition
*condition
);
43 static bool lttng_condition_event_rule_validate(
44 const struct lttng_condition
*condition
)
47 struct lttng_condition_event_rule
*event_rule
;
53 event_rule
= container_of(
54 condition
, struct lttng_condition_event_rule
, parent
);
55 if (!event_rule
->rule
) {
56 ERR("Invalid event rule condition: a rule must be set.");
60 valid
= lttng_event_rule_validate(event_rule
->rule
);
66 * Serializes the C string `str` into `buf`.
68 * Encoding is the length of `str` plus one (for the null character),
69 * and then the string, including its null terminator.
72 int serialize_cstr(const char *str
, struct lttng_dynamic_buffer
*buf
)
75 const uint32_t len
= strlen(str
) + 1;
77 /* Serialize the length, including the null terminator. */
78 DBG("Serializing C string's length (including null terminator): "
80 ret
= lttng_dynamic_buffer_append(buf
, &len
, sizeof(len
));
85 /* Serialize the string. */
86 DBG("Serializing C string: '%s'", str
);
87 ret
= lttng_dynamic_buffer_append(buf
, str
, len
);
97 * Serializes the event expression `expr` into `buf`.
100 int serialize_event_expr(const struct lttng_event_expr
*expr
,
101 struct lttng_payload
*payload
)
103 const uint8_t type
= expr
->type
;
106 /* Serialize the expression's type. */
107 DBG("Serializing event expression's type: %d", expr
->type
);
108 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &type
, sizeof(type
));
113 /* Serialize the expression */
114 switch (expr
->type
) {
115 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
116 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
118 const struct lttng_event_expr_field
*field_expr
=
120 const struct lttng_event_expr_field
,
123 /* Serialize the field name. */
124 DBG("Serializing field event expression's field name: '%s'",
126 ret
= serialize_cstr(field_expr
->name
, &payload
->buffer
);
133 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
135 const struct lttng_event_expr_app_specific_context_field
*field_expr
=
137 const struct lttng_event_expr_app_specific_context_field
,
140 /* Serialize the provider name. */
141 DBG("Serializing app-specific context field event expression's "
142 "provider name: '%s'",
143 field_expr
->provider_name
);
144 ret
= serialize_cstr(field_expr
->provider_name
, &payload
->buffer
);
149 /* Serialize the type name. */
150 DBG("Serializing app-specific context field event expression's "
152 field_expr
->provider_name
);
153 ret
= serialize_cstr(field_expr
->type_name
, &payload
->buffer
);
160 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
162 const struct lttng_event_expr_array_field_element
*elem_expr
=
164 const struct lttng_event_expr_array_field_element
,
166 const uint32_t index
= elem_expr
->index
;
168 /* Serialize the index. */
169 DBG("Serializing array field element event expression's "
170 "index: %u", elem_expr
->index
);
171 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &index
, sizeof(index
));
176 /* Serialize the parent array field expression. */
177 DBG("Serializing array field element event expression's "
178 "parent array field event expression.");
179 ret
= serialize_event_expr(elem_expr
->array_field_expr
, payload
);
194 static int lttng_condition_event_rule_serialize(
195 const struct lttng_condition
*condition
,
196 struct lttng_payload
*payload
)
199 struct lttng_condition_event_rule
*event_rule
;
200 /* Used for iteration and communication (size matters). */
201 uint32_t i
, capture_descr_count
;
203 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
)) {
208 DBG("Serializing event rule condition");
209 event_rule
= container_of(
210 condition
, struct lttng_condition_event_rule
, parent
);
212 DBG("Serializing event rule condition's event rule");
213 ret
= lttng_event_rule_serialize(event_rule
->rule
, payload
);
218 capture_descr_count
= lttng_dynamic_pointer_array_get_count(
219 &event_rule
->capture_descriptors
);
220 DBG("Serializing event rule condition's capture descriptor count: %" PRIu32
,
221 capture_descr_count
);
222 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &capture_descr_count
,
223 sizeof(capture_descr_count
));
228 for (i
= 0; i
< capture_descr_count
; i
++) {
229 const struct lttng_event_expr
*expr
=
230 lttng_dynamic_pointer_array_get_pointer(
231 &event_rule
->capture_descriptors
, i
);
233 DBG("Serializing event rule condition's capture descriptor %" PRIu32
,
235 ret
= serialize_event_expr(expr
, payload
);
246 bool capture_descriptors_are_equal(
247 const struct lttng_condition_event_rule
*condition_a
,
248 const struct lttng_condition_event_rule
*condition_b
)
250 bool is_equal
= true;
251 size_t capture_descr_count_a
;
252 size_t capture_descr_count_b
;
255 capture_descr_count_a
= lttng_dynamic_pointer_array_get_count(
256 &condition_a
->capture_descriptors
);
257 capture_descr_count_b
= lttng_dynamic_pointer_array_get_count(
258 &condition_b
->capture_descriptors
);
260 if (capture_descr_count_a
!= capture_descr_count_b
) {
264 for (i
= 0; i
< capture_descr_count_a
; i
++) {
265 const struct lttng_event_expr
*expr_a
=
266 lttng_dynamic_pointer_array_get_pointer(
267 &condition_a
->capture_descriptors
,
269 const struct lttng_event_expr
*expr_b
=
270 lttng_dynamic_pointer_array_get_pointer(
271 &condition_b
->capture_descriptors
,
274 if (!lttng_event_expr_is_equal(expr_a
, expr_b
)) {
288 static bool lttng_condition_event_rule_is_equal(
289 const struct lttng_condition
*_a
,
290 const struct lttng_condition
*_b
)
292 bool is_equal
= false;
293 struct lttng_condition_event_rule
*a
, *b
;
295 a
= container_of(_a
, struct lttng_condition_event_rule
, parent
);
296 b
= container_of(_b
, struct lttng_condition_event_rule
, parent
);
298 /* Both event rules must be set or both must be unset. */
299 if ((a
->rule
&& !b
->rule
) || (!a
->rule
&& b
->rule
)) {
300 WARN("Comparing event_rule conditions with uninitialized rule");
304 is_equal
= lttng_event_rule_is_equal(a
->rule
, b
->rule
);
309 is_equal
= capture_descriptors_are_equal(a
, b
);
315 static void lttng_condition_event_rule_destroy(
316 struct lttng_condition
*condition
)
318 struct lttng_condition_event_rule
*event_rule
;
320 event_rule
= container_of(
321 condition
, struct lttng_condition_event_rule
, parent
);
323 lttng_event_rule_put(event_rule
->rule
);
324 lttng_dynamic_pointer_array_reset(&event_rule
->capture_descriptors
);
329 void destroy_event_expr(void *ptr
)
331 lttng_event_expr_destroy(ptr
);
334 struct lttng_condition
*lttng_condition_event_rule_create(
335 struct lttng_event_rule
*rule
)
337 struct lttng_condition
*parent
= NULL
;
338 struct lttng_condition_event_rule
*condition
= NULL
;
344 condition
= zmalloc(sizeof(struct lttng_condition_event_rule
));
349 lttng_condition_init(&condition
->parent
,
350 LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
);
351 condition
->parent
.validate
= lttng_condition_event_rule_validate
,
352 condition
->parent
.serialize
= lttng_condition_event_rule_serialize
,
353 condition
->parent
.equal
= lttng_condition_event_rule_is_equal
,
354 condition
->parent
.destroy
= lttng_condition_event_rule_destroy
,
356 lttng_event_rule_get(rule
);
357 condition
->rule
= rule
;
360 lttng_dynamic_pointer_array_init(&condition
->capture_descriptors
,
363 parent
= &condition
->parent
;
369 uint64_t uint_from_buffer(const struct lttng_buffer_view
*view
, size_t size
,
373 const struct lttng_buffer_view uint_view
=
374 lttng_buffer_view_from_view(view
, *offset
, size
);
376 if (!lttng_buffer_view_is_valid(&uint_view
)) {
383 ret
= (uint64_t) *uint_view
.data
;
385 case sizeof(uint32_t):
389 memcpy(&u32
, uint_view
.data
, sizeof(u32
));
390 ret
= (uint64_t) u32
;
394 memcpy(&ret
, uint_view
.data
, sizeof(ret
));
407 const char *str_from_buffer(const struct lttng_buffer_view
*view
,
413 len
= uint_from_buffer(view
, sizeof(uint32_t), offset
);
414 if (len
== UINT64_C(-1)) {
418 ret
= &view
->data
[*offset
];
420 if (!lttng_buffer_view_contains_string(view
, ret
, len
)) {
435 struct lttng_event_expr
*event_expr_from_payload(
436 struct lttng_payload_view
*view
, size_t *offset
)
438 struct lttng_event_expr
*expr
= NULL
;
442 type
= uint_from_buffer(&view
->buffer
, sizeof(uint8_t), offset
);
443 if (type
== UINT64_C(-1)) {
448 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
449 str
= str_from_buffer(&view
->buffer
, offset
);
454 expr
= lttng_event_expr_event_payload_field_create(str
);
456 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
457 str
= str_from_buffer(&view
->buffer
, offset
);
462 expr
= lttng_event_expr_channel_context_field_create(str
);
464 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
466 const char *provider_name
;
467 const char *type_name
;
469 provider_name
= str_from_buffer(&view
->buffer
, offset
);
470 if (!provider_name
) {
474 type_name
= str_from_buffer(&view
->buffer
, offset
);
479 expr
= lttng_event_expr_app_specific_context_field_create(
480 provider_name
, type_name
);
483 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
485 struct lttng_event_expr
*array_field_expr
;
486 const uint64_t index
= uint_from_buffer(
487 &view
->buffer
, sizeof(uint32_t), offset
);
489 if (index
== UINT64_C(-1)) {
493 /* Array field expression is the encoded after this. */
494 array_field_expr
= event_expr_from_payload(view
, offset
);
495 if (!array_field_expr
) {
499 /* Move ownership of `array_field_expr` to new expression. */
500 expr
= lttng_event_expr_array_field_element_create(
501 array_field_expr
, (unsigned int) index
);
503 /* `array_field_expr` not moved: destroy it. */
504 lttng_event_expr_destroy(array_field_expr
);
516 lttng_event_expr_destroy(expr
);
524 ssize_t
lttng_condition_event_rule_create_from_payload(
525 struct lttng_payload_view
*view
,
526 struct lttng_condition
**_condition
)
528 ssize_t consumed_length
;
530 ssize_t event_rule_length
;
531 uint32_t i
, capture_descr_count
;
532 struct lttng_condition
*condition
= NULL
;
533 struct lttng_event_rule
*event_rule
= NULL
;
535 if (!view
|| !_condition
) {
539 /* Struct lttng_event_rule. */
541 struct lttng_payload_view event_rule_view
=
542 lttng_payload_view_from_view(view
, offset
, -1);
544 event_rule_length
= lttng_event_rule_create_from_payload(
545 &event_rule_view
, &event_rule
);
548 if (event_rule_length
< 0 || !event_rule
) {
552 /* Create condition (no capture descriptors yet) at this point. */
553 condition
= lttng_condition_event_rule_create(event_rule
);
559 /* Capture descriptor count. */
560 assert(event_rule_length
>= 0);
561 offset
+= (size_t) event_rule_length
;
562 capture_descr_count
= uint_from_buffer(&view
->buffer
, sizeof(uint32_t), &offset
);
563 if (capture_descr_count
== UINT32_C(-1)) {
567 /* Capture descriptors. */
568 for (i
= 0; i
< capture_descr_count
; i
++) {
569 struct lttng_event_expr
*expr
= event_expr_from_payload(
571 enum lttng_condition_status status
;
577 /* Move ownership of `expr` to `condition`. */
578 status
= lttng_condition_event_rule_append_capture_descriptor(
580 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
581 /* `expr` not moved: destroy it. */
582 lttng_event_expr_destroy(expr
);
587 consumed_length
= (ssize_t
) offset
;
588 *_condition
= condition
;
593 consumed_length
= -1;
596 lttng_event_rule_put(event_rule
);
597 lttng_condition_put(condition
);
598 return consumed_length
;
602 enum lttng_condition_status
lttng_condition_event_rule_borrow_rule_mutable(
603 const struct lttng_condition
*condition
,
604 struct lttng_event_rule
**rule
)
606 struct lttng_condition_event_rule
*event_rule
;
607 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
609 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
) || !rule
) {
610 status
= LTTNG_CONDITION_STATUS_INVALID
;
614 event_rule
= container_of(
615 condition
, struct lttng_condition_event_rule
, parent
);
616 if (!event_rule
->rule
) {
617 status
= LTTNG_CONDITION_STATUS_UNSET
;
621 *rule
= event_rule
->rule
;
626 enum lttng_condition_status
lttng_condition_event_rule_get_rule(
627 const struct lttng_condition
*condition
,
628 const struct lttng_event_rule
**rule
)
630 struct lttng_event_rule
*mutable_rule
= NULL
;
631 const enum lttng_condition_status status
=
632 lttng_condition_event_rule_borrow_rule_mutable(
633 condition
, &mutable_rule
);
635 *rule
= mutable_rule
;
639 enum lttng_condition_status
640 lttng_condition_event_rule_append_capture_descriptor(
641 struct lttng_condition
*condition
,
642 struct lttng_event_expr
*expr
)
645 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
646 struct lttng_condition_event_rule
*event_rule_cond
=
647 container_of(condition
,
648 struct lttng_condition_event_rule
, parent
);
650 /* Only accept l-values. */
651 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
) || !expr
||
652 !lttng_event_expr_is_lvalue(expr
)) {
653 status
= LTTNG_CONDITION_STATUS_INVALID
;
657 ret
= lttng_dynamic_pointer_array_add_pointer(
658 &event_rule_cond
->capture_descriptors
, expr
);
660 status
= LTTNG_CONDITION_STATUS_ERROR
;
668 enum lttng_condition_status
669 lttng_condition_event_rule_get_capture_descriptor_count(
670 const struct lttng_condition
*condition
, unsigned int *count
)
672 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
673 const struct lttng_condition_event_rule
*event_rule_cond
=
674 container_of(condition
,
675 const struct lttng_condition_event_rule
,
678 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
) || !count
) {
679 status
= LTTNG_CONDITION_STATUS_INVALID
;
683 *count
= lttng_dynamic_pointer_array_get_count(
684 &event_rule_cond
->capture_descriptors
);
690 const struct lttng_event_expr
*
691 lttng_condition_event_rule_get_capture_descriptor_at_index(
692 const struct lttng_condition
*condition
, unsigned int index
)
694 const struct lttng_condition_event_rule
*event_rule_cond
=
695 container_of(condition
,
696 const struct lttng_condition_event_rule
,
698 const struct lttng_event_expr
*expr
= NULL
;
700 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
) ||
701 index
>= lttng_dynamic_pointer_array_get_count(
702 &event_rule_cond
->capture_descriptors
)) {
706 expr
= lttng_dynamic_pointer_array_get_pointer(
707 &event_rule_cond
->capture_descriptors
, index
);
714 ssize_t
lttng_evaluation_event_rule_create_from_payload(
715 struct lttng_payload_view
*view
,
716 struct lttng_evaluation
**_evaluation
)
718 ssize_t ret
, offset
= 0;
719 const char *trigger_name
;
720 struct lttng_evaluation
*evaluation
= NULL
;
721 const struct lttng_evaluation_event_rule_comm
*header
;
722 const struct lttng_payload_view header_view
=
723 lttng_payload_view_from_view(
724 view
, 0, sizeof(*header
));
731 if (!lttng_payload_view_is_valid(&header_view
)) {
732 ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain header");
737 header
= (typeof(header
)) header_view
.buffer
.data
;
739 /* Map the originating trigger's name. */
740 offset
+= sizeof(*header
);
742 struct lttng_payload_view current_view
=
743 lttng_payload_view_from_view(view
, offset
,
744 header
->trigger_name_length
);
746 if (!lttng_payload_view_is_valid(¤t_view
)) {
747 ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain trigger name");
752 trigger_name
= current_view
.buffer
.data
;
753 if (!lttng_buffer_view_contains_string(¤t_view
.buffer
,
754 trigger_name
, header
->trigger_name_length
)) {
755 ERR("Failed to initialize from malformed event rule evaluation: invalid trigger name");
761 offset
+= header
->trigger_name_length
;
763 evaluation
= lttng_evaluation_event_rule_create(trigger_name
);
769 *_evaluation
= evaluation
;
774 lttng_evaluation_destroy(evaluation
);
778 static int lttng_evaluation_event_rule_serialize(
779 const struct lttng_evaluation
*evaluation
,
780 struct lttng_payload
*payload
)
783 struct lttng_evaluation_event_rule
*hit
;
784 struct lttng_evaluation_event_rule_comm comm
;
787 evaluation
, struct lttng_evaluation_event_rule
, parent
);
790 comm
.trigger_name_length
= strlen(hit
->name
) + 1;
792 ret
= lttng_dynamic_buffer_append(
793 &payload
->buffer
, &comm
, sizeof(comm
));
798 ret
= lttng_dynamic_buffer_append(
799 &payload
->buffer
, hit
->name
, comm
.trigger_name_length
);
804 static void lttng_evaluation_event_rule_destroy(
805 struct lttng_evaluation
*evaluation
)
807 struct lttng_evaluation_event_rule
*hit
;
810 evaluation
, struct lttng_evaluation_event_rule
, parent
);
816 struct lttng_evaluation
*lttng_evaluation_event_rule_create(
817 const char *trigger_name
)
819 struct lttng_evaluation_event_rule
*hit
;
820 struct lttng_evaluation
*evaluation
= NULL
;
822 hit
= zmalloc(sizeof(struct lttng_evaluation_event_rule
));
827 hit
->name
= strdup(trigger_name
);
832 hit
->parent
.type
= LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
;
833 hit
->parent
.serialize
= lttng_evaluation_event_rule_serialize
;
834 hit
->parent
.destroy
= lttng_evaluation_event_rule_destroy
;
836 evaluation
= &hit
->parent
;
841 lttng_evaluation_event_rule_destroy(&hit
->parent
);
847 enum lttng_evaluation_status
lttng_evaluation_event_rule_get_trigger_name(
848 const struct lttng_evaluation
*evaluation
, const char **name
)
850 struct lttng_evaluation_event_rule
*hit
;
851 enum lttng_evaluation_status status
= LTTNG_EVALUATION_STATUS_OK
;
853 if (!evaluation
|| !is_event_rule_evaluation(evaluation
) || !name
) {
854 status
= LTTNG_EVALUATION_STATUS_INVALID
;
859 evaluation
, struct lttng_evaluation_event_rule
, parent
);