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 <dgoulet@efficios.com>
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
--- /dev/null
+/*
+ * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
+ *
+ * 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 <assert.h>
+
+#include <common/common.h>
+#include <common/sessiond-comm/sessiond-comm.h>
+#include <common/uri.h>
+#include <common/utils.h>
+
+#include <common/compat/endian.h>
+
+#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;
+}
--- /dev/null
+/*
+ * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
+ *
+ * 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 */
--- /dev/null
+/*
+ * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
+ *
+ * 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 <assert.h>
+#include <urcu/uatomic.h>
+
+#include <common/common.h>
+#include <common/sessiond-comm/agent.h>
+
+#include <common/compat/endian.h>
+
+#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();
+}
--- /dev/null
+/*
+ * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
+ *
+ * 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 <inttypes.h>
+
+#include <common/hashtable/hashtable.h>
+#include <lttng/lttng.h>
+
+/*
+ * 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 */
}
/*
- * 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;
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;
assert(usess);
- ret = event_jul_disable(usess, event_name);
+ ret = event_agent_disable(usess, event_name);
if (ret != LTTNG_OK) {
goto error;
}
assert(usess);
- ret = event_jul_disable_all(usess);
+ ret = event_agent_disable_all(usess);
if (ret != LTTNG_OK) {
goto error;
}
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;
/* 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;
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) {
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;
}
}
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;
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++;
}
}
(*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++;
}
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:
}
/*
- * 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;
}
}
/*
- * 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;
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:
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;
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;
}
/*
- * 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);
goto error;
}
- ret = jul_disable_event(jevent);
+ ret = agent_disable_event(jevent);
if (ret != LTTNG_OK) {
goto 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) {
/*
/* 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;
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 */
+++ /dev/null
-/*
- * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
- *
- * 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 <assert.h>
-
-#include <common/common.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/uri.h>
-#include <common/utils.h>
-
-#include <common/compat/endian.h>
-
-#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;
-}
+++ /dev/null
-/*
- * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
- *
- * 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 */
+++ /dev/null
-/*
- * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
- *
- * 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 <assert.h>
-#include <urcu/uatomic.h>
-
-#include <common/common.h>
-#include <common/sessiond-comm/jul.h>
-
-#include <common/compat/endian.h>
-
-#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();
-}
+++ /dev/null
-/*
- * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
- *
- * 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 <inttypes.h>
-
-#include <common/hashtable/hashtable.h>
-#include <lttng/lttng.h>
-
-/*
- * 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 */
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.
#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"
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;
/*
/* 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 */
(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);
ret = -ENOMEM;
}
break;
- case 'J': /* JUL TCP port. */
+ case 'J': /* Agent TCP port. */
{
unsigned long v;
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':
}
/*
- * 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];
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;
*/
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;
}
}
write_pidfile();
- write_julport();
+ write_agent_port();
/* Initialize communication library */
lttcomm_init();
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 */
}
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");
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;
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;
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();
}
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) {
/* 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;
}
error_consumer:
ht_cleanup_push(lus->domain_global.channels);
- jul_destroy_domain(&lus->domain_jul);
+ agent_destroy(&lus->agent);
free(lus);
error:
return NULL;
/* 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,
#include <common/defaults.h>
#include "consumer.h"
-#include "jul.h"
+#include "agent.h"
#include "ust-ctl.h"
struct ltt_ust_ht_key {
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;
#include <common/compat/uuid.h>
-#include "jul.h"
+#include "agent.h"
#include "trace-ust.h"
#include "ust-registry.h"
* 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
#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 */
#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
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
--- /dev/null
+/*
+ * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
+ *
+ * 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 <stdint.h>
+
+#include <lttng/lttng.h>
+
+/*
+ * 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 */
+++ /dev/null
-/*
- * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
- *
- * 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 <stdint.h>
-
-#include <lttng/lttng.h>
-
-/*
- * 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 */
$(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 \