#include <unistd.h>
#include <urcu/list.h>
+#include <lttng-ht.h>
#include <lttng-sessiond-comm.h>
#include <lttngerr.h>
#include "context.h"
-#include "hashtable.h"
#include "kernel.h"
+#include "ust-app.h"
+#include "trace-ust.h"
/*
* Add kernel context to an event of a specific channel.
}
/*
- * Add kernel context to tracer.
+ * Add UST context to channel.
*/
-int context_kernel_add(struct ltt_kernel_session *ksession,
- struct lttng_event_context *ctx, char *event_name,
- char *channel_name)
+static int add_uctx_to_channel(struct ltt_ust_session *usess, int domain,
+ struct ltt_ust_channel *uchan, struct lttng_event_context *ctx)
{
int ret;
- struct ltt_kernel_channel *kchan;
- struct lttng_kernel_context kctx;
+ struct ltt_ust_context *uctx;
- /* Setup kernel context structure */
- kctx.ctx = ctx->ctx;
- kctx.u.perf_counter.type = ctx->u.perf_counter.type;
- kctx.u.perf_counter.config = ctx->u.perf_counter.config;
- strncpy(kctx.u.perf_counter.name, ctx->u.perf_counter.name,
- LTTNG_SYMBOL_NAME_LEN);
- kctx.u.perf_counter.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
-
- if (strlen(channel_name) == 0) {
- ret = add_kctx_all_channels(ksession, &kctx, event_name);
- if (ret != LTTCOMM_OK) {
- goto error;
- }
- } else {
- /* Get kernel channel */
- kchan = trace_kernel_get_channel_by_name(channel_name, ksession);
- if (kchan == NULL) {
- ret = LTTCOMM_KERN_CHAN_NOT_FOUND;
- goto error;
- }
+ /* Create ltt UST context */
+ uctx = trace_ust_create_context(ctx);
+ if (uctx == NULL) {
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
- ret = add_kctx_to_channel(&kctx, kchan, event_name);
- if (ret != LTTCOMM_OK) {
+ switch (domain) {
+ case LTTNG_DOMAIN_UST:
+ ret = ust_app_add_ctx_channel_glb(usess, uchan, uctx);
+ if (ret < 0) {
goto error;
}
+ break;
+ default:
+ ret = LTTCOMM_NOT_IMPLEMENTED;
+ goto error;
}
- ret = LTTCOMM_OK;
+ /* Add ltt UST context node to ltt UST channel */
+ lttng_ht_add_unique_ulong(uchan->ctx, &uctx->node);
+
+ return LTTCOMM_OK;
error:
+ free(uctx);
return ret;
}
/*
- * UST support.
- */
-
-/*
- * Add UST context to an event of a specific channel.
+ * Add UST context to event.
*/
-#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)
+static int add_uctx_to_event(struct ltt_ust_session *usess, int domain,
+ struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent,
+ struct lttng_event_context *ctx)
{
- int ret, found = 0;
- struct ltt_ust_event *ustevent;
- struct object_data *context_data; /* FIXME: currently a memleak */
+ int ret;
+ struct ltt_ust_context *uctx;
- DBG("Add UST context to event %s", event_name);
+ /* Create ltt UST context */
+ uctx = trace_ust_create_context(ctx);
+ if (uctx == NULL) {
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
- 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);
+ switch (domain) {
+ case LTTNG_DOMAIN_UST:
+ ret = ust_app_add_ctx_event_glb(usess, uchan, uevent, uctx);
if (ret < 0) {
goto error;
}
- found = 1;
- }
-
- ret = found;
-
-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 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 */
-
- if (strlen(event_name) == 0) {
- no_event = 1;
+ break;
+ default:
+ ret = LTTCOMM_NOT_IMPLEMENTED;
+ goto error;
}
- DBG("Adding ust context to all channels (event: %s)", event_name);
+ /* Add ltt UST context node to ltt UST event */
+ lttng_ht_add_unique_ulong(uevent->ctx, &uctx->node);
- struct cds_lfht_node *node;
- struct cds_lfht_iter iter;
+ return LTTCOMM_OK;
- 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);
- if (ret < 0) {
- ret = LTTCOMM_UST_CONTEXT_FAIL;
- goto error;
- }
- } else {
- ret = add_ustctx_to_event(ustsession, ustctx, ustchan, event_name);
- if (ret < 0) {
- ret = LTTCOMM_UST_CONTEXT_FAIL;
- goto error;
- } else if (ret == 1) {
- /* Event found and context added */
- found = 1;
- break;
- }
- }
- hashtable_get_next(channels, &iter);
- }
- if (!found && !no_event) {
- ret = LTTCOMM_NO_EVENT;
- goto error;
- }
- ret = LTTCOMM_OK;
error:
- rcu_read_unlock();
+ free(uctx);
return ret;
-#endif
- return 0;
}
/*
- * Add UST context to a specific channel.
- *
- * If event_name is specified, add context to that event.
+ * Add kernel context to tracer.
*/
-static int add_ustctx_to_channel(struct ltt_ust_session *ustsession,
- struct lttng_ust_context *ustctx,
- struct ltt_ust_channel *ustchan, char *event_name)
+int context_kernel_add(struct ltt_kernel_session *ksession,
+ struct lttng_event_context *ctx, char *event_name,
+ char *channel_name)
{
-#ifdef DISABLE
- int ret, no_event = 0, found = 0;
- struct object_data *context_data; /* FIXME: currently a memleak */
-
- if (strlen(event_name) == 0) {
- no_event = 1;
- }
+ int ret;
+ struct ltt_kernel_channel *kchan;
+ struct lttng_kernel_context kctx;
- DBG("Add UST context to channel '%s', event '%s'",
- ustchan->name, event_name);
+ /* Setup kernel context structure */
+ kctx.ctx = ctx->ctx;
+ kctx.u.perf_counter.type = ctx->u.perf_counter.type;
+ kctx.u.perf_counter.config = ctx->u.perf_counter.config;
+ strncpy(kctx.u.perf_counter.name, ctx->u.perf_counter.name,
+ LTTNG_SYMBOL_NAME_LEN);
+ kctx.u.perf_counter.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
- if (no_event) {
- //ret = ustctl_add_context(ustsession->sock, ustctx,
- // ustchan->obj, &context_data);
- if (ret < 0) {
- ret = LTTCOMM_UST_CONTEXT_FAIL;
+ if (strlen(channel_name) == 0) {
+ ret = add_kctx_all_channels(ksession, &kctx, event_name);
+ if (ret != LTTCOMM_OK) {
goto error;
}
} else {
- ret = add_ustctx_to_event(ustsession, ustctx, ustchan, event_name);
- if (ret < 0) {
- ret = LTTCOMM_UST_CONTEXT_FAIL;
+ /* Get kernel channel */
+ kchan = trace_kernel_get_channel_by_name(channel_name, ksession);
+ if (kchan == NULL) {
+ ret = LTTCOMM_KERN_CHAN_NOT_FOUND;
goto error;
- } else if (ret == 1) {
- /* Event found and context added */
- found = 1;
}
- }
- if (!found && !no_event) {
- ret = LTTCOMM_NO_EVENT;
- goto error;
+ ret = add_kctx_to_channel(&kctx, kchan, event_name);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
}
ret = LTTCOMM_OK;
error:
return ret;
-#endif
- return 0;
}
/*
* Add UST context to tracer.
*/
-int context_ust_add(struct ltt_ust_session *ustsession,
+int context_ust_add(struct ltt_ust_session *usess, int domain,
struct lttng_event_context *ctx, char *event_name,
- char *channel_name, int domain)
+ char *channel_name)
{
- 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;
-
+ int ret = LTTCOMM_OK, have_event = 0;
+ struct lttng_ht_iter iter, uiter;
+ struct lttng_ht *chan_ht;
+ struct ltt_ust_channel *uchan = NULL;
+ struct ltt_ust_event *uevent = NULL;
+
+ /*
+ * Define which channel's hashtable to use from the domain or quit if
+ * unknown domain.
+ */
switch (domain) {
- case LTTNG_DOMAIN_UST:
- chan_ht = ustsession->domain_global.channels;
- break;
+ case LTTNG_DOMAIN_UST:
+ chan_ht = usess->domain_global.channels;
+ break;
+ case LTTNG_DOMAIN_UST_EXEC_NAME:
+ case LTTNG_DOMAIN_UST_PID:
+ case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
+ default:
+ ret = LTTCOMM_NOT_IMPLEMENTED;
+ goto error;
}
- if (strlen(channel_name) == 0) {
- ret = add_ustctx_all_channels(ustsession, &ustctx, event_name, chan_ht);
- if (ret != LTTCOMM_OK) {
- goto error;
- }
- } else {
- /* Get UST channel */
- ustchan = trace_ust_find_channel_by_name(chan_ht, channel_name);
- if (ustchan == NULL) {
+ /* Do we have an event name */
+ if (strlen(event_name) != 0) {
+ have_event = 1;
+ }
+
+ /* Get UST channel if defined */
+ if (strlen(channel_name) != 0) {
+ uchan = trace_ust_find_channel_by_name(chan_ht, channel_name);
+ if (uchan == NULL) {
ret = LTTCOMM_UST_CHAN_NOT_FOUND;
goto error;
}
+ }
- ret = add_ustctx_to_channel(ustsession, &ustctx, ustchan, event_name);
- if (ret != LTTCOMM_OK) {
+ /* If UST channel specified and event name, get UST event ref */
+ if (uchan && have_event) {
+ uevent = trace_ust_find_event_by_name(uchan->events, event_name);
+ if (uevent == NULL) {
+ ret = LTTCOMM_UST_EVENT_NOT_FOUND;
goto error;
}
}
- ret = LTTCOMM_OK;
+ /* At this point, we have 4 possibilities */
+
+ if (uchan && uevent) { /* Add ctx to event in channel */
+ ret = add_uctx_to_event(usess, domain, uchan, uevent, ctx);
+ } else if (uchan && !have_event) { /* Add ctx to channel */
+ ret = add_uctx_to_channel(usess, domain, uchan, ctx);
+ } else if (!uchan && have_event) { /* Add ctx to event */
+ /* Add context to event without having the channel name */
+ cds_lfht_for_each_entry(chan_ht->ht, &iter.iter, uchan, node.node) {
+ uevent = trace_ust_find_event_by_name(uchan->events, event_name);
+ if (uevent != NULL) {
+ ret = add_uctx_to_event(usess, domain, uchan, uevent, ctx);
+ /*
+ * LTTng UST does not allowed the same event to be registered
+ * multiple time in different or the same channel. So, if we
+ * found our event, we stop.
+ */
+ goto end;
+ }
+ }
+ ret = LTTCOMM_UST_EVENT_NOT_FOUND;
+ goto error;
+ } else if (!uchan && !have_event) { /* Add ctx all events, all channels */
+ /* For all channels */
+ cds_lfht_for_each_entry(chan_ht->ht, &iter.iter, uchan, node.node) {
+ ret = add_uctx_to_channel(usess, domain, uchan, ctx);
+ if (ret < 0) {
+ ERR("Context added to channel %s failed", uchan->name);
+ continue;
+ }
+
+ /* For all events in channel */
+ cds_lfht_for_each_entry(uchan->events->ht, &uiter.iter, uevent,
+ node.node) {
+ ret = add_uctx_to_event(usess, domain, uchan, uevent, ctx);
+ if (ret < 0) {
+ ERR("Context add to event %s in channel %s failed",
+ uevent->attr.name, uchan->name);
+ continue;
+ }
+ }
+ }
+ }
+
+end:
+ switch (ret) {
+ case -EEXIST:
+ ret = LTTCOMM_UST_CONTEXT_EXIST;
+ goto error;
+ case -ENOMEM:
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+
+ return LTTCOMM_OK;
error:
return ret;