From 71a559f8ebee6ba681dfba864d6dace2efcf0440 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Fri, 5 Feb 2016 17:10:41 -0500 Subject: [PATCH] Enable agent application contexts if filter has such dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérémie Galarneau --- src/bin/lttng-sessiond/cmd.c | 2 +- src/bin/lttng-sessiond/event.c | 74 +++++++++++++++++++++++- src/common/Makefile.am | 3 +- src/common/context.c | 93 ++++++++++++++++++++++++++++++ src/common/context.h | 35 ++++++++++++ src/common/filter.c | 100 +++++++++++++++++++++++++++++++++ src/common/filter.h | 46 +++++++++++++++ 7 files changed, 350 insertions(+), 3 deletions(-) create mode 100644 src/common/context.c create mode 100644 src/common/context.h create mode 100644 src/common/filter.c create mode 100644 src/common/filter.h diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index eca3cf439..83286a002 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -1790,7 +1790,7 @@ static int _cmd_enable_event(struct ltt_session *session, filter_expression = NULL; filter = NULL; exclusion = NULL; - if (ret != LTTNG_OK) { + if (ret != LTTNG_OK && ret != LTTNG_ERR_UST_EVENT_ENABLED) { goto error; } break; diff --git a/src/bin/lttng-sessiond/event.c b/src/bin/lttng-sessiond/event.c index e4c79df74..b7b80d366 100644 --- a/src/bin/lttng-sessiond/event.c +++ b/src/bin/lttng-sessiond/event.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 - David Goulet + * Copyright (C) 2016 - Jérémie Galarneau * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2 only, @@ -23,6 +24,8 @@ #include #include #include +#include +#include #include "channel.h" #include "event.h" @@ -416,6 +419,67 @@ error: return ret; } +/* + * Check if this event's filter requires the activation of application contexts + * and enable them in the agent. + */ +static int add_filter_app_ctx(struct lttng_filter_bytecode *bytecode, + const char *filter_expression, struct agent *agt) +{ + int ret = LTTNG_OK; + char *provider_name = NULL, *ctx_name = NULL; + struct bytecode_symbol_iterator *it = + bytecode_symbol_iterator_create(bytecode); + + if (!it) { + ret = LTTNG_ERR_NOMEM; + goto end; + } + + do { + struct lttng_event_context ctx; + const char *symbol_name = + bytecode_symbol_iterator_get_name(it); + + if (parse_application_context(symbol_name, &provider_name, + &ctx_name)) { + /* Not an application context. */ + continue; + } + + ctx.ctx = LTTNG_EVENT_CONTEXT_APP_CONTEXT; + ctx.u.app_ctx.provider_name = provider_name; + ctx.u.app_ctx.ctx_name = ctx_name; + + /* Recognized an application context. */ + DBG("Enabling event with filter expression \"%s\" requires enabling the %s:%s application context.", + filter_expression, provider_name, ctx_name); + + ret = agent_add_context(&ctx, agt); + if (ret != LTTNG_OK) { + ERR("Failed to add application context %s:%s.", + provider_name, ctx_name); + goto end; + } + + ret = agent_enable_context(&ctx, agt->domain); + if (ret != LTTNG_OK) { + ERR("Failed to enable application context %s:%s.", + provider_name, ctx_name); + goto end; + } + + free(provider_name); + free(ctx_name); + provider_name = ctx_name = NULL; + } while (bytecode_symbol_iterator_next(it) == 0); +end: + free(provider_name); + free(ctx_name); + bytecode_symbol_iterator_destroy(it); + return ret; +} + /* * Enable a single agent event for a given UST session. * @@ -439,7 +503,7 @@ int event_agent_enable(struct ltt_ust_session *usess, filter_expression ? filter_expression : "NULL"); aevent = agent_find_event(event->name, event->loglevel_type, - event->loglevel, filter_expression, agt); + event->loglevel, filter_expression, agt); if (!aevent) { aevent = agent_create_event(event->name, event->loglevel_type, event->loglevel, filter, @@ -448,6 +512,7 @@ int event_agent_enable(struct ltt_ust_session *usess, ret = LTTNG_ERR_NOMEM; goto error; } + created = 1; } @@ -456,6 +521,13 @@ int event_agent_enable(struct ltt_ust_session *usess, goto end; } + if (created && filter) { + ret = add_filter_app_ctx(filter, filter_expression, agt); + if (ret != LTTNG_OK) { + goto error; + } + } + ret = agent_enable_event(aevent, agt->domain); if (ret != LTTNG_OK) { goto error; diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 148130177..66146bb73 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -72,7 +72,8 @@ libcommon_la_SOURCES = error.h error.c utils.c utils.h runas.c runas.h \ pipe.c pipe.h readwrite.c readwrite.h \ mi-lttng.h mi-lttng.c \ daemonize.c daemonize.h \ - sessiond-comm/unix.c sessiond-comm/unix.h + sessiond-comm/unix.c sessiond-comm/unix.h \ + filter.c filter.h context.c context.h libcommon_la_LIBADD = \ -luuid \ diff --git a/src/common/context.c b/src/common/context.c new file mode 100644 index 000000000..ead6bb3f5 --- /dev/null +++ b/src/common/context.c @@ -0,0 +1,93 @@ +/* + * context.c + * + * LTTng context utilities. + * + * Copyright 2016 - Jérémie Galarneau + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License, version 2.1 only, + * as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "context.h" +#include +#include +#include +#include + +int parse_application_context(const char *str, char **out_provider_name, + char **out_ctx_name) +{ + const char app_ctx_prefix[] = "$app."; + char *provider_name = NULL, *ctx_name = NULL; + size_t i, len, colon_pos = 0, provider_name_len, ctx_name_len; + + if (!str || !out_provider_name || !out_ctx_name) { + goto not_found; + } + + len = strlen(str); + if (len <= sizeof(app_ctx_prefix) - 1) { + goto not_found; + } + + /* String starts with $app. */ + if (strncmp(str, app_ctx_prefix, sizeof(app_ctx_prefix) - 1)) { + goto not_found; + } + + /* Validate that the ':' separator is present. */ + for (i = sizeof(app_ctx_prefix); i < len; i++) { + const char c = str[i]; + + if (c == ':') { + colon_pos = i; + break; + } + } + + /* + * No colon found or no ctx name ("$app.provider:") or no provider name + * given ("$app.:..."), which is invalid. + */ + if (!colon_pos || colon_pos == len || + colon_pos == sizeof(app_ctx_prefix)) { + goto not_found; + } + + provider_name_len = colon_pos - sizeof(app_ctx_prefix) + 2; + provider_name = zmalloc(provider_name_len); + if (!provider_name) { + PERROR("malloc provider_name"); + goto not_found; + } + strncpy(provider_name, str + sizeof(app_ctx_prefix) - 1, + provider_name_len - 1); + + ctx_name_len = len - colon_pos; + ctx_name = zmalloc(ctx_name_len); + if (!ctx_name) { + PERROR("malloc ctx_name"); + goto not_found; + } + strncpy(ctx_name, str + colon_pos + 1, ctx_name_len - 1); + + *out_provider_name = provider_name; + *out_ctx_name = ctx_name; + return 0; +not_found: + free(provider_name); + free(ctx_name); + return -1; +} + diff --git a/src/common/context.h b/src/common/context.h new file mode 100644 index 000000000..5552f4da5 --- /dev/null +++ b/src/common/context.h @@ -0,0 +1,35 @@ +/* + * Copyright 2016 - Jérémie Galarneau + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License, version 2 only, as + * published by the Free Software Foundation. + * + * 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., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LTTNG_COMMON_CONTEXT_H +#define LTTNG_COMMON_CONTEXT_H + +/* + * Parse string as an application context of the form + * "$app.provider_name:context_name" and return the provider name and context + * name separately. + * + * provider_name and ctx_name are returned only if an application context name + * was successfully parsed and must be freed by the caller. + * + * Returns 0 if the string is a valid application context, else a negative + * value on error. + */ +int parse_application_context(const char *str, char **provider_name, + char **ctx_name); + +#endif /* LTTNG_COMMON_CONTEXT_H */ diff --git a/src/common/filter.c b/src/common/filter.c new file mode 100644 index 000000000..f103d240f --- /dev/null +++ b/src/common/filter.c @@ -0,0 +1,100 @@ +/* + * filter.c + * + * LTTng filter bytecode utilities. + * + * Copyright 2016 - Jérémie Galarneau + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License, version 2.1 only, + * as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "filter.h" +#include + +struct bytecode_symbol_iterator { + /* No ownership of bytecode is taken. */ + char *bytecode; + size_t offset, len; +}; + +struct bytecode_symbol_iterator *bytecode_symbol_iterator_create( + struct lttng_filter_bytecode *bytecode) +{ + struct bytecode_symbol_iterator *it = NULL; + + if (!bytecode) { + goto end; + } + + it = zmalloc(sizeof(*it)); + if (!it) { + goto end; + } + + it->bytecode = bytecode->data; + it->offset = bytecode->reloc_table_offset; + it->len = bytecode->len; +end: + return it; +} + +int bytecode_symbol_iterator_next(struct bytecode_symbol_iterator *it) +{ + int ret; + size_t len; + + if (!it || it->offset >= it->len) { + ret = -1; + goto end; + } + + len = strlen(it->bytecode + it->offset + sizeof(uint16_t)) + 1; + it->offset += len + sizeof(uint16_t); + ret = it->offset >= it->len ? -1 : 0; +end: + return ret; +} + +int bytecode_symbol_iterator_get_type(struct bytecode_symbol_iterator *it) +{ + int ret; + + if (!it) { + ret = -1; + goto end; + } + + ret = *((uint16_t *) (it->bytecode + it->offset)); +end: + return ret; + } + +const char *bytecode_symbol_iterator_get_name( + struct bytecode_symbol_iterator *it) +{ + const char *ret = NULL; + + if (!it) { + goto end; + } + + ret = it->bytecode + it->offset + sizeof(uint16_t); +end: + return ret; +} + +void bytecode_symbol_iterator_destroy(struct bytecode_symbol_iterator *it) +{ + free(it); +} diff --git a/src/common/filter.h b/src/common/filter.h new file mode 100644 index 000000000..051177a0e --- /dev/null +++ b/src/common/filter.h @@ -0,0 +1,46 @@ +/* + * Copyright 2016 - Jérémie Galarneau + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License, version 2 only, as + * published by the Free Software Foundation. + * + * 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., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LTTNG_COMMON_FILTER_H +#define LTTNG_COMMON_FILTER_H + +#include + +struct bytecode_symbol_iterator; + +/* + * Create an iterator on a bytecode's symbols. The iterator points to the + * first element after creation. + */ +struct bytecode_symbol_iterator *bytecode_symbol_iterator_create( + struct lttng_filter_bytecode *bytecode); + +/* + * Advance iterator of one element. + * + * Returns 0 if a next element exists or a negative value at the end. + */ +int bytecode_symbol_iterator_next(struct bytecode_symbol_iterator *it); + +int bytecode_symbol_iterator_get_type(struct bytecode_symbol_iterator *it); + +const char *bytecode_symbol_iterator_get_name( + struct bytecode_symbol_iterator *it); + +void bytecode_symbol_iterator_destroy(struct bytecode_symbol_iterator *it); + +#endif /* LTTNG_COMMON_FILTER_H */ -- 2.34.1