+enum tracer_executed_action_state {
+ TRACER_EXECUTED_ACTION_STATE_REGISTER,
+ TRACER_EXECUTED_ACTION_STATE_UNREGISTER
+};
+
+static
+enum lttng_error_code sync_incr_value_action_ust(
+ struct ltt_session *session,
+ const struct lttng_condition *condition,
+ const char *map_name,
+ uint64_t tracer_token,
+ struct lttng_map_key *key,
+ enum tracer_executed_action_state state)
+{
+ enum lttng_error_code ret_code;
+ const struct lttng_event_rule *event_rule;
+ enum lttng_condition_status cond_status;
+ enum lttng_event_rule_status er_status;
+ struct ltt_ust_session *usess = session->ust_session;
+ const char *pattern;
+ struct ltt_ust_map *map;
+ char *filter_expression;
+ struct lttng_bytecode *filter;
+ struct lttng_event_exclusion *exclusion;
+ enum lttng_event_rule_generate_exclusions_status
+ generate_exclusion_status;
+
+ DBG("Syncing UST incr-value action for session '%s', map '%s'",
+ session->name, map_name);
+ if (!usess) {
+ DBG("No UST session");
+ ret_code = LTTNG_OK;
+ goto end;
+ }
+
+ assert(usess->domain_global.maps);
+
+ map = trace_ust_find_map_by_name(usess->domain_global.maps, map_name);
+ if (!map) {
+ DBG("UST map \"%s\" not found", map_name);
+ ret_code = LTTNG_OK;
+ goto end;
+ }
+
+ cond_status = lttng_condition_on_event_get_rule(condition, &event_rule);
+ if (cond_status != LTTNG_CONDITION_STATUS_OK) {
+ ERR("Error getting on-event condition event-rule");
+ ret_code = LTTNG_ERR_INVALID_MAP;
+ goto end;
+ }
+
+ er_status = lttng_event_rule_tracepoint_get_pattern(event_rule, &pattern);
+ if (er_status != LTTNG_EVENT_RULE_STATUS_OK) {
+ /* At this point, this is a fatal error. */
+ abort();
+ }
+
+ /*
+ * FIXME: frdeso, reuse the event notifier functions and approach to
+ * create the event.
+ */
+ filter_expression = (char *) lttng_event_rule_get_filter(event_rule);
+ filter = (struct lttng_bytecode *)lttng_event_rule_get_filter_bytecode(
+ event_rule);
+ generate_exclusion_status = lttng_event_rule_generate_exclusions(
+ event_rule, &exclusion);
+ if (generate_exclusion_status == LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_ERROR) {
+ ERR("Error generating the exclusion");
+ ret_code = LTTNG_ERR_EXCLUSION_INVAL;
+ goto end;
+ }
+
+ switch (state) {
+ case TRACER_EXECUTED_ACTION_STATE_REGISTER:
+ ret_code = map_event_ust_enable_tracepoint(usess,
+ map, tracer_token, (char *) pattern, key,
+ LTTNG_EVENT_TRACEPOINT, LTTNG_EVENT_LOGLEVEL_ALL,
+ 0, filter_expression, filter, exclusion, false);
+ if (ret_code == LTTNG_ERR_UST_EVENT_ENABLED) {
+ ret_code = LTTNG_OK;
+ } else if (ret_code != LTTNG_OK) {
+ ERR("Enabling UST map event");
+ goto end;
+ }
+ break;
+ case TRACER_EXECUTED_ACTION_STATE_UNREGISTER:
+ ret_code = map_event_ust_disable_tracepoint(usess,
+ map, tracer_token, (char *) pattern, key,
+ LTTNG_EVENT_TRACEPOINT, LTTNG_EVENT_LOGLEVEL_ALL,
+ 0, filter_expression, filter, exclusion, false);
+ if (ret_code == LTTNG_ERR_UST_EVENT_ENABLED) {
+ ret_code = LTTNG_OK;
+ } else if (ret_code != LTTNG_OK) {
+ ERR("Enabling UST map event");
+ goto end;
+ }
+ break;
+ default:
+ abort();
+ }
+
+ ret_code = LTTNG_OK;
+
+end:
+ return ret_code;
+}
+
+static
+enum lttng_error_code sync_incr_value_action_kernel(
+ struct ltt_session *session,
+ const struct lttng_credentials *creds,
+ const struct lttng_condition *condition,
+ const char *map_name,
+ uint64_t tracer_token,
+ struct lttng_map_key *key,
+ enum tracer_executed_action_state state)
+{
+ enum lttng_error_code ret_code;
+ const struct lttng_event_rule *event_rule;
+ enum lttng_condition_status cond_status;
+ struct ltt_kernel_map *kmap;
+ struct ltt_kernel_session *ksess = session->kernel_session;
+
+ DBG("Syncing kernel incr-value action for session '%s', map '%s'",
+ session->name, map_name);
+
+ if (!ksess) {
+ DBG("No kernel session");
+ ret_code = LTTNG_OK;
+ goto end;
+ }
+
+ kmap = trace_kernel_get_map_by_name(map_name, ksess);
+ if (!kmap) {
+ DBG("Kernel map \"%s\" not found", map_name);
+ ret_code = LTTNG_OK;
+ goto end;
+ }
+
+ cond_status = lttng_condition_on_event_get_rule(condition, &event_rule);
+ if (cond_status != LTTNG_CONDITION_STATUS_OK) {
+ ret_code = LTTNG_ERR_INVALID_MAP;
+ ERR("Error getting on-event condition event-rule");
+ goto end;
+ }
+
+ switch (state) {
+ case TRACER_EXECUTED_ACTION_STATE_REGISTER:
+ ret_code = map_event_kernel_enable_event(kmap, creds, tracer_token,
+ event_rule, key);
+ if(ret_code != LTTNG_OK) {
+ ERR("Error enabling event counter to the kernel tracer");
+ goto end;
+ }
+ break;
+ case TRACER_EXECUTED_ACTION_STATE_UNREGISTER:
+ ret_code = map_event_kernel_disable_event(kmap, tracer_token);
+ if(ret_code != LTTNG_OK) {
+ ERR("Error disabling event counter to the kernel tracer");
+ goto end;
+ }
+ break;
+ }
+
+end:
+ return ret_code;
+}
+
+static
+enum lttng_error_code sync_incr_value_action(
+ const struct lttng_credentials *creds,
+ const struct lttng_condition *condition,
+ const struct lttng_action *action,
+ enum tracer_executed_action_state state)
+{
+ enum lttng_error_code ret;
+ const char *session_name, *map_name;
+ enum lttng_action_status action_status;
+ enum lttng_condition_status cond_status;
+ const struct lttng_event_rule *event_rule;
+ struct ltt_session *session = NULL;
+ struct lttng_map_key *key;
+ uint64_t action_tracer_token;
+
+ action_status = lttng_action_incr_value_get_map_name(action,
+ &map_name);
+ if (action_status != LTTNG_ACTION_STATUS_OK) {
+ ERR("Map name not set for incr-value action");
+ ret = LTTNG_ERR_INVALID_MAP;
+ goto end;
+ }
+
+ action_status = lttng_action_incr_value_get_session_name(action,
+ &session_name);
+ if (action_status != LTTNG_ACTION_STATUS_OK) {
+ ERR("Session name not set for incr-value action");
+ ret = LTTNG_ERR_INVALID_MAP;
+ goto end;
+ }
+
+ action_status = lttng_action_incr_value_borrow_key_mutable(action, &key);
+ if (action_status != LTTNG_ACTION_STATUS_OK) {
+ ERR("Key not set for incr-value action");
+ ret = LTTNG_ERR_INVALID_MAP;
+ goto end;
+ }
+
+ /* Returns a refcounted reference */
+ session = session_find_by_name(session_name);
+ if(!session) {
+ DBG("Session not found for incr-value action: session-name=%s",
+ session_name);
+ ret = LTTNG_OK;
+ goto end;
+ }
+
+ cond_status = lttng_condition_on_event_get_rule(condition, &event_rule);
+ if (cond_status != LTTNG_CONDITION_STATUS_OK) {
+ ERR("Error getting on-event condition event-rule");
+ ret = LTTNG_ERR_INVALID_MAP;
+ session_put(session);
+ goto end;
+ }
+
+ action_tracer_token = lttng_action_incr_value_get_tracer_token(action);
+
+ switch (lttng_event_rule_get_domain_type(event_rule)) {
+ case LTTNG_DOMAIN_UST:
+ ret = sync_incr_value_action_ust(session, condition,
+ map_name, action_tracer_token, key, state);
+ if (ret == LTTNG_ERR_UST_EVENT_EXIST) {
+ DBG("Incr-value action already registered");
+ ret = LTTNG_OK;
+ }
+ break;
+ case LTTNG_DOMAIN_KERNEL:
+ ret = sync_incr_value_action_kernel(session, creds, condition,
+ map_name, action_tracer_token, key, state);
+ if (ret == LTTNG_ERR_KERN_EVENT_EXIST) {
+ DBG("Incr-value action already registered");
+ ret = LTTNG_OK;
+ }
+ break;
+ default:
+ abort();
+ }
+
+ goto end;
+end:
+ if (session) {
+ session_put(session);
+ }
+ return ret;
+}
+
+static
+enum lttng_error_code sync_one_tracer_executed_action(
+ const struct lttng_credentials *creds,
+ const struct lttng_condition *condition,
+ const struct lttng_action *action,
+ enum tracer_executed_action_state state)
+{
+ enum lttng_action_type action_type;
+ enum lttng_error_code ret;
+
+ action_type = lttng_action_get_type(action);
+ assert(action_type != LTTNG_ACTION_TYPE_GROUP);
+
+ switch (action_type) {
+ case LTTNG_ACTION_TYPE_INCREMENT_VALUE:
+ DBG("Action type \"%s\" is a tracer executed action.",
+ lttng_action_type_string(action_type));
+
+ ret = sync_incr_value_action(creds, condition, action, state);
+ if (ret != LTTNG_OK) {
+ ERR("Error syncing increment value action to the tracer");
+ }
+ break;
+ default:
+ DBG("Action type \"%s\" is not a tracer executed action.",
+ lttng_action_type_string(action_type));
+ ret = LTTNG_OK;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+static
+enum lttng_error_code sync_all_tracer_executed_actions(
+ const struct lttng_trigger *trigger,
+ const struct lttng_credentials *cmd_creds,
+ enum tracer_executed_action_state state)
+{
+ enum lttng_error_code ret;
+ unsigned int i, count;
+ enum lttng_action_status action_status;
+ enum lttng_action_type action_type;
+ const struct lttng_action *action;
+ const struct lttng_condition *condition;
+
+ condition = lttng_trigger_get_const_condition(trigger);
+ action = lttng_trigger_get_const_action(trigger);
+
+ action_type = lttng_action_get_type(action);
+
+ DBG("Iterating over all actions of trigger \"%s\" to sync any tracer executed actions",
+ trigger->name);
+
+ if (action_type != LTTNG_ACTION_TYPE_GROUP) {
+ ret = sync_one_tracer_executed_action(cmd_creds, condition, action,
+ state);
+ } else {
+ action_status = lttng_action_group_get_count(action, &count);
+ assert(action_status == LTTNG_ACTION_STATUS_OK);
+
+ for (i = 0; i < count; i++) {
+ const struct lttng_action *inner_action =
+ lttng_action_group_get_at_index(action, i);
+
+ ret = sync_one_tracer_executed_action(cmd_creds, condition,
+ inner_action, state);
+ if (ret != LTTNG_OK) {
+ ERR("Error syncing tracer executed action");
+ goto end;
+ }
+ }
+ }
+
+end:
+ return ret;
+}
+