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
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 \
+++ /dev/null
-/*
- * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_CONDITION_ON_EVENT_INTERNAL_H
-#define LTTNG_CONDITION_ON_EVENT_INTERNAL_H
-
-#include <lttng/condition/condition-internal.h>
-#include <common/buffer-view.h>
-#include <common/macros.h>
-#include <lttng/condition/evaluation-internal.h>
-#include <common/dynamic-array.h>
-#include <lttng/event-field-value.h>
-
-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 */
+++ /dev/null
-/*
- * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_CONDITION_ON_EVENT_H
-#define LTTNG_CONDITION_ON_EVENT_H
-
-#include <lttng/event-rule/event-rule.h>
-#include <lttng/condition/condition.h>
-#include <lttng/condition/evaluation.h>
-
-#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 */
--- /dev/null
+/*
+ * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_CONDITION_ON_EVENT_INTERNAL_H
+#define LTTNG_CONDITION_ON_EVENT_INTERNAL_H
+
+#include <lttng/condition/condition-internal.h>
+#include <common/buffer-view.h>
+#include <common/macros.h>
+#include <lttng/condition/evaluation-internal.h>
+#include <common/dynamic-array.h>
+#include <lttng/event-field-value.h>
+
+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 */
--- /dev/null
+/*
+ * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_CONDITION_ON_EVENT_H
+#define LTTNG_CONDITION_ON_EVENT_H
+
+#include <lttng/event-rule/event-rule.h>
+#include <lttng/condition/condition.h>
+#include <lttng/condition/evaluation.h>
+
+#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 */
#include <lttng/condition/buffer-usage.h>
#include <lttng/condition/condition.h>
#include <lttng/condition/evaluation.h>
-#include <lttng/condition/event-rule.h>
+#include <lttng/condition/on-event.h>
#include <lttng/condition/session-consumed-size.h>
#include <lttng/condition/session-rotation.h>
#include <lttng/constant.h>
#include <lttng/action/start-session.h>
#include <lttng/action/stop-session.h>
#include <lttng/condition/evaluation.h>
-#include <lttng/condition/event-rule-internal.h>
+#include <lttng/condition/on-event-internal.h>
#include <lttng/lttng-error.h>
#include <lttng/trigger/trigger-internal.h>
#include <pthread.h>
#include <lttng/event-rule/event-rule-internal.h>
#include <lttng/event-rule/tracepoint.h>
#include <lttng/condition/condition.h>
-#include <lttng/condition/event-rule.h>
+#include <lttng/condition/on-event.h>
#include <lttng/domain-internal.h>
#include <common/common.h>
#include <lttng/trigger/trigger-internal.h>
#include <lttng/condition/condition.h>
#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/event-rule.h>
-#include <lttng/condition/event-rule-internal.h>
+#include <lttng/condition/on-event.h>
+#include <lttng/condition/on-event-internal.h>
#include <lttng/event-rule/event-rule.h>
#include <lttng/event-rule/event-rule-internal.h>
#include <lttng/action/action.h>
#include <lttng/condition/buffer-usage-internal.h>
#include <lttng/condition/session-consumed-size-internal.h>
#include <lttng/condition/session-rotation-internal.h>
-#include <lttng/condition/event-rule-internal.h>
-#include <lttng/condition/event-rule.h>
+#include <lttng/condition/on-event-internal.h>
+#include <lttng/condition/on-event.h>
#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/condition/on-event-internal.h>
#include "condition-internal.h"
static
#include <common/compat/errno.h>
#include <lttng/lttng.h>
#include <lttng/condition/condition.h>
-#include <lttng/condition/event-rule.h>
+#include <lttng/condition/on-event.h>
#include <lttng/event-rule/event-rule.h>
#include <lttng/event-rule/event-rule-internal.h>
#include <common/bytecode/bytecode.h>
#include <lttng/userspace-probe.h>
#include <lttng/userspace-probe-internal.h>
-#include <lttng/condition/event-rule.h>
-#include <lttng/condition/event-rule-internal.h>
+#include <lttng/condition/on-event.h>
+#include <lttng/condition/on-event-internal.h>
#include <lttng/event-rule/event-rule.h>
#include <lttng/event-rule/event-rule-internal.h>
#include <lttng/event-rule/userspace-probe-internal.h>
#include <lttng/condition/buffer-usage-internal.h>
#include <lttng/condition/session-consumed-size-internal.h>
#include <lttng/condition/session-rotation-internal.h>
-#include <lttng/condition/event-rule-internal.h>
+#include <lttng/condition/on-event-internal.h>
#include <lttng/domain-internal.h>
#include <lttng/notification/channel-internal.h>
#include <lttng/trigger/trigger-internal.h>
#include <lttng/event-rule/event-rule-internal.h>
#include <lttng/event-rule/tracepoint.h>
#include <lttng/condition/condition.h>
-#include <lttng/condition/event-rule-internal.h>
-#include <lttng/condition/event-rule.h>
+#include <lttng/condition/on-event-internal.h>
+#include <lttng/condition/on-event.h>
#include <lttng/trigger/trigger-internal.h>
#include <common/sessiond-comm/sessiond-comm.h>
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 \
#include <lttng/condition/condition-internal.h>
#include <lttng/condition/buffer-usage-internal.h>
-#include <lttng/condition/event-rule-internal.h>
+#include <lttng/condition/on-event-internal.h>
#include <lttng/condition/session-consumed-size-internal.h>
#include <lttng/condition/session-rotation-internal.h>
#include <common/macros.h>
+++ /dev/null
-/*
- * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#include <assert.h>
-#include <common/error.h>
-#include <common/event-expr-to-bytecode.h>
-#include <common/macros.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <lttng/condition/condition-internal.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/condition/event-rule-internal.h>
-#include <lttng/condition/event-rule.h>
-#include <lttng/event-expr-internal.h>
-#include <lttng/event-expr.h>
-#include <lttng/event-field-value-internal.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/lttng-error.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <vendor/msgpack/msgpack.h>
-
-#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;
-}
--- /dev/null
+/*
+ * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <assert.h>
+#include <common/error.h>
+#include <common/event-expr-to-bytecode.h>
+#include <common/macros.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <lttng/condition/condition-internal.h>
+#include <lttng/condition/on-event-internal.h>
+#include <lttng/condition/on-event.h>
+#include <lttng/event-expr-internal.h>
+#include <lttng/event-expr.h>
+#include <lttng/event-field-value-internal.h>
+#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/lttng-error.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <vendor/msgpack/msgpack.h>
+
+#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;
+}
#include <lttng/condition/buffer-usage-internal.h>
#include <lttng/condition/session-consumed-size-internal.h>
#include <lttng/condition/session-rotation-internal.h>
-#include <lttng/condition/event-rule-internal.h>
+#include <lttng/condition/on-event-internal.h>
#include <common/macros.h>
#include <common/error.h>
#include <stdbool.h>
#include <lttng/trigger/trigger-internal.h>
#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/event-rule-internal.h>
-#include <lttng/condition/event-rule.h>
-#include <lttng/condition/event-rule-internal.h>
+#include <lttng/condition/on-event-internal.h>
+#include <lttng/condition/on-event.h>
+#include <lttng/condition/on-event-internal.h>
#include <lttng/condition/buffer-usage.h>
#include <lttng/event-rule/event-rule-internal.h>
#include <lttng/event-expr-internal.h>
#include <sys/time.h>
#include <time.h>
-#include <lttng/condition/event-rule.h>
+#include <lttng/condition/on-event.h>
#include <lttng/lttng.h>
#include "utils.h"
#include <lttng/event.h>
#include <lttng/event-rule/tracepoint.h>
#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/event-rule.h>
+#include <lttng/condition/on-event.h>
#include <lttng/domain.h>
#include <common/dynamic-buffer.h>
#include <common/buffer-view.h>