X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Fconditions%2Fevent-rule.c;h=b1219544a5a331fc1204c7f1778d36128987dc94;hp=8d3f1cd536c01e427513ff528d764063ea849715;hb=d602bd6a8ee25d5ca662dde4edb3db3cabf264e1;hpb=6fb7c69074b6884da56bb0758e92e1c7f7859859 diff --git a/src/common/conditions/event-rule.c b/src/common/conditions/event-rule.c index 8d3f1cd53..b1219544a 100644 --- a/src/common/conditions/event-rule.c +++ b/src/common/conditions/event-rule.c @@ -7,54 +7,59 @@ #include #include +#include #include #include +#include #include +#include #include #include #include #include +#include #include +#include #include #include #include -#define IS_EVENT_RULE_CONDITION(condition) \ +#define IS_ON_EVENT_CONDITION(condition) \ (lttng_condition_get_type(condition) == \ - LTTNG_CONDITION_TYPE_EVENT_RULE_HIT) + LTTNG_CONDITION_TYPE_ON_EVENT) -static bool is_event_rule_evaluation(const struct lttng_evaluation *evaluation) +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_EVENT_RULE_HIT; + return type == LTTNG_CONDITION_TYPE_ON_EVENT; } -static bool lttng_condition_event_rule_validate( +static bool lttng_condition_on_event_validate( const struct lttng_condition *condition); -static int lttng_condition_event_rule_serialize( +static int lttng_condition_on_event_serialize( const struct lttng_condition *condition, struct lttng_payload *payload); -static bool lttng_condition_event_rule_is_equal( +static bool lttng_condition_on_event_is_equal( const struct lttng_condition *_a, const struct lttng_condition *_b); -static void lttng_condition_event_rule_destroy( +static void lttng_condition_on_event_destroy( struct lttng_condition *condition); -static bool lttng_condition_event_rule_validate( +static bool lttng_condition_on_event_validate( const struct lttng_condition *condition) { bool valid = false; - struct lttng_condition_event_rule *event_rule; + struct lttng_condition_on_event *event_rule; if (!condition) { goto end; } event_rule = container_of( - condition, struct lttng_condition_event_rule, parent); + condition, struct lttng_condition_on_event, parent); if (!event_rule->rule) { - ERR("Invalid event rule condition: a rule must be set."); + ERR("Invalid on event condition: a rule must be set"); goto end; } @@ -63,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`. * @@ -176,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; @@ -194,22 +245,22 @@ end: static struct lttng_capture_descriptor * -lttng_condition_event_rule_get_internal_capture_descriptor_at_index( +lttng_condition_on_event_get_internal_capture_descriptor_at_index( const struct lttng_condition *condition, unsigned int index) { - const struct lttng_condition_event_rule *event_rule_cond = + const struct lttng_condition_on_event *on_event_cond = container_of(condition, - const struct lttng_condition_event_rule, + const struct lttng_condition_on_event, parent); struct lttng_capture_descriptor *desc = NULL; unsigned int count; enum lttng_condition_status status; - if (!condition || !IS_EVENT_RULE_CONDITION(condition)) { + if (!condition || !IS_ON_EVENT_CONDITION(condition)) { goto end; } - status = lttng_condition_event_rule_get_capture_descriptor_count( + status = lttng_condition_on_event_get_capture_descriptor_count( condition, &count); if (status != LTTNG_CONDITION_STATUS_OK) { goto end; @@ -220,44 +271,44 @@ lttng_condition_event_rule_get_internal_capture_descriptor_at_index( } desc = lttng_dynamic_pointer_array_get_pointer( - &event_rule_cond->capture_descriptors, index); + &on_event_cond->capture_descriptors, index); end: return desc; } -static int lttng_condition_event_rule_serialize( +static int lttng_condition_on_event_serialize( const struct lttng_condition *condition, struct lttng_payload *payload) { int ret; - struct lttng_condition_event_rule *event_rule; + 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_EVENT_RULE_CONDITION(condition)) { + if (!condition || !IS_ON_EVENT_CONDITION(condition)) { ret = -1; goto end; } - DBG("Serializing event rule condition"); - event_rule = container_of( - condition, struct lttng_condition_event_rule, parent); + DBG("Serializing on event condition"); + on_event_condition = container_of( + condition, struct lttng_condition_on_event, parent); - DBG("Serializing event rule condition's event rule"); - ret = lttng_event_rule_serialize(event_rule->rule, payload); + 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_event_rule_get_capture_descriptor_count( + 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 event rule condition's capture descriptor count: %" PRIu32, + 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)); @@ -267,10 +318,10 @@ static int lttng_condition_event_rule_serialize( for (i = 0; i < capture_descr_count; i++) { const struct lttng_capture_descriptor *desc = - lttng_condition_event_rule_get_internal_capture_descriptor_at_index( + lttng_condition_on_event_get_internal_capture_descriptor_at_index( condition, i); - DBG("Serializing event rule condition's capture descriptor %" PRIu32, + DBG("Serializing on event condition's capture descriptor %" PRIu32, i); ret = serialize_event_expr(desc->event_expression, payload); if (ret) { @@ -293,13 +344,13 @@ bool capture_descriptors_are_equal( size_t i; enum lttng_condition_status status; - status = lttng_condition_event_rule_get_capture_descriptor_count( + 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_event_rule_get_capture_descriptor_count( + status = lttng_condition_on_event_get_capture_descriptor_count( condition_b, &capture_descr_count_b); if (status != LTTNG_CONDITION_STATUS_OK) { goto not_equal; @@ -311,11 +362,11 @@ bool capture_descriptors_are_equal( for (i = 0; i < capture_descr_count_a; i++) { const struct lttng_event_expr *expr_a = - lttng_condition_event_rule_get_capture_descriptor_at_index( + lttng_condition_on_event_get_capture_descriptor_at_index( condition_a, i); const struct lttng_event_expr *expr_b = - lttng_condition_event_rule_get_capture_descriptor_at_index( + lttng_condition_on_event_get_capture_descriptor_at_index( condition_b, i); @@ -333,15 +384,15 @@ end: return is_equal; } -static bool lttng_condition_event_rule_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_event_rule *a, *b; + struct lttng_condition_on_event *a, *b; - a = container_of(_a, struct lttng_condition_event_rule, parent); - b = container_of(_b, struct lttng_condition_event_rule, parent); + 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)) { @@ -360,17 +411,17 @@ end: return is_equal; } -static void lttng_condition_event_rule_destroy( +static void lttng_condition_on_event_destroy( struct lttng_condition *condition) { - struct lttng_condition_event_rule *event_rule; + struct lttng_condition_on_event *on_event_condition; - event_rule = container_of( - condition, struct lttng_condition_event_rule, parent); + on_event_condition = container_of( + condition, struct lttng_condition_on_event, parent); - lttng_event_rule_put(event_rule->rule); - lttng_dynamic_pointer_array_reset(&event_rule->capture_descriptors); - free(event_rule); + lttng_event_rule_put(on_event_condition->rule); + lttng_dynamic_pointer_array_reset(&on_event_condition->capture_descriptors); + free(on_event_condition); } static @@ -384,27 +435,27 @@ void destroy_capture_descriptor(void *ptr) free(desc); } -struct lttng_condition *lttng_condition_event_rule_create( +struct lttng_condition *lttng_condition_on_event_create( struct lttng_event_rule *rule) { struct lttng_condition *parent = NULL; - struct lttng_condition_event_rule *condition = NULL; + struct lttng_condition_on_event *condition = NULL; if (!rule) { goto end; } - condition = zmalloc(sizeof(struct lttng_condition_event_rule)); + condition = zmalloc(sizeof(struct lttng_condition_on_event)); if (!condition) { return NULL; } lttng_condition_init(&condition->parent, - LTTNG_CONDITION_TYPE_EVENT_RULE_HIT); - condition->parent.validate = lttng_condition_event_rule_validate, - condition->parent.serialize = lttng_condition_event_rule_serialize, - condition->parent.equal = lttng_condition_event_rule_is_equal, - condition->parent.destroy = lttng_condition_event_rule_destroy, + 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; @@ -574,7 +625,7 @@ end: } LTTNG_HIDDEN -ssize_t lttng_condition_event_rule_create_from_payload( +ssize_t lttng_condition_on_event_create_from_payload( struct lttng_payload_view *view, struct lttng_condition **_condition) { @@ -602,13 +653,12 @@ ssize_t lttng_condition_event_rule_create_from_payload( goto error; } - /* Create condition (no capture descriptors yet) at this point. */ - condition = lttng_condition_event_rule_create(event_rule); + /* 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; @@ -628,7 +678,7 @@ ssize_t lttng_condition_event_rule_create_from_payload( } /* Move ownership of `expr` to `condition`. */ - status = lttng_condition_event_rule_append_capture_descriptor( + status = lttng_condition_on_event_append_capture_descriptor( condition, expr); if (status != LTTNG_CONDITION_STATUS_OK) { /* `expr` not moved: destroy it. */ @@ -652,20 +702,20 @@ end: } LTTNG_HIDDEN -enum lttng_condition_status lttng_condition_event_rule_borrow_rule_mutable( +enum lttng_condition_status lttng_condition_on_event_borrow_rule_mutable( const struct lttng_condition *condition, struct lttng_event_rule **rule) { - struct lttng_condition_event_rule *event_rule; + struct lttng_condition_on_event *event_rule; enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; - if (!condition || !IS_EVENT_RULE_CONDITION(condition) || !rule) { + if (!condition || !IS_ON_EVENT_CONDITION(condition) || !rule) { status = LTTNG_CONDITION_STATUS_INVALID; goto end; } event_rule = container_of( - condition, struct lttng_condition_event_rule, parent); + condition, struct lttng_condition_on_event, parent); if (!event_rule->rule) { status = LTTNG_CONDITION_STATUS_UNSET; goto end; @@ -676,13 +726,13 @@ end: return status; } -enum lttng_condition_status lttng_condition_event_rule_get_rule( +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_event_rule_borrow_rule_mutable( + lttng_condition_on_event_borrow_rule_mutable( condition, &mutable_rule); *rule = mutable_rule; @@ -690,24 +740,48 @@ enum lttng_condition_status lttng_condition_event_rule_get_rule( } enum lttng_condition_status -lttng_condition_event_rule_append_capture_descriptor( +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_event_rule *event_rule_cond = + struct lttng_condition_on_event *event_rule_cond = container_of(condition, - struct lttng_condition_event_rule, parent); + 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_EVENT_RULE_CONDITION(condition) || !expr || + 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; @@ -732,35 +806,35 @@ end: } enum lttng_condition_status -lttng_condition_event_rule_get_capture_descriptor_count( +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_event_rule *event_rule_cond = + const struct lttng_condition_on_event *on_event_condition = container_of(condition, - const struct lttng_condition_event_rule, + const struct lttng_condition_on_event, parent); - if (!condition || !IS_EVENT_RULE_CONDITION(condition) || !count) { + if (!condition || !IS_ON_EVENT_CONDITION(condition) || !count) { status = LTTNG_CONDITION_STATUS_INVALID; goto end; } *count = lttng_dynamic_pointer_array_get_count( - &event_rule_cond->capture_descriptors); + &on_event_condition->capture_descriptors); end: return status; } const struct lttng_event_expr * -lttng_condition_event_rule_get_capture_descriptor_at_index( +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_event_rule_get_internal_capture_descriptor_at_index( + desc = lttng_condition_on_event_get_internal_capture_descriptor_at_index( condition, index); if (desc == NULL) { goto end; @@ -772,17 +846,20 @@ end: } LTTNG_HIDDEN -ssize_t lttng_evaluation_event_rule_create_from_payload( +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_event_rule_comm *header; + 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; @@ -800,7 +877,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); @@ -820,13 +897,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_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; @@ -836,16 +940,17 @@ error: return ret; } -static int lttng_evaluation_event_rule_serialize( +static int lttng_evaluation_on_event_serialize( const struct lttng_evaluation *evaluation, struct lttng_payload *payload) { int ret = 0; - struct lttng_evaluation_event_rule *hit; - struct lttng_evaluation_event_rule_comm comm; + 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_event_rule, parent); + evaluation, struct lttng_evaluation_on_event, parent); assert(hit->name); comm.trigger_name_length = strlen(hit->name) + 1; @@ -858,67 +963,551 @@ 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; } -static void lttng_evaluation_event_rule_destroy( +static void lttng_evaluation_on_event_destroy( struct lttng_evaluation *evaluation) { - struct lttng_evaluation_event_rule *hit; + struct lttng_evaluation_on_event *hit; hit = container_of( - evaluation, struct lttng_evaluation_event_rule, parent); + 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_event_rule_create( - const char *trigger_name) +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_event_rule *hit; + struct lttng_evaluation_on_event *hit; struct lttng_evaluation *evaluation = NULL; - hit = zmalloc(sizeof(struct lttng_evaluation_event_rule)); + hit = zmalloc(sizeof(struct lttng_evaluation_on_event)); if (!hit) { - goto end; + goto error; } hit->name = strdup(trigger_name); if (!hit->name) { - goto end; + goto error; } - hit->parent.type = LTTNG_CONDITION_TYPE_EVENT_RULE_HIT; - hit->parent.serialize = lttng_evaluation_event_rule_serialize; - hit->parent.destroy = lttng_evaluation_event_rule_destroy; + 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; -end: +error: if (hit) { - lttng_evaluation_event_rule_destroy(&hit->parent); + lttng_evaluation_on_event_destroy(&hit->parent); } return evaluation; } -enum lttng_evaluation_status lttng_evaluation_event_rule_get_trigger_name( +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_event_rule *hit; + struct lttng_evaluation_on_event *hit; enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK; - if (!evaluation || !is_event_rule_evaluation(evaluation) || !name) { + if (!evaluation || !is_on_event_evaluation(evaluation) || !name) { status = LTTNG_EVALUATION_STATUS_INVALID; goto end; } hit = container_of( - evaluation, struct lttng_evaluation_event_rule, parent); + 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; +}