From: Philippe Proulx Date: Fri, 1 May 2020 20:33:26 +0000 (-0400) Subject: Make captured field values available to event rule cond. evaluation X-Git-Tag: v2.13.0-rc1~233 X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=commitdiff_plain;h=7c920b632d63ffd82074430d77862176e0fc477c Make captured field values available to event rule cond. evaluation liblttng-ctl: Add the public lttng_evaluation_get_captured_values() function. This function returns an array event field value which contains the captured field values as requested by the evaluation's condition's capture descriptors. This array event field value contains as many elements as returned by lttng_condition_event_rule_get_capture_descriptor_count() for the evaluation's condition. However, lttng_event_field_value_array_get_element_at_index() could return `LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE` for some or all indexes if there was no such field to capture at tracing time. Common: Internally, an event rule evaluation now contains a captured field value payload (CFVP) as well as the array event field value to be returned by lttng_evaluation_get_captured_values(). The CFVP is MessagePack-encoded. When you create an event rule evaluation with lttng_evaluation_event_rule_create(), you must pass the CFVP as well as the `decode_capture_payload` option parameter. If `decode_capture_payload` is `true`, lttng_evaluation_event_rule_create() creates the array event field value from the CFVP thanks to msgpack-c. lttng_evaluation_event_rule_create() also accepts the event rule condition now because it relies on the capture descriptors to create the event field values if `decode_capture_payload` is `true`. When an event rule evaluation is serialized: Only its CFVP is serialized (as is). When an event rule evaluation is deserialized: lttng_evaluation_event_rule_create() is called with the `decode_capture_payload` parameter set to `true`. Session daemon: action_executor_notify_handler() calls lttng_evaluation_event_rule_create() with the `decode_capture_payload` parameter set to `false` to send the evaluation to the clients with the CFVP. This CFVP directly comes from the tracer. Signed-off-by: Philippe Proulx Signed-off-by: Jérémie Galarneau Change-Id: Ib2ae39dae005ad555eb8309e0bfd53f746d5e8dd Depends-on: lttng-ust: I8423c510bf6af2f9bf85256e8d6f931d36f7054b --- diff --git a/include/lttng/condition/evaluation-internal.h b/include/lttng/condition/evaluation-internal.h index 15ae4af4d..eaef721fb 100644 --- a/include/lttng/condition/evaluation-internal.h +++ b/include/lttng/condition/evaluation-internal.h @@ -9,6 +9,7 @@ #define LTTNG_EVALUATION_INTERNAL_H #include +#include #include #include #include @@ -38,7 +39,9 @@ void lttng_evaluation_init(struct lttng_evaluation *evaluation, enum lttng_condition_type type); LTTNG_HIDDEN -ssize_t lttng_evaluation_create_from_payload(struct lttng_payload_view *view, +ssize_t lttng_evaluation_create_from_payload( + const struct lttng_condition *condition, + struct lttng_payload_view *view, struct lttng_evaluation **evaluation); LTTNG_HIDDEN diff --git a/include/lttng/condition/event-rule-internal.h b/include/lttng/condition/event-rule-internal.h index 0f2f3fbf6..6dd663d7c 100644 --- a/include/lttng/condition/event-rule-internal.h +++ b/include/lttng/condition/event-rule-internal.h @@ -13,6 +13,7 @@ #include #include #include +#include struct lttng_capture_descriptor { struct lttng_event_expr *event_expression; @@ -30,6 +31,18 @@ struct lttng_condition_event_rule { struct lttng_evaluation_event_rule { 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_event_rule_comm { @@ -52,10 +65,14 @@ lttng_condition_event_rule_borrow_rule_mutable( LTTNG_HIDDEN struct lttng_evaluation *lttng_evaluation_event_rule_create( - const char* trigger_name); + const struct lttng_condition_event_rule *condition, + const char* trigger_name, + const char *capture_payload, size_t capture_payload_size, + bool decode_capture_payload); LTTNG_HIDDEN ssize_t lttng_evaluation_event_rule_create_from_payload( + const struct lttng_condition_event_rule *condition, struct lttng_payload_view *view, struct lttng_evaluation **_evaluation); diff --git a/include/lttng/condition/event-rule.h b/include/lttng/condition/event-rule.h index 91fce32d6..02e7a20e7 100644 --- a/include/lttng/condition/event-rule.h +++ b/include/lttng/condition/event-rule.h @@ -17,6 +17,7 @@ extern "C" { #endif struct lttng_event_expr; +struct lttng_event_field_value; /** * Event rule conditions allows an action to be taken whenever an event matching @@ -74,6 +75,30 @@ lttng_evaluation_event_rule_get_trigger_name( const struct lttng_evaluation *evaluation, const char **name); +/* + * Sets `*field_val` to the array event field value of the event rule + * 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_EVENT_RULE_HIT`. + * * The condition of `evaluation` has no capture descriptors. + * * `field_val` is `NULL`. + */ +extern enum lttng_evaluation_status +lttng_evaluation_event_rule_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 event rule condition `condition`. diff --git a/include/lttng/event-field-value.h b/include/lttng/event-field-value.h index db4a4fb3b..7fa851a79 100644 --- a/include/lttng/event-field-value.h +++ b/include/lttng/event-field-value.h @@ -169,12 +169,18 @@ lttng_event_field_value_real_get_value( * Returns the raw value (an UTF-8 C string) of the string event field * value `field_val`, or `NULL` if: * - * * `field_val` is `NULL`. - * * The type of `field_val` is not - * `LTTNG_EVENT_FIELD_VALUE_TYPE_STRING`. + * `LTTNG_EVENT_FIELD_VALUE_STATUS_OK`: + * Success. + * + * `LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID`: + * * `field_val` is `NULL`. + * * The type of `field_val` is not + * `LTTNG_EVENT_FIELD_VALUE_TYPE_STRING`. */ -extern const char *lttng_event_field_value_string_get_value( - const struct lttng_event_field_value *field_val); +extern enum lttng_event_field_value_status +lttng_event_field_value_string_get_value( + const struct lttng_event_field_value *field_val, + const char **value); /* * Sets `*length` to the length (the number of contained elements) of diff --git a/src/bin/lttng-sessiond/notification-thread-events.c b/src/bin/lttng-sessiond/notification-thread-events.c index 7fea927d8..257fe1c73 100644 --- a/src/bin/lttng-sessiond/notification-thread-events.c +++ b/src/bin/lttng-sessiond/notification-thread-events.c @@ -4350,6 +4350,7 @@ int dispatch_one_event_notifier_notification(struct notification_thread_state *s struct notification_client_list *client_list = NULL; const char *trigger_name; int ret; + unsigned int capture_count = 0; /* Find triggers associated with this token. */ rcu_read_lock(); @@ -4382,14 +4383,34 @@ int dispatch_one_event_notifier_notification(struct notification_thread_state *s trigger_status = lttng_trigger_get_name(element->trigger, &trigger_name); assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + if (lttng_condition_event_rule_get_capture_descriptor_count( + lttng_trigger_get_const_condition(element->trigger), + &capture_count) != LTTNG_CONDITION_STATUS_OK) { + ERR("Failed to get capture count"); + ret = -1; + goto end; + } + + if (!notification->capture_buffer && capture_count != 0) { + ERR("Expected capture but capture buffer is null"); + ret = -1; + goto end; + } + evaluation = lttng_evaluation_event_rule_create( - trigger_name); + container_of(lttng_trigger_get_const_condition( + element->trigger), + struct lttng_condition_event_rule, + parent), + trigger_name, + notification->capture_buffer, + notification->capture_buf_size, false); + if (evaluation == NULL) { ERR("[notification-thread] Failed to create event rule hit evaluation while creating and enqueuing action executor job"); ret = -1; goto end_unlock; } - client_list = get_client_list_from_condition(state, lttng_trigger_get_const_condition(element->trigger)); executor_status = action_executor_enqueue(state->executor, @@ -4460,6 +4481,7 @@ next_client: end_unlock: notification_client_list_put(client_list); rcu_read_unlock(); +end: return ret; } diff --git a/src/common/conditions/event-rule.c b/src/common/conditions/event-rule.c index dcc31ef86..3f6b96015 100644 --- a/src/common/conditions/event-rule.c +++ b/src/common/conditions/event-rule.c @@ -10,12 +10,15 @@ #include #include #include +#include #include #include #include #include #include #include +#include +#include #include #include #include @@ -56,7 +59,7 @@ static bool lttng_condition_event_rule_validate( event_rule = container_of( condition, struct lttng_condition_event_rule, parent); if (!event_rule->rule) { - ERR("Invalid event rule condition: a rule must be set."); + ERR("Invalid event rule condition: a rule must be set"); goto end; } @@ -65,6 +68,52 @@ 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`. * @@ -178,7 +227,7 @@ int serialize_event_expr(const struct lttng_event_expr *expr, /* Serialize the parent array field expression. */ DBG("Serializing array field element event expression's " - "parent array field event expression."); + "parent array field event expression"); ret = serialize_event_expr(elem_expr->array_field_expr, payload); if (ret) { goto end; @@ -775,6 +824,7 @@ end: LTTNG_HIDDEN ssize_t lttng_evaluation_event_rule_create_from_payload( + const struct lttng_condition_event_rule *condition, struct lttng_payload_view *view, struct lttng_evaluation **_evaluation) { @@ -785,6 +835,8 @@ ssize_t lttng_evaluation_event_rule_create_from_payload( 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; @@ -802,7 +854,7 @@ ssize_t lttng_evaluation_event_rule_create_from_payload( /* Map the originating trigger's name. */ offset += sizeof(*header); { - struct lttng_payload_view current_view = + const struct lttng_payload_view current_view = lttng_payload_view_from_view(view, offset, header->trigger_name_length); @@ -822,13 +874,40 @@ ssize_t lttng_evaluation_event_rule_create_from_payload( } 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; + } - evaluation = lttng_evaluation_event_rule_create(trigger_name); + 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_event_rule_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; @@ -845,6 +924,7 @@ static int lttng_evaluation_event_rule_serialize( int ret = 0; struct lttng_evaluation_event_rule *hit; struct lttng_evaluation_event_rule_comm comm; + uint32_t capture_payload_size; hit = container_of( evaluation, struct lttng_evaluation_event_rule, parent); @@ -860,6 +940,68 @@ static int lttng_evaluation_event_rule_serialize( 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; } @@ -872,24 +1014,333 @@ static void lttng_evaluation_event_rule_destroy( hit = container_of( evaluation, struct lttng_evaluation_event_rule, 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_event_rule *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_event_rule_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_event_rule_create( - const char *trigger_name) + const struct lttng_condition_event_rule *condition, + const char *trigger_name, + const char *capture_payload, size_t capture_payload_size, + bool decode_capture_payload) { struct lttng_evaluation_event_rule *hit; struct lttng_evaluation *evaluation = NULL; hit = zmalloc(sizeof(struct lttng_evaluation_event_rule)); if (!hit) { - goto end; + goto error; } hit->name = strdup(trigger_name); if (!hit->name) { - goto end; + 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_EVENT_RULE_HIT; @@ -899,7 +1350,7 @@ struct lttng_evaluation *lttng_evaluation_event_rule_create( evaluation = &hit->parent; hit = NULL; -end: +error: if (hit) { lttng_evaluation_event_rule_destroy(&hit->parent); } @@ -907,6 +1358,32 @@ end: return evaluation; } +enum lttng_evaluation_status lttng_evaluation_event_rule_get_captured_values( + const struct lttng_evaluation *evaluation, + const struct lttng_event_field_value **field_val) +{ + struct lttng_evaluation_event_rule *hit; + enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK; + + if (!evaluation || !is_event_rule_evaluation(evaluation) || + !field_val) { + status = LTTNG_EVALUATION_STATUS_INVALID; + goto end; + } + + hit = container_of(evaluation, struct lttng_evaluation_event_rule, + 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_event_rule_get_trigger_name( const struct lttng_evaluation *evaluation, const char **name) { diff --git a/src/common/evaluation.c b/src/common/evaluation.c index d8a68a784..16c3ef39c 100644 --- a/src/common/evaluation.c +++ b/src/common/evaluation.c @@ -5,6 +5,7 @@ * */ +#include #include #include #include @@ -49,6 +50,7 @@ end: LTTNG_HIDDEN ssize_t lttng_evaluation_create_from_payload( + const struct lttng_condition *condition, struct lttng_payload_view *src_view, struct lttng_evaluation **evaluation) { @@ -116,7 +118,13 @@ ssize_t lttng_evaluation_create_from_payload( evaluation_size += ret; break; case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT: - ret = lttng_evaluation_event_rule_create_from_payload(&evaluation_view, evaluation); + assert(condition); + assert(condition->type == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT); + ret = lttng_evaluation_event_rule_create_from_payload( + container_of(condition, + const struct lttng_condition_event_rule, + parent), + &evaluation_view, evaluation); if (ret < 0) { goto end; } diff --git a/src/common/event-field-value.c b/src/common/event-field-value.c index d7687880f..b571f6246 100644 --- a/src/common/event-field-value.c +++ b/src/common/event-field-value.c @@ -517,21 +517,23 @@ end: return ret; } -const char *lttng_event_field_value_string_get_value( - const struct lttng_event_field_value *field_val) +enum lttng_event_field_value_status lttng_event_field_value_string_get_value( + const struct lttng_event_field_value *field_val, + const char **value) { - const char *ret; + enum lttng_event_field_value_status status; if (!field_val || field_val->type != LTTNG_EVENT_FIELD_VALUE_TYPE_STRING) { - ret = NULL; + status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID; goto end; } - ret = container_of(field_val, + *value = container_of(field_val, const struct lttng_event_field_value_string, parent)->val; + status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK; end: - return ret; + return status; } enum lttng_event_field_value_status lttng_event_field_value_array_get_length( diff --git a/src/common/notification.c b/src/common/notification.c index c347b3cea..a4e971bd5 100644 --- a/src/common/notification.c +++ b/src/common/notification.c @@ -122,7 +122,7 @@ ssize_t lttng_notification_create_from_payload( notification_size, -1); evaluation_size = lttng_evaluation_create_from_payload( - &evaluation_view, &evaluation); + condition, &evaluation_view, &evaluation); } if (evaluation_size < 0) {