#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <unistd.h>
#include <lttngerr.h>
ua_chan->handle = -1;
ua_chan->obj = NULL;
ua_chan->ctx = hashtable_new(0);
- ua_chan->streams = hashtable_new(0);
+ CDS_INIT_LIST_HEAD(&ua_chan->streams.head);
ua_chan->events = hashtable_new_str(0);
hashtable_node_init(&ua_chan->node, (void *) ua_chan->name,
strlen(ua_chan->name));
struct lttng_ust_channel_attr uattr;
struct ltt_ust_channel *uchan;
+ DBG("Starting all UST traces");
+
rcu_read_lock();
hashtable_get_first(ust_app_ht, &iter);
while ((node = hashtable_iter_get_node(&iter)) != NULL) {
goto next;
}
- ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, "%s/%s",
- usess->pathname, "metadata");
+ ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, "%s/%s-%d",
+ usess->pathname, app->name, app->key.pid);
+ if (ret < 0) {
+ PERROR("asprintf UST create stream");
+ goto next;
+ }
+
+ ret = mkdir(ua_sess->metadata->pathname, S_IRWXU | S_IRWXG);
+ if (ret < 0) {
+ goto next;
+ }
+
+ ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, "%s/%s-%d/metadata",
+ usess->pathname, app->name, app->key.pid);
if (ret < 0) {
PERROR("asprintf UST create stream");
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));
+ for (;;) {
+ struct lttng_ust_object_data *obj;
+ struct ltt_ust_stream *ustream;
- 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 = ustctl_create_stream(app->key.sock, ua_chan->obj,
+ &obj);
+ if (ret < 0) {
+ /* Got all streams */
+ goto next_chan;
+ }
- 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;
+ ustream = malloc(sizeof(*ustream));
+ if (ustream == NULL) {
+ goto next_chan;
+ }
+ memset(ustream, 0, sizeof(struct ltt_ust_stream));
+ ustream->obj = obj;
+ ustream->handle = ustream->obj->handle;
+ /* Order is important */
+ cds_list_add_tail(&ustream->list, &ua_chan->streams.head);
+ ret = snprintf(ustream->pathname, PATH_MAX, "%s/%s-%d/%s_%u",
+ usess->pathname, app->name, app->key.pid,
+ uchan->name, ua_chan->streams.count++);
+ if (ret < 0) {
+ PERROR("asprintf UST create stream");
+ goto next_chan;
+ }
}
next_chan:
return 0;
}
+
+void ust_app_global_update(struct ltt_ust_session *usess, int sock)
+{
+ int ret = 0;
+ int session_existed = 1;
+ 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 ust_app_event *ua_event;
+ struct lttng_ust_event ltt_uevent;
+ struct ltt_ust_channel *uchan;
+ struct lttng_ust_object_data *obj_event;
+ struct lttng_ust_channel_attr uattr;
+
+ DBG2("UST app global update for app sock %d for session uid %d", sock,
+ usess->uid);
+
+ rcu_read_lock();
+ app = find_app_by_sock(sock);
+ if (app == NULL) {
+ ERR("Failed to update app sock %d", sock);
+ goto error;
+ }
+
+ 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 error;
+ }
+ shallow_copy_session(ua_sess, usess);
+ session_existed= 0;
+ }
+
+ 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 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);
+ }
+
+ if (session_existed) {
+ goto error;
+ }
+
+ 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 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",
+ usess->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",
+ usess->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);
+ }
+
+
+ /* Iterate over all channels */
+ 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("UST app channel not found for uchan %s", uchan->name);
+ goto next_chan;
+ }
+
+ 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_chan;
+ }
+
+ 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);
+
+ /* For each event(s) of that channel */
+ hashtable_get_first(ua_chan->events, &iter);
+ while ((node = hashtable_iter_get_node(&iter)) != NULL) {
+ ua_event = caa_container_of(node, struct ust_app_event, node);
+
+ /* Prepare lttng ust event */
+ memset(<t_uevent, 0, sizeof(ltt_uevent));
+ strncpy(ltt_uevent.name, ua_event->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;
+
+ /* 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",
+ ua_event->name, app->key.pid, ret);
+ /* TODO: free() ua_event and obj_event */
+ goto next_event;
+ }
+
+ ua_event->obj = obj_event;
+ ua_event->handle = obj_event->handle;
+ ua_event->enabled = 1;
+
+ DBG2("Event %s UST create successfully for pid:%d",
+ ua_event->name, app->key.pid);
+
+next_event:
+ hashtable_get_next(ua_chan->events, &iter);
+ }
+
+ for (;;) {
+ struct lttng_ust_object_data *obj;
+ struct ltt_ust_stream *ustream;
+
+ ret = ustctl_create_stream(app->key.sock, ua_chan->obj, &obj);
+ if (ret < 0) {
+ /* Got all streams */
+ break;
+ }
+
+ ustream = zmalloc(sizeof(*ustream));
+ if (ustream == NULL) {
+ PERROR("zmalloc ust stream");
+ goto error;
+ }
+
+ ustream->obj = obj;
+ ustream->handle = ustream->obj->handle;
+ /* Order is important */
+ cds_list_add_tail(&ustream->list, &ua_chan->streams.head);
+
+ ret = snprintf(ustream->pathname, PATH_MAX, "%s/%s-%d/%s_%u",
+ usess->pathname, app->name, app->key.pid,
+ uchan->name, ua_chan->streams.count++);
+ if (ret < 0) {
+ PERROR("asprintf UST create stream");
+ goto error;
+ }
+ }
+
+next_chan:
+ /* Next applications */
+ hashtable_get_next(ua_sess->channels, &iter);
+ }
+
+ if (usess->start_trace) {
+ /* Setup UST consumer socket and send fds to it */
+ ret = ust_consumer_send_session(usess->consumer_fd, ua_sess);
+ if (ret < 0) {
+ ERR("UST consumer send session failed");
+ goto error;
+ }
+
+ /* 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 error;
+ }
+
+ /* Quiescent wait after starting trace */
+ ustctl_wait_quiescent(app->key.sock);
+
+ DBG2("UST trace started for app pid %d", app->key.pid);
+ }
+
+error:
+ rcu_read_unlock();
+ return;
+}