From: David Goulet Date: Mon, 28 Jul 2014 20:06:35 +0000 (-0400) Subject: Refactor JUL to agent namespace X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=commitdiff_plain;h=022d91ba14053d6093a6d6a1af02a345c6fd42d2 Refactor JUL to agent namespace The specific JUL concept has been removed and it is now "agent" objects. This is the first step to support multiple agents within the same subsystem. Signed-off-by: David Goulet --- diff --git a/src/bin/lttng-sessiond/Makefile.am b/src/bin/lttng-sessiond/Makefile.am index 5bd62e558..712a14e8c 100644 --- a/src/bin/lttng-sessiond/Makefile.am +++ b/src/bin/lttng-sessiond/Makefile.am @@ -27,14 +27,14 @@ lttng_sessiond_SOURCES = utils.c utils.h \ buffer-registry.c buffer-registry.h \ testpoint.h ht-cleanup.c \ snapshot.c snapshot.h \ - jul.c jul.h \ + agent.c agent.h \ save.h save.c \ load-session-thread.h load-session-thread.c if HAVE_LIBLTTNG_UST_CTL lttng_sessiond_SOURCES += trace-ust.c ust-registry.c ust-app.c \ ust-consumer.c ust-consumer.h ust-thread.c \ - ust-metadata.c ust-clock.h jul-thread.c jul-thread.h + ust-metadata.c ust-clock.h agent-thread.c agent-thread.h endif # Add main.c at the end for compile order diff --git a/src/bin/lttng-sessiond/agent-thread.c b/src/bin/lttng-sessiond/agent-thread.c new file mode 100644 index 000000000..da0171ba0 --- /dev/null +++ b/src/bin/lttng-sessiond/agent-thread.c @@ -0,0 +1,382 @@ +/* + * Copyright (C) 2013 - David Goulet + * + * 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. + * + * 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 _GNU_SOURCE +#include + +#include +#include +#include +#include + +#include + +#include "fd-limit.h" +#include "agent-thread.h" +#include "lttng-sessiond.h" +#include "session.h" +#include "utils.h" + +/* + * Note that there is not port here. It's set after this URI is parsed so we + * can let the user define a custom one. However, localhost is ALWAYS the + * default listening address. + */ +static const char *default_reg_uri = + "tcp://" DEFAULT_NETWORK_VIEWER_BIND_ADDRESS; + +/* + * Update agent application using the given socket. This is done just after + * registration was successful. + * + * 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) +{ + struct ltt_session *session, *stmp; + struct ltt_session_list *list; + + list = session_get_list(); + assert(list); + + session_lock_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); + } + session_unlock(session); + } + session_unlock_list(); +} + +/* + * Destroy a agent application by socket. + */ +static void destroy_agent_app(int sock) +{ + struct agent_app *app; + + assert(sock >= 0); + + /* + * Not finding an application is a very important error that should NEVER + * happen. The hash table deletion is ONLY done through this call even on + * thread cleanup. + */ + rcu_read_lock(); + app = agent_find_app_by_sock(sock); + assert(app); + rcu_read_unlock(); + + /* RCU read side lock is taken in this function call. */ + agent_delete_app(app); + + /* The application is freed in a RCU call but the socket is closed here. */ + agent_destroy_app(app); +} + +/* + * Cleanup remaining agent apps in the hash table. This should only be called in + * the exit path of the thread. + */ +static void clean_agent_apps_ht(void) +{ + struct lttng_ht_node_ulong *node; + struct lttng_ht_iter iter; + + DBG3("[agent-thread] Cleaning agent apps ht"); + + rcu_read_lock(); + cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, node, node) { + struct agent_app *app; + + app = caa_container_of(node, struct agent_app, node); + destroy_agent_app(app->sock->fd); + } + rcu_read_unlock(); +} + +/* + * Create and init socket from uri. + */ +static struct lttcomm_sock *init_tcp_socket(void) +{ + int ret; + struct lttng_uri *uri = NULL; + struct lttcomm_sock *sock = NULL; + + /* + * This should never fail since the URI is hardcoded and the port is set + * before this thread is launched. + */ + ret = uri_parse(default_reg_uri, &uri); + assert(ret); + assert(agent_tcp_port); + uri->port = agent_tcp_port; + + sock = lttcomm_alloc_sock_from_uri(uri); + uri_free(uri); + if (sock == NULL) { + ERR("[agent-thread] agent allocating TCP socket"); + goto error; + } + + ret = lttcomm_create_sock(sock); + if (ret < 0) { + goto error; + } + + ret = sock->ops->bind(sock); + if (ret < 0) { + WARN("Another session daemon is using this agent port. Agent support " + "will be deactivated to prevent interfering with the tracing."); + goto error; + } + + ret = sock->ops->listen(sock, -1); + if (ret < 0) { + goto error; + } + + DBG("[agent-thread] Listening on TCP port %u and socket %d", + agent_tcp_port, sock->fd); + + return sock; + +error: + if (sock) { + lttcomm_destroy_sock(sock); + } + return NULL; +} + +/* + * Close and destroy the given TCP socket. + */ +static void destroy_tcp_socket(struct lttcomm_sock *sock) +{ + assert(sock); + + DBG3("[agent-thread] Destroy TCP socket on port %u", agent_tcp_port); + + /* This will return gracefully if fd is invalid. */ + sock->ops->close(sock); + lttcomm_destroy_sock(sock); +} + +/* + * Handle a new agent registration using the reg socket. After that, a new + * agent application is added to the global hash table and attach to an UST app + * object. If r_app is not NULL, the created app is set to the pointer. + * + * Return the new FD created upon accept() on success or else a negative errno + * value. + */ +static int handle_registration(struct lttcomm_sock *reg_sock, + struct agent_app **r_app) +{ + int ret; + pid_t pid; + ssize_t size; + struct agent_app *app; + struct agent_register_msg msg; + struct lttcomm_sock *new_sock; + + assert(reg_sock); + + new_sock = reg_sock->ops->accept(reg_sock); + if (!new_sock) { + ret = -ENOTCONN; + goto error; + } + + size = new_sock->ops->recvmsg(new_sock, &msg, sizeof(msg), 0); + if (size < sizeof(msg)) { + ret = -errno; + goto error_socket; + } + pid = be32toh(msg.pid); + + DBG2("[agent-thread] New registration for pid %d on socket %d", pid, + new_sock->fd); + + app = agent_create_app(pid, new_sock); + if (!app) { + ret = -ENOMEM; + goto error_socket; + } + + /* + * Add before assigning the socket value to the UST app so it can be found + * concurrently. + */ + agent_add_app(app); + + /* + * We don't need to attach the agent app to the app. If we ever do so, we + * should consider both registration order of agent before app and app + * before agent. + */ + + if (r_app) { + *r_app = app; + } + + return new_sock->fd; + +error_socket: + new_sock->ops->close(new_sock); + lttcomm_destroy_sock(new_sock); +error: + return ret; +} + +/* + * This thread manage application notify communication. + */ +void *agent_thread_manage_registration(void *data) +{ + int i, ret, pollfd; + uint32_t revents, nb_fd; + struct lttng_poll_event events; + struct lttcomm_sock *reg_sock; + + DBG("[agent-thread] Manage agent application registration."); + + rcu_register_thread(); + rcu_thread_online(); + + /* Agent initialization call MUST be called before starting the thread. */ + assert(agent_apps_ht_by_sock); + + /* Create pollset with size 2, quit pipe and socket. */ + ret = sessiond_set_thread_pollset(&events, 2); + if (ret < 0) { + goto error_poll_create; + } + + reg_sock = init_tcp_socket(); + if (!reg_sock) { + goto error_tcp_socket; + } + + /* Add create valid TCP socket to poll set. */ + ret = lttng_poll_add(&events, reg_sock->fd, + LPOLLIN | LPOLLERR | LPOLLHUP | LPOLLRDHUP); + if (ret < 0) { + goto error; + } + + while (1) { + DBG3("[agent-thread] Manage agent polling on %d fds", + LTTNG_POLL_GETNB(&events)); + + /* Inifinite blocking call, waiting for transmission */ +restart: + ret = lttng_poll_wait(&events, -1); + if (ret < 0) { + /* + * Restart interrupted system call. + */ + if (errno == EINTR) { + goto restart; + } + goto error; + } + nb_fd = ret; + DBG3("[agent-thread] %d fd ready", nb_fd); + + for (i = 0; i < nb_fd; i++) { + /* Fetch once the poll data */ + revents = LTTNG_POLL_GETEV(&events, i); + pollfd = LTTNG_POLL_GETFD(&events, i); + + /* Thread quit pipe has been closed. Killing thread. */ + ret = sessiond_check_thread_quit_pipe(pollfd, revents); + if (ret) { + goto exit; + } + + /* + * Check first if this is a POLLERR since POLLIN is also included + * in an error value thus checking first. + */ + if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { + /* Removing from the poll set */ + ret = lttng_poll_del(&events, pollfd); + if (ret < 0) { + goto error; + } + + destroy_agent_app(pollfd); + } else if (revents & (LPOLLIN)) { + int new_fd; + struct agent_app *app = NULL; + + /* Pollin event of agent app socket should NEVER happen. */ + assert(pollfd == reg_sock->fd); + + new_fd = handle_registration(reg_sock, &app); + if (new_fd < 0) { + WARN("[agent-thread] agent registration failed. Ignoring."); + /* Somehow the communication failed. Just continue. */ + continue; + } + /* Should not have a NULL app on success. */ + assert(app); + + /* Only add poll error event to only detect shutdown. */ + ret = lttng_poll_add(&events, new_fd, + LPOLLERR | LPOLLHUP | LPOLLRDHUP); + if (ret < 0) { + destroy_agent_app(new_fd); + continue; + } + + /* Update newly registered app. */ + update_agent_app(new_fd); + + /* On failure, the poll will detect it and clean it up. */ + (void) agent_send_registration_done(app); + } else { + ERR("Unknown poll events %u for sock %d", revents, pollfd); + continue; + } + } + } + +exit: + /* Whatever happens, try to delete it and exit. */ + (void) lttng_poll_del(&events, reg_sock->fd); +error: + destroy_tcp_socket(reg_sock); +error_tcp_socket: + lttng_poll_clean(&events); +error_poll_create: + DBG("[agent-thread] is cleaning up and stopping."); + + if (agent_apps_ht_by_sock) { + clean_agent_apps_ht(); + lttng_ht_destroy(agent_apps_ht_by_sock); + } + + rcu_thread_offline(); + rcu_unregister_thread(); + return NULL; +} diff --git a/src/bin/lttng-sessiond/agent-thread.h b/src/bin/lttng-sessiond/agent-thread.h new file mode 100644 index 000000000..0a0b3682f --- /dev/null +++ b/src/bin/lttng-sessiond/agent-thread.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2013 - David Goulet + * + * 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. + * + * 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. + */ + +#ifndef LTTNG_SESSIOND_AGENT_THREAD_H +#define LTTNG_SESSIOND_AGENT_THREAD_H + +#ifdef HAVE_LIBLTTNG_UST_CTL + +void *agent_thread_manage_registration(void *data); + +#else /* HAVE_LIBLTTNG_UST_CTL */ + +static inline +void *agent_thread_manage_registration(void *data) +{ + return NULL; +} + +#endif /* HAVE_LIBLTTNG_UST_CTL */ + +#endif /* LTTNG_SESSIOND_AGENT_THREAD_H */ diff --git a/src/bin/lttng-sessiond/agent.c b/src/bin/lttng-sessiond/agent.c new file mode 100644 index 000000000..cf8264a30 --- /dev/null +++ b/src/bin/lttng-sessiond/agent.c @@ -0,0 +1,952 @@ +/* + * Copyright (C) 2013 - David Goulet + * + * 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. + * + * 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 _GNU_SOURCE +#include +#include + +#include +#include + +#include + +#include "agent.h" +#include "ust-app.h" +#include "utils.h" + +/* + * Match function for the events hash table lookup by name. + */ +static int ht_match_event_by_name(struct cds_lfht_node *node, + const void *_key) +{ + struct agent_event *event; + const struct agent_ht_key *key; + + assert(node); + assert(_key); + + event = caa_container_of(node, struct agent_event, node.node); + key = _key; + + /* Match 1 elements of the key: name. */ + + /* Event name */ + if (strncmp(event->name, key->name, sizeof(event->name)) != 0) { + goto no_match; + } + /* Match. */ + return 1; + +no_match: + return 0; +} + +/* + * Match function for the events hash table lookup by name and loglevel. + */ +static int ht_match_event(struct cds_lfht_node *node, + const void *_key) +{ + struct agent_event *event; + const struct agent_ht_key *key; + + assert(node); + assert(_key); + + event = caa_container_of(node, struct agent_event, node.node); + key = _key; + + /* Match 2 elements of the key: name and loglevel. */ + + /* Event name */ + if (strncmp(event->name, key->name, sizeof(event->name)) != 0) { + goto no_match; + } + + if (event->loglevel != key->loglevel) { + if (event->loglevel_type == LTTNG_EVENT_LOGLEVEL_ALL && + key->loglevel == 0 && event->loglevel == -1) { + goto match; + } + goto no_match; + } +match: + return 1; + +no_match: + return 0; +} + +/* + * Add unique agent event based on the event name and loglevel. + */ +static void add_unique_agent_event(struct lttng_ht *ht, + struct agent_event *event) +{ + struct cds_lfht_node *node_ptr; + struct agent_ht_key key; + + assert(ht); + assert(ht->ht); + assert(event); + + key.name = event->name; + key.loglevel = event->loglevel; + + 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); +} + +/* + * URCU delayed agent event reclaim. + */ +static void destroy_event_agent_rcu(struct rcu_head *head) +{ + struct lttng_ht_node_str *node = + caa_container_of(head, struct lttng_ht_node_str, head); + struct agent_event *event = + caa_container_of(node, struct agent_event, node); + + free(event); +} + +/* + * URCU delayed agent app reclaim. + */ +static void destroy_app_agent_rcu(struct rcu_head *head) +{ + struct lttng_ht_node_ulong *node = + caa_container_of(head, struct lttng_ht_node_ulong, head); + struct agent_app *app = + caa_container_of(node, struct agent_app, node); + + free(app); +} + +/* + * Communication with the agent. Send the message header to the given socket in + * big endian. + * + * Return 0 on success or else a negative errno message of sendmsg() op. + */ +static int send_header(struct lttcomm_sock *sock, uint64_t data_size, + uint32_t cmd, uint32_t cmd_version) +{ + int ret; + ssize_t size; + struct lttcomm_agent_hdr msg; + + assert(sock); + + memset(&msg, 0, sizeof(msg)); + msg.data_size = htobe64(data_size); + msg.cmd = htobe32(cmd); + msg.cmd_version = htobe32(cmd_version); + + size = sock->ops->sendmsg(sock, &msg, sizeof(msg), 0); + if (size < sizeof(msg)) { + ret = -errno; + goto error; + } + ret = 0; + +error: + return ret; +} + +/* + * Communication call with the agent. Send the payload to the given socket. The + * header MUST be sent prior to this call. + * + * Return 0 on success or else a negative errno value of sendmsg() op. + */ +static int send_payload(struct lttcomm_sock *sock, void *data, + size_t size) +{ + int ret; + ssize_t len; + + assert(sock); + assert(data); + + len = sock->ops->sendmsg(sock, data, size, 0); + if (len < size) { + ret = -errno; + goto error; + } + ret = 0; + +error: + return ret; +} + +/* + * Communication call with the agent. Receive reply from the agent using the + * given socket. + * + * Return 0 on success or else a negative errno value from recvmsg() op. + */ +static int recv_reply(struct lttcomm_sock *sock, void *buf, size_t size) +{ + int ret; + ssize_t len; + + assert(sock); + assert(buf); + + len = sock->ops->recvmsg(sock, buf, size, 0); + if (len < size) { + ret = -errno; + goto error; + } + ret = 0; + +error: + return ret; +} + +/* + * Internal event listing for a given app. Populate events. + * + * Return number of element in the list or else a negative LTTNG_ERR* code. + * On success, the caller is responsible for freeing the memory + * allocated for "events". + */ +static ssize_t list_events(struct agent_app *app, struct lttng_event **events) +{ + int ret, i, len = 0, offset = 0; + uint32_t nb_event; + size_t data_size; + struct lttng_event *tmp_events = NULL; + struct lttcomm_agent_list_reply *reply = NULL; + struct lttcomm_agent_list_reply_hdr reply_hdr; + + assert(app); + assert(app->sock); + assert(events); + + DBG2("Agent listing events for app pid: %d and socket %d", app->pid, + app->sock->fd); + + ret = send_header(app->sock, 0, AGENT_CMD_LIST, 0); + if (ret < 0) { + goto error_io; + } + + /* Get list header so we know how much we'll receive. */ + ret = recv_reply(app->sock, &reply_hdr, sizeof(reply_hdr)); + if (ret < 0) { + goto error_io; + } + + switch (be32toh(reply_hdr.ret_code)) { + case AGENT_RET_CODE_SUCCESS: + data_size = be32toh(reply_hdr.data_size) + sizeof(*reply); + break; + default: + ERR("Agent returned an unknown code: %" PRIu32, + be32toh(reply_hdr.ret_code)); + ret = LTTNG_ERR_FATAL; + goto error; + } + + reply = zmalloc(data_size); + if (!reply) { + ret = LTTNG_ERR_NOMEM; + goto error; + } + + /* Get the list with the appropriate data size. */ + ret = recv_reply(app->sock, reply, data_size); + if (ret < 0) { + goto error_io; + } + + nb_event = be32toh(reply->nb_event); + tmp_events = zmalloc(sizeof(*tmp_events) * nb_event); + if (!tmp_events) { + ret = LTTNG_ERR_NOMEM; + goto error; + } + + for (i = 0; i < nb_event; i++) { + offset += len; + strncpy(tmp_events[i].name, reply->payload + offset, + sizeof(tmp_events[i].name)); + tmp_events[i].pid = app->pid; + tmp_events[i].enabled = -1; + len = strlen(reply->payload + offset) + 1; + } + + *events = tmp_events; + + free(reply); + return nb_event; + +error_io: + ret = LTTNG_ERR_UST_LIST_FAIL; +error: + free(reply); + free(tmp_events); + return -ret; + +} + +/* + * Internal enable agent event on a agent application. This function + * communicates with the agent to enable a given event. + * + * Return LTTNG_OK on success or else a LTTNG_ERR* code. + */ +static int enable_event(struct agent_app *app, struct agent_event *event) +{ + int ret; + uint64_t data_size; + struct lttcomm_agent_enable msg; + struct lttcomm_agent_generic_reply reply; + + assert(app); + assert(app->sock); + assert(event); + + DBG2("Agent enabling event %s for app pid: %d and socket %d", event->name, + app->pid, app->sock->fd); + + data_size = sizeof(msg); + + ret = send_header(app->sock, data_size, AGENT_CMD_ENABLE, 0); + if (ret < 0) { + goto error_io; + } + + memset(&msg, 0, sizeof(msg)); + msg.loglevel = event->loglevel; + msg.loglevel_type = event->loglevel_type; + strncpy(msg.name, event->name, sizeof(msg.name)); + ret = send_payload(app->sock, &msg, sizeof(msg)); + if (ret < 0) { + goto error_io; + } + + ret = recv_reply(app->sock, &reply, sizeof(reply)); + if (ret < 0) { + goto error_io; + } + + switch (be32toh(reply.ret_code)) { + case AGENT_RET_CODE_SUCCESS: + break; + case AGENT_RET_CODE_UNKNOWN_NAME: + ret = LTTNG_ERR_UST_EVENT_NOT_FOUND; + goto error; + default: + ERR("Agent returned an unknown code: %" PRIu32, + be32toh(reply.ret_code)); + ret = LTTNG_ERR_FATAL; + goto error; + } + + return LTTNG_OK; + +error_io: + ret = LTTNG_ERR_UST_ENABLE_FAIL; +error: + return ret; +} + +/* + * Internal disable agent event call on a agent application. This function + * communicates with the agent to disable a given event. + * + * Return LTTNG_OK on success or else a LTTNG_ERR* code. + */ +static int disable_event(struct agent_app *app, struct agent_event *event) +{ + int ret; + uint64_t data_size; + struct lttcomm_agent_disable msg; + struct lttcomm_agent_generic_reply reply; + + assert(app); + assert(app->sock); + 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); + + 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; + } + + ret = recv_reply(app->sock, &reply, sizeof(reply)); + if (ret < 0) { + goto error_io; + } + + switch (be32toh(reply.ret_code)) { + case AGENT_RET_CODE_SUCCESS: + break; + case AGENT_RET_CODE_UNKNOWN_NAME: + ret = LTTNG_ERR_UST_EVENT_NOT_FOUND; + goto error; + default: + ERR("Agent returned an unknown code: %" PRIu32, + be32toh(reply.ret_code)); + ret = LTTNG_ERR_FATAL; + goto error; + } + + return LTTNG_OK; + +error_io: + ret = LTTNG_ERR_UST_DISABLE_FAIL; +error: + return ret; +} + +/* + * Send back the registration DONE command to a given agent application. + * + * Return 0 on success or else a negative value. + */ +int agent_send_registration_done(struct agent_app *app) +{ + assert(app); + assert(app->sock); + + DBG("Agent sending registration done to app socket %d", app->sock->fd); + + return send_header(app->sock, 0, AGENT_CMD_REG_DONE, 0); +} + +/* + * Enable agent event on every agent applications registered with the session + * daemon. + * + * Return LTTNG_OK on success or else a LTTNG_ERR* code. + */ +int agent_enable_event(struct agent_event *event) +{ + int ret; + struct agent_app *app; + struct lttng_ht_iter iter; + + assert(event); + + rcu_read_lock(); + + cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, app, + node.node) { + /* Enable event on agent application through TCP socket. */ + ret = enable_event(app, event); + if (ret != LTTNG_OK) { + goto error; + } + } + + event->enabled = 1; + ret = LTTNG_OK; + +error: + rcu_read_unlock(); + return ret; +} + +/* + * Disable agent event on every agent applications registered with the session + * daemon. + * + * Return LTTNG_OK on success or else a LTTNG_ERR* code. + */ +int agent_disable_event(struct agent_event *event) +{ + int ret; + struct agent_app *app; + struct lttng_ht_iter iter; + + assert(event); + + rcu_read_lock(); + + cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, app, + node.node) { + /* Enable event on agent application through TCP socket. */ + ret = disable_event(app, event); + if (ret != LTTNG_OK) { + goto error; + } + } + + event->enabled = 0; + ret = LTTNG_OK; + +error: + rcu_read_unlock(); + return ret; +} + +/* + * Ask every agent for the list of possible event. Events is allocated with the + * events of every agent application. + * + * Return the number of events or else a negative value. + */ +int agent_list_events(struct lttng_event **events) +{ + int ret; + size_t nbmem, count = 0; + struct agent_app *app; + struct lttng_event *tmp_events = NULL; + struct lttng_ht_iter iter; + + assert(events); + + nbmem = UST_APP_EVENT_LIST_SIZE; + tmp_events = zmalloc(nbmem * sizeof(*tmp_events)); + if (!tmp_events) { + PERROR("zmalloc agent list events"); + ret = -ENOMEM; + goto error; + } + + rcu_read_lock(); + cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, app, + node.node) { + ssize_t nb_ev; + struct lttng_event *agent_events; + + nb_ev = list_events(app, &agent_events); + if (nb_ev < 0) { + ret = nb_ev; + goto error_unlock; + } + + if (count + nb_ev > nbmem) { + /* In case the realloc fails, we free the memory */ + struct lttng_event *new_tmp_events; + size_t new_nbmem; + + new_nbmem = max_t(size_t, count + nb_ev, nbmem << 1); + DBG2("Reallocating agent event list from %zu to %zu entries", + nbmem, new_nbmem); + new_tmp_events = realloc(tmp_events, + new_nbmem * sizeof(*new_tmp_events)); + if (!new_tmp_events) { + PERROR("realloc agent events"); + ret = -ENOMEM; + free(agent_events); + goto error_unlock; + } + /* Zero the new memory */ + memset(new_tmp_events + nbmem, 0, + (new_nbmem - nbmem) * sizeof(*new_tmp_events)); + nbmem = new_nbmem; + tmp_events = new_tmp_events; + } + memcpy(tmp_events + count, agent_events, + nb_ev * sizeof(*tmp_events)); + free(agent_events); + count += nb_ev; + } + rcu_read_unlock(); + + ret = count; + *events = tmp_events; + return ret; + +error_unlock: + rcu_read_unlock(); +error: + free(tmp_events); + return ret; +} + +/* + * Create a agent app object using the given PID. + * + * 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 *app; + + assert(sock); + + app = zmalloc(sizeof(*app)); + if (!app) { + PERROR("zmalloc agent create"); + goto error; + } + + app->pid = pid; + app->sock = sock; + lttng_ht_node_init_ulong(&app->node, (unsigned long) app->sock->fd); + +error: + return app; +} + +/* + * Lookup agent app by socket in the global hash table. + * + * RCU read side lock MUST be acquired. + * + * Return object if found else NULL. + */ +struct agent_app *agent_find_app_by_sock(int sock) +{ + struct lttng_ht_node_ulong *node; + struct lttng_ht_iter iter; + struct agent_app *app; + + assert(sock >= 0); + + lttng_ht_lookup(agent_apps_ht_by_sock, (void *)((unsigned long) sock), &iter); + node = lttng_ht_iter_get_node_ulong(&iter); + if (node == NULL) { + goto error; + } + app = caa_container_of(node, struct agent_app, node); + + DBG3("Agent app pid %d found by sock %d.", app->pid, sock); + return app; + +error: + DBG3("Agent app NOT found by sock %d.", sock); + return NULL; +} + +/* + * Add agent application object to the global hash table. + */ +void agent_add_app(struct agent_app *app) +{ + assert(app); + + DBG3("Agent adding app sock: %d and pid: %d to ht", app->sock->fd, app->pid); + + rcu_read_lock(); + lttng_ht_add_unique_ulong(agent_apps_ht_by_sock, &app->node); + rcu_read_unlock(); +} + +/* + * Delete agent application from the global hash table. + */ +void agent_delete_app(struct agent_app *app) +{ + int ret; + struct lttng_ht_iter iter; + + assert(app); + + DBG3("Agent deleting app pid: %d and sock: %d", app->pid, app->sock->fd); + + iter.iter.node = &app->node.node; + rcu_read_lock(); + ret = lttng_ht_del(agent_apps_ht_by_sock, &iter); + rcu_read_unlock(); + assert(!ret); +} + +/* + * Destroy a agent application object by detaching it from its corresponding + * UST app if one is connected by closing the socket. Finally, perform a + * delayed memory reclaim. + */ +void agent_destroy_app(struct agent_app *app) +{ + assert(app); + + if (app->sock) { + app->sock->ops->close(app->sock); + lttcomm_destroy_sock(app->sock); + } + + call_rcu(&app->node.head, destroy_app_agent_rcu); +} + +/* + * Initialize an already allocated agent object. + * + * Return 0 on success or else a negative errno value. + */ +int agent_init(struct agent *agt) +{ + int ret; + + assert(agt); + + agt->events = lttng_ht_new(0, LTTNG_HT_TYPE_STRING); + if (!agt->events) { + ret = -ENOMEM; + goto error; + } + + return 0; + +error: + return ret; +} + +/* + * Create a newly allocated agent event data structure. If name is valid, it's + * copied into the created event. + * + * Return a new object else NULL on error. + */ +struct agent_event *agent_create_event(const char *name, + struct lttng_filter_bytecode *filter) +{ + struct agent_event *event; + + DBG3("Agent create new event with name %s", name); + + event = zmalloc(sizeof(*event)); + if (!event) { + goto error; + } + + if (name) { + strncpy(event->name, name, sizeof(event->name)); + event->name[sizeof(event->name) - 1] = '\0'; + lttng_ht_node_init_str(&event->node, event->name); + } + + if (filter) { + event->filter = filter; + } + +error: + return event; +} + +/* + * Unique add of a agent event to an agent object. + */ +void agent_add_event(struct agent_event *event, struct agent *agt) +{ + assert(event); + assert(agt); + assert(agt->events); + + DBG3("Agent adding event %s", event->name); + + rcu_read_lock(); + add_unique_agent_event(agt->events, event); + rcu_read_unlock(); + agt->being_used = 1; +} + +/* + * Find a agent event in the given agent using name. + * + * RCU read side lock MUST be acquired. + * + * Return object if found else NULL. + */ +struct agent_event *agent_find_event_by_name(const char *name, + 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); + + ht = agt->events; + key.name = name; + + cds_lfht_lookup(ht->ht, ht->hash_fct((void *) name, lttng_ht_seed), + ht_match_event_by_name, &key, &iter.iter); + node = lttng_ht_iter_get_node_str(&iter); + if (node == NULL) { + goto error; + } + + DBG3("Agent event found %s by name.", name); + return caa_container_of(node, struct agent_event, node); + +error: + DBG3("Agent NOT found by name %s.", name); + return NULL; +} + +/* + * Find a agent event in the given agent using name and loglevel. + * + * RCU read side lock MUST be acquired. + * + * Return object if found else NULL. + */ +struct agent_event *agent_find_event(const char *name, int loglevel, + 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); + + ht = agt->events; + key.name = name; + key.loglevel = loglevel; + + cds_lfht_lookup(ht->ht, ht->hash_fct((void *) name, lttng_ht_seed), + ht_match_event, &key, &iter.iter); + node = lttng_ht_iter_get_node_str(&iter); + if (node == NULL) { + goto error; + } + + DBG3("Agent event found %s.", name); + return caa_container_of(node, struct agent_event, node); + +error: + DBG3("Agent NOT found %s.", name); + return NULL; +} + +/* + * Free given agent event. This event must not be globally visible at this + * point (only expected to be used on failure just after event creation). After + * this call, the pointer is not usable anymore. + */ +void agent_destroy_event(struct agent_event *event) +{ + assert(event); + + free(event); +} + +/* + * Destroy an agent completely. Note that the given pointer is NOT freed + * thus a reference to static or stack data can be passed to this function. + */ +void agent_destroy(struct agent *agt) +{ + struct lttng_ht_node_str *node; + struct lttng_ht_iter iter; + + assert(agt); + + DBG3("Agent destroy"); + + /* + * Just ignore if no events hash table exists. This is possible if for + * instance an agent object was allocated but not initialized. + */ + if (!agt->events) { + return; + } + + rcu_read_lock(); + cds_lfht_for_each_entry(agt->events->ht, &iter.iter, node, node) { + int ret; + struct agent_event *event; + + /* + * When destroying an event, we have to try to disable it on the agent + * side so the event stops generating data. The return value is not + * important since we have to continue anyway destroying the object. + */ + event = caa_container_of(node, struct agent_event, node); + (void) agent_disable_event(event, agt->domain); + + ret = lttng_ht_del(agt->events, &iter); + assert(!ret); + call_rcu(&node->head, destroy_event_agent_rcu); + } + rcu_read_unlock(); + + lttng_ht_destroy(agt->events); +} + +/* + * Initialize agent subsystem. + */ +int agent_setup(void) +{ + agent_apps_ht_by_sock = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG); + if (!agent_apps_ht_by_sock) { + return -1; + } + + return 0; +} + +/* + * Update a agent application (given socket) using the given agent. + * + * 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) +{ + int ret; + struct agent_app *app; + struct agent_event *event; + struct lttng_ht_iter iter; + + assert(agt); + assert(sock >= 0); + + DBG("Agent updating app socket %d", sock); + + rcu_read_lock(); + cds_lfht_for_each_entry(agt->events->ht, &iter.iter, event, node.node) { + /* Skip event if disabled. */ + if (!event->enabled) { + continue; + } + + 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); + + ret = enable_event(app, event); + if (ret != LTTNG_OK) { + DBG2("Agent update unable to enable event %s on app pid: %d sock %d", + event->name, app->pid, app->sock->fd); + /* Let's try the others here and don't assume the app is dead. */ + continue; + } + } + rcu_read_unlock(); +} diff --git a/src/bin/lttng-sessiond/agent.h b/src/bin/lttng-sessiond/agent.h new file mode 100644 index 000000000..404365e0a --- /dev/null +++ b/src/bin/lttng-sessiond/agent.h @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2013 - David Goulet + * + * 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. + * + * 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. + */ + +#ifndef LTTNG_SESSIOND_AGENT_H +#define LTTNG_SESSIOND_AGENT_H + +#define _GNU_SOURCE +#include + +#include +#include + +/* + * Hash table that contains the agent app created upon registration indexed by + * socket. + */ +struct lttng_ht *agent_apps_ht_by_sock; + +struct agent_ht_key { + const char *name; + int loglevel; +}; + +/* + * Registration message payload from an agent application. The PID is used to + * find back the corresponding UST app object so both socket can be linked. + */ +struct agent_register_msg { + uint32_t pid; +}; + +/* + * Agent application object created after a successful registration. This + * object is linked to its associated UST app by their PID through hash table + * lookups. + */ +struct agent_app { + /* + * PID sent during registration of a AGENT application. + */ + pid_t pid; + + /* + * AGENT TCP socket that was created upon registration. + */ + struct lttcomm_sock *sock; + + /* Initialized with the AGENT sock value. */ + struct lttng_ht_node_ulong node; +}; + +/* + * Agent event representation. + */ +struct agent_event { + /* Name of the event. */ + char name[LTTNG_SYMBOL_NAME_LEN]; + int loglevel; + enum lttng_loglevel_type loglevel_type; + + /* + * Tells if the event is enabled or not on the agent. + */ + unsigned int enabled:1; + + /* Hash table node of the agent domain object. */ + struct lttng_ht_node_str node; + + /* Bytecode filter associated with the event . NULL if none. */ + struct lttng_filter_bytecode *filter; +}; + +/* + * Agent object containing events enabled/disabled for it. + */ +struct agent { + /* + * This indicates if that domain is being used meaning if at least one + * event has been at some point in time added to it. This is used so when + * listing domains for a session, we can tell or not if the agent is + * actually enabled. + */ + unsigned int being_used:1; + /* Contains event indexed by name. */ + struct lttng_ht *events; +}; + +/* Setup agent subsystem. */ +int agent_setup(void); + +/* Initialize an already allocated agent domain. */ +int agent_init(struct agent *agt); +void agent_destroy(struct agent *agt); + +/* Agent event API. */ +struct agent_event *agent_create_event(const char *name, + struct lttng_filter_bytecode *filter); +void agent_add_event(struct agent_event *event, struct agent *agt); + +struct agent_event *agent_find_event(const char *name, int loglevel, + struct agent *agt); +struct agent_event *agent_find_event_by_name(const char *name, + struct agent *agt); +void agent_delete_event(struct agent_event *event, struct agent *agt); +void agent_destroy_event(struct agent_event *event); + +/* Agent app API. */ +struct agent_app *agent_create_app(pid_t pid, 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); +void agent_destroy_app(struct agent_app *app); +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); +void agent_update(struct agent *agt, int sock); +int agent_list_events(struct lttng_event **events); + +#endif /* LTTNG_SESSIOND_AGENT_H */ diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 0cc71303a..d518449c0 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -185,25 +185,25 @@ static void list_lttng_channels(int domain, struct ltt_session *session, } /* - * Create a list of JUL domain events. + * Create a list of agent domain events. * * Return number of events in list on success or else a negative value. */ -static int list_lttng_jul_events(struct jul_domain *dom, +static int list_lttng_agent_events(struct agent *agt, struct lttng_event **events) { int i = 0, ret = 0; unsigned int nb_event = 0; - struct jul_event *event; + struct agent_event *event; struct lttng_event *tmp_events; struct lttng_ht_iter iter; - assert(dom); + assert(agt); assert(events); - DBG3("Listing JUL events"); + DBG3("Listing agent events"); - nb_event = lttng_ht_get_count(dom->events); + nb_event = lttng_ht_get_count(agt->events); if (nb_event == 0) { ret = nb_event; goto error; @@ -211,13 +211,13 @@ static int list_lttng_jul_events(struct jul_domain *dom, tmp_events = zmalloc(nb_event * sizeof(*tmp_events)); if (!tmp_events) { - PERROR("zmalloc JUL events session"); + PERROR("zmalloc agent events session"); ret = -LTTNG_ERR_FATAL; goto error; } rcu_read_lock(); - cds_lfht_for_each_entry(dom->events->ht, &iter.iter, event, node.node) { + cds_lfht_for_each_entry(agt->events->ht, &iter.iter, event, node.node) { strncpy(tmp_events[i].name, event->name, sizeof(tmp_events[i].name)); tmp_events[i].name[sizeof(tmp_events[i].name) - 1] = '\0'; tmp_events[i].enabled = event->enabled; @@ -1077,7 +1077,7 @@ int cmd_disable_event(struct ltt_session *session, int domain, assert(usess); - ret = event_jul_disable(usess, event_name); + ret = event_agent_disable(usess, event_name); if (ret != LTTNG_OK) { goto error; } @@ -1182,7 +1182,7 @@ int cmd_disable_event_all(struct ltt_session *session, int domain, assert(usess); - ret = event_jul_disable_all(usess); + ret = event_agent_disable_all(usess); if (ret != LTTNG_OK) { goto error; } @@ -1474,7 +1474,7 @@ int cmd_enable_event(struct ltt_session *session, struct lttng_domain *domain, assert(usess); - /* Create the default JUL tracepoint. */ + /* Create the default tracepoint. */ memset(&uevent, 0, sizeof(uevent)); uevent.type = LTTNG_EVENT_TRACEPOINT; uevent.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL; @@ -1503,9 +1503,9 @@ int cmd_enable_event(struct ltt_session *session, struct lttng_domain *domain, /* The wild card * means that everything should be enabled. */ if (strncmp(event->name, "*", 1) == 0 && strlen(event->name) == 1) { - ret = event_jul_enable_all(usess, event, filter); + ret = event_agent_enable_all(usess, event, filter); } else { - ret = event_jul_enable(usess, event, filter); + ret = event_agent_enable(usess, event, filter); } if (ret != LTTNG_OK) { goto error; @@ -1695,7 +1695,7 @@ int cmd_enable_event_all(struct ltt_session *session, assert(usess); - /* Create the default JUL tracepoint. */ + /* Create the default tracepoint. */ uevent.type = LTTNG_EVENT_TRACEPOINT; uevent.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL; if (is_root) { @@ -1726,7 +1726,7 @@ int cmd_enable_event_all(struct ltt_session *session, strncpy(event.name, "*", sizeof(event.name)); event.name[sizeof(event.name) - 1] = '\0'; - ret = event_jul_enable_all(usess, &event, filter); + ret = event_agent_enable_all(usess, &event, filter); if (ret != LTTNG_OK) { goto error; } @@ -1775,7 +1775,7 @@ ssize_t cmd_list_tracepoints(int domain, struct lttng_event **events) } break; case LTTNG_DOMAIN_JUL: - nb_events = jul_list_events(events); + nb_events = agent_list_events(events); if (nb_events < 0) { ret = LTTNG_ERR_UST_LIST_FAIL; goto error; @@ -2380,7 +2380,7 @@ ssize_t cmd_list_domains(struct ltt_session *session, DBG3("Listing domains found UST global domain"); nb_dom++; - if (session->ust_session->domain_jul.being_used) { + if (session->ust_session->agent.being_used) { nb_dom++; } } @@ -2401,7 +2401,7 @@ ssize_t cmd_list_domains(struct ltt_session *session, (*domains)[index].buf_type = session->ust_session->buffer_type; index++; - if (session->ust_session->domain_jul.being_used) { + if (session->ust_session->agent.being_used) { (*domains)[index].type = LTTNG_DOMAIN_JUL; (*domains)[index].buf_type = session->ust_session->buffer_type; index++; @@ -2498,8 +2498,8 @@ ssize_t cmd_list_events(int domain, struct ltt_session *session, } case LTTNG_DOMAIN_JUL: if (session->ust_session) { - nb_event = list_lttng_jul_events( - &session->ust_session->domain_jul, events); + nb_event = list_lttng_agent_events( + &session->ust_session->agent, events); } break; default: diff --git a/src/bin/lttng-sessiond/event.c b/src/bin/lttng-sessiond/event.c index 2ccffae65..80721a788 100644 --- a/src/bin/lttng-sessiond/event.c +++ b/src/bin/lttng-sessiond/event.c @@ -617,30 +617,30 @@ error: } /* - * Enable all JUL event for a given UST session. + * Enable all agent event for a given UST session. * * Return LTTNG_OK on success or else a LTTNG_ERR* code. */ -int event_jul_enable_all(struct ltt_ust_session *usess, +int event_agent_enable_all(struct ltt_ust_session *usess, struct lttng_event *event, struct lttng_filter_bytecode *filter) { int ret; - struct jul_event *jevent; + struct agent_event *jevent; struct lttng_ht_iter iter; assert(usess); - DBG("Event JUL enabling ALL events for session %" PRIu64, usess->id); + DBG("Event agent enabling ALL events for session %" PRIu64, usess->id); - /* Enable event on JUL application through TCP socket. */ - ret = event_jul_enable(usess, event, filter); + /* Enable event on agent application through TCP socket. */ + ret = event_agent_enable(usess, 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->domain_jul.events->ht, &iter.iter, jevent, + cds_lfht_for_each_entry(usess->agent.events->ht, &iter.iter, jevent, node.node) { jevent->enabled = 1; } @@ -653,26 +653,26 @@ error: } /* - * Enable a single JUL event for a given UST session. + * Enable a single agent event for a given UST session. * * Return LTTNG_OK on success or else a LTTNG_ERR* code. */ -int event_jul_enable(struct ltt_ust_session *usess, struct lttng_event *event, +int event_agent_enable(struct ltt_ust_session *usess, struct lttng_event *event, struct lttng_filter_bytecode *filter) { int ret, created = 0; - struct jul_event *jevent; + struct agent_event *jevent; assert(usess); assert(event); - DBG("Event JUL enabling %s for session %" PRIu64 " with loglevel type %d " + 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 = jul_find_event(event->name, event->loglevel, &usess->domain_jul); + jevent = agent_find_event(event->name, event->loglevel, &usess->agent); if (!jevent) { - jevent = jul_create_event(event->name, filter); + jevent = agent_create_event(event->name, filter); if (!jevent) { ret = LTTNG_ERR_NOMEM; goto error; @@ -687,14 +687,14 @@ int event_jul_enable(struct ltt_ust_session *usess, struct lttng_event *event, goto end; } - ret = jul_enable_event(jevent); + ret = agent_enable_event(jevent); if (ret != LTTNG_OK) { goto error; } /* If the event was created prior to the enable, add it to the domain. */ if (created) { - jul_add_event(jevent, &usess->domain_jul); + agent_add_event(jevent, &usess->agent); } end: @@ -702,20 +702,20 @@ end: error: if (created) { - jul_destroy_event(jevent); + agent_destroy_event(jevent); } return ret; } /* - * Disable a single JUL event for a given UST session. + * Disable a single agent event for a given UST session. * * Return LTTNG_OK on success or else a LTTNG_ERR* code. */ -int event_jul_disable(struct ltt_ust_session *usess, char *event_name) +int event_agent_disable(struct ltt_ust_session *usess, char *event_name) { int ret; - struct jul_event *jevent; + struct agent_event *jevent; struct ltt_ust_event *uevent = NULL; struct ltt_ust_channel *uchan = NULL; char *ust_event_name; @@ -723,9 +723,9 @@ int event_jul_disable(struct ltt_ust_session *usess, char *event_name) assert(usess); assert(event_name); - DBG("Event JUL disabling %s for session %" PRIu64, event_name, usess->id); + DBG("Event agent disabling %s for session %" PRIu64, event_name, usess->id); - jevent = jul_find_event_by_name(event_name, &usess->domain_jul); + jevent = agent_find_event_by_name(event_name, &usess->agent); if (!jevent) { ret = LTTNG_ERR_UST_EVENT_NOT_FOUND; goto error; @@ -754,13 +754,13 @@ int event_jul_disable(struct ltt_ust_session *usess, char *event_name) } /* - * The loglevel is hardcoded with 0 here since the JUL ust event is set + * The loglevel is hardcoded with 0 here since the agent ust event is set * with the loglevel type to ALL thus the loglevel stays 0. The event's - * filter is the one handling the loglevel for JUL. + * filter is the one handling the loglevel for agent. */ uevent = trace_ust_find_event(uchan->events, ust_event_name, jevent->filter, 0, NULL); - /* If the JUL event exists, it must be available on the UST side. */ + /* If the agent event exists, it must be available on the UST side. */ assert(uevent); ret = ust_app_disable_event_glb(usess, uchan, uevent); @@ -769,7 +769,7 @@ int event_jul_disable(struct ltt_ust_session *usess, char *event_name) goto error; } - ret = jul_disable_event(jevent); + ret = agent_disable_event(jevent); if (ret != LTTNG_OK) { goto error; } @@ -781,20 +781,20 @@ error: return ret; } /* - * Disable all JUL event for a given UST session. + * Disable all agent event for a given UST session. * * Return LTTNG_OK on success or else a LTTNG_ERR* code. */ -int event_jul_disable_all(struct ltt_ust_session *usess) +int event_agent_disable_all(struct ltt_ust_session *usess) { int ret, do_disable = 0; - struct jul_event *jevent; + struct agent_event *jevent; struct lttng_ht_iter iter; assert(usess); - /* Enable event on JUL application through TCP socket. */ - ret = event_jul_disable(usess, "*"); + /* Enable event on agent application through TCP socket. */ + ret = event_agent_disable(usess, "*"); if (ret != LTTNG_OK) { if (ret == LTTNG_ERR_UST_EVENT_NOT_FOUND) { /* @@ -810,10 +810,10 @@ int event_jul_disable_all(struct ltt_ust_session *usess) /* Flag every event that they are now enabled. */ rcu_read_lock(); - cds_lfht_for_each_entry(usess->domain_jul.events->ht, &iter.iter, jevent, + cds_lfht_for_each_entry(usess->agent.events->ht, &iter.iter, jevent, node.node) { if (jevent->enabled && do_disable) { - ret = event_jul_disable(usess, jevent->name); + ret = event_agent_disable(usess, jevent->name); if (ret != LTTNG_OK) { rcu_read_unlock(); goto error; diff --git a/src/bin/lttng-sessiond/event.h b/src/bin/lttng-sessiond/event.h index 1297b6c48..7a87c3521 100644 --- a/src/bin/lttng-sessiond/event.h +++ b/src/bin/lttng-sessiond/event.h @@ -49,12 +49,12 @@ int event_ust_enable_all_tracepoints(struct ltt_ust_session *usess, int event_ust_disable_all_tracepoints(struct ltt_ust_session *usess, struct ltt_ust_channel *uchan); -int event_jul_enable(struct ltt_ust_session *usess, struct lttng_event *event, +int event_agent_enable(struct ltt_ust_session *usess, struct lttng_event *event, struct lttng_filter_bytecode *filter); -int event_jul_enable_all(struct ltt_ust_session *usess, +int event_agent_enable_all(struct ltt_ust_session *usess, struct lttng_event *event, struct lttng_filter_bytecode *filter); -int event_jul_disable(struct ltt_ust_session *usess, char *event_name); -int event_jul_disable_all(struct ltt_ust_session *usess); +int event_agent_disable(struct ltt_ust_session *usess, char *event_name); +int event_agent_disable_all(struct ltt_ust_session *usess); #endif /* _LTT_EVENT_H */ diff --git a/src/bin/lttng-sessiond/jul-thread.c b/src/bin/lttng-sessiond/jul-thread.c deleted file mode 100644 index 9859a1071..000000000 --- a/src/bin/lttng-sessiond/jul-thread.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright (C) 2013 - David Goulet - * - * 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. - * - * 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 _GNU_SOURCE -#include - -#include -#include -#include -#include - -#include - -#include "fd-limit.h" -#include "jul-thread.h" -#include "lttng-sessiond.h" -#include "session.h" -#include "utils.h" - -/* - * Note that there is not port here. It's set after this URI is parsed so we - * can let the user define a custom one. However, localhost is ALWAYS the - * default listening address. - */ -static const char *default_reg_uri = - "tcp://" DEFAULT_NETWORK_VIEWER_BIND_ADDRESS; - -/* - * Update JUL application using the given socket. This is done just after - * registration was successful. - * - * This is a quite heavy call in terms of locking since the session list lock - * AND session lock are acquired. - */ -static void update_jul_app(int sock) -{ - struct ltt_session *session, *stmp; - struct ltt_session_list *list; - - list = session_get_list(); - assert(list); - - session_lock_list(); - cds_list_for_each_entry_safe(session, stmp, &list->head, list) { - session_lock(session); - if (session->ust_session) { - jul_update(&session->ust_session->domain_jul, sock); - } - session_unlock(session); - } - session_unlock_list(); -} - -/* - * Destroy a JUL application by socket. - */ -static void destroy_jul_app(int sock) -{ - struct jul_app *app; - - assert(sock >= 0); - - /* - * Not finding an application is a very important error that should NEVER - * happen. The hash table deletion is ONLY done through this call even on - * thread cleanup. - */ - rcu_read_lock(); - app = jul_find_app_by_sock(sock); - assert(app); - rcu_read_unlock(); - - /* RCU read side lock is taken in this function call. */ - jul_delete_app(app); - - /* The application is freed in a RCU call but the socket is closed here. */ - jul_destroy_app(app); -} - -/* - * Cleanup remaining JUL apps in the hash table. This should only be called in - * the exit path of the thread. - */ -static void clean_jul_apps_ht(void) -{ - struct lttng_ht_node_ulong *node; - struct lttng_ht_iter iter; - - DBG3("[jul-thread] Cleaning JUL apps ht"); - - rcu_read_lock(); - cds_lfht_for_each_entry(jul_apps_ht_by_sock->ht, &iter.iter, node, node) { - struct jul_app *app; - - app = caa_container_of(node, struct jul_app, node); - destroy_jul_app(app->sock->fd); - } - rcu_read_unlock(); -} - -/* - * Create and init socket from uri. - */ -static struct lttcomm_sock *init_tcp_socket(void) -{ - int ret; - struct lttng_uri *uri = NULL; - struct lttcomm_sock *sock = NULL; - - /* - * This should never fail since the URI is hardcoded and the port is set - * before this thread is launched. - */ - ret = uri_parse(default_reg_uri, &uri); - assert(ret); - assert(jul_tcp_port); - uri->port = jul_tcp_port; - - sock = lttcomm_alloc_sock_from_uri(uri); - uri_free(uri); - if (sock == NULL) { - ERR("[jul-thread] JUL allocating TCP socket"); - goto error; - } - - ret = lttcomm_create_sock(sock); - if (ret < 0) { - goto error; - } - - ret = sock->ops->bind(sock); - if (ret < 0) { - WARN("Another session daemon is using this JUL port. JUL support " - "will be deactivated to prevent interfering with the tracing."); - goto error; - } - - ret = sock->ops->listen(sock, -1); - if (ret < 0) { - goto error; - } - - DBG("[jul-thread] Listening on TCP port %u and socket %d", jul_tcp_port, - sock->fd); - - return sock; - -error: - if (sock) { - lttcomm_destroy_sock(sock); - } - return NULL; -} - -/* - * Close and destroy the given TCP socket. - */ -static void destroy_tcp_socket(struct lttcomm_sock *sock) -{ - assert(sock); - - DBG3("[jul-thread] Destroy TCP socket on port %u", jul_tcp_port); - - /* This will return gracefully if fd is invalid. */ - sock->ops->close(sock); - lttcomm_destroy_sock(sock); -} - -/* - * Handle a new JUL registration using the reg socket. After that, a new JUL - * application is added to the global hash table and attach to an UST app - * object. If r_app is not NULL, the created app is set to the pointer. - * - * Return the new FD created upon accept() on success or else a negative errno - * value. - */ -static int handle_registration(struct lttcomm_sock *reg_sock, - struct jul_app **r_app) -{ - int ret; - pid_t pid; - ssize_t size; - struct jul_app *app; - struct jul_register_msg msg; - struct lttcomm_sock *new_sock; - - assert(reg_sock); - - new_sock = reg_sock->ops->accept(reg_sock); - if (!new_sock) { - ret = -ENOTCONN; - goto error; - } - - size = new_sock->ops->recvmsg(new_sock, &msg, sizeof(msg), 0); - if (size < sizeof(msg)) { - ret = -errno; - goto error_socket; - } - pid = be32toh(msg.pid); - - DBG2("[jul-thread] New registration for pid %d on socket %d", pid, - new_sock->fd); - - app = jul_create_app(pid, new_sock); - if (!app) { - ret = -ENOMEM; - goto error_socket; - } - - /* - * Add before assigning the socket value to the UST app so it can be found - * concurrently. - */ - jul_add_app(app); - - /* - * We don't need to attach the JUL app to the app. If we ever do - * so, we should consider both registration order of JUL before - * app and app before JUL. - */ - - if (r_app) { - *r_app = app; - } - - return new_sock->fd; - -error_socket: - new_sock->ops->close(new_sock); - lttcomm_destroy_sock(new_sock); -error: - return ret; -} - -/* - * This thread manage application notify communication. - */ -void *jul_thread_manage_registration(void *data) -{ - int i, ret, pollfd; - uint32_t revents, nb_fd; - struct lttng_poll_event events; - struct lttcomm_sock *reg_sock; - - DBG("[jul-thread] Manage JUL application registration."); - - rcu_register_thread(); - rcu_thread_online(); - - /* JUL initialization call MUST be called before starting the thread. */ - assert(jul_apps_ht_by_sock); - - /* Create pollset with size 2, quit pipe and socket. */ - ret = sessiond_set_thread_pollset(&events, 2); - if (ret < 0) { - goto error_poll_create; - } - - reg_sock = init_tcp_socket(); - if (!reg_sock) { - goto error_tcp_socket; - } - - /* Add create valid TCP socket to poll set. */ - ret = lttng_poll_add(&events, reg_sock->fd, - LPOLLIN | LPOLLERR | LPOLLHUP | LPOLLRDHUP); - if (ret < 0) { - goto error; - } - - while (1) { - DBG3("[jul-thread] Manage JUL polling on %d fds", - LTTNG_POLL_GETNB(&events)); - - /* Inifinite blocking call, waiting for transmission */ -restart: - ret = lttng_poll_wait(&events, -1); - if (ret < 0) { - /* - * Restart interrupted system call. - */ - if (errno == EINTR) { - goto restart; - } - goto error; - } - nb_fd = ret; - DBG3("[jul-thread] %d fd ready", nb_fd); - - for (i = 0; i < nb_fd; i++) { - /* Fetch once the poll data */ - revents = LTTNG_POLL_GETEV(&events, i); - pollfd = LTTNG_POLL_GETFD(&events, i); - - /* Thread quit pipe has been closed. Killing thread. */ - ret = sessiond_check_thread_quit_pipe(pollfd, revents); - if (ret) { - goto exit; - } - - /* - * Check first if this is a POLLERR since POLLIN is also included - * in an error value thus checking first. - */ - if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { - /* Removing from the poll set */ - ret = lttng_poll_del(&events, pollfd); - if (ret < 0) { - goto error; - } - - destroy_jul_app(pollfd); - } else if (revents & (LPOLLIN)) { - int new_fd; - struct jul_app *app = NULL; - - /* Pollin event of JUL app socket should NEVER happen. */ - assert(pollfd == reg_sock->fd); - - new_fd = handle_registration(reg_sock, &app); - if (new_fd < 0) { - WARN("[jul-thread] JUL registration failed. Ignoring."); - /* Somehow the communication failed. Just continue. */ - continue; - } - /* Should not have a NULL app on success. */ - assert(app); - - /* Only add poll error event to only detect shutdown. */ - ret = lttng_poll_add(&events, new_fd, - LPOLLERR | LPOLLHUP | LPOLLRDHUP); - if (ret < 0) { - destroy_jul_app(new_fd); - continue; - } - - /* Update newly registered app. */ - update_jul_app(new_fd); - - /* On failure, the poll will detect it and clean it up. */ - (void) jul_send_registration_done(app); - } else { - ERR("Unknown poll events %u for sock %d", revents, pollfd); - continue; - } - } - } - -exit: - /* Whatever happens, try to delete it and exit. */ - (void) lttng_poll_del(&events, reg_sock->fd); -error: - destroy_tcp_socket(reg_sock); -error_tcp_socket: - lttng_poll_clean(&events); -error_poll_create: - DBG("[jul-thread] is cleaning up and stopping."); - - if (jul_apps_ht_by_sock) { - clean_jul_apps_ht(); - lttng_ht_destroy(jul_apps_ht_by_sock); - } - - rcu_thread_offline(); - rcu_unregister_thread(); - return NULL; -} diff --git a/src/bin/lttng-sessiond/jul-thread.h b/src/bin/lttng-sessiond/jul-thread.h deleted file mode 100644 index 2f455da86..000000000 --- a/src/bin/lttng-sessiond/jul-thread.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2013 - David Goulet - * - * 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. - * - * 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. - */ - -#ifndef LTTNG_SESSIOND_JUL_THREAD_H -#define LTTNG_SESSIOND_JUL_THREAD_H - -#ifdef HAVE_LIBLTTNG_UST_CTL - -void *jul_thread_manage_registration(void *data); - -#else /* HAVE_LIBLTTNG_UST_CTL */ - -static inline -void *jul_thread_manage_registration(void *data) -{ - return NULL; -} - -#endif /* HAVE_LIBLTTNG_UST_CTL */ - -#endif /* LTTNG_SESSIOND_JUL_THREAD_H */ diff --git a/src/bin/lttng-sessiond/jul.c b/src/bin/lttng-sessiond/jul.c deleted file mode 100644 index bf4669b23..000000000 --- a/src/bin/lttng-sessiond/jul.c +++ /dev/null @@ -1,952 +0,0 @@ -/* - * Copyright (C) 2013 - David Goulet - * - * 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. - * - * 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 _GNU_SOURCE -#include -#include - -#include -#include - -#include - -#include "jul.h" -#include "ust-app.h" -#include "utils.h" - -/* - * Match function for the events hash table lookup by name. - */ -static int ht_match_event_by_name(struct cds_lfht_node *node, - const void *_key) -{ - struct jul_event *event; - const struct jul_ht_key *key; - - assert(node); - assert(_key); - - event = caa_container_of(node, struct jul_event, node.node); - key = _key; - - /* Match 1 elements of the key: name. */ - - /* Event name */ - if (strncmp(event->name, key->name, sizeof(event->name)) != 0) { - goto no_match; - } - /* Match. */ - return 1; - -no_match: - return 0; -} - -/* - * Match function for the events hash table lookup by name and loglevel. - */ -static int ht_match_event(struct cds_lfht_node *node, - const void *_key) -{ - struct jul_event *event; - const struct jul_ht_key *key; - - assert(node); - assert(_key); - - event = caa_container_of(node, struct jul_event, node.node); - key = _key; - - /* Match 2 elements of the key: name and loglevel. */ - - /* Event name */ - if (strncmp(event->name, key->name, sizeof(event->name)) != 0) { - goto no_match; - } - - if (event->loglevel != key->loglevel) { - if (event->loglevel_type == LTTNG_EVENT_LOGLEVEL_ALL && - key->loglevel == 0 && event->loglevel == -1) { - goto match; - } - goto no_match; - } -match: - return 1; - -no_match: - return 0; -} - -/* - * Add unique JUL event based on the event name and loglevel. - */ -static void add_unique_jul_event(struct lttng_ht *ht, struct jul_event *event) -{ - struct cds_lfht_node *node_ptr; - struct jul_ht_key key; - - assert(ht); - assert(ht->ht); - assert(event); - - key.name = event->name; - key.loglevel = event->loglevel; - - 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); -} - -/* - * URCU delayed JUL event reclaim. - */ -static void destroy_event_jul_rcu(struct rcu_head *head) -{ - struct lttng_ht_node_str *node = - caa_container_of(head, struct lttng_ht_node_str, head); - struct jul_event *event = - caa_container_of(node, struct jul_event, node); - - free(event); -} - -/* - * URCU delayed JUL app reclaim. - */ -static void destroy_app_jul_rcu(struct rcu_head *head) -{ - struct lttng_ht_node_ulong *node = - caa_container_of(head, struct lttng_ht_node_ulong, head); - struct jul_app *app = - caa_container_of(node, struct jul_app, node); - - free(app); -} - -/* - * Communication with Java agent. Send the message header to the given - * socket in big endian. - * - * Return 0 on success or else a negative errno message of sendmsg() op. - */ -static int send_header(struct lttcomm_sock *sock, uint64_t data_size, - uint32_t cmd, uint32_t cmd_version) -{ - int ret; - ssize_t size; - struct lttcomm_jul_hdr msg; - - assert(sock); - - memset(&msg, 0, sizeof(msg)); - msg.data_size = htobe64(data_size); - msg.cmd = htobe32(cmd); - msg.cmd_version = htobe32(cmd_version); - - size = sock->ops->sendmsg(sock, &msg, sizeof(msg), 0); - if (size < sizeof(msg)) { - ret = -errno; - goto error; - } - ret = 0; - -error: - return ret; -} - -/* - * Communication call with the Java agent. Send the payload to the given - * socket. The header MUST be sent prior to this call. - * - * Return 0 on success or else a negative errno value of sendmsg() op. - */ -static int send_payload(struct lttcomm_sock *sock, void *data, - size_t size) -{ - int ret; - ssize_t len; - - assert(sock); - assert(data); - - len = sock->ops->sendmsg(sock, data, size, 0); - if (len < size) { - ret = -errno; - goto error; - } - ret = 0; - -error: - return ret; -} - -/* - * Communication call with the Java agent. Receive reply from the agent using - * the given socket. - * - * Return 0 on success or else a negative errno value from recvmsg() op. - */ -static int recv_reply(struct lttcomm_sock *sock, void *buf, size_t size) -{ - int ret; - ssize_t len; - - assert(sock); - assert(buf); - - len = sock->ops->recvmsg(sock, buf, size, 0); - if (len < size) { - ret = -errno; - goto error; - } - ret = 0; - -error: - return ret; -} - - -/* - * Internal event listing for a given app. Populate events. - * - * Return number of element in the list or else a negative LTTNG_ERR* code. - * On success, the caller is responsible for freeing the memory - * allocated for "events". - */ -static ssize_t list_events(struct jul_app *app, struct lttng_event **events) -{ - int ret, i, len = 0, offset = 0; - uint32_t nb_event; - size_t data_size; - struct lttng_event *tmp_events = NULL; - struct lttcomm_jul_list_reply *reply = NULL; - struct lttcomm_jul_list_reply_hdr reply_hdr; - - assert(app); - assert(app->sock); - assert(events); - - DBG2("JUL listing events for app pid: %d and socket %d", app->pid, - app->sock->fd); - - ret = send_header(app->sock, 0, JUL_CMD_LIST, 0); - if (ret < 0) { - goto error_io; - } - - /* Get list header so we know how much we'll receive. */ - ret = recv_reply(app->sock, &reply_hdr, sizeof(reply_hdr)); - if (ret < 0) { - goto error_io; - } - - switch (be32toh(reply_hdr.ret_code)) { - case JUL_RET_CODE_SUCCESS: - data_size = be32toh(reply_hdr.data_size) + sizeof(*reply); - break; - default: - ERR("Java agent returned an unknown code: %" PRIu32, - be32toh(reply_hdr.ret_code)); - ret = LTTNG_ERR_FATAL; - goto error; - } - - reply = zmalloc(data_size); - if (!reply) { - ret = LTTNG_ERR_NOMEM; - goto error; - } - - /* Get the list with the appropriate data size. */ - ret = recv_reply(app->sock, reply, data_size); - if (ret < 0) { - goto error_io; - } - - nb_event = be32toh(reply->nb_event); - tmp_events = zmalloc(sizeof(*tmp_events) * nb_event); - if (!tmp_events) { - ret = LTTNG_ERR_NOMEM; - goto error; - } - - for (i = 0; i < nb_event; i++) { - offset += len; - strncpy(tmp_events[i].name, reply->payload + offset, - sizeof(tmp_events[i].name)); - tmp_events[i].pid = app->pid; - tmp_events[i].enabled = -1; - len = strlen(reply->payload + offset) + 1; - } - - *events = tmp_events; - - free(reply); - return nb_event; - -error_io: - ret = LTTNG_ERR_UST_LIST_FAIL; -error: - free(reply); - free(tmp_events); - return -ret; - -} - -/* - * Internal enable JUL event on a JUL application. This function - * communicates with the Java agent to enable a given event (Logger name). - * - * Return LTTNG_OK on success or else a LTTNG_ERR* code. - */ -static int enable_event(struct jul_app *app, struct jul_event *event) -{ - int ret; - uint64_t data_size; - struct lttcomm_jul_enable msg; - struct lttcomm_jul_generic_reply reply; - - assert(app); - assert(app->sock); - assert(event); - - DBG2("JUL enabling event %s for app pid: %d and socket %d", event->name, - app->pid, app->sock->fd); - - data_size = sizeof(msg); - - ret = send_header(app->sock, data_size, JUL_CMD_ENABLE, 0); - if (ret < 0) { - goto error_io; - } - - memset(&msg, 0, sizeof(msg)); - msg.loglevel = event->loglevel; - msg.loglevel_type = event->loglevel_type; - strncpy(msg.name, event->name, sizeof(msg.name)); - ret = send_payload(app->sock, &msg, sizeof(msg)); - if (ret < 0) { - goto error_io; - } - - ret = recv_reply(app->sock, &reply, sizeof(reply)); - if (ret < 0) { - goto error_io; - } - - switch (be32toh(reply.ret_code)) { - case JUL_RET_CODE_SUCCESS: - break; - case JUL_RET_CODE_UNKNOWN_NAME: - ret = LTTNG_ERR_UST_EVENT_NOT_FOUND; - goto error; - default: - ERR("Java agent returned an unknown code: %" PRIu32, - be32toh(reply.ret_code)); - ret = LTTNG_ERR_FATAL; - goto error; - } - - return LTTNG_OK; - -error_io: - ret = LTTNG_ERR_UST_ENABLE_FAIL; -error: - return ret; -} - -/* - * Internal disable JUL event call on a JUL application. This function - * communicates with the Java agent to disable a given event (Logger name). - * - * Return LTTNG_OK on success or else a LTTNG_ERR* code. - */ -static int disable_event(struct jul_app *app, struct jul_event *event) -{ - int ret; - uint64_t data_size; - struct lttcomm_jul_disable msg; - struct lttcomm_jul_generic_reply reply; - - assert(app); - assert(app->sock); - assert(event); - - DBG2("JUL disabling event %s for app pid: %d and socket %d", event->name, - app->pid, app->sock->fd); - - data_size = sizeof(msg); - - ret = send_header(app->sock, data_size, JUL_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; - } - - ret = recv_reply(app->sock, &reply, sizeof(reply)); - if (ret < 0) { - goto error_io; - } - - switch (be32toh(reply.ret_code)) { - case JUL_RET_CODE_SUCCESS: - break; - case JUL_RET_CODE_UNKNOWN_NAME: - ret = LTTNG_ERR_UST_EVENT_NOT_FOUND; - goto error; - default: - ERR("Java agent returned an unknown code: %" PRIu32, - be32toh(reply.ret_code)); - ret = LTTNG_ERR_FATAL; - goto error; - } - - return LTTNG_OK; - -error_io: - ret = LTTNG_ERR_UST_DISABLE_FAIL; -error: - return ret; -} - -/* - * Send back the registration DONE command to a given JUL application. - * - * Return 0 on success or else a negative value. - */ -int jul_send_registration_done(struct jul_app *app) -{ - assert(app); - assert(app->sock); - - DBG("JUL sending registration done to app socket %d", app->sock->fd); - - return send_header(app->sock, 0, JUL_CMD_REG_DONE, 0); -} - -/* - * Enable JUL event on every JUL applications registered with the session - * daemon. - * - * Return LTTNG_OK on success or else a LTTNG_ERR* code. - */ -int jul_enable_event(struct jul_event *event) -{ - int ret; - struct jul_app *app; - struct lttng_ht_iter iter; - - assert(event); - - rcu_read_lock(); - - cds_lfht_for_each_entry(jul_apps_ht_by_sock->ht, &iter.iter, app, - node.node) { - /* Enable event on JUL application through TCP socket. */ - ret = enable_event(app, event); - if (ret != LTTNG_OK) { - goto error; - } - } - - event->enabled = 1; - ret = LTTNG_OK; - -error: - rcu_read_unlock(); - return ret; -} - -/* - * Disable JUL event on every JUL applications registered with the session - * daemon. - * - * Return LTTNG_OK on success or else a LTTNG_ERR* code. - */ -int jul_disable_event(struct jul_event *event) -{ - int ret; - struct jul_app *app; - struct lttng_ht_iter iter; - - assert(event); - - rcu_read_lock(); - - cds_lfht_for_each_entry(jul_apps_ht_by_sock->ht, &iter.iter, app, - node.node) { - /* Enable event on JUL application through TCP socket. */ - ret = disable_event(app, event); - if (ret != LTTNG_OK) { - goto error; - } - } - - event->enabled = 0; - ret = LTTNG_OK; - -error: - rcu_read_unlock(); - return ret; -} - -/* - * Ask every java agent for the list of possible event (logger name). Events is - * allocated with the events of every JUL application. - * - * Return the number of events or else a negative value. - */ -int jul_list_events(struct lttng_event **events) -{ - int ret; - size_t nbmem, count = 0; - struct jul_app *app; - struct lttng_event *tmp_events = NULL; - struct lttng_ht_iter iter; - - assert(events); - - nbmem = UST_APP_EVENT_LIST_SIZE; - tmp_events = zmalloc(nbmem * sizeof(*tmp_events)); - if (!tmp_events) { - PERROR("zmalloc jul list events"); - ret = -ENOMEM; - goto error; - } - - rcu_read_lock(); - cds_lfht_for_each_entry(jul_apps_ht_by_sock->ht, &iter.iter, app, - node.node) { - ssize_t nb_ev; - struct lttng_event *jul_events; - - nb_ev = list_events(app, &jul_events); - if (nb_ev < 0) { - ret = nb_ev; - goto error_unlock; - } - - if (count + nb_ev > nbmem) { - /* In case the realloc fails, we free the memory */ - struct lttng_event *new_tmp_events; - size_t new_nbmem; - - new_nbmem = max_t(size_t, count + nb_ev, nbmem << 1); - DBG2("Reallocating JUL event list from %zu to %zu entries", - nbmem, new_nbmem); - new_tmp_events = realloc(tmp_events, - new_nbmem * sizeof(*new_tmp_events)); - if (!new_tmp_events) { - PERROR("realloc JUL events"); - ret = -ENOMEM; - free(jul_events); - goto error_unlock; - } - /* Zero the new memory */ - memset(new_tmp_events + nbmem, 0, - (new_nbmem - nbmem) * sizeof(*new_tmp_events)); - nbmem = new_nbmem; - tmp_events = new_tmp_events; - } - memcpy(tmp_events + count, jul_events, - nb_ev * sizeof(*tmp_events)); - free(jul_events); - count += nb_ev; - } - rcu_read_unlock(); - - ret = count; - *events = tmp_events; - return ret; - -error_unlock: - rcu_read_unlock(); -error: - free(tmp_events); - return ret; -} - -/* - * Create a JUL app object using the given PID. - * - * Return newly allocated object or else NULL on error. - */ -struct jul_app *jul_create_app(pid_t pid, struct lttcomm_sock *sock) -{ - struct jul_app *app; - - assert(sock); - - app = zmalloc(sizeof(*app)); - if (!app) { - PERROR("zmalloc JUL create"); - goto error; - } - - app->pid = pid; - app->sock = sock; - lttng_ht_node_init_ulong(&app->node, (unsigned long) app->sock->fd); - -error: - return app; -} - -/* - * Lookup JUL app by socket in the global hash table. - * - * RCU read side lock MUST be acquired. - * - * Return object if found else NULL. - */ -struct jul_app *jul_find_app_by_sock(int sock) -{ - struct lttng_ht_node_ulong *node; - struct lttng_ht_iter iter; - struct jul_app *app; - - assert(sock >= 0); - - lttng_ht_lookup(jul_apps_ht_by_sock, (void *)((unsigned long) sock), &iter); - node = lttng_ht_iter_get_node_ulong(&iter); - if (node == NULL) { - goto error; - } - app = caa_container_of(node, struct jul_app, node); - - DBG3("JUL app pid %d found by sock %d.", app->pid, sock); - return app; - -error: - DBG3("JUL app NOT found by sock %d.", sock); - return NULL; -} - -/* - * Add JUL application object to a given hash table. - */ -void jul_add_app(struct jul_app *app) -{ - assert(app); - - DBG3("JUL adding app sock: %d and pid: %d to ht", app->sock->fd, app->pid); - - rcu_read_lock(); - lttng_ht_add_unique_ulong(jul_apps_ht_by_sock, &app->node); - rcu_read_unlock(); -} - -/* - * Delete JUL application from the global hash table. - */ -void jul_delete_app(struct jul_app *app) -{ - int ret; - struct lttng_ht_iter iter; - - assert(app); - - DBG3("JUL deleting app pid: %d and sock: %d", app->pid, app->sock->fd); - - iter.iter.node = &app->node.node; - rcu_read_lock(); - ret = lttng_ht_del(jul_apps_ht_by_sock, &iter); - rcu_read_unlock(); - assert(!ret); -} - -/* - * Destroy a JUL application object by detaching it from its corresponding UST - * app if one is connected by closing the socket. Finally, perform a - * delayed memory reclaim. - */ -void jul_destroy_app(struct jul_app *app) -{ - assert(app); - - if (app->sock) { - app->sock->ops->close(app->sock); - lttcomm_destroy_sock(app->sock); - } - - call_rcu(&app->node.head, destroy_app_jul_rcu); -} - -/* - * Initialize an already allocated JUL domain object. - * - * Return 0 on success or else a negative errno value. - */ -int jul_init_domain(struct jul_domain *dom) -{ - int ret; - - assert(dom); - - dom->events = lttng_ht_new(0, LTTNG_HT_TYPE_STRING); - if (!dom->events) { - ret = -ENOMEM; - goto error; - } - - return 0; - -error: - return ret; -} - -/* - * Create a newly allocated JUL event data structure. If name is valid, it's - * copied into the created event. - * - * Return a new object else NULL on error. - */ -struct jul_event *jul_create_event(const char *name, - struct lttng_filter_bytecode *filter) -{ - struct jul_event *event; - - DBG3("JUL create new event with name %s", name); - - event = zmalloc(sizeof(*event)); - if (!event) { - goto error; - } - - if (name) { - strncpy(event->name, name, sizeof(event->name)); - event->name[sizeof(event->name) - 1] = '\0'; - lttng_ht_node_init_str(&event->node, event->name); - } - - if (filter) { - event->filter = filter; - } - -error: - return event; -} - -/* - * Unique add of a JUL event to a given domain. - */ -void jul_add_event(struct jul_event *event, struct jul_domain *dom) -{ - assert(event); - assert(dom); - assert(dom->events); - - DBG3("JUL adding event %s to domain", event->name); - - rcu_read_lock(); - add_unique_jul_event(dom->events, event); - rcu_read_unlock(); - dom->being_used = 1; -} - -/* - * Find a JUL event in the given domain using name and loglevel. - * - * RCU read side lock MUST be acquired. - * - * Return object if found else NULL. - */ -struct jul_event *jul_find_event_by_name(const char *name, - struct jul_domain *dom) -{ - struct lttng_ht_node_str *node; - struct lttng_ht_iter iter; - struct lttng_ht *ht; - struct jul_ht_key key; - - assert(name); - assert(dom); - assert(dom->events); - - ht = dom->events; - key.name = name; - - cds_lfht_lookup(ht->ht, ht->hash_fct((void *) name, lttng_ht_seed), - ht_match_event_by_name, &key, &iter.iter); - node = lttng_ht_iter_get_node_str(&iter); - if (node == NULL) { - goto error; - } - - DBG3("JUL event found %s by name.", name); - return caa_container_of(node, struct jul_event, node); - -error: - DBG3("JUL NOT found by name %s.", name); - return NULL; -} - -/* - * Find a JUL event in the given domain using name and loglevel. - * - * RCU read side lock MUST be acquired. - * - * Return object if found else NULL. - */ -struct jul_event *jul_find_event(const char *name, - enum lttng_loglevel_jul loglevel, struct jul_domain *dom) -{ - struct lttng_ht_node_str *node; - struct lttng_ht_iter iter; - struct lttng_ht *ht; - struct jul_ht_key key; - - assert(name); - assert(dom); - assert(dom->events); - - ht = dom->events; - key.name = name; - key.loglevel = loglevel; - - cds_lfht_lookup(ht->ht, ht->hash_fct((void *) name, lttng_ht_seed), - ht_match_event, &key, &iter.iter); - node = lttng_ht_iter_get_node_str(&iter); - if (node == NULL) { - goto error; - } - - DBG3("JUL event found %s.", name); - return caa_container_of(node, struct jul_event, node); - -error: - DBG3("JUL NOT found %s.", name); - return NULL; -} - -/* - * Free given JUL event. This event must not be globally visible at this - * point (only expected to be used on failure just after event - * creation). After this call, the pointer is not usable anymore. - */ -void jul_destroy_event(struct jul_event *event) -{ - assert(event); - - free(event); -} - -/* - * Destroy a JUL domain completely. Note that the given pointer is NOT freed - * thus a reference to static or stack data can be passed to this function. - */ -void jul_destroy_domain(struct jul_domain *dom) -{ - struct lttng_ht_node_str *node; - struct lttng_ht_iter iter; - - assert(dom); - - DBG3("JUL destroy domain"); - - /* - * Just ignore if no events hash table exists. This is possible if for - * instance a JUL domain object was allocated but not initialized. - */ - if (!dom->events) { - return; - } - - rcu_read_lock(); - cds_lfht_for_each_entry(dom->events->ht, &iter.iter, node, node) { - int ret; - struct jul_event *event; - - /* - * When destroying an event, we have to try to disable it on the agent - * side so the event stops generating data. The return value is not - * important since we have to continue anyway destroying the object. - */ - event = caa_container_of(node, struct jul_event, node); - (void) jul_disable_event(event); - - ret = lttng_ht_del(dom->events, &iter); - assert(!ret); - call_rcu(&node->head, destroy_event_jul_rcu); - } - rcu_read_unlock(); - - lttng_ht_destroy(dom->events); -} - -/* - * Initialize JUL subsystem. - */ -int jul_init(void) -{ - jul_apps_ht_by_sock = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG); - if (!jul_apps_ht_by_sock) { - return -1; - } - - return 0; -} - -/* - * Update a JUL application (given socket) using the given domain. - * - * 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 jul_update(struct jul_domain *domain, int sock) -{ - int ret; - struct jul_app *app; - struct jul_event *event; - struct lttng_ht_iter iter; - - assert(domain); - assert(sock >= 0); - - DBG("JUL updating app socket %d", sock); - - rcu_read_lock(); - cds_lfht_for_each_entry(domain->events->ht, &iter.iter, event, node.node) { - /* Skip event if disabled. */ - if (!event->enabled) { - continue; - } - - app = jul_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); - - ret = enable_event(app, event); - if (ret != LTTNG_OK) { - DBG2("JUL update unable to enable event %s on app pid: %d sock %d", - event->name, app->pid, app->sock->fd); - /* Let's try the others here and don't assume the app is dead. */ - continue; - } - } - rcu_read_unlock(); -} diff --git a/src/bin/lttng-sessiond/jul.h b/src/bin/lttng-sessiond/jul.h deleted file mode 100644 index 0a0c8ef0e..000000000 --- a/src/bin/lttng-sessiond/jul.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2013 - David Goulet - * - * 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. - * - * 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. - */ - -#ifndef LTTNG_SESSIOND_JUL_H -#define LTTNG_SESSIOND_JUL_H - -#define _GNU_SOURCE -#include - -#include -#include - -/* - * Hash table that contains the JUL app created upon registration indexed by - * socket. - */ -struct lttng_ht *jul_apps_ht_by_sock; - -struct jul_ht_key { - const char *name; - enum lttng_loglevel_jul loglevel; -}; - -/* - * Registration message payload from a JUL application. The PID is used to find - * back the corresponding UST app object so both socket can be linked. - */ -struct jul_register_msg { - uint32_t pid; -}; - -/* - * JUL application object created after a successful registration. This - * object is linked to its associated UST app by their PID through hash - * table lookups. - */ -struct jul_app { - /* - * PID sent during registration of a JUL application. - */ - pid_t pid; - - /* - * JUL TCP socket that was created upon registration. - */ - struct lttcomm_sock *sock; - - /* Initialized with the JUL sock value. */ - struct lttng_ht_node_ulong node; -}; - -/* - * Java Util Logging event representation. - */ -struct jul_event { - /* - * Name of the event which is directly mapped to a Logger object name in - * the JUL API. - */ - char name[LTTNG_SYMBOL_NAME_LEN]; - enum lttng_loglevel_jul loglevel; - enum lttng_loglevel_type loglevel_type; - - /* - * Tells if the event is enabled or not on the JUL Agent. - */ - unsigned int enabled:1; - - /* - * Hash table nodes of the JUL domain. Indexed by name string. - */ - struct lttng_ht_node_str node; - - /* Bytecode filter associated with the event . NULL if none. */ - struct lttng_filter_bytecode *filter; -}; - -/* - * Top level data structure in a UST session containing JUL event name created - * for it. - */ -struct jul_domain { - /* - * This indicates if that domain is being used meaning if at least one - * event has been at some point in time added to it. This is used so when - * listing domains for a session, we can tell or not if the JUL is actually - * enabled. - */ - unsigned int being_used:1; - /* - * Contains JUL event indexed by name. - */ - struct lttng_ht *events; -}; - -/* Initialize JUL domain subsystem. */ -int jul_init(void); - -/* Initialize an already allocated JUL domain. */ -int jul_init_domain(struct jul_domain *dom); -void jul_destroy_domain(struct jul_domain *dom); - -/* JUL event API. */ -struct jul_event *jul_create_event(const char *name, - struct lttng_filter_bytecode *filter); -void jul_add_event(struct jul_event *event, struct jul_domain *dom); -struct jul_event *jul_find_event(const char *name, - enum lttng_loglevel_jul loglevel, struct jul_domain *dom); -struct jul_event *jul_find_event_by_name(const char *name, - struct jul_domain *dom); -void jul_delete_event(struct jul_event *event, struct jul_domain *dom); -void jul_destroy_event(struct jul_event *event); - -/* JUL app API. */ -struct jul_app *jul_create_app(pid_t pid, struct lttcomm_sock *sock); -void jul_add_app(struct jul_app *app); -void jul_delete_app(struct jul_app *app); -struct jul_app *jul_find_app_by_sock(int sock); -void jul_destroy_app(struct jul_app *app); -int jul_send_registration_done(struct jul_app *app); - -/* JUL action API */ -int jul_enable_event(struct jul_event *event); -int jul_disable_event(struct jul_event *event); -void jul_update(struct jul_domain *domain, int sock); -int jul_list_events(struct lttng_event **events); - -#endif /* LTTNG_SESSIOND_JUL_H */ diff --git a/src/bin/lttng-sessiond/lttng-sessiond.h b/src/bin/lttng-sessiond/lttng-sessiond.h index f3fb750a9..d0150123c 100644 --- a/src/bin/lttng-sessiond/lttng-sessiond.h +++ b/src/bin/lttng-sessiond/lttng-sessiond.h @@ -107,9 +107,9 @@ extern int ht_cleanup_pipe[2]; extern long page_size; /* - * Global set once in main(). JUL TCP port for registration. + * Global set once in main(). Agent TCP port for registration. */ -extern unsigned int jul_tcp_port; +extern unsigned int agent_tcp_port; /* * Section name to look for in the daemon configuration file. diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index fdc537603..61ddf905c 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -67,7 +67,7 @@ #include "health-sessiond.h" #include "testpoint.h" #include "ust-thread.h" -#include "jul-thread.h" +#include "agent-thread.h" #include "save.h" #include "load-session-thread.h" @@ -204,7 +204,7 @@ static pthread_t kernel_thread; static pthread_t dispatch_thread; static pthread_t health_thread; static pthread_t ht_cleanup_thread; -static pthread_t jul_reg_thread; +static pthread_t agent_reg_thread; static pthread_t load_session_thread; /* @@ -289,8 +289,8 @@ long page_size; /* Application health monitoring */ struct health_app *health_sessiond; -/* JUL TCP port for registration. Used by the JUL thread. */ -unsigned int jul_tcp_port = DEFAULT_JUL_TCP_PORT; +/* Agent TCP port for registration. Used by the agent thread. */ +unsigned int agent_tcp_port = DEFAULT_AGENT_TCP_PORT; /* Am I root or not. */ int is_root; /* Set to 1 if the daemon is running as root */ @@ -571,7 +571,7 @@ static void cleanup(void) (void) unlink(path); snprintf(path, PATH_MAX, "%s/%s", rundir, - DEFAULT_LTTNG_SESSIOND_JULPORT_FILE); + DEFAULT_LTTNG_SESSIOND_AGENTPORT_FILE); DBG("Removing %s", path); (void) unlink(path); @@ -4361,7 +4361,7 @@ static int set_option(int opt, const char *arg, const char *optname) ret = -ENOMEM; } break; - case 'J': /* JUL TCP port. */ + case 'J': /* Agent TCP port. */ { unsigned long v; @@ -4375,8 +4375,8 @@ static int set_option(int opt, const char *arg, const char *optname) ERR("Port overflow in --jul-tcp-port parameter: %s", arg); return -1; } - jul_tcp_port = (uint32_t) v; - DBG3("JUL TCP port set to non default: %u", jul_tcp_port); + agent_tcp_port = (uint32_t) v; + DBG3("Agent TCP port set to non default: %u", agent_tcp_port); break; } case 'l': @@ -4916,9 +4916,9 @@ error: } /* - * Write JUL TCP port using the rundir. + * Write agent TCP port using the rundir. */ -static void write_julport(void) +static void write_agent_port(void) { int ret; char path[PATH_MAX]; @@ -4926,18 +4926,18 @@ static void write_julport(void) assert(rundir); ret = snprintf(path, sizeof(path), "%s/" - DEFAULT_LTTNG_SESSIOND_JULPORT_FILE, rundir); + DEFAULT_LTTNG_SESSIOND_AGENTPORT_FILE, rundir); if (ret < 0) { - PERROR("snprintf julport path"); + PERROR("snprintf agent port path"); goto error; } /* - * Create TCP JUL port file in rundir. Return value is of no importance. + * Create TCP agent port file in rundir. Return value is of no importance. * The execution will continue even though we are not able to write the * file. */ - (void) utils_create_pid_file(jul_tcp_port, path); + (void) utils_create_pid_file(agent_tcp_port, path); error: return; @@ -5174,8 +5174,8 @@ int main(int argc, char **argv) */ ust_app_ht_alloc(); - /* Initialize JUL domain subsystem. */ - if ((ret = jul_init()) < 0) { + /* Initialize agent domain subsystem. */ + if ((ret = agent_setup()) < 0) { /* ENOMEM at this point. */ goto error; } @@ -5279,7 +5279,7 @@ int main(int argc, char **argv) } write_pidfile(); - write_julport(); + write_agent_port(); /* Initialize communication library */ lttcomm_init(); @@ -5357,12 +5357,12 @@ int main(int argc, char **argv) goto exit_apps_notify; } - /* Create JUL registration thread. */ - ret = pthread_create(&jul_reg_thread, NULL, - jul_thread_manage_registration, (void *) NULL); + /* Create agent registration thread. */ + ret = pthread_create(&agent_reg_thread, NULL, + agent_thread_manage_registration, (void *) NULL); if (ret != 0) { - PERROR("pthread_create JUL"); - goto exit_jul_reg; + PERROR("pthread_create agent"); + goto exit_agent_reg; } /* Don't start this thread if kernel tracing is not requested nor root */ @@ -5388,13 +5388,13 @@ int main(int argc, char **argv) } exit_kernel: - ret = pthread_join(jul_reg_thread, &status); + ret = pthread_join(agent_reg_thread, &status); if (ret != 0) { - PERROR("pthread_join JUL"); + PERROR("pthread_join agent"); goto error; /* join error, exit without cleanup */ } -exit_jul_reg: +exit_agent_reg: ret = pthread_join(apps_notify_thread, &status); if (ret != 0) { PERROR("pthread_join apps notify"); diff --git a/src/bin/lttng-sessiond/save.c b/src/bin/lttng-sessiond/save.c index 90b3a3b9c..e92ed8d88 100644 --- a/src/bin/lttng-sessiond/save.c +++ b/src/bin/lttng-sessiond/save.c @@ -1011,7 +1011,7 @@ end: static int save_ust_session(struct config_writer *writer, - struct ltt_session *session, int save_jul) + struct ltt_session *session, int save_agent) { int ret; struct ltt_ust_channel *ust_chan; @@ -1023,7 +1023,7 @@ int save_ust_session(struct config_writer *writer, assert(session); ret = config_writer_write_element_string(writer, config_element_type, - save_jul ? config_domain_type_jul : config_domain_type_ust); + save_agent ? config_domain_type_jul : config_domain_type_ust); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; @@ -1053,11 +1053,11 @@ int save_ust_session(struct config_writer *writer, rcu_read_lock(); cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht, &iter.iter, node, node) { - int jul_channel; + int agent_channel; ust_chan = caa_container_of(node, struct ltt_ust_channel, node); - jul_channel = !strcmp(DEFAULT_JUL_CHANNEL_NAME, ust_chan->name); - if (!(save_jul ^ jul_channel)) { + agent_channel = !strcmp(DEFAULT_JUL_CHANNEL_NAME, ust_chan->name); + if (!(save_agent ^ agent_channel)) { ret = save_ust_channel(writer, ust_chan, session->ust_session); if (ret) { rcu_read_unlock(); @@ -1139,7 +1139,7 @@ int save_domains(struct config_writer *writer, struct ltt_session *session) } if (session->ust_session && - session->ust_session->domain_jul.being_used) { + session->ust_session->agent.being_used) { ret = config_writer_open_element(writer, config_element_domain); if (ret) { diff --git a/src/bin/lttng-sessiond/trace-ust.c b/src/bin/lttng-sessiond/trace-ust.c index 96225a21b..9c22e3890 100644 --- a/src/bin/lttng-sessiond/trace-ust.c +++ b/src/bin/lttng-sessiond/trace-ust.c @@ -242,7 +242,7 @@ struct ltt_ust_session *trace_ust_create_session(uint64_t session_id) /* Alloc UST global domain channels' HT */ lus->domain_global.channels = lttng_ht_new(0, LTTNG_HT_TYPE_STRING); - ret = jul_init_domain(&lus->domain_jul); + ret = agent_init(&lus->agent); if (ret < 0) { goto error_consumer; } @@ -266,7 +266,7 @@ struct ltt_ust_session *trace_ust_create_session(uint64_t session_id) error_consumer: ht_cleanup_push(lus->domain_global.channels); - jul_destroy_domain(&lus->domain_jul); + agent_destroy(&lus->agent); free(lus); error: return NULL; @@ -720,7 +720,7 @@ void trace_ust_destroy_session(struct ltt_ust_session *session) /* Cleaning up UST domain */ destroy_domain_global(&session->domain_global); - jul_destroy_domain(&session->domain_jul); + agent_destroy(&session->agent); /* Cleanup UID buffer registry object(s). */ cds_list_for_each_entry_safe(reg, sreg, &session->buffer_reg_uid_list, diff --git a/src/bin/lttng-sessiond/trace-ust.h b/src/bin/lttng-sessiond/trace-ust.h index 86f8d40b1..d58e37121 100644 --- a/src/bin/lttng-sessiond/trace-ust.h +++ b/src/bin/lttng-sessiond/trace-ust.h @@ -27,7 +27,7 @@ #include #include "consumer.h" -#include "jul.h" +#include "agent.h" #include "ust-ctl.h" struct ltt_ust_ht_key { @@ -78,7 +78,7 @@ struct ltt_ust_domain_global { struct ltt_ust_session { uint64_t id; /* Unique identifier of session */ struct ltt_ust_domain_global domain_global; - struct jul_domain domain_jul; + struct agent agent; /* UID/GID of the user owning the session */ uid_t uid; gid_t gid; diff --git a/src/bin/lttng-sessiond/ust-app.h b/src/bin/lttng-sessiond/ust-app.h index f83e857cf..d1e260fd1 100644 --- a/src/bin/lttng-sessiond/ust-app.h +++ b/src/bin/lttng-sessiond/ust-app.h @@ -22,7 +22,7 @@ #include -#include "jul.h" +#include "agent.h" #include "trace-ust.h" #include "ust-registry.h" @@ -266,13 +266,14 @@ struct ust_app { * Hash table containing ust_app_channel indexed by channel objd. */ struct lttng_ht *ust_objd; + /* - * If this application is of the JUL domain and this is non negative then a - * lookup MUST be done to acquire a read side reference to the - * corresponding JUL app object. If the lookup fails, this should be set to - * a negative value indicating that the JUL application is gone. + * If this application is of the agent domain and this is non negative then + * a lookup MUST be done to acquire a read side reference to the + * corresponding agent app object. If the lookup fails, this should be set + * to a negative value indicating that the agent application is gone. */ - int jul_app_sock; + int agent_app_sock; }; #ifdef HAVE_LIBLTTNG_UST_CTL diff --git a/src/common/defaults.h b/src/common/defaults.h index c857cb756..1aecb30e5 100644 --- a/src/common/defaults.h +++ b/src/common/defaults.h @@ -88,7 +88,7 @@ #define DEFAULT_LTTNG_RUNDIR CONFIG_LTTNG_SYSTEM_RUNDIR #define DEFAULT_LTTNG_HOME_RUNDIR "%s/.lttng" #define DEFAULT_LTTNG_SESSIOND_PIDFILE "lttng-sessiond.pid" -#define DEFAULT_LTTNG_SESSIOND_JULPORT_FILE "jul.port" +#define DEFAULT_LTTNG_SESSIOND_AGENTPORT_FILE "jul.port" #define DEFAULT_LTTNG_SESSIOND_LOCKFILE "lttng-sessiond.lck" /* Default probes list */ @@ -233,15 +233,15 @@ #define DEFAULT_NETWORK_CONTROL_BIND_ADDRESS "0.0.0.0" #define DEFAULT_NETWORK_DATA_BIND_ADDRESS "0.0.0.0" #define DEFAULT_NETWORK_VIEWER_BIND_ADDRESS "localhost" -#define DEFAULT_JUL_BIND_ADDRESS "localhost" +#define DEFAULT_AGENT_BIND_ADDRESS "localhost" /* Default network ports for trace streaming support. */ #define DEFAULT_NETWORK_CONTROL_PORT 5342 #define DEFAULT_NETWORK_DATA_PORT 5343 #define DEFAULT_NETWORK_VIEWER_PORT 5344 -/* JUL registration TCP port. */ -#define DEFAULT_JUL_TCP_PORT 5345 +/* Agent registration TCP port. */ +#define DEFAULT_AGENT_TCP_PORT 5345 /* * If a thread stalls for this amount of time, it will be considered bogus (bad diff --git a/src/common/sessiond-comm/Makefile.am b/src/common/sessiond-comm/Makefile.am index c72c87fbc..fdffa401e 100644 --- a/src/common/sessiond-comm/Makefile.am +++ b/src/common/sessiond-comm/Makefile.am @@ -5,5 +5,5 @@ noinst_LTLIBRARIES = libsessiond-comm.la libsessiond_comm_la_SOURCES = sessiond-comm.c sessiond-comm.h \ unix.c unix.h inet.c inet.h inet6.c inet6.h \ - relayd.h jul.h + relayd.h agent.h libsessiond_comm_la_LIBADD = -lrt diff --git a/src/common/sessiond-comm/agent.h b/src/common/sessiond-comm/agent.h new file mode 100644 index 000000000..93ef7ac09 --- /dev/null +++ b/src/common/sessiond-comm/agent.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2013 - David Goulet + * + * 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. + * + * 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. + */ + +#ifndef AGENT_COMM +#define AGENT_COMM + +#define _GNU_SOURCE +#include + +#include + +/* + * Command value pass in the header. + */ +enum lttcomm_agent_command { + AGENT_CMD_LIST = 1, + AGENT_CMD_ENABLE = 2, + AGENT_CMD_DISABLE = 3, + AGENT_CMD_REG_DONE = 4, /* End registration process. */ +}; + +/* + * Return code from the Java agent. + */ +enum lttcomm_agent_ret_code { + AGENT_RET_CODE_SUCCESS = 1, + AGENT_RET_CODE_INVALID = 2, + AGENT_RET_CODE_UNKNOWN_NAME = 3, +}; + +/* + * Agent application communication header. + */ +struct lttcomm_agent_hdr { + uint64_t data_size; /* data size following this header */ + uint32_t cmd; /* Enum of agent command. */ + uint32_t cmd_version; /* command version */ +} LTTNG_PACKED; + +/* + * Enable event command payload. + */ +struct lttcomm_agent_enable { + uint32_t loglevel; + uint32_t loglevel_type; + char name[LTTNG_SYMBOL_NAME_LEN]; +} LTTNG_PACKED; + +/* + * Disable event command payload. + */ +struct lttcomm_agent_disable { + char name[LTTNG_SYMBOL_NAME_LEN]; +} LTTNG_PACKED; + +/* + * Generic reply coming from the Java Agent. + */ +struct lttcomm_agent_generic_reply { + uint32_t ret_code; +} LTTNG_PACKED; + +/* + * List command reply header. + */ +struct lttcomm_agent_list_reply_hdr { + uint32_t ret_code; + uint32_t data_size; +} LTTNG_PACKED; + +/* + * List command reply payload coming from the Java Agent. + */ +struct lttcomm_agent_list_reply { + uint32_t nb_event; + /* List of event name each of them ending by a NULL byte. */ + char payload[]; +} LTTNG_PACKED; + +#endif /* AGENT_COMM */ diff --git a/src/common/sessiond-comm/jul.h b/src/common/sessiond-comm/jul.h deleted file mode 100644 index f269fa816..000000000 --- a/src/common/sessiond-comm/jul.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2013 - David Goulet - * - * 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. - * - * 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. - */ - -#ifndef _JUL_COMM -#define _JUL_COMM - -#define _GNU_SOURCE -#include - -#include - -/* - * Command value pass in the header. - */ -enum lttcomm_jul_command { - JUL_CMD_LIST = 1, - JUL_CMD_ENABLE = 2, - JUL_CMD_DISABLE = 3, - JUL_CMD_REG_DONE = 4, /* End registration process. */ -}; - -/* - * Return code from the Java agent. - */ -enum lttcomm_jul_ret_code { - JUL_RET_CODE_SUCCESS = 1, - JUL_RET_CODE_INVALID = 2, - JUL_RET_CODE_UNKNOWN_NAME = 3, -}; - -/* - * JUL application communication header. - */ -struct lttcomm_jul_hdr { - uint64_t data_size; /* data size following this header */ - uint32_t cmd; /* Enum of JUL command. */ - uint32_t cmd_version; /* command version */ -} LTTNG_PACKED; - -/* - * Enable event command payload. - */ -struct lttcomm_jul_enable { - uint32_t loglevel; - uint32_t loglevel_type; - char name[LTTNG_SYMBOL_NAME_LEN]; -} LTTNG_PACKED; - -/* - * Disable event command payload. - */ -struct lttcomm_jul_disable { - char name[LTTNG_SYMBOL_NAME_LEN]; -} LTTNG_PACKED; - -/* - * Generic reply coming from the Java Agent. - */ -struct lttcomm_jul_generic_reply { - uint32_t ret_code; -} LTTNG_PACKED; - -/* - * List command reply header. - */ -struct lttcomm_jul_list_reply_hdr { - uint32_t ret_code; - uint32_t data_size; -} LTTNG_PACKED; - -/* - * List command reply payload coming from the Java Agent. - */ -struct lttcomm_jul_list_reply { - uint32_t nb_event; - /* List of event name each of them ending by a NULL byte. */ - char payload[]; -} LTTNG_PACKED; - -#endif /* _JUL_COMM */ diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am index ec8d22f62..dd3dd8c15 100644 --- a/tests/unit/Makefile.am +++ b/tests/unit/Makefile.am @@ -59,7 +59,7 @@ UST_DATA_TRACE=$(top_builddir)/src/bin/lttng-sessiond/trace-ust.o \ $(top_builddir)/src/bin/lttng-sessiond/fd-limit.o \ $(top_builddir)/src/bin/lttng-sessiond/session.o \ $(top_builddir)/src/bin/lttng-sessiond/snapshot.o \ - $(top_builddir)/src/bin/lttng-sessiond/jul.o \ + $(top_builddir)/src/bin/lttng-sessiond/agent.o \ $(top_builddir)/src/common/.libs/uri.o \ $(top_builddir)/src/common/.libs/utils.o \ $(top_builddir)/src/common/health/libhealth.la \