+static
+void init_ust_trigger_from_event_rule(const struct lttng_event_rule *rule, struct lttng_ust_trigger *trigger)
+{
+ enum lttng_event_rule_status status;
+ enum lttng_loglevel_type loglevel_type;
+ enum lttng_ust_loglevel_type ust_loglevel_type = LTTNG_UST_LOGLEVEL_ALL;
+ int loglevel = -1;
+ const char *pattern;
+
+ /* For now only LTTNG_EVENT_RULE_TYPE_TRACEPOINT are supported */
+ assert(lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_TRACEPOINT);
+
+ memset(trigger, 0, sizeof(*trigger));
+
+ if (lttng_event_rule_is_agent(rule)) {
+ /*
+ * Special event for agents
+ * The actual meat of the event is in the filter that will be
+ * attached later on.
+ * Set the default values for the agent event.
+ */
+ pattern = event_get_default_agent_ust_name(lttng_event_rule_get_domain_type(rule));
+ loglevel = 0;
+ ust_loglevel_type = LTTNG_UST_LOGLEVEL_ALL;
+ } else {
+ status = lttng_event_rule_tracepoint_get_pattern(rule, &pattern);
+ if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+ /* At this point this is a fatal error */
+ assert(0);
+ }
+
+ status = lttng_event_rule_tracepoint_get_loglevel_type(
+ rule, &loglevel_type);
+ if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+ /* At this point this is a fatal error */
+ assert(0);
+ }
+
+ switch (loglevel_type) {
+ case LTTNG_EVENT_LOGLEVEL_ALL:
+ ust_loglevel_type = LTTNG_UST_LOGLEVEL_ALL;
+ break;
+ case LTTNG_EVENT_LOGLEVEL_RANGE:
+ ust_loglevel_type = LTTNG_UST_LOGLEVEL_RANGE;
+ break;
+ case LTTNG_EVENT_LOGLEVEL_SINGLE:
+ ust_loglevel_type = LTTNG_UST_LOGLEVEL_SINGLE;
+ break;
+ }
+
+ if (loglevel_type != LTTNG_EVENT_LOGLEVEL_ALL) {
+ status = lttng_event_rule_tracepoint_get_loglevel(
+ rule, &loglevel);
+ assert(status == LTTNG_EVENT_RULE_STATUS_OK);
+ }
+ }
+
+ trigger->instrumentation = LTTNG_UST_TRACEPOINT;
+ strncpy(trigger->name, pattern, LTTNG_UST_SYM_NAME_LEN - 1);
+ trigger->loglevel_type = ust_loglevel_type;
+ trigger->loglevel = loglevel;
+}
+
+/*
+ * Create the specified event rule token onto the UST tracer for a UST app.
+ */
+static
+int create_ust_token_event_rule(struct ust_app *app, struct ust_app_token_event_rule *ua_token)
+{
+ int ret = 0;
+ struct lttng_ust_trigger trigger;
+ struct lttng_condition *condition = NULL;
+ struct lttng_event_rule *event_rule = NULL;
+ unsigned int capture_bytecode_count = 0;
+
+ health_code_update();
+ assert(app->token_communication.handle);
+
+ condition = lttng_trigger_get_condition(ua_token->trigger);
+ assert(condition);
+ assert(lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT);
+
+ lttng_condition_event_rule_get_rule_no_const(condition, &event_rule);
+ assert(event_rule);
+ assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_TRACEPOINT);
+ /* Should we also test for UST at this point, or do we trust all the
+ * upper level? */
+
+ init_ust_trigger_from_event_rule(event_rule, &trigger);
+ trigger.id = ua_token->token;
+
+ /* Create UST trigger on tracer */
+ pthread_mutex_lock(&app->sock_lock);
+ ret = ustctl_create_trigger(app->sock, &trigger, app->token_communication.handle, &ua_token->obj);
+ pthread_mutex_unlock(&app->sock_lock);
+ if (ret < 0) {
+ if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
+ abort();
+ ERR("Error ustctl create trigger %s for app pid: %d with ret %d",
+ trigger.name, app->pid, ret);
+ } else {
+ /*
+ * This is normal behavior, an application can die during the
+ * creation process. Don't report an error so the execution can
+ * continue normally.
+ */
+ ret = 0;
+ DBG3("UST app create event failed. Application is dead.");
+ }
+ goto error;
+ }
+
+ ua_token->handle = ua_token->obj->handle;
+
+ DBG2("UST app event %s created successfully for pid:%d object: %p",
+ trigger.name, app->pid, ua_token->obj);
+
+ health_code_update();
+
+ /* Set filter if one is present. */
+ if (ua_token->filter) {
+ ret = set_ust_filter(app, ua_token->filter, ua_token->obj);
+ if (ret < 0) {
+ goto error;
+ }
+ }
+
+ /* Set exclusions for the event */
+ if (ua_token->exclusion) {
+ ret = set_ust_exclusions(app, ua_token->exclusion, ua_token->obj);
+ if (ret < 0) {
+ goto error;
+ }
+ }
+
+ /* Set the capture bytecode
+ * TODO: do we want to emulate what is done with exclusion and provide
+ * and object with a count of capture bytecode? instead of multiple
+ * call?
+ * */
+ capture_bytecode_count = lttng_trigger_get_capture_bytecode_count(ua_token->trigger);
+ for (unsigned int i = 0; i < capture_bytecode_count; i++) {
+ const struct lttng_bytecode *capture_bytecode = lttng_trigger_get_capture_bytecode_at_index(ua_token->trigger, i);
+ ret = set_ust_capture(app, capture_bytecode, i, ua_token->obj);
+ if (ret < 0) {
+ goto error;
+ }
+ }
+
+ /*
+ * We now need to explicitly enable the event, since it
+ * is disabled at creation.
+ */
+ ret = enable_ust_object(app, ua_token->obj);
+ if (ret < 0) {
+ /*
+ * If we hit an EPERM, something is wrong with our enable call. If
+ * we get an EEXIST, there is a problem on the tracer side since we
+ * just created it.
+ */
+ switch (ret) {
+ case -LTTNG_UST_ERR_PERM:
+ /* Code flow problem */
+ assert(0);
+ case -LTTNG_UST_ERR_EXIST:
+ /* It's OK for our use case. */
+ ret = 0;
+ break;
+ default:
+ break;
+ }
+ goto error;
+ }
+ ua_token->enabled = true;
+
+error:
+ health_code_update();
+ return ret;
+}
+