Introduce trigger hash table with tracer token as key
[lttng-tools.git] / src / bin / lttng-sessiond / notification-thread-events.c
index 9bf146d3773ce6c4cb5a9ee894fbad6cdb481630..81fba4e6912253c7daf8b825594bf3106cc93361 100644 (file)
@@ -281,6 +281,17 @@ int match_trigger(struct cds_lfht_node *node, const void *key)
        return !!lttng_trigger_is_equal(trigger_key, trigger_ht_element->trigger);
 }
 
+static
+int match_trigger_token(struct cds_lfht_node *node, const void *key)
+{
+       const uint64_t *_key = key;
+       struct notification_trigger_tokens_ht_element *element;
+
+       element = caa_container_of(node,
+                       struct notification_trigger_tokens_ht_element, node);
+       return *_key == element->token;
+}
+
 static
 int match_client_list_condition(struct cds_lfht_node *node, const void *key)
 {
@@ -2322,6 +2333,7 @@ int handle_notification_thread_command_register_trigger(
        struct notification_client_list *client_list = NULL;
        struct lttng_trigger_ht_element *trigger_ht_element = NULL;
        struct notification_client_list_element *client_list_element;
+       struct notification_trigger_tokens_ht_element *trigger_tokens_ht_element = NULL;
        struct cds_lfht_node *node;
        struct cds_lfht_iter iter;
        const char* trigger_name;
@@ -2400,10 +2412,47 @@ int handle_notification_thread_command_register_trigger(
                goto error_free_ht_element;
        }
 
+       if (lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT) {
+               trigger_tokens_ht_element = zmalloc(sizeof(*trigger_tokens_ht_element));
+               if (!trigger_tokens_ht_element) {
+                       /* Fatal error. */
+                       ret = -1;
+                       cds_lfht_del(state->triggers_ht,
+                                       &trigger_ht_element->node);
+                       cds_lfht_del(state->triggers_by_name_uid_ht,
+                                       &trigger_ht_element->node_by_name_uid);
+                       goto error_free_ht_element;
+               }
+
+               /* Add trigger token to the trigger_tokens_ht. */
+               cds_lfht_node_init(&trigger_tokens_ht_element->node);
+               trigger_tokens_ht_element->token =
+                               LTTNG_OPTIONAL_GET(trigger->tracer_token);
+               trigger_tokens_ht_element->trigger = trigger;
+
+               node = cds_lfht_add_unique(state->trigger_tokens_ht,
+                               hash_key_u64(&trigger_tokens_ht_element->token,
+                                               lttng_ht_seed),
+                               match_trigger_token,
+                               &trigger_tokens_ht_element->token,
+                               &trigger_tokens_ht_element->node);
+               if (node != &trigger_tokens_ht_element->node) {
+                       /* Internal corruption, fatal error. */
+                       ret = -1;
+                       *cmd_result = LTTNG_ERR_TRIGGER_EXISTS;
+                       cds_lfht_del(state->triggers_ht,
+                                       &trigger_ht_element->node);
+                       cds_lfht_del(state->triggers_by_name_uid_ht,
+                                       &trigger_ht_element->node_by_name_uid);
+                       goto error_free_ht_element;
+               }
+       }
+
        /*
         * Ownership of the trigger and of its wrapper was transfered to
-        * the triggers_ht.
+        * the triggers_ht. Same for token ht element if necessary.
         */
+       trigger_tokens_ht_element = NULL;
        trigger_ht_element = NULL;
        free_trigger = false;
 
@@ -2585,6 +2634,7 @@ error_free_ht_element:
                                free_lttng_trigger_ht_element_rcu);
        }
 
+       free(trigger_tokens_ht_element);
 error:
        if (free_trigger) {
                lttng_trigger_destroy(trigger);
@@ -2600,6 +2650,13 @@ void free_lttng_trigger_ht_element_rcu(struct rcu_head *node)
                        rcu_node));
 }
 
+static
+void free_notification_trigger_tokens_ht_element_rcu(struct rcu_head *node)
+{
+       free(caa_container_of(node, struct notification_trigger_tokens_ht_element,
+                       rcu_node));
+}
+
 static
 int handle_notification_thread_command_unregister_trigger(
                struct notification_thread_state *state,
@@ -2648,6 +2705,28 @@ int handle_notification_thread_command_unregister_trigger(
                }
        }
 
+       if (lttng_condition_get_type(condition) ==
+                       LTTNG_CONDITION_TYPE_EVENT_RULE_HIT) {
+               struct notification_trigger_tokens_ht_element
+                               *trigger_tokens_ht_element;
+
+               cds_lfht_for_each_entry (state->trigger_tokens_ht, &iter,
+                               trigger_tokens_ht_element, node) {
+                       if (!lttng_trigger_is_equal(trigger,
+                                           trigger_tokens_ht_element->trigger)) {
+                               continue;
+                       }
+
+                       DBG("[notification-thread] Removed trigger from tokens_ht");
+                       cds_lfht_del(state->trigger_tokens_ht,
+                                       &trigger_tokens_ht_element->node);
+                       call_rcu(&trigger_tokens_ht_element->rcu_node,
+                                       free_notification_trigger_tokens_ht_element_rcu);
+
+                       break;
+               }
+       }
+
        if (is_trigger_action_notify(trigger)) {
                /*
                 * Remove and release the client list from
This page took 0.025385 seconds and 4 git commands to generate.