goto error;
}
+ /*
+ * Do we have a UST url set. If yes, this means we have both kernel and UST
+ * to print.
+ */
if (strlen(tmp_uurl) > 0) {
ret = snprintf(dst, size, "[K]: %s [data: %d] -- [U]: %s [data: %d]",
tmp_urls, kdata_port, tmp_uurl, udata_port);
} else {
- ret = snprintf(dst, size, "%s [data: %d]", tmp_urls, kdata_port);
+ int dport;
+ if (kuri) {
+ dport = kdata_port;
+ } else {
+ /* No kernel URI, use the UST port. */
+ dport = udata_port;
+ }
+ ret = snprintf(dst, size, "%s [data: %d]", tmp_urls, dport);
}
error:
assert(socket->fd >= 0);
pthread_mutex_lock(socket->lock);
- ret = kernel_consumer_send_session(socket->fd, session);
+ ret = kernel_consumer_send_session(socket, session);
pthread_mutex_unlock(socket->lock);
if (ret < 0) {
ret = LTTNG_ERR_KERN_CONSUMER_FAIL;
*/
static int send_consumer_relayd_socket(int domain, struct ltt_session *session,
struct lttng_uri *relayd_uri, struct consumer_output *consumer,
- int consumer_fd)
+ struct consumer_socket *consumer_sock)
{
int ret;
struct lttcomm_sock *sock = NULL;
}
/* Send relayd socket to consumer. */
- ret = consumer_send_relayd_socket(consumer_fd, sock,
- consumer, relayd_uri->stype);
+ ret = consumer_send_relayd_socket(consumer_sock, sock,
+ consumer, relayd_uri->stype, session->id);
if (ret < 0) {
ret = LTTNG_ERR_ENABLE_CONSUMER_FAIL;
goto close_sock;
}
+ /* Flag that the corresponding socket was sent. */
+ if (relayd_uri->stype == LTTNG_STREAM_CONTROL) {
+ consumer->dst.net.control_sock_sent = 1;
+ } else if (relayd_uri->stype == LTTNG_STREAM_DATA) {
+ consumer->dst.net.data_sock_sent = 1;
+ }
+
ret = LTTNG_OK;
/*
* session.
*/
static int send_consumer_relayd_sockets(int domain,
- struct ltt_session *session, struct consumer_output *consumer, int fd)
+ struct ltt_session *session, struct consumer_output *consumer,
+ struct consumer_socket *sock)
{
- int ret;
+ int ret = LTTNG_OK;
assert(session);
assert(consumer);
- /* Don't resend the sockets to the consumer. */
- if (consumer->dst.net.relayd_socks_sent) {
- ret = LTTNG_OK;
- goto error;
- }
-
/* Sending control relayd socket. */
- ret = send_consumer_relayd_socket(domain, session,
- &consumer->dst.net.control, consumer, fd);
- if (ret != LTTNG_OK) {
- goto error;
+ if (!consumer->dst.net.control_sock_sent) {
+ ret = send_consumer_relayd_socket(domain, session,
+ &consumer->dst.net.control, consumer, sock);
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
}
/* Sending data relayd socket. */
- ret = send_consumer_relayd_socket(domain, session,
- &consumer->dst.net.data, consumer, fd);
- if (ret != LTTNG_OK) {
- goto error;
+ if (!consumer->dst.net.data_sock_sent) {
+ ret = send_consumer_relayd_socket(domain, session,
+ &consumer->dst.net.data, consumer, sock);
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
}
- /* Flag that all relayd sockets were sent to the consumer. */
- consumer->dst.net.relayd_socks_sent = 1;
-
error:
return ret;
}
assert(socket->fd >= 0);
pthread_mutex_lock(socket->lock);
- send_consumer_relayd_sockets(LTTNG_DOMAIN_UST, session,
- usess->consumer, socket->fd);
+ ret = send_consumer_relayd_sockets(LTTNG_DOMAIN_UST, session,
+ usess->consumer, socket);
pthread_mutex_unlock(socket->lock);
if (ret != LTTNG_OK) {
goto error;
assert(socket->fd >= 0);
pthread_mutex_lock(socket->lock);
- send_consumer_relayd_sockets(LTTNG_DOMAIN_KERNEL, session,
- ksess->consumer, socket->fd);
+ ret = send_consumer_relayd_sockets(LTTNG_DOMAIN_KERNEL, session,
+ ksess->consumer, socket);
pthread_mutex_unlock(socket->lock);
if (ret != LTTNG_OK) {
goto error;
return ret;
}
+/*
+ * Start a kernel session by opening all necessary streams.
+ */
+static int start_kernel_session(struct ltt_kernel_session *ksess, int wpipe)
+{
+ int ret;
+ struct ltt_kernel_channel *kchan;
+
+ /* Open kernel metadata */
+ if (ksess->metadata == NULL) {
+ ret = kernel_open_metadata(ksess);
+ if (ret < 0) {
+ ret = LTTNG_ERR_KERN_META_FAIL;
+ goto error;
+ }
+ }
+
+ /* Open kernel metadata stream */
+ if (ksess->metadata_stream_fd < 0) {
+ ret = kernel_open_metadata_stream(ksess);
+ if (ret < 0) {
+ ERR("Kernel create metadata stream failed");
+ ret = LTTNG_ERR_KERN_STREAM_FAIL;
+ goto error;
+ }
+ }
+
+ /* For each channel */
+ cds_list_for_each_entry(kchan, &ksess->channel_list.head, list) {
+ if (kchan->stream_count == 0) {
+ ret = kernel_open_channel_stream(kchan);
+ if (ret < 0) {
+ ret = LTTNG_ERR_KERN_STREAM_FAIL;
+ goto error;
+ }
+ /* Update the stream global counter */
+ ksess->stream_count_global += ret;
+ }
+ }
+
+ /* Setup kernel consumer socket and send fds to it */
+ ret = init_kernel_tracing(ksess);
+ if (ret < 0) {
+ ret = LTTNG_ERR_KERN_START_FAIL;
+ goto error;
+ }
+
+ /* This start the kernel tracing */
+ ret = kernel_start_session(ksess);
+ if (ret < 0) {
+ ret = LTTNG_ERR_KERN_START_FAIL;
+ goto error;
+ }
+
+ /* Quiescent wait after starting trace */
+ kernel_wait_quiescent(kernel_tracer_fd);
+
+ ksess->started = 1;
+
+ ret = LTTNG_OK;
+
+error:
+ return ret;
+}
+
/*
* Command LTTNG_DISABLE_CHANNEL processed by the client thread.
*/
{
struct ltt_kernel_channel *kchan;
- /* Mandatory for a kernel channel. */
- assert(wpipe > 0);
-
kchan = trace_kernel_get_channel_by_name(attr->name,
session->kernel_session);
if (kchan == NULL) {
}
kernel_wait_quiescent(kernel_tracer_fd);
+
+ /*
+ * If the session was previously started, start as well this newly
+ * created kernel session so the events/channels enabled *after* the
+ * start actually work.
+ */
+ if (session->started && !session->kernel_session->started) {
+ ret = start_kernel_session(session->kernel_session, wpipe);
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
+ }
break;
}
case LTTNG_DOMAIN_UST:
} else {
ret = channel_ust_enable(usess, domain, uchan);
}
+
+ /* Start the UST session if the session was already started. */
+ if (session->started && !usess->start_trace) {
+ ret = ust_app_start_trace_all(usess);
+ if (ret < 0) {
+ ret = LTTNG_ERR_UST_START_FAIL;
+ goto error;
+ }
+ ret = LTTNG_OK;
+ usess->start_trace = 1;
+ }
break;
}
#if 0
* Command LTTNG_ADD_CONTEXT processed by the client thread.
*/
int cmd_add_context(struct ltt_session *session, int domain,
- char *channel_name, char *event_name, struct lttng_event_context *ctx)
+ char *channel_name, struct lttng_event_context *ctx, int kwpipe)
{
int ret;
switch (domain) {
case LTTNG_DOMAIN_KERNEL:
+ assert(session->kernel_session);
+
+ if (session->kernel_session->channel_count == 0) {
+ /* Create default channel */
+ ret = channel_kernel_create(session->kernel_session, NULL, kwpipe);
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
+ }
+
/* Add kernel context to kernel tracer */
- ret = context_kernel_add(session->kernel_session, ctx,
- event_name, channel_name);
+ ret = context_kernel_add(session->kernel_session, ctx, channel_name);
if (ret != LTTNG_OK) {
goto error;
}
case LTTNG_DOMAIN_UST:
{
struct ltt_ust_session *usess = session->ust_session;
-
assert(usess);
- ret = context_ust_add(usess, domain, ctx, event_name, channel_name);
- if (ret != LTTNG_OK) {
- goto error;
- }
- break;
- }
-#if 0
- case LTTNG_DOMAIN_UST_EXEC_NAME:
- case LTTNG_DOMAIN_UST_PID:
- case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
-#endif
- default:
- ret = LTTNG_ERR_UND;
- goto error;
- }
-
- ret = LTTNG_OK;
-
-error:
- return ret;
-}
-
-/*
- * Command LTTNG_SET_FILTER processed by the client thread.
- */
-int cmd_set_filter(struct ltt_session *session, int domain,
- char *channel_name, char *event_name,
- struct lttng_filter_bytecode *bytecode)
-{
- int ret;
+ unsigned int chan_count =
+ lttng_ht_get_count(usess->domain_global.channels);
+ if (chan_count == 0) {
+ struct lttng_channel *attr;
+ /* Create default channel */
+ attr = channel_new_default_attr(domain);
+ if (attr == NULL) {
+ ret = LTTNG_ERR_FATAL;
+ goto error;
+ }
- switch (domain) {
- case LTTNG_DOMAIN_KERNEL:
- ret = LTTNG_ERR_FATAL;
- break;
- case LTTNG_DOMAIN_UST:
- {
- struct ltt_ust_session *usess = session->ust_session;
+ ret = channel_ust_create(usess, domain, attr);
+ if (ret != LTTNG_OK) {
+ free(attr);
+ goto error;
+ }
+ free(attr);
+ }
- ret = filter_ust_set(usess, domain, bytecode, event_name, channel_name);
+ ret = context_ust_add(usess, domain, ctx, channel_name);
if (ret != LTTNG_OK) {
goto error;
}
error:
return ret;
-
}
-
/*
* Command LTTNG_ENABLE_EVENT processed by the client thread.
*/
int cmd_enable_event(struct ltt_session *session, int domain,
- char *channel_name, struct lttng_event *event, int wpipe)
+ char *channel_name, struct lttng_event *event,
+ struct lttng_filter_bytecode *filter, int wpipe)
{
int ret;
struct lttng_channel *attr;
}
/* At this point, the session and channel exist on the tracer */
- ret = event_ust_enable_tracepoint(usess, domain, uchan, event);
+ ret = event_ust_enable_tracepoint(usess, domain, uchan, event, filter);
if (ret != LTTNG_OK) {
goto error;
}
* Command LTTNG_ENABLE_ALL_EVENT processed by the client thread.
*/
int cmd_enable_event_all(struct ltt_session *session, int domain,
- char *channel_name, int event_type, int wpipe)
+ char *channel_name, int event_type,
+ struct lttng_filter_bytecode *filter, int wpipe)
{
int ret;
struct lttng_channel *attr;
switch (event_type) {
case LTTNG_EVENT_ALL:
case LTTNG_EVENT_TRACEPOINT:
- ret = event_ust_enable_all_tracepoints(usess, domain, uchan);
+ ret = event_ust_enable_all_tracepoints(usess, domain, uchan,
+ filter);
if (ret != LTTNG_OK) {
goto error;
}
int ret;
struct ltt_kernel_session *ksession;
struct ltt_ust_session *usess;
- struct ltt_kernel_channel *kchan;
assert(session);
/* Kernel tracing */
if (ksession != NULL) {
- /* Open kernel metadata */
- if (ksession->metadata == NULL) {
- ret = kernel_open_metadata(ksession);
- if (ret < 0) {
- ret = LTTNG_ERR_KERN_META_FAIL;
- goto error;
- }
- }
-
- /* Open kernel metadata stream */
- if (ksession->metadata_stream_fd < 0) {
- ret = kernel_open_metadata_stream(ksession);
- if (ret < 0) {
- ERR("Kernel create metadata stream failed");
- ret = LTTNG_ERR_KERN_STREAM_FAIL;
- goto error;
- }
- }
-
- /* For each channel */
- cds_list_for_each_entry(kchan, &ksession->channel_list.head, list) {
- if (kchan->stream_count == 0) {
- ret = kernel_open_channel_stream(kchan);
- if (ret < 0) {
- ret = LTTNG_ERR_KERN_STREAM_FAIL;
- goto error;
- }
- /* Update the stream global counter */
- ksession->stream_count_global += ret;
- }
- }
-
- /* Setup kernel consumer socket and send fds to it */
- ret = init_kernel_tracing(ksession);
- if (ret < 0) {
- ret = LTTNG_ERR_KERN_START_FAIL;
- goto error;
- }
-
- /* This start the kernel tracing */
- ret = kernel_start_session(ksession);
- if (ret < 0) {
- ret = LTTNG_ERR_KERN_START_FAIL;
+ ret = start_kernel_session(ksession, kernel_tracer_fd);
+ if (ret != LTTNG_OK) {
goto error;
}
-
- /* Quiescent wait after starting trace */
- kernel_wait_quiescent(kernel_tracer_fd);
}
/* Flag session that trace should start automatically */
}
}
+ session->started = 1;
+
ret = LTTNG_OK;
error:
}
kernel_wait_quiescent(kernel_tracer_fd);
+
+ ksession->started = 0;
}
if (usess) {
}
}
+ session->started = 0;
+
ret = LTTNG_OK;
error:
goto error;
}
- if (!session->start_consumer) {
- ret = LTTNG_ERR_NO_CONSUMER;
- goto error;
- }
-
/*
* This case switch makes sure the domain session has a temporary consumer
* so the URL can be set.
/*
* Don't send relayd socket if URI is NOT remote or if the relayd
- * sockets for the session are already sent.
+ * socket for the session was already sent.
*/
if (uris[i].dtype == LTTNG_DST_PATH ||
- consumer->dst.net.relayd_socks_sent) {
+ (uris[i].stype == LTTNG_STREAM_CONTROL &&
+ consumer->dst.net.control_sock_sent) ||
+ (uris[i].stype == LTTNG_STREAM_DATA &&
+ consumer->dst.net.data_sock_sent)) {
continue;
}
pthread_mutex_lock(socket->lock);
ret = send_consumer_relayd_socket(domain, session, &uris[i],
- consumer, socket->fd);
+ consumer, socket);
pthread_mutex_unlock(socket->lock);
if (ret != LTTNG_OK) {
rcu_read_unlock();
socket = consumer_allocate_socket(sock);
if (socket == NULL) {
+ ret = close(sock);
+ if (ret < 0) {
+ PERROR("close register consumer");
+ }
ret = LTTNG_ERR_FATAL;
- close(sock);
goto error;
}
goto error;
}
- if (!session->start_consumer) {
- ret = LTTNG_ERR_NO_CONSUMER;
- goto error;
- }
-
switch (domain) {
case 0:
assert(session->consumer);
break;
}
- /* Append default kernel trace dir to subdir */
- strncat(ksess->consumer->subdir, DEFAULT_KERNEL_TRACE_DIR,
- sizeof(ksess->consumer->subdir) -
- strlen(ksess->consumer->subdir) - 1);
-
/*
* @session-lock
* This is race free for now since the session lock is acquired before
* is valid.
*/
rcu_read_lock();
+ /* Destroy current consumer. We are about to replace it */
consumer_destroy_output(ksess->consumer);
rcu_read_unlock();
ksess->consumer = consumer;
break;
}
- /* Append default kernel trace dir to subdir */
- strncat(usess->consumer->subdir, DEFAULT_UST_TRACE_DIR,
- sizeof(usess->consumer->subdir) -
- strlen(usess->consumer->subdir) - 1);
-
/*
* @session-lock
* This is race free for now since the session lock is acquired before
* is valid.
*/
rcu_read_lock();
+ /* Destroy current consumer. We are about to replace it */
consumer_destroy_output(usess->consumer);
rcu_read_unlock();
usess->consumer = consumer;
break;
}
+ session->start_consumer = 1;
+
/* Enable it */
if (consumer) {
consumer->enabled = 1;
return ret;
}
+/*
+ * Command LTTNG_DATA_PENDING returning 0 if the data is NOT pending meaning
+ * ready for trace analysis (or anykind of reader) or else 1 for pending data.
+ */
+int cmd_data_pending(struct ltt_session *session)
+{
+ int ret;
+ struct ltt_kernel_session *ksess = session->kernel_session;
+ struct ltt_ust_session *usess = session->ust_session;
+
+ assert(session);
+
+ /* Session MUST be stopped to ask for data availability. */
+ if (session->enabled) {
+ ret = LTTNG_ERR_SESSION_STARTED;
+ goto error;
+ }
+
+ if (ksess && ksess->consumer) {
+ ret = consumer_is_data_pending(ksess->id, ksess->consumer);
+ if (ret == 1) {
+ /* Data is still being extracted for the kernel. */
+ goto error;
+ }
+ }
+
+ if (usess && usess->consumer) {
+ ret = consumer_is_data_pending(usess->id, usess->consumer);
+ if (ret == 1) {
+ /* Data is still being extracted for the kernel. */
+ goto error;
+ }
+ }
+
+ /* Data is ready to be read by a viewer */
+ ret = 0;
+
+error:
+ return ret;
+}
+
/*
* Init command subsystem.
*/