* This is a quite heavy call in terms of locking since the session list lock
* AND session lock are acquired.
*/
-static void update_agent_app(int sock)
+static void update_agent_app(struct agent_app *app)
{
struct ltt_session *session, *stmp;
struct ltt_session_list *list;
cds_list_for_each_entry_safe(session, stmp, &list->head, list) {
session_lock(session);
if (session->ust_session) {
- agent_update(&session->ust_session->agent, sock);
+ struct agent *agt;
+
+ agt = trace_ust_find_agent(session->ust_session, app->domain);
+ if (agt) {
+ agent_update(agt, app->sock->fd);
+ }
}
session_unlock(session);
}
int ret;
pid_t pid;
ssize_t size;
+ enum lttng_domain_type domain;
struct agent_app *app;
struct agent_register_msg msg;
struct lttcomm_sock *new_sock;
ret = -errno;
goto error_socket;
}
+ domain = be32toh(msg.domain);
pid = be32toh(msg.pid);
- DBG2("[agent-thread] New registration for pid %d on socket %d", pid,
- new_sock->fd);
+ DBG2("[agent-thread] New registration for pid %d domain %d on socket %d",
+ pid, domain, new_sock->fd);
- app = agent_create_app(pid, new_sock);
+ app = agent_create_app(pid, domain, new_sock);
if (!app) {
ret = -ENOMEM;
goto error_socket;
}
/* Update newly registered app. */
- update_agent_app(new_fd);
+ update_agent_app(app);
/* On failure, the poll will detect it and clean it up. */
(void) agent_send_registration_done(app);
*
* Return LTTNG_OK on success or else a LTTNG_ERR* code.
*/
-int agent_enable_event(struct agent_event *event)
+int agent_enable_event(struct agent_event *event,
+ enum lttng_domain_type domain)
{
int ret;
struct agent_app *app;
cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, app,
node.node) {
+ if (app->domain != domain) {
+ continue;
+ }
+
/* Enable event on agent application through TCP socket. */
ret = enable_event(app, event);
if (ret != LTTNG_OK) {
*
* Return LTTNG_OK on success or else a LTTNG_ERR* code.
*/
-int agent_disable_event(struct agent_event *event)
+int agent_disable_event(struct agent_event *event,
+ enum lttng_domain_type domain)
{
int ret;
struct agent_app *app;
cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, app,
node.node) {
+ if (app->domain != domain) {
+ continue;
+ }
+
/* Enable event on agent application through TCP socket. */
ret = disable_event(app, event);
if (ret != LTTNG_OK) {
*
* Return newly allocated object or else NULL on error.
*/
-struct agent_app *agent_create_app(pid_t pid, struct lttcomm_sock *sock)
+struct agent_app *agent_create_app(pid_t pid, enum lttng_domain_type domain,
+ struct lttcomm_sock *sock)
{
struct agent_app *app;
}
app->pid = pid;
+ app->domain = domain;
app->sock = sock;
lttng_ht_node_init_ulong(&app->node, (unsigned long) app->sock->fd);
ret = -ENOMEM;
goto error;
}
+ lttng_ht_node_init_u64(&agt->node, agt->domain);
return 0;
return ret;
}
+/*
+ * Add agent object to the given hash table.
+ */
+void agent_add(struct agent *agt, struct lttng_ht *ht)
+{
+ assert(agt);
+ assert(ht);
+
+ DBG3("Agent adding from domain %d", agt->domain);
+
+ rcu_read_lock();
+ lttng_ht_add_unique_u64(ht, &agt->node);
+ rcu_read_unlock();
+}
+
+/*
+ * Create an agent object for the given domain.
+ *
+ * Return the allocated agent or NULL on error.
+ */
+struct agent *agent_create(enum lttng_domain_type domain)
+{
+ int ret;
+ struct agent *agt;
+
+ agt = zmalloc(sizeof(*agt));
+ if (!agt) {
+ goto error;
+ }
+ agt->domain = domain;
+
+ ret = agent_init(agt);
+ if (ret < 0) {
+ free(agt);
+ goto error;
+ }
+
+error:
+ return agt;
+}
+
/*
* Create a newly allocated agent event data structure. If name is valid, it's
* copied into the created event.
* find back the corresponding UST app object so both socket can be linked.
*/
struct agent_register_msg {
+ /* This maps to a lttng_domain_type. */
+ uint32_t domain;
uint32_t pid;
};
*/
pid_t pid;
+ /* Domain of the application. */
+ enum lttng_domain_type domain;
+
/*
* AGENT TCP socket that was created upon registration.
*/
* actually enabled.
*/
unsigned int being_used:1;
+
+ /* What domain this agent is. */
+ enum lttng_domain_type domain;
+
/* Contains event indexed by name. */
struct lttng_ht *events;
+
+ /* Node used for the hash table indexed by domain type. */
+ struct lttng_ht_node_u64 node;
};
/* Setup agent subsystem. */
/* Initialize an already allocated agent domain. */
int agent_init(struct agent *agt);
+struct agent *agent_create(enum lttng_domain_type domain);
void agent_destroy(struct agent *agt);
+void agent_add(struct agent *agt, struct lttng_ht *ht);
/* Agent event API. */
struct agent_event *agent_create_event(const char *name,
void agent_destroy_event(struct agent_event *event);
/* Agent app API. */
-struct agent_app *agent_create_app(pid_t pid, struct lttcomm_sock *sock);
+struct agent_app *agent_create_app(pid_t pid, enum lttng_domain_type domain,
+ struct lttcomm_sock *sock);
void agent_add_app(struct agent_app *app);
void agent_delete_app(struct agent_app *app);
struct agent_app *agent_find_app_by_sock(int sock);
int agent_send_registration_done(struct agent_app *app);
/* Agent action API */
-int agent_enable_event(struct agent_event *event);
-int agent_disable_event(struct agent_event *event);
+int agent_enable_event(struct agent_event *event,
+ enum lttng_domain_type domain);
+int agent_disable_event(struct agent_event *event,
+ enum lttng_domain_type domain);
void agent_update(struct agent *agt, int sock);
int agent_list_events(struct lttng_event **events);
}
case LTTNG_DOMAIN_JUL:
{
+ struct agent *agt;
struct ltt_ust_session *usess = session->ust_session;
assert(usess);
- ret = event_agent_disable(usess, event_name);
+ agt = trace_ust_find_agent(usess, LTTNG_DOMAIN_JUL);
+ if (!agt) {
+ ret = -LTTNG_ERR_UST_EVENT_NOT_FOUND;
+ goto error;
+ }
+
+ ret = event_agent_disable(usess, agt, event_name);
if (ret != LTTNG_OK) {
goto error;
}
}
case LTTNG_DOMAIN_JUL:
{
+ struct agent *agt;
struct ltt_ust_session *usess = session->ust_session;
assert(usess);
- ret = event_agent_disable_all(usess);
+ agt = trace_ust_find_agent(usess, LTTNG_DOMAIN_JUL);
+ if (!agt) {
+ ret = -LTTNG_ERR_UST_EVENT_NOT_FOUND;
+ goto error;
+ }
+
+ ret = event_agent_disable_all(usess, agt);
if (ret != LTTNG_OK) {
goto error;
}
}
case LTTNG_DOMAIN_JUL:
{
+ struct agent *agt;
struct lttng_event uevent;
struct lttng_domain tmp_dom;
struct ltt_ust_session *usess = session->ust_session;
assert(usess);
+ agt = trace_ust_find_agent(usess, LTTNG_DOMAIN_JUL);
+ if (!agt) {
+ agt = agent_create(LTTNG_DOMAIN_JUL);
+ if (!agt) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto error;
+ }
+ agent_add(agt, usess->agents);
+ }
+
/* Create the default tracepoint. */
memset(&uevent, 0, sizeof(uevent));
uevent.type = LTTNG_EVENT_TRACEPOINT;
/* The wild card * means that everything should be enabled. */
if (strncmp(event->name, "*", 1) == 0 && strlen(event->name) == 1) {
- ret = event_agent_enable_all(usess, event, filter);
+ ret = event_agent_enable_all(usess, agt, event, filter);
} else {
- ret = event_agent_enable(usess, event, filter);
+ ret = event_agent_enable(usess, agt, event, filter);
}
if (ret != LTTNG_OK) {
goto error;
}
case LTTNG_DOMAIN_JUL:
{
+ struct agent *agt;
struct lttng_event uevent, event;
struct lttng_domain tmp_dom;
struct ltt_ust_session *usess = session->ust_session;
assert(usess);
+ agt = trace_ust_find_agent(usess, LTTNG_DOMAIN_JUL);
+ if (!agt) {
+ agt = agent_create(LTTNG_DOMAIN_JUL);
+ if (!agt) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto error;
+ }
+ agent_add(agt, usess->agents);
+ }
+
/* Create the default tracepoint. */
uevent.type = LTTNG_EVENT_TRACEPOINT;
uevent.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
strncpy(event.name, "*", sizeof(event.name));
event.name[sizeof(event.name) - 1] = '\0';
- ret = event_agent_enable_all(usess, &event, filter);
+ ret = event_agent_enable_all(usess, agt, &event, filter);
if (ret != LTTNG_OK) {
goto error;
}
{
int ret, index = 0;
ssize_t nb_dom = 0;
+ struct agent *agt;
+ struct lttng_ht_iter iter;
if (session->kernel_session != NULL) {
DBG3("Listing domains found kernel domain");
DBG3("Listing domains found UST global domain");
nb_dom++;
- if (session->ust_session->agent.being_used) {
- nb_dom++;
+ cds_lfht_for_each_entry(session->ust_session->agents->ht, &iter.iter,
+ agt, node.node) {
+ if (agt->being_used) {
+ nb_dom++;
+ }
}
}
(*domains)[index].buf_type = session->ust_session->buffer_type;
index++;
- if (session->ust_session->agent.being_used) {
- (*domains)[index].type = LTTNG_DOMAIN_JUL;
- (*domains)[index].buf_type = session->ust_session->buffer_type;
- index++;
+ cds_lfht_for_each_entry(session->ust_session->agents->ht, &iter.iter,
+ agt, node.node) {
+ if (agt->being_used) {
+ (*domains)[index].type = agt->domain;
+ (*domains)[index].buf_type = session->ust_session->buffer_type;
+ index++;
+ }
}
}
}
case LTTNG_DOMAIN_JUL:
if (session->ust_session) {
- nb_event = list_lttng_agent_events(
- &session->ust_session->agent, events);
+ struct lttng_ht_iter iter;
+ struct agent *agt;
+
+ cds_lfht_for_each_entry(session->ust_session->agents->ht,
+ &iter.iter, agt, node.node) {
+ nb_event = list_lttng_agent_events(agt, events);
+ }
}
break;
default:
* Return LTTNG_OK on success or else a LTTNG_ERR* code.
*/
int event_agent_enable_all(struct ltt_ust_session *usess,
- struct lttng_event *event, struct lttng_filter_bytecode *filter)
+ struct agent *agt, struct lttng_event *event,
+ struct lttng_filter_bytecode *filter)
{
int ret;
- struct agent_event *jevent;
+ struct agent_event *aevent;
struct lttng_ht_iter iter;
assert(usess);
DBG("Event agent enabling ALL events for session %" PRIu64, usess->id);
/* Enable event on agent application through TCP socket. */
- ret = event_agent_enable(usess, event, filter);
+ ret = event_agent_enable(usess, agt, event, filter);
if (ret != LTTNG_OK) {
goto error;
}
/* Flag every event that they are now enabled. */
rcu_read_lock();
- cds_lfht_for_each_entry(usess->agent.events->ht, &iter.iter, jevent,
+ cds_lfht_for_each_entry(agt->events->ht, &iter.iter, aevent,
node.node) {
- jevent->enabled = 1;
+ aevent->enabled = 1;
}
rcu_read_unlock();
*
* Return LTTNG_OK on success or else a LTTNG_ERR* code.
*/
-int event_agent_enable(struct ltt_ust_session *usess, struct lttng_event *event,
+int event_agent_enable(struct ltt_ust_session *usess,
+ struct agent *agt, struct lttng_event *event,
struct lttng_filter_bytecode *filter)
{
int ret, created = 0;
- struct agent_event *jevent;
+ struct agent_event *aevent;
assert(usess);
assert(event);
+ assert(agt);
DBG("Event agent enabling %s for session %" PRIu64 " with loglevel type %d "
"and loglevel %d", event->name, usess->id, event->loglevel_type,
event->loglevel);
- jevent = agent_find_event(event->name, event->loglevel, &usess->agent);
- if (!jevent) {
- jevent = agent_create_event(event->name, filter);
- if (!jevent) {
+ aevent = agent_find_event(event->name, event->loglevel, agt);
+ if (!aevent) {
+ aevent = agent_create_event(event->name, filter);
+ if (!aevent) {
ret = LTTNG_ERR_NOMEM;
goto error;
}
- jevent->loglevel = event->loglevel;
- jevent->loglevel_type = event->loglevel_type;
+ aevent->loglevel = event->loglevel;
+ aevent->loglevel_type = event->loglevel_type;
created = 1;
}
/* Already enabled? */
- if (jevent->enabled) {
+ if (aevent->enabled) {
goto end;
}
- ret = agent_enable_event(jevent);
+ ret = agent_enable_event(aevent, agt->domain);
if (ret != LTTNG_OK) {
goto error;
}
/* If the event was created prior to the enable, add it to the domain. */
if (created) {
- agent_add_event(jevent, &usess->agent);
+ agent_add_event(aevent, agt);
}
end:
error:
if (created) {
- agent_destroy_event(jevent);
+ agent_destroy_event(aevent);
}
return ret;
}
*
* Return LTTNG_OK on success or else a LTTNG_ERR* code.
*/
-int event_agent_disable(struct ltt_ust_session *usess, char *event_name)
+int event_agent_disable(struct ltt_ust_session *usess, struct agent *agt,
+ char *event_name)
{
int ret;
- struct agent_event *jevent;
+ struct agent_event *aevent;
struct ltt_ust_event *uevent = NULL;
struct ltt_ust_channel *uchan = NULL;
char *ust_event_name;
+ assert(agt);
assert(usess);
assert(event_name);
DBG("Event agent disabling %s for session %" PRIu64, event_name, usess->id);
- jevent = agent_find_event_by_name(event_name, &usess->agent);
- if (!jevent) {
+ aevent = agent_find_event_by_name(event_name, agt);
+ if (!aevent) {
ret = LTTNG_ERR_UST_EVENT_NOT_FOUND;
goto error;
}
/* Already disabled? */
- if (!jevent->enabled) {
+ if (!aevent->enabled) {
goto end;
}
* filter is the one handling the loglevel for agent.
*/
uevent = trace_ust_find_event(uchan->events, ust_event_name,
- jevent->filter, 0, NULL);
+ aevent->filter, 0, NULL);
/* If the agent event exists, it must be available on the UST side. */
assert(uevent);
goto error;
}
- ret = agent_disable_event(jevent);
+ ret = agent_disable_event(aevent, agt->domain);
if (ret != LTTNG_OK) {
goto error;
}
*
* Return LTTNG_OK on success or else a LTTNG_ERR* code.
*/
-int event_agent_disable_all(struct ltt_ust_session *usess)
+int event_agent_disable_all(struct ltt_ust_session *usess,
+ struct agent *agt)
{
int ret, do_disable = 0;
- struct agent_event *jevent;
+ struct agent_event *aevent;
struct lttng_ht_iter iter;
+ assert(agt);
assert(usess);
- /* Enable event on agent application through TCP socket. */
- ret = event_agent_disable(usess, "*");
+ /* Disable event on agent application through TCP socket. */
+ ret = event_agent_disable(usess, agt, "*");
if (ret != LTTNG_OK) {
if (ret == LTTNG_ERR_UST_EVENT_NOT_FOUND) {
/*
/* Flag every event that they are now enabled. */
rcu_read_lock();
- cds_lfht_for_each_entry(usess->agent.events->ht, &iter.iter, jevent,
+ cds_lfht_for_each_entry(agt->events->ht, &iter.iter, aevent,
node.node) {
- if (jevent->enabled && do_disable) {
- ret = event_agent_disable(usess, jevent->name);
+ if (aevent->enabled && do_disable) {
+ ret = event_agent_disable(usess, agt, aevent->name);
if (ret != LTTNG_OK) {
rcu_read_unlock();
goto error;
}
}
- jevent->enabled = 0;
+ aevent->enabled = 0;
}
rcu_read_unlock();
#ifndef _LTT_EVENT_H
#define _LTT_EVENT_H
+#include "agent.h"
#include "trace-kernel.h"
int event_kernel_disable_tracepoint(struct ltt_kernel_channel *kchan,
int event_ust_disable_all_tracepoints(struct ltt_ust_session *usess,
struct ltt_ust_channel *uchan);
-int event_agent_enable(struct ltt_ust_session *usess, struct lttng_event *event,
- struct lttng_filter_bytecode *filter);
-int event_agent_enable_all(struct ltt_ust_session *usess,
+int event_agent_enable(struct ltt_ust_session *usess, struct agent *agt,
+ struct lttng_event *event, struct lttng_filter_bytecode *filter);
+int event_agent_enable_all(struct ltt_ust_session *usess, struct agent *agt,
struct lttng_event *event, struct lttng_filter_bytecode *filter);
-int event_agent_disable(struct ltt_ust_session *usess, char *event_name);
-int event_agent_disable_all(struct ltt_ust_session *usess);
+int event_agent_disable(struct ltt_ust_session *usess, struct agent *agt,
+ char *event_name);
+int event_agent_disable_all(struct ltt_ust_session *usess, struct agent *agt);
#endif /* _LTT_EVENT_H */
}
if (session->ust_session &&
- session->ust_session->agent.being_used) {
+ lttng_ht_get_count(session->ust_session->agents) > 0) {
ret = config_writer_open_element(writer,
config_element_domain);
if (ret) {
return NULL;
}
+/*
+ * Lookup an agent in the session agents hash table by domain type and return
+ * the object if found else NULL.
+ */
+struct agent *trace_ust_find_agent(struct ltt_ust_session *session,
+ enum lttng_domain_type domain_type)
+{
+ struct agent *agt = NULL;
+ struct lttng_ht_node_u64 *node;
+ struct lttng_ht_iter iter;
+ uint64_t key;
+
+ assert(session);
+
+ DBG3("Trace ust agent lookup for domain %d", domain_type);
+
+ key = domain_type;
+
+ lttng_ht_lookup(session->agents, &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;
+}
+
/*
* Allocate and initialize a ust session data structure.
*
*/
struct ltt_ust_session *trace_ust_create_session(uint64_t session_id)
{
- int ret;
struct ltt_ust_session *lus;
/* Allocate a new ltt ust session */
/* Alloc UST global domain channels' HT */
lus->domain_global.channels = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
- ret = agent_init(&lus->agent);
- if (ret < 0) {
- goto error_consumer;
- }
+ /* Alloc agent hash table. */
+ lus->agents = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
lus->consumer = consumer_create_output(CONSUMER_DST_LOCAL);
if (lus->consumer == NULL) {
error_consumer:
ht_cleanup_push(lus->domain_global.channels);
- agent_destroy(&lus->agent);
+ ht_cleanup_push(lus->agents);
free(lus);
error:
return NULL;
*/
void trace_ust_destroy_session(struct ltt_ust_session *session)
{
+ struct agent *agt;
struct buffer_reg_uid *reg, *sreg;
+ struct lttng_ht_iter iter;
assert(session);
/* Cleaning up UST domain */
destroy_domain_global(&session->domain_global);
- agent_destroy(&session->agent);
+
+ cds_lfht_for_each_entry(session->agents->ht, &iter.iter, agt, node.node) {
+ lttng_ht_del(session->agents, &iter);
+ agent_destroy(agt);
+ }
/* Cleanup UID buffer registry object(s). */
cds_list_for_each_entry_safe(reg, sreg, &session->buffer_reg_uid_list,
struct ltt_ust_session {
uint64_t id; /* Unique identifier of session */
struct ltt_ust_domain_global domain_global;
- struct agent agent;
+ /* Hash table of agent indexed by agent domain. */
+ struct lttng_ht *agents;
/* UID/GID of the user owning the session */
uid_t uid;
gid_t gid;
struct lttng_event_exclusion *exclusion);
struct ltt_ust_channel *trace_ust_find_channel_by_name(struct lttng_ht *ht,
char *name);
+struct agent *trace_ust_find_agent(struct ltt_ust_session *session,
+ enum lttng_domain_type domain_type);
/*
* Create functions malloc() the data structure.
{
return;
}
+static inline
+struct agent *trace_ust_find_agent(struct ltt_ust_session *session,
+ enum lttng_domain_type domain_type)
+{
+ return NULL;
+}
#endif /* HAVE_LIBLTTNG_UST_CTL */