2 * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 #include <lttng/condition/event-rule.h>
19 #include <lttng/condition/condition-internal.h>
20 #include <lttng/condition/event-rule-internal.h>
21 #include <lttng/event-rule/event-rule-internal.h>
22 #include <lttng/event-field-value-internal.h>
23 #include <lttng/event-expr-internal.h>
24 #include <lttng/event-expr.h>
25 #include <lttng/lttng-error.h>
26 #include <common/macros.h>
27 #include <common/error.h>
28 #include <common/event-expr-to-bytecode.h>
36 #define IS_EVENT_RULE_CONDITION(condition) ( \
37 lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT \
41 bool is_event_rule_evaluation(const struct lttng_evaluation
*evaluation
)
43 enum lttng_condition_type type
= lttng_evaluation_get_type(evaluation
);
45 return type
== LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
;
50 bool lttng_condition_event_rule_validate(
51 const struct lttng_condition
*condition
);
53 int lttng_condition_event_rule_serialize(
54 const struct lttng_condition
*condition
,
55 struct lttng_dynamic_buffer
*buf
,
58 bool lttng_condition_event_rule_is_equal(const struct lttng_condition
*_a
,
59 const struct lttng_condition
*_b
);
61 void lttng_condition_event_rule_destroy(
62 struct lttng_condition
*condition
);
66 bool lttng_condition_event_rule_validate(
67 const struct lttng_condition
*condition
)
70 struct lttng_condition_event_rule
*event_rule
;
76 event_rule
= container_of(condition
,
77 struct lttng_condition_event_rule
, parent
);
78 if (!event_rule
->rule
) {
79 ERR("Invalid session event_rule condition: a rule must be set.");
83 valid
= lttng_event_rule_validate(event_rule
->rule
);
89 * Serializes the C string `str` into `buf`.
91 * Encoding is the length of `str` plus one (for the null character),
92 * and then the string, including its null character.
95 int serialize_cstr(const char *str
, struct lttng_dynamic_buffer
*buf
)
98 uint32_t len
= strlen(str
) + 1;
100 /* Serialize the length, including the null character */
101 DBG("Serializing C string's length (including null character): "
103 ret
= lttng_dynamic_buffer_append(buf
, &len
, sizeof(len
));
108 /* Serialize the string */
109 DBG("Serializing C string: \"%s\"", str
);
110 ret
= lttng_dynamic_buffer_append(buf
, str
, len
);
120 * Serializes the event expression `expr` into `buf`.
123 int serialize_event_expr(const struct lttng_event_expr
*expr
,
124 struct lttng_dynamic_buffer
*buf
)
129 /* Serialize the expression's type */
130 DBG("Serializing event expression's type: %d", expr
->type
);
132 ret
= lttng_dynamic_buffer_append(buf
, &type
, sizeof(type
));
137 /* Serialize the expression */
138 switch (expr
->type
) {
139 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
140 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
142 const struct lttng_event_expr_field
*field_expr
=
144 const struct lttng_event_expr_field
,
147 /* Serialize the field name */
148 DBG("Serializing field event expression's field name: \"%s\"",
150 ret
= serialize_cstr(field_expr
->name
, buf
);
157 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
159 const struct lttng_event_expr_app_specific_context_field
*field_expr
=
161 const struct lttng_event_expr_app_specific_context_field
,
164 /* Serialize the provider name */
165 DBG("Serializing app-specific context field event expression's "
166 "provider name: \"%s\"",
167 field_expr
->provider_name
);
168 ret
= serialize_cstr(field_expr
->provider_name
, buf
);
173 /* Serialize the type name */
174 DBG("Serializing app-specific context field event expression's "
176 field_expr
->provider_name
);
177 ret
= serialize_cstr(field_expr
->type_name
, buf
);
184 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
186 const struct lttng_event_expr_array_field_element
*elem_expr
=
188 const struct lttng_event_expr_array_field_element
,
190 uint32_t index
= elem_expr
->index
;
192 /* Serialize the index */
193 DBG("Serializing array field element event expression's "
194 "index: %u", elem_expr
->index
);
195 ret
= lttng_dynamic_buffer_append(buf
, &index
, sizeof(index
));
200 /* Serialize the parent array field expression */
201 DBG("Serializing array field element event expression's "
202 "parent array field event expression.");
203 ret
= serialize_event_expr(elem_expr
->array_field_expr
, buf
);
219 int lttng_condition_event_rule_serialize(
220 const struct lttng_condition
*condition
,
221 struct lttng_dynamic_buffer
*buf
,
225 struct lttng_condition_event_rule
*event_rule
;
226 enum lttng_condition_status status
;
227 uint32_t capture_descr_count
;
230 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
)) {
235 DBG("Serializing event rule condition");
236 event_rule
= container_of(condition
, struct lttng_condition_event_rule
,
239 DBG("Serializing event rule condition's event rule");
240 ret
= lttng_event_rule_serialize(event_rule
->rule
, buf
, fd_to_send
);
245 status
= lttng_condition_event_rule_get_capture_descriptor_count(
246 condition
, &capture_descr_count
);
247 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
252 DBG("Serializing event rule condition's capture descriptor count: %" PRIu32
,
253 capture_descr_count
);
254 ret
= lttng_dynamic_buffer_append(buf
, &capture_descr_count
,
255 sizeof(capture_descr_count
));
260 for (i
= 0; i
< capture_descr_count
; i
++) {
261 const struct lttng_capture_descriptor
*desc
=
262 lttng_condition_event_rule_get_internal_capture_descriptor_at_index(
265 DBG("Serializing event rule condition's capture descriptor %" PRIu32
,
267 ret
= serialize_event_expr(desc
->event_expression
, buf
);
273 * Appending the internal index payload linked with the
275 * TODO: might want to move to an englobing object to describe a
276 * capture descriptor publicly.
278 ret
= lttng_dynamic_buffer_append(buf
, &desc
->capture_index
,
279 sizeof(desc
->capture_index
));
290 bool capture_descriptors_are_equal(
291 const struct lttng_condition
*condition_a
,
292 const struct lttng_condition
*condition_b
)
294 bool is_equal
= true;
295 unsigned int capture_descr_count_a
;
296 unsigned int capture_descr_count_b
;
298 enum lttng_condition_status status
;
300 status
= lttng_condition_event_rule_get_capture_descriptor_count(
301 condition_a
, &capture_descr_count_a
);
302 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
306 status
= lttng_condition_event_rule_get_capture_descriptor_count(
307 condition_b
, &capture_descr_count_b
);
308 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
312 if (capture_descr_count_a
!= capture_descr_count_b
) {
316 for (i
= 0; i
< capture_descr_count_a
; i
++) {
317 const struct lttng_event_expr
*expr_a
=
318 lttng_condition_event_rule_get_capture_descriptor_at_index(
321 const struct lttng_event_expr
*expr_b
=
322 lttng_condition_event_rule_get_capture_descriptor_at_index(
326 if (!lttng_event_expr_is_equal(expr_a
, expr_b
)) {
341 bool lttng_condition_event_rule_is_equal(const struct lttng_condition
*_a
,
342 const struct lttng_condition
*_b
)
344 bool is_equal
= false;
345 struct lttng_condition_event_rule
*a
, *b
;
347 a
= container_of(_a
, struct lttng_condition_event_rule
, parent
);
348 b
= container_of(_b
, struct lttng_condition_event_rule
, parent
);
350 /* Both session names must be set or both must be unset. */
351 if ((a
->rule
&& !b
->rule
) ||
352 (!a
->rule
&& b
->rule
)) {
353 WARN("Comparing session event_rule conditions with uninitialized rule.");
357 is_equal
= lttng_event_rule_is_equal(a
->rule
, b
->rule
);
362 is_equal
= capture_descriptors_are_equal(_a
, _b
);
369 void lttng_condition_event_rule_destroy(
370 struct lttng_condition
*condition
)
372 struct lttng_condition_event_rule
*event_rule
;
374 event_rule
= container_of(condition
,
375 struct lttng_condition_event_rule
, parent
);
378 lttng_event_rule_destroy(event_rule
->rule
);
379 lttng_dynamic_pointer_array_reset(&event_rule
->capture_descriptors
);
384 void destroy_capture_descriptor(void *ptr
)
386 struct lttng_capture_descriptor
*desc
=
387 (struct lttng_capture_descriptor
*) ptr
;
388 lttng_event_expr_destroy(desc
->event_expression
);
392 struct lttng_condition
*lttng_condition_event_rule_create(
393 struct lttng_event_rule
*rule
)
395 struct lttng_condition
*parent
= NULL
;
396 struct lttng_condition_event_rule
*condition
= NULL
;
402 condition
= zmalloc(sizeof(struct lttng_condition_event_rule
));
407 lttng_condition_init(&condition
->parent
, LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
);
408 condition
->parent
.validate
= lttng_condition_event_rule_validate
,
409 condition
->parent
.serialize
= lttng_condition_event_rule_serialize
,
410 condition
->parent
.equal
= lttng_condition_event_rule_is_equal
,
411 condition
->parent
.destroy
= lttng_condition_event_rule_destroy
,
413 condition
->rule
= rule
;
414 lttng_dynamic_pointer_array_init(&condition
->capture_descriptors
,
415 destroy_capture_descriptor
);
417 parent
= &condition
->parent
;
423 int64_t int_from_buffer(const struct lttng_buffer_view
*view
, size_t size
,
428 if (*offset
+ size
> view
->size
) {
435 ret
= (int64_t) view
->data
[*offset
];
437 case sizeof(int32_t):
441 memcpy(&s32
, &view
->data
[*offset
], sizeof(s32
));
446 memcpy(&ret
, &view
->data
[*offset
], sizeof(ret
));
458 uint64_t uint_from_buffer(const struct lttng_buffer_view
*view
, size_t size
,
463 if (*offset
+ size
> view
->size
) {
470 ret
= (uint64_t) view
->data
[*offset
];
472 case sizeof(uint32_t):
476 memcpy(&u32
, &view
->data
[*offset
], sizeof(u32
));
477 ret
= (uint64_t) u32
;
481 memcpy(&ret
, &view
->data
[*offset
], sizeof(ret
));
494 const char *str_from_buffer(const struct lttng_buffer_view
*view
,
500 len
= uint_from_buffer(view
, sizeof(uint32_t), offset
);
501 if (len
== UINT64_C(-1)) {
505 ret
= &view
->data
[*offset
];
507 if (!lttng_buffer_view_contains_string(view
, ret
, len
)) {
522 struct lttng_event_expr
*event_expr_from_buffer(
523 const struct lttng_buffer_view
*view
, size_t *offset
)
525 struct lttng_event_expr
*expr
= NULL
;
529 type
= uint_from_buffer(view
, sizeof(uint8_t), offset
);
530 if (type
== UINT64_C(-1)) {
535 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
536 str
= str_from_buffer(view
, offset
);
541 expr
= lttng_event_expr_event_payload_field_create(str
);
543 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
544 str
= str_from_buffer(view
, offset
);
549 expr
= lttng_event_expr_channel_context_field_create(str
);
551 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
553 const char *provider_name
;
554 const char *type_name
;
556 provider_name
= str_from_buffer(view
, offset
);
557 if (!provider_name
) {
561 type_name
= str_from_buffer(view
, offset
);
566 expr
= lttng_event_expr_app_specific_context_field_create(
567 provider_name
, type_name
);
570 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
572 struct lttng_event_expr
*array_field_expr
;
575 index
= uint_from_buffer(view
, sizeof(uint32_t), offset
);
576 if (index
== UINT64_C(-1)) {
580 /* Array field expression is the encoded after this */
581 array_field_expr
= event_expr_from_buffer(view
, offset
);
582 if (!array_field_expr
) {
586 /* Move ownership of `array_field_expr` to new expression */
587 expr
= lttng_event_expr_array_field_element_create(
588 array_field_expr
, (unsigned int) index
);
590 /* `array_field_expr` not moved: destroy it */
591 lttng_event_expr_destroy(array_field_expr
);
603 lttng_event_expr_destroy(expr
);
611 ssize_t
lttng_condition_event_rule_create_from_buffer(
612 const struct lttng_buffer_view
*view
,
613 struct lttng_condition
**_condition
)
615 ssize_t consumed_length
;
618 uint64_t capture_descr_count
;
620 struct lttng_condition
*condition
= NULL
;
621 struct lttng_event_rule
*event_rule
= NULL
;
622 struct lttng_buffer_view event_rule_view
;
624 if (!view
|| !_condition
) {
629 event_rule_view
= lttng_buffer_view_from_view(view
, offset
, -1);
630 size
= lttng_event_rule_create_from_buffer(&event_rule_view
,
632 if (size
< 0 || !event_rule
) {
636 /* Create condition (no capture descriptors yet) at this point */
637 condition
= lttng_condition_event_rule_create(event_rule
);
642 /* Ownership moved to `condition` */
645 /* Capture descriptor count */
647 offset
+= (size_t) size
;
648 capture_descr_count
= uint_from_buffer(view
, sizeof(uint32_t), &offset
);
649 if (capture_descr_count
== UINT64_C(-1)) {
653 /* Capture descriptors */
654 for (i
= 0; i
< capture_descr_count
; i
++) {
655 enum lttng_condition_status status
;
656 struct lttng_capture_descriptor
*desc
;
658 struct lttng_event_expr
*expr
= event_expr_from_buffer(
660 int32_t payload_index
= int_from_buffer(view
, sizeof(int32_t),
667 /* Move ownership of `expr` to `condition` */
668 status
= lttng_condition_event_rule_append_capture_descriptor(
670 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
671 /* `expr` not moved: destroy it */
672 lttng_event_expr_destroy(expr
);
677 * Set the internal payload object for the descriptor. This can
678 * be used by liblttng-ctl to access capture msgpack payload on
681 desc
= lttng_condition_event_rule_get_internal_capture_descriptor_at_index(condition
, i
);
685 desc
->capture_index
= payload_index
;
688 consumed_length
= (ssize_t
) offset
;
689 *_condition
= condition
;
694 consumed_length
= -1;
697 lttng_event_rule_destroy(event_rule
);
698 lttng_condition_destroy(condition
);
699 return consumed_length
;
703 enum lttng_condition_status
704 lttng_condition_event_rule_get_rule_no_const(
705 const struct lttng_condition
*condition
,
706 struct lttng_event_rule
**rule
)
708 struct lttng_condition_event_rule
*event_rule
;
709 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
711 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
) || !rule
) {
712 status
= LTTNG_CONDITION_STATUS_INVALID
;
716 event_rule
= container_of(condition
, struct lttng_condition_event_rule
,
718 if (!event_rule
->rule
) {
719 status
= LTTNG_CONDITION_STATUS_UNSET
;
722 *rule
= event_rule
->rule
;
727 enum lttng_condition_status
728 lttng_condition_event_rule_get_rule(
729 const struct lttng_condition
*condition
,
730 const struct lttng_event_rule
**rule
)
732 struct lttng_event_rule
*no_const_rule
= NULL
;
733 enum lttng_condition_status status
;
735 status
= lttng_condition_event_rule_get_rule_no_const(condition
, &no_const_rule
);
736 *rule
= no_const_rule
;
740 enum lttng_condition_status
741 lttng_condition_event_rule_append_capture_descriptor(
742 struct lttng_condition
*condition
,
743 struct lttng_event_expr
*expr
)
745 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
746 struct lttng_condition_event_rule
*event_rule_cond
=
747 container_of(condition
,
748 struct lttng_condition_event_rule
, parent
);
750 struct lttng_capture_descriptor
*descriptor
= NULL
;
751 const struct lttng_event_rule
*rule
= NULL
;
753 /* Only accept l-values */
754 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
) || !expr
||
755 !lttng_event_expr_is_lvalue(expr
)) {
756 status
= LTTNG_CONDITION_STATUS_INVALID
;
760 status
= lttng_condition_event_rule_get_rule(condition
, &rule
);
761 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
765 switch(lttng_event_rule_get_type(rule
)) {
766 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT
:
767 case LTTNG_EVENT_RULE_TYPE_SYSCALL
:
769 status
= LTTNG_CONDITION_STATUS_OK
;
771 case LTTNG_EVENT_RULE_TYPE_UNKNOWN
:
772 status
= LTTNG_CONDITION_STATUS_INVALID
;
775 status
= LTTNG_CONDITION_STATUS_UNSUPPORTED
;
779 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
783 descriptor
= malloc(sizeof(*descriptor
));
784 if (descriptor
== NULL
) {
785 status
= LTTNG_CONDITION_STATUS_ERROR
;
789 descriptor
->capture_index
= -1;
790 descriptor
->event_expression
= expr
;
792 ret
= lttng_dynamic_pointer_array_add_pointer(
793 &event_rule_cond
->capture_descriptors
, descriptor
);
795 status
= LTTNG_CONDITION_STATUS_ERROR
;
799 /* Ownership is transfered to the internal capture_descriptors array */
806 enum lttng_condition_status
807 lttng_condition_event_rule_get_capture_descriptor_count(
808 const struct lttng_condition
*condition
, unsigned int *count
)
810 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
811 const struct lttng_condition_event_rule
*event_rule_cond
=
812 container_of(condition
,
813 const struct lttng_condition_event_rule
,
816 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
) || !count
) {
817 status
= LTTNG_CONDITION_STATUS_INVALID
;
821 *count
= lttng_dynamic_pointer_array_get_count(
822 &event_rule_cond
->capture_descriptors
);
829 struct lttng_capture_descriptor
*
830 lttng_condition_event_rule_get_internal_capture_descriptor_at_index(
831 const struct lttng_condition
*condition
, unsigned int index
)
833 const struct lttng_condition_event_rule
*event_rule_cond
=
834 container_of(condition
,
835 const struct lttng_condition_event_rule
,
837 struct lttng_capture_descriptor
*desc
= NULL
;
839 enum lttng_condition_status status
;
841 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
)) {
845 status
= lttng_condition_event_rule_get_capture_descriptor_count(
847 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
851 if (index
>= count
) {
855 desc
= lttng_dynamic_pointer_array_get_pointer(
856 &event_rule_cond
->capture_descriptors
, index
);
861 const struct lttng_event_expr
*
862 lttng_condition_event_rule_get_capture_descriptor_at_index(
863 const struct lttng_condition
*condition
, unsigned int index
)
865 const struct lttng_event_expr
*expr
= NULL
;
866 const struct lttng_capture_descriptor
*desc
= NULL
;
868 desc
= lttng_condition_event_rule_get_internal_capture_descriptor_at_index(
873 expr
= desc
->event_expression
;
880 ssize_t
lttng_evaluation_event_rule_create_from_buffer(
881 const struct lttng_condition_event_rule
*condition
,
882 const struct lttng_buffer_view
*view
,
883 struct lttng_evaluation
**_evaluation
)
885 ssize_t ret
, offset
= 0;
887 struct lttng_evaluation
*evaluation
= NULL
;
888 const struct lttng_evaluation_event_rule_comm
*comm
=
889 (const struct lttng_evaluation_event_rule_comm
*) view
->data
;
890 struct lttng_buffer_view current_view
;
891 uint32_t capture_payload_size
;
892 const char *capture_payload
= NULL
;
899 if (view
->size
< sizeof(*comm
)) {
904 /* Map the name, view of the payload */
905 offset
+= sizeof(*comm
);
906 current_view
= lttng_buffer_view_from_view(view
, offset
, comm
->trigger_name_length
);
907 name
= current_view
.data
;
913 if (comm
->trigger_name_length
== 1 ||
914 name
[comm
->trigger_name_length
- 1] != '\0' ||
915 strlen(name
) != comm
->trigger_name_length
- 1) {
917 * Check that the name is not NULL, is NULL-terminated, and
918 * does not contain a NULL before the last byte.
924 offset
+= comm
->trigger_name_length
;
925 current_view
= lttng_buffer_view_from_view(view
, offset
, -1);
927 if (current_view
.size
< sizeof(capture_payload_size
)) {
932 memcpy(&capture_payload_size
, current_view
.data
,
933 sizeof(capture_payload_size
));
934 offset
+= sizeof(capture_payload_size
);
936 if (capture_payload_size
> 0) {
937 current_view
= lttng_buffer_view_from_view(view
, offset
, -1);
939 if (current_view
.size
< capture_payload_size
) {
944 capture_payload
= current_view
.data
;
947 evaluation
= lttng_evaluation_event_rule_create(condition
, name
,
948 capture_payload
, capture_payload_size
, true);
954 offset
+= capture_payload_size
;
955 *_evaluation
= evaluation
;
960 lttng_evaluation_destroy(evaluation
);
965 int lttng_evaluation_event_rule_serialize(
966 const struct lttng_evaluation
*evaluation
,
967 struct lttng_dynamic_buffer
*buf
)
970 struct lttng_evaluation_event_rule
*hit
;
971 struct lttng_evaluation_event_rule_comm comm
;
972 uint32_t capture_payload_size
;
974 hit
= container_of(evaluation
, struct lttng_evaluation_event_rule
,
976 comm
.trigger_name_length
= strlen(hit
->name
) + 1;
977 ret
= lttng_dynamic_buffer_append(buf
, &comm
, sizeof(comm
));
981 ret
= lttng_dynamic_buffer_append(buf
, hit
->name
, comm
.trigger_name_length
);
986 capture_payload_size
= (uint32_t) hit
->capture_payload
.size
;
987 ret
= lttng_dynamic_buffer_append(buf
, &capture_payload_size
,
988 sizeof(capture_payload_size
));
993 ret
= lttng_dynamic_buffer_append(buf
, hit
->capture_payload
.data
,
994 hit
->capture_payload
.size
);
1004 bool msgpack_str_is_equal(const struct msgpack_object
*obj
, const char *str
)
1006 bool is_equal
= true;
1008 assert(obj
->type
== MSGPACK_OBJECT_STR
);
1010 if (obj
->via
.str
.size
!= strlen(str
)) {
1015 if (strncmp(obj
->via
.str
.ptr
, str
, obj
->via
.str
.size
) != 0) {
1025 const msgpack_object
*get_msgpack_map_obj(const struct msgpack_object
*map_obj
,
1028 const msgpack_object
*ret
= NULL
;
1031 assert(map_obj
->type
== MSGPACK_OBJECT_MAP
);
1033 for (i
= 0; i
< map_obj
->via
.map
.size
; i
++) {
1034 const struct msgpack_object_kv
*kv
= &map_obj
->via
.map
.ptr
[i
];
1036 assert(kv
->key
.type
== MSGPACK_OBJECT_STR
);
1038 if (msgpack_str_is_equal(&kv
->key
, name
)) {
1049 void lttng_evaluation_event_rule_destroy(
1050 struct lttng_evaluation
*evaluation
)
1052 struct lttng_evaluation_event_rule
*hit
;
1054 hit
= container_of(evaluation
, struct lttng_evaluation_event_rule
,
1057 lttng_dynamic_buffer_reset(&hit
->capture_payload
);
1058 if (hit
->captured_values
) {
1059 lttng_event_field_value_destroy(hit
->captured_values
);
1065 int event_field_value_from_obj(const msgpack_object
*obj
,
1066 struct lttng_event_field_value
**field_val
)
1072 switch (obj
->type
) {
1073 case MSGPACK_OBJECT_NIL
:
1077 case MSGPACK_OBJECT_POSITIVE_INTEGER
:
1078 *field_val
= lttng_event_field_value_uint_create(
1081 case MSGPACK_OBJECT_NEGATIVE_INTEGER
:
1082 *field_val
= lttng_event_field_value_int_create(
1085 case MSGPACK_OBJECT_FLOAT32
:
1086 case MSGPACK_OBJECT_FLOAT64
:
1087 *field_val
= lttng_event_field_value_real_create(
1090 case MSGPACK_OBJECT_STR
:
1091 *field_val
= lttng_event_field_value_string_create_with_size(
1092 obj
->via
.str
.ptr
, obj
->via
.str
.size
);
1094 case MSGPACK_OBJECT_ARRAY
:
1098 *field_val
= lttng_event_field_value_array_create();
1103 for (i
= 0; i
< obj
->via
.array
.size
; i
++) {
1104 const msgpack_object
*elem_obj
= &obj
->via
.array
.ptr
[i
];
1105 struct lttng_event_field_value
*elem_field_val
;
1107 ret
= event_field_value_from_obj(elem_obj
,
1114 if (elem_field_val
) {
1115 ret
= lttng_event_field_value_array_append(
1116 *field_val
, elem_field_val
);
1118 ret
= lttng_event_field_value_array_append_unavailable(
1123 lttng_event_field_value_destroy(elem_field_val
);
1130 case MSGPACK_OBJECT_MAP
:
1133 * As of this version, the only valid map object is
1134 * for an enumeration value, for example:
1141 * - Carling Black Label
1143 const msgpack_object
*inner_obj
;
1146 inner_obj
= get_msgpack_map_obj(obj
, "type");
1148 ERR("Missing `type` entry in map object.");
1152 if (inner_obj
->type
!= MSGPACK_OBJECT_STR
) {
1153 ERR("Map object's `type` entry is not a string (it's a %d).",
1158 if (!msgpack_str_is_equal(inner_obj
, "enum")) {
1159 ERR("Map object's `type` entry: expecting `enum`.");
1163 inner_obj
= get_msgpack_map_obj(obj
, "value");
1165 ERR("Missing `value` entry in map object.");
1169 if (inner_obj
->type
== MSGPACK_OBJECT_POSITIVE_INTEGER
) {
1170 *field_val
= lttng_event_field_value_enum_uint_create(
1171 inner_obj
->via
.u64
);
1172 } else if (inner_obj
->type
== MSGPACK_OBJECT_NEGATIVE_INTEGER
) {
1173 *field_val
= lttng_event_field_value_enum_int_create(
1174 inner_obj
->via
.i64
);
1176 ERR("Map object's `value` entry is not an integer (it's a %d).",
1185 inner_obj
= get_msgpack_map_obj(obj
, "labels");
1191 if (inner_obj
->type
!= MSGPACK_OBJECT_ARRAY
) {
1192 ERR("Map object's `labels` entry is not an array (it's a %d).",
1197 for (label_i
= 0; label_i
< inner_obj
->via
.array
.size
;
1200 const msgpack_object
*elem_obj
=
1201 &inner_obj
->via
.array
.ptr
[label_i
];
1203 if (elem_obj
->type
!= MSGPACK_OBJECT_STR
) {
1204 ERR("Map object's `labels` entry's type is not a string (it's a %d).",
1209 iret
= lttng_event_field_value_enum_append_label_with_size(
1210 *field_val
, elem_obj
->via
.str
.ptr
,
1211 elem_obj
->via
.str
.size
);
1220 ERR("Unexpected object type %d.", obj
->type
);
1231 lttng_event_field_value_destroy(*field_val
);
1240 struct lttng_event_field_value
*event_field_value_from_capture_payload(
1241 const struct lttng_condition_event_rule
*condition
,
1242 const char *capture_payload
, size_t capture_payload_size
)
1244 struct lttng_event_field_value
*ret
= NULL
;
1245 msgpack_unpacked unpacked
;
1246 msgpack_unpack_return unpack_return
;
1247 const msgpack_object
*root_obj
;
1248 const msgpack_object_array
*root_array_obj
;
1253 assert(capture_payload
);
1255 /* Initialize value */
1256 msgpack_unpacked_init(&unpacked
);
1259 unpack_return
= msgpack_unpack_next(&unpacked
, capture_payload
,
1260 capture_payload_size
, NULL
);
1261 if (unpack_return
!= MSGPACK_UNPACK_SUCCESS
) {
1262 ERR("msgpack_unpack_next() failed to decode the "
1263 "MessagePack-encoded capture payload "
1264 "(size %zu); returned %d.",
1265 capture_payload_size
, unpack_return
);
1269 /* Get root array */
1270 root_obj
= &unpacked
.data
;
1272 if (root_obj
->type
!= MSGPACK_OBJECT_ARRAY
) {
1273 ERR("Expecting an array as the root object; got type %d.",
1278 root_array_obj
= &root_obj
->via
.array
;
1280 /* Create an empty root array event field value */
1281 ret
= lttng_event_field_value_array_create();
1287 * For each capture descriptor in the condition object:
1289 * 1. Get its corresponding captured field value MessagePack
1292 * 2. Create a corresponding event field value.
1294 * 3. Append it to `ret` (the root array event field value).
1296 count
= lttng_dynamic_pointer_array_get_count(
1297 &condition
->capture_descriptors
);
1300 for (i
= 0; i
< count
; i
++) {
1301 const struct lttng_capture_descriptor
*capture_descriptor
=
1302 lttng_condition_event_rule_get_internal_capture_descriptor_at_index(
1303 &condition
->parent
, i
);
1304 const msgpack_object
*elem_obj
;
1305 struct lttng_event_field_value
*elem_field_val
;
1308 assert(capture_descriptor
);
1309 assert(capture_descriptor
->capture_index
>= 0);
1311 if (capture_descriptor
->capture_index
>= root_array_obj
->size
) {
1312 ERR("Root array object of size %u does not have enough "
1313 "elements for the capture index %u "
1314 "(for capture descriptor #%zu).",
1315 (unsigned int) root_array_obj
->size
,
1316 (unsigned int) capture_descriptor
->capture_index
,
1321 elem_obj
= &root_array_obj
->ptr
[(size_t) capture_descriptor
->capture_index
];
1322 iret
= event_field_value_from_obj(elem_obj
,
1328 if (elem_field_val
) {
1329 iret
= lttng_event_field_value_array_append(ret
,
1332 iret
= lttng_event_field_value_array_append_unavailable(
1337 lttng_event_field_value_destroy(elem_field_val
);
1345 lttng_event_field_value_destroy(ret
);
1349 msgpack_unpacked_destroy(&unpacked
);
1354 struct lttng_evaluation
*lttng_evaluation_event_rule_create(
1355 const struct lttng_condition_event_rule
*condition
,
1356 const char *trigger_name
,
1357 const char *capture_payload
, size_t capture_payload_size
,
1358 bool decode_capture_payload
)
1360 struct lttng_evaluation_event_rule
*hit
;
1362 hit
= zmalloc(sizeof(struct lttng_evaluation_event_rule
));
1367 /* TODO errir handling */
1368 hit
->name
= strdup(trigger_name
);
1369 lttng_dynamic_buffer_init(&hit
->capture_payload
);
1371 if (capture_payload
) {
1372 lttng_dynamic_buffer_append(&hit
->capture_payload
,
1373 capture_payload
, capture_payload_size
);
1375 if (decode_capture_payload
) {
1376 hit
->captured_values
=
1377 event_field_value_from_capture_payload(
1380 capture_payload_size
);
1381 if (!hit
->captured_values
) {
1382 ERR("Failed to decode the capture payload (size %zu).",
1383 capture_payload_size
);
1389 hit
->parent
.type
= LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
;
1390 hit
->parent
.serialize
= lttng_evaluation_event_rule_serialize
;
1391 hit
->parent
.destroy
= lttng_evaluation_event_rule_destroy
;
1395 lttng_evaluation_event_rule_destroy(&hit
->parent
);
1399 return &hit
->parent
;
1402 enum lttng_evaluation_status
lttng_evaluation_get_captured_values(
1403 const struct lttng_evaluation
*evaluation
,
1404 const struct lttng_event_field_value
**field_val
)
1406 struct lttng_evaluation_event_rule
*hit
;
1407 enum lttng_evaluation_status status
= LTTNG_EVALUATION_STATUS_OK
;
1409 if (!evaluation
|| !is_event_rule_evaluation(evaluation
) ||
1411 status
= LTTNG_EVALUATION_STATUS_INVALID
;
1415 hit
= container_of(evaluation
, struct lttng_evaluation_event_rule
,
1417 if (!hit
->captured_values
) {
1418 status
= LTTNG_EVALUATION_STATUS_INVALID
;
1422 *field_val
= hit
->captured_values
;
1428 enum lttng_evaluation_status
1429 lttng_evaluation_event_rule_get_trigger_name(
1430 const struct lttng_evaluation
*evaluation
,
1433 struct lttng_evaluation_event_rule
*hit
;
1434 enum lttng_evaluation_status status
= LTTNG_EVALUATION_STATUS_OK
;
1436 if (!evaluation
|| !is_event_rule_evaluation(evaluation
) || !name
) {
1437 status
= LTTNG_EVALUATION_STATUS_INVALID
;
1441 hit
= container_of(evaluation
, struct lttng_evaluation_event_rule
,
1449 enum lttng_error_code
1450 lttng_condition_event_rule_generate_capture_descriptor_bytecode_set(
1451 struct lttng_condition
*condition
,
1452 struct lttng_dynamic_pointer_array
*bytecode_set
)
1454 enum lttng_error_code ret
;
1455 enum lttng_condition_status status
;
1456 unsigned int capture_count
;
1457 const struct lttng_condition_event_rule_capture_bytecode_element
*set_element
;
1458 struct lttng_capture_descriptor
*local_capture_desc
;
1460 struct lttng_condition_event_rule_capture_bytecode_element
*set_element_to_append
=
1462 struct lttng_bytecode
*bytecode
= NULL
;
1464 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
) ||
1466 ret
= LTTNG_ERR_FATAL
;
1470 status
= lttng_condition_event_rule_get_capture_descriptor_count(
1471 condition
, &capture_count
);
1472 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
1473 ret
= LTTNG_ERR_FATAL
;
1478 * O(n^2), don't care. This code path is not hot.
1479 * Before inserting into the set, validate that the expression is not
1480 * already present in it.
1482 for (unsigned int i
= 0; i
< capture_count
; i
++) {
1483 int found_in_set
= false;
1485 set_count
= lttng_dynamic_pointer_array_get_count(bytecode_set
);
1487 local_capture_desc
=
1488 lttng_condition_event_rule_get_internal_capture_descriptor_at_index(
1490 if (local_capture_desc
== NULL
) {
1491 ret
= LTTNG_ERR_FATAL
;
1496 * Iterate over the set to check if already present in the set.
1498 for (ssize_t j
= 0; j
< set_count
; j
++) {
1499 set_element
= (struct lttng_condition_event_rule_capture_bytecode_element
1501 lttng_dynamic_pointer_array_get_pointer(
1503 if (set_element
== NULL
) {
1504 ret
= LTTNG_ERR_FATAL
;
1508 if (!lttng_event_expr_is_equal(
1509 local_capture_desc
->event_expression
,
1510 set_element
->expression
)) {
1511 /* Check against next set element */
1516 * Already present in the set, assign the
1517 * capture index of the capture descriptor for
1520 found_in_set
= true;
1521 local_capture_desc
->capture_index
= j
;
1522 /* Exit inner loop */
1527 /* Process next local capture descriptor */
1532 * Not found in the set.
1533 * Insert the capture descriptor in the set.
1535 set_element_to_append
= malloc(sizeof(*set_element_to_append
));
1536 if (set_element_to_append
== NULL
) {
1537 ret
= LTTNG_ERR_NOMEM
;
1541 /* Generate the bytecode */
1542 status
= lttng_event_expr_to_bytecode(
1543 local_capture_desc
->event_expression
,
1545 if (status
< 0 || bytecode
== NULL
) {
1546 /* TODO: return pertinent capture related error code */
1547 ret
= LTTNG_ERR_FILTER_INVAL
;
1551 set_element_to_append
->bytecode
= bytecode
;
1554 * Ensure the lifetime of the event expression.
1555 * Our reference will be put on condition destroy.
1557 lttng_event_expr_get(local_capture_desc
->event_expression
);
1558 set_element_to_append
->expression
=
1559 local_capture_desc
->event_expression
;
1561 ret
= lttng_dynamic_pointer_array_add_pointer(
1562 bytecode_set
, set_element_to_append
);
1564 ret
= LTTNG_ERR_NOMEM
;
1568 /* Ownership tranfered to the bytecode set */
1569 set_element_to_append
= NULL
;
1572 /* Assign the capture descriptor for future use */
1573 local_capture_desc
->capture_index
= set_count
;
1576 /* Everything went better than expected */
1580 free(set_element_to_append
);