compat/poll.h $(COMPAT) \
trace-kernel.c trace-kernel.h \
kernel-ctl.c kernel-ctl.h \
- ust-ctl.h ust-app.h trace-ust.h \
+ ust-ctl.h ust-app.h trace-ust.h \
context.c context.h \
channel.c channel.h \
event.c event.h \
futex.c futex.h \
shm.c shm.h \
session.c session.h \
- ltt-sessiond.h main.c \
../hashtable/rculfhash.c \
../hashtable/rculfhash.h \
../hashtable/hash.c ../hashtable/hash.h
if LTTNG_TOOLS_HAVE_UST
-ltt_sessiond_SOURCES += \
- trace-ust.c \
- ust-app.c
+ltt_sessiond_SOURCES += trace-ust.c ust-app.c ust-consumer.c ust-consumer.h
endif
+# Add main.c at the end for compile order
+ltt_sessiond_SOURCES += ltt-sessiond.h main.c
+
# link on liblttngctl for check if sessiond is already alive.
ltt_sessiond_LDADD = -lrt -lurcu-cds -lurcu \
$(top_builddir)/liblttng-sessiond-comm/liblttng-sessiond-comm.la \
/*
* Create UST channel and enable it on the tracer.
*/
-int channel_ust_create(struct ltt_ust_session *usession,
- struct lttng_channel *chan, int sock)
+int channel_ust_create(struct ltt_ust_session *usess,
+ struct lttng_channel *attr)
{
int ret;
- struct lttng_channel *attr = chan;
- struct ltt_ust_channel *suchan;
- struct lttng_ust_channel_attr uattr;
- struct object_data *obj;
-
- /* Creating channel attributes if needed */
- if (attr == NULL) {
- /* FIXME: this appears to be a memory leak */
- /* TODO: get default for other UST domains */
- attr = channel_new_default_attr(LTTNG_DOMAIN_UST);
- if (attr == NULL) {
- ret = LTTCOMM_FATAL;
+ struct ltt_ust_channel *uchan;
+ //struct lttng_ust_channel_attr uattr;
+ //struct object_data *obj;
+
+ uchan = trace_ust_find_channel_by_name(usess->domain_global.channels,
+ attr->name);
+ if (uchan == NULL) {
+ uchan = trace_ust_create_channel(attr, usess->pathname);
+ if (uchan == NULL) {
+ ret = LTTCOMM_UST_CHAN_FAIL;
goto error;
}
- }
-
- suchan = trace_ust_create_channel(attr, usession->path);
- if (suchan == NULL) {
- ret = LTTCOMM_UST_CHAN_FAIL;
+ rcu_read_lock();
+ hashtable_add_unique(usess->domain_global.channels, &uchan->node);
+ rcu_read_unlock();
+ } else {
+ ret = LTTCOMM_UST_CHAN_EXIST;
goto error;
}
- uattr.overwrite = attr->attr.overwrite;
- uattr.subbuf_size = attr->attr.subbuf_size;
- uattr.num_subbuf = attr->attr.num_subbuf;
- uattr.switch_timer_interval = attr->attr.switch_timer_interval;
- uattr.read_timer_interval = attr->attr.read_timer_interval;
- uattr.output = attr->attr.output;
- ret = ustctl_create_channel(sock, usession->handle,
- &uattr, &obj);
+ /* TODO: NOTIFY ust application to update */
+ /*
+ ret = ustctl_create_channel(sock, usession->handle, &uattr, &obj);
if (ret < 0) {
ret = LTTCOMM_UST_CHAN_FAIL;
goto error;
}
+ */
- suchan->attr.overwrite = uattr.overwrite;
- suchan->attr.subbuf_size = uattr.subbuf_size;
- suchan->attr.num_subbuf = uattr.num_subbuf;
- suchan->attr.switch_timer_interval = uattr.switch_timer_interval;
- suchan->attr.read_timer_interval = uattr.read_timer_interval;
- suchan->attr.output = uattr.output;
- suchan->handle = obj->handle;
- suchan->attr.shm_fd = obj->shm_fd;
- suchan->attr.wait_fd = obj->wait_fd;
- suchan->attr.memory_map_size = obj->memory_map_size;
- suchan->obj = obj;
+ /*
+ uchan->attr.overwrite = uattr.overwrite;
+ uchan->attr.subbuf_size = uattr.subbuf_size;
+ uchan->attr.num_subbuf = uattr.num_subbuf;
+ uchan->attr.switch_timer_interval = uattr.switch_timer_interval;
+ uchan->attr.read_timer_interval = uattr.read_timer_interval;
+ uchan->attr.output = uattr.output;
+ uchan->handle = obj->handle;
+ uchan->attr.shm_fd = obj->shm_fd;
+ uchan->attr.wait_fd = obj->wait_fd;
+ uchan->attr.memory_map_size = obj->memory_map_size;
+ uchan->obj = obj;
+ */
/* Add channel to session */
- cds_list_add(&suchan->list, &usession->channels.head);
- usession->channels.count++;
+ //rcu_read_lock();
+ //cds_list_add(&uchan->list, &usession->channels.head);
+ //usession->channels.count++;
+ //rcu_read_unlock();
- DBG2("Channel %s UST create successfully for sock:%d", suchan->name, sock);
+ //DBG2("Channel %s UST create successfully for sock:%d", uchan->name, sock);
ret = LTTCOMM_OK;
struct ltt_ust_channel *uchan, int sock)
{
int ret = LTTCOMM_OK;
+#ifdef DISABLE
struct object_data obj;
- obj.handle = uchan->handle;
obj.shm_fd = uchan->attr.shm_fd;
obj.wait_fd = uchan->attr.wait_fd;
obj.memory_map_size = uchan->attr.memory_map_size;
}
ret = LTTCOMM_OK;
end:
+#endif
return ret;
}
struct ltt_ust_channel *uchan, int sock)
{
int ret = LTTCOMM_OK;
+#ifdef DISABLE
struct object_data obj;
- obj.handle = uchan->handle;
obj.shm_fd = uchan->attr.shm_fd;
obj.wait_fd = uchan->attr.wait_fd;
obj.memory_map_size = uchan->attr.memory_map_size;
}
ret = LTTCOMM_OK;
end:
+#endif
return ret;
}
struct lttng_channel *chan, int kernel_pipe);
int channel_ust_create(struct ltt_ust_session *usession,
- struct lttng_channel *chan, int sock);
+ struct lttng_channel *chan);
int channel_ust_copy(struct ltt_ust_channel *dst,
struct ltt_ust_channel *src);
int channel_ust_disable(struct ltt_ust_session *usession,
#endif
#include "context.h"
+#include "hashtable.h"
#include "kernel-ctl.h"
/*
/*
* Add UST context to an event of a specific channel.
*/
+#ifdef DISABLE
static int add_ustctx_to_event(struct ltt_ust_session *ustsession,
struct lttng_ust_context *ustctx,
struct ltt_ust_channel *ustchan, char *event_name)
DBG("Add UST context to event %s", event_name);
- ustevent = trace_ust_get_event_by_name(event_name, ustchan);
+ ustevent = trace_ust_find_event_by_name(ustchan->events, event_name);
if (ustevent != NULL) {
ret = ustctl_add_context(ustsession->sock, ustctx,
ustevent->obj, &context_data);
error:
return ret;
}
+#endif
/*
* Add UST context to all channel.
* If event_name is specified, add context to event instead.
*/
static int add_ustctx_all_channels(struct ltt_ust_session *ustsession,
- struct lttng_ust_context *ustctx, char *event_name)
+ struct lttng_ust_context *ustctx, char *event_name,
+ struct cds_lfht *channels)
{
+#ifdef DISABLE
int ret, no_event = 0, found = 0;
struct ltt_ust_channel *ustchan;
struct object_data *context_data; /* FIXME: currently a memleak */
DBG("Adding ust context to all channels (event: %s)", event_name);
- /* Go over all channels */
- cds_list_for_each_entry(ustchan, &ustsession->channels.head, list) {
+ struct cds_lfht_node *node;
+ struct cds_lfht_iter iter;
+
+ rcu_read_lock();
+ hashtable_get_first(channels, &iter);
+ while ((node = hashtable_iter_get_node(&iter)) != NULL) {
+ ustchan = caa_container_of(node, struct ltt_ust_channel, node);
if (no_event) {
- ret = ustctl_add_context(ustsession->sock,
- ustctx, ustchan->obj, &context_data);
+ //ret = ustctl_add_context(ustsession->sock,
+ // ustctx, ustchan->obj, &context_data);
if (ret < 0) {
ret = LTTCOMM_UST_CONTEXT_FAIL;
goto error;
break;
}
}
+ hashtable_get_next(channels, &iter);
}
+ rcu_read_unlock();
if (!found && !no_event) {
ret = LTTCOMM_NO_EVENT;
error:
return ret;
+#endif
+ return 0;
}
/*
struct lttng_ust_context *ustctx,
struct ltt_ust_channel *ustchan, char *event_name)
{
+#ifdef DISABLE
int ret, no_event = 0, found = 0;
struct object_data *context_data; /* FIXME: currently a memleak */
ustchan->name, event_name);
if (no_event) {
- ret = ustctl_add_context(ustsession->sock, ustctx,
- ustchan->obj, &context_data);
+ //ret = ustctl_add_context(ustsession->sock, ustctx,
+ // ustchan->obj, &context_data);
if (ret < 0) {
ret = LTTCOMM_UST_CONTEXT_FAIL;
goto error;
error:
return ret;
+#endif
+ return 0;
}
/*
*/
int context_ust_add(struct ltt_ust_session *ustsession,
struct lttng_event_context *ctx, char *event_name,
- char *channel_name)
+ char *channel_name, int domain)
{
int ret;
+ struct cds_lfht *chan_ht = NULL;
struct ltt_ust_channel *ustchan;
struct lttng_ust_context ustctx;
/* Setup UST context structure */
ustctx.ctx = ctx->ctx;
+ switch (domain) {
+ case LTTNG_DOMAIN_UST:
+ chan_ht = ustsession->domain_global.channels;
+ break;
+ }
+
if (strlen(channel_name) == 0) {
- ret = add_ustctx_all_channels(ustsession, &ustctx, event_name);
+ ret = add_ustctx_all_channels(ustsession, &ustctx, event_name, chan_ht);
if (ret != LTTCOMM_OK) {
goto error;
}
} else {
/* Get UST channel */
- ustchan = trace_ust_get_channel_by_name(channel_name, ustsession);
+ ustchan = trace_ust_find_channel_by_name(chan_ht, channel_name);
if (ustchan == NULL) {
ret = LTTCOMM_UST_CHAN_NOT_FOUND;
goto error;
int context_kernel_add(struct ltt_kernel_session *ksession,
struct lttng_event_context *ctx, char *event_name, char *channel_name);
int context_ust_add(struct ltt_ust_session *ustsession,
- struct lttng_event_context *ctx, char *event_name, char *channel_name);
+ struct lttng_event_context *ctx, char *event_name,
+ char *channel_name, int domain);
#endif /* _LTT_CONTEXT_H */
#include "channel.h"
#include "event.h"
+#include "hashtable.h"
#include "kernel-ctl.h"
/*
/*
* Enable UST tracepoint event for a channel from a UST session.
*/
-int event_ust_enable_tracepoint(struct ltt_ust_session *ustsession,
- struct ltt_ust_channel *ustchan, struct lttng_event *event)
+#ifdef DISABLE
+int event_ust_enable_tracepoint(struct ltt_ust_session *usess,
+ struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent)
{
int ret;
- struct ltt_ust_event *ustevent;
- struct lttng_ust_event lttngustevent;
- struct object_data *object_event;
+ struct lttng_ust_event ltt_uevent;
+ struct object_data *obj_event;
- ustevent = trace_ust_get_event_by_name(event->name, ustchan);
- if (ustevent == NULL) {
- ustevent = trace_ust_create_event(event);
- if (ustevent == NULL) {
- ret = -1;
- goto end;
- }
- strncpy(lttngustevent.name, event->name,
- LTTNG_UST_SYM_NAME_LEN);
- lttngustevent.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
- /* TODO: adjust to other instrumentation types */
- lttngustevent.instrumentation = LTTNG_UST_TRACEPOINT;
- ret = ustctl_create_event(ustsession->sock, <tngustevent,
- ustchan->obj, &object_event);
- if (ret < 0) {
- if (ret == -EEXIST) {
- ret = LTTCOMM_KERN_EVENT_EXIST;
- } else {
- ret = LTTCOMM_KERN_ENABLE_FAIL;
- }
- goto end;
- }
- ustevent->obj = object_event;
- ustevent->handle = object_event->handle;
- ustevent->enabled = 1;
- /* Add event to event list */
- cds_list_add(&ustevent->list, &ustchan->events.head);
- ustchan->events.count++;
- } else if (ustevent->enabled == 0) {
- ret = ustctl_enable(ustsession->sock, ustevent->obj);
- if (ret < 0) {
- ret = LTTCOMM_KERN_ENABLE_FAIL;
- goto end;
- }
- ustevent->enabled = 1;
+ strncpy(ltt_uevent.name, uevent->attr.name, sizeof(ltt_uevent.name));
+ ltt_uevent.name[sizeof(ltt_uevent.name) - 1] = '\0';
+ /* TODO: adjust to other instrumentation types */
+ ltt_uevent.instrumentation = LTTNG_UST_TRACEPOINT;
+
+ ret = ustctl_create_event(app->key.sock, <t_uevent,
+ uchan->obj, &obj_event);
+ if (ret < 0) {
+ DBG("Error ustctl create event %s for app pid: %d, sock: %d ret %d",
+ uevent->attr.name, app->key.pid, app->key.sock, ret);
+ goto next;
}
+
+ uevent->obj = obj_event;
+ uevent->handle = obj_event->handle;
+ uevent->enabled = 1;
ret = LTTCOMM_OK;
end:
return ret;
}
+#endif
+#ifdef DISABLE
int event_ust_disable_tracepoint(struct ltt_ust_session *ustsession,
struct ltt_ust_channel *ustchan, char *event_name)
{
int ret;
struct ltt_ust_event *ustevent;
- ustevent = trace_ust_get_event_by_name(event_name, ustchan);
+ ustevent = trace_ust_find_event_by_name(ustchan->events, event_name);
if (ustevent == NULL) {
ret = LTTCOMM_NO_EVENT;
goto end;
}
- ret = ustctl_disable(ustsession->sock, ustevent->obj);
+ //ret = ustctl_disable(ustsession->sock, ustevent->obj);
if (ret < 0) {
ret = LTTCOMM_UST_ENABLE_FAIL;
goto end;
end:
return ret;
}
+#endif
struct ltt_kernel_channel *kchan, int kernel_tracer_fd);
int event_ust_enable_tracepoint(struct ltt_ust_session *ustsession,
- struct ltt_ust_channel *ustchan, struct lttng_event *event);
+ struct ltt_ust_channel *ustchan, struct ltt_ust_event *uevent);
int event_ust_disable_tracepoint(struct ltt_ust_session *ustsession,
struct ltt_ust_channel *ustchan, char *event_name);
}
return cds_lfht_new(hash_key, hash_compare_key, 0x42UL,
- CDS_LFHT_AUTO_RESIZE, size, NULL);
+ size, size, CDS_LFHT_AUTO_RESIZE, NULL);
}
struct cds_lfht *hashtable_new_str(unsigned long size)
}
return cds_lfht_new(hash_key_str, hash_compare_key_str, 0x42UL,
- CDS_LFHT_AUTO_RESIZE, size, NULL);
+ size, size, CDS_LFHT_AUTO_RESIZE, NULL);
}
struct cds_lfht_node *hashtable_iter_get_node(struct cds_lfht_iter *iter)
#include <lttng-sessiond-comm.h>
#include <lttng/lttng-consumer.h>
-#ifdef CONFIG_LTTNG_TOOLS_HAVE_UST
-#include <ust/lttng-ust-ctl.h>
-#else
-#include "lttng-ust-ctl.h"
-#endif
-
-
#include <lttngerr.h>
#include "channel.h"
#include "ust-app.h"
#include "ust-ctl.h"
#include "utils.h"
-#include "ust-ctl.h"
struct consumer_data {
enum lttng_consumer_type type;
return ret;
}
-/*
- * Send all stream fds of UST channel to the consumer.
- */
-static int send_ustconsumer_channel_streams(struct consumer_data *consumer_data,
- int sock, struct ltt_ust_channel *channel)
-{
- int ret, fds[2];
- struct ltt_ust_stream *stream;
- struct lttcomm_consumer_msg lum;
-
- DBG("Sending streams of channel %s to UST consumer",
- channel->name);
-
- /* Send channel */
- lum.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL;
- /*
- * We need to keep shm_fd open to make sure this key stays
- * unique within the session daemon.
- */
- lum.u.channel.channel_key = channel->obj->shm_fd;
- lum.u.channel.max_sb_size = channel->attr.subbuf_size;
- lum.u.channel.mmap_len = channel->obj->memory_map_size;
- DBG("Sending channel %d to consumer", lum.u.channel.channel_key);
- ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum));
- if (ret < 0) {
- perror("send consumer channel");
- goto error;
- }
- fds[0] = channel->obj->shm_fd;
- fds[1] = channel->obj->wait_fd;
- ret = lttcomm_send_fds_unix_sock(sock, fds, 2);
- if (ret < 0) {
- perror("send consumer channel ancillary data");
- goto error;
- }
-
- /* Send streams */
- cds_list_for_each_entry(stream, &channel->stream_list.head, list) {
- int fds[2];
-
- if (!stream->obj->shm_fd) {
- continue;
- }
- lum.cmd_type = LTTNG_CONSUMER_ADD_STREAM;
- lum.u.stream.channel_key = channel->obj->shm_fd;
- lum.u.stream.stream_key = stream->obj->shm_fd;
- lum.u.stream.state = LTTNG_CONSUMER_ACTIVE_STREAM;
- lum.u.stream.output = channel->attr.output;
- lum.u.stream.mmap_len = stream->obj->memory_map_size;
- strncpy(lum.u.stream.path_name, stream->pathname, PATH_MAX - 1);
- lum.u.stream.path_name[PATH_MAX - 1] = '\0';
- DBG("Sending stream %d to consumer", lum.u.stream.stream_key);
- ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum));
- if (ret < 0) {
- perror("send consumer stream");
- goto error;
- }
- fds[0] = stream->obj->shm_fd;
- fds[1] = stream->obj->wait_fd;
- ret = lttcomm_send_fds_unix_sock(sock, fds, 2);
- if (ret < 0) {
- perror("send consumer stream ancillary data");
- goto error;
- }
- }
-
- DBG("consumer channel streams sent");
-
- return 0;
-
-error:
- return ret;
-}
-
/*
* Send all stream fds of the kernel session to the consumer.
*/
return ret;
}
-/*
- * Send all stream fds of the UST session to the consumer.
- */
-static int send_ustconsumer_session_streams(struct consumer_data *consumer_data,
- struct ltt_ust_session *session)
-{
- int ret;
- struct ltt_ust_channel *chan;
- struct lttcomm_consumer_msg lum;
- int sock = session->consumer_fd;
-
- DBG("Sending metadata stream fd");
-
- /* Extra protection. It's NOT supposed to be set to 0 at this point */
- if (session->consumer_fd == 0) {
- session->consumer_fd = consumer_data->cmd_sock;
- }
-
- if (session->metadata->obj->shm_fd != 0) {
- int fds[2];
-
- /* Send metadata channel fd */
- lum.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL;
- lum.u.channel.channel_key = session->metadata->obj->shm_fd;
- lum.u.channel.max_sb_size = session->metadata->attr.subbuf_size;
- lum.u.channel.mmap_len = 0; /* for kernel */
- DBG("Sending metadata channel %d to consumer", lum.u.stream.stream_key);
- ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum));
- if (ret < 0) {
- perror("send consumer channel");
- goto error;
- }
- fds[0] = session->metadata->obj->shm_fd;
- fds[1] = session->metadata->obj->wait_fd;
- ret = lttcomm_send_fds_unix_sock(sock, fds, 2);
- if (ret < 0) {
- perror("send consumer metadata channel");
- goto error;
- }
-
- /* Send metadata stream fd */
- lum.cmd_type = LTTNG_CONSUMER_ADD_STREAM;
- lum.u.stream.channel_key = session->metadata->obj->shm_fd;
- lum.u.stream.stream_key = session->metadata->stream_obj->shm_fd;
- lum.u.stream.state = LTTNG_CONSUMER_ACTIVE_STREAM;
- lum.u.stream.output = DEFAULT_UST_CHANNEL_OUTPUT;
- lum.u.stream.mmap_len = session->metadata->stream_obj->memory_map_size;
- strncpy(lum.u.stream.path_name, session->metadata->pathname, PATH_MAX - 1);
- lum.u.stream.path_name[PATH_MAX - 1] = '\0';
- DBG("Sending metadata stream %d to consumer", lum.u.stream.stream_key);
- ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum));
- if (ret < 0) {
- perror("send consumer metadata stream");
- goto error;
- }
- fds[0] = session->metadata->stream_obj->shm_fd;
- fds[1] = session->metadata->stream_obj->wait_fd;
- ret = lttcomm_send_fds_unix_sock(sock, fds, 2);
- if (ret < 0) {
- perror("send consumer stream");
- goto error;
- }
- }
-
- cds_list_for_each_entry(chan, &session->channels.head, list) {
- ret = send_ustconsumer_channel_streams(consumer_data, sock, chan);
- if (ret < 0) {
- goto error;
- }
- }
-
- DBG("consumer fds (metadata and channel streams) sent");
-
- return 0;
-
-error:
- return ret;
-}
-
/*
* Notify UST applications using the shm mmap futex.
*/
lttcomm_connect_unix_sock(consumer_data->cmd_unix_sock_path);
if (consumer_data->cmd_sock < 0) {
sem_post(&consumer_data->sem);
- perror("consumer connect");
+ PERROR("consumer connect");
goto error;
}
/* Signal condition to tell that the kconsumerd is ready */
/* Setting up the consumer_data pid */
consumer_data->pid = ret;
- DBG2("consumer pid %d", consumer_data->pid);
+ DBG2("Consumer pid %d", consumer_data->pid);
pthread_mutex_unlock(&consumer_data->pid_mutex);
DBG2("Spawning consumer control thread");
return ret;
}
-/*
- * Init tracing by creating trace directory and sending fds ust consumer.
- */
-static int init_ust_tracing(struct ltt_ust_session *session)
-{
- int ret = 0;
-
- if (session->consumer_fds_sent == 0) {
- /*
- * Assign default ust consumer socket if no consumer assigned to the
- * ust session. At this point, it's NOT suppose to be 0 but this is
- * an extra security check.
- */
- if (session->consumer_fd == 0) {
- session->consumer_fd = ustconsumer_data.cmd_sock;
- }
-
- ret = send_ustconsumer_session_streams(&ustconsumer_data, session);
- if (ret < 0) {
- ret = LTTCOMM_UST_CONSUMER_FAIL;
- goto error;
- }
-
- session->consumer_fds_sent = 1;
- }
-
-error:
- return ret;
-}
-
/*
* Create an UST session and add it to the session ust list.
*/
struct lttng_domain *domain)
{
int ret;
+ unsigned int uid;
struct ltt_ust_session *lus = NULL;
- struct ust_app *app;
switch (domain->type) {
- case LTTNG_DOMAIN_UST_PID:
- app = ust_app_find_by_pid(domain->attr.pid);
- if (app == NULL) {
- ret = LTTCOMM_APP_NOT_FOUND;
- goto error;
- }
+ case LTTNG_DOMAIN_UST:
break;
default:
ret = LTTCOMM_UNKNOWN_DOMAIN;
DBG("Creating UST session");
- lus = trace_ust_create_session(session->path, domain->attr.pid, domain);
+ session_lock_list();
+ uid = session_list_ptr->count;
+ session_unlock_list();
+
+ lus = trace_ust_create_session(session->path, uid, domain);
if (lus == NULL) {
ret = LTTCOMM_UST_SESS_FAIL;
goto error;
}
- ret = mkdir_recursive(lus->path, S_IRWXU | S_IRWXG,
+ ret = mkdir_recursive(lus->pathname, S_IRWXU | S_IRWXG,
geteuid(), allowed_group());
if (ret < 0) {
if (ret != -EEXIST) {
/* The domain type dictate different actions on session creation */
switch (domain->type) {
- case LTTNG_DOMAIN_UST_PID:
- app = ust_app_find_by_pid(domain->attr.pid);
- if (app == NULL) {
- ret = LTTCOMM_APP_NOT_FOUND;
- goto error;
- }
- /* Create session on the UST tracer */
- ret = ustctl_create_session(app->key.sock, lus);
- if (ret < 0) {
- ret = LTTCOMM_UST_SESS_FAIL;
- goto error;
- }
-
- lus->handle = ret;
- break;
- case LTTNG_DOMAIN_UST:
- /* Create session on the UST tracer */
- ret = ustctl_create_session(app->key.sock, lus);
- if (ret < 0) {
- ret = LTTCOMM_UST_SESS_FAIL;
- goto error;
- }
- break;
- case LTTNG_DOMAIN_UST_EXEC_NAME:
- break;
- default:
- goto error;
+ case LTTNG_DOMAIN_UST:
+ /* No ustctl for the global UST domain */
+ break;
+ default:
+ goto error;
}
- lus->handle = ret;
- lus->sock = app->sock;
-
session->ust_session = lus;
- printf("%p\n", session->ust_session);
return LTTCOMM_OK;
{
struct ltt_ust_channel *uchan;
- DBG2("Enabling channel for LTTNG_DOMAIN_UST domain");
+ DBG2("Enabling channel for LTTNG_DOMAIN_UST");
+ /* Get channel in global UST domain HT */
uchan = trace_ust_find_channel_by_name(usess->domain_global.channels,
attr->name);
if (uchan == NULL) {
- uchan = trace_ust_create_channel(attr, usess->path);
+ uchan = trace_ust_create_channel(attr, usess->pathname);
if (uchan == NULL) {
ret = LTTCOMM_UST_CHAN_FAIL;
goto error;
rcu_read_lock();
hashtable_add_unique(usess->domain_global.channels, &uchan->node);
rcu_read_unlock();
+ DBG2("UST channel %s added to global domain HT", attr->name);
} else {
ret = LTTCOMM_UST_CHAN_EXIST;
goto error;
}
- /* TODO: Iterate over trace apps to enable that channel */
+ ret = ust_app_add_channel(usess, uchan);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
break;
}
break;
}
case LTTNG_DOMAIN_UST:
- {
- struct ltt_ust_session *ustsession;
-
- cds_list_for_each_entry(ustsession, &session->ust_session_list.head, list) {
- struct ltt_ust_channel *ustchan;
-
- ustchan = trace_ust_get_channel_by_name(channel_name,
- ustsession);
- if (ustchan == NULL) {
- ret = LTTCOMM_KERN_CHAN_NOT_FOUND;
- goto error;
- }
- ret = event_ust_disable_tracepoint(ustsession, ustchan, event_name);
- if (ret != LTTCOMM_OK) {
- goto error;
- }
-
- ustctl_wait_quiescent(ustsession->sock);
- }
- break;
- }
case LTTNG_DOMAIN_UST_EXEC_NAME:
case LTTNG_DOMAIN_UST_PID:
case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
break;
case LTTNG_DOMAIN_UST:
{
- struct ltt_ust_session *ustsession;
+ /*
+ struct ltt_ust_session *usess;
- cds_list_for_each_entry(ustsession, &session->ust_session_list.head, list) {
- /* Add UST context to UST tracer */
- ret = context_ust_add(ustsession, ctx,
- event_name, channel_name);
+ cds_list_for_each_entry(usess, &session->ust_session_list.head, list) {
+ ret = context_ust_add(usess, ctx,
+ event_name, channel_name, domain);
if (ret != LTTCOMM_OK) {
goto error;
}
}
break;
+ */
}
default:
/* TODO: UST other domains */
{
int ret;
struct lttng_channel *attr;
+ struct ltt_ust_session *usess = session->ust_session;
switch (domain) {
case LTTNG_DOMAIN_KERNEL:
goto error;
}
- ret = event_kernel_enable_tracepoint(session->kernel_session, kchan, event);
+ ret = event_kernel_enable_tracepoint(session->kernel_session, kchan,
+ event);
if (ret != LTTCOMM_OK) {
goto error;
}
}
case LTTNG_DOMAIN_UST:
{
- struct ltt_ust_session *ustsession;
-
- cds_list_for_each_entry(ustsession, &session->ust_session_list.head, list) {
- struct ltt_ust_channel *ustchan;
-
- ustchan = trace_ust_get_channel_by_name(channel_name,
- ustsession);
- if (ustchan == NULL) {
- attr = channel_new_default_attr(domain);
- if (attr == NULL) {
- ret = LTTCOMM_FATAL;
- goto error;
- }
- snprintf(attr->name, NAME_MAX, "%s", channel_name);
+ struct ltt_ust_channel *uchan;
+ struct ltt_ust_event *uevent;
- ret = channel_ust_create(ustsession,
- attr, ustsession->sock);
- if (ret != LTTCOMM_OK) {
- goto error;
- }
- }
+ uchan = trace_ust_find_channel_by_name(usess->domain_global.channels,
+ channel_name);
+ if (uchan == NULL) {
+ /* TODO: Create default channel */
+ ret = LTTCOMM_UST_CHAN_NOT_FOUND;
+ goto error;
+ }
- /* Get the newly created ust channel pointer */
- ustchan = trace_ust_get_channel_by_name(channel_name,
- ustsession);
- if (ustchan == NULL) {
- /* This sould not happen... */
+ uevent = trace_ust_find_event_by_name(uchan->events, event->name);
+ if (uevent == NULL) {
+ uevent = trace_ust_create_event(event);
+ if (uevent == NULL) {
ret = LTTCOMM_FATAL;
goto error;
}
+ }
- ret = event_ust_enable_tracepoint(ustsession, ustchan, event);
- if (ret != LTTCOMM_OK) {
- goto error;
- }
-
- ustctl_wait_quiescent(ustsession->sock);
+ ret = ust_app_add_event(usess, uchan, uevent);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_ENABLE_FAIL;
+ goto error;
}
break;
}
case LTTNG_DOMAIN_UST_PID:
case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
default:
- /* TODO: UST other domains */
ret = LTTCOMM_NOT_IMPLEMENTED;
goto error;
}
{
int ret;
struct ltt_kernel_session *ksession;
- struct ltt_ust_session *ustsession;
+ struct ltt_ust_session *usess = session->ust_session;
/* Short cut */
ksession = session->kernel_session;
kernel_wait_quiescent(kernel_tracer_fd);
}
- /* Start all UST traces */
- cds_list_for_each_entry(ustsession, &session->ust_session_list.head, list) {
- struct ltt_ust_channel *ustchan;
-
- /* Open kernel metadata */
- if (ustsession->metadata == NULL) {
- struct lttng_ust_channel_attr ustattr;
-
- /* Allocate UST metadata */
- ustsession->metadata = trace_ust_create_metadata(ustsession->path);
- if (ustsession->metadata == NULL) {
- ret = LTTCOMM_UST_META_FAIL;
- goto error;
- }
-
- ustattr.overwrite = ustsession->metadata->attr.overwrite;
- ustattr.subbuf_size = ustsession->metadata->attr.subbuf_size;
- ustattr.num_subbuf = ustsession->metadata->attr.num_subbuf;
- ustattr.switch_timer_interval = ustsession->metadata->attr.switch_timer_interval;
- ustattr.read_timer_interval = ustsession->metadata->attr.read_timer_interval;
- ustattr.output = ustsession->metadata->attr.output;
-
- /* UST tracer metadata creation */
- ret = ustctl_open_metadata(ustsession->sock,
- ustsession->handle, &ustattr,
- &ustsession->metadata->obj);
- if (ret < 0) {
- ret = LTTCOMM_UST_META_FAIL;
- goto error;
- }
- }
-
- /* Open UST metadata stream */
- if (ustsession->metadata->stream_obj == NULL) {
- ret = ustctl_create_stream(ustsession->sock,
- ustsession->metadata->obj,
- &ustsession->metadata->stream_obj);
- if (ret < 0) {
- ERR("UST create metadata stream failed");
- ret = LTTCOMM_UST_STREAM_FAIL;
- goto error;
- }
- ret = asprintf(&ustsession->metadata->pathname, "%s/%s",
- ustsession->path, "metadata");
- if (ret < 0) {
- perror("asprintf UST create stream");
- goto error;
- }
- }
-
- /* For each channel */
- cds_list_for_each_entry(ustchan, &ustsession->channels.head, list) {
- if (ustchan->stream_count == 0) {
- struct ltt_ust_stream *ustream;
-
- ustream = zmalloc(sizeof(*ustream));
- if (!ustream) {
- ret = LTTCOMM_UST_STREAM_FAIL;
- goto error;
- }
- ret = ustctl_create_stream(ustsession->sock,
- ustchan->obj, &ustream->obj);
- if (ret < 0) {
- ret = LTTCOMM_UST_STREAM_FAIL;
- goto error;
- }
- ret = asprintf(&ustream->pathname, "%s/%s_%d",
- ustchan->trace_path, ustchan->name,
- ustchan->stream_count);
- if (ret < 0) {
- perror("asprintf UST create stream");
- goto error;
- }
- cds_list_add(&ustream->list, &ustchan->stream_list.head);
- ustchan->stream_count++;
- }
- }
-
- /* Setup UST consumer socket and send fds to it */
- ret = init_ust_tracing(ustsession);
- if (ret < 0) {
- ret = LTTCOMM_UST_START_FAIL;
- goto error;
- }
-
- /* This start the UST tracing */
- ret = ustctl_start_session(ustsession->sock, ustsession->handle);
- if (ret < 0) {
- ret = LTTCOMM_UST_START_FAIL;
- goto error;
- }
-
- /* Quiescent wait after starting trace */
- ustctl_wait_quiescent(ustsession->sock);
+ ret = ust_app_start_trace(usess);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_START_FAIL;
+ goto error;
}
ret = LTTCOMM_OK;
int ret;
struct ltt_kernel_channel *kchan;
struct ltt_kernel_session *ksession;
- struct ltt_ust_session *ustsession;
- struct ltt_ust_channel *ustchan;
+ //struct ltt_ust_session *usess;
+ //struct ltt_ust_channel *ustchan;
/* Short cut */
ksession = session->kernel_session;
kernel_wait_quiescent(kernel_tracer_fd);
}
+#ifdef DISABLE
/* Stop each UST session */
DBG("Stop UST tracing");
- cds_list_for_each_entry(ustsession, &session->ust_session_list.head, list) {
+ cds_list_for_each_entry(usess, &session->ust_session_list.head, list) {
/* Flush all buffers before stopping */
- ret = ustctl_flush_buffer(ustsession->sock, ustsession->metadata->obj);
+ ret = ustctl_flush_buffer(usess->sock, usess->metadata->obj);
if (ret < 0) {
ERR("UST metadata flush failed");
}
- cds_list_for_each_entry(ustchan, &ustsession->channels.head, list) {
- ret = ustctl_flush_buffer(ustsession->sock, ustchan->obj);
+ cds_list_for_each_entry(ustchan, &usess->channels.head, list) {
+ ret = ustctl_flush_buffer(usess->sock, ustchan->obj);
if (ret < 0) {
ERR("UST flush buffer error");
}
}
- ret = ustctl_stop_session(ustsession->sock, ustsession->handle);
+ ret = ustctl_stop_session(usess->sock, usess->handle);
if (ret < 0) {
ret = LTTCOMM_KERN_STOP_FAIL;
goto error;
}
- ustctl_wait_quiescent(ustsession->sock);
+ ustctl_wait_quiescent(usess->sock);
}
+#endif
ret = LTTCOMM_OK;
}
break;
case LTTNG_DOMAIN_UST:
- case LTTNG_DOMAIN_UST_EXEC_NAME:
- case LTTNG_DOMAIN_UST_PID:
- case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
{
- struct ltt_ust_session *usess;
if (need_tracing_session) {
if (cmd_ctx->session->ust_session == NULL) {
ret = create_ust_session(cmd_ctx->session,
ret = LTTCOMM_KERN_CONSUMER_FAIL;
goto error;
}
+
+ cmd_ctx->session->ust_session->consumer_fd =
+ ustconsumer_data.cmd_sock;
}
pthread_mutex_unlock(&ustconsumer_data.pid_mutex);
}
break;
+ }
default:
break;
}
if (ret < 0) {
goto exit;
}
+
ret = set_consumer_sockets(&ustconsumer_data);
if (ret < 0) {
goto exit;
struct ltt_session *session_find_by_name(char *name);
struct ltt_session_list *session_get_list(void);
-unsigned long session_ust_count(struct ltt_session *session);
#endif /* _LTT_SESSION_H */
*
* Return pointer to structure or NULL.
*/
-struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid,
+struct ltt_ust_session *trace_ust_create_session(char *path, unsigned int uid,
struct lttng_domain *domain)
{
int ret;
}
/* Init data structure */
- lus->handle = -1;
- lus->enabled = 1;
lus->consumer_fds_sent = 0;
- lus->metadata = NULL;
+ lus->uid = uid;
/* Alloc UST domain hash tables */
lus->domain_pid = hashtable_new(0);
lus->domain_global.channels = hashtable_new_str(0);
/* Set session path */
- ret = snprintf(lus->path, PATH_MAX, "%s/ust_%d", path, pid);
+ ret = snprintf(lus->pathname, PATH_MAX, "%s/ust", path);
if (ret < 0) {
PERROR("snprintf kernel traces path");
goto error;
}
/* Copy UST channel attributes */
- memcpy(&luc->attr, &chan->attr, sizeof(struct lttng_ust_channel));
+ luc->attr.overwrite = chan->attr.overwrite;
+ luc->attr.subbuf_size = chan->attr.subbuf_size;
+ luc->attr.num_subbuf = chan->attr.num_subbuf;
+ luc->attr.switch_timer_interval = chan->attr.switch_timer_interval;
+ luc->attr.read_timer_interval = chan->attr.read_timer_interval;
+ luc->attr.output = chan->attr.output;
/* Translate to UST output enum */
switch (luc->attr.output) {
break;
}
- luc->handle = -1;
- luc->enabled = 1;
-
/* Copy channel name */
strncpy(luc->name, chan->name, sizeof(&luc->name));
luc->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
luc->ctx = hashtable_new_str(0);
/* Set trace output path */
- ret = snprintf(luc->trace_path, PATH_MAX, "%s", path);
+ ret = snprintf(luc->pathname, PATH_MAX, "%s", path);
if (ret < 0) {
perror("asprintf ust create channel");
goto error;
}
- CDS_INIT_LIST_HEAD(&luc->stream_list.head);
DBG2("Trace UST channel %s created", luc->name);
strncpy(lue->attr.name, ev->name, LTTNG_UST_SYM_NAME_LEN);
lue->attr.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
- /* Setting up a ust event */
- lue->handle = -1;
- lue->enabled = 1;
-
/* Init node */
hashtable_node_init(&lue->node, (void *) lue->attr.name,
strlen(lue->attr.name));
rcu_read_lock();
- DBG2("Trace UST destroy session %d", session->handle);
+ DBG2("Trace UST destroy session %d", session->uid);
- if (session->metadata != NULL) {
- trace_ust_destroy_metadata(session->metadata);
- }
+ //if (session->metadata != NULL) {
+ // trace_ust_destroy_metadata(session->metadata);
+ //}
/* Cleaning up UST domain */
destroy_domain_global(&session->domain_global);
#include <urcu/list.h>
#include <lttng/lttng.h>
-/*
- * FIXME: temporary workaround: we use a lttng-tools local version of
- * lttng-ust-abi.h if UST is not found. Eventually, we should use our
- * own internal structures within lttng-tools instead of relying on the
- * UST ABI.
- */
-#ifdef CONFIG_CONFIG_LTTNG_TOOLS_HAVE_UST
-#include <ust/lttng-ust-abi.h>
-#else
-#include "lttng-ust-abi.h"
-#endif
+#include "ust-ctl.h"
#include "../hashtable/rculfhash.h"
-
/* UST Stream list */
struct ltt_ust_stream_list {
unsigned int count;
/* UST event */
struct ltt_ust_event {
- int handle;
- int enabled;
- struct object_data *obj;
struct lttng_ust_event attr;
struct cds_lfht *ctx;
struct cds_lfht_node node;
/* UST stream */
struct ltt_ust_stream {
- /* TODO hashtable */
+ int handle;
+ char pathname[PATH_MAX];
struct object_data *obj;
- struct cds_list_head list;
- char *pathname;
+ struct cds_lfht_node node;
};
/* UST channel */
struct ltt_ust_channel {
- int handle;
- int enabled;
char name[LTTNG_UST_SYM_NAME_LEN];
- char trace_path[PATH_MAX]; /* Trace file path name */
- struct object_data *obj;
-
- unsigned int stream_count;
- struct ltt_ust_stream_list stream_list;
+ char pathname[PATH_MAX];
struct lttng_ust_channel attr;
struct cds_lfht *ctx;
struct cds_lfht *events;
/* UST session */
struct ltt_ust_session {
- int sock; /* socket to send cmds to app */
- int handle;
- int enabled;
+ int uid; /* Unique identifier of session */
int consumer_fds_sent;
int consumer_fd;
- char path[PATH_MAX];
- struct ltt_ust_metadata *metadata;
- struct object_data *obj;
+ char pathname[PATH_MAX];
struct ltt_ust_domain_global domain_global;
/*
- * Those two hash tables contains data for a specific UST domain and a HT
- * of channels for each. See ltt_ust_domain_exec and ltt_ust_domain_pid
- * data structures.
+ * Those two hash tables contains data for a specific UST domain and each
+ * contains a HT of channels. See ltt_ust_domain_exec and
+ * ltt_ust_domain_pid data structures.
*/
struct cds_lfht *domain_pid;
struct cds_lfht *domain_exec;
/*
* Create functions malloc() the data structure.
*/
-struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid,
+struct ltt_ust_session *trace_ust_create_session(char *path, unsigned int uid,
struct lttng_domain *domain);
struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *attr,
char *path);
return NULL;
}
-static inline
-struct ltt_ust_session *trace_ust_get_session_by_pid(
- struct ltt_ust_session_list *session_list, pid_t pid)
-{
- return NULL;
-}
-
static inline
struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid,
struct lttng_domain *domain)
void trace_ust_destroy_session(struct ltt_ust_session *session)
{
}
+
static inline
void trace_ust_destroy_metadata(struct ltt_ust_metadata *metadata)
{
}
+
static inline
void trace_ust_destroy_channel(struct ltt_ust_channel *channel)
{
}
+
static inline
void trace_ust_destroy_event(struct ltt_ust_event *event)
{
}
-#endif
+#endif /* CONFIG_CONFIG_LTTNG_TOOLS_HAVE_UST */
#endif /* _LTT_TRACE_UST_H */
#include <unistd.h>
#include <lttngerr.h>
+#include <lttng-share.h>
#include "hashtable.h"
#include "ust-app.h"
#include "../hashtable/hash.h"
+#include "ust-ctl.h"
+#include "ust-consumer.h"
/*
* Delete a traceable application structure from the global list.
rcu_read_lock();
- hashtable_get_first(lta->channels, &iter);
- while ((node = hashtable_iter_get_node(&iter)) != NULL) {
- ret = hashtable_del(lta->channels, &iter);
- if (!ret) {
- trace_ust_destroy_channel(
- caa_container_of(node, struct ltt_ust_channel, node));
- }
- hashtable_get_next(lta->channels, &iter);
- }
-
- free(lta->channels);
+ free(lta->sessions);
close(lta->key.sock);
/* Remove from apps hash table */
struct cds_lfht_node *node;
struct ust_app_key *key;
struct cds_lfht_iter iter;
- //struct ust_app *app;
rcu_read_lock();
lta = malloc(sizeof(struct ust_app));
if (lta == NULL) {
- perror("malloc");
+ PERROR("malloc");
return -ENOMEM;
}
lta->name[16] = '\0';
hashtable_node_init(<a->node, (void *)((unsigned long)lta->key.pid),
sizeof(void *));
- lta->channels = hashtable_new_str(0);
+
+ /* Session hashtable */
+ lta->sessions = hashtable_new(0);
/* Set sock key map */
hashtable_node_init(<a->key.node, (void *)((unsigned long)lta->key.sock),
ust_app_ht = hashtable_new(0);
ust_app_sock_key_map = hashtable_new(0);
}
+
+/*
+ * Alloc new UST app session.
+ */
+static struct ust_app_session *alloc_app_session(void)
+{
+ struct ust_app_session *ua_sess;
+
+ ua_sess = zmalloc(sizeof(struct ust_app_session));
+ if (ua_sess == NULL) {
+ PERROR("malloc");
+ goto error;
+ }
+
+ ua_sess->enabled = 0;
+ ua_sess->handle = -1;
+ ua_sess->channels = hashtable_new_str(0);
+ ua_sess->metadata = NULL;
+ ua_sess->obj = NULL;
+
+ return ua_sess;
+
+error:
+ return NULL;
+}
+
+static struct ust_app_channel *alloc_app_channel(char *name)
+{
+ struct ust_app_channel *ua_chan;
+
+ ua_chan = zmalloc(sizeof(struct ust_app_channel));
+ if (ua_chan == NULL) {
+ PERROR("malloc");
+ goto error;
+ }
+
+ strncpy(ua_chan->name, name, sizeof(ua_chan->name));
+ ua_chan->name[sizeof(ua_chan->name) - 1] = '\0';
+ ua_chan->enabled = 0;
+ ua_chan->handle = -1;
+ ua_chan->obj = NULL;
+ ua_chan->ctx = hashtable_new(0);
+ ua_chan->streams = hashtable_new(0);
+ ua_chan->events = hashtable_new_str(0);
+ hashtable_node_init(&ua_chan->node, (void *) ua_chan->name,
+ strlen(ua_chan->name));
+
+ DBG3("UST app channel %s allocated", ua_chan->name);
+
+ return ua_chan;
+
+error:
+ return NULL;
+}
+
+static struct ust_app_event *alloc_app_event(char *name)
+{
+ struct ust_app_event *ua_event;
+
+ ua_event = zmalloc(sizeof(struct ust_app_event));
+ if (ua_event == NULL) {
+ PERROR("malloc");
+ goto error;
+ }
+
+ strncpy(ua_event->name, name, sizeof(ua_event->name));
+ ua_event->name[sizeof(ua_event->name) - 1] = '\0';
+ ua_event->ctx = hashtable_new(0);
+ hashtable_node_init(&ua_event->node, (void *) ua_event->name,
+ strlen(ua_event->name));
+
+ DBG3("UST app event %s allocated", ua_event->name);
+
+ return ua_event;
+
+error:
+ return NULL;
+}
+
+static void shallow_copy_event(struct ust_app_event *ua_event,
+ struct ltt_ust_event *uevent)
+{
+ strncpy(ua_event->name, uevent->attr.name, sizeof(ua_event->name));
+ ua_event->name[sizeof(ua_event->name) - 1] = '\0';
+
+ /* TODO: support copy context */
+}
+
+static void shallow_copy_channel(struct ust_app_channel *ua_chan,
+ struct ltt_ust_channel *uchan)
+{
+ struct cds_lfht_iter iter;
+ struct cds_lfht_node *node, *ua_event_node;
+ struct ltt_ust_event *uevent;
+ struct ust_app_event *ua_event;
+
+ DBG2("Shallow copy of UST app channel %s", ua_chan->name);
+
+ strncpy(ua_chan->name, uchan->name, sizeof(ua_chan->name));
+ ua_chan->name[sizeof(ua_chan->name) - 1] = '\0';
+
+ /* TODO: support copy context */
+
+ hashtable_get_first(uchan->events, &iter);
+ while ((node = hashtable_iter_get_node(&iter)) != NULL) {
+ uevent = caa_container_of(node, struct ltt_ust_event, node);
+
+ ua_event_node = hashtable_lookup(ua_chan->events,
+ (void *) uevent->attr.name, strlen(uevent->attr.name), &iter);
+ if (ua_event_node == NULL) {
+ DBG2("UST event %s not found on shallow copy channel",
+ uevent->attr.name);
+ ua_event = alloc_app_event(uevent->attr.name);
+ if (ua_event == NULL) {
+ continue;
+ }
+ hashtable_add_unique(ua_chan->events, &ua_event->node);
+ } else {
+ ua_event = caa_container_of(node, struct ust_app_event, node);
+ }
+
+ shallow_copy_event(ua_event, uevent);
+
+ /* Get next UST events */
+ hashtable_get_next(uchan->events, &iter);
+ }
+
+ DBG3("Shallow copy channel done");
+}
+
+static void shallow_copy_session(struct ust_app_session *ua_sess,
+ struct ltt_ust_session *usess)
+{
+ struct cds_lfht_node *node, *ua_chan_node;
+ struct cds_lfht_iter iter;
+ struct ltt_ust_channel *uchan;
+ struct ust_app_channel *ua_chan;
+
+ DBG2("Shallow copy of session handle");
+
+ ua_sess->uid = usess->uid;
+
+ /* TODO: support all UST domain */
+
+ /* Iterate over all channels in global domain. */
+ hashtable_get_first(usess->domain_global.channels, &iter);
+ while ((node = hashtable_iter_get_node(&iter)) != NULL) {
+ uchan = caa_container_of(node, struct ltt_ust_channel, node);
+
+ ua_chan_node = hashtable_lookup(ua_sess->channels,
+ (void *) uchan->name, strlen(uchan->name), &iter);
+ if (ua_chan_node == NULL) {
+ DBG2("Channel %s not found on shallow session copy, creating it",
+ uchan->name);
+ ua_chan = alloc_app_channel(uchan->name);
+ if (ua_chan == NULL) {
+ /* malloc failed... continuing */
+ continue;
+ }
+ hashtable_add_unique(ua_sess->channels, &ua_chan->node);
+ } else {
+ ua_chan = caa_container_of(node, struct ust_app_channel, node);
+ }
+
+ shallow_copy_channel(ua_chan, uchan);
+
+ /* Next item in hash table */
+ hashtable_get_next(usess->domain_global.channels, &iter);
+ }
+}
+
+static struct ust_app_session *lookup_session_by_app(
+ struct ltt_ust_session *usess, struct ust_app *app)
+{
+ struct cds_lfht_iter iter;
+ struct cds_lfht_node *node;
+
+ /* Get right UST app session from app */
+ node = hashtable_lookup(app->sessions,
+ (void *) ((unsigned long) usess->uid),
+ sizeof(void *), &iter);
+ if (node == NULL) {
+ goto error;
+ }
+
+ return caa_container_of(node, struct ust_app_session, node);
+
+error:
+ return NULL;
+}
+
+int ust_app_add_channel(struct ltt_ust_session *usess,
+ struct ltt_ust_channel *uchan)
+{
+ int ret = 0;
+ struct cds_lfht_iter iter;
+ struct cds_lfht_node *node, *ua_chan_node;
+ struct ust_app *app;
+ struct ust_app_session *ua_sess;
+ struct ust_app_channel *ua_chan;
+
+ DBG2("UST app adding channel %s to global domain for session uid %d",
+ uchan->name, usess->uid);
+
+ rcu_read_lock();
+ hashtable_get_first(ust_app_ht, &iter);
+ while ((node = hashtable_iter_get_node(&iter)) != NULL) {
+ app = caa_container_of(node, struct ust_app, node);
+
+ ua_sess = lookup_session_by_app(usess, app);
+ if (ua_sess == NULL) {
+ DBG2("UST app pid: %d session uid %d not found, creating one",
+ app->key.pid, usess->uid);
+ ua_sess = alloc_app_session();
+ if (ua_sess == NULL) {
+ /* Only malloc can failed so something is really wrong */
+ goto next;
+ }
+ shallow_copy_session(ua_sess, usess);
+ }
+
+ if (ua_sess->handle == -1) {
+ ret = ustctl_create_session(app->key.sock);
+ if (ret < 0) {
+ DBG("Error creating session for app pid %d, sock %d",
+ app->key.pid, app->key.sock);
+ /* TODO: free() ua_sess */
+ goto next;
+ }
+
+ DBG2("UST app ustctl create session handle %d", ret);
+ ua_sess->handle = ret;
+
+ /* Add ust app session to app's HT */
+ hashtable_node_init(&ua_sess->node,
+ (void *)((unsigned long) ua_sess->uid), sizeof(void *));
+ hashtable_add_unique(app->sessions, &ua_sess->node);
+ }
+
+ /* Lookup channel in the ust app session */
+ ua_chan_node = hashtable_lookup(ua_sess->channels,
+ (void *) uchan->name, strlen(uchan->name), &iter);
+ if (ua_chan_node == NULL) {
+ ERR("Channel suppose to be present with the above shallow "
+ "session copy. Continuing...");
+ goto next;
+ }
+
+ ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
+
+ /* TODO: remove cast and use lttng-ust-abi.h */
+ ret = ustctl_create_channel(app->key.sock, ua_sess->handle,
+ (struct lttng_ust_channel_attr *)&uchan->attr, &ua_chan->obj);
+ if (ret < 0) {
+ DBG("Error creating channel %s for app (pid: %d, sock: %d) "
+ "and session handle %d with ret %d",
+ uchan->name, app->key.pid, app->key.sock,
+ ua_sess->handle, ret);
+ goto next;
+ }
+
+ ua_chan->handle = ua_chan->obj->handle;
+ ua_chan->attr.shm_fd = ua_chan->obj->shm_fd;
+ ua_chan->attr.wait_fd = ua_chan->obj->wait_fd;
+ ua_chan->attr.memory_map_size = ua_chan->obj->memory_map_size;
+
+ DBG2("Channel %s UST create successfully for pid:%d and sock:%d",
+ uchan->name, app->key.pid, app->key.sock);
+
+next:
+ /* Next applications */
+ hashtable_get_next(ust_app_ht, &iter);
+ }
+ rcu_read_unlock();
+
+ return ret;
+}
+
+int ust_app_add_event(struct ltt_ust_session *usess,
+ struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent)
+{
+ int ret = 0;
+ struct cds_lfht_iter iter;
+ struct cds_lfht_node *node, *ua_chan_node, *ua_event_node;
+ struct ust_app *app;
+ struct ust_app_session *ua_sess;
+ struct ust_app_channel *ua_chan;
+ struct ust_app_event *ua_event;
+ struct lttng_ust_event ltt_uevent;
+ struct object_data *obj_event;
+
+ DBG2("UST app adding event %s to global domain for session uid %d",
+ uevent->attr.name, usess->uid);
+
+ rcu_read_lock();
+ hashtable_get_first(ust_app_ht, &iter);
+ while ((node = hashtable_iter_get_node(&iter)) != NULL) {
+ app = caa_container_of(node, struct ust_app, node);
+
+ ua_sess = lookup_session_by_app(usess, app);
+ if (ua_sess == NULL) {
+ DBG2("UST app (pid: %d, sock: %d) session not found, creating one",
+ app->key.pid, app->key.sock);
+ ua_sess = alloc_app_session();
+ if (ua_sess == NULL) {
+ /* Only malloc can failed so something is really wrong */
+ goto next;
+ }
+ shallow_copy_session(ua_sess, usess);
+ }
+
+ if (ua_sess->handle == -1) {
+ ret = ustctl_create_session(app->key.sock);
+ if (ret < 0) {
+ DBG("Error creating session for app pid %d, sock %d",
+ app->key.pid, app->key.sock);
+ /* TODO: free() ua_sess */
+ goto next;
+ }
+
+ DBG2("UST app ustctl create session handle %d", ret);
+ ua_sess->handle = ret;
+ /* Add ust app session to app's HT */
+ hashtable_node_init(&ua_sess->node,
+ (void *)((unsigned long) ua_sess->uid), sizeof(void *));
+ hashtable_add_unique(app->sessions, &ua_sess->node);
+ }
+
+ /* Lookup channel in the ust app session */
+ ua_chan_node = hashtable_lookup(ua_sess->channels,
+ (void *) uchan->name, strlen(uchan->name), &iter);
+ if (ua_chan_node == NULL) {
+ ERR("Channel suppose to be present with the above shallow "
+ "session copy. Continuing...");
+ goto next;
+ }
+
+ ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
+
+ /* Prepare lttng ust event */
+ strncpy(ltt_uevent.name, uevent->attr.name, sizeof(ltt_uevent.name));
+ ltt_uevent.name[sizeof(ltt_uevent.name) - 1] = '\0';
+ /* TODO: adjust to other instrumentation types */
+ ltt_uevent.instrumentation = LTTNG_UST_TRACEPOINT;
+
+ /* Get event node */
+ ua_event_node = hashtable_lookup(ua_chan->events,
+ (void *) uevent->attr.name, strlen(uevent->attr.name), &iter);
+ if (ua_event_node == NULL) {
+ DBG2("UST app event %s not found, creating one", uevent->attr.name);
+ /* Does not exist so create one */
+ ua_event = alloc_app_event(uevent->attr.name);
+ if (ua_event == NULL) {
+ /* Only malloc can failed so something is really wrong */
+ goto next;
+ }
+
+ shallow_copy_event(ua_event, uevent);
+
+ /* Create UST event on tracer */
+ ret = ustctl_create_event(app->key.sock, <t_uevent, ua_chan->obj,
+ &obj_event);
+ if (ret < 0) {
+ ERR("Error ustctl create event %s for app pid: %d with ret %d",
+ uevent->attr.name, app->key.pid, ret);
+ /* TODO: free() ua_event and obj_event */
+ goto next;
+ }
+ ua_event->obj = obj_event;
+ ua_event->handle = obj_event->handle;
+ ua_event->enabled = 1;
+ } else {
+ ua_event = caa_container_of(ua_event_node,
+ struct ust_app_event, node);
+
+ if (ua_event->enabled == 0) {
+ ret = ustctl_enable(app->key.sock, ua_event->obj);
+ if (ret < 0) {
+ ERR("Error ustctl enable event %s for app "
+ "pid: %d with ret %d", uevent->attr.name,
+ app->key.pid, ret);
+ goto next;
+ }
+ ua_event->enabled = 1;
+ }
+ }
+
+ hashtable_add_unique(ua_chan->events, &ua_event->node);
+
+ DBG2("Event %s UST create successfully for pid:%d", uevent->attr.name,
+ app->key.pid);
+
+next:
+ /* Next applications */
+ hashtable_get_next(ust_app_ht, &iter);
+ }
+ rcu_read_unlock();
+
+ return ret;
+}
+
+int ust_app_start_trace(struct ltt_ust_session *usess)
+{
+ int ret = 0;
+ struct cds_lfht_iter iter;
+ struct cds_lfht_node *node, *ua_chan_node;
+ struct ust_app *app;
+ struct ust_app_session *ua_sess;
+ struct ust_app_channel *ua_chan;
+ struct lttng_ust_channel_attr uattr;
+ struct ltt_ust_channel *uchan;
+
+ rcu_read_lock();
+ hashtable_get_first(ust_app_ht, &iter);
+ while ((node = hashtable_iter_get_node(&iter)) != NULL) {
+ app = caa_container_of(node, struct ust_app, node);
+
+ ua_sess = lookup_session_by_app(usess, app);
+ if (ua_sess == NULL) {
+ /* Only malloc can failed so something is really wrong */
+ goto next;
+ }
+
+ if (ua_sess->metadata == NULL) {
+ /* Allocate UST metadata */
+ ua_sess->metadata = trace_ust_create_metadata(usess->pathname);
+ if (ua_sess->metadata == NULL) {
+ ERR("UST app session %d creating metadata failed",
+ ua_sess->handle);
+ goto next;
+ }
+
+ uattr.overwrite = ua_sess->metadata->attr.overwrite;
+ uattr.subbuf_size = ua_sess->metadata->attr.subbuf_size;
+ uattr.num_subbuf = ua_sess->metadata->attr.num_subbuf;
+ uattr.switch_timer_interval =
+ ua_sess->metadata->attr.switch_timer_interval;
+ uattr.read_timer_interval =
+ ua_sess->metadata->attr.read_timer_interval;
+ uattr.output = ua_sess->metadata->attr.output;
+
+ /* UST tracer metadata creation */
+ ret = ustctl_open_metadata(app->key.sock, ua_sess->handle, &uattr,
+ &ua_sess->metadata->obj);
+ if (ret < 0) {
+ ERR("UST app open metadata failed for app pid:%d",
+ app->key.pid);
+ goto next;
+ }
+
+ DBG2("UST metadata opened for app pid %d", app->key.pid);
+ }
+
+ /* Open UST metadata stream */
+ if (ua_sess->metadata->stream_obj == NULL) {
+ ret = ustctl_create_stream(app->key.sock, ua_sess->metadata->obj,
+ &ua_sess->metadata->stream_obj);
+ if (ret < 0) {
+ ERR("UST create metadata stream failed");
+ goto next;
+ }
+
+ ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, "%s/%s",
+ usess->pathname, "metadata");
+ if (ret < 0) {
+ PERROR("asprintf UST create stream");
+ goto next;
+ }
+
+ DBG2("UST metadata stream object created for app pid %d",
+ app->key.pid);
+ }
+
+ /* For each channel */
+ hashtable_get_first(usess->domain_global.channels, &iter);
+ while ((node = hashtable_iter_get_node(&iter)) != NULL) {
+ uchan = caa_container_of(node, struct ltt_ust_channel, node);
+
+ /* Lookup channel in the ust app session */
+ ua_chan_node = hashtable_lookup(ua_sess->channels,
+ (void *) uchan->name, strlen(uchan->name), &iter);
+ if (ua_chan_node == NULL) {
+ ERR("Channel suppose to be present with the above shallow "
+ "session copy. Continuing...");
+ goto next;
+ }
+
+ ua_chan = caa_container_of(ua_chan_node,
+ struct ust_app_channel, node);
+
+ struct ltt_ust_stream *ustream;
+
+ ustream = malloc(sizeof(*ustream));
+ if (ustream == NULL) {
+ goto next_chan;
+ }
+
+ memset(ustream, 0, sizeof(struct ltt_ust_stream));
+
+ ret = ustctl_create_stream(app->key.sock, ua_chan->obj,
+ &ustream->obj);
+ if (ret < 0) {
+ ERR("Creating channel stream failed");
+ goto next_chan;
+ }
+
+ ustream->handle = ustream->obj->handle;
+
+ hashtable_node_init(&ustream->node,
+ (void *)((unsigned long) ustream->handle), sizeof(void *));
+ hashtable_add_unique(ua_chan->streams, &ustream->node);
+
+ ret = snprintf(ustream->pathname, PATH_MAX, "%s/%s_%lu",
+ uchan->pathname, uchan->name,
+ hashtable_get_count(ua_chan->streams));
+ if (ret < 0) {
+ PERROR("asprintf UST create stream");
+ goto next_chan;
+ }
+
+next_chan:
+ /* Next applications */
+ hashtable_get_next(ua_sess->channels, &iter);
+ }
+
+ /* Setup UST consumer socket and send fds to it */
+ printf("WTF HERE: sock: %d\n", usess->consumer_fd);
+ ret = ust_consumer_send_session(usess->consumer_fd, ua_sess);
+ if (ret < 0) {
+ goto next;
+ }
+
+ /* This start the UST tracing */
+ ret = ustctl_start_session(app->key.sock, ua_sess->handle);
+ if (ret < 0) {
+ ERR("Error starting tracing for app pid: %d", app->key.pid);
+ goto next;
+ }
+
+ /* Quiescent wait after starting trace */
+ ustctl_wait_quiescent(app->key.sock);
+next:
+ /* Next applications */
+ hashtable_get_next(ust_app_ht, &iter);
+ }
+ rcu_read_unlock();
+
+ return 0;
+}
char name[16];
};
+/*
+ * Global applications HT used by the session daemon.
+ */
struct cds_lfht *ust_app_ht;
struct cds_lfht *ust_app_sock_key_map;
struct cds_lfht_node node;
};
+struct ust_app_event {
+ int enabled;
+ int handle;
+ struct object_data *obj;
+ char name[LTTNG_UST_SYM_NAME_LEN];
+ struct cds_lfht *ctx;
+ struct cds_lfht_node node;
+};
+
+struct ust_app_channel {
+ int enabled;
+ int handle;
+ char name[LTTNG_UST_SYM_NAME_LEN];
+ struct lttng_ust_channel attr;
+ struct object_data *obj;
+ struct cds_lfht *streams;
+ struct cds_lfht *ctx;
+ struct cds_lfht *events;
+ struct cds_lfht_node node;
+};
+
+struct ust_app_session {
+ int enabled;
+ int handle; /* Used has unique identifier */
+ unsigned int uid;
+ struct ltt_ust_metadata *metadata;
+ struct object_data *obj;
+ struct cds_lfht *channels; /* Registered channels */
+ struct cds_lfht_node node;
+};
+
/*
* Registered traceable applications. Libust registers to the session daemon
* and a linked list is kept of all running traceable app.
*/
struct ust_app {
- //int sock;
- //pid_t pid;
pid_t ppid;
uid_t uid; /* User ID that owns the apps */
gid_t gid; /* Group ID that owns the apps */
uint32_t v_major; /* Verion major number */
uint32_t v_minor; /* Verion minor number */
char name[17]; /* Process name (short) */
- struct cds_lfht *channels;
+ struct cds_lfht *sessions;
struct cds_lfht_node node;
struct ust_app_key key;
};
int ust_app_register(struct ust_register_msg *msg, int sock);
void ust_app_unregister(int sock);
+int ust_app_add_channel(struct ltt_ust_session *usess,
+ struct ltt_ust_channel *uchan);
+int ust_app_add_event(struct ltt_ust_session *usess,
+ struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent);
unsigned long ust_app_list_count(void);
+int ust_app_start_trace(struct ltt_ust_session *usess);
void ust_app_clean_list(void);
void ust_app_ht_alloc(void);
return NULL;
}
-#endif
+static inline
+int ust_app_add_channel(struct ltt_ust_session *usess,
+ struct ltt_ust_channel *uchan)
+{
+ return 0;
+}
+
+#endif /* CONFIG_LTTNG_TOOLS_HAVE_UST */
#endif /* _LTT_UST_APP_H */
--- /dev/null
+/*
+ * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; only version 2 of the License.
+ *
+ * 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., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <lttngerr.h>
+#include <lttng-share.h>
+#include <lttng-sessiond-comm.h>
+#include <lttng/lttng-consumer.h>
+
+#include "hashtable.h"
+#include "ust-consumer.h"
+
+/*
+ * Send all stream fds of UST channel to the consumer.
+ */
+static int send_channel_streams(int sock,
+ struct ust_app_channel *uchan)
+{
+ int ret, fds[2];
+ struct ltt_ust_stream *stream;
+ struct lttcomm_consumer_msg lum;
+ struct cds_lfht_iter iter;
+ struct cds_lfht_node *node;
+
+ DBG("Sending streams of channel %s to UST consumer", uchan->name);
+
+ /* Send channel */
+ lum.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL;
+
+ /*
+ * We need to keep shm_fd open to make sure this key stays unique within
+ * the session daemon.
+ */
+ lum.u.channel.channel_key = uchan->obj->shm_fd;
+ lum.u.channel.max_sb_size = uchan->attr.subbuf_size;
+ lum.u.channel.mmap_len = uchan->obj->memory_map_size;
+ DBG("Sending channel %d to consumer", lum.u.channel.channel_key);
+ ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum));
+ if (ret < 0) {
+ perror("send consumer channel");
+ goto error;
+ }
+ fds[0] = uchan->obj->shm_fd;
+ fds[1] = uchan->obj->wait_fd;
+ ret = lttcomm_send_fds_unix_sock(sock, fds, 2);
+ if (ret < 0) {
+ perror("send consumer channel ancillary data");
+ goto error;
+ }
+
+
+ rcu_read_lock();
+ hashtable_get_first(uchan->streams, &iter);
+ while ((node = hashtable_iter_get_node(&iter)) != NULL) {
+ stream = caa_container_of(node, struct ltt_ust_stream, node);
+
+ int fds[2];
+
+ if (!stream->obj->shm_fd) {
+ goto next;
+ }
+
+ lum.cmd_type = LTTNG_CONSUMER_ADD_STREAM;
+ lum.u.stream.channel_key = uchan->obj->shm_fd;
+ lum.u.stream.stream_key = stream->obj->shm_fd;
+ lum.u.stream.state = LTTNG_CONSUMER_ACTIVE_STREAM;
+ lum.u.stream.output = uchan->attr.output;
+ lum.u.stream.mmap_len = stream->obj->memory_map_size;
+ strncpy(lum.u.stream.path_name, stream->pathname, PATH_MAX - 1);
+ lum.u.stream.path_name[PATH_MAX - 1] = '\0';
+ DBG("Sending stream %d to consumer", lum.u.stream.stream_key);
+ ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum));
+ if (ret < 0) {
+ perror("send consumer stream");
+ goto error;
+ }
+
+ fds[0] = stream->obj->shm_fd;
+ fds[1] = stream->obj->wait_fd;
+ ret = lttcomm_send_fds_unix_sock(sock, fds, 2);
+ if (ret < 0) {
+ perror("send consumer stream ancillary data");
+ goto error;
+ }
+
+next:
+ hashtable_get_next(uchan->streams, &iter);
+ }
+ rcu_read_unlock();
+
+ DBG("consumer channel streams sent");
+
+ return 0;
+
+error:
+ return ret;
+}
+
+/*
+ * Send all stream fds of the UST session to the consumer.
+ */
+int ust_consumer_send_session(int consumer_fd, struct ust_app_session *usess)
+{
+ int ret = 0;
+ int sock = consumer_fd;
+ struct cds_lfht_iter iter;
+ struct cds_lfht_node *node;
+ struct lttcomm_consumer_msg lum;
+ struct ust_app_channel *uchan;
+
+ DBG("Sending metadata stream fd");
+
+ if (usess->metadata->obj->shm_fd != 0) {
+ int fds[2];
+
+ /* Send metadata channel fd */
+ lum.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL;
+ lum.u.channel.channel_key = usess->metadata->obj->shm_fd;
+ lum.u.channel.max_sb_size = usess->metadata->attr.subbuf_size;
+ lum.u.channel.mmap_len = 0; /* for kernel */
+ DBG("Sending metadata channel %d to consumer", lum.u.stream.stream_key);
+ ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum));
+ if (ret < 0) {
+ perror("send consumer channel");
+ goto error;
+ }
+ fds[0] = usess->metadata->obj->shm_fd;
+ fds[1] = usess->metadata->obj->wait_fd;
+ ret = lttcomm_send_fds_unix_sock(sock, fds, 2);
+ if (ret < 0) {
+ perror("send consumer metadata channel");
+ goto error;
+ }
+
+ /* Send metadata stream fd */
+ lum.cmd_type = LTTNG_CONSUMER_ADD_STREAM;
+ lum.u.stream.channel_key = usess->metadata->obj->shm_fd;
+ lum.u.stream.stream_key = usess->metadata->stream_obj->shm_fd;
+ lum.u.stream.state = LTTNG_CONSUMER_ACTIVE_STREAM;
+ lum.u.stream.output = DEFAULT_UST_CHANNEL_OUTPUT;
+ lum.u.stream.mmap_len = usess->metadata->stream_obj->memory_map_size;
+ strncpy(lum.u.stream.path_name, usess->metadata->pathname, PATH_MAX - 1);
+ lum.u.stream.path_name[PATH_MAX - 1] = '\0';
+ DBG("Sending metadata stream %d to consumer", lum.u.stream.stream_key);
+ ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum));
+ if (ret < 0) {
+ perror("send consumer metadata stream");
+ goto error;
+ }
+ fds[0] = usess->metadata->stream_obj->shm_fd;
+ fds[1] = usess->metadata->stream_obj->wait_fd;
+ ret = lttcomm_send_fds_unix_sock(sock, fds, 2);
+ if (ret < 0) {
+ perror("send consumer stream");
+ goto error;
+ }
+ }
+
+ /* Send each channel fd streams of session */
+ rcu_read_lock();
+ hashtable_get_first(usess->channels, &iter);
+ while ((node = hashtable_iter_get_node(&iter)) != NULL) {
+ uchan = caa_container_of(node, struct ust_app_channel, node);
+
+ ret = send_channel_streams(sock, uchan);
+ if (ret < 0) {
+ goto error;
+ }
+ hashtable_get_next(usess->channels, &iter);
+ }
+ rcu_read_unlock();
+
+ DBG("consumer fds (metadata and channel streams) sent");
+
+ return 0;
+
+error:
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; only version 2 of the License.
+ *
+ * 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., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _UST_CONSUMER_H
+#define _UST_CONSUMER_H
+
+#include "ust-app.h"
+
+int ust_consumer_send_session(int consumer_fd, struct ust_app_session *usess);
+
+#endif /* _UST_CONSUMER_H */
/*
+ * ust-ctl.h
+ *
+ * Meta header used to include all relevant file from the lttng ust ABI.
+ *
* Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; only version 2
- * of the License.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; only version 2 of the License.
*
- * 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.
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * 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., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _LTT_UST_CTL_H
#define _LTT_UST_CTL_H
#include <config.h>
-#include <lttng/lttng.h>
-
-#include "trace-ust.h"
+/*
+ * FIXME: temporary workaround: we use a lttng-tools local version of
+ * lttng-ust-abi.h if UST is not found. Eventually, we should use our
+ * own internal structures within lttng-tools instead of relying on the
+ * UST ABI.
+ */
#ifdef CONFIG_LTTNG_TOOLS_HAVE_UST
-
+#include <ust/lttng-ust-ctl.h>
+#include <ust/lttng-ust-abi.h>
#else
-
+#include "lttng-ust-ctl.h"
+#include "lttng-ust-abi.h"
#endif
#endif /* _LTT_UST_CTL_H */