X-Git-Url: https://git.liburcu.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fagent.c;h=77846b4f2251e7891d4f32b5ad196da4f4535f53;hb=3a5f70173aa04d11ccb22694d5d31a702cad33ab;hp=ced0f85cf018c93d5ad1ac9a79a7e6c788ab136c;hpb=c12618b52dfd3c5ba932065b32cb5928fe0c2012;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/agent.c b/src/bin/lttng-sessiond/agent.c index ced0f85cf..77846b4f2 100644 --- a/src/bin/lttng-sessiond/agent.c +++ b/src/bin/lttng-sessiond/agent.c @@ -1,26 +1,25 @@ /* - * Copyright (C) 2013 - David Goulet - * Copyright (C) 2016 - Jérémie Galarneau + * Copyright (C) 2013 David Goulet + * Copyright (C) 2016 Jérémie Galarneau * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License, version 2 only, as - * published by the Free Software Foundation. + * SPDX-License-Identifier: GPL-2.0-only * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #define _LGPL_SOURCE -#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include @@ -29,10 +28,16 @@ #include "agent.h" #include "ust-app.h" #include "utils.h" -#include "error.h" +#include "common/error.h" #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. */ @@ -91,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; @@ -111,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) @@ -120,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; @@ -143,11 +149,18 @@ static int ht_match_event(struct cds_lfht_node *node, } /* Filter expression */ - if (strncmp(event->filter_expression, key->filter_expression, - strlen(event->filter_expression)) != 0) { + if (!!event->filter_expression != !!key->filter_expression) { + /* One has a filter expression, the other does not */ goto no_match; } + if (event->filter_expression) { + if (strncmp(event->filter_expression, key->filter_expression, + strlen(event->filter_expression)) != 0) { + goto no_match; + } + } + return 1; no_match: @@ -163,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; @@ -175,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); } /* @@ -217,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); @@ -247,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) { @@ -272,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) { @@ -303,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); @@ -353,8 +366,11 @@ static ssize_t list_events(struct agent_app *app, struct lttng_event **events) for (i = 0; i < nb_event; i++) { offset += len; - strncpy(tmp_events[i].name, reply->payload + offset, - sizeof(tmp_events[i].name)); + if (lttng_strncpy(tmp_events[i].name, reply->payload + offset, + sizeof(tmp_events[i].name))) { + ret = LTTNG_ERR_INVALID; + goto error; + } tmp_events[i].pid = app->pid; tmp_events[i].enabled = -1; len = strlen(reply->payload + offset) + 1; @@ -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); @@ -408,17 +424,20 @@ static int enable_event(struct agent_app *app, struct agent_event *event) } data_size = sizeof(msg) + filter_expression_length; - ret = send_header(app->sock, data_size, AGENT_CMD_ENABLE, 0); - if (ret < 0) { - goto error_io; - } - memset(&msg, 0, sizeof(msg)); msg.loglevel_value = htobe32(event->loglevel_value); msg.loglevel_type = htobe32(event->loglevel_type); - strncpy(msg.name, event->name, sizeof(msg.name)); + if (lttng_strncpy(msg.name, event->name, sizeof(msg.name))) { + ret = LTTNG_ERR_INVALID; + goto error; + } msg.filter_expression_length = htobe32(filter_expression_length); + ret = send_header(app->sock, data_size, AGENT_CMD_ENABLE, 0); + if (ret < 0) { + goto error_io; + } + bytes_to_send = zmalloc(data_size); if (!bytes_to_send) { ret = LTTNG_ERR_NOMEM; @@ -492,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", @@ -583,22 +602,25 @@ 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); data_size = sizeof(msg); + memset(&msg, 0, sizeof(msg)); + if (lttng_strncpy(msg.name, event->name, sizeof(msg.name))) { + ret = LTTNG_ERR_INVALID; + goto error; + } ret = send_header(app->sock, data_size, AGENT_CMD_DISABLE, 0); if (ret < 0) { goto error_io; } - memset(&msg, 0, sizeof(msg)); - strncpy(msg.name, event->name, sizeof(msg.name)); ret = send_payload(app->sock, &msg, sizeof(msg)); if (ret < 0) { goto error_io; @@ -637,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); @@ -658,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; @@ -675,7 +697,7 @@ int agent_enable_event(struct agent_event *event, } } - event->enabled = 1; + event->enabled_count++; ret = LTTNG_OK; error: @@ -692,7 +714,7 @@ void destroy_app_ctx(struct agent_app_ctx *ctx) } static -struct agent_app_ctx *create_app_ctx(struct lttng_event_context *ctx) +struct agent_app_ctx *create_app_ctx(const struct lttng_event_context *ctx) { struct agent_app_ctx *agent_ctx = NULL; @@ -700,7 +722,7 @@ struct agent_app_ctx *create_app_ctx(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; @@ -722,14 +744,14 @@ end: * * Return LTTNG_OK on success or else a LTTNG_ERR* code. */ -int agent_enable_context(struct lttng_event_context *ctx, +int agent_enable_context(const struct lttng_event_context *ctx, enum lttng_domain_type domain) { int ret; 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; @@ -737,7 +759,7 @@ int agent_enable_context(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; @@ -780,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; @@ -800,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(); @@ -814,18 +847,19 @@ end: * * Return LTTNG_OK on success or else a LTTNG_ERR* code. */ -int disable_context(struct agent_app_ctx *ctx, enum lttng_domain_type domain) +static int disable_context(struct agent_app_ctx *ctx, + enum lttng_domain_type domain) { int ret = LTTNG_OK; 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; @@ -856,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); @@ -869,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; @@ -935,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; } @@ -965,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; @@ -987,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); } /* @@ -1003,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); } /* @@ -1019,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); @@ -1038,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) { @@ -1059,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); @@ -1102,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; @@ -1138,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); @@ -1150,15 +1185,15 @@ void agent_add_event(struct agent_event *event, struct agent *agt) /* * Unique add of a agent context to an agent object. */ -int agent_add_context(struct lttng_event_context *ctx, struct agent *agt) +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) { @@ -1187,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; @@ -1199,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. @@ -1226,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; @@ -1266,7 +1390,7 @@ error: */ void agent_destroy_event(struct agent_event *event) { - assert(event); + LTTNG_ASSERT(event); free(event->filter); free(event->filter_expression); @@ -1292,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"); @@ -1311,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); } @@ -1330,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; } /* @@ -1347,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 @@ -1356,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); @@ -1374,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); @@ -1386,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); } /* @@ -1395,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; } @@ -1442,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; +}