Enable agent application contexts if filter has such dependencies
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 5 Feb 2016 22:10:41 +0000 (17:10 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 12 Feb 2016 22:54:03 +0000 (17:54 -0500)
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
src/bin/lttng-sessiond/cmd.c
src/bin/lttng-sessiond/event.c
src/common/Makefile.am
src/common/context.c [new file with mode: 0644]
src/common/context.h [new file with mode: 0644]
src/common/filter.c [new file with mode: 0644]
src/common/filter.h [new file with mode: 0644]

index eca3cf439c0ced16022d65e4dd44645c6d63cb6b..83286a00213fc6df857d1573f01304a008a3290c 100644 (file)
@@ -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;
index e4c79df74a4dca37f132478408caacd92d9f2577..b7b80d366c6ed60d9027ffcfd1e3320c60cc18d0 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2016 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
  *
  * 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 <lttng/lttng.h>
 #include <common/error.h>
 #include <common/sessiond-comm/sessiond-comm.h>
+#include <common/filter.h>
+#include <common/context.h>
 
 #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;
index 148130177f177d2be79fd0e99c638d64b3da6b54..66146bb73d9d82ff2833a62f22fa929501dbc2c8 100644 (file)
@@ -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 (file)
index 0000000..ead6bb3
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * context.c
+ *
+ * LTTng context utilities.
+ *
+ * Copyright 2016 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * 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 <stddef.h>
+#include <string.h>
+#include <common/error.h>
+#include <common/macros.h>
+
+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 (file)
index 0000000..5552f4d
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * 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 (file)
index 0000000..f103d24
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * filter.c
+ *
+ * LTTng filter bytecode utilities.
+ *
+ * Copyright 2016 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * 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 <stddef.h>
+
+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 (file)
index 0000000..051177a
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * 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 <common/sessiond-comm/sessiond-comm.h>
+
+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 */
This page took 0.037898 seconds and 4 git commands to generate.