+/*
+ * Create a UST session onto the tracer of app and add it the session
+ * hashtable.
+ *
+ * Return ust app session or NULL on error.
+ */
+static struct ust_app_session *create_ust_app_session(
+ struct ltt_ust_session *usess, struct ust_app *app)
+{
+ int ret;
+ struct ust_app_session *ua_sess;
+
+ ua_sess = lookup_session_by_app(usess, app);
+ if (ua_sess == NULL) {
+ DBG2("UST app pid: %d session uid %d not found, creating it",
+ app->key.pid, usess->uid);
+ ua_sess = alloc_ust_app_session();
+ if (ua_sess == NULL) {
+ /* Only malloc can failed so something is really wrong */
+ goto error;
+ }
+ shadow_copy_session(ua_sess, usess);
+ }
+
+ if (ua_sess->handle == -1) {
+ ret = ustctl_create_session(app->key.sock);
+ if (ret < 0) {
+ ERR("Error creating session for app pid %d, sock %d",
+ app->key.pid, app->key.sock);
+ /* TODO: free() ua_sess */
+ goto error;
+ }
+
+ 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);
+
+ DBG2("UST app session created successfully with handle %d", ret);
+ }
+
+ return ua_sess;
+
+error:
+ return NULL;
+}
+
+static struct ust_app_channel *create_ust_app_channel(
+ struct ust_app_session *ua_sess, struct ltt_ust_channel *uchan,
+ struct ust_app *app)
+{
+ int ret = 0;
+ struct cds_lfht_iter iter;
+ struct cds_lfht_node *ua_chan_node;
+ struct ust_app_channel *ua_chan;
+
+ /* 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) {
+ DBG2("Unable to find channel %s in ust session uid %u",
+ uchan->name, ua_sess->uid);
+ ua_chan = alloc_ust_app_channel(uchan->name);
+ if (ua_chan == NULL) {
+ goto error;
+ }
+ shadow_copy_channel(ua_chan, uchan);
+ hashtable_add_unique(ua_sess->channels, &ua_chan->node);
+ } else {
+ 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",
+ ua_chan->name, app->key.pid, app->key.sock,
+ ua_sess->handle, ret);
+ goto error;
+ }
+
+ 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",
+ ua_chan->name, app->key.pid, app->key.sock);
+
+ return ua_chan;
+
+error:
+ return NULL;
+}
+
+static struct ust_app_event *create_ust_app_event(
+ struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan,
+ struct ltt_ust_event *uevent, struct ust_app *app)
+{
+ int ret;
+ struct cds_lfht_iter iter;
+ struct cds_lfht_node *ua_event_node;
+ struct ust_app_event *ua_event;
+
+ /* 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 it", uevent->attr.name);
+ /* Does not exist so create one */
+ ua_event = alloc_ust_app_event(uevent->attr.name);
+ if (ua_event == NULL) {
+ /* Only malloc can failed so something is really wrong */
+ goto error;
+ }
+ shadow_copy_event(ua_event, uevent);
+
+ hashtable_add_unique(ua_chan->events, &ua_event->node);
+ } else {
+ ua_event = caa_container_of(ua_event_node, struct ust_app_event, node);
+ }
+
+ /* Create UST event on tracer */
+ ret = ustctl_create_event(app->key.sock, &uevent->attr, ua_chan->obj,
+ &ua_event->obj);
+ 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 */
+ goto error;
+ }
+ ua_event->handle = ua_event->obj->handle;
+ ua_event->enabled = 1;
+
+
+ DBG2("Event %s UST create successfully for pid:%d", uevent->attr.name,
+ app->key.pid);
+
+ return ua_event;
+
+error:
+ return NULL;
+}
+
+static int create_ust_app_metadata(struct ust_app_session *ua_sess,
+ char *pathname, struct ust_app *app)
+{
+ int ret = 0;
+ struct lttng_ust_channel_attr uattr;
+
+ if (ua_sess->metadata == NULL) {
+ /* Allocate UST metadata */
+ ua_sess->metadata = trace_ust_create_metadata(pathname);
+ if (ua_sess->metadata == NULL) {
+ ERR("UST app session %d creating metadata failed",
+ ua_sess->handle);
+ goto error;
+ }
+
+ 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 error;
+ }
+
+ 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 error;
+ }
+
+ ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, "%s/%s-%d",
+ pathname, app->name, app->key.pid);
+ if (ret < 0) {
+ PERROR("asprintf UST create stream");
+ goto error;
+ }
+
+ ret = mkdir(ua_sess->metadata->pathname, S_IRWXU | S_IRWXG);
+ if (ret < 0) {
+ PERROR("mkdir UST metadata");
+ goto error;
+ }
+
+ ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, "%s/%s-%d/metadata",
+ pathname, app->name, app->key.pid);
+ if (ret < 0) {
+ PERROR("asprintf UST create stream");
+ goto error;
+ }
+
+ DBG2("UST metadata stream object created for app pid %d",
+ app->key.pid);
+ }
+
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * Add channel to all ust app session.
+ */
+int ust_app_add_channel_all(struct ltt_ust_session *usess,