X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fagent.c;h=77846b4f2251e7891d4f32b5ad196da4f4535f53;hp=1926b0820fc808f4076e12b8110a4ce5fe34cbae;hb=a0377dfefe40662ba7d68617bce6ff467114136c;hpb=ab5be9fa2eb5ba9600a82cd18fd3cfcbac69169a diff --git a/src/bin/lttng-sessiond/agent.c b/src/bin/lttng-sessiond/agent.c index 1926b0820..77846b4f2 100644 --- a/src/bin/lttng-sessiond/agent.c +++ b/src/bin/lttng-sessiond/agent.c @@ -7,10 +7,19 @@ */ #define _LGPL_SOURCE -#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include @@ -23,6 +32,12 @@ #define AGENT_RET_CODE_INDEX(code) (code - AGENT_RET_CODE_SUCCESS) +typedef enum lttng_event_rule_status (*event_rule_logging_get_name_pattern)( + const struct lttng_event_rule *rule, const char **pattern); +typedef enum lttng_event_rule_status (*event_rule_logging_get_log_level_rule)( + const struct lttng_event_rule *rule, + const struct lttng_log_level_rule **log_level_rule); + /* * Agent application context representation. */ @@ -81,8 +96,8 @@ static int ht_match_event_by_name(struct cds_lfht_node *node, struct agent_event *event; const struct agent_ht_key *key; - assert(node); - assert(_key); + LTTNG_ASSERT(node); + LTTNG_ASSERT(_key); event = caa_container_of(node, struct agent_event, node.node); key = _key; @@ -101,7 +116,8 @@ no_match: } /* - * Match function for the events hash table lookup by name and loglevel. + * Match function for the events hash table lookup by name, log level and + * filter expression. */ static int ht_match_event(struct cds_lfht_node *node, const void *_key) @@ -110,8 +126,8 @@ static int ht_match_event(struct cds_lfht_node *node, const struct agent_ht_key *key; int ll_match; - assert(node); - assert(_key); + LTTNG_ASSERT(node); + LTTNG_ASSERT(_key); event = caa_container_of(node, struct agent_event, node.node); key = _key; @@ -160,9 +176,9 @@ static void add_unique_agent_event(struct lttng_ht *ht, struct cds_lfht_node *node_ptr; struct agent_ht_key key; - assert(ht); - assert(ht->ht); - assert(event); + LTTNG_ASSERT(ht); + LTTNG_ASSERT(ht->ht); + LTTNG_ASSERT(event); key.name = event->name; key.loglevel_value = event->loglevel_value; @@ -172,7 +188,7 @@ static void add_unique_agent_event(struct lttng_ht *ht, node_ptr = cds_lfht_add_unique(ht->ht, ht->hash_fct(event->node.key, lttng_ht_seed), ht_match_event, &key, &event->node.node); - assert(node_ptr == &event->node.node); + LTTNG_ASSERT(node_ptr == &event->node.node); } /* @@ -214,7 +230,7 @@ static int send_header(struct lttcomm_sock *sock, uint64_t data_size, ssize_t size; struct lttcomm_agent_hdr msg; - assert(sock); + LTTNG_ASSERT(sock); memset(&msg, 0, sizeof(msg)); msg.data_size = htobe64(data_size); @@ -244,8 +260,8 @@ static int send_payload(struct lttcomm_sock *sock, const void *data, int ret; ssize_t len; - assert(sock); - assert(data); + LTTNG_ASSERT(sock); + LTTNG_ASSERT(data); len = sock->ops->sendmsg(sock, data, size, 0); if (len < size) { @@ -269,8 +285,8 @@ static int recv_reply(struct lttcomm_sock *sock, void *buf, size_t size) int ret; ssize_t len; - assert(sock); - assert(buf); + LTTNG_ASSERT(sock); + LTTNG_ASSERT(buf); len = sock->ops->recvmsg(sock, buf, size, 0); if (len < size) { @@ -300,9 +316,9 @@ static ssize_t list_events(struct agent_app *app, struct lttng_event **events) struct lttcomm_agent_list_reply *reply = NULL; struct lttcomm_agent_list_reply_hdr reply_hdr; - assert(app); - assert(app->sock); - assert(events); + LTTNG_ASSERT(app); + LTTNG_ASSERT(app->sock); + LTTNG_ASSERT(events); DBG2("Agent listing events for app pid: %d and socket %d", app->pid, app->sock->fd); @@ -380,7 +396,7 @@ error: * * Return LTTNG_OK on success or else a LTTNG_ERR* code. */ -static int enable_event(struct agent_app *app, struct agent_event *event) +static int enable_event(const struct agent_app *app, struct agent_event *event) { int ret; char *bytes_to_send; @@ -390,9 +406,9 @@ static int enable_event(struct agent_app *app, struct agent_event *event) struct lttcomm_agent_enable_event msg; struct lttcomm_agent_generic_reply reply; - assert(app); - assert(app->sock); - assert(event); + LTTNG_ASSERT(app); + LTTNG_ASSERT(app->sock); + LTTNG_ASSERT(event); DBG2("Agent enabling event %s for app pid: %d and socket %d", event->name, app->pid, app->sock->fd); @@ -495,18 +511,18 @@ end: * * Return LTTNG_OK on success or else a LTTNG_ERR* code. */ -static int app_context_op(struct agent_app *app, - struct agent_app_ctx *ctx, enum lttcomm_agent_command cmd) +static int app_context_op(const struct agent_app *app, + const struct agent_app_ctx *ctx, enum lttcomm_agent_command cmd) { int ret; uint32_t reply_ret_code; struct lttcomm_agent_generic_reply reply; size_t app_ctx_provider_name_len, app_ctx_name_len, data_size; - assert(app); - assert(app->sock); - assert(ctx); - assert(cmd == AGENT_CMD_APP_CTX_ENABLE || + LTTNG_ASSERT(app); + LTTNG_ASSERT(app->sock); + LTTNG_ASSERT(ctx); + LTTNG_ASSERT(cmd == AGENT_CMD_APP_CTX_ENABLE || cmd == AGENT_CMD_APP_CTX_DISABLE); DBG2("Agent %s application %s:%s for app pid: %d and socket %d", @@ -586,9 +602,9 @@ static int disable_event(struct agent_app *app, struct agent_event *event) struct lttcomm_agent_disable_event msg; struct lttcomm_agent_generic_reply reply; - assert(app); - assert(app->sock); - assert(event); + LTTNG_ASSERT(app); + LTTNG_ASSERT(app->sock); + LTTNG_ASSERT(event); DBG2("Agent disabling event %s for app pid: %d and socket %d", event->name, app->pid, app->sock->fd); @@ -643,8 +659,8 @@ error: */ int agent_send_registration_done(struct agent_app *app) { - assert(app); - assert(app->sock); + LTTNG_ASSERT(app); + LTTNG_ASSERT(app->sock); DBG("Agent sending registration done to app socket %d", app->sock->fd); @@ -664,11 +680,11 @@ int agent_enable_event(struct agent_event *event, struct agent_app *app; struct lttng_ht_iter iter; - assert(event); + LTTNG_ASSERT(event); rcu_read_lock(); - cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, app, + cds_lfht_for_each_entry(the_agent_apps_ht_by_sock->ht, &iter.iter, app, node.node) { if (app->domain != domain) { continue; @@ -681,7 +697,7 @@ int agent_enable_event(struct agent_event *event, } } - event->enabled = 1; + event->enabled_count++; ret = LTTNG_OK; error: @@ -706,7 +722,7 @@ struct agent_app_ctx *create_app_ctx(const struct lttng_event_context *ctx) goto end; } - assert(ctx->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT); + LTTNG_ASSERT(ctx->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT); agent_ctx = zmalloc(sizeof(*ctx)); if (!agent_ctx) { goto end; @@ -735,7 +751,7 @@ int agent_enable_context(const struct lttng_event_context *ctx, struct agent_app *app; struct lttng_ht_iter iter; - assert(ctx); + LTTNG_ASSERT(ctx); if (ctx->ctx != LTTNG_EVENT_CONTEXT_APP_CONTEXT) { ret = LTTNG_ERR_INVALID; goto error; @@ -743,7 +759,7 @@ int agent_enable_context(const struct lttng_event_context *ctx, rcu_read_lock(); - cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, app, + cds_lfht_for_each_entry(the_agent_apps_ht_by_sock->ht, &iter.iter, app, node.node) { struct agent_app_ctx *agent_ctx; @@ -786,14 +802,24 @@ int agent_disable_event(struct agent_event *event, struct agent_app *app; struct lttng_ht_iter iter; - assert(event); - if (!event->enabled) { + LTTNG_ASSERT(event); + if (!AGENT_EVENT_IS_ENABLED(event)) { + goto end; + } + + if (--event->enabled_count != 0) { + /* + * Agent event still enabled. Disable the agent event only when + * all "users" have disabled it (event notifiers, event rules, + * etc.). + */ + ret = LTTNG_OK; goto end; } rcu_read_lock(); - cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, app, + cds_lfht_for_each_entry(the_agent_apps_ht_by_sock->ht, &iter.iter, app, node.node) { if (app->domain != domain) { continue; @@ -806,7 +832,8 @@ int agent_disable_event(struct agent_event *event, } } - event->enabled = 0; + /* event->enabled_count is now 0. */ + LTTNG_ASSERT(!AGENT_EVENT_IS_ENABLED(event)); error: rcu_read_unlock(); @@ -827,12 +854,12 @@ static int disable_context(struct agent_app_ctx *ctx, struct agent_app *app; struct lttng_ht_iter iter; - assert(ctx); + LTTNG_ASSERT(ctx); rcu_read_lock(); DBG2("Disabling agent application context %s:%s", ctx->provider_name, ctx->ctx_name); - cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, app, + cds_lfht_for_each_entry(the_agent_apps_ht_by_sock->ht, &iter.iter, app, node.node) { if (app->domain != domain) { continue; @@ -863,7 +890,7 @@ int agent_list_events(struct lttng_event **events, struct lttng_event *tmp_events = NULL; struct lttng_ht_iter iter; - assert(events); + LTTNG_ASSERT(events); DBG2("Agent listing events for domain %d", domain); @@ -876,7 +903,7 @@ int agent_list_events(struct lttng_event **events, } rcu_read_lock(); - cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, app, + cds_lfht_for_each_entry(the_agent_apps_ht_by_sock->ht, &iter.iter, app, node.node) { ssize_t nb_ev; struct lttng_event *agent_events; @@ -942,11 +969,11 @@ struct agent_app *agent_create_app(pid_t pid, enum lttng_domain_type domain, { struct agent_app *app; - assert(sock); + LTTNG_ASSERT(sock); app = zmalloc(sizeof(*app)); if (!app) { - PERROR("zmalloc agent create"); + PERROR("Failed to allocate agent application instance"); goto error; } @@ -972,9 +999,10 @@ struct agent_app *agent_find_app_by_sock(int sock) struct lttng_ht_iter iter; struct agent_app *app; - assert(sock >= 0); + LTTNG_ASSERT(sock >= 0); - lttng_ht_lookup(agent_apps_ht_by_sock, (void *)((unsigned long) sock), &iter); + lttng_ht_lookup(the_agent_apps_ht_by_sock, + (void *) ((unsigned long) sock), &iter); node = lttng_ht_iter_get_node_ulong(&iter); if (node == NULL) { goto error; @@ -994,10 +1022,10 @@ error: */ void agent_add_app(struct agent_app *app) { - assert(app); + LTTNG_ASSERT(app); DBG3("Agent adding app sock: %d and pid: %d to ht", app->sock->fd, app->pid); - lttng_ht_add_unique_ulong(agent_apps_ht_by_sock, &app->node); + lttng_ht_add_unique_ulong(the_agent_apps_ht_by_sock, &app->node); } /* @@ -1010,13 +1038,13 @@ void agent_delete_app(struct agent_app *app) int ret; struct lttng_ht_iter iter; - assert(app); + LTTNG_ASSERT(app); DBG3("Agent deleting app pid: %d and sock: %d", app->pid, app->sock->fd); iter.iter.node = &app->node.node; - ret = lttng_ht_del(agent_apps_ht_by_sock, &iter); - assert(!ret); + ret = lttng_ht_del(the_agent_apps_ht_by_sock, &iter); + LTTNG_ASSERT(!ret); } /* @@ -1026,7 +1054,7 @@ void agent_delete_app(struct agent_app *app) */ void agent_destroy_app(struct agent_app *app) { - assert(app); + LTTNG_ASSERT(app); if (app->sock) { app->sock->ops->close(app->sock); @@ -1045,7 +1073,7 @@ int agent_init(struct agent *agt) { int ret; - assert(agt); + LTTNG_ASSERT(agt); agt->events = lttng_ht_new(0, LTTNG_HT_TYPE_STRING); if (!agt->events) { @@ -1066,8 +1094,8 @@ error: */ void agent_add(struct agent *agt, struct lttng_ht *ht) { - assert(agt); - assert(ht); + LTTNG_ASSERT(agt); + LTTNG_ASSERT(ht); DBG3("Agent adding from domain %d", agt->domain); @@ -1109,7 +1137,7 @@ error: */ struct agent_event *agent_create_event(const char *name, enum lttng_loglevel_type loglevel_type, int loglevel_value, - struct lttng_filter_bytecode *filter, char *filter_expression) + struct lttng_bytecode *filter, char *filter_expression) { struct agent_event *event = NULL; @@ -1145,9 +1173,9 @@ error: */ void agent_add_event(struct agent_event *event, struct agent *agt) { - assert(event); - assert(agt); - assert(agt->events); + LTTNG_ASSERT(event); + LTTNG_ASSERT(agt); + LTTNG_ASSERT(agt->events); DBG3("Agent adding event %s", event->name); add_unique_agent_event(agt->events, event); @@ -1162,10 +1190,10 @@ int agent_add_context(const struct lttng_event_context *ctx, struct agent *agt) int ret = LTTNG_OK; struct agent_app_ctx *agent_ctx = NULL; - assert(ctx); - assert(agt); - assert(agt->events); - assert(ctx->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT); + LTTNG_ASSERT(ctx); + LTTNG_ASSERT(agt); + LTTNG_ASSERT(agt->events); + LTTNG_ASSERT(ctx->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT); agent_ctx = create_app_ctx(ctx); if (!agent_ctx) { @@ -1194,10 +1222,10 @@ void agent_find_events_by_name(const char *name, struct agent *agt, struct lttng_ht *ht; struct agent_ht_key key; - assert(name); - assert(agt); - assert(agt->events); - assert(iter); + LTTNG_ASSERT(name); + LTTNG_ASSERT(agt); + LTTNG_ASSERT(agt->events); + LTTNG_ASSERT(iter); ht = agt->events; key.name = name; @@ -1206,6 +1234,93 @@ void agent_find_events_by_name(const char *name, struct agent *agt, ht_match_event_by_name, &key, &iter->iter); } +/* + * Find the agent event matching a trigger. + * + * RCU read side lock MUST be acquired. It must be held for as long as + * the returned agent_event is used. + * + * Return object if found else NULL. + */ +struct agent_event *agent_find_event_by_trigger( + const struct lttng_trigger *trigger, struct agent *agt) +{ + enum lttng_condition_status c_status; + enum lttng_event_rule_status er_status; + enum lttng_domain_type domain; + const struct lttng_condition *condition; + const struct lttng_event_rule *rule; + const char *name; + const char *filter_expression; + const struct lttng_log_level_rule *log_level_rule; + /* Unused when loglevel_type is 'ALL'. */ + int loglevel_value = 0; + enum lttng_loglevel_type loglevel_type; + event_rule_logging_get_name_pattern logging_get_name_pattern; + event_rule_logging_get_log_level_rule logging_get_log_level_rule; + + LTTNG_ASSERT(agt); + LTTNG_ASSERT(agt->events); + + condition = lttng_trigger_get_const_condition(trigger); + + LTTNG_ASSERT(lttng_condition_get_type(condition) == + LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES); + + c_status = lttng_condition_event_rule_matches_get_rule( + condition, &rule); + LTTNG_ASSERT(c_status == LTTNG_CONDITION_STATUS_OK); + + switch (lttng_event_rule_get_type(rule)) { + case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING: + logging_get_name_pattern = + lttng_event_rule_jul_logging_get_name_pattern; + logging_get_log_level_rule = + lttng_event_rule_jul_logging_get_log_level_rule; + break; + case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING: + logging_get_name_pattern = + lttng_event_rule_log4j_logging_get_name_pattern; + logging_get_log_level_rule = + lttng_event_rule_log4j_logging_get_log_level_rule; + break; + case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING: + logging_get_name_pattern = + lttng_event_rule_python_logging_get_name_pattern; + logging_get_log_level_rule = + lttng_event_rule_python_logging_get_log_level_rule; + break; + default: + abort(); + break; + } + + domain = lttng_event_rule_get_domain_type(rule); + LTTNG_ASSERT(domain == LTTNG_DOMAIN_JUL || domain == LTTNG_DOMAIN_LOG4J || + domain == LTTNG_DOMAIN_PYTHON); + + /* Get the event's pattern name ('name' in the legacy terminology). */ + er_status = logging_get_name_pattern(rule, &name); + LTTNG_ASSERT(er_status == LTTNG_EVENT_RULE_STATUS_OK); + + /* Get the internal filter expression. */ + filter_expression = lttng_event_rule_get_filter(rule); + + /* Map log_level_rule to loglevel value. */ + er_status = logging_get_log_level_rule(rule, &log_level_rule); + if (er_status == LTTNG_EVENT_RULE_STATUS_UNSET) { + loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL; + loglevel_value = 0; + } else if (er_status == LTTNG_EVENT_RULE_STATUS_OK) { + lttng_log_level_rule_to_loglevel(log_level_rule, &loglevel_type, &loglevel_value); + } else { + abort(); + } + + return agent_find_event(name, loglevel_type, loglevel_value, + filter_expression, agt); +} + /* * Get the next agent event duplicate by name. This should be called * after a call to agent_find_events_by_name() to iterate on events. @@ -1233,17 +1348,19 @@ void agent_event_next_duplicate(const char *name, * Return object if found else NULL. */ struct agent_event *agent_find_event(const char *name, - enum lttng_loglevel_type loglevel_type, int loglevel_value, - char *filter_expression, struct agent *agt) + enum lttng_loglevel_type loglevel_type, + int loglevel_value, + const char *filter_expression, + struct agent *agt) { struct lttng_ht_node_str *node; struct lttng_ht_iter iter; struct lttng_ht *ht; struct agent_ht_key key; - assert(name); - assert(agt); - assert(agt->events); + LTTNG_ASSERT(name); + LTTNG_ASSERT(agt); + LTTNG_ASSERT(agt->events); ht = agt->events; key.name = name; @@ -1273,7 +1390,7 @@ error: */ void agent_destroy_event(struct agent_event *event) { - assert(event); + LTTNG_ASSERT(event); free(event->filter); free(event->filter_expression); @@ -1299,7 +1416,7 @@ void agent_destroy(struct agent *agt) struct lttng_ht_iter iter; struct agent_app_ctx *ctx; - assert(agt); + LTTNG_ASSERT(agt); DBG3("Agent destroy"); @@ -1318,7 +1435,7 @@ void agent_destroy(struct agent *agt) (void) agent_disable_event(event, agt->domain); ret = lttng_ht_del(agt->events, &iter); - assert(!ret); + LTTNG_ASSERT(!ret); call_rcu(&node->head, destroy_event_agent_rcu); } @@ -1337,14 +1454,8 @@ void agent_destroy(struct agent *agt) */ int agent_app_ht_alloc(void) { - int ret = 0; - - agent_apps_ht_by_sock = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG); - if (!agent_apps_ht_by_sock) { - ret = -1; - } - - return ret; + the_agent_apps_ht_by_sock = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG); + return the_agent_apps_ht_by_sock ? 0 : -1; } /* @@ -1354,7 +1465,7 @@ void agent_destroy_app_by_sock(int sock) { struct agent_app *app; - assert(sock >= 0); + LTTNG_ASSERT(sock >= 0); /* * Not finding an application is a very important error that should NEVER @@ -1363,7 +1474,7 @@ void agent_destroy_app_by_sock(int sock) */ rcu_read_lock(); app = agent_find_app_by_sock(sock); - assert(app); + LTTNG_ASSERT(app); /* RCU read side lock is assumed to be held by this function. */ agent_delete_app(app); @@ -1381,11 +1492,12 @@ void agent_app_ht_clean(void) struct lttng_ht_node_ulong *node; struct lttng_ht_iter iter; - if (!agent_apps_ht_by_sock) { + if (!the_agent_apps_ht_by_sock) { return; } rcu_read_lock(); - cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, node, node) { + cds_lfht_for_each_entry( + the_agent_apps_ht_by_sock->ht, &iter.iter, node, node) { struct agent_app *app; app = caa_container_of(node, struct agent_app, node); @@ -1393,7 +1505,7 @@ void agent_app_ht_clean(void) } rcu_read_unlock(); - lttng_ht_destroy(agent_apps_ht_by_sock); + lttng_ht_destroy(the_agent_apps_ht_by_sock); } /* @@ -1402,29 +1514,27 @@ void agent_app_ht_clean(void) * Note that this function is most likely to be used with a tracing session * thus the caller should make sure to hold the appropriate lock(s). */ -void agent_update(struct agent *agt, int sock) +void agent_update(const struct agent *agt, const struct agent_app *app) { int ret; - struct agent_app *app; struct agent_event *event; struct lttng_ht_iter iter; struct agent_app_ctx *ctx; - assert(agt); - assert(sock >= 0); + LTTNG_ASSERT(agt); + LTTNG_ASSERT(app); - DBG("Agent updating app socket %d", sock); + DBG("Agent updating app: pid = %ld", (long) app->pid); rcu_read_lock(); - app = agent_find_app_by_sock(sock); /* * We are in the registration path thus if the application is gone, * there is a serious code flow error. */ - assert(app); + cds_lfht_for_each_entry(agt->events->ht, &iter.iter, event, node.node) { /* Skip event if disabled. */ - if (!event->enabled) { + if (!AGENT_EVENT_IS_ENABLED(event)) { continue; } @@ -1449,3 +1559,66 @@ void agent_update(struct agent *agt, int sock) rcu_read_unlock(); } + +/* + * Allocate the per-event notifier domain agent hash table. It is lazily + * populated as domains are used. + */ +int agent_by_event_notifier_domain_ht_create(void) +{ + the_trigger_agents_ht_by_domain = lttng_ht_new(0, LTTNG_HT_TYPE_U64); + return the_trigger_agents_ht_by_domain ? 0 : -1; +} + +/* + * Clean-up the per-event notifier domain agent hash table and destroy it. + */ +void agent_by_event_notifier_domain_ht_destroy(void) +{ + struct lttng_ht_node_u64 *node; + struct lttng_ht_iter iter; + + if (!the_trigger_agents_ht_by_domain) { + return; + } + + rcu_read_lock(); + cds_lfht_for_each_entry(the_trigger_agents_ht_by_domain->ht, + &iter.iter, node, node) { + struct agent *agent = + caa_container_of(node, struct agent, node); + const int ret = lttng_ht_del( + the_trigger_agents_ht_by_domain, &iter); + + LTTNG_ASSERT(ret == 0); + agent_destroy(agent); + } + + rcu_read_unlock(); + lttng_ht_destroy(the_trigger_agents_ht_by_domain); +} + +struct agent *agent_find_by_event_notifier_domain( + enum lttng_domain_type domain_type) +{ + struct agent *agt = NULL; + struct lttng_ht_node_u64 *node; + struct lttng_ht_iter iter; + const uint64_t key = (uint64_t) domain_type; + + LTTNG_ASSERT(the_trigger_agents_ht_by_domain); + + DBG3("Per-event notifier domain agent lookup for domain '%s'", + lttng_domain_type_str(domain_type)); + + lttng_ht_lookup(the_trigger_agents_ht_by_domain, &key, &iter); + node = lttng_ht_iter_get_node_u64(&iter); + if (!node) { + goto end; + } + + agt = caa_container_of(node, struct agent, node); + +end: + return agt; +}