X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Ftrigger.c;h=ec96fc80b7d804249c8c4f1f395d4a693080fd1e;hp=e69e72e076267be0b7b6290b9032cc11b941caa1;hb=9c374932629a1c25927dad13fce02ba1c4892cf7;hpb=6808ef55e595f2cb28e8c0dafe5dff3e0faaa742 diff --git a/src/common/trigger.c b/src/common/trigger.c index e69e72e07..ec96fc80b 100644 --- a/src/common/trigger.c +++ b/src/common/trigger.c @@ -5,20 +5,27 @@ * */ -#include -#include -#include +#include #include -#include -#include -#include #include +#include #include -#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include LTTNG_HIDDEN -bool lttng_trigger_validate(struct lttng_trigger *trigger) +bool lttng_trigger_validate(const struct lttng_trigger *trigger) { bool valid; @@ -61,6 +68,9 @@ struct lttng_trigger *lttng_trigger_create( lttng_action_get(action); trigger->action = action; + pthread_mutex_init(&trigger->lock, NULL); + trigger->registered = false; + end: return trigger; } @@ -76,14 +86,12 @@ struct lttng_condition *lttng_trigger_get_condition( return trigger ? trigger->condition : NULL; } -LTTNG_HIDDEN const struct lttng_condition *lttng_trigger_get_const_condition( const struct lttng_trigger *trigger) { - return trigger->condition; + return trigger ? trigger->condition : NULL; } - /* * Note: the lack of reference counting 'get' on the action object is normal. * This API was exposed as such in 2.11. The client is not expected to call @@ -95,11 +103,10 @@ struct lttng_action *lttng_trigger_get_action( return trigger ? trigger->action : NULL; } -LTTNG_HIDDEN const struct lttng_action *lttng_trigger_get_const_action( const struct lttng_trigger *trigger) { - return trigger->action; + return trigger ? trigger->action : NULL; } static void trigger_destroy_ref(struct urcu_ref *ref) @@ -117,6 +124,8 @@ static void trigger_destroy_ref(struct urcu_ref *ref) lttng_action_put(action); lttng_condition_put(condition); + pthread_mutex_destroy(&trigger->lock); + free(trigger->name); free(trigger); } @@ -264,7 +273,7 @@ error: lttng_condition_put(condition); lttng_action_put(action); end: - if (ret == 0) { + if (ret >= 0) { *_trigger = trigger; } else { lttng_trigger_put(trigger); @@ -337,9 +346,10 @@ LTTNG_HIDDEN bool lttng_trigger_is_equal( const struct lttng_trigger *a, const struct lttng_trigger *b) { - /* - * Name is not taken into account since it is cosmetic only. - */ + if (strcmp(a->name, b->name) != 0) { + return false; + } + if (!lttng_condition_is_equal(a->condition, b->condition)) { return false; } @@ -738,3 +748,197 @@ enum lttng_trigger_status lttng_trigger_get_owner_uid( end: return ret; } + +LTTNG_HIDDEN +enum lttng_domain_type lttng_trigger_get_underlying_domain_type_restriction( + const struct lttng_trigger *trigger) +{ + enum lttng_domain_type type = LTTNG_DOMAIN_NONE; + const struct lttng_event_rule *event_rule; + enum lttng_condition_status c_status; + enum lttng_condition_type c_type; + + assert(trigger); + assert(trigger->condition); + + c_type = lttng_condition_get_type(trigger->condition); + assert (c_type != LTTNG_CONDITION_TYPE_UNKNOWN); + + switch (c_type) { + case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE: + case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING: + case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED: + /* Apply to any domain. */ + type = LTTNG_DOMAIN_NONE; + break; + case LTTNG_CONDITION_TYPE_ON_EVENT: + /* Return the domain of the event rule. */ + c_status = lttng_condition_on_event_get_rule( + trigger->condition, &event_rule); + assert(c_status == LTTNG_CONDITION_STATUS_OK); + type = lttng_event_rule_get_domain_type(event_rule); + break; + case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH: + case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW: + /* Return the domain of the channel being monitored. */ + c_status = lttng_condition_buffer_usage_get_domain_type( + trigger->condition, &type); + assert(c_status == LTTNG_CONDITION_STATUS_OK); + break; + default: + abort(); + } + + return type; +} + +/* + * Generate bytecode related to the trigger. + * On success LTTNG_OK. On error, returns lttng_error code. + */ +LTTNG_HIDDEN +enum lttng_error_code lttng_trigger_generate_bytecode( + struct lttng_trigger *trigger, + const struct lttng_credentials *creds) +{ + enum lttng_error_code ret; + struct lttng_condition *condition = NULL; + + condition = lttng_trigger_get_condition(trigger); + if (!condition) { + ret = LTTNG_ERR_INVALID_TRIGGER; + goto end; + } + + switch (lttng_condition_get_type(condition)) { + case LTTNG_CONDITION_TYPE_ON_EVENT: + { + struct lttng_event_rule *event_rule; + const enum lttng_condition_status condition_status = + lttng_condition_on_event_borrow_rule_mutable( + condition, &event_rule); + + assert(condition_status == LTTNG_CONDITION_STATUS_OK); + + /* Generate the filter bytecode. */ + ret = lttng_event_rule_generate_filter_bytecode( + event_rule, creds); + if (ret != LTTNG_OK) { + goto end; + } + + /* Generate the capture bytecode. */ + ret = lttng_condition_on_event_generate_capture_descriptor_bytecode( + condition); + if (ret != LTTNG_OK) { + goto end; + } + + ret = LTTNG_OK; + break; + } + default: + ret = LTTNG_OK; + break; + } +end: + return ret; +} + +LTTNG_HIDDEN +struct lttng_trigger *lttng_trigger_copy(const struct lttng_trigger *trigger) +{ + int ret; + struct lttng_payload copy_buffer; + struct lttng_trigger *copy = NULL; + + lttng_payload_init(©_buffer); + + ret = lttng_trigger_serialize(trigger, ©_buffer); + if (ret < 0) { + goto end; + } + + { + struct lttng_payload_view view = + lttng_payload_view_from_payload( + ©_buffer, 0, -1); + ret = lttng_trigger_create_from_payload( + &view, ©); + if (ret < 0) { + copy = NULL; + goto end; + } + } + +end: + lttng_payload_reset(©_buffer); + return copy; +} + +LTTNG_HIDDEN +bool lttng_trigger_needs_tracer_notifier(const struct lttng_trigger *trigger) +{ + bool needs_tracer_notifier = false; + const struct lttng_condition *condition = + lttng_trigger_get_const_condition(trigger); + + switch (lttng_condition_get_type(condition)) { + case LTTNG_CONDITION_TYPE_ON_EVENT: + needs_tracer_notifier = true; + goto end; + case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE: + case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH: + case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW: + case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING: + case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED: + goto end; + case LTTNG_CONDITION_TYPE_UNKNOWN: + default: + abort(); + } +end: + return needs_tracer_notifier; +} + +LTTNG_HIDDEN +void lttng_trigger_set_as_registered(struct lttng_trigger *trigger) +{ + pthread_mutex_lock(&trigger->lock); + trigger->registered = true; + pthread_mutex_unlock(&trigger->lock); +} + +LTTNG_HIDDEN +void lttng_trigger_set_as_unregistered(struct lttng_trigger *trigger) +{ + pthread_mutex_lock(&trigger->lock); + trigger->registered = false; + pthread_mutex_unlock(&trigger->lock); +} + +/* + * The trigger must be locked before calling lttng_trigger_registered. + * The lock is necessary since a trigger can be unregistered at anytime. + * Manipulations requiring that the trigger be registered must always acquire + * the trigger lock for the duration of the manipulation using + * `lttng_trigger_lock` and `lttng_trigger_unlock`. + */ +LTTNG_HIDDEN +bool lttng_trigger_is_registered(struct lttng_trigger *trigger) +{ + ASSERT_LOCKED(trigger->lock); + return trigger->registered; +} + +LTTNG_HIDDEN +void lttng_trigger_lock(struct lttng_trigger *trigger) +{ + pthread_mutex_lock(&trigger->lock); +} + +LTTNG_HIDDEN +void lttng_trigger_unlock(struct lttng_trigger *trigger) +{ + pthread_mutex_unlock(&trigger->lock); +}