From: Jonathan Rajotte Date: Thu, 5 Nov 2020 02:46:11 +0000 (-0500) Subject: Rename files for condition event-rule to on-event X-Git-Tag: v2.13.0-rc1~219 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=e393070aaad23313daae844ff87043babaae69e7;p=lttng-tools.git Rename files for condition event-rule to on-event Signed-off-by: Jonathan Rajotte Signed-off-by: Jérémie Galarneau Change-Id: I8bde2f15674be16c0a21c670affff4c4503ed846 --- diff --git a/include/Makefile.am b/include/Makefile.am index 8dae80973..751fa0ebd 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -134,7 +134,7 @@ lttngactioninclude_HEADERS= \ lttngconditioninclude_HEADERS= \ lttng/condition/condition.h \ lttng/condition/buffer-usage.h \ - lttng/condition/event-rule.h \ + lttng/condition/on-event.h \ lttng/condition/session-consumed-size.h \ lttng/condition/session-rotation.h \ lttng/condition/evaluation.h @@ -167,7 +167,7 @@ noinst_HEADERS = \ lttng/action/stop-session-internal.h \ lttng/condition/condition-internal.h \ lttng/condition/buffer-usage-internal.h \ - lttng/condition/event-rule-internal.h \ + lttng/condition/on-event-internal.h \ lttng/condition/session-consumed-size-internal.h \ lttng/condition/evaluation-internal.h \ lttng/condition/session-rotation-internal.h \ diff --git a/include/lttng/condition/event-rule-internal.h b/include/lttng/condition/event-rule-internal.h deleted file mode 100644 index e22cb762a..000000000 --- a/include/lttng/condition/event-rule-internal.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2019 Jonathan Rajotte - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#ifndef LTTNG_CONDITION_ON_EVENT_INTERNAL_H -#define LTTNG_CONDITION_ON_EVENT_INTERNAL_H - -#include -#include -#include -#include -#include -#include - -struct lttng_capture_descriptor { - struct lttng_event_expr *event_expression; - struct lttng_bytecode *bytecode; -}; - -struct lttng_condition_on_event { - struct lttng_condition parent; - struct lttng_event_rule *rule; - - /* Array of `struct lttng_capture_descriptor *`. */ - struct lttng_dynamic_pointer_array capture_descriptors; -}; - -struct lttng_evaluation_on_event { - struct lttng_evaluation parent; - char *name; - - /* MessagePack-encoded captured event field values. */ - struct lttng_dynamic_buffer capture_payload; - - /* - * The content of this array event field value is the decoded - * version of `capture_payload` above. - * - * This is a cache: it's not serialized/deserialized in - * communications from/to the library and the session daemon. - */ - struct lttng_event_field_value *captured_values; -}; - -struct lttng_evaluation_on_event_comm { - /* Includes the null terminator. */ - uint32_t trigger_name_length; - /* Trigger name. */ - char payload[]; -} LTTNG_PACKED; - -LTTNG_HIDDEN -ssize_t lttng_condition_on_event_create_from_payload( - struct lttng_payload_view *view, - struct lttng_condition **condition); - -LTTNG_HIDDEN -enum lttng_condition_status -lttng_condition_on_event_borrow_rule_mutable( - const struct lttng_condition *condition, - struct lttng_event_rule **rule); - -LTTNG_HIDDEN -struct lttng_evaluation *lttng_evaluation_on_event_create( - const struct lttng_condition_on_event *condition, - const char* trigger_name, - const char *capture_payload, size_t capture_payload_size, - bool decode_capture_payload); - -LTTNG_HIDDEN -ssize_t lttng_evaluation_on_event_create_from_payload( - const struct lttng_condition_on_event *condition, - struct lttng_payload_view *view, - struct lttng_evaluation **_evaluation); - -LTTNG_HIDDEN -enum lttng_error_code -lttng_condition_on_event_generate_capture_descriptor_bytecode( - struct lttng_condition *condition); - -LTTNG_HIDDEN -const struct lttng_bytecode * -lttng_condition_on_event_get_capture_bytecode_at_index( - const struct lttng_condition *condition, unsigned int index); - -#endif /* LTTNG_CONDITION_ON_EVENT_INTERNAL_H */ diff --git a/include/lttng/condition/event-rule.h b/include/lttng/condition/event-rule.h deleted file mode 100644 index 450507613..000000000 --- a/include/lttng/condition/event-rule.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2019 Jonathan Rajotte - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#ifndef LTTNG_CONDITION_ON_EVENT_H -#define LTTNG_CONDITION_ON_EVENT_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct lttng_event_expr; -struct lttng_event_field_value; - -/** - * On event conditions allows an action to be taken whenever an event matching - * the on event is hit by the tracers. - * - * An on event condition can also specify a payload to be captured at runtime. - * This is done via the capture descriptor. - * - * Note: the dynamic runtime capture of payload is only available for the - * trigger notification subsystem. - */ - -/* - * Create a newly allocated on event condition. - * - * Returns a new condition on success, NULL on failure. This condition must be - * destroyed using lttng_condition_destroy(). - */ -extern struct lttng_condition *lttng_condition_on_event_create( - struct lttng_event_rule *rule); - -/* - * Get the rule property of a on event condition. - * - * The caller does not assume the ownership of the returned rule. The - * rule shall only be used for the duration of the condition's - * lifetime. - * - * Returns LTTNG_CONDITION_STATUS_OK and a pointer to the condition's rule - * on success, LTTNG_CONDITION_STATUS_INVALID if an invalid - * parameter is passed. */ -extern enum lttng_condition_status lttng_condition_on_event_get_rule( - const struct lttng_condition *condition, - const struct lttng_event_rule **rule); - -/** - * lttng_evaluation_on_event_hit are specialised lttng_evaluations which - * allow users to query a number of properties resulting from the evaluation - * of a condition which evaluated to true. - * - * The evaluation of a on event hit yields two different results: - * TEMPORARY - The name of the triggers associated with the condition. - * TODO - The captured event payload if any - */ - -/* - * Get the trigger name property of a on event hit evaluation. - * - * Returns LTTNG_EVALUATION_STATUS_OK on success and a trigger name - * or LTTNG_EVALUATION_STATUS_INVALID if - * an invalid parameter is passed. - */ -extern enum lttng_evaluation_status -lttng_evaluation_on_event_get_trigger_name( - const struct lttng_evaluation *evaluation, - const char **name); - -/* - * Sets `*field_val` to the array event field value of the on event - * condition evaluation `evaluation` which contains its captured values. - * - * Returns: - * - * `LTTNG_EVALUATION_STATUS_OK`: - * Success. - * - * `*field_val` is an array event field value with a length of at - * least one. - * - * `LTTNG_EVALUATION_STATUS_INVALID`: - * * `evaluation` is `NULL`. - * * The type of the condition of `evaluation` is not - * `LTTNG_CONDITION_TYPE_ON_EVENT`. - * * The condition of `evaluation` has no capture descriptors. - * * `field_val` is `NULL`. - */ -extern enum lttng_evaluation_status -lttng_evaluation_on_event_get_captured_values( - const struct lttng_evaluation *evaluation, - const struct lttng_event_field_value **field_val); - -/* - * Appends (transfering the ownership) the capture descriptor `expr` to - * the on event condition `condition`. - * - * Returns: - * - * `LTTNG_CONDITION_STATUS_OK`: - * Success. - * - * `LTTNG_CONDITION_STATUS_ERROR`: - * Memory error. - * - * `LTTNG_CONDITION_STATUS_INVALID`: - * * `condition` is `NULL`. - * * The type of `condition` is not - * `LTTNG_CONDITION_TYPE_ON_EVENT`. - * * `expr` is `NULL`. - * * `expr` is not a locator expression, that is, its type is not - * one of: - * - * * `LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD` - * * `LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD` - * * `LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD` - * * `LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT` - * - * `LTTNG_CONDITION_STATUS_UNSUPPORTED`: - * * The associated event-rule does not support runtime capture. - */ -extern enum lttng_condition_status -lttng_condition_on_event_append_capture_descriptor( - struct lttng_condition *condition, - struct lttng_event_expr *expr); - -/* - * Sets `*count` to the number of capture descriptors in the on event - * condition `condition`. - * - * Returns: - * - * `LTTNG_CONDITION_STATUS_OK`: - * Success. - * - * `LTTNG_CONDITION_STATUS_INVALID`: - * * `condition` is `NULL`. - * * The type of `condition` is not - * `LTTNG_CONDITION_TYPE_ON_EVENT`. - * * `count` is `NULL`. - */ -extern enum lttng_condition_status -lttng_condition_on_event_get_capture_descriptor_count( - const struct lttng_condition *condition, unsigned int *count); - -/* - * Returns the capture descriptor (borrowed) of the on event condition - * `condition` at the index `index`, or `NULL` if: - * - * * `condition` is `NULL`. - * * The type of `condition` is not - * `LTTNG_CONDITION_TYPE_ON_EVENT`. - * * `index` is greater than or equal to the number of capture - * descriptors in `condition` (as returned by - * lttng_condition_on_event_get_capture_descriptor_count()). - */ -extern const struct lttng_event_expr * -lttng_condition_on_event_get_capture_descriptor_at_index( - const struct lttng_condition *condition, unsigned int index); - -#ifdef __cplusplus -} -#endif - -#endif /* LTTNG_CONDITION_ON_EVENT_H */ diff --git a/include/lttng/condition/on-event-internal.h b/include/lttng/condition/on-event-internal.h new file mode 100644 index 000000000..e22cb762a --- /dev/null +++ b/include/lttng/condition/on-event-internal.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2019 Jonathan Rajotte + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_CONDITION_ON_EVENT_INTERNAL_H +#define LTTNG_CONDITION_ON_EVENT_INTERNAL_H + +#include +#include +#include +#include +#include +#include + +struct lttng_capture_descriptor { + struct lttng_event_expr *event_expression; + struct lttng_bytecode *bytecode; +}; + +struct lttng_condition_on_event { + struct lttng_condition parent; + struct lttng_event_rule *rule; + + /* Array of `struct lttng_capture_descriptor *`. */ + struct lttng_dynamic_pointer_array capture_descriptors; +}; + +struct lttng_evaluation_on_event { + struct lttng_evaluation parent; + char *name; + + /* MessagePack-encoded captured event field values. */ + struct lttng_dynamic_buffer capture_payload; + + /* + * The content of this array event field value is the decoded + * version of `capture_payload` above. + * + * This is a cache: it's not serialized/deserialized in + * communications from/to the library and the session daemon. + */ + struct lttng_event_field_value *captured_values; +}; + +struct lttng_evaluation_on_event_comm { + /* Includes the null terminator. */ + uint32_t trigger_name_length; + /* Trigger name. */ + char payload[]; +} LTTNG_PACKED; + +LTTNG_HIDDEN +ssize_t lttng_condition_on_event_create_from_payload( + struct lttng_payload_view *view, + struct lttng_condition **condition); + +LTTNG_HIDDEN +enum lttng_condition_status +lttng_condition_on_event_borrow_rule_mutable( + const struct lttng_condition *condition, + struct lttng_event_rule **rule); + +LTTNG_HIDDEN +struct lttng_evaluation *lttng_evaluation_on_event_create( + const struct lttng_condition_on_event *condition, + const char* trigger_name, + const char *capture_payload, size_t capture_payload_size, + bool decode_capture_payload); + +LTTNG_HIDDEN +ssize_t lttng_evaluation_on_event_create_from_payload( + const struct lttng_condition_on_event *condition, + struct lttng_payload_view *view, + struct lttng_evaluation **_evaluation); + +LTTNG_HIDDEN +enum lttng_error_code +lttng_condition_on_event_generate_capture_descriptor_bytecode( + struct lttng_condition *condition); + +LTTNG_HIDDEN +const struct lttng_bytecode * +lttng_condition_on_event_get_capture_bytecode_at_index( + const struct lttng_condition *condition, unsigned int index); + +#endif /* LTTNG_CONDITION_ON_EVENT_INTERNAL_H */ diff --git a/include/lttng/condition/on-event.h b/include/lttng/condition/on-event.h new file mode 100644 index 000000000..450507613 --- /dev/null +++ b/include/lttng/condition/on-event.h @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2019 Jonathan Rajotte + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_CONDITION_ON_EVENT_H +#define LTTNG_CONDITION_ON_EVENT_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct lttng_event_expr; +struct lttng_event_field_value; + +/** + * On event conditions allows an action to be taken whenever an event matching + * the on event is hit by the tracers. + * + * An on event condition can also specify a payload to be captured at runtime. + * This is done via the capture descriptor. + * + * Note: the dynamic runtime capture of payload is only available for the + * trigger notification subsystem. + */ + +/* + * Create a newly allocated on event condition. + * + * Returns a new condition on success, NULL on failure. This condition must be + * destroyed using lttng_condition_destroy(). + */ +extern struct lttng_condition *lttng_condition_on_event_create( + struct lttng_event_rule *rule); + +/* + * Get the rule property of a on event condition. + * + * The caller does not assume the ownership of the returned rule. The + * rule shall only be used for the duration of the condition's + * lifetime. + * + * Returns LTTNG_CONDITION_STATUS_OK and a pointer to the condition's rule + * on success, LTTNG_CONDITION_STATUS_INVALID if an invalid + * parameter is passed. */ +extern enum lttng_condition_status lttng_condition_on_event_get_rule( + const struct lttng_condition *condition, + const struct lttng_event_rule **rule); + +/** + * lttng_evaluation_on_event_hit are specialised lttng_evaluations which + * allow users to query a number of properties resulting from the evaluation + * of a condition which evaluated to true. + * + * The evaluation of a on event hit yields two different results: + * TEMPORARY - The name of the triggers associated with the condition. + * TODO - The captured event payload if any + */ + +/* + * Get the trigger name property of a on event hit evaluation. + * + * Returns LTTNG_EVALUATION_STATUS_OK on success and a trigger name + * or LTTNG_EVALUATION_STATUS_INVALID if + * an invalid parameter is passed. + */ +extern enum lttng_evaluation_status +lttng_evaluation_on_event_get_trigger_name( + const struct lttng_evaluation *evaluation, + const char **name); + +/* + * Sets `*field_val` to the array event field value of the on event + * condition evaluation `evaluation` which contains its captured values. + * + * Returns: + * + * `LTTNG_EVALUATION_STATUS_OK`: + * Success. + * + * `*field_val` is an array event field value with a length of at + * least one. + * + * `LTTNG_EVALUATION_STATUS_INVALID`: + * * `evaluation` is `NULL`. + * * The type of the condition of `evaluation` is not + * `LTTNG_CONDITION_TYPE_ON_EVENT`. + * * The condition of `evaluation` has no capture descriptors. + * * `field_val` is `NULL`. + */ +extern enum lttng_evaluation_status +lttng_evaluation_on_event_get_captured_values( + const struct lttng_evaluation *evaluation, + const struct lttng_event_field_value **field_val); + +/* + * Appends (transfering the ownership) the capture descriptor `expr` to + * the on event condition `condition`. + * + * Returns: + * + * `LTTNG_CONDITION_STATUS_OK`: + * Success. + * + * `LTTNG_CONDITION_STATUS_ERROR`: + * Memory error. + * + * `LTTNG_CONDITION_STATUS_INVALID`: + * * `condition` is `NULL`. + * * The type of `condition` is not + * `LTTNG_CONDITION_TYPE_ON_EVENT`. + * * `expr` is `NULL`. + * * `expr` is not a locator expression, that is, its type is not + * one of: + * + * * `LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD` + * * `LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD` + * * `LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD` + * * `LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT` + * + * `LTTNG_CONDITION_STATUS_UNSUPPORTED`: + * * The associated event-rule does not support runtime capture. + */ +extern enum lttng_condition_status +lttng_condition_on_event_append_capture_descriptor( + struct lttng_condition *condition, + struct lttng_event_expr *expr); + +/* + * Sets `*count` to the number of capture descriptors in the on event + * condition `condition`. + * + * Returns: + * + * `LTTNG_CONDITION_STATUS_OK`: + * Success. + * + * `LTTNG_CONDITION_STATUS_INVALID`: + * * `condition` is `NULL`. + * * The type of `condition` is not + * `LTTNG_CONDITION_TYPE_ON_EVENT`. + * * `count` is `NULL`. + */ +extern enum lttng_condition_status +lttng_condition_on_event_get_capture_descriptor_count( + const struct lttng_condition *condition, unsigned int *count); + +/* + * Returns the capture descriptor (borrowed) of the on event condition + * `condition` at the index `index`, or `NULL` if: + * + * * `condition` is `NULL`. + * * The type of `condition` is not + * `LTTNG_CONDITION_TYPE_ON_EVENT`. + * * `index` is greater than or equal to the number of capture + * descriptors in `condition` (as returned by + * lttng_condition_on_event_get_capture_descriptor_count()). + */ +extern const struct lttng_event_expr * +lttng_condition_on_event_get_capture_descriptor_at_index( + const struct lttng_condition *condition, unsigned int index); + +#ifdef __cplusplus +} +#endif + +#endif /* LTTNG_CONDITION_ON_EVENT_H */ diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h index 84032d1ec..790943edf 100644 --- a/include/lttng/lttng.h +++ b/include/lttng/lttng.h @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/bin/lttng-sessiond/action-executor.c b/src/bin/lttng-sessiond/action-executor.c index 69bf1f1d3..7c2079ae9 100644 --- a/src/bin/lttng-sessiond/action-executor.c +++ b/src/bin/lttng-sessiond/action-executor.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/bin/lttng-sessiond/agent.c b/src/bin/lttng-sessiond/agent.c index f9d98ab1e..9832e5ef9 100644 --- a/src/bin/lttng-sessiond/agent.c +++ b/src/bin/lttng-sessiond/agent.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 6732a1c3c..d3fc274c3 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -30,8 +30,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include diff --git a/src/bin/lttng-sessiond/condition-internal.c b/src/bin/lttng-sessiond/condition-internal.c index 0163a8977..07b32f86d 100644 --- a/src/bin/lttng-sessiond/condition-internal.c +++ b/src/bin/lttng-sessiond/condition-internal.c @@ -13,9 +13,10 @@ #include #include #include -#include -#include +#include +#include #include +#include #include "condition-internal.h" static diff --git a/src/bin/lttng-sessiond/event.c b/src/bin/lttng-sessiond/event.c index 17f510154..136617d77 100644 --- a/src/bin/lttng-sessiond/event.c +++ b/src/bin/lttng-sessiond/event.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index 4e5216edc..bad864db0 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -28,8 +28,8 @@ #include #include -#include -#include +#include +#include #include #include #include diff --git a/src/bin/lttng-sessiond/notification-thread-events.c b/src/bin/lttng-sessiond/notification-thread-events.c index aadc1b0a8..816456cd8 100644 --- a/src/bin/lttng-sessiond/notification-thread-events.c +++ b/src/bin/lttng-sessiond/notification-thread-events.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index de2289502..81e3bd848 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -26,8 +26,8 @@ #include #include #include -#include -#include +#include +#include #include #include diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 154ab0faf..9aca16b2e 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -45,7 +45,7 @@ libcommon_la_SOURCES = \ common.h \ conditions/buffer-usage.c \ conditions/condition.c \ - conditions/event-rule.c \ + conditions/on-event.c \ conditions/session-consumed-size.c \ conditions/session-rotation.c \ context.c context.h \ diff --git a/src/common/conditions/condition.c b/src/common/conditions/condition.c index fa45ee22b..4948dbd3f 100644 --- a/src/common/conditions/condition.c +++ b/src/common/conditions/condition.c @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/common/conditions/event-rule.c b/src/common/conditions/event-rule.c deleted file mode 100644 index b1219544a..000000000 --- a/src/common/conditions/event-rule.c +++ /dev/null @@ -1,1513 +0,0 @@ -/* - * Copyright (C) 2020 Jonathan Rajotte - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define IS_ON_EVENT_CONDITION(condition) \ - (lttng_condition_get_type(condition) == \ - LTTNG_CONDITION_TYPE_ON_EVENT) - -static bool is_on_event_evaluation(const struct lttng_evaluation *evaluation) -{ - enum lttng_condition_type type = lttng_evaluation_get_type(evaluation); - - return type == LTTNG_CONDITION_TYPE_ON_EVENT; -} - -static bool lttng_condition_on_event_validate( - const struct lttng_condition *condition); -static int lttng_condition_on_event_serialize( - const struct lttng_condition *condition, - struct lttng_payload *payload); -static bool lttng_condition_on_event_is_equal( - const struct lttng_condition *_a, - const struct lttng_condition *_b); -static void lttng_condition_on_event_destroy( - struct lttng_condition *condition); - -static bool lttng_condition_on_event_validate( - const struct lttng_condition *condition) -{ - bool valid = false; - struct lttng_condition_on_event *event_rule; - - if (!condition) { - goto end; - } - - event_rule = container_of( - condition, struct lttng_condition_on_event, parent); - if (!event_rule->rule) { - ERR("Invalid on event condition: a rule must be set"); - goto end; - } - - valid = lttng_event_rule_validate(event_rule->rule); -end: - return valid; -} - -static const char *msgpack_object_type_str(msgpack_object_type type) -{ - const char *name; - - switch (type) { - case MSGPACK_OBJECT_NIL: - name = "MSGPACK_OBJECT_NIL"; - break; - case MSGPACK_OBJECT_BOOLEAN: - name = "MSGPACK_OBJECT_BOOLEAN"; - break; - case MSGPACK_OBJECT_POSITIVE_INTEGER: - name = "MSGPACK_OBJECT_POSITIVE_INTEGER"; - break; - case MSGPACK_OBJECT_NEGATIVE_INTEGER: - name = "MSGPACK_OBJECT_NEGATIVE_INTEGER"; - break; - case MSGPACK_OBJECT_FLOAT32: - name = "MSGPACK_OBJECT_FLOAT32"; - break; - case MSGPACK_OBJECT_FLOAT: - /* Same value as MSGPACK_OBJECT_FLOAT64 */ - name = "MSGPACK_OBJECT_FLOAT(64)"; - break; - case MSGPACK_OBJECT_STR: - name = "MSGPACK_OBJECT_STR"; - break; - case MSGPACK_OBJECT_ARRAY: - name = "MSGPACK_OBJECT_ARRAY"; - break; - case MSGPACK_OBJECT_MAP: - name = "MSGPACK_OBJECT_MAP"; - break; - case MSGPACK_OBJECT_BIN: - name = "MSGPACK_OBJECT_BIN"; - break; - case MSGPACK_OBJECT_EXT: - name = "MSGPACK_OBJECT_EXT"; - break; - default: - abort(); - } - - return name; -} - -/* - * Serializes the C string `str` into `buf`. - * - * Encoding is the length of `str` plus one (for the null character), - * and then the string, including its null terminator. - */ -static -int serialize_cstr(const char *str, struct lttng_dynamic_buffer *buf) -{ - int ret; - const uint32_t len = strlen(str) + 1; - - /* Serialize the length, including the null terminator. */ - DBG("Serializing C string's length (including null terminator): " - "%" PRIu32, len); - ret = lttng_dynamic_buffer_append(buf, &len, sizeof(len)); - if (ret) { - goto end; - } - - /* Serialize the string. */ - DBG("Serializing C string: '%s'", str); - ret = lttng_dynamic_buffer_append(buf, str, len); - if (ret) { - goto end; - } - -end: - return ret; -} - -/* - * Serializes the event expression `expr` into `buf`. - */ -static -int serialize_event_expr(const struct lttng_event_expr *expr, - struct lttng_payload *payload) -{ - const uint8_t type = expr->type; - int ret; - - /* Serialize the expression's type. */ - DBG("Serializing event expression's type: %d", expr->type); - ret = lttng_dynamic_buffer_append(&payload->buffer, &type, sizeof(type)); - if (ret) { - goto end; - } - - /* Serialize the expression */ - switch (expr->type) { - case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD: - case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD: - { - const struct lttng_event_expr_field *field_expr = - container_of(expr, - const struct lttng_event_expr_field, - parent); - - /* Serialize the field name. */ - DBG("Serializing field event expression's field name: '%s'", - field_expr->name); - ret = serialize_cstr(field_expr->name, &payload->buffer); - if (ret) { - goto end; - } - - break; - } - case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD: - { - const struct lttng_event_expr_app_specific_context_field *field_expr = - container_of(expr, - const struct lttng_event_expr_app_specific_context_field, - parent); - - /* Serialize the provider name. */ - DBG("Serializing app-specific context field event expression's " - "provider name: '%s'", - field_expr->provider_name); - ret = serialize_cstr(field_expr->provider_name, &payload->buffer); - if (ret) { - goto end; - } - - /* Serialize the type name. */ - DBG("Serializing app-specific context field event expression's " - "type name: '%s'", - field_expr->provider_name); - ret = serialize_cstr(field_expr->type_name, &payload->buffer); - if (ret) { - goto end; - } - - break; - } - case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT: - { - const struct lttng_event_expr_array_field_element *elem_expr = - container_of(expr, - const struct lttng_event_expr_array_field_element, - parent); - const uint32_t index = elem_expr->index; - - /* Serialize the index. */ - DBG("Serializing array field element event expression's " - "index: %u", elem_expr->index); - ret = lttng_dynamic_buffer_append(&payload->buffer, &index, sizeof(index)); - if (ret) { - goto end; - } - - /* Serialize the parent array field expression. */ - DBG("Serializing array field element event expression's " - "parent array field event expression"); - ret = serialize_event_expr(elem_expr->array_field_expr, payload); - if (ret) { - goto end; - } - - break; - } - default: - break; - } - -end: - return ret; -} - -static -struct lttng_capture_descriptor * -lttng_condition_on_event_get_internal_capture_descriptor_at_index( - const struct lttng_condition *condition, unsigned int index) -{ - const struct lttng_condition_on_event *on_event_cond = - container_of(condition, - const struct lttng_condition_on_event, - parent); - struct lttng_capture_descriptor *desc = NULL; - unsigned int count; - enum lttng_condition_status status; - - if (!condition || !IS_ON_EVENT_CONDITION(condition)) { - goto end; - } - - status = lttng_condition_on_event_get_capture_descriptor_count( - condition, &count); - if (status != LTTNG_CONDITION_STATUS_OK) { - goto end; - } - - if (index >= count) { - goto end; - } - - desc = lttng_dynamic_pointer_array_get_pointer( - &on_event_cond->capture_descriptors, index); -end: - return desc; -} - -static int lttng_condition_on_event_serialize( - const struct lttng_condition *condition, - struct lttng_payload *payload) -{ - int ret; - struct lttng_condition_on_event *on_event_condition; - enum lttng_condition_status status; - /* Used for iteration and communication (size matters). */ - uint32_t i, capture_descr_count; - - if (!condition || !IS_ON_EVENT_CONDITION(condition)) { - ret = -1; - goto end; - } - - DBG("Serializing on event condition"); - on_event_condition = container_of( - condition, struct lttng_condition_on_event, parent); - - DBG("Serializing on event condition's event rule"); - ret = lttng_event_rule_serialize(on_event_condition->rule, payload); - if (ret) { - goto end; - } - - status = lttng_condition_on_event_get_capture_descriptor_count( - condition, &capture_descr_count); - if (status != LTTNG_CONDITION_STATUS_OK) { - ret = -1; - goto end; - }; - - DBG("Serializing on event condition's capture descriptor count: %" PRIu32, - capture_descr_count); - ret = lttng_dynamic_buffer_append(&payload->buffer, &capture_descr_count, - sizeof(capture_descr_count)); - if (ret) { - goto end; - } - - for (i = 0; i < capture_descr_count; i++) { - const struct lttng_capture_descriptor *desc = - lttng_condition_on_event_get_internal_capture_descriptor_at_index( - condition, i); - - DBG("Serializing on event condition's capture descriptor %" PRIu32, - i); - ret = serialize_event_expr(desc->event_expression, payload); - if (ret) { - goto end; - } - } - -end: - return ret; -} - -static -bool capture_descriptors_are_equal( - const struct lttng_condition *condition_a, - const struct lttng_condition *condition_b) -{ - bool is_equal = true; - unsigned int capture_descr_count_a; - unsigned int capture_descr_count_b; - size_t i; - enum lttng_condition_status status; - - status = lttng_condition_on_event_get_capture_descriptor_count( - condition_a, &capture_descr_count_a); - if (status != LTTNG_CONDITION_STATUS_OK) { - goto not_equal; - } - - status = lttng_condition_on_event_get_capture_descriptor_count( - condition_b, &capture_descr_count_b); - if (status != LTTNG_CONDITION_STATUS_OK) { - goto not_equal; - } - - if (capture_descr_count_a != capture_descr_count_b) { - goto not_equal; - } - - for (i = 0; i < capture_descr_count_a; i++) { - const struct lttng_event_expr *expr_a = - lttng_condition_on_event_get_capture_descriptor_at_index( - condition_a, - i); - const struct lttng_event_expr *expr_b = - lttng_condition_on_event_get_capture_descriptor_at_index( - condition_b, - i); - - if (!lttng_event_expr_is_equal(expr_a, expr_b)) { - goto not_equal; - } - } - - goto end; - -not_equal: - is_equal = false; - -end: - return is_equal; -} - -static bool lttng_condition_on_event_is_equal( - const struct lttng_condition *_a, - const struct lttng_condition *_b) -{ - bool is_equal = false; - struct lttng_condition_on_event *a, *b; - - a = container_of(_a, struct lttng_condition_on_event, parent); - b = container_of(_b, struct lttng_condition_on_event, parent); - - /* Both event rules must be set or both must be unset. */ - if ((a->rule && !b->rule) || (!a->rule && b->rule)) { - WARN("Comparing event_rule conditions with uninitialized rule"); - goto end; - } - - is_equal = lttng_event_rule_is_equal(a->rule, b->rule); - if (!is_equal) { - goto end; - } - - is_equal = capture_descriptors_are_equal(_a, _b); - -end: - return is_equal; -} - -static void lttng_condition_on_event_destroy( - struct lttng_condition *condition) -{ - struct lttng_condition_on_event *on_event_condition; - - on_event_condition = container_of( - condition, struct lttng_condition_on_event, parent); - - lttng_event_rule_put(on_event_condition->rule); - lttng_dynamic_pointer_array_reset(&on_event_condition->capture_descriptors); - free(on_event_condition); -} - -static -void destroy_capture_descriptor(void *ptr) -{ - struct lttng_capture_descriptor *desc = - (struct lttng_capture_descriptor *) ptr; - - lttng_event_expr_destroy(desc->event_expression); - free(desc->bytecode); - free(desc); -} - -struct lttng_condition *lttng_condition_on_event_create( - struct lttng_event_rule *rule) -{ - struct lttng_condition *parent = NULL; - struct lttng_condition_on_event *condition = NULL; - - if (!rule) { - goto end; - } - - condition = zmalloc(sizeof(struct lttng_condition_on_event)); - if (!condition) { - return NULL; - } - - lttng_condition_init(&condition->parent, - LTTNG_CONDITION_TYPE_ON_EVENT); - condition->parent.validate = lttng_condition_on_event_validate, - condition->parent.serialize = lttng_condition_on_event_serialize, - condition->parent.equal = lttng_condition_on_event_is_equal, - condition->parent.destroy = lttng_condition_on_event_destroy, - - lttng_event_rule_get(rule); - condition->rule = rule; - rule = NULL; - - lttng_dynamic_pointer_array_init(&condition->capture_descriptors, - destroy_capture_descriptor); - - parent = &condition->parent; -end: - return parent; -} - -static -uint64_t uint_from_buffer(const struct lttng_buffer_view *view, size_t size, - size_t *offset) -{ - uint64_t ret; - const struct lttng_buffer_view uint_view = - lttng_buffer_view_from_view(view, *offset, size); - - if (!lttng_buffer_view_is_valid(&uint_view)) { - ret = UINT64_C(-1); - goto end; - } - - switch (size) { - case 1: - ret = (uint64_t) *uint_view.data; - break; - case sizeof(uint32_t): - { - uint32_t u32; - - memcpy(&u32, uint_view.data, sizeof(u32)); - ret = (uint64_t) u32; - break; - } - case sizeof(ret): - memcpy(&ret, uint_view.data, sizeof(ret)); - break; - default: - abort(); - } - - *offset += size; - -end: - return ret; -} - -static -const char *str_from_buffer(const struct lttng_buffer_view *view, - size_t *offset) -{ - uint64_t len; - const char *ret; - - len = uint_from_buffer(view, sizeof(uint32_t), offset); - if (len == UINT64_C(-1)) { - goto error; - } - - ret = &view->data[*offset]; - - if (!lttng_buffer_view_contains_string(view, ret, len)) { - goto error; - } - - *offset += len; - goto end; - -error: - ret = NULL; - -end: - return ret; -} - -static -struct lttng_event_expr *event_expr_from_payload( - struct lttng_payload_view *view, size_t *offset) -{ - struct lttng_event_expr *expr = NULL; - const char *str; - uint64_t type; - - type = uint_from_buffer(&view->buffer, sizeof(uint8_t), offset); - if (type == UINT64_C(-1)) { - goto error; - } - - switch (type) { - case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD: - str = str_from_buffer(&view->buffer, offset); - if (!str) { - goto error; - } - - expr = lttng_event_expr_event_payload_field_create(str); - break; - case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD: - str = str_from_buffer(&view->buffer, offset); - if (!str) { - goto error; - } - - expr = lttng_event_expr_channel_context_field_create(str); - break; - case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD: - { - const char *provider_name; - const char *type_name; - - provider_name = str_from_buffer(&view->buffer, offset); - if (!provider_name) { - goto error; - } - - type_name = str_from_buffer(&view->buffer, offset); - if (!type_name) { - goto error; - } - - expr = lttng_event_expr_app_specific_context_field_create( - provider_name, type_name); - break; - } - case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT: - { - struct lttng_event_expr *array_field_expr; - const uint64_t index = uint_from_buffer( - &view->buffer, sizeof(uint32_t), offset); - - if (index == UINT64_C(-1)) { - goto error; - } - - /* Array field expression is the encoded after this. */ - array_field_expr = event_expr_from_payload(view, offset); - if (!array_field_expr) { - goto error; - } - - /* Move ownership of `array_field_expr` to new expression. */ - expr = lttng_event_expr_array_field_element_create( - array_field_expr, (unsigned int) index); - if (!expr) { - /* `array_field_expr` not moved: destroy it. */ - lttng_event_expr_destroy(array_field_expr); - } - - break; - } - default: - abort(); - } - - goto end; - -error: - lttng_event_expr_destroy(expr); - expr = NULL; - -end: - return expr; -} - -LTTNG_HIDDEN -ssize_t lttng_condition_on_event_create_from_payload( - struct lttng_payload_view *view, - struct lttng_condition **_condition) -{ - ssize_t consumed_length; - size_t offset = 0; - ssize_t event_rule_length; - uint32_t i, capture_descr_count; - struct lttng_condition *condition = NULL; - struct lttng_event_rule *event_rule = NULL; - - if (!view || !_condition) { - goto error; - } - - /* Struct lttng_event_rule. */ - { - struct lttng_payload_view event_rule_view = - lttng_payload_view_from_view(view, offset, -1); - - event_rule_length = lttng_event_rule_create_from_payload( - &event_rule_view, &event_rule); - } - - if (event_rule_length < 0 || !event_rule) { - goto error; - } - - /* Create condition (no capture descriptors yet) at this point */ - condition = lttng_condition_on_event_create(event_rule); - if (!condition) { - goto error; - } - - /* Capture descriptor count. */ - assert(event_rule_length >= 0); - offset += (size_t) event_rule_length; - capture_descr_count = uint_from_buffer(&view->buffer, sizeof(uint32_t), &offset); - if (capture_descr_count == UINT32_C(-1)) { - goto error; - } - - /* Capture descriptors. */ - for (i = 0; i < capture_descr_count; i++) { - enum lttng_condition_status status; - struct lttng_event_expr *expr = event_expr_from_payload( - view, &offset); - - if (!expr) { - goto error; - } - - /* Move ownership of `expr` to `condition`. */ - status = lttng_condition_on_event_append_capture_descriptor( - condition, expr); - if (status != LTTNG_CONDITION_STATUS_OK) { - /* `expr` not moved: destroy it. */ - lttng_event_expr_destroy(expr); - goto error; - } - } - - consumed_length = (ssize_t) offset; - *_condition = condition; - condition = NULL; - goto end; - -error: - consumed_length = -1; - -end: - lttng_event_rule_put(event_rule); - lttng_condition_put(condition); - return consumed_length; -} - -LTTNG_HIDDEN -enum lttng_condition_status lttng_condition_on_event_borrow_rule_mutable( - const struct lttng_condition *condition, - struct lttng_event_rule **rule) -{ - struct lttng_condition_on_event *event_rule; - enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; - - if (!condition || !IS_ON_EVENT_CONDITION(condition) || !rule) { - status = LTTNG_CONDITION_STATUS_INVALID; - goto end; - } - - event_rule = container_of( - condition, struct lttng_condition_on_event, parent); - if (!event_rule->rule) { - status = LTTNG_CONDITION_STATUS_UNSET; - goto end; - } - - *rule = event_rule->rule; -end: - return status; -} - -enum lttng_condition_status lttng_condition_on_event_get_rule( - const struct lttng_condition *condition, - const struct lttng_event_rule **rule) -{ - struct lttng_event_rule *mutable_rule = NULL; - const enum lttng_condition_status status = - lttng_condition_on_event_borrow_rule_mutable( - condition, &mutable_rule); - - *rule = mutable_rule; - return status; -} - -enum lttng_condition_status -lttng_condition_on_event_append_capture_descriptor( - struct lttng_condition *condition, - struct lttng_event_expr *expr) -{ - int ret; - enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; - struct lttng_condition_on_event *event_rule_cond = - container_of(condition, - struct lttng_condition_on_event, parent); - struct lttng_capture_descriptor *descriptor = NULL; - const struct lttng_event_rule *rule = NULL; - - /* Only accept l-values. */ - if (!condition || !IS_ON_EVENT_CONDITION(condition) || !expr || - !lttng_event_expr_is_lvalue(expr)) { - status = LTTNG_CONDITION_STATUS_INVALID; - goto end; - } - - status = lttng_condition_on_event_get_rule(condition, &rule); - if (status != LTTNG_CONDITION_STATUS_OK) { - goto end; - } - - switch(lttng_event_rule_get_type(rule)) { - case LTTNG_EVENT_RULE_TYPE_TRACEPOINT: - case LTTNG_EVENT_RULE_TYPE_SYSCALL: - /* Supported. */ - status = LTTNG_CONDITION_STATUS_OK; - break; - case LTTNG_EVENT_RULE_TYPE_UNKNOWN: - status = LTTNG_CONDITION_STATUS_INVALID; - break; - default: - status = LTTNG_CONDITION_STATUS_UNSUPPORTED; - break; - } - - if (status != LTTNG_CONDITION_STATUS_OK) { - goto end; - } - - descriptor = malloc(sizeof(*descriptor)); - if (descriptor == NULL) { - status = LTTNG_CONDITION_STATUS_ERROR; - goto end; - } - - descriptor->event_expression = expr; - descriptor->bytecode = NULL; - - ret = lttng_dynamic_pointer_array_add_pointer( - &event_rule_cond->capture_descriptors, descriptor); - if (ret) { - status = LTTNG_CONDITION_STATUS_ERROR; - goto end; - } - - /* Ownership is transfered to the internal capture_descriptors array */ - descriptor = NULL; -end: - free(descriptor); - return status; -} - -enum lttng_condition_status -lttng_condition_on_event_get_capture_descriptor_count( - const struct lttng_condition *condition, unsigned int *count) -{ - enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; - const struct lttng_condition_on_event *on_event_condition = - container_of(condition, - const struct lttng_condition_on_event, - parent); - - if (!condition || !IS_ON_EVENT_CONDITION(condition) || !count) { - status = LTTNG_CONDITION_STATUS_INVALID; - goto end; - } - - *count = lttng_dynamic_pointer_array_get_count( - &on_event_condition->capture_descriptors); - -end: - return status; -} - -const struct lttng_event_expr * -lttng_condition_on_event_get_capture_descriptor_at_index( - const struct lttng_condition *condition, unsigned int index) -{ - const struct lttng_event_expr *expr = NULL; - const struct lttng_capture_descriptor *desc = NULL; - - desc = lttng_condition_on_event_get_internal_capture_descriptor_at_index( - condition, index); - if (desc == NULL) { - goto end; - } - expr = desc->event_expression; - -end: - return expr; -} - -LTTNG_HIDDEN -ssize_t lttng_evaluation_on_event_create_from_payload( - const struct lttng_condition_on_event *condition, - struct lttng_payload_view *view, - struct lttng_evaluation **_evaluation) -{ - ssize_t ret, offset = 0; - const char *trigger_name; - struct lttng_evaluation *evaluation = NULL; - const struct lttng_evaluation_on_event_comm *header; - const struct lttng_payload_view header_view = - lttng_payload_view_from_view( - view, 0, sizeof(*header)); - uint32_t capture_payload_size; - const char *capture_payload = NULL; - - if (!_evaluation) { - ret = -1; - goto error; - } - - if (!lttng_payload_view_is_valid(&header_view)) { - ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain header"); - ret = -1; - goto error; - } - - header = (typeof(header)) header_view.buffer.data; - - /* Map the originating trigger's name. */ - offset += sizeof(*header); - { - const struct lttng_payload_view current_view = - lttng_payload_view_from_view(view, offset, - header->trigger_name_length); - - if (!lttng_payload_view_is_valid(¤t_view)) { - ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain trigger name"); - ret = -1; - goto error; - } - - trigger_name = current_view.buffer.data; - if (!lttng_buffer_view_contains_string(¤t_view.buffer, - trigger_name, header->trigger_name_length)) { - ERR("Failed to initialize from malformed event rule evaluation: invalid trigger name"); - ret = -1; - goto error; - } - } - - offset += header->trigger_name_length; - { - const struct lttng_payload_view current_view = - lttng_payload_view_from_view(view, offset, -1); - - if (current_view.buffer.size < sizeof(capture_payload_size)) { - ret = -1; - goto error; - } - - memcpy(&capture_payload_size, current_view.buffer.data, - sizeof(capture_payload_size)); - } - offset += sizeof(capture_payload_size); - - if (capture_payload_size > 0) { - const struct lttng_payload_view current_view = - lttng_payload_view_from_view(view, offset, -1); - - if (current_view.buffer.size < capture_payload_size) { - ret = -1; - goto error; - } - - capture_payload = current_view.buffer.data; - } - - evaluation = lttng_evaluation_on_event_create(condition, trigger_name, - capture_payload, capture_payload_size, true); - if (!evaluation) { - ret = -1; - goto error; - } - - offset += capture_payload_size; - *_evaluation = evaluation; - evaluation = NULL; - ret = offset; - -error: - lttng_evaluation_destroy(evaluation); - return ret; -} - -static int lttng_evaluation_on_event_serialize( - const struct lttng_evaluation *evaluation, - struct lttng_payload *payload) -{ - int ret = 0; - struct lttng_evaluation_on_event *hit; - struct lttng_evaluation_on_event_comm comm; - uint32_t capture_payload_size; - - hit = container_of( - evaluation, struct lttng_evaluation_on_event, parent); - - assert(hit->name); - comm.trigger_name_length = strlen(hit->name) + 1; - - ret = lttng_dynamic_buffer_append( - &payload->buffer, &comm, sizeof(comm)); - if (ret) { - goto end; - } - - ret = lttng_dynamic_buffer_append( - &payload->buffer, hit->name, comm.trigger_name_length); - if (ret) { - goto end; - } - - capture_payload_size = (uint32_t) hit->capture_payload.size; - ret = lttng_dynamic_buffer_append(&payload->buffer, &capture_payload_size, - sizeof(capture_payload_size)); - if (ret) { - goto end; - } - - ret = lttng_dynamic_buffer_append(&payload->buffer, hit->capture_payload.data, - hit->capture_payload.size); - if (ret) { - goto end; - } - -end: - return ret; -} - -static -bool msgpack_str_is_equal(const struct msgpack_object *obj, const char *str) -{ - bool is_equal = true; - - assert(obj->type == MSGPACK_OBJECT_STR); - - if (obj->via.str.size != strlen(str)) { - is_equal = false; - goto end; - } - - if (strncmp(obj->via.str.ptr, str, obj->via.str.size) != 0) { - is_equal = false; - goto end; - } - -end: - return is_equal; -} - -static -const msgpack_object *get_msgpack_map_obj(const struct msgpack_object *map_obj, - const char *name) -{ - const msgpack_object *ret = NULL; - size_t i; - - assert(map_obj->type == MSGPACK_OBJECT_MAP); - - for (i = 0; i < map_obj->via.map.size; i++) { - const struct msgpack_object_kv *kv = &map_obj->via.map.ptr[i]; - - assert(kv->key.type == MSGPACK_OBJECT_STR); - - if (msgpack_str_is_equal(&kv->key, name)) { - ret = &kv->val; - goto end; - } - } - -end: - return ret; -} - -static void lttng_evaluation_on_event_destroy( - struct lttng_evaluation *evaluation) -{ - struct lttng_evaluation_on_event *hit; - - hit = container_of( - evaluation, struct lttng_evaluation_on_event, parent); - free(hit->name); - lttng_dynamic_buffer_reset(&hit->capture_payload); - lttng_event_field_value_destroy(hit->captured_values); - free(hit); -} - -static -int event_field_value_from_obj(const msgpack_object *obj, - struct lttng_event_field_value **field_val) -{ - int ret = 0; - - assert(obj); - assert(field_val); - - switch (obj->type) { - case MSGPACK_OBJECT_NIL: - /* Unavailable. */ - *field_val = NULL; - goto end; - case MSGPACK_OBJECT_POSITIVE_INTEGER: - *field_val = lttng_event_field_value_uint_create( - obj->via.u64); - break; - case MSGPACK_OBJECT_NEGATIVE_INTEGER: - *field_val = lttng_event_field_value_int_create( - obj->via.i64); - break; - case MSGPACK_OBJECT_FLOAT32: - case MSGPACK_OBJECT_FLOAT64: - *field_val = lttng_event_field_value_real_create( - obj->via.f64); - break; - case MSGPACK_OBJECT_STR: - *field_val = lttng_event_field_value_string_create_with_size( - obj->via.str.ptr, obj->via.str.size); - break; - case MSGPACK_OBJECT_ARRAY: - { - size_t i; - - *field_val = lttng_event_field_value_array_create(); - if (!*field_val) { - goto error; - } - - for (i = 0; i < obj->via.array.size; i++) { - const msgpack_object *elem_obj = &obj->via.array.ptr[i]; - struct lttng_event_field_value *elem_field_val; - - ret = event_field_value_from_obj(elem_obj, - &elem_field_val); - if (ret) { - goto error; - } - - if (elem_field_val) { - ret = lttng_event_field_value_array_append( - *field_val, elem_field_val); - } else { - ret = lttng_event_field_value_array_append_unavailable( - *field_val); - } - - if (ret) { - lttng_event_field_value_destroy(elem_field_val); - goto error; - } - } - - break; - } - case MSGPACK_OBJECT_MAP: - { - /* - * As of this version, the only valid map object is - * for an enumeration value, for example: - * - * type: enum - * value: 177 - * labels: - * - Labatt 50 - * - Molson Dry - * - Carling Black Label - */ - const msgpack_object *inner_obj; - size_t label_i; - - inner_obj = get_msgpack_map_obj(obj, "type"); - if (!inner_obj) { - ERR("Missing `type` entry in map object"); - goto error; - } - - if (inner_obj->type != MSGPACK_OBJECT_STR) { - ERR("Map object's `type` entry is not a string: type = %s", - msgpack_object_type_str(inner_obj->type)); - goto error; - } - - if (!msgpack_str_is_equal(inner_obj, "enum")) { - ERR("Map object's `type` entry: expecting `enum`"); - goto error; - } - - inner_obj = get_msgpack_map_obj(obj, "value"); - if (!inner_obj) { - ERR("Missing `value` entry in map object"); - goto error; - } - - if (inner_obj->type == MSGPACK_OBJECT_POSITIVE_INTEGER) { - *field_val = lttng_event_field_value_enum_uint_create( - inner_obj->via.u64); - } else if (inner_obj->type == MSGPACK_OBJECT_NEGATIVE_INTEGER) { - *field_val = lttng_event_field_value_enum_int_create( - inner_obj->via.i64); - } else { - ERR("Map object's `value` entry is not an integer: type = %s", - msgpack_object_type_str(inner_obj->type)); - goto error; - } - - if (!*field_val) { - goto error; - } - - inner_obj = get_msgpack_map_obj(obj, "labels"); - if (!inner_obj) { - /* No labels */ - goto end; - } - - if (inner_obj->type != MSGPACK_OBJECT_ARRAY) { - ERR("Map object's `labels` entry is not an array: type = %s", - msgpack_object_type_str(inner_obj->type)); - goto error; - } - - for (label_i = 0; label_i < inner_obj->via.array.size; - label_i++) { - int iret; - const msgpack_object *elem_obj = - &inner_obj->via.array.ptr[label_i]; - - if (elem_obj->type != MSGPACK_OBJECT_STR) { - ERR("Map object's `labels` entry's type is not a string: type = %s", - msgpack_object_type_str(elem_obj->type)); - goto error; - } - - iret = lttng_event_field_value_enum_append_label_with_size( - *field_val, elem_obj->via.str.ptr, - elem_obj->via.str.size); - if (iret) { - goto error; - } - } - - break; - } - default: - ERR("Unexpected object type: type = %s", - msgpack_object_type_str(obj->type)); - goto error; - } - - if (!*field_val) { - goto error; - } - - goto end; - -error: - lttng_event_field_value_destroy(*field_val); - *field_val = NULL; - ret = -1; - -end: - return ret; -} - -static -struct lttng_event_field_value *event_field_value_from_capture_payload( - const struct lttng_condition_on_event *condition, - const char *capture_payload, size_t capture_payload_size) -{ - struct lttng_event_field_value *ret = NULL; - msgpack_unpacked unpacked; - msgpack_unpack_return unpack_return; - const msgpack_object *root_obj; - const msgpack_object_array *root_array_obj; - size_t i; - size_t count; - - assert(condition); - assert(capture_payload); - - /* Initialize value. */ - msgpack_unpacked_init(&unpacked); - - /* Decode. */ - unpack_return = msgpack_unpack_next(&unpacked, capture_payload, - capture_payload_size, NULL); - if (unpack_return != MSGPACK_UNPACK_SUCCESS) { - ERR("msgpack_unpack_next() failed to decode the " - "MessagePack-encoded capture payload: " - "size = %zu, ret = %d", - capture_payload_size, unpack_return); - goto error; - } - - /* Get root array. */ - root_obj = &unpacked.data; - - if (root_obj->type != MSGPACK_OBJECT_ARRAY) { - ERR("Expecting an array as the root object: type = %s", - msgpack_object_type_str(root_obj->type)); - goto error; - } - - root_array_obj = &root_obj->via.array; - - /* Create an empty root array event field value. */ - ret = lttng_event_field_value_array_create(); - if (!ret) { - goto error; - } - - /* - * For each capture descriptor in the condition object: - * - * 1. Get its corresponding captured field value MessagePack - * object. - * - * 2. Create a corresponding event field value. - * - * 3. Append it to `ret` (the root array event field value). - */ - count = lttng_dynamic_pointer_array_get_count( - &condition->capture_descriptors); - assert(count > 0); - - for (i = 0; i < count; i++) { - const struct lttng_capture_descriptor *capture_descriptor = - lttng_condition_on_event_get_internal_capture_descriptor_at_index( - &condition->parent, i); - const msgpack_object *elem_obj; - struct lttng_event_field_value *elem_field_val; - int iret; - - assert(capture_descriptor); - - elem_obj = &root_array_obj->ptr[i]; - iret = event_field_value_from_obj(elem_obj, - &elem_field_val); - if (iret) { - goto error; - } - - if (elem_field_val) { - iret = lttng_event_field_value_array_append(ret, - elem_field_val); - } else { - iret = lttng_event_field_value_array_append_unavailable( - ret); - } - - if (iret) { - lttng_event_field_value_destroy(elem_field_val); - goto error; - } - } - - goto end; - -error: - lttng_event_field_value_destroy(ret); - ret = NULL; - -end: - msgpack_unpacked_destroy(&unpacked); - return ret; -} - -LTTNG_HIDDEN -struct lttng_evaluation *lttng_evaluation_on_event_create( - const struct lttng_condition_on_event *condition, - const char *trigger_name, - const char *capture_payload, size_t capture_payload_size, - bool decode_capture_payload) -{ - struct lttng_evaluation_on_event *hit; - struct lttng_evaluation *evaluation = NULL; - - hit = zmalloc(sizeof(struct lttng_evaluation_on_event)); - if (!hit) { - goto error; - } - - hit->name = strdup(trigger_name); - if (!hit->name) { - goto error; - } - - lttng_dynamic_buffer_init(&hit->capture_payload); - - if (capture_payload) { - const int ret = lttng_dynamic_buffer_append( - &hit->capture_payload, capture_payload, - capture_payload_size); - if (ret) { - ERR("Failed to initialize capture payload of event rule evaluation"); - goto error; - } - - if (decode_capture_payload) { - hit->captured_values = - event_field_value_from_capture_payload( - condition, - capture_payload, - capture_payload_size); - if (!hit->captured_values) { - ERR("Failed to decode the capture payload: size = %zu", - capture_payload_size); - goto error; - } - } - } - - hit->parent.type = LTTNG_CONDITION_TYPE_ON_EVENT; - hit->parent.serialize = lttng_evaluation_on_event_serialize; - hit->parent.destroy = lttng_evaluation_on_event_destroy; - - evaluation = &hit->parent; - hit = NULL; - -error: - if (hit) { - lttng_evaluation_on_event_destroy(&hit->parent); - } - - return evaluation; -} - -enum lttng_evaluation_status lttng_evaluation_on_event_get_captured_values( - const struct lttng_evaluation *evaluation, - const struct lttng_event_field_value **field_val) -{ - struct lttng_evaluation_on_event *hit; - enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK; - - if (!evaluation || !is_on_event_evaluation(evaluation) || - !field_val) { - status = LTTNG_EVALUATION_STATUS_INVALID; - goto end; - } - - hit = container_of(evaluation, struct lttng_evaluation_on_event, - parent); - if (!hit->captured_values) { - status = LTTNG_EVALUATION_STATUS_INVALID; - goto end; - } - - *field_val = hit->captured_values; - -end: - return status; -} - -enum lttng_evaluation_status lttng_evaluation_on_event_get_trigger_name( - const struct lttng_evaluation *evaluation, const char **name) -{ - struct lttng_evaluation_on_event *hit; - enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK; - - if (!evaluation || !is_on_event_evaluation(evaluation) || !name) { - status = LTTNG_EVALUATION_STATUS_INVALID; - goto end; - } - - hit = container_of( - evaluation, struct lttng_evaluation_on_event, parent); - *name = hit->name; -end: - return status; -} - -LTTNG_HIDDEN -enum lttng_error_code -lttng_condition_on_event_generate_capture_descriptor_bytecode( - struct lttng_condition *condition) -{ - enum lttng_error_code ret; - enum lttng_condition_status status; - unsigned int capture_count, i; - - if (!condition || !IS_ON_EVENT_CONDITION(condition)) { - ret = LTTNG_ERR_FATAL; - goto end; - } - - status = lttng_condition_on_event_get_capture_descriptor_count( - condition, &capture_count); - if (status != LTTNG_CONDITION_STATUS_OK) { - ret = LTTNG_ERR_FATAL; - goto end; - } - - for (i = 0; i < capture_count; i++) { - struct lttng_capture_descriptor *local_capture_desc = - lttng_condition_on_event_get_internal_capture_descriptor_at_index( - condition, i); - - if (local_capture_desc == NULL) { - ret = LTTNG_ERR_FATAL; - goto end; - } - - /* Generate the bytecode. */ - status = lttng_event_expr_to_bytecode( - local_capture_desc->event_expression, - &local_capture_desc->bytecode); - if (status < 0 || local_capture_desc->bytecode == NULL) { - ret = LTTNG_ERR_INVALID_CAPTURE_EXPRESSION; - goto end; - } - } - - /* Everything went better than expected */ - ret = LTTNG_OK; - -end: - return ret; -} - -LTTNG_HIDDEN -const struct lttng_bytecode * -lttng_condition_on_event_get_capture_bytecode_at_index( - const struct lttng_condition *condition, unsigned int index) -{ - const struct lttng_condition_on_event *event_rule_cond = - container_of(condition, - const struct lttng_condition_on_event, - parent); - struct lttng_capture_descriptor *desc = NULL; - struct lttng_bytecode *bytecode = NULL; - unsigned int count; - enum lttng_condition_status status; - - if (!condition || !IS_ON_EVENT_CONDITION(condition)) { - goto end; - } - - status = lttng_condition_on_event_get_capture_descriptor_count( - condition, &count); - if (status != LTTNG_CONDITION_STATUS_OK) { - goto end; - } - - if (index >= count) { - goto end; - } - - desc = lttng_dynamic_pointer_array_get_pointer( - &event_rule_cond->capture_descriptors, index); - if (desc == NULL) { - goto end; - } - - bytecode = desc->bytecode; -end: - return bytecode; -} diff --git a/src/common/conditions/on-event.c b/src/common/conditions/on-event.c new file mode 100644 index 000000000..a10df868a --- /dev/null +++ b/src/common/conditions/on-event.c @@ -0,0 +1,1512 @@ +/* + * Copyright (C) 2020 Jonathan Rajotte + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IS_ON_EVENT_CONDITION(condition) \ + (lttng_condition_get_type(condition) == \ + LTTNG_CONDITION_TYPE_ON_EVENT) + +static bool is_on_event_evaluation(const struct lttng_evaluation *evaluation) +{ + enum lttng_condition_type type = lttng_evaluation_get_type(evaluation); + + return type == LTTNG_CONDITION_TYPE_ON_EVENT; +} + +static bool lttng_condition_on_event_validate( + const struct lttng_condition *condition); +static int lttng_condition_on_event_serialize( + const struct lttng_condition *condition, + struct lttng_payload *payload); +static bool lttng_condition_on_event_is_equal( + const struct lttng_condition *_a, + const struct lttng_condition *_b); +static void lttng_condition_on_event_destroy( + struct lttng_condition *condition); + +static bool lttng_condition_on_event_validate( + const struct lttng_condition *condition) +{ + bool valid = false; + struct lttng_condition_on_event *event_rule; + + if (!condition) { + goto end; + } + + event_rule = container_of( + condition, struct lttng_condition_on_event, parent); + if (!event_rule->rule) { + ERR("Invalid on event condition: a rule must be set"); + goto end; + } + + valid = lttng_event_rule_validate(event_rule->rule); +end: + return valid; +} + +static const char *msgpack_object_type_str(msgpack_object_type type) +{ + const char *name; + + switch (type) { + case MSGPACK_OBJECT_NIL: + name = "MSGPACK_OBJECT_NIL"; + break; + case MSGPACK_OBJECT_BOOLEAN: + name = "MSGPACK_OBJECT_BOOLEAN"; + break; + case MSGPACK_OBJECT_POSITIVE_INTEGER: + name = "MSGPACK_OBJECT_POSITIVE_INTEGER"; + break; + case MSGPACK_OBJECT_NEGATIVE_INTEGER: + name = "MSGPACK_OBJECT_NEGATIVE_INTEGER"; + break; + case MSGPACK_OBJECT_FLOAT32: + name = "MSGPACK_OBJECT_FLOAT32"; + break; + case MSGPACK_OBJECT_FLOAT: + /* Same value as MSGPACK_OBJECT_FLOAT64 */ + name = "MSGPACK_OBJECT_FLOAT(64)"; + break; + case MSGPACK_OBJECT_STR: + name = "MSGPACK_OBJECT_STR"; + break; + case MSGPACK_OBJECT_ARRAY: + name = "MSGPACK_OBJECT_ARRAY"; + break; + case MSGPACK_OBJECT_MAP: + name = "MSGPACK_OBJECT_MAP"; + break; + case MSGPACK_OBJECT_BIN: + name = "MSGPACK_OBJECT_BIN"; + break; + case MSGPACK_OBJECT_EXT: + name = "MSGPACK_OBJECT_EXT"; + break; + default: + abort(); + } + + return name; +} + +/* + * Serializes the C string `str` into `buf`. + * + * Encoding is the length of `str` plus one (for the null character), + * and then the string, including its null terminator. + */ +static +int serialize_cstr(const char *str, struct lttng_dynamic_buffer *buf) +{ + int ret; + const uint32_t len = strlen(str) + 1; + + /* Serialize the length, including the null terminator. */ + DBG("Serializing C string's length (including null terminator): " + "%" PRIu32, len); + ret = lttng_dynamic_buffer_append(buf, &len, sizeof(len)); + if (ret) { + goto end; + } + + /* Serialize the string. */ + DBG("Serializing C string: '%s'", str); + ret = lttng_dynamic_buffer_append(buf, str, len); + if (ret) { + goto end; + } + +end: + return ret; +} + +/* + * Serializes the event expression `expr` into `buf`. + */ +static +int serialize_event_expr(const struct lttng_event_expr *expr, + struct lttng_payload *payload) +{ + const uint8_t type = expr->type; + int ret; + + /* Serialize the expression's type. */ + DBG("Serializing event expression's type: %d", expr->type); + ret = lttng_dynamic_buffer_append(&payload->buffer, &type, sizeof(type)); + if (ret) { + goto end; + } + + /* Serialize the expression */ + switch (expr->type) { + case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD: + case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD: + { + const struct lttng_event_expr_field *field_expr = + container_of(expr, + const struct lttng_event_expr_field, + parent); + + /* Serialize the field name. */ + DBG("Serializing field event expression's field name: '%s'", + field_expr->name); + ret = serialize_cstr(field_expr->name, &payload->buffer); + if (ret) { + goto end; + } + + break; + } + case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD: + { + const struct lttng_event_expr_app_specific_context_field *field_expr = + container_of(expr, + const struct lttng_event_expr_app_specific_context_field, + parent); + + /* Serialize the provider name. */ + DBG("Serializing app-specific context field event expression's " + "provider name: '%s'", + field_expr->provider_name); + ret = serialize_cstr(field_expr->provider_name, &payload->buffer); + if (ret) { + goto end; + } + + /* Serialize the type name. */ + DBG("Serializing app-specific context field event expression's " + "type name: '%s'", + field_expr->provider_name); + ret = serialize_cstr(field_expr->type_name, &payload->buffer); + if (ret) { + goto end; + } + + break; + } + case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT: + { + const struct lttng_event_expr_array_field_element *elem_expr = + container_of(expr, + const struct lttng_event_expr_array_field_element, + parent); + const uint32_t index = elem_expr->index; + + /* Serialize the index. */ + DBG("Serializing array field element event expression's " + "index: %u", elem_expr->index); + ret = lttng_dynamic_buffer_append(&payload->buffer, &index, sizeof(index)); + if (ret) { + goto end; + } + + /* Serialize the parent array field expression. */ + DBG("Serializing array field element event expression's " + "parent array field event expression"); + ret = serialize_event_expr(elem_expr->array_field_expr, payload); + if (ret) { + goto end; + } + + break; + } + default: + break; + } + +end: + return ret; +} + +static +struct lttng_capture_descriptor * +lttng_condition_on_event_get_internal_capture_descriptor_at_index( + const struct lttng_condition *condition, unsigned int index) +{ + const struct lttng_condition_on_event *on_event_cond = + container_of(condition, + const struct lttng_condition_on_event, + parent); + struct lttng_capture_descriptor *desc = NULL; + unsigned int count; + enum lttng_condition_status status; + + if (!condition || !IS_ON_EVENT_CONDITION(condition)) { + goto end; + } + + status = lttng_condition_on_event_get_capture_descriptor_count( + condition, &count); + if (status != LTTNG_CONDITION_STATUS_OK) { + goto end; + } + + if (index >= count) { + goto end; + } + + desc = lttng_dynamic_pointer_array_get_pointer( + &on_event_cond->capture_descriptors, index); +end: + return desc; +} + +static int lttng_condition_on_event_serialize( + const struct lttng_condition *condition, + struct lttng_payload *payload) +{ + int ret; + struct lttng_condition_on_event *on_event_condition; + enum lttng_condition_status status; + /* Used for iteration and communication (size matters). */ + uint32_t i, capture_descr_count; + + if (!condition || !IS_ON_EVENT_CONDITION(condition)) { + ret = -1; + goto end; + } + + DBG("Serializing on event condition"); + on_event_condition = container_of( + condition, struct lttng_condition_on_event, parent); + + DBG("Serializing on event condition's event rule"); + ret = lttng_event_rule_serialize(on_event_condition->rule, payload); + if (ret) { + goto end; + } + + status = lttng_condition_on_event_get_capture_descriptor_count( + condition, &capture_descr_count); + if (status != LTTNG_CONDITION_STATUS_OK) { + ret = -1; + goto end; + }; + + DBG("Serializing on event condition's capture descriptor count: %" PRIu32, + capture_descr_count); + ret = lttng_dynamic_buffer_append(&payload->buffer, &capture_descr_count, + sizeof(capture_descr_count)); + if (ret) { + goto end; + } + + for (i = 0; i < capture_descr_count; i++) { + const struct lttng_capture_descriptor *desc = + lttng_condition_on_event_get_internal_capture_descriptor_at_index( + condition, i); + + DBG("Serializing on event condition's capture descriptor %" PRIu32, + i); + ret = serialize_event_expr(desc->event_expression, payload); + if (ret) { + goto end; + } + } + +end: + return ret; +} + +static +bool capture_descriptors_are_equal( + const struct lttng_condition *condition_a, + const struct lttng_condition *condition_b) +{ + bool is_equal = true; + unsigned int capture_descr_count_a; + unsigned int capture_descr_count_b; + size_t i; + enum lttng_condition_status status; + + status = lttng_condition_on_event_get_capture_descriptor_count( + condition_a, &capture_descr_count_a); + if (status != LTTNG_CONDITION_STATUS_OK) { + goto not_equal; + } + + status = lttng_condition_on_event_get_capture_descriptor_count( + condition_b, &capture_descr_count_b); + if (status != LTTNG_CONDITION_STATUS_OK) { + goto not_equal; + } + + if (capture_descr_count_a != capture_descr_count_b) { + goto not_equal; + } + + for (i = 0; i < capture_descr_count_a; i++) { + const struct lttng_event_expr *expr_a = + lttng_condition_on_event_get_capture_descriptor_at_index( + condition_a, + i); + const struct lttng_event_expr *expr_b = + lttng_condition_on_event_get_capture_descriptor_at_index( + condition_b, + i); + + if (!lttng_event_expr_is_equal(expr_a, expr_b)) { + goto not_equal; + } + } + + goto end; + +not_equal: + is_equal = false; + +end: + return is_equal; +} + +static bool lttng_condition_on_event_is_equal( + const struct lttng_condition *_a, + const struct lttng_condition *_b) +{ + bool is_equal = false; + struct lttng_condition_on_event *a, *b; + + a = container_of(_a, struct lttng_condition_on_event, parent); + b = container_of(_b, struct lttng_condition_on_event, parent); + + /* Both event rules must be set or both must be unset. */ + if ((a->rule && !b->rule) || (!a->rule && b->rule)) { + WARN("Comparing event_rule conditions with uninitialized rule"); + goto end; + } + + is_equal = lttng_event_rule_is_equal(a->rule, b->rule); + if (!is_equal) { + goto end; + } + + is_equal = capture_descriptors_are_equal(_a, _b); + +end: + return is_equal; +} + +static void lttng_condition_on_event_destroy( + struct lttng_condition *condition) +{ + struct lttng_condition_on_event *on_event_condition; + + on_event_condition = container_of( + condition, struct lttng_condition_on_event, parent); + + lttng_event_rule_put(on_event_condition->rule); + lttng_dynamic_pointer_array_reset(&on_event_condition->capture_descriptors); + free(on_event_condition); +} + +static +void destroy_capture_descriptor(void *ptr) +{ + struct lttng_capture_descriptor *desc = + (struct lttng_capture_descriptor *) ptr; + + lttng_event_expr_destroy(desc->event_expression); + free(desc->bytecode); + free(desc); +} + +struct lttng_condition *lttng_condition_on_event_create( + struct lttng_event_rule *rule) +{ + struct lttng_condition *parent = NULL; + struct lttng_condition_on_event *condition = NULL; + + if (!rule) { + goto end; + } + + condition = zmalloc(sizeof(struct lttng_condition_on_event)); + if (!condition) { + return NULL; + } + + lttng_condition_init(&condition->parent, + LTTNG_CONDITION_TYPE_ON_EVENT); + condition->parent.validate = lttng_condition_on_event_validate, + condition->parent.serialize = lttng_condition_on_event_serialize, + condition->parent.equal = lttng_condition_on_event_is_equal, + condition->parent.destroy = lttng_condition_on_event_destroy, + + lttng_event_rule_get(rule); + condition->rule = rule; + rule = NULL; + + lttng_dynamic_pointer_array_init(&condition->capture_descriptors, + destroy_capture_descriptor); + + parent = &condition->parent; +end: + return parent; +} + +static +uint64_t uint_from_buffer(const struct lttng_buffer_view *view, size_t size, + size_t *offset) +{ + uint64_t ret; + const struct lttng_buffer_view uint_view = + lttng_buffer_view_from_view(view, *offset, size); + + if (!lttng_buffer_view_is_valid(&uint_view)) { + ret = UINT64_C(-1); + goto end; + } + + switch (size) { + case 1: + ret = (uint64_t) *uint_view.data; + break; + case sizeof(uint32_t): + { + uint32_t u32; + + memcpy(&u32, uint_view.data, sizeof(u32)); + ret = (uint64_t) u32; + break; + } + case sizeof(ret): + memcpy(&ret, uint_view.data, sizeof(ret)); + break; + default: + abort(); + } + + *offset += size; + +end: + return ret; +} + +static +const char *str_from_buffer(const struct lttng_buffer_view *view, + size_t *offset) +{ + uint64_t len; + const char *ret; + + len = uint_from_buffer(view, sizeof(uint32_t), offset); + if (len == UINT64_C(-1)) { + goto error; + } + + ret = &view->data[*offset]; + + if (!lttng_buffer_view_contains_string(view, ret, len)) { + goto error; + } + + *offset += len; + goto end; + +error: + ret = NULL; + +end: + return ret; +} + +static +struct lttng_event_expr *event_expr_from_payload( + struct lttng_payload_view *view, size_t *offset) +{ + struct lttng_event_expr *expr = NULL; + const char *str; + uint64_t type; + + type = uint_from_buffer(&view->buffer, sizeof(uint8_t), offset); + if (type == UINT64_C(-1)) { + goto error; + } + + switch (type) { + case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD: + str = str_from_buffer(&view->buffer, offset); + if (!str) { + goto error; + } + + expr = lttng_event_expr_event_payload_field_create(str); + break; + case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD: + str = str_from_buffer(&view->buffer, offset); + if (!str) { + goto error; + } + + expr = lttng_event_expr_channel_context_field_create(str); + break; + case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD: + { + const char *provider_name; + const char *type_name; + + provider_name = str_from_buffer(&view->buffer, offset); + if (!provider_name) { + goto error; + } + + type_name = str_from_buffer(&view->buffer, offset); + if (!type_name) { + goto error; + } + + expr = lttng_event_expr_app_specific_context_field_create( + provider_name, type_name); + break; + } + case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT: + { + struct lttng_event_expr *array_field_expr; + const uint64_t index = uint_from_buffer( + &view->buffer, sizeof(uint32_t), offset); + + if (index == UINT64_C(-1)) { + goto error; + } + + /* Array field expression is the encoded after this. */ + array_field_expr = event_expr_from_payload(view, offset); + if (!array_field_expr) { + goto error; + } + + /* Move ownership of `array_field_expr` to new expression. */ + expr = lttng_event_expr_array_field_element_create( + array_field_expr, (unsigned int) index); + if (!expr) { + /* `array_field_expr` not moved: destroy it. */ + lttng_event_expr_destroy(array_field_expr); + } + + break; + } + default: + abort(); + } + + goto end; + +error: + lttng_event_expr_destroy(expr); + expr = NULL; + +end: + return expr; +} + +LTTNG_HIDDEN +ssize_t lttng_condition_on_event_create_from_payload( + struct lttng_payload_view *view, + struct lttng_condition **_condition) +{ + ssize_t consumed_length; + size_t offset = 0; + ssize_t event_rule_length; + uint32_t i, capture_descr_count; + struct lttng_condition *condition = NULL; + struct lttng_event_rule *event_rule = NULL; + + if (!view || !_condition) { + goto error; + } + + /* Struct lttng_event_rule. */ + { + struct lttng_payload_view event_rule_view = + lttng_payload_view_from_view(view, offset, -1); + + event_rule_length = lttng_event_rule_create_from_payload( + &event_rule_view, &event_rule); + } + + if (event_rule_length < 0 || !event_rule) { + goto error; + } + + /* Create condition (no capture descriptors yet) at this point */ + condition = lttng_condition_on_event_create(event_rule); + if (!condition) { + goto error; + } + + /* Capture descriptor count. */ + assert(event_rule_length >= 0); + offset += (size_t) event_rule_length; + capture_descr_count = uint_from_buffer(&view->buffer, sizeof(uint32_t), &offset); + if (capture_descr_count == UINT32_C(-1)) { + goto error; + } + + /* Capture descriptors. */ + for (i = 0; i < capture_descr_count; i++) { + enum lttng_condition_status status; + struct lttng_event_expr *expr = event_expr_from_payload( + view, &offset); + + if (!expr) { + goto error; + } + + /* Move ownership of `expr` to `condition`. */ + status = lttng_condition_on_event_append_capture_descriptor( + condition, expr); + if (status != LTTNG_CONDITION_STATUS_OK) { + /* `expr` not moved: destroy it. */ + lttng_event_expr_destroy(expr); + goto error; + } + } + + consumed_length = (ssize_t) offset; + *_condition = condition; + condition = NULL; + goto end; + +error: + consumed_length = -1; + +end: + lttng_event_rule_put(event_rule); + lttng_condition_put(condition); + return consumed_length; +} + +LTTNG_HIDDEN +enum lttng_condition_status lttng_condition_on_event_borrow_rule_mutable( + const struct lttng_condition *condition, + struct lttng_event_rule **rule) +{ + struct lttng_condition_on_event *event_rule; + enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; + + if (!condition || !IS_ON_EVENT_CONDITION(condition) || !rule) { + status = LTTNG_CONDITION_STATUS_INVALID; + goto end; + } + + event_rule = container_of( + condition, struct lttng_condition_on_event, parent); + if (!event_rule->rule) { + status = LTTNG_CONDITION_STATUS_UNSET; + goto end; + } + + *rule = event_rule->rule; +end: + return status; +} + +enum lttng_condition_status lttng_condition_on_event_get_rule( + const struct lttng_condition *condition, + const struct lttng_event_rule **rule) +{ + struct lttng_event_rule *mutable_rule = NULL; + const enum lttng_condition_status status = + lttng_condition_on_event_borrow_rule_mutable( + condition, &mutable_rule); + + *rule = mutable_rule; + return status; +} + +enum lttng_condition_status +lttng_condition_on_event_append_capture_descriptor( + struct lttng_condition *condition, + struct lttng_event_expr *expr) +{ + int ret; + enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; + struct lttng_condition_on_event *event_rule_cond = + container_of(condition, + struct lttng_condition_on_event, parent); + struct lttng_capture_descriptor *descriptor = NULL; + const struct lttng_event_rule *rule = NULL; + + /* Only accept l-values. */ + if (!condition || !IS_ON_EVENT_CONDITION(condition) || !expr || + !lttng_event_expr_is_lvalue(expr)) { + status = LTTNG_CONDITION_STATUS_INVALID; + goto end; + } + + status = lttng_condition_on_event_get_rule(condition, &rule); + if (status != LTTNG_CONDITION_STATUS_OK) { + goto end; + } + + switch(lttng_event_rule_get_type(rule)) { + case LTTNG_EVENT_RULE_TYPE_TRACEPOINT: + case LTTNG_EVENT_RULE_TYPE_SYSCALL: + /* Supported. */ + status = LTTNG_CONDITION_STATUS_OK; + break; + case LTTNG_EVENT_RULE_TYPE_UNKNOWN: + status = LTTNG_CONDITION_STATUS_INVALID; + break; + default: + status = LTTNG_CONDITION_STATUS_UNSUPPORTED; + break; + } + + if (status != LTTNG_CONDITION_STATUS_OK) { + goto end; + } + + descriptor = malloc(sizeof(*descriptor)); + if (descriptor == NULL) { + status = LTTNG_CONDITION_STATUS_ERROR; + goto end; + } + + descriptor->event_expression = expr; + descriptor->bytecode = NULL; + + ret = lttng_dynamic_pointer_array_add_pointer( + &event_rule_cond->capture_descriptors, descriptor); + if (ret) { + status = LTTNG_CONDITION_STATUS_ERROR; + goto end; + } + + /* Ownership is transfered to the internal capture_descriptors array */ + descriptor = NULL; +end: + free(descriptor); + return status; +} + +enum lttng_condition_status +lttng_condition_on_event_get_capture_descriptor_count( + const struct lttng_condition *condition, unsigned int *count) +{ + enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; + const struct lttng_condition_on_event *on_event_condition = + container_of(condition, + const struct lttng_condition_on_event, + parent); + + if (!condition || !IS_ON_EVENT_CONDITION(condition) || !count) { + status = LTTNG_CONDITION_STATUS_INVALID; + goto end; + } + + *count = lttng_dynamic_pointer_array_get_count( + &on_event_condition->capture_descriptors); + +end: + return status; +} + +const struct lttng_event_expr * +lttng_condition_on_event_get_capture_descriptor_at_index( + const struct lttng_condition *condition, unsigned int index) +{ + const struct lttng_event_expr *expr = NULL; + const struct lttng_capture_descriptor *desc = NULL; + + desc = lttng_condition_on_event_get_internal_capture_descriptor_at_index( + condition, index); + if (desc == NULL) { + goto end; + } + expr = desc->event_expression; + +end: + return expr; +} + +LTTNG_HIDDEN +ssize_t lttng_evaluation_on_event_create_from_payload( + const struct lttng_condition_on_event *condition, + struct lttng_payload_view *view, + struct lttng_evaluation **_evaluation) +{ + ssize_t ret, offset = 0; + const char *trigger_name; + struct lttng_evaluation *evaluation = NULL; + const struct lttng_evaluation_on_event_comm *header; + const struct lttng_payload_view header_view = + lttng_payload_view_from_view( + view, 0, sizeof(*header)); + uint32_t capture_payload_size; + const char *capture_payload = NULL; + + if (!_evaluation) { + ret = -1; + goto error; + } + + if (!lttng_payload_view_is_valid(&header_view)) { + ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain header"); + ret = -1; + goto error; + } + + header = (typeof(header)) header_view.buffer.data; + + /* Map the originating trigger's name. */ + offset += sizeof(*header); + { + const struct lttng_payload_view current_view = + lttng_payload_view_from_view(view, offset, + header->trigger_name_length); + + if (!lttng_payload_view_is_valid(¤t_view)) { + ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain trigger name"); + ret = -1; + goto error; + } + + trigger_name = current_view.buffer.data; + if (!lttng_buffer_view_contains_string(¤t_view.buffer, + trigger_name, header->trigger_name_length)) { + ERR("Failed to initialize from malformed event rule evaluation: invalid trigger name"); + ret = -1; + goto error; + } + } + + offset += header->trigger_name_length; + { + const struct lttng_payload_view current_view = + lttng_payload_view_from_view(view, offset, -1); + + if (current_view.buffer.size < sizeof(capture_payload_size)) { + ret = -1; + goto error; + } + + memcpy(&capture_payload_size, current_view.buffer.data, + sizeof(capture_payload_size)); + } + offset += sizeof(capture_payload_size); + + if (capture_payload_size > 0) { + const struct lttng_payload_view current_view = + lttng_payload_view_from_view(view, offset, -1); + + if (current_view.buffer.size < capture_payload_size) { + ret = -1; + goto error; + } + + capture_payload = current_view.buffer.data; + } + + evaluation = lttng_evaluation_on_event_create(condition, trigger_name, + capture_payload, capture_payload_size, true); + if (!evaluation) { + ret = -1; + goto error; + } + + offset += capture_payload_size; + *_evaluation = evaluation; + evaluation = NULL; + ret = offset; + +error: + lttng_evaluation_destroy(evaluation); + return ret; +} + +static int lttng_evaluation_on_event_serialize( + const struct lttng_evaluation *evaluation, + struct lttng_payload *payload) +{ + int ret = 0; + struct lttng_evaluation_on_event *hit; + struct lttng_evaluation_on_event_comm comm; + uint32_t capture_payload_size; + + hit = container_of( + evaluation, struct lttng_evaluation_on_event, parent); + + assert(hit->name); + comm.trigger_name_length = strlen(hit->name) + 1; + + ret = lttng_dynamic_buffer_append( + &payload->buffer, &comm, sizeof(comm)); + if (ret) { + goto end; + } + + ret = lttng_dynamic_buffer_append( + &payload->buffer, hit->name, comm.trigger_name_length); + if (ret) { + goto end; + } + + capture_payload_size = (uint32_t) hit->capture_payload.size; + ret = lttng_dynamic_buffer_append(&payload->buffer, &capture_payload_size, + sizeof(capture_payload_size)); + if (ret) { + goto end; + } + + ret = lttng_dynamic_buffer_append(&payload->buffer, hit->capture_payload.data, + hit->capture_payload.size); + if (ret) { + goto end; + } + +end: + return ret; +} + +static +bool msgpack_str_is_equal(const struct msgpack_object *obj, const char *str) +{ + bool is_equal = true; + + assert(obj->type == MSGPACK_OBJECT_STR); + + if (obj->via.str.size != strlen(str)) { + is_equal = false; + goto end; + } + + if (strncmp(obj->via.str.ptr, str, obj->via.str.size) != 0) { + is_equal = false; + goto end; + } + +end: + return is_equal; +} + +static +const msgpack_object *get_msgpack_map_obj(const struct msgpack_object *map_obj, + const char *name) +{ + const msgpack_object *ret = NULL; + size_t i; + + assert(map_obj->type == MSGPACK_OBJECT_MAP); + + for (i = 0; i < map_obj->via.map.size; i++) { + const struct msgpack_object_kv *kv = &map_obj->via.map.ptr[i]; + + assert(kv->key.type == MSGPACK_OBJECT_STR); + + if (msgpack_str_is_equal(&kv->key, name)) { + ret = &kv->val; + goto end; + } + } + +end: + return ret; +} + +static void lttng_evaluation_on_event_destroy( + struct lttng_evaluation *evaluation) +{ + struct lttng_evaluation_on_event *hit; + + hit = container_of( + evaluation, struct lttng_evaluation_on_event, parent); + free(hit->name); + lttng_dynamic_buffer_reset(&hit->capture_payload); + lttng_event_field_value_destroy(hit->captured_values); + free(hit); +} + +static +int event_field_value_from_obj(const msgpack_object *obj, + struct lttng_event_field_value **field_val) +{ + int ret = 0; + + assert(obj); + assert(field_val); + + switch (obj->type) { + case MSGPACK_OBJECT_NIL: + /* Unavailable. */ + *field_val = NULL; + goto end; + case MSGPACK_OBJECT_POSITIVE_INTEGER: + *field_val = lttng_event_field_value_uint_create( + obj->via.u64); + break; + case MSGPACK_OBJECT_NEGATIVE_INTEGER: + *field_val = lttng_event_field_value_int_create( + obj->via.i64); + break; + case MSGPACK_OBJECT_FLOAT32: + case MSGPACK_OBJECT_FLOAT64: + *field_val = lttng_event_field_value_real_create( + obj->via.f64); + break; + case MSGPACK_OBJECT_STR: + *field_val = lttng_event_field_value_string_create_with_size( + obj->via.str.ptr, obj->via.str.size); + break; + case MSGPACK_OBJECT_ARRAY: + { + size_t i; + + *field_val = lttng_event_field_value_array_create(); + if (!*field_val) { + goto error; + } + + for (i = 0; i < obj->via.array.size; i++) { + const msgpack_object *elem_obj = &obj->via.array.ptr[i]; + struct lttng_event_field_value *elem_field_val; + + ret = event_field_value_from_obj(elem_obj, + &elem_field_val); + if (ret) { + goto error; + } + + if (elem_field_val) { + ret = lttng_event_field_value_array_append( + *field_val, elem_field_val); + } else { + ret = lttng_event_field_value_array_append_unavailable( + *field_val); + } + + if (ret) { + lttng_event_field_value_destroy(elem_field_val); + goto error; + } + } + + break; + } + case MSGPACK_OBJECT_MAP: + { + /* + * As of this version, the only valid map object is + * for an enumeration value, for example: + * + * type: enum + * value: 177 + * labels: + * - Labatt 50 + * - Molson Dry + * - Carling Black Label + */ + const msgpack_object *inner_obj; + size_t label_i; + + inner_obj = get_msgpack_map_obj(obj, "type"); + if (!inner_obj) { + ERR("Missing `type` entry in map object"); + goto error; + } + + if (inner_obj->type != MSGPACK_OBJECT_STR) { + ERR("Map object's `type` entry is not a string: type = %s", + msgpack_object_type_str(inner_obj->type)); + goto error; + } + + if (!msgpack_str_is_equal(inner_obj, "enum")) { + ERR("Map object's `type` entry: expecting `enum`"); + goto error; + } + + inner_obj = get_msgpack_map_obj(obj, "value"); + if (!inner_obj) { + ERR("Missing `value` entry in map object"); + goto error; + } + + if (inner_obj->type == MSGPACK_OBJECT_POSITIVE_INTEGER) { + *field_val = lttng_event_field_value_enum_uint_create( + inner_obj->via.u64); + } else if (inner_obj->type == MSGPACK_OBJECT_NEGATIVE_INTEGER) { + *field_val = lttng_event_field_value_enum_int_create( + inner_obj->via.i64); + } else { + ERR("Map object's `value` entry is not an integer: type = %s", + msgpack_object_type_str(inner_obj->type)); + goto error; + } + + if (!*field_val) { + goto error; + } + + inner_obj = get_msgpack_map_obj(obj, "labels"); + if (!inner_obj) { + /* No labels */ + goto end; + } + + if (inner_obj->type != MSGPACK_OBJECT_ARRAY) { + ERR("Map object's `labels` entry is not an array: type = %s", + msgpack_object_type_str(inner_obj->type)); + goto error; + } + + for (label_i = 0; label_i < inner_obj->via.array.size; + label_i++) { + int iret; + const msgpack_object *elem_obj = + &inner_obj->via.array.ptr[label_i]; + + if (elem_obj->type != MSGPACK_OBJECT_STR) { + ERR("Map object's `labels` entry's type is not a string: type = %s", + msgpack_object_type_str(elem_obj->type)); + goto error; + } + + iret = lttng_event_field_value_enum_append_label_with_size( + *field_val, elem_obj->via.str.ptr, + elem_obj->via.str.size); + if (iret) { + goto error; + } + } + + break; + } + default: + ERR("Unexpected object type: type = %s", + msgpack_object_type_str(obj->type)); + goto error; + } + + if (!*field_val) { + goto error; + } + + goto end; + +error: + lttng_event_field_value_destroy(*field_val); + *field_val = NULL; + ret = -1; + +end: + return ret; +} + +static +struct lttng_event_field_value *event_field_value_from_capture_payload( + const struct lttng_condition_on_event *condition, + const char *capture_payload, size_t capture_payload_size) +{ + struct lttng_event_field_value *ret = NULL; + msgpack_unpacked unpacked; + msgpack_unpack_return unpack_return; + const msgpack_object *root_obj; + const msgpack_object_array *root_array_obj; + size_t i; + size_t count; + + assert(condition); + assert(capture_payload); + + /* Initialize value. */ + msgpack_unpacked_init(&unpacked); + + /* Decode. */ + unpack_return = msgpack_unpack_next(&unpacked, capture_payload, + capture_payload_size, NULL); + if (unpack_return != MSGPACK_UNPACK_SUCCESS) { + ERR("msgpack_unpack_next() failed to decode the " + "MessagePack-encoded capture payload: " + "size = %zu, ret = %d", + capture_payload_size, unpack_return); + goto error; + } + + /* Get root array. */ + root_obj = &unpacked.data; + + if (root_obj->type != MSGPACK_OBJECT_ARRAY) { + ERR("Expecting an array as the root object: type = %s", + msgpack_object_type_str(root_obj->type)); + goto error; + } + + root_array_obj = &root_obj->via.array; + + /* Create an empty root array event field value. */ + ret = lttng_event_field_value_array_create(); + if (!ret) { + goto error; + } + + /* + * For each capture descriptor in the condition object: + * + * 1. Get its corresponding captured field value MessagePack + * object. + * + * 2. Create a corresponding event field value. + * + * 3. Append it to `ret` (the root array event field value). + */ + count = lttng_dynamic_pointer_array_get_count( + &condition->capture_descriptors); + assert(count > 0); + + for (i = 0; i < count; i++) { + const struct lttng_capture_descriptor *capture_descriptor = + lttng_condition_on_event_get_internal_capture_descriptor_at_index( + &condition->parent, i); + const msgpack_object *elem_obj; + struct lttng_event_field_value *elem_field_val; + int iret; + + assert(capture_descriptor); + + elem_obj = &root_array_obj->ptr[i]; + iret = event_field_value_from_obj(elem_obj, + &elem_field_val); + if (iret) { + goto error; + } + + if (elem_field_val) { + iret = lttng_event_field_value_array_append(ret, + elem_field_val); + } else { + iret = lttng_event_field_value_array_append_unavailable( + ret); + } + + if (iret) { + lttng_event_field_value_destroy(elem_field_val); + goto error; + } + } + + goto end; + +error: + lttng_event_field_value_destroy(ret); + ret = NULL; + +end: + msgpack_unpacked_destroy(&unpacked); + return ret; +} + +LTTNG_HIDDEN +struct lttng_evaluation *lttng_evaluation_on_event_create( + const struct lttng_condition_on_event *condition, + const char *trigger_name, + const char *capture_payload, size_t capture_payload_size, + bool decode_capture_payload) +{ + struct lttng_evaluation_on_event *hit; + struct lttng_evaluation *evaluation = NULL; + + hit = zmalloc(sizeof(struct lttng_evaluation_on_event)); + if (!hit) { + goto error; + } + + hit->name = strdup(trigger_name); + if (!hit->name) { + goto error; + } + + lttng_dynamic_buffer_init(&hit->capture_payload); + + if (capture_payload) { + const int ret = lttng_dynamic_buffer_append( + &hit->capture_payload, capture_payload, + capture_payload_size); + if (ret) { + ERR("Failed to initialize capture payload of event rule evaluation"); + goto error; + } + + if (decode_capture_payload) { + hit->captured_values = + event_field_value_from_capture_payload( + condition, + capture_payload, + capture_payload_size); + if (!hit->captured_values) { + ERR("Failed to decode the capture payload: size = %zu", + capture_payload_size); + goto error; + } + } + } + + hit->parent.type = LTTNG_CONDITION_TYPE_ON_EVENT; + hit->parent.serialize = lttng_evaluation_on_event_serialize; + hit->parent.destroy = lttng_evaluation_on_event_destroy; + + evaluation = &hit->parent; + hit = NULL; + +error: + if (hit) { + lttng_evaluation_on_event_destroy(&hit->parent); + } + + return evaluation; +} + +enum lttng_evaluation_status lttng_evaluation_on_event_get_captured_values( + const struct lttng_evaluation *evaluation, + const struct lttng_event_field_value **field_val) +{ + struct lttng_evaluation_on_event *hit; + enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK; + + if (!evaluation || !is_on_event_evaluation(evaluation) || + !field_val) { + status = LTTNG_EVALUATION_STATUS_INVALID; + goto end; + } + + hit = container_of(evaluation, struct lttng_evaluation_on_event, + parent); + if (!hit->captured_values) { + status = LTTNG_EVALUATION_STATUS_INVALID; + goto end; + } + + *field_val = hit->captured_values; + +end: + return status; +} + +enum lttng_evaluation_status lttng_evaluation_on_event_get_trigger_name( + const struct lttng_evaluation *evaluation, const char **name) +{ + struct lttng_evaluation_on_event *hit; + enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK; + + if (!evaluation || !is_on_event_evaluation(evaluation) || !name) { + status = LTTNG_EVALUATION_STATUS_INVALID; + goto end; + } + + hit = container_of( + evaluation, struct lttng_evaluation_on_event, parent); + *name = hit->name; +end: + return status; +} + +LTTNG_HIDDEN +enum lttng_error_code +lttng_condition_on_event_generate_capture_descriptor_bytecode( + struct lttng_condition *condition) +{ + enum lttng_error_code ret; + enum lttng_condition_status status; + unsigned int capture_count, i; + + if (!condition || !IS_ON_EVENT_CONDITION(condition)) { + ret = LTTNG_ERR_FATAL; + goto end; + } + + status = lttng_condition_on_event_get_capture_descriptor_count( + condition, &capture_count); + if (status != LTTNG_CONDITION_STATUS_OK) { + ret = LTTNG_ERR_FATAL; + goto end; + } + + for (i = 0; i < capture_count; i++) { + struct lttng_capture_descriptor *local_capture_desc = + lttng_condition_on_event_get_internal_capture_descriptor_at_index( + condition, i); + + if (local_capture_desc == NULL) { + ret = LTTNG_ERR_FATAL; + goto end; + } + + /* Generate the bytecode. */ + status = lttng_event_expr_to_bytecode( + local_capture_desc->event_expression, + &local_capture_desc->bytecode); + if (status < 0 || local_capture_desc->bytecode == NULL) { + ret = LTTNG_ERR_INVALID_CAPTURE_EXPRESSION; + goto end; + } + } + + /* Everything went better than expected */ + ret = LTTNG_OK; + +end: + return ret; +} + +LTTNG_HIDDEN +const struct lttng_bytecode * +lttng_condition_on_event_get_capture_bytecode_at_index( + const struct lttng_condition *condition, unsigned int index) +{ + const struct lttng_condition_on_event *event_rule_cond = + container_of(condition, + const struct lttng_condition_on_event, + parent); + struct lttng_capture_descriptor *desc = NULL; + struct lttng_bytecode *bytecode = NULL; + unsigned int count; + enum lttng_condition_status status; + + if (!condition || !IS_ON_EVENT_CONDITION(condition)) { + goto end; + } + + status = lttng_condition_on_event_get_capture_descriptor_count( + condition, &count); + if (status != LTTNG_CONDITION_STATUS_OK) { + goto end; + } + + if (index >= count) { + goto end; + } + + desc = lttng_dynamic_pointer_array_get_pointer( + &event_rule_cond->capture_descriptors, index); + if (desc == NULL) { + goto end; + } + + bytecode = desc->bytecode; +end: + return bytecode; +} diff --git a/src/common/evaluation.c b/src/common/evaluation.c index 872875a9f..2b06be614 100644 --- a/src/common/evaluation.c +++ b/src/common/evaluation.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/common/trigger.c b/src/common/trigger.c index 0fdcf4049..ca082d139 100644 --- a/src/common/trigger.c +++ b/src/common/trigger.c @@ -7,9 +7,9 @@ #include #include -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/tests/regression/tools/trigger/utils/notification-client.c b/tests/regression/tools/trigger/utils/notification-client.c index 0722945f7..2c7c896d8 100644 --- a/tests/regression/tools/trigger/utils/notification-client.c +++ b/tests/regression/tools/trigger/utils/notification-client.c @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include "utils.h" diff --git a/tests/unit/test_condition.c b/tests/unit/test_condition.c index 4f4818743..c5a94bb65 100644 --- a/tests/unit/test_condition.c +++ b/tests/unit/test_condition.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include