2 * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
8 #include <common/error.hpp>
9 #include <common/macros.hpp>
10 #include <common/mi-lttng.hpp>
12 #include <lttng/condition/condition-internal.hpp>
13 #include <lttng/condition/event-rule-matches-internal.hpp>
14 #include <lttng/condition/event-rule-matches.h>
15 #include <lttng/event-expr-internal.hpp>
16 #include <lttng/event-expr.h>
17 #include <lttng/event-field-value-internal.hpp>
18 #include <lttng/event-rule/event-rule-internal.hpp>
19 #include <lttng/lttng-error.h>
21 #include <vendor/msgpack/msgpack.h>
28 #define IS_EVENT_RULE_MATCHES_CONDITION(condition) \
29 (lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES)
31 static bool is_event_rule_matches_evaluation(const struct lttng_evaluation
*evaluation
)
33 enum lttng_condition_type type
= lttng_evaluation_get_type(evaluation
);
35 return type
== LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES
;
38 static bool lttng_condition_event_rule_matches_validate(const struct lttng_condition
*condition
);
39 static int lttng_condition_event_rule_matches_serialize(const struct lttng_condition
*condition
,
40 struct lttng_payload
*payload
);
41 static bool lttng_condition_event_rule_matches_is_equal(const struct lttng_condition
*_a
,
42 const struct lttng_condition
*_b
);
43 static void lttng_condition_event_rule_matches_destroy(struct lttng_condition
*condition
);
45 static bool lttng_condition_event_rule_matches_validate(const struct lttng_condition
*condition
)
48 struct lttng_condition_event_rule_matches
*event_rule
;
55 lttng::utils::container_of(condition
, <tng_condition_event_rule_matches::parent
);
56 if (!event_rule
->rule
) {
57 ERR("Invalid on event condition: a rule must be set");
61 valid
= lttng_event_rule_validate(event_rule
->rule
);
66 static const char *msgpack_object_type_str(msgpack_object_type type
)
71 case MSGPACK_OBJECT_NIL
:
72 name
= "MSGPACK_OBJECT_NIL";
74 case MSGPACK_OBJECT_BOOLEAN
:
75 name
= "MSGPACK_OBJECT_BOOLEAN";
77 case MSGPACK_OBJECT_POSITIVE_INTEGER
:
78 name
= "MSGPACK_OBJECT_POSITIVE_INTEGER";
80 case MSGPACK_OBJECT_NEGATIVE_INTEGER
:
81 name
= "MSGPACK_OBJECT_NEGATIVE_INTEGER";
83 case MSGPACK_OBJECT_FLOAT32
:
84 name
= "MSGPACK_OBJECT_FLOAT32";
86 case MSGPACK_OBJECT_FLOAT
:
87 /* Same value as MSGPACK_OBJECT_FLOAT64 */
88 name
= "MSGPACK_OBJECT_FLOAT(64)";
90 case MSGPACK_OBJECT_STR
:
91 name
= "MSGPACK_OBJECT_STR";
93 case MSGPACK_OBJECT_ARRAY
:
94 name
= "MSGPACK_OBJECT_ARRAY";
96 case MSGPACK_OBJECT_MAP
:
97 name
= "MSGPACK_OBJECT_MAP";
99 case MSGPACK_OBJECT_BIN
:
100 name
= "MSGPACK_OBJECT_BIN";
102 case MSGPACK_OBJECT_EXT
:
103 name
= "MSGPACK_OBJECT_EXT";
113 * Serializes the C string `str` into `buf`.
115 * Encoding is the length of `str` plus one (for the null character),
116 * and then the string, including its null terminator.
118 static int serialize_cstr(const char *str
, struct lttng_dynamic_buffer
*buf
)
121 const uint32_t len
= strlen(str
) + 1;
123 /* Serialize the length, including the null terminator. */
124 DBG("Serializing C string's length (including null terminator): "
127 ret
= lttng_dynamic_buffer_append(buf
, &len
, sizeof(len
));
132 /* Serialize the string. */
133 DBG("Serializing C string: '%s'", str
);
134 ret
= lttng_dynamic_buffer_append(buf
, str
, len
);
144 * Serializes the event expression `expr` into `buf`.
146 static int serialize_event_expr(const struct lttng_event_expr
*expr
, struct lttng_payload
*payload
)
148 const uint8_t type
= expr
->type
;
151 /* Serialize the expression's type. */
152 DBG("Serializing event expression's type: %d", expr
->type
);
153 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &type
, sizeof(type
));
158 /* Serialize the expression */
159 switch (expr
->type
) {
160 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
161 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
163 const struct lttng_event_expr_field
*field_expr
=
164 lttng::utils::container_of(expr
, <tng_event_expr_field::parent
);
166 /* Serialize the field name. */
167 DBG("Serializing field event expression's field name: '%s'", field_expr
->name
);
168 ret
= serialize_cstr(field_expr
->name
, &payload
->buffer
);
175 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
177 const struct lttng_event_expr_app_specific_context_field
*field_expr
=
178 lttng::utils::container_of(
179 expr
, <tng_event_expr_app_specific_context_field::parent
);
181 /* Serialize the provider name. */
182 DBG("Serializing app-specific context field event expression's "
183 "provider name: '%s'",
184 field_expr
->provider_name
);
185 ret
= serialize_cstr(field_expr
->provider_name
, &payload
->buffer
);
190 /* Serialize the type name. */
191 DBG("Serializing app-specific context field event expression's "
193 field_expr
->provider_name
);
194 ret
= serialize_cstr(field_expr
->type_name
, &payload
->buffer
);
201 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
203 const struct lttng_event_expr_array_field_element
*elem_expr
=
204 lttng::utils::container_of(expr
,
205 <tng_event_expr_array_field_element::parent
);
206 const uint32_t index
= elem_expr
->index
;
208 /* Serialize the index. */
209 DBG("Serializing array field element event expression's "
212 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &index
, sizeof(index
));
217 /* Serialize the parent array field expression. */
218 DBG("Serializing array field element event expression's "
219 "parent array field event expression");
220 ret
= serialize_event_expr(elem_expr
->array_field_expr
, payload
);
235 static struct lttng_capture_descriptor
*
236 lttng_condition_event_rule_matches_get_internal_capture_descriptor_at_index(
237 const struct lttng_condition
*condition
, unsigned int index
)
239 const struct lttng_condition_event_rule_matches
*event_rule_matches_cond
=
240 lttng::utils::container_of(condition
, <tng_condition_event_rule_matches::parent
);
241 struct lttng_capture_descriptor
*desc
= nullptr;
243 enum lttng_condition_status status
;
245 if (!condition
|| !IS_EVENT_RULE_MATCHES_CONDITION(condition
)) {
249 status
= lttng_condition_event_rule_matches_get_capture_descriptor_count(condition
, &count
);
250 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
254 if (index
>= count
) {
258 desc
= (lttng_capture_descriptor
*) lttng_dynamic_pointer_array_get_pointer(
259 &event_rule_matches_cond
->capture_descriptors
, index
);
264 static int lttng_condition_event_rule_matches_serialize(const struct lttng_condition
*condition
,
265 struct lttng_payload
*payload
)
268 struct lttng_condition_event_rule_matches
*event_rule_matches_condition
;
269 enum lttng_condition_status status
;
270 /* Used for iteration and communication (size matters). */
271 uint32_t i
, capture_descr_count
;
273 if (!condition
|| !IS_EVENT_RULE_MATCHES_CONDITION(condition
)) {
278 DBG("Serializing on event condition");
279 event_rule_matches_condition
=
280 lttng::utils::container_of(condition
, <tng_condition_event_rule_matches::parent
);
282 DBG("Serializing on event condition's event rule");
283 ret
= lttng_event_rule_serialize(event_rule_matches_condition
->rule
, payload
);
288 status
= lttng_condition_event_rule_matches_get_capture_descriptor_count(
289 condition
, &capture_descr_count
);
290 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
295 DBG("Serializing on event condition's capture descriptor count: %" PRIu32
,
296 capture_descr_count
);
297 ret
= lttng_dynamic_buffer_append(
298 &payload
->buffer
, &capture_descr_count
, sizeof(capture_descr_count
));
303 for (i
= 0; i
< capture_descr_count
; i
++) {
304 const struct lttng_capture_descriptor
*desc
=
305 lttng_condition_event_rule_matches_get_internal_capture_descriptor_at_index(
308 DBG("Serializing on event condition's capture descriptor %" PRIu32
, i
);
309 ret
= serialize_event_expr(desc
->event_expression
, payload
);
319 static bool capture_descriptors_are_equal(const struct lttng_condition
*condition_a
,
320 const struct lttng_condition
*condition_b
)
322 bool is_equal
= true;
323 unsigned int capture_descr_count_a
;
324 unsigned int capture_descr_count_b
;
326 enum lttng_condition_status status
;
328 status
= lttng_condition_event_rule_matches_get_capture_descriptor_count(
329 condition_a
, &capture_descr_count_a
);
330 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
334 status
= lttng_condition_event_rule_matches_get_capture_descriptor_count(
335 condition_b
, &capture_descr_count_b
);
336 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
340 if (capture_descr_count_a
!= capture_descr_count_b
) {
344 for (i
= 0; i
< capture_descr_count_a
; i
++) {
345 const struct lttng_event_expr
*expr_a
=
346 lttng_condition_event_rule_matches_get_capture_descriptor_at_index(
348 const struct lttng_event_expr
*expr_b
=
349 lttng_condition_event_rule_matches_get_capture_descriptor_at_index(
352 if (!lttng_event_expr_is_equal(expr_a
, expr_b
)) {
366 static bool lttng_condition_event_rule_matches_is_equal(const struct lttng_condition
*_a
,
367 const struct lttng_condition
*_b
)
369 bool is_equal
= false;
370 struct lttng_condition_event_rule_matches
*a
, *b
;
372 a
= lttng::utils::container_of(_a
, <tng_condition_event_rule_matches::parent
);
373 b
= lttng::utils::container_of(_b
, <tng_condition_event_rule_matches::parent
);
375 /* Both event rules must be set or both must be unset. */
376 if ((a
->rule
&& !b
->rule
) || (!a
->rule
&& b
->rule
)) {
377 WARN("Comparing event_rule conditions with uninitialized rule");
381 is_equal
= lttng_event_rule_is_equal(a
->rule
, b
->rule
);
386 is_equal
= capture_descriptors_are_equal(_a
, _b
);
392 static void lttng_condition_event_rule_matches_destroy(struct lttng_condition
*condition
)
394 struct lttng_condition_event_rule_matches
*event_rule_matches_condition
;
396 event_rule_matches_condition
=
397 lttng::utils::container_of(condition
, <tng_condition_event_rule_matches::parent
);
399 lttng_event_rule_put(event_rule_matches_condition
->rule
);
400 lttng_dynamic_pointer_array_reset(&event_rule_matches_condition
->capture_descriptors
);
401 free(event_rule_matches_condition
);
404 static void destroy_capture_descriptor(void *ptr
)
406 struct lttng_capture_descriptor
*desc
= (struct lttng_capture_descriptor
*) ptr
;
408 lttng_event_expr_destroy(desc
->event_expression
);
409 free(desc
->bytecode
);
413 static enum lttng_error_code
414 lttng_condition_event_rule_matches_mi_serialize(const struct lttng_condition
*condition
,
415 struct mi_writer
*writer
)
418 enum lttng_error_code ret_code
;
419 enum lttng_condition_status status
;
420 const struct lttng_event_rule
*rule
= nullptr;
421 unsigned int capture_descriptor_count
, i
;
423 LTTNG_ASSERT(condition
);
424 LTTNG_ASSERT(writer
);
425 LTTNG_ASSERT(IS_EVENT_RULE_MATCHES_CONDITION(condition
));
427 status
= lttng_condition_event_rule_matches_get_rule(condition
, &rule
);
428 LTTNG_ASSERT(status
== LTTNG_CONDITION_STATUS_OK
);
429 LTTNG_ASSERT(rule
!= nullptr);
431 status
= lttng_condition_event_rule_matches_get_capture_descriptor_count(
432 condition
, &capture_descriptor_count
);
433 LTTNG_ASSERT(status
== LTTNG_CONDITION_STATUS_OK
);
435 /* Open condition event rule matches element. */
436 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_condition_event_rule_matches
);
441 /* Serialize the event rule. */
442 ret_code
= lttng_event_rule_mi_serialize(rule
, writer
);
443 if (ret_code
!= LTTNG_OK
) {
447 /* Open the capture descriptors element. */
448 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_capture_descriptors
);
453 for (i
= 0; i
< capture_descriptor_count
; i
++) {
454 const struct lttng_event_expr
*descriptor
= nullptr;
456 descriptor
= lttng_condition_event_rule_matches_get_capture_descriptor_at_index(
458 LTTNG_ASSERT(descriptor
);
460 ret_code
= lttng_event_expr_mi_serialize(descriptor
, writer
);
461 if (ret_code
!= LTTNG_OK
) {
466 /* Close capture descriptors element. */
467 ret
= mi_lttng_writer_close_element(writer
);
472 /* Close condition_event_rule_matches. */
473 ret
= mi_lttng_writer_close_element(writer
);
481 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
486 struct lttng_condition
*lttng_condition_event_rule_matches_create(struct lttng_event_rule
*rule
)
488 struct lttng_condition
*parent
= nullptr;
489 struct lttng_condition_event_rule_matches
*condition
= nullptr;
495 condition
= zmalloc
<lttng_condition_event_rule_matches
>();
500 lttng_condition_init(&condition
->parent
, LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES
);
501 condition
->parent
.validate
= lttng_condition_event_rule_matches_validate
,
502 condition
->parent
.serialize
= lttng_condition_event_rule_matches_serialize
,
503 condition
->parent
.equal
= lttng_condition_event_rule_matches_is_equal
,
504 condition
->parent
.destroy
= lttng_condition_event_rule_matches_destroy
,
505 condition
->parent
.mi_serialize
= lttng_condition_event_rule_matches_mi_serialize
,
507 lttng_event_rule_get(rule
);
508 condition
->rule
= rule
;
511 lttng_dynamic_pointer_array_init(&condition
->capture_descriptors
,
512 destroy_capture_descriptor
);
514 parent
= &condition
->parent
;
519 static uint64_t uint_from_buffer(const struct lttng_buffer_view
*view
, size_t size
, size_t *offset
)
522 const struct lttng_buffer_view uint_view
= lttng_buffer_view_from_view(view
, *offset
, size
);
524 if (!lttng_buffer_view_is_valid(&uint_view
)) {
531 ret
= (unsigned char) *uint_view
.data
;
533 case sizeof(uint32_t):
537 memcpy(&u32
, uint_view
.data
, sizeof(u32
));
538 ret
= (uint64_t) u32
;
542 memcpy(&ret
, uint_view
.data
, sizeof(ret
));
554 static const char *str_from_buffer(const struct lttng_buffer_view
*view
, size_t *offset
)
559 len
= uint_from_buffer(view
, sizeof(uint32_t), offset
);
560 if (len
== UINT64_C(-1)) {
564 ret
= &view
->data
[*offset
];
566 if (!lttng_buffer_view_contains_string(view
, ret
, len
)) {
580 static struct lttng_event_expr
*event_expr_from_payload(struct lttng_payload_view
*view
,
583 struct lttng_event_expr
*expr
= nullptr;
587 type
= uint_from_buffer(&view
->buffer
, sizeof(uint8_t), offset
);
588 if (type
== UINT64_C(-1)) {
593 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
594 str
= str_from_buffer(&view
->buffer
, offset
);
599 expr
= lttng_event_expr_event_payload_field_create(str
);
601 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
602 str
= str_from_buffer(&view
->buffer
, offset
);
607 expr
= lttng_event_expr_channel_context_field_create(str
);
609 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
611 const char *provider_name
;
612 const char *type_name
;
614 provider_name
= str_from_buffer(&view
->buffer
, offset
);
615 if (!provider_name
) {
619 type_name
= str_from_buffer(&view
->buffer
, offset
);
624 expr
= lttng_event_expr_app_specific_context_field_create(provider_name
, type_name
);
627 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
629 struct lttng_event_expr
*array_field_expr
;
630 const uint64_t index
= uint_from_buffer(&view
->buffer
, sizeof(uint32_t), offset
);
632 if (index
== UINT64_C(-1)) {
636 /* Array field expression is the encoded after this. */
637 array_field_expr
= event_expr_from_payload(view
, offset
);
638 if (!array_field_expr
) {
642 /* Move ownership of `array_field_expr` to new expression. */
643 expr
= lttng_event_expr_array_field_element_create(array_field_expr
,
644 (unsigned int) index
);
646 /* `array_field_expr` not moved: destroy it. */
647 lttng_event_expr_destroy(array_field_expr
);
653 ERR("Invalid event expression type encoutered while deserializing event expression: type = %" PRIu64
,
661 lttng_event_expr_destroy(expr
);
668 ssize_t
lttng_condition_event_rule_matches_create_from_payload(struct lttng_payload_view
*view
,
669 struct lttng_condition
**_condition
)
671 ssize_t consumed_length
;
673 ssize_t event_rule_length
;
674 uint32_t i
, capture_descr_count
;
675 struct lttng_condition
*condition
= nullptr;
676 struct lttng_event_rule
*event_rule
= nullptr;
678 if (!view
|| !_condition
) {
682 /* Struct lttng_event_rule. */
684 struct lttng_payload_view event_rule_view
=
685 lttng_payload_view_from_view(view
, offset
, -1);
688 lttng_event_rule_create_from_payload(&event_rule_view
, &event_rule
);
691 if (event_rule_length
< 0 || !event_rule
) {
695 offset
+= event_rule_length
;
697 /* Create condition (no capture descriptors yet) at this point */
698 condition
= lttng_condition_event_rule_matches_create(event_rule
);
703 /* Capture descriptor count. */
704 LTTNG_ASSERT(event_rule_length
>= 0);
705 capture_descr_count
= uint_from_buffer(&view
->buffer
, sizeof(uint32_t), &offset
);
706 if (capture_descr_count
== UINT32_C(-1)) {
710 /* Capture descriptors. */
711 for (i
= 0; i
< capture_descr_count
; i
++) {
712 enum lttng_condition_status status
;
713 struct lttng_event_expr
*expr
= event_expr_from_payload(view
, &offset
);
719 /* Move ownership of `expr` to `condition`. */
720 status
= lttng_condition_event_rule_matches_append_capture_descriptor(condition
,
722 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
723 /* `expr` not moved: destroy it. */
724 lttng_event_expr_destroy(expr
);
729 consumed_length
= (ssize_t
) offset
;
730 *_condition
= condition
;
735 consumed_length
= -1;
738 lttng_event_rule_put(event_rule
);
739 lttng_condition_put(condition
);
740 return consumed_length
;
743 enum lttng_condition_status
744 lttng_condition_event_rule_matches_borrow_rule_mutable(const struct lttng_condition
*condition
,
745 struct lttng_event_rule
**rule
)
747 struct lttng_condition_event_rule_matches
*event_rule
;
748 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
750 if (!condition
|| !IS_EVENT_RULE_MATCHES_CONDITION(condition
) || !rule
) {
751 status
= LTTNG_CONDITION_STATUS_INVALID
;
756 lttng::utils::container_of(condition
, <tng_condition_event_rule_matches::parent
);
757 if (!event_rule
->rule
) {
758 status
= LTTNG_CONDITION_STATUS_UNSET
;
762 *rule
= event_rule
->rule
;
767 enum lttng_condition_status
768 lttng_condition_event_rule_matches_get_rule(const struct lttng_condition
*condition
,
769 const struct lttng_event_rule
**rule
)
771 struct lttng_event_rule
*mutable_rule
= nullptr;
772 const enum lttng_condition_status status
=
773 lttng_condition_event_rule_matches_borrow_rule_mutable(condition
, &mutable_rule
);
775 *rule
= mutable_rule
;
779 void lttng_condition_event_rule_matches_set_error_counter_index(struct lttng_condition
*condition
,
780 uint64_t error_counter_index
)
782 struct lttng_condition_event_rule_matches
*event_rule_matches_cond
=
783 lttng::utils::container_of(condition
, <tng_condition_event_rule_matches::parent
);
785 LTTNG_OPTIONAL_SET(&event_rule_matches_cond
->error_counter_index
, error_counter_index
);
789 lttng_condition_event_rule_matches_get_error_counter_index(const struct lttng_condition
*condition
)
791 const struct lttng_condition_event_rule_matches
*event_rule_matches_cond
=
792 lttng::utils::container_of(condition
, <tng_condition_event_rule_matches::parent
);
794 return LTTNG_OPTIONAL_GET(event_rule_matches_cond
->error_counter_index
);
797 enum lttng_condition_status
798 lttng_condition_event_rule_matches_append_capture_descriptor(struct lttng_condition
*condition
,
799 struct lttng_event_expr
*expr
)
802 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
803 struct lttng_condition_event_rule_matches
*event_rule_matches_cond
=
804 lttng::utils::container_of(condition
, <tng_condition_event_rule_matches::parent
);
805 struct lttng_capture_descriptor
*descriptor
= nullptr;
806 const struct lttng_event_rule
*rule
= nullptr;
808 /* Only accept l-values. */
809 if (!condition
|| !IS_EVENT_RULE_MATCHES_CONDITION(condition
) || !expr
||
810 !lttng_event_expr_is_lvalue(expr
)) {
811 status
= LTTNG_CONDITION_STATUS_INVALID
;
815 status
= lttng_condition_event_rule_matches_get_rule(condition
, &rule
);
816 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
820 switch (lttng_event_rule_get_type(rule
)) {
821 case LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT
:
822 case LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT
:
823 case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING
:
824 case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING
:
825 case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING
:
826 case LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL
:
828 status
= LTTNG_CONDITION_STATUS_OK
;
830 case LTTNG_EVENT_RULE_TYPE_UNKNOWN
:
831 status
= LTTNG_CONDITION_STATUS_INVALID
;
834 status
= LTTNG_CONDITION_STATUS_UNSUPPORTED
;
838 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
842 descriptor
= malloc
<lttng_capture_descriptor
>();
843 if (descriptor
== nullptr) {
844 status
= LTTNG_CONDITION_STATUS_ERROR
;
848 descriptor
->event_expression
= expr
;
849 descriptor
->bytecode
= nullptr;
851 ret
= lttng_dynamic_pointer_array_add_pointer(&event_rule_matches_cond
->capture_descriptors
,
854 status
= LTTNG_CONDITION_STATUS_ERROR
;
858 /* Ownership is transfered to the internal capture_descriptors array */
859 descriptor
= nullptr;
865 enum lttng_condition_status
lttng_condition_event_rule_matches_get_capture_descriptor_count(
866 const struct lttng_condition
*condition
, unsigned int *count
)
868 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
869 const struct lttng_condition_event_rule_matches
*event_rule_matches_condition
=
870 lttng::utils::container_of(condition
, <tng_condition_event_rule_matches::parent
);
872 if (!condition
|| !IS_EVENT_RULE_MATCHES_CONDITION(condition
) || !count
) {
873 status
= LTTNG_CONDITION_STATUS_INVALID
;
877 *count
= lttng_dynamic_pointer_array_get_count(
878 &event_rule_matches_condition
->capture_descriptors
);
884 const struct lttng_event_expr
*lttng_condition_event_rule_matches_get_capture_descriptor_at_index(
885 const struct lttng_condition
*condition
, unsigned int index
)
887 const struct lttng_event_expr
*expr
= nullptr;
888 const struct lttng_capture_descriptor
*desc
= nullptr;
890 desc
= lttng_condition_event_rule_matches_get_internal_capture_descriptor_at_index(
892 if (desc
== nullptr) {
895 expr
= desc
->event_expression
;
901 ssize_t
lttng_evaluation_event_rule_matches_create_from_payload(
902 const struct lttng_condition_event_rule_matches
*condition
,
903 struct lttng_payload_view
*view
,
904 struct lttng_evaluation
**_evaluation
)
906 ssize_t ret
, offset
= 0;
907 struct lttng_evaluation
*evaluation
= nullptr;
908 uint32_t capture_payload_size
;
909 const char *capture_payload
= nullptr;
917 const struct lttng_payload_view current_view
=
918 lttng_payload_view_from_view(view
, offset
, -1);
920 if (current_view
.buffer
.size
< sizeof(capture_payload_size
)) {
925 memcpy(&capture_payload_size
,
926 current_view
.buffer
.data
,
927 sizeof(capture_payload_size
));
929 offset
+= sizeof(capture_payload_size
);
931 if (capture_payload_size
> 0) {
932 const struct lttng_payload_view current_view
=
933 lttng_payload_view_from_view(view
, offset
, -1);
935 if (current_view
.buffer
.size
< capture_payload_size
) {
940 capture_payload
= current_view
.buffer
.data
;
943 evaluation
= lttng_evaluation_event_rule_matches_create(
944 condition
, capture_payload
, capture_payload_size
, true);
950 offset
+= capture_payload_size
;
951 *_evaluation
= evaluation
;
952 evaluation
= nullptr;
956 lttng_evaluation_destroy(evaluation
);
960 static int lttng_evaluation_event_rule_matches_serialize(const struct lttng_evaluation
*evaluation
,
961 struct lttng_payload
*payload
)
964 struct lttng_evaluation_event_rule_matches
*hit
;
965 uint32_t capture_payload_size
;
967 hit
= lttng::utils::container_of(evaluation
, <tng_evaluation_event_rule_matches::parent
);
969 capture_payload_size
= (uint32_t) hit
->capture_payload
.size
;
970 ret
= lttng_dynamic_buffer_append(
971 &payload
->buffer
, &capture_payload_size
, sizeof(capture_payload_size
));
976 ret
= lttng_dynamic_buffer_append(
977 &payload
->buffer
, hit
->capture_payload
.data
, hit
->capture_payload
.size
);
986 static bool msgpack_str_is_equal(const struct msgpack_object
*obj
, const char *str
)
988 bool is_equal
= true;
990 LTTNG_ASSERT(obj
->type
== MSGPACK_OBJECT_STR
);
992 if (obj
->via
.str
.size
!= strlen(str
)) {
997 if (strncmp(obj
->via
.str
.ptr
, str
, obj
->via
.str
.size
) != 0) {
1006 static const msgpack_object
*get_msgpack_map_obj(const struct msgpack_object
*map_obj
,
1009 const msgpack_object
*ret
= nullptr;
1012 LTTNG_ASSERT(map_obj
->type
== MSGPACK_OBJECT_MAP
);
1014 for (i
= 0; i
< map_obj
->via
.map
.size
; i
++) {
1015 const struct msgpack_object_kv
*kv
= &map_obj
->via
.map
.ptr
[i
];
1017 LTTNG_ASSERT(kv
->key
.type
== MSGPACK_OBJECT_STR
);
1019 if (msgpack_str_is_equal(&kv
->key
, name
)) {
1029 static void lttng_evaluation_event_rule_matches_destroy(struct lttng_evaluation
*evaluation
)
1031 struct lttng_evaluation_event_rule_matches
*hit
;
1033 hit
= lttng::utils::container_of(evaluation
, <tng_evaluation_event_rule_matches::parent
);
1034 lttng_dynamic_buffer_reset(&hit
->capture_payload
);
1035 lttng_event_field_value_destroy(hit
->captured_values
);
1039 static int event_field_value_from_obj(const msgpack_object
*obj
,
1040 struct lttng_event_field_value
**field_val
)
1045 LTTNG_ASSERT(field_val
);
1047 switch (obj
->type
) {
1048 case MSGPACK_OBJECT_NIL
:
1050 *field_val
= nullptr;
1052 case MSGPACK_OBJECT_POSITIVE_INTEGER
:
1053 *field_val
= lttng_event_field_value_uint_create(obj
->via
.u64
);
1055 case MSGPACK_OBJECT_NEGATIVE_INTEGER
:
1056 *field_val
= lttng_event_field_value_int_create(obj
->via
.i64
);
1058 case MSGPACK_OBJECT_FLOAT32
:
1059 case MSGPACK_OBJECT_FLOAT64
:
1060 *field_val
= lttng_event_field_value_real_create(obj
->via
.f64
);
1062 case MSGPACK_OBJECT_STR
:
1063 *field_val
= lttng_event_field_value_string_create_with_size(obj
->via
.str
.ptr
,
1066 case MSGPACK_OBJECT_ARRAY
:
1070 *field_val
= lttng_event_field_value_array_create();
1075 for (i
= 0; i
< obj
->via
.array
.size
; i
++) {
1076 const msgpack_object
*elem_obj
= &obj
->via
.array
.ptr
[i
];
1077 struct lttng_event_field_value
*elem_field_val
;
1079 ret
= event_field_value_from_obj(elem_obj
, &elem_field_val
);
1084 if (elem_field_val
) {
1085 ret
= lttng_event_field_value_array_append(*field_val
,
1088 ret
= lttng_event_field_value_array_append_unavailable(*field_val
);
1092 lttng_event_field_value_destroy(elem_field_val
);
1099 case MSGPACK_OBJECT_MAP
:
1102 * As of this version, the only valid map object is
1103 * for an enumeration value, for example:
1110 * - Carling Black Label
1112 const msgpack_object
*inner_obj
;
1115 inner_obj
= get_msgpack_map_obj(obj
, "type");
1117 ERR("Missing `type` entry in map object");
1121 if (inner_obj
->type
!= MSGPACK_OBJECT_STR
) {
1122 ERR("Map object's `type` entry is not a string: type = %s",
1123 msgpack_object_type_str(inner_obj
->type
));
1127 if (!msgpack_str_is_equal(inner_obj
, "enum")) {
1128 ERR("Map object's `type` entry: expecting `enum`");
1132 inner_obj
= get_msgpack_map_obj(obj
, "value");
1134 ERR("Missing `value` entry in map object");
1138 if (inner_obj
->type
== MSGPACK_OBJECT_POSITIVE_INTEGER
) {
1139 *field_val
= lttng_event_field_value_enum_uint_create(inner_obj
->via
.u64
);
1140 } else if (inner_obj
->type
== MSGPACK_OBJECT_NEGATIVE_INTEGER
) {
1141 *field_val
= lttng_event_field_value_enum_int_create(inner_obj
->via
.i64
);
1143 ERR("Map object's `value` entry is not an integer: type = %s",
1144 msgpack_object_type_str(inner_obj
->type
));
1152 inner_obj
= get_msgpack_map_obj(obj
, "labels");
1158 if (inner_obj
->type
!= MSGPACK_OBJECT_ARRAY
) {
1159 ERR("Map object's `labels` entry is not an array: type = %s",
1160 msgpack_object_type_str(inner_obj
->type
));
1164 for (label_i
= 0; label_i
< inner_obj
->via
.array
.size
; label_i
++) {
1166 const msgpack_object
*elem_obj
= &inner_obj
->via
.array
.ptr
[label_i
];
1168 if (elem_obj
->type
!= MSGPACK_OBJECT_STR
) {
1169 ERR("Map object's `labels` entry's type is not a string: type = %s",
1170 msgpack_object_type_str(elem_obj
->type
));
1174 iret
= lttng_event_field_value_enum_append_label_with_size(
1175 *field_val
, elem_obj
->via
.str
.ptr
, elem_obj
->via
.str
.size
);
1184 ERR("Unexpected object type: type = %s", msgpack_object_type_str(obj
->type
));
1195 lttng_event_field_value_destroy(*field_val
);
1196 *field_val
= nullptr;
1203 static struct lttng_event_field_value
*
1204 event_field_value_from_capture_payload(const struct lttng_condition_event_rule_matches
*condition
,
1205 const char *capture_payload
,
1206 size_t capture_payload_size
)
1208 struct lttng_event_field_value
*ret
= nullptr;
1209 msgpack_unpacked unpacked
;
1210 msgpack_unpack_return unpack_return
;
1211 const msgpack_object
*root_obj
;
1212 const msgpack_object_array
*root_array_obj
;
1216 LTTNG_ASSERT(condition
);
1217 LTTNG_ASSERT(capture_payload
);
1219 /* Initialize value. */
1220 msgpack_unpacked_init(&unpacked
);
1224 msgpack_unpack_next(&unpacked
, capture_payload
, capture_payload_size
, nullptr);
1225 if (unpack_return
!= MSGPACK_UNPACK_SUCCESS
) {
1226 ERR("msgpack_unpack_next() failed to decode the "
1227 "MessagePack-encoded capture payload: "
1228 "size = %zu, ret = %d",
1229 capture_payload_size
,
1234 /* Get root array. */
1235 root_obj
= &unpacked
.data
;
1237 if (root_obj
->type
!= MSGPACK_OBJECT_ARRAY
) {
1238 ERR("Expecting an array as the root object: type = %s",
1239 msgpack_object_type_str(root_obj
->type
));
1243 root_array_obj
= &root_obj
->via
.array
;
1245 /* Create an empty root array event field value. */
1246 ret
= lttng_event_field_value_array_create();
1252 * For each capture descriptor in the condition object:
1254 * 1. Get its corresponding captured field value MessagePack
1257 * 2. Create a corresponding event field value.
1259 * 3. Append it to `ret` (the root array event field value).
1261 count
= lttng_dynamic_pointer_array_get_count(&condition
->capture_descriptors
);
1262 LTTNG_ASSERT(count
> 0);
1264 for (i
= 0; i
< count
; i
++) {
1265 const struct lttng_capture_descriptor
*capture_descriptor
=
1266 lttng_condition_event_rule_matches_get_internal_capture_descriptor_at_index(
1267 &condition
->parent
, i
);
1268 const msgpack_object
*elem_obj
;
1269 struct lttng_event_field_value
*elem_field_val
;
1272 LTTNG_ASSERT(capture_descriptor
);
1274 elem_obj
= &root_array_obj
->ptr
[i
];
1275 iret
= event_field_value_from_obj(elem_obj
, &elem_field_val
);
1280 if (elem_field_val
) {
1281 iret
= lttng_event_field_value_array_append(ret
, elem_field_val
);
1283 iret
= lttng_event_field_value_array_append_unavailable(ret
);
1287 lttng_event_field_value_destroy(elem_field_val
);
1295 lttng_event_field_value_destroy(ret
);
1299 msgpack_unpacked_destroy(&unpacked
);
1303 struct lttng_evaluation
*lttng_evaluation_event_rule_matches_create(
1304 const struct lttng_condition_event_rule_matches
*condition
,
1305 const char *capture_payload
,
1306 size_t capture_payload_size
,
1307 bool decode_capture_payload
)
1309 struct lttng_evaluation_event_rule_matches
*hit
;
1310 struct lttng_evaluation
*evaluation
= nullptr;
1312 hit
= zmalloc
<lttng_evaluation_event_rule_matches
>();
1317 lttng_dynamic_buffer_init(&hit
->capture_payload
);
1319 if (capture_payload
) {
1320 const int ret
= lttng_dynamic_buffer_append(
1321 &hit
->capture_payload
, capture_payload
, capture_payload_size
);
1323 ERR("Failed to initialize capture payload of event rule evaluation");
1327 if (decode_capture_payload
) {
1328 hit
->captured_values
= event_field_value_from_capture_payload(
1329 condition
, capture_payload
, capture_payload_size
);
1330 if (!hit
->captured_values
) {
1331 ERR("Failed to decode the capture payload: size = %zu",
1332 capture_payload_size
);
1338 hit
->parent
.type
= LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES
;
1339 hit
->parent
.serialize
= lttng_evaluation_event_rule_matches_serialize
;
1340 hit
->parent
.destroy
= lttng_evaluation_event_rule_matches_destroy
;
1342 evaluation
= &hit
->parent
;
1347 lttng_evaluation_event_rule_matches_destroy(&hit
->parent
);
1353 enum lttng_evaluation_event_rule_matches_status
1354 lttng_evaluation_event_rule_matches_get_captured_values(
1355 const struct lttng_evaluation
*evaluation
, const struct lttng_event_field_value
**field_val
)
1357 struct lttng_evaluation_event_rule_matches
*hit
;
1358 enum lttng_evaluation_event_rule_matches_status status
=
1359 LTTNG_EVALUATION_EVENT_RULE_MATCHES_STATUS_OK
;
1361 if (!evaluation
|| !is_event_rule_matches_evaluation(evaluation
) || !field_val
) {
1362 status
= LTTNG_EVALUATION_EVENT_RULE_MATCHES_STATUS_INVALID
;
1366 hit
= lttng::utils::container_of(evaluation
, <tng_evaluation_event_rule_matches::parent
);
1367 if (!hit
->captured_values
) {
1368 status
= LTTNG_EVALUATION_EVENT_RULE_MATCHES_STATUS_NONE
;
1372 *field_val
= hit
->captured_values
;
1378 enum lttng_error_code
lttng_condition_event_rule_matches_generate_capture_descriptor_bytecode(
1379 struct lttng_condition
*condition
)
1381 enum lttng_error_code ret
;
1382 enum lttng_condition_status status
;
1383 unsigned int capture_count
, i
;
1385 if (!condition
|| !IS_EVENT_RULE_MATCHES_CONDITION(condition
)) {
1386 ret
= LTTNG_ERR_FATAL
;
1390 status
= lttng_condition_event_rule_matches_get_capture_descriptor_count(condition
,
1392 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
1393 ret
= LTTNG_ERR_FATAL
;
1397 for (i
= 0; i
< capture_count
; i
++) {
1398 struct lttng_capture_descriptor
*local_capture_desc
=
1399 lttng_condition_event_rule_matches_get_internal_capture_descriptor_at_index(
1403 if (local_capture_desc
== nullptr) {
1404 ret
= LTTNG_ERR_FATAL
;
1408 /* Generate the bytecode. */
1409 bytecode_ret
= lttng_event_expr_to_bytecode(local_capture_desc
->event_expression
,
1410 &local_capture_desc
->bytecode
);
1411 if (bytecode_ret
< 0 || local_capture_desc
->bytecode
== nullptr) {
1412 ret
= LTTNG_ERR_INVALID_CAPTURE_EXPRESSION
;
1417 /* Everything went better than expected */
1424 const struct lttng_bytecode
*lttng_condition_event_rule_matches_get_capture_bytecode_at_index(
1425 const struct lttng_condition
*condition
, unsigned int index
)
1427 const struct lttng_condition_event_rule_matches
*event_rule_matches_cond
=
1428 lttng::utils::container_of(condition
, <tng_condition_event_rule_matches::parent
);
1429 struct lttng_capture_descriptor
*desc
= nullptr;
1430 struct lttng_bytecode
*bytecode
= nullptr;
1432 enum lttng_condition_status status
;
1434 if (!condition
|| !IS_EVENT_RULE_MATCHES_CONDITION(condition
)) {
1438 status
= lttng_condition_event_rule_matches_get_capture_descriptor_count(condition
, &count
);
1439 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
1443 if (index
>= count
) {
1447 desc
= (lttng_capture_descriptor
*) lttng_dynamic_pointer_array_get_pointer(
1448 &event_rule_matches_cond
->capture_descriptors
, index
);
1449 if (desc
== nullptr) {
1453 bytecode
= desc
->bytecode
;