/src/bin/lttng-crash/lttng-crash
/src/bin/lttng-relayd/lttng-relayd
/src/lib/lttng-ctl/lttng-ctl.pc
-/src/lib/lttng-ctl/filter/filter-grammar-test
-/src/lib/lttng-ctl/filter/filter-lexer.c
-/src/lib/lttng-ctl/filter/filter-parser.c
-/src/lib/lttng-ctl/filter/filter-parser.h
-/src/lib/lttng-ctl/filter/filter-parser.output
+/src/common/filter/filter-grammar-test
+/src/common/filter/filter-lexer.c
+/src/common/filter/filter-parser.c
+/src/common/filter/filter-parser.h
+/src/common/filter/filter-parser.output
/extras/bindings/swig/python/lttng.i
/extras/bindings/swig/python/lttng.py
/tests/unit/test_directory_handle
/tests/unit/test_relayd_backward_compat_group_by_session
/tests/unit/test_fd_tracker
+/tests/unit/test_event_rule
+/tests/unit/test_condition
kernel_all_events_basic
kernel_event_basic
ust_global_event_wildcard
/tests/regression/tools/notification/notification
/tests/regression/tools/rotation/schedule_api
/tests/regression/tools/notification/rotation
+/tests/regression/tools/trigger/base_client
+/tests/regression/tools/trigger/trigger
/tests/regression/ust/overlap/demo/demo
/tests/regression/ust/linking/demo_builtin
/tests/regression/ust/linking/demo_static
RW_PROG_CXX_WORKS
AM_CONDITIONAL([CXX_WORKS], [test "x$rw_cv_prog_cxx_works" = "xyes"])
+# Detect warning flags supported by the compiler, append them to WARN_CFLAGS.
+#
+# Pass -Werror as an extra flag during the test: this is needed to make the
+# -Wunknown-warning-option diagnostic fatal with clang.
+AX_APPEND_COMPILE_FLAGS([ dnl
+ -Wall dnl
+ dnl We currently get this warning when building with Clang:
+ dnl
+ dnl /usr/include/setjmp.h:54:12: error: declaration of built-in function '__sigsetjmp' requires the declaration of the 'jmp_buf' type, commonly provided in the header <setjmp.h>. [-Werror,-Wincomplete-setjmp-declaration]
+ dnl extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) __THROWNL;
+ dnl ^
+ -Wno-incomplete-setjmp-declaration dnl
+ -Wdiscarded-qualifiers dnl
+ ],
+ [WARN_CFLAGS],
+ [-Werror])
+
+# When given, add -Werror to WARN_CFLAGS.
+AC_ARG_ENABLE([Werror],
+ [AS_HELP_STRING([--enable-Werror], [Treat compiler warnings as errors.])]
+)
+AS_IF([test "x$enable_Werror" = "xyes"],
+ [WARN_CFLAGS="${WARN_CFLAGS} -Werror"]
+)
+
# Checks for programs.
AC_PROG_GREP
AC_PROG_MAKE_SET
AM_CONDITIONAL([BUILD_LIB_TESTPOINT], [test x$build_lib_testpoint = xyes])
AM_CONDITIONAL([BUILD_LIB_UST_CONSUMER], [test x$build_lib_ust_consumer = xyes])
-AM_CFLAGS="-Wall -fno-strict-aliasing $PTHREAD_CFLAGS"
+AM_CFLAGS="${WARN_CFLAGS} -fno-strict-aliasing $PTHREAD_CFLAGS"
AC_SUBST(AM_CFLAGS)
+# This is set even though it is empty, so Makefiles can do "AM_LDFLAGS += ...".
+AM_LDFLAGS=""
+AC_SUBST(AM_LDFLAGS)
+
# The order in which the include folders are searched is important.
# The top_builddir should always be searched first in the event that a build
# time generated file is included. An example of this is the "version.i" file.
# In a scenario where lttng-tools is built from a distribution tarball and in a
# out-of-tree manner, the generated "version.i" has priority on the one from
# the source (distribution tarball) and must be found first.
-AM_CPPFLAGS="-I\$(top_builddir)/include -I\$(top_srcdir)/include -I\$(top_srcdir)/src -include config.h $AM_CPPFLAGS"
+AM_CPPFLAGS="-I\$(top_builddir)/include -I\$(top_srcdir)/include -I\$(top_builddir)/src -I\$(top_srcdir)/src -include config.h $AM_CPPFLAGS"
AC_SUBST(AM_CPPFLAGS)
lttngincludedir="${includedir}/lttng"
lttngtriggerincludedir="${includedir}/lttng/trigger"
AC_SUBST(lttngtriggerincludedir)
+lttngeventruleincludedir="${includedir}/lttng/event-rule"
+AC_SUBST(lttngeventruleincludedir)
+
lttnglibexecdir="${libdir}/lttng/libexec"
AC_SUBST(lttnglibexecdir)
extras/core-handler/Makefile
src/Makefile
src/common/Makefile
+ src/common/argpar/Makefile
src/common/kernel-ctl/Makefile
src/common/kernel-consumer/Makefile
src/common/consumer/Makefile
src/common/config/Makefile
src/common/string-utils/Makefile
src/common/fd-tracker/Makefile
+ src/common/filter/Makefile
src/lib/Makefile
src/lib/lttng-ctl/Makefile
- src/lib/lttng-ctl/filter/Makefile
src/lib/lttng-ctl/lttng-ctl.pc
src/bin/Makefile
src/bin/lttng-consumerd/Makefile
tests/regression/tools/working-directory/Makefile
tests/regression/tools/relayd-grouping/Makefile
tests/regression/tools/clear/Makefile
+ tests/regression/tools/trigger/Makefile
tests/regression/ust/Makefile
tests/regression/ust/nprocesses/Makefile
tests/regression/ust/high-throughput/Makefile
--- /dev/null
+# Trigger notification exemple
+
+## Description
+This exemple is made-up of three executables.
+
+### `notification-client`
+
+```
+Usage: notification-client TRIGGER_NAME
+```
+
+A simple client that subscribes to the notifications emitted by the `TRIGGER_NAME` trigger.
+
+### `instrumented-app`
+
+An application that emits the `trigger_exemple:my_event` event every 2 seconds.
+
+### `demo.sh`
+
+This script adds a trigger named `demo_trigger` which emits a notification when the user-space `trigger_exemple:my_event` event occurs.
+
+Once the trigger has been setup, the notification-client is launched to print all notifications emitted by the `demo_trigger` trigger.
+
+## Building
+
+Simply run the included Makefile.
+
+## Running the exemple
+
+1) Launch a session daemon using:
+ ```
+ $ lttng-sessiond
+ ```
+2) Launch the `demo.sh` script
+3) Launch the `instrumented-app`
+
+The following output should be produced:
+
+```
+$ ./demo.sh
+Registering a notification trigger named "demo_trigger" for the trigger_exemple:my_event user-space event
+Trigger registered successfully.
+Subscribed to notifications of trigger "demo_trigger"
+[02-14-2020] 18:13:34.779766 - Received notification of event rule trigger "demo_trigger"
+[02-14-2020] 18:13:36.779888 - Received notification of event rule trigger "demo_trigger"
+[02-14-2020] 18:13:38.780514 - Received notification of event rule trigger "demo_trigger"
+[02-14-2020] 18:13:40.780656 - Received notification of event rule trigger "demo_trigger"
+```
+
+```
+$ ./instrumented-app
+[02-14-2020] 18:13:34.779433 - Tracing event "trigger_exemple:my_event"
+[02-14-2020] 18:13:36.779693 - Tracing event "trigger_exemple:my_event"
+[02-14-2020] 18:13:38.780010 - Tracing event "trigger_exemple:my_event"
+[02-14-2020] 18:13:40.780286 - Tracing event "trigger_exemple:my_event"
+```
--- /dev/null
+#!/bin/bash
+#
+# Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+#
+# SPDX-License-Identifier: MIT
+
+EVENT_NAME=trigger_exemple:my_event
+TRIGGER_NAME=demo_trigger
+
+lttng list > /dev/null 2>&1
+if [ $? -ne 0 ]; then
+ echo "Could not connect to session daemon, are you sure it is running?"
+ exit 1
+fi
+
+echo "Registering a notification trigger named \"$TRIGGER_NAME\" for the $EVENT_NAME user-space event"
+lttng add-trigger --id $TRIGGER_NAME --condition on-event --userspace $EVENT_NAME --action notify
+
+./notification-client $TRIGGER_NAME
+
--- /dev/null
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#include "tp.h"
+
+#include <lttng/tracepoint.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+ uint64_t i;
+
+ for (i = 0; i < UINT64_MAX; i++) {
+ char time_str[64];
+ struct timeval tv;
+ time_t the_time;
+
+ gettimeofday(&tv, NULL);
+ the_time = tv.tv_sec;
+
+ strftime(time_str, sizeof(time_str), "[%m-%d-%Y] %T",
+ localtime(&the_time));
+ printf("%s.%ld - Tracing event \"trigger_exemple:my_event\"\n", time_str, tv.tv_usec);
+
+ tracepoint(trigger_exemple, my_event, i);
+ sleep(2);
+ }
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#include <lttng/condition/event-rule.h>
+#include <lttng/lttng.h>
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <time.h>
+
+bool action_group_contains_notify(const struct lttng_action *action_group)
+{
+ unsigned int i, count;
+ enum lttng_action_status status =
+ lttng_action_group_get_count(action_group, &count);
+
+ if (status != LTTNG_ACTION_STATUS_OK) {
+ printf("Failed to get action count from action group\n");
+ exit(1);
+ }
+
+ for (i = 0; i < count; i++) {
+ const struct lttng_action *action =
+ lttng_action_group_get_at_index_const(
+ action_group, i);
+ const enum lttng_action_type action_type =
+ lttng_action_get_type(action);
+
+ if (action_type == LTTNG_ACTION_TYPE_NOTIFY) {
+ return true;
+ }
+ }
+ return false;
+}
+
+int print_notification(struct lttng_notification *notification)
+{
+ int ret = 0;
+ const struct lttng_condition *condition =
+ lttng_notification_get_condition(notification);
+ const struct lttng_evaluation *evaluation =
+ lttng_notification_get_evaluation(notification);
+ const enum lttng_condition_type type =
+ lttng_evaluation_get_type(evaluation);
+
+ switch (type) {
+ case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
+ printf("Received consumed size notification\n");
+ break;
+ case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
+ case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
+ printf("Received buffer usage notification\n");
+ break;
+ case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
+ printf("Received session rotation ongoing notification\n");
+ break;
+ case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
+ printf("Received session rotation completed notification\n");
+ break;
+ case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT:
+ {
+ const char *trigger_name;
+ enum lttng_evaluation_status evaluation_status;
+ char time_str[64];
+ struct timeval tv;
+ time_t the_time;
+
+ gettimeofday(&tv, NULL);
+ the_time = tv.tv_sec;
+
+ strftime(time_str, sizeof(time_str), "[%m-%d-%Y] %T",
+ localtime(&the_time));
+ printf("%s.%ld - ", time_str, tv.tv_usec);
+
+ evaluation_status =
+ lttng_evaluation_event_rule_get_trigger_name(
+ evaluation, &trigger_name);
+ if (evaluation_status != LTTNG_EVALUATION_STATUS_OK) {
+ fprintf(stderr, "Failed to get trigger name of event rule notification\n");
+ ret = -1;
+ break;
+ }
+
+ printf("Received notification of event rule trigger \"%s\"\n",
+ trigger_name);
+ break;
+ }
+ default:
+ fprintf(stderr, "Unknown notification type (%d)\n", type);
+ }
+
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+ struct lttng_triggers *triggers = NULL;
+ unsigned int count, i, subcription_count = 0;
+ enum lttng_trigger_status trigger_status;
+ struct lttng_notification_channel *notification_channel = NULL;
+
+ if (argc != 2) {
+ fprintf(stderr, "Missing trigger name\n");
+ fprintf(stderr, "Usage: notification-client TRIGGER_NAME\n");
+ goto end;
+ }
+
+ notification_channel = lttng_notification_channel_create(
+ lttng_session_daemon_notification_endpoint);
+ if (!notification_channel) {
+ fprintf(stderr, "Failed to create notification channel\n");
+ ret = -1;
+ goto end;
+ }
+
+ ret = lttng_list_triggers(&triggers);
+ if (ret) {
+ fprintf(stderr, "Failed to list triggers\n");
+ goto end;
+ }
+
+ trigger_status = lttng_triggers_get_count(triggers, &count);
+ if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
+ fprintf(stderr, "Failed to get trigger count\n");
+ ret = -1;
+ goto end;
+ }
+
+ for (i = 0; i < count; i++) {
+ const struct lttng_trigger *trigger =
+ lttng_triggers_get_at_index(triggers, i);
+ const struct lttng_condition *condition =
+ lttng_trigger_get_const_condition(trigger);
+ const struct lttng_action *action =
+ lttng_trigger_get_const_action(trigger);
+ const enum lttng_action_type action_type =
+ lttng_action_get_type(action);
+ enum lttng_notification_channel_status channel_status;
+ const char *trigger_name = NULL;
+ enum lttng_trigger_status trigger_status;
+
+ lttng_trigger_get_name(trigger, &trigger_name);
+ if (strcmp(trigger_name, argv[1])) {
+ continue;
+ }
+
+ if (!((action_type == LTTNG_ACTION_TYPE_GROUP &&
+ action_group_contains_notify(action)) ||
+ action_type == LTTNG_ACTION_TYPE_NOTIFY)) {
+ printf("The action of trigger \"%s\" is not \"notify\", skipping.\n",
+ trigger_name);
+ continue;
+ }
+
+ channel_status = lttng_notification_channel_subscribe(
+ notification_channel, condition);
+ if (channel_status) {
+ fprintf(stderr, "Failed to subscribe to notifications of trigger \"%s\"\n",
+ trigger_name);
+ ret = -1;
+ goto end;
+ }
+
+ printf("Subscribed to notifications of trigger \"%s\"\n",
+ trigger_name);
+ subcription_count++;
+ }
+
+ if (subcription_count == 0) {
+ printf("No matching trigger with a notify action found.\n");
+ ret = 0;
+ goto end;
+ }
+
+ for (;;) {
+ struct lttng_notification *notification;
+ enum lttng_notification_channel_status channel_status;
+
+ channel_status =
+ lttng_notification_channel_get_next_notification(
+ notification_channel,
+ ¬ification);
+ switch (channel_status) {
+ case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED:
+ printf("Dropped notification\n");
+ break;
+ case LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED:
+ ret = 0;
+ goto end;
+ case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK:
+ break;
+ case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED:
+ printf("Notification channel was closed by peer.\n");
+ break;
+ default:
+ fprintf(stderr, "A communication error occurred on the notification channel.\n");
+ ret = -1;
+ goto end;
+ }
+
+ ret = print_notification(notification);
+ lttng_notification_destroy(notification);
+ if (ret) {
+ goto end;
+ }
+ }
+end:
+ lttng_triggers_destroy(triggers);
+ lttng_notification_channel_destroy(notification_channel);
+ return !!ret;
+}
--- /dev/null
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#define TRACEPOINT_DEFINE
+#define TRACEPOINT_CREATE_PROBES
+#include "tp.h"
--- /dev/null
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#undef TRACEPOINT_PROVIDER
+#define TRACEPOINT_PROVIDER trigger_exemple
+
+#undef TRACEPOINT_INCLUDE
+#define TRACEPOINT_INCLUDE "./tp.h"
+
+#if !defined(_TRACEPOINT_TRIGGER_EXEMPLE_H) || defined(TRACEPOINT_HEADER_MULTI_READ)
+#define _TRACEPOINT_TRIGGER_EXEMPLE_H
+
+#include <lttng/tracepoint.h>
+
+TRACEPOINT_EVENT(trigger_exemple, my_event,
+ TP_ARGS(int, iteration),
+ TP_FIELDS(
+ ctf_integer(uint64_t, iteration, iteration)
+ )
+)
+
+#endif /* _TRACEPOINT_TRIGGER_EXEMPLE_H */
+
+#include <lttng/tracepoint-event.h>
lttng-rotate \
lttng-enable-rotation \
lttng-disable-rotation \
- lttng-clear
+ lttng-clear \
+ lttng-add-trigger \
+ lttng-remove-trigger \
+ lttng-list-triggers
+
MAN3_NAMES =
MAN8_NAMES = lttng-sessiond lttng-relayd
MAN1_NO_ASCIIDOC_NAMES =
--- /dev/null
+lttng-add-trigger(1)
+=====================
+:revdate: 17 January 2020
+
+
+NAME
+----
+lttng-add-trigger - Create LTTng triggers
+
+
+SYNOPSIS
+--------
+
+[verse]
+*lttng* ['linkgenoptions:(GENERAL OPTIONS)'] *add-trigger* [--id ID]
+ [--fire-every N] [--fire-once-after N]
+ --condition CONDITION-NAME CONDITION-ARGS
+ --action ACTION-NAME ACTION-ARGS
+ [--action ACTION-NAME ACTION-ARGS]...
+
+
+DESCRIPTION
+-----------
+
+The `lttng add-trigger` command is used to create triggers. A
+trigger is an association between a *condition* and one or more
+*actions*. When the condition associated to a trigger is met, the
+actions associated to that trigger are executed. The tracing does not
+have to be active for the conditions to be met, and triggers are
+independent from tracing sessions.
+
+By default, a trigger fires every time its condition is met. The
+'--fire-every' and '--fire-once-after' options can be used to change
+this mode.
+
+The syntax by which conditions and actions are specified is described
+below.
+
+[[conditions]]
+Conditions
+~~~~~~~~~~
+
+Conditions are specified with the `--condition` option, followed by a
+condition name, and possibly some more arguments, depending on the
+specific condition. There must be exactly one condition given in the
+`lttng add-trigger` invocation.
+
+The available conditions are:
+
+Event rule: `on-event [event rule arguments]`::
+ This type of condition is met when the tracer encounters an event
+ matching the given even rule. The arguments describing the event
+ rule are the same as those describing the event rules of the
+ man:lttng-enable-event(1) command, with these exceptions:
+
+ - It is not possible to use filter operands that use values from
+ the context.
+
+[[actions]]
+Actions
+~~~~~~~
+
+Actions are specified with the `--action` option, followed by an action
+name, and possibly some more arguments, depending on the specific
+action. There must be at least one action given in the
+`lttng add-trigger` invocation.
+
+The available actions are:
+
+Notify: *notify*::
+ This action causes the LTTng session daemon to send a notification,
+ through its notification mechanism (see man:lttng-sessiond(8)).
+ Some details about the condition evaluation are sent along with the
+ notification.
+
+Start session: *start-session* session-name::
+ This action causes the LTTng session daemon to start tracing for the
+ session with the given name. If no session with the given name exist
+ at the time the condition is met, nothing is done.
+
+Stop session: *stop-session* session-name::
+ This action causes the LTTng session daemon to stop tracing for the
+ session with the given name. If no session with the given name exist
+ at the time the condition is met, nothing is done.
+
+Rotate session: *rotate-session* session-name::
+ This action causes the LTTng session daemon to rotate the session
+ with the given name. See man:lttng-rotate(1) for more information
+ about the session rotation concept. If no session with the given
+ name exist at the time the condition is met, nothing is done.
+
+Snapshot session: *snapshot-session* session-name::
+ This action causes the LTTng session daemon to take a snapshot of the
+ session with the given name. See man:lttng-snapshot(1) for more
+ information about the session snapshot concept. If no session with
+ the given name exist at the time the condition is met, nothing is
+ done.
+
+OPTIONS
+-------
+
+option:--condition::
+ Define the condition for the trigger. See the
+ <<conditions,CONDITIONS>> section for more details.
+
+option:--action::
+ Define an action for the trigger. See the <<actions,ACTIONS>>
+ section for more details.
+
+option:--id='ID'::
+ Set the id of the trigger to 'ID'. If omitted, an id will
+ automatically be assigned to the trigger by the session daemon.
++
+If a trigger with the specified 'ID' already exists, the trigger
+creation will fail.
+
+option:--fire-every 'N'::
+ Execute the trigger's actions every 'N' times the condition is met.
+
+option:--fire-once-after 'N'::
+ Execute the trigger's actions once after 'N' times the condition is
+ met, then never after that.
+
+include::common-cmd-help-options.txt[]
+
+
+include::common-cmd-footer.txt[]
+
+
+SEE ALSO
+--------
+man:lttng-list-triggers(1),
+man:lttng-remove-trigger(1),
+man:lttng(1)
--- /dev/null
+lttng-list-triggers(1)
+======================
+:revdate: 20 January 2020
+
+
+NAME
+----
+lttng-list-triggers - List LTTng triggers
+
+
+SYNOPSIS
+--------
+
+[verse]
+*lttng* ['linkgenoptions:(GENERAL OPTIONS)'] *list-triggers*
+
+
+DESCRIPTION
+-----------
+
+The `lttng list-triggers` command list the existing triggers.
+
+
+OPTIONS
+-------
+
+include::common-cmd-help-options.txt[]
+
+
+include::common-cmd-footer.txt[]
+
+
+SEE ALSO
+--------
+man:lttng-add-trigger(1),
+man:lttng-remove-trigger(1),
+man:lttng(1)
--- /dev/null
+lttng-remove-trigger(1)
+========================
+:revdate: 20 January 2020
+
+
+NAME
+----
+lttng-remove-trigger - Remove LTTng triggers
+
+
+SYNOPSIS
+--------
+
+[verse]
+*lttng* ['linkgenoptions:(GENERAL OPTIONS)'] *remove-trigger* 'ID'
+
+
+DESCRIPTION
+-----------
+
+The `lttng remove-trigger` command removes the trigger with the given
+'ID'.
+
+
+OPTIONS
+-------
+
+include::common-cmd-help-options.txt[]
+
+
+include::common-cmd-footer.txt[]
+
+
+SEE ALSO
+--------
+man:lttng-add-trigger(1),
+man:lttng-list-trigger(1),
+man:lttng(1)
// This makes the typemap code useable with both Python 2 and 3.
#define PyInt_AsSsize_t PyLong_AsSsize_t
#endif
+
+// Avoid -Wmissing-declarations warning.
+PyObject *SWIG_init(void);
%}
typedef unsigned int uint32_t;
lttngactioninclude_HEADERS= \
lttng/action/action.h \
- lttng/action/notify.h
+ lttng/action/group.h \
+ lttng/action/notify.h \
+ lttng/action/rotate-session.h \
+ lttng/action/snapshot-session.h \
+ lttng/action/start-session.h \
+ lttng/action/stop-session.h
lttngconditioninclude_HEADERS= \
lttng/condition/condition.h \
lttng/condition/buffer-usage.h \
+ lttng/condition/event-rule.h \
lttng/condition/session-consumed-size.h \
lttng/condition/session-rotation.h \
lttng/condition/evaluation.h
lttngtriggerinclude_HEADERS= \
lttng/trigger/trigger.h
+lttngeventruleinclude_HEADERS= \
+ lttng/event-rule/event-rule.h \
+ lttng/event-rule/kprobe.h \
+ lttng/event-rule/kretprobe.h \
+ lttng/event-rule/syscall.h \
+ lttng/event-rule/tracepoint.h \
+ lttng/event-rule/uprobe.h
+
noinst_HEADERS = \
lttng/snapshot-internal.h \
lttng/health-internal.h \
lttng/action/notify-internal.h \
lttng/condition/condition-internal.h \
lttng/condition/buffer-usage-internal.h \
+ lttng/condition/event-rule-internal.h \
lttng/condition/session-consumed-size-internal.h \
lttng/condition/evaluation-internal.h \
lttng/condition/session-rotation-internal.h \
lttng/session-internal.h \
lttng/session-descriptor-internal.h \
lttng/tracker-internal.h \
+ lttng/event-rule/event-rule-internal.h \
+ lttng/event-rule/kprobe-internal.h \
+ lttng/event-rule/kretprobe-internal.h \
+ lttng/event-rule/uprobe-internal.h \
+ lttng/event-rule/syscall-internal.h \
+ lttng/event-rule/tracepoint-internal.h \
version.h \
version.i
#include <common/dynamic-buffer.h>
#include <stdbool.h>
#include <sys/types.h>
+#include <urcu/ref.h>
typedef bool (*action_validate_cb)(struct lttng_action *action);
typedef void (*action_destroy_cb)(struct lttng_action *action);
typedef int (*action_serialize_cb)(struct lttng_action *action,
struct lttng_dynamic_buffer *buf);
+typedef bool (*action_equal_cb)(const struct lttng_action *a,
+ const struct lttng_action *b);
+typedef ssize_t (*action_create_from_buffer_cb)(
+ const struct lttng_buffer_view *view,
+ struct lttng_action **action);
struct lttng_action {
+ struct urcu_ref ref;
enum lttng_action_type type;
action_validate_cb validate;
action_serialize_cb serialize;
+ action_equal_cb equal;
action_destroy_cb destroy;
};
int8_t action_type;
} LTTNG_PACKED;
+LTTNG_HIDDEN
+void lttng_action_init(struct lttng_action *action,
+ enum lttng_action_type type,
+ action_validate_cb validate,
+ action_serialize_cb serialize,
+ action_equal_cb equal,
+ action_destroy_cb destroy);
+
LTTNG_HIDDEN
bool lttng_action_validate(struct lttng_action *action);
enum lttng_action_type lttng_action_get_type_const(
const struct lttng_action *action);
+LTTNG_HIDDEN
+bool lttng_action_is_equal(const struct lttng_action *a,
+ const struct lttng_action *b);
+
+LTTNG_HIDDEN
+void lttng_action_get(struct lttng_action *action);
+
+LTTNG_HIDDEN
+void lttng_action_put(struct lttng_action *action);
+
+LTTNG_HIDDEN
+const char* lttng_action_type_string(enum lttng_action_type action_type);
+
#endif /* LTTNG_ACTION_INTERNAL_H */
enum lttng_action_type {
LTTNG_ACTION_TYPE_UNKNOWN = -1,
LTTNG_ACTION_TYPE_NOTIFY = 0,
+ LTTNG_ACTION_TYPE_START_SESSION = 1,
+ LTTNG_ACTION_TYPE_STOP_SESSION = 2,
+ LTTNG_ACTION_TYPE_ROTATE_SESSION = 3,
+ LTTNG_ACTION_TYPE_SNAPSHOT_SESSION = 4,
+ LTTNG_ACTION_TYPE_GROUP = 5,
+};
+
+enum lttng_action_status {
+ LTTNG_ACTION_STATUS_OK = 0,
+ LTTNG_ACTION_STATUS_ERROR = -1,
+ LTTNG_ACTION_STATUS_UNKNOWN = -2,
+ LTTNG_ACTION_STATUS_INVALID = -3,
+ LTTNG_ACTION_STATUS_UNSET = -4,
};
/*
* Returns the type of an action on success, LTTNG_ACTION_TYPE_UNKNOWN on error.
*/
extern enum lttng_action_type lttng_action_get_type(
- struct lttng_action *action);
+ const struct lttng_action *action);
/*
* Destroy (frees) an action object.
--- /dev/null
+/*
+ * Copyright (C) 2019 EfficiOS, Inc.
+ *
+ * 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
+ */
+
+#ifndef LTTNG_ACTION_GROUP_INTERNAL_H
+#define LTTNG_ACTION_GROUP_INTERNAL_H
+
+#include <sys/types.h>
+
+#include <common/macros.h>
+
+struct lttng_action;
+struct lttng_buffer_view;
+
+/*
+ * Create an action group from a buffer view.
+ *
+ * On success, return the number of bytes consumed from `view`, and the created
+ * group in `*group`. On failure, return -1.
+ */
+LTTNG_HIDDEN
+extern ssize_t lttng_action_group_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_action **group);
+
+#endif /* LTTNG_ACTION_GROUP_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 EfficiOS, inc.
+ *
+ * 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
+ */
+
+#ifndef LTTNG_ACTION_GROUP_H
+#define LTTNG_ACTION_GROUP_H
+
+struct lttng_action;
+struct lttng_action_group;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Create a newly allocated action group object.
+ *
+ * Returns a new action group on success, NULL on failure. This action group
+ * must be destroyed using lttng_action_group_destroy().
+ */
+extern struct lttng_action *lttng_action_group_create(void);
+
+/*
+ * Add an action to an lttng_action object of type LTTNG_ACTION_GROUP.
+ *
+ * The group takes ownership of the action.
+ */
+extern enum lttng_action_status lttng_action_group_add_action(
+ struct lttng_action *group, struct lttng_action *action);
+
+extern enum lttng_action_status lttng_action_group_get_count(
+ const struct lttng_action *group, unsigned int *count);
+
+extern const struct lttng_action *lttng_action_group_get_at_index_const(
+ const struct lttng_action *group,
+ unsigned int index);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_ACTION_GROUP_H */
struct lttng_action parent;
};
+LTTNG_HIDDEN
+ssize_t lttng_action_notify_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_action **action);
+
#endif /* LTTNG_ACTION_NOTIFY_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 EfficiOS, Inc.
+ *
+ * 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
+ */
+
+#ifndef LTTNG_ACTION_ROTATE_SESSION_INTERNAL_H
+#define LTTNG_ACTION_ROTATE_SESSION_INTERNAL_H
+
+#include <sys/types.h>
+
+#include <common/macros.h>
+
+struct lttng_action;
+struct lttng_buffer_view;
+
+/*
+ * Create a "rotate session" action from a buffer view.
+ *
+ * On success, return the number of bytes consumed from `view`, and the created
+ * action in `*action`. On failure, return -1.
+ */
+LTTNG_HIDDEN
+extern ssize_t lttng_action_rotate_session_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_action **action);
+
+#endif /* LTTNG_ACTION_ROTATE_SESSION_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 EfficiOS, inc.
+ *
+ * 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
+ */
+
+#ifndef LTTNG_ACTION_ROTATE_SESSION_H
+#define LTTNG_ACTION_ROTATE_SESSION_H
+
+struct lttng_action;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Create a newly allocated rotate-session action object.
+ *
+ * Returns a new action on success, NULL on failure. This action must be
+ * destroyed using lttng_action_destroy().
+ */
+extern struct lttng_action *lttng_action_rotate_session_create(void);
+
+/*
+ * Set the session name of an lttng_action object of type
+ * LTTNG_ACTION_TYPE_ROTATE_SESSION.
+ */
+extern enum lttng_action_status lttng_action_rotate_session_set_session_name(
+ struct lttng_action *action, const char *session_name);
+
+/*
+ * Get the session name of an lttng_action object of type
+ * LTTNG_ACTION_TYPE_ROTATE_SESSION.
+ */
+extern enum lttng_action_status lttng_action_rotate_session_get_session_name(
+ const struct lttng_action *action, const char **session_name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_ACTION_ROTATE_SESSION_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 EfficiOS, Inc.
+ *
+ * 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
+ */
+
+#ifndef LTTNG_ACTION_SNAPSHOT_SESSION_INTERNAL_H
+#define LTTNG_ACTION_SNAPSHOT_SESSION_INTERNAL_H
+
+#include <sys/types.h>
+
+#include <common/macros.h>
+
+struct lttng_action;
+struct lttng_buffer_view;
+
+/*
+ * Create a "snapshot session" action from a buffer view.
+ *
+ * On success, return the number of bytes consumed from `view`, and the created
+ * action in `*action`. On failure, return -1.
+ */
+LTTNG_HIDDEN
+extern ssize_t lttng_action_snapshot_session_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_action **action);
+
+#endif /* LTTNG_ACTION_SNAPSHOT_SESSION_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 EfficiOS, inc.
+ *
+ * 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
+ */
+
+#ifndef LTTNG_ACTION_SNAPSHOT_SESSION_H
+#define LTTNG_ACTION_SNAPSHOT_SESSION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct lttng_action;
+struct lttng_snapshot_output;
+
+/*
+ * Create a newly allocated snapshot-session action object.
+ *
+ * Returns a new action on success, NULL on failure. This action must be
+ * destroyed using lttng_action_destroy().
+ */
+extern struct lttng_action *lttng_action_snapshot_session_create(void);
+
+/*
+ * Set the session name of an lttng_action object of type
+ * LTTNG_ACTION_TYPE_SNAPSHOT_SESSION.
+ */
+extern enum lttng_action_status lttng_action_snapshot_session_set_session_name(
+ struct lttng_action *action, const char *session_name);
+
+/*
+ * Get the session name of an lttng_action object of type
+ * LTTNG_ACTION_TYPE_SNAPSHOT_SESSION.
+ */
+extern enum lttng_action_status lttng_action_snapshot_session_get_session_name(
+ const struct lttng_action *action, const char **session_name);
+
+/*
+ * Set an explicit snapshot output for this snapshot session action.
+ *
+ * The given snapshot output will be used instead of the session's
+ * default snapshot output.
+ *
+ * This function takes ownership of the given snapshot output.
+ */
+extern enum lttng_action_status lttng_action_snapshot_session_set_output(
+ struct lttng_action *action,
+ struct lttng_snapshot_output *output);
+
+/*
+ * Get the explicit snapshot output for this snapshot session action.
+ */
+extern enum lttng_action_status lttng_action_snapshot_session_get_output_const(
+ const struct lttng_action *action,
+ const struct lttng_snapshot_output **output);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_ACTION_SNAPSHOT_SESSION_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 EfficiOS, Inc.
+ *
+ * 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
+ */
+
+#ifndef LTTNG_ACTION_START_SESSION_INTERNAL_H
+#define LTTNG_ACTION_START_SESSION_INTERNAL_H
+
+#include <sys/types.h>
+
+#include <common/macros.h>
+
+struct lttng_action;
+struct lttng_buffer_view;
+
+/*
+ * Create a "start session" action from a buffer view.
+ *
+ * On success, return the number of bytes consumed from `view`, and the created
+ * action in `*action`. On failure, return -1.
+ */
+LTTNG_HIDDEN
+extern ssize_t lttng_action_start_session_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_action **action);
+
+#endif /* LTTNG_ACTION_START_SESSION_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 EfficiOS, inc.
+ *
+ * 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
+ */
+
+#ifndef LTTNG_ACTION_START_SESSION_H
+#define LTTNG_ACTION_START_SESSION_H
+
+struct lttng_action;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Create a newly allocated start-session action object.
+ *
+ * Returns a new action on success, NULL on failure. This action must be
+ * destroyed using lttng_action_destroy().
+ */
+extern struct lttng_action *lttng_action_start_session_create(void);
+
+/*
+ * Set the session name of an lttng_action object of type
+ * LTTNG_ACTION_TYPE_START_SESSION.
+ */
+extern enum lttng_action_status lttng_action_start_session_set_session_name(
+ struct lttng_action *action, const char *session_name);
+
+/*
+ * Get the session name of an lttng_action object of type
+ * LTTNG_ACTION_TYPE_START_SESSION.
+ */
+extern enum lttng_action_status lttng_action_start_session_get_session_name(
+ const struct lttng_action *action, const char **session_name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_ACTION_START_SESSION_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 EfficiOS, Inc.
+ *
+ * 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
+ */
+
+#ifndef LTTNG_ACTION_STOP_SESSION_INTERNAL_H
+#define LTTNG_ACTION_STOP_SESSION_INTERNAL_H
+
+#include <sys/types.h>
+
+#include <common/macros.h>
+
+struct lttng_action;
+struct lttng_buffer_view;
+
+/*
+ * Create a "stop session" action from a buffer view.
+ *
+ * On success, return the number of bytes consumed from `view`, and the created
+ * action in `*action`. On failure, return -1.
+ */
+LTTNG_HIDDEN
+extern ssize_t lttng_action_stop_session_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_action **action);
+
+#endif /* LTTNG_ACTION_STOP_SESSION_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 EfficiOS, inc.
+ *
+ * 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
+ */
+
+#ifndef LTTNG_ACTION_STOP_SESSION_H
+#define LTTNG_ACTION_STOP_SESSION_H
+
+struct lttng_action;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Create a newly allocated stop-session action object.
+ *
+ * Returns a new action on success, NULL on failure. This action must be
+ * destroyed using lttng_action_destroy().
+ */
+extern struct lttng_action *lttng_action_stop_session_create(void);
+
+/*
+ * Set the session name of an lttng_action object of type
+ * LTTNG_ACTION_TYPE_STOP_SESSION.
+ */
+extern enum lttng_action_status lttng_action_stop_session_set_session_name(
+ struct lttng_action *action, const char *session_name);
+
+/*
+ * Get the session name of an lttng_action object of type
+ * LTTNG_ACTION_TYPE_STOP_SESSION.
+ */
+extern enum lttng_action_status lttng_action_stop_session_get_session_name(
+ const struct lttng_action *action, const char **session_name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_ACTION_STOP_SESSION_H */
typedef bool (*condition_validate_cb)(const struct lttng_condition *condition);
typedef int (*condition_serialize_cb)(
const struct lttng_condition *condition,
- struct lttng_dynamic_buffer *buf);
+ struct lttng_dynamic_buffer *buf,
+ int *fd_to_send);
typedef bool (*condition_equal_cb)(const struct lttng_condition *a,
const struct lttng_condition *b);
typedef ssize_t (*condition_create_from_buffer_cb)(
LTTNG_HIDDEN
int lttng_condition_serialize(const struct lttng_condition *condition,
- struct lttng_dynamic_buffer *buf);
+ struct lttng_dynamic_buffer *buf,
+ int *fd_to_send);
LTTNG_HIDDEN
bool lttng_condition_is_equal(const struct lttng_condition *a,
const struct lttng_condition *b);
+LTTNG_HIDDEN
+const char *lttng_condition_type_str(enum lttng_condition_type type);
+
#endif /* LTTNG_CONDITION_INTERNAL_H */
LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW = 102,
LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING = 103,
LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED = 104,
+ LTTNG_CONDITION_TYPE_EVENT_RULE_HIT = 105,
};
enum lttng_condition_status {
--- /dev/null
+/*
+ * Copyright (C) 2019 - Jonathan Rajotte <jonathan.rajotte-julien@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
+ */
+
+#ifndef LTTNG_CONDITION_event_rule_INTERNAL_H
+#define LTTNG_CONDITION_event_rule_INTERNAL_H
+
+#include <lttng/condition/condition-internal.h>
+#include <common/buffer-view.h>
+#include <common/macros.h>
+#include <lttng/condition/evaluation-internal.h>
+
+struct lttng_condition_event_rule {
+ struct lttng_condition parent;
+ struct lttng_event_rule *rule;
+};
+
+struct lttng_condition_event_rule_comm {
+ /* length excludes its own length */
+ uint32_t length;
+ /* rule */
+ char payload[];
+} LTTNG_PACKED;
+
+struct lttng_evaluation_event_rule {
+ struct lttng_evaluation parent;
+ char *name;
+};
+
+struct lttng_evaluation_event_rule_comm {
+ uint32_t trigger_name_length;
+ /* Trigger name */
+ char payload[];
+} LTTNG_PACKED;
+
+
+LTTNG_HIDDEN
+ssize_t lttng_condition_event_rule_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_condition **condition);
+
+LTTNG_HIDDEN
+enum lttng_condition_status
+lttng_condition_event_rule_get_rule_no_const(
+ const struct lttng_condition *condition,
+ struct lttng_event_rule **rule);
+
+LTTNG_HIDDEN
+struct lttng_evaluation *lttng_evaluation_event_rule_create(const char* trigger_name);
+
+LTTNG_HIDDEN
+ssize_t lttng_evaluation_event_rule_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_evaluation **_evaluation);
+
+#endif /* LTTNG_CONDITION_event_rule_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 - Jonathan Rajotte <jonathan.rajotte-julien@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
+ */
+
+#ifndef LTTNG_CONDITION_EVENT_RULE_H
+#define LTTNG_CONDITION_EVENT_RULE_H
+
+#include <lttng/event-rule/event-rule.h>
+#include <lttng/condition/condition.h>
+#include <lttng/condition/evaluation.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * TODO: overall desciption of an event rule condition.
+ */
+
+/*
+ * Create a newly allocated event rule condition.
+ *
+ * Rule will be copied internally.
+ *
+ * Returns a new condition on success, NULL on failure. This condition must be
+ * destroyed using lttng_condition_destroy().
+ */
+extern struct lttng_condition *lttng_condition_event_rule_create(
+ struct lttng_event_rule *rule);
+
+/*
+ * Get the rule property of a event rule condition.
+ *
+ * The caller does not assume the ownership of the returned rule. The
+ * rule shall only be used for the duration of the condition's
+ * lifetime.
+ *
+ * Returns LTTNG_CONDITION_STATUS_OK and a pointer to the condition's rule
+ * on success, LTTNG_CONDITION_STATUS_INVALID if an invalid
+ * parameter is passed. */
+extern enum lttng_condition_status lttng_condition_event_rule_get_rule(
+ const struct lttng_condition *condition, const struct lttng_event_rule **rule);
+
+/**
+ * lttng_evaluation_event_rule_hit are specialised lttng_evaluations which
+ * allow users to query a number of properties resulting from the evaluation
+ * of a condition which evaluated to true.
+ *
+ * The evaluation of a event rule hit yields two different results:
+ * TEMPORARY - The name of the triggers associated with the condition.
+ * TODO - The captured event payload if any
+ */
+
+/*
+ * Get the trigger name property of a event rule hit evaluation.
+ *
+ * Returns LTTNG_EVALUATION_STATUS_OK on success and a trigger name
+ * or LTTNG_EVALUATION_STATUS_INVALID if
+ * an invalid parameter is passed.
+ */
+extern enum lttng_evaluation_status
+lttng_evaluation_event_rule_get_trigger_name(
+ const struct lttng_evaluation *evaluation,
+ const char **name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_CONDITION_EVENT_RULE_H */
--- /dev/null
+/*
+ * Copyright (C) 2020 - EfficiOS, inc.
+ *
+ * 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
+ */
+
+#ifndef LTTNG_DOMAIN_INTERNAL_H
+#define LTTNG_DOMAIN_INTERNAL_H
+
+#include "lttng/domain.h"
+#include "common/macros.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LTTNG_HIDDEN
+const char *lttng_domain_type_str(enum lttng_domain_type domain_type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_DOMAIN_INTERNAL_H */
LTTNG_HIDDEN
struct lttng_event *lttng_event_copy(const struct lttng_event *event);
+// FIXME: the implementation of these should be moved to some common file,
+// they should not be in the enable_events.c file.
+
+LTTNG_HIDDEN
+int loglevel_str_to_value(const char *inputstr);
+
+LTTNG_HIDDEN
+int loglevel_log4j_str_to_value(const char *inputstr);
+
+LTTNG_HIDDEN
+int loglevel_jul_str_to_value(const char *inputstr);
+
+LTTNG_HIDDEN
+int loglevel_python_str_to_value(const char *inputstr);
+
#endif /* LTTNG_EVENT_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 - Jonathan Rajotte-Julien
+ * <jonathan.rajotte-julien@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
+ */
+
+#ifndef LTTNG_EVENT_RULE_INTERNAL_H
+#define LTTNG_EVENT_RULE_INTERNAL_H
+
+#include <common/buffer-view.h>
+#include <common/dynamic-buffer.h>
+#include <common/macros.h>
+#include <lttng/event.h>
+#include <lttng/event-rule/event-rule.h>
+#include <lttng/lttng-error.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <urcu/ref.h>
+
+typedef void (*event_rule_destroy_cb)(struct lttng_event_rule *event_rule);
+typedef bool (*event_rule_validate_cb)(
+ const struct lttng_event_rule *event_rule);
+typedef int (*event_rule_serialize_cb)(
+ const struct lttng_event_rule *event_rule,
+ struct lttng_dynamic_buffer *buf,
+ int *fd_to_send);
+typedef bool (*event_rule_equal_cb)(const struct lttng_event_rule *a,
+ const struct lttng_event_rule *b);
+typedef ssize_t (*event_rule_create_from_buffer_cb)(
+ const struct lttng_buffer_view *view,
+ struct lttng_event_rule **event_rule);
+typedef enum lttng_error_code (*event_rule_populate_cb)(
+ struct lttng_event_rule *event_rule, uid_t uid, gid_t gid);
+typedef const char *(*event_rule_get_filter_cb)(
+ const struct lttng_event_rule *event_rule);
+typedef const struct lttng_filter_bytecode *(
+ *event_rule_get_filter_bytecode_cb)(
+ const struct lttng_event_rule *event_rule);
+typedef struct lttng_event_exclusion *(*event_rule_generate_exclusions_cb)(
+ struct lttng_event_rule *event_rule);
+typedef struct lttng_event *(*event_rule_generate_lttng_event_cb)(
+ const struct lttng_event_rule *event_rule);
+
+struct lttng_event_rule {
+ struct urcu_ref ref;
+ enum lttng_event_rule_type type;
+ event_rule_validate_cb validate;
+ event_rule_serialize_cb serialize;
+ event_rule_equal_cb equal;
+ event_rule_destroy_cb destroy;
+ event_rule_populate_cb populate;
+ /* Optional */
+ event_rule_get_filter_cb get_filter;
+ event_rule_get_filter_bytecode_cb get_filter_bytecode;
+ event_rule_generate_exclusions_cb generate_exclusions;
+ event_rule_generate_lttng_event_cb generate_lttng_event;
+};
+
+struct lttng_event_rule_comm {
+ /* enum lttng_event_rule_type */
+ int8_t event_rule_type;
+ char payload[];
+};
+
+LTTNG_HIDDEN
+void lttng_event_rule_init(struct lttng_event_rule *event_rule,
+ enum lttng_event_rule_type type);
+
+LTTNG_HIDDEN
+bool lttng_event_rule_validate(const struct lttng_event_rule *event_rule);
+
+LTTNG_HIDDEN
+ssize_t lttng_event_rule_create_from_buffer(
+ const struct lttng_buffer_view *buffer,
+ struct lttng_event_rule **event_rule);
+
+LTTNG_HIDDEN
+int lttng_event_rule_serialize(const struct lttng_event_rule *event_rule,
+ struct lttng_dynamic_buffer *buf,
+ int *fd_to_send);
+
+LTTNG_HIDDEN
+bool lttng_event_rule_is_equal(const struct lttng_event_rule *a,
+ const struct lttng_event_rule *b);
+
+LTTNG_HIDDEN
+bool lttng_event_rule_get(struct lttng_event_rule *rule);
+
+LTTNG_HIDDEN
+void lttng_event_rule_put(struct lttng_event_rule *rule);
+
+LTTNG_HIDDEN
+enum lttng_domain_type lttng_event_rule_get_domain_type(
+ const struct lttng_event_rule *rule);
+
+LTTNG_HIDDEN
+enum lttng_error_code lttng_event_rule_populate(
+ struct lttng_event_rule *rule, uid_t uid, gid_t gid);
+
+/* If not present return NULL
+ * Caller DO NOT own the returned object
+ */
+LTTNG_HIDDEN
+const char *lttng_event_rule_get_filter(const struct lttng_event_rule *rule);
+
+/* If not present return NULL
+ * Caller DO NOT own the returned object
+ */
+LTTNG_HIDDEN
+const struct lttng_filter_bytecode *lttng_event_rule_get_filter_bytecode(
+ const struct lttng_event_rule *rule);
+
+/*
+ * If not present return NULL
+ * Caller OWN the returned object
+ * TODO: should this be done another way?
+ */
+LTTNG_HIDDEN
+struct lttng_event_exclusion *lttng_event_rule_generate_exclusions(
+ struct lttng_event_rule *rule);
+
+/*
+ * This is compatibility helper, allowing us to generate a sessiond side (not
+ * communication) struct lttng_event object. This facilitate integration with
+ * current code.
+ * Caller OWN the returned object
+ */
+LTTNG_HIDDEN
+struct lttng_event *lttng_event_rule_generate_lttng_event(
+ const struct lttng_event_rule *rule);
+
+/* Quick helper to test if the event rule apply to an agent domain */
+LTTNG_HIDDEN
+bool lttng_event_rule_is_agent(const struct lttng_event_rule *rule);
+
+LTTNG_HIDDEN
+const char *lttng_event_rule_type_str(enum lttng_event_rule_type type);
+
+#endif /* LTTNG_EVENT_RULE_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 - Jonathan Rajotte-Julien <jonathan.rajotte-julien@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
+ */
+
+#ifndef LTTNG_EVENT_RULE_H
+#define LTTNG_EVENT_RULE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct lttng_event_rule;
+
+enum lttng_event_rule_type {
+ LTTNG_EVENT_RULE_TYPE_UNKNOWN = -1,
+ LTTNG_EVENT_RULE_TYPE_TRACEPOINT = 100,
+ LTTNG_EVENT_RULE_TYPE_SYSCALL = 101,
+ LTTNG_EVENT_RULE_TYPE_KPROBE = 102,
+ LTTNG_EVENT_RULE_TYPE_KRETPROBE = 103,
+ LTTNG_EVENT_RULE_TYPE_UPROBE = 104,
+};
+
+
+enum lttng_event_rule_status {
+ LTTNG_EVENT_RULE_STATUS_OK = 0,
+ LTTNG_EVENT_RULE_STATUS_ERROR = -1,
+ LTTNG_EVENT_RULE_STATUS_UNKNOWN = -2,
+ LTTNG_EVENT_RULE_STATUS_INVALID = -3,
+ LTTNG_EVENT_RULE_STATUS_UNSET = -4,
+ LTTNG_EVENT_RULE_STATUS_UNSUPPORTED = -5,
+};
+
+/**
+ * Event rule describe a set of criteria to be used as a discriminant in regards
+ * to a set of events.
+ *
+ * Event rule have the following base properties:
+ * - the instrumentation type for the event rule,
+ * - tracepoint
+ * - syscall
+ * - probe
+ * - userspace-probe
+ * - the domain the event rule covers.
+ */
+
+/*
+ * Get the event rule type.
+ *
+ * Returns the type of an event rule on success, LTTNG_EVENT_RULE_UNKNOWN on
+ * error.
+ */
+extern enum lttng_event_rule_type lttng_event_rule_get_type(
+ const struct lttng_event_rule *event_rule);
+
+/*
+ * Destroy (release) a event_rule object.
+ */
+extern void lttng_event_rule_destroy(struct lttng_event_rule *rule);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_EVENT_RULE_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 - Jonathan Rajotte-Julien <jonathan.rajotte-julien@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
+ */
+
+#ifndef LTTNG_EVENT_RULE_KPROBE_INTERNAL_H
+#define LTTNG_EVENT_RULE_KPROBE_INTERNAL_H
+
+#include <lttng/event-rule/kprobe.h>
+#include <lttng/event-rule/event-rule-internal.h>
+#include <common/buffer-view.h>
+#include <common/macros.h>
+
+struct lttng_event_rule_kprobe {
+ struct lttng_event_rule parent;
+ char *name;
+ struct {
+ uint64_t address;
+ uint64_t offset;
+ char *symbol_name;
+ bool set;
+ } probe;
+};
+
+struct lttng_event_rule_kprobe_comm {
+ uint32_t name_len;
+ uint32_t probe_symbol_name_len;
+ uint64_t probe_address;
+ uint64_t probe_offset;
+ /* name, source symbol_name */
+ char payload[];
+} LTTNG_PACKED;
+
+LTTNG_HIDDEN
+ssize_t lttng_event_rule_kprobe_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_event_rule **rule);
+
+LTTNG_HIDDEN
+uint64_t lttng_event_rule_kprobe_get_address(
+ const struct lttng_event_rule *rule);
+
+LTTNG_HIDDEN
+uint64_t lttng_event_rule_kprobe_get_offset(
+ const struct lttng_event_rule *rule);
+
+LTTNG_HIDDEN
+const char *lttng_event_rule_kprobe_get_symbol_name(
+ const struct lttng_event_rule *rule);
+
+#endif /* LTTNG_EVENT_RULE_KPROBE_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 - Jonathan Rajotte-Julien <jonathan.rajotte-julien@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
+ */
+
+#ifndef LTTNG_EVENT_RULE_KPROBE_H
+#define LTTNG_EVENT_RULE_KPROBE_H
+
+#include <lttng/event-rule/event-rule.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * TODO:
+ */
+extern struct lttng_event_rule *lttng_event_rule_kprobe_create(void);
+
+/*
+ * Set the source of a kprobe event rule.
+ *
+ * TODO: list possible format
+ *
+ * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_kprobe_set_source(
+ struct lttng_event_rule *rule, const char *source);
+
+/*
+ * Set the name of a kprobe event rule.
+ *
+ * The name is copied.
+ *
+ * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_kprobe_set_name(
+ struct lttng_event_rule *rule, const char *name);
+
+/*
+ * Get the name of a kprobe event rule.
+ *
+ * The caller does not assume the ownership of the returned name.
+ * The name shall only only be used for the duration of the event
+ * rule's lifetime, or before a different name is set.
+ *
+ * Returns LTTNG_EVENT_RULE_STATUS_OK and a pointer to the event rule's name on
+ * success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid parameter is passed,
+ * or LTTNG_EVENT_RULE_STATUS_UNSET if a name was not set prior to this call.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_kprobe_get_name(
+ const struct lttng_event_rule *rule, const char **name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_EVENT_RULE_KPROBE_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 - Jonathan Rajotte-Julien <jonathan.rajotte-julien@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
+ */
+
+#ifndef LTTNG_EVENT_RULE_KRETPROBE_INTERNAL_H
+#define LTTNG_EVENT_RULE_KRETPROBE_INTERNAL_H
+
+#include <lttng/event-rule/kretprobe.h>
+#include <lttng/event-rule/event-rule-internal.h>
+#include <common/buffer-view.h>
+#include <common/macros.h>
+
+struct lttng_event_rule_kretprobe {
+ struct lttng_event_rule parent;
+ char *name;
+ struct {
+ uint64_t address;
+ uint64_t offset;
+ char *symbol_name;
+ } probe;
+};
+
+struct lttng_event_rule_kretprobe_comm {
+ uint32_t name_len;
+ uint32_t probe_symbol_len;
+ /*name, probe symbol_name */
+ char payload[];
+} LTTNG_PACKED;
+
+LTTNG_HIDDEN
+ssize_t lttng_event_rule_kretprobe_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_event_rule **rule);
+
+LTTNG_HIDDEN
+uint64_t lttng_event_rule_kretprobe_get_address(
+ const struct lttng_event_rule *rule);
+
+LTTNG_HIDDEN
+uint64_t lttng_event_rule_kretprobe_get_offset(
+ const struct lttng_event_rule *rule);
+
+LTTNG_HIDDEN
+const char *lttng_event_rule_kretprobe_get_symbol_name(
+ const struct lttng_event_rule *rule);
+
+#endif /* LTTNG_EVENT_RULE_KRETPROBE_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 - Jonathan Rajotte-Julien <jonathan.rajotte-julien@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
+ */
+
+#ifndef LTTNG_EVENT_RULE_KRETPROBE_H
+#define LTTNG_EVENT_RULE_KRETPROBE_H
+
+#include <lttng/event-rule/event-rule.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * TODO:
+ */
+extern struct lttng_event_rule *lttng_event_rule_kretprobe_create(void);
+
+/*
+ * Set the source of a kretprobe event rule.
+ *
+ * TODO: list possible format
+ *
+ * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_kretprobe_set_source(
+ struct lttng_event_rule *rule, const char *source);
+
+/*
+ * Set the name of a kretprobe event rule.
+ *
+ * The name is copied.
+ *
+ * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_kretprobe_set_name(
+ struct lttng_event_rule *rule, const char *name);
+
+/*
+ * Get the name of a kretprobe event rule.
+ *
+ * The caller does not assume the ownership of the returned name.
+ * The name shall only only be used for the duration of the event
+ * rule's lifetime, or before a different name is set.
+ *
+ * Returns LTTNG_EVENT_RULE_STATUS_OK and a pointer to the event rule's name on
+ * success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid parameter is passed,
+ * or LTTNG_EVENT_RULE_STATUS_UNSET if a name was not set prior to this call.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_kretprobe_get_name(
+ const struct lttng_event_rule *rule, const char **name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_EVENT_RULE_KRETPROBE_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 - Jonathan Rajotte-Julien <jonathan.rajotte-julien@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
+ */
+
+#ifndef LTTNG_EVENT_RULE_SYSCALL_INTERNAL_H
+#define LTTNG_EVENT_RULE_SYSCALL_INTERNAL_H
+
+#include <lttng/event-rule/syscall.h>
+#include <lttng/event-rule/event-rule-internal.h>
+#include <common/buffer-view.h>
+#include <common/macros.h>
+
+struct lttng_event_rule_syscall {
+ struct lttng_event_rule parent;
+ char *pattern;
+ char *filter_expression;
+
+ /* internal use only */
+ struct {
+ char *filter;
+ struct lttng_filter_bytecode *bytecode;
+ } internal_filter;
+};
+
+struct lttng_event_rule_syscall_comm {
+ uint32_t pattern_len;
+ uint32_t filter_expression_len;
+ /* pattern, filter expression */
+ char payload[];
+} LTTNG_PACKED;
+
+LTTNG_HIDDEN
+ssize_t lttng_event_rule_syscall_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_event_rule **rule);
+
+#endif /* LTTNG_EVENT_RULE_SYSCALL_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 - Jonathan Rajotte-Julien <jonathan.rajotte-julien@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
+ */
+
+#ifndef LTTNG_EVENT_RULE_SYSCALL_H
+#define LTTNG_EVENT_RULE_SYSCALL_H
+
+#include <lttng/event-rule/event-rule.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * TODO:
+ */
+extern struct lttng_event_rule *lttng_event_rule_syscall_create(void);
+
+/*
+ * Set the pattern of a syscall event rule.
+ *
+ * Pattern can contains wildcard '*'. See man lttng-enable-event.
+ *
+ * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_syscall_set_pattern(
+ struct lttng_event_rule *rule, const char *pattern);
+
+/*
+ * Get the pattern of a tracecpoint event rule.
+ *
+ * The caller does not assume the ownership of the returned pattern. The
+ * pattern shall only only be used for the duration of the event rule's
+ * lifetime, or before a different pattern is set.
+ *
+ * Returns LTTNG_EVENT_RULE_STATUS_OK and a pointer to the event rule's pattern
+ * on success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid
+ * parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a pattern
+ * was not set prior to this call.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_syscall_get_pattern(
+ const struct lttng_event_rule *rule, const char **pattern);
+
+/*
+ * Set the filter expression of a syscall event rule.
+ *
+ * The expression is copied.
+ *
+ * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_syscall_set_filter(
+ struct lttng_event_rule *rule, const char *expression);
+
+/*
+ * Get the filter expression of a syscall event rule.
+ *
+ * The caller does not assume the ownership of the returned filter expression.
+ * The filter expression shall only only be used for the duration of the event
+ * rule's lifetime, or before a different filter expression is set.
+ *
+ * Returns LTTNG_EVENT_RULE_STATUS_OK and a pointer to the event rule's filter
+ * expression on success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid
+ * parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a filter expression
+ * was not set prior to this call.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_syscall_get_filter(
+ const struct lttng_event_rule *rule, const char **expression);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_EVENT_RULE_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 - Jonathan Rajotte-Julien <jonathan.rajotte-julien@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
+ */
+
+#ifndef LTTNG_EVENT_RULE_TRACEPOINT_INTERNAL_H
+#define LTTNG_EVENT_RULE_TRACEPOINT_INTERNAL_H
+
+#include <lttng/event-rule/tracepoint.h>
+#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/domain.h>
+#include <lttng/event.h>
+#include <common/buffer-view.h>
+#include <common/macros.h>
+
+struct lttng_event_rule_tracepoint {
+ struct lttng_event_rule parent;
+
+ /* Domain */
+ enum lttng_domain_type domain;
+
+ /* Name pattern */
+ char *pattern;
+
+ /* Filter */
+ char *filter_expression;
+
+ /* Loglevel */
+ struct {
+ enum lttng_loglevel_type type;
+ int value;
+ } loglevel;
+
+ /* Exclusions */
+
+ struct {
+ char **values;
+ unsigned int count;
+ } exclusions;
+
+ /* internal use only */
+ struct {
+ char *filter;
+ struct lttng_filter_bytecode *bytecode;
+ } internal_filter;
+};
+
+struct lttng_event_rule_tracepoint_comm {
+ /* enum lttng_domain_type */
+ int8_t domain_type;
+ /* enum lttng_event_logleven_type */
+ int8_t loglevel_type;
+ int32_t loglevel_value;
+ uint32_t pattern_len;
+ uint32_t filter_expression_len;
+ uint32_t exclusions_count;
+ uint32_t exclusions_len;
+ /*
+ * pattern, filter expression and exclusions each terminating with '\0'
+ */
+ char payload[];
+} LTTNG_PACKED;
+
+LTTNG_HIDDEN
+ssize_t lttng_event_rule_tracepoint_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_event_rule **rule);
+
+#endif /* LTTNG_EVENT_RULE_TRACEPOINT_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 - Jonathan Rajotte-Julien <jonathan.rajotte-julien@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
+ */
+
+#ifndef LTTNG_EVENT_RULE_TRACEPOINT_H
+#define LTTNG_EVENT_RULE_TRACEPOINT_H
+
+#include <lttng/event-rule/event-rule.h>
+#include <lttng/domain.h>
+#include <lttng/event.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * TODO:
+ */
+extern struct lttng_event_rule *lttng_event_rule_tracepoint_create(
+ enum lttng_domain_type domain);
+
+/*
+ * Set the pattern of a tracepoint event rule.
+ *
+ * Pattern can contains wildcard '*'. See man lttng-enable-event.
+ *
+ * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_tracepoint_set_pattern(
+ struct lttng_event_rule *rule, const char *pattern);
+
+/*
+ * Get the pattern of a tracepoint event rule.
+ *
+ * The caller does not assume the ownership of the returned pattern. The
+ * pattern shall only only be used for the duration of the event rule's
+ * lifetime, or before a different pattern is set.
+ *
+ * Returns LTTNG_EVENT_RULE_STATUS_OK and a pointer to the event rule's pattern
+ * on success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid
+ * parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a pattern
+ * was not set prior to this call.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_tracepoint_get_pattern(
+ const struct lttng_event_rule *rule, const char **pattern);
+
+/*
+ * Set the domain type of a tracepoint event rule.
+ *
+ * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_tracepoint_set_filter(
+ struct lttng_event_rule *rule, const char *expression);
+
+/*
+ * Get the domain type of a tracecpoint event rule.
+ *
+ * Returns LTTNG_EVENT_RULE_STATUS_OK and sets the domain type output parameter
+ * on success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid parameter is
+ * passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a pattern was not set prior to
+ * this call.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_tracepoint_get_domain_type(
+ const struct lttng_event_rule *rule,
+ enum lttng_domain_type *type);
+
+/*
+ * Set the filter expression of a tracepoint event rule.
+ *
+ * The expression is copied.
+ *
+ * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_tracepoint_set_filter(
+ struct lttng_event_rule *rule, const char *expression);
+
+/*
+ * Get the filter expression of a tracepoint event rule.
+ *
+ * The caller does not assume the ownership of the returned filter expression.
+ * The filter expression shall only only be used for the duration of the event
+ * rule's lifetime, or before a different filter expression is set.
+ *
+ * Returns LTTNG_EVENT_RULE_STATUS_OK and a pointer to the event rule's filter
+ * expression on success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid
+ * parameter is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a filter expression
+ * was not set prior to this call.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_tracepoint_get_filter(
+ const struct lttng_event_rule *rule, const char **expression);
+
+/*
+ * Set the single loglevel of a tracepoint event rule.
+ *
+ * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_tracepoint_set_loglevel(
+ struct lttng_event_rule *rule, int level);
+
+/*
+ * Set the loglevel range of a tracepoint event rule.
+ *
+ * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+extern enum lttng_event_rule_status
+lttng_event_rule_tracepoint_set_loglevel_range(
+ struct lttng_event_rule *rule, int level);
+
+/*
+ * Set the loglevel to all of a tracepoint event rule.
+ *
+ * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+extern enum lttng_event_rule_status
+lttng_event_rule_tracepoint_set_loglevel_all(struct lttng_event_rule *rule);
+
+/*
+ * Get the loglevel type of a tracepoint event rule.
+ *
+ * Returns LTTNG_EVENT_RULE_STATUS_OK and sets the loglevel type output
+ * parameter on success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid parameter
+ * is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a loglevel was not set prior
+ * to this call.
+ */
+extern enum lttng_event_rule_status
+lttng_event_rule_tracepoint_get_loglevel_type(
+ const struct lttng_event_rule *rule, enum lttng_loglevel_type *type);
+
+/*
+ * Get the loglevel of a tracepoint event rule.
+ *
+ * Returns LTTNG_EVENT_RULE_STATUS_OK and sets the loglevel output parameter
+ * on success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid parameter is
+ * passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a loglevel was not set prior to
+ * this call.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_tracepoint_get_loglevel(
+ const struct lttng_event_rule *rule, int *level);
+
+/*
+ * Set the exclusions property of a event rule.
+ *
+ * The passed exclusions will be copied to the event_rule.
+ *
+ * Returns LTTNG_EVENT_RULE_STATUS_OK on success,
+ * LTTNG_EVENT_RULE_STATUS_INVALID if invalid parameters are passed, or
+ * LTTNG_EVENT_RULE_STATUS_UNSUPPORTED if this property is not supported by the
+ * domain.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_tracepoint_set_exclusions(
+ struct lttng_event_rule *rule,
+ unsigned int count,
+ const char **exclusions);
+
+/*
+ * Get the exclusions property count of a event rule.
+ *
+ * Returns LTTNG_EVENT_RULE_STATUS_OK and sets the count output parameter
+ * on success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid parameter is
+ * passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a domain type was not set prior
+ * to this call.
+ */
+extern enum lttng_event_rule_status
+lttng_event_rule_tracepoint_get_exclusions_count(
+ const struct lttng_event_rule *rule, unsigned int *count);
+
+/*
+ * TODO:
+ * */
+extern enum lttng_event_rule_status
+lttng_event_rule_tracepoint_get_exclusion_at_index(
+ const struct lttng_event_rule *rule,
+ unsigned int index,
+ const char **exclusion);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_EVENT_RULE_TRACEPOINT_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 - Jonathan Rajotte-Julien <jonathan.rajotte-julien@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
+ */
+
+#ifndef LTTNG_EVENT_RULE_UPROBE_INTERNAL_H
+#define LTTNG_EVENT_RULE_UPROBE_INTERNAL_H
+
+#include <lttng/event-rule/uprobe.h>
+#include <lttng/event-rule/event-rule-internal.h>
+#include <common/buffer-view.h>
+#include <common/macros.h>
+
+struct lttng_event_rule_uprobe {
+ struct lttng_event_rule parent;
+ char *name;
+ struct lttng_userspace_probe_location *location;
+};
+
+struct lttng_event_rule_uprobe_comm {
+ uint32_t name_len;
+ uint32_t location_len;
+ /*name, location object */
+ char payload[];
+} LTTNG_PACKED;
+
+LTTNG_HIDDEN
+ssize_t lttng_event_rule_uprobe_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_event_rule **rule);
+
+LTTNG_HIDDEN
+struct lttng_userspace_probe_location *
+lttng_event_rule_uprobe_get_location_no_const(
+ const struct lttng_event_rule *rule);
+
+#endif /* LTTNG_EVENT_RULE_UPROBE_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2019 - Jonathan Rajotte-Julien <jonathan.rajotte-julien@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
+ */
+
+#ifndef LTTNG_EVENT_RULE_UPROBE_H
+#define LTTNG_EVENT_RULE_UPROBE_H
+
+#include <lttng/event-rule/event-rule.h>
+#include <lttng/userspace-probe.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * TODO:
+ */
+extern struct lttng_event_rule *lttng_event_rule_uprobe_create(void);
+
+/*
+ * Set the location of a uprobe event rule.
+ *
+ * The location is copied internally.
+ *
+ * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_uprobe_set_location(
+ struct lttng_event_rule *rule, const struct lttng_userspace_probe_location *location);
+
+/*
+ * Get the location of a uprobe event rule.
+ *
+ * The caller does not assume the ownership of the returned location.
+ * The location shall only be used for the duration of the event
+ * rule's lifetime, or before a different location is set.
+ *
+ * Returns LTTNG_EVENT_RULE_STATUS_OK and a pointer to the event rule's location
+ * on success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid parameter is passed,
+ * or LTTNG_EVENT_RULE_STATUS_UNSET if a location was not set prior to this call.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_uprobe_get_location(
+ const struct lttng_event_rule *rule,
+ const struct lttng_userspace_probe_location **location);
+
+/*
+ * Set the name of a uprobe event rule.
+ *
+ * The name is copied.
+ *
+ * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_uprobe_set_name(
+ struct lttng_event_rule *rule, const char *name);
+
+/*
+ * Get the name of a uprobe event rule.
+ *
+ * The caller does not assume the ownership of the returned name.
+ * The name shall only only be used for the duration of the event
+ * rule's lifetime, or before a different name is set.
+ *
+ * Returns LTTNG_EVENT_RULE_STATUS_OK and a pointer to the event rule's name on
+ * success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid parameter is passed,
+ * or LTTNG_EVENT_RULE_STATUS_UNSET if a name was not set prior to this call.
+ */
+extern enum lttng_event_rule_status lttng_event_rule_uprobe_get_name(
+ const struct lttng_event_rule *rule, const char **name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_EVENT_RULE_UPROBE_H */
#include <lttng/session-descriptor.h>
#include <lttng/destruction-handle.h>
#include <lttng/action/action.h>
+#include <lttng/action/group.h>
#include <lttng/action/notify.h>
+#include <lttng/action/rotate-session.h>
+#include <lttng/action/snapshot-session.h>
+#include <lttng/action/start-session.h>
+#include <lttng/action/stop-session.h>
#include <lttng/condition/condition.h>
#include <lttng/condition/buffer-usage.h>
#include <lttng/condition/session-consumed-size.h>
#include <lttng/condition/session-rotation.h>
#include <lttng/condition/evaluation.h>
+#include <lttng/condition/event-rule.h>
+#include <lttng/event-rule/event-rule.h>
+#include <lttng/event-rule/kprobe.h>
+#include <lttng/event-rule/kretprobe.h>
+#include <lttng/event-rule/syscall.h>
+#include <lttng/event-rule/tracepoint.h>
+#include <lttng/event-rule/uprobe.h>
#include <lttng/notification/channel.h>
#include <lttng/notification/notification.h>
#include <lttng/trigger/trigger.h>
size_t count;
/*
- * Containes snapshot output object.
+ * Contains snapshot output object.
*/
struct lttng_snapshot_output *array;
};
*/
/* Return snapshot ID. */
-uint32_t lttng_snapshot_output_get_id(struct lttng_snapshot_output *output);
+uint32_t lttng_snapshot_output_get_id(const struct lttng_snapshot_output *output);
/* Return maximum size of a snapshot. */
-uint64_t lttng_snapshot_output_get_maxsize(struct lttng_snapshot_output *output);
+uint64_t lttng_snapshot_output_get_maxsize(const struct lttng_snapshot_output *output);
/* Return snapshot name. */
-const char *lttng_snapshot_output_get_name(struct lttng_snapshot_output *output);
+const char *lttng_snapshot_output_get_name(const struct lttng_snapshot_output *output);
/* Return snapshot control URL in a text format. */
-const char *lttng_snapshot_output_get_ctrl_url(struct lttng_snapshot_output *output);
+const char *lttng_snapshot_output_get_ctrl_url(const struct lttng_snapshot_output *output);
/* Return snapshot data URL in a text format. */
-const char *lttng_snapshot_output_get_data_url(struct lttng_snapshot_output *output);
+const char *lttng_snapshot_output_get_data_url(const struct lttng_snapshot_output *output);
/*
* Snapshot output setter family functions.
/* Set the snapshot name. */
int lttng_snapshot_output_set_name(const char *name,
struct lttng_snapshot_output *output);
+
+/*
+ * Set the output destination to be a path on the local filesystem.
+ *
+ * The path must be absolute. It can optionally begin with `file://`.
+ */
+int lttng_snapshot_output_set_local_path(const char *path,
+ struct lttng_snapshot_output *output);
+
+/*
+ * Set the output destination to be the network from a combined control/data
+ * URL.
+ *
+ * `url` must start with `net://` or `net6://`.
+ */
+int lttng_snapshot_output_set_network_url(const char *url,
+ struct lttng_snapshot_output *output);
+
+/*
+ * Set the output destination to be the network using separate URLs for control
+ * and data.
+ *
+ * `ctrl_url` and `data_url` must start with `tcp://` or `tcp6://`.
+ */
+int lttng_snapshot_output_set_network_urls(
+ const char *ctrl_url, const char *data_url,
+ struct lttng_snapshot_output *output);
+
+// Deprecated?
+
/* Set the control URL. Local and remote URL are supported. */
int lttng_snapshot_output_set_ctrl_url(const char *url,
struct lttng_snapshot_output *output);
#include <common/macros.h>
#include <common/buffer-view.h>
#include <common/dynamic-buffer.h>
+#include <common/dynamic-array.h>
+#include <common/credentials.h>
#include <stdint.h>
#include <stdbool.h>
#include <sys/types.h>
+#include <urcu/ref.h>
struct lttng_trigger {
+ struct urcu_ref ref; /* internal use only */
+ bool owns_internal_objects; /* internal use only */
+
struct lttng_condition *condition;
struct lttng_action *action;
+ char *name;
+ struct { /* Internal use only */
+ bool set;
+ uint64_t value;
+ } key;
+ struct { /* internal use only */
+ struct lttng_credentials credentials;
+ bool set;
+ } creds;
+ struct {
+ enum lttng_trigger_firing_policy_type type;
+ uint64_t threshold;
+ uint64_t current_count;
+ } firing_policy;
+};
+
+struct lttng_triggers {
+ struct lttng_dynamic_pointer_array array;
};
struct lttng_trigger_comm {
/* length excludes its own length. */
+ uint32_t name_length /* Includes '\0' */;
uint32_t length;
- /* A condition and action object follow. */
+ uint8_t policy_type;
+ uint64_t policy_threshold;
+ /* A name, condition and action object follow. */
char payload[];
} LTTNG_PACKED;
+struct lttng_triggers_comm {
+ uint32_t count;
+ uint32_t length;
+ /* Count * lttng_trigger_comm structure */
+ char payload[];
+};
+
LTTNG_HIDDEN
ssize_t lttng_trigger_create_from_buffer(const struct lttng_buffer_view *view,
struct lttng_trigger **trigger);
LTTNG_HIDDEN
-int lttng_trigger_serialize(struct lttng_trigger *trigger,
- struct lttng_dynamic_buffer *buf);
+int lttng_trigger_serialize(const struct lttng_trigger *trigger,
+ struct lttng_dynamic_buffer *buf,
+ int *fd_to_send);
LTTNG_HIDDEN
-const struct lttng_condition *lttng_trigger_get_const_condition(
- const struct lttng_trigger *trigger);
+bool lttng_trigger_validate(const struct lttng_trigger *trigger);
+
+LTTNG_HIDDEN
+int lttng_trigger_assign(struct lttng_trigger *dst,
+ const struct lttng_trigger *src);
+
+LTTNG_HIDDEN
+bool lttng_trigger_is_equal(const struct lttng_trigger *a,
+ const struct lttng_trigger *b);
+
+LTTNG_HIDDEN
+void lttng_trigger_set_key(struct lttng_trigger *trigger, uint64_t key);
+
+LTTNG_HIDDEN
+uint64_t lttng_trigger_get_key(const struct lttng_trigger *trigger);
+
+LTTNG_HIDDEN
+int lttng_trigger_generate_name(struct lttng_trigger *trigger, uint64_t offset);
+
+/*
+ * Allocate a new list of lttng_trigger.
+ * The returned object must be freed via lttng_triggers_destroy.
+ */
+LTTNG_HIDDEN
+struct lttng_triggers *lttng_triggers_create(void);
+
+/*
+ * Return the non-const pointer of an element at index "index" of a
+ * lttng_triggers.
+ *
+ * The ownership of the lttng_triggers element is NOT transfered.
+ * The returned object can NOT be freed via lttng_trigger_destroy.
+ */
+LTTNG_HIDDEN
+struct lttng_trigger *lttng_triggers_get_pointer_of_index(
+ const struct lttng_triggers *triggers, unsigned int index);
+
+/*
+ * TODO:
+ */
+LTTNG_HIDDEN
+int lttng_triggers_add(
+ struct lttng_triggers *triggers, struct lttng_trigger *trigger);
+
+/*
+ * Serialize a trigger collection to a lttng_dynamic_buffer.
+ * Return LTTNG_OK on success, negative lttng error code on error.
+ */
+LTTNG_HIDDEN
+int lttng_triggers_serialize(const struct lttng_triggers *triggers,
+ struct lttng_dynamic_buffer *buffer);
+
+LTTNG_HIDDEN
+ssize_t lttng_triggers_create_from_buffer(const struct lttng_buffer_view *view,
+ struct lttng_triggers **triggers);
LTTNG_HIDDEN
-const struct lttng_action *lttng_trigger_get_const_action(
+const struct lttng_credentials *lttng_trigger_get_credentials(
const struct lttng_trigger *trigger);
LTTNG_HIDDEN
-bool lttng_trigger_validate(struct lttng_trigger *trigger);
+void lttng_trigger_set_credentials(
+ struct lttng_trigger *trigger, uid_t uid, gid_t git);
+
+LTTNG_HIDDEN
+void lttng_trigger_get(struct lttng_trigger *trigger);
+
+LTTNG_HIDDEN
+void lttng_trigger_put(struct lttng_trigger *trigger);
+
+LTTNG_HIDDEN
+bool lttng_trigger_is_ready_to_fire(
+ struct lttng_trigger *trigger);
+
+/*
+ * Return the type of any uderlying domain requirement. If no particular
+ * requirement is needed return LTTNG_DOMAIN_NONE.
+ */
+LTTNG_HIDDEN
+enum lttng_domain_type lttng_trigger_get_underlying_domain_type_restriction(
+ const struct lttng_trigger *trigger);
#endif /* LTTNG_TRIGGER_INTERNAL_H */
struct lttng_action;
struct lttng_condition;
struct lttng_trigger;
+/* A collection of trigger */
+struct lttng_triggers;
#ifdef __cplusplus
extern "C" {
LTTNG_REGISTER_TRIGGER_STATUS_INVALID = -1,
};
+enum lttng_trigger_status {
+ LTTNG_TRIGGER_STATUS_OK = 0,
+ LTTNG_TRIGGER_STATUS_ERROR = -1,
+ LTTNG_TRIGGER_STATUS_UNKNOWN = -2,
+ LTTNG_TRIGGER_STATUS_INVALID = -3,
+ LTTNG_TRIGGER_STATUS_UNSET = -4,
+ LTTNG_TRIGGER_STATUS_UNSUPPORTED = -5,
+};
+
+enum lttng_trigger_firing_policy_type {
+ LTTNG_TRIGGER_FIRE_EVERY_N = 0,
+ LTTNG_TRIGGER_FIRE_ONCE_AFTER_N = 1,
+};
+
/*
* Create a trigger object associating a condition and an action.
*
extern struct lttng_condition *lttng_trigger_get_condition(
struct lttng_trigger *trigger);
+const struct lttng_condition *lttng_trigger_get_const_condition(
+ const struct lttng_trigger *trigger);
+
/*
* Get the action of a trigger.
*
extern struct lttng_action *lttng_trigger_get_action(
struct lttng_trigger *trigger);
+const struct lttng_action *lttng_trigger_get_const_action(
+ const struct lttng_trigger *trigger);
+
+/*
+ * Get the name of a trigger.
+ *
+ * The caller does not assume the ownership of the returned name.
+ * The name shall only only be used for the duration of the trigger's
+ * lifetime, or before a different name is set.
+ *
+ * Returns LTTNG_TRIGGER_STATUS_OK and a pointer to the trigger's name on
+ * success, LTTNG_TRIGGER_STATUS_INVALID if an invalid parameter is passed,
+ * or LTTNG_TRIGGER_STATUS_UNSET if a name was not set prior to this call.
+ */
+extern enum lttng_trigger_status lttng_trigger_get_name(
+ const struct lttng_trigger *trigger, const char **name);
+
+/*
+ * Set the trigger name.
+ *
+ * A name is optional.
+ * A name will be assigned on trigger registration if no name is set.
+ *
+ * The name is copied.
+ *
+ * Return LTTNG_TRIGGER_STATUS_OK on success, LTTNG_TRIGGER_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+extern enum lttng_trigger_status lttng_trigger_set_name(
+ struct lttng_trigger *trigger, const char *name);
+
+/*
+ * Set the trigger firing policy.
+ *
+ * This is optional. By default a trigger is set to fire each time the
+ * associated condition occurs.
+ *
+ * Threshold is the number of time the condition must be hit before the policy is
+ * enacted.
+ *
+ * Return LTTNG_TRIGGER_STATUS_OK on success, LTTNG_TRIGGER_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+extern enum lttng_trigger_status lttng_trigger_set_firing_policy(
+ struct lttng_trigger *trigger,
+ enum lttng_trigger_firing_policy_type policy_type,
+ unsigned long long threshold);
+extern enum lttng_trigger_status lttng_trigger_get_firing_policy(
+ const struct lttng_trigger *trigger,
+ enum lttng_trigger_firing_policy_type *policy_type,
+ unsigned long long *threshold);
+
/*
* Destroy (frees) a trigger object.
*/
*
* Return 0 on success, a negative LTTng error code on error.
*/
-extern int lttng_unregister_trigger(struct lttng_trigger *trigger);
+extern int lttng_unregister_trigger(const struct lttng_trigger *trigger);
+
+/*
+ * List current triggers.
+ *
+ * On success, triggers is allocated.
+ * The trigger collection must be free by the caller with lttng_destroy_triggers
+ *
+ * Returns 0 on success, else a negative LTTng error code.
+ */
+extern int lttng_list_triggers(struct lttng_triggers **triggers);
+
+/*
+ * Get a trigger from the collection at a given index.
+ *
+ * Note that the collection maintains the ownership of the returned trigger.
+ * It must not be destroyed by the user, nor should it be held beyond the
+ * lifetime of the trigger collection.
+ *
+ * Returns a trigger, or NULL on error.
+ */
+extern const struct lttng_trigger *lttng_triggers_get_at_index(
+ const struct lttng_triggers *triggers, unsigned int index);
+
+/*
+ * Get the number of trigger in a tracker id list.
+ *
+ * Return LTTNG_TRIGGER_STATUS_OK on success,
+ * LTTNG_TRIGGER_STATUS_INVALID when passed invalid parameters.
+ */
+extern enum lttng_trigger_status lttng_triggers_get_count(
+ const struct lttng_triggers *triggers, unsigned int *count);
+
+/*
+ * Destroy a trigger collection.
+ */
+extern void lttng_triggers_destroy(struct lttng_triggers *ids);
+
#ifdef __cplusplus
}
#include <common/dynamic-buffer.h>
#include <common/buffer-view.h>
+typedef bool (*userspace_probe_location_equal_cb)(
+ const struct lttng_userspace_probe_location *a,
+ const struct lttng_userspace_probe_location *b);
+
/*
* No elf-specific comm structure is defined since no elf-specific payload is
* currently needed.
struct lttng_userspace_probe_location {
enum lttng_userspace_probe_location_type type;
struct lttng_userspace_probe_location_lookup_method *lookup_method;
+ userspace_probe_location_equal_cb equal;
};
struct lttng_userspace_probe_location_function {
struct lttng_userspace_probe_location *lttng_userspace_probe_location_copy(
const struct lttng_userspace_probe_location *location);
+LTTNG_HIDDEN
+bool lttng_userspace_probe_location_is_equal(
+ const struct lttng_userspace_probe_location *a,
+ const struct lttng_userspace_probe_location *b);
+
+LTTNG_HIDDEN
+int lttng_userspace_probe_location_set_binary_fd(
+ struct lttng_userspace_probe_location *location, int fd);
+
#endif /* LTTNG_USERSPACE_PROBE_INTERNAL_H */
--- /dev/null
+# ============================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_append_compile_flags.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+# AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+# For every FLAG1, FLAG2 it is checked whether the compiler works with the
+# flag. If it does, the flag is added FLAGS-VARIABLE
+#
+# If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
+# CFLAGS) is used. During the check the flag is always added to the
+# current language's flags.
+#
+# If EXTRA-FLAGS is defined, it is added to the current language's default
+# flags (e.g. CFLAGS) when the check is done. The check is thus made with
+# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
+# force the compiler to issue an error when a bad flag is given.
+#
+# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+# NOTE: This macro depends on the AX_APPEND_FLAG and
+# AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with
+# AX_APPEND_LINK_FLAGS.
+#
+# LICENSE
+#
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 7
+
+AC_DEFUN([AX_APPEND_COMPILE_FLAGS],
+[AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG])
+AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
+for flag in $1; do
+ AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3], [$4])
+done
+])dnl AX_APPEND_COMPILE_FLAGS
--- /dev/null
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_append_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE])
+#
+# DESCRIPTION
+#
+# FLAG is appended to the FLAGS-VARIABLE shell variable, with a space
+# added in between.
+#
+# If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
+# CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains
+# FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly
+# FLAG.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 8
+
+AC_DEFUN([AX_APPEND_FLAG],
+[dnl
+AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF
+AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])
+AS_VAR_SET_IF(FLAGS,[
+ AS_CASE([" AS_VAR_GET(FLAGS) "],
+ [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])],
+ [
+ AS_VAR_APPEND(FLAGS,[" $1"])
+ AC_RUN_LOG([: FLAGS="$FLAGS"])
+ ])
+ ],
+ [
+ AS_VAR_SET(FLAGS,[$1])
+ AC_RUN_LOG([: FLAGS="$FLAGS"])
+ ])
+AS_VAR_POPDEF([FLAGS])dnl
+])dnl AX_APPEND_FLAG
--- /dev/null
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+# Check whether the given FLAG works with the current language's compiler
+# or gives an error. (Warnings, however, are ignored)
+#
+# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+# success/failure.
+#
+# If EXTRA-FLAGS is defined, it is added to the current language's default
+# flags (e.g. CFLAGS) when the check is done. The check is thus made with
+# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
+# force the compiler to issue an error when a bad flag is given.
+#
+# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 6
+
+AC_DEFUN([AX_CHECK_COMPILE_FLAG],
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
+AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
+ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
+ _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
+ AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+ [AS_VAR_SET(CACHEVAR,[yes])],
+ [AS_VAR_SET(CACHEVAR,[no])])
+ _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
+AS_VAR_IF(CACHEVAR,yes,
+ [m4_default([$2], :)],
+ [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_COMPILE_FLAGS
--- /dev/null
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_require_defined.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_REQUIRE_DEFINED(MACRO)
+#
+# DESCRIPTION
+#
+# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have
+# been defined and thus are available for use. This avoids random issues
+# where a macro isn't expanded. Instead the configure script emits a
+# non-fatal:
+#
+# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found
+#
+# It's like AC_REQUIRE except it doesn't expand the required macro.
+#
+# Here's an example:
+#
+# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
+#
+# LICENSE
+#
+# Copyright (c) 2014 Mike Frysinger <vapier@gentoo.org>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 2
+
+AC_DEFUN([AX_REQUIRE_DEFINED], [dnl
+ m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])])
+])dnl AX_REQUIRE_DEFINED
--- /dev/null
+ag --ignore rename.sh -l "event-rule-uprobe-internal\.h" | xargs sed -i 's/event-rule-uprobe-internal\.h/uprobe-internal.h/g'
+ag --ignore rename.sh -l "event-rule-kprobe-internal\.h" | xargs sed -i 's/event-rule-kprobe-internal\.h/kprobe-internal.h/g'
+ag --ignore rename.sh -l "event-rule-kretprobe-internal\.h" | xargs sed -i 's/event-rule-kretprobe-internal\.h/kretprobe-internal.h/g'
+ag --ignore rename.sh -l "event-rule-syscall-internal\.h" | xargs sed -i 's/event-rule-syscall-internal\.h/syscall-internal.h/g'
+ag --ignore rename.sh -l "event-rule-tracepoint-internal\.h" | xargs sed -i 's/event-rule-tracepoint-internal\.h/tracepoint-internal.h/g'
+
+ag --ignore rename.sh -l "event-rule-uprobe\.h" | xargs sed -i 's/event-rule-uprobe\.h/uprobe.h/g'
+ag --ignore rename.sh -l "event-rule-kprobe\.h" | xargs sed -i 's/event-rule-kprobe\.h/kprobe.h/g'
+ag --ignore rename.sh -l "event-rule-kretprobe\.h" | xargs sed -i 's/event-rule-kretprobe\.h/kretprobe.h/g'
+ag --ignore rename.sh -l "event-rule-syscall\.h" | xargs sed -i 's/event-rule-syscall\.h/syscall.h/g'
+ag --ignore rename.sh -l "event-rule-tracepoint\.h" | xargs sed -i 's/event-rule-tracepoint\.h/tracepoint.h/g'
+git add .
+git commit --amend --no-edit
};
/* Variables */
-static char *progname,
- *opt_viewer_path = NULL,
- *opt_output_path = NULL;
+static const char *progname;
+static char *opt_viewer_path = NULL;
+static char *opt_output_path = NULL;
static char *input_path;
}
if (!opt_viewer_path) {
- opt_viewer_path = DEFAULT_VIEWER;
+ opt_viewer_path = (char *) DEFAULT_VIEWER;
}
/* No leftovers, or more than one input path, print usage and quit */
#define _LGPL_SOURCE
#include <assert.h>
+#include "cmd-2-2.h"
+
#include <common/common.h>
#include <common/sessiond-comm/relayd.h>
manage-kernel.c manage-kernel.h \
manage-consumer.c manage-consumer.h \
clear.c clear.h \
- tracker.c tracker.h
+ tracker.c tracker.h \
+ action-executor.c action-executor.h
if HAVE_LIBLTTNG_UST_CTL
lttng_sessiond_SOURCES += trace-ust.c ust-registry.c ust-app.c \
--- /dev/null
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include "action-executor.h"
+#include "cmd.h"
+#include "health-sessiond.h"
+#include "lttng-sessiond.h"
+#include "notification-thread-internal.h"
+#include "session.h"
+#include "thread.h"
+#include <common/macros.h>
+#include <lttng/action/group.h>
+#include <lttng/action/notify.h>
+#include <lttng/action/rotate-session.h>
+#include <lttng/action/snapshot-session.h>
+#include <lttng/action/start-session.h>
+#include <lttng/action/stop-session.h>
+#include <lttng/condition/evaluation.h>
+#include <lttng/condition/event-rule-internal.h>
+#include <lttng/lttng-error.h>
+#include <lttng/trigger/trigger-internal.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <urcu/list.h>
+
+#define THREAD_NAME "Action Executor"
+#define MAX_QUEUED_WORK_COUNT 8192
+
+struct action_work_item {
+ uint64_t id;
+ struct lttng_trigger *trigger;
+ struct notification_client_list *client_list;
+ struct cds_list_head list_node;
+};
+
+struct action_executor {
+ struct lttng_thread *thread;
+ struct notification_thread_handle *notification_thread_handle;
+ struct {
+ uint64_t pending_count;
+ struct cds_list_head list;
+ pthread_cond_t cond;
+ pthread_mutex_t lock;
+ } work;
+ bool should_quit;
+ uint64_t next_work_item_id;
+};
+
+typedef int (*action_executor_handler)(struct action_executor *executor,
+ const struct action_work_item *,
+ const struct lttng_action *action);
+
+static int action_executor_notify_handler(struct action_executor *executor,
+ const struct action_work_item *,
+ const struct lttng_action *);
+static int action_executor_start_session_handler(struct action_executor *executor,
+ const struct action_work_item *,
+ const struct lttng_action *);
+static int action_executor_stop_session_handler(struct action_executor *executor,
+ const struct action_work_item *,
+ const struct lttng_action *);
+static int action_executor_rotate_session_handler(struct action_executor *executor,
+ const struct action_work_item *,
+ const struct lttng_action *);
+static int action_executor_snapshot_session_handler(struct action_executor *executor,
+ const struct action_work_item *,
+ const struct lttng_action *);
+static int action_executor_group_handler(struct action_executor *executor,
+ const struct action_work_item *,
+ const struct lttng_action *);
+static int action_executor_generic_handler(struct action_executor *executor,
+ const struct action_work_item *,
+ const struct lttng_action *);
+
+static const action_executor_handler action_executors[] = {
+ [LTTNG_ACTION_TYPE_NOTIFY] = action_executor_notify_handler,
+ [LTTNG_ACTION_TYPE_START_SESSION] = action_executor_start_session_handler,
+ [LTTNG_ACTION_TYPE_STOP_SESSION] = action_executor_stop_session_handler,
+ [LTTNG_ACTION_TYPE_ROTATE_SESSION] = action_executor_rotate_session_handler,
+ [LTTNG_ACTION_TYPE_SNAPSHOT_SESSION] = action_executor_snapshot_session_handler,
+ [LTTNG_ACTION_TYPE_GROUP] = action_executor_group_handler,
+};
+
+static const char *get_action_name(const struct lttng_action *action)
+{
+ const char *action_type_names[] = {
+ [LTTNG_ACTION_TYPE_NOTIFY] = "Notify",
+ [LTTNG_ACTION_TYPE_START_SESSION] = "Start session",
+ [LTTNG_ACTION_TYPE_STOP_SESSION] = "Stop session",
+ [LTTNG_ACTION_TYPE_ROTATE_SESSION] = "Rotate session",
+ [LTTNG_ACTION_TYPE_SNAPSHOT_SESSION] = "Snapshot session",
+ [LTTNG_ACTION_TYPE_GROUP] = "Group",
+ };
+
+ return action_type_names[lttng_action_get_type(action)];
+}
+
+static const char *get_trigger_name(const struct lttng_trigger *trigger)
+{
+ const char *trigger_name;
+ enum lttng_trigger_status trigger_status;
+
+ trigger_status = lttng_trigger_get_name(trigger, &trigger_name);
+ assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
+
+ return trigger_name;
+}
+
+static int client_handle_transmission_status(
+ struct notification_client *client,
+ enum client_transmission_status status,
+ void *user_data)
+{
+ struct action_executor *executor = user_data;
+
+ switch (status) {
+ case CLIENT_TRANSMISSION_STATUS_COMPLETE:
+ DBG("Sent notification to client");
+ break;
+ default:
+ ERR("Could not send notification to client");
+ }
+
+ return 0;
+}
+
+static int action_executor_notify_handler(struct action_executor *executor,
+ const struct action_work_item *work_item,
+ const struct lttng_action *action)
+{
+ int ret = 0;
+ struct lttng_evaluation *evaluation = NULL;
+
+ assert(work_item->client_list);
+
+ evaluation = lttng_evaluation_event_rule_create(
+ get_trigger_name(work_item->trigger));
+ if (!evaluation) {
+ ERR("Failed to create event rule hit evaluation");
+ ret = -1;
+ goto end;
+ }
+
+ ret = notification_client_list_send_evaluation(work_item->client_list,
+ lttng_trigger_get_const_condition(work_item->trigger),
+ evaluation,
+ lttng_trigger_get_credentials(work_item->trigger), NULL,
+ client_handle_transmission_status, executor);
+end:
+ lttng_evaluation_destroy(evaluation);
+ return ret;
+}
+
+static int action_executor_start_session_handler(struct action_executor *executor,
+ const struct action_work_item *work_item,
+ const struct lttng_action *action)
+{
+ int ret = 0;
+ const char *session_name;
+ enum lttng_action_status action_status;
+ struct ltt_session *session;
+
+ action_status = lttng_action_start_session_get_session_name(
+ action, &session_name);
+ if (action_status != LTTNG_ACTION_STATUS_OK) {
+ ERR("Failed to get session name from \"%s\" action",
+ get_action_name(action));
+ ret = -1;
+ goto end;
+ }
+
+ session_lock_list();
+ session = session_find_by_name(session_name);
+ if (session) {
+ enum lttng_error_code cmd_ret;
+
+ session_lock(session);
+ cmd_ret = cmd_start_trace(session);
+ session_unlock(session);
+
+ switch (cmd_ret) {
+ case LTTNG_OK:
+ DBG("Successfully started session \"%s\" on behalf of trigger \"%s\"",
+ session_name,
+ get_trigger_name(work_item->trigger));
+ break;
+ case LTTNG_ERR_TRACE_ALREADY_STARTED:
+ DBG("Attempted to start session \"%s\" on behalf of trigger \"%s\" but it was already started",
+ session_name,
+ get_trigger_name(work_item->trigger));
+ break;
+ default:
+ WARN("Failed to start session \"%s\" on behalf of trigger \"%s\": %s",
+ session_name,
+ get_trigger_name(work_item->trigger),
+ lttng_strerror(-cmd_ret));
+ break;
+ }
+ session_put(session);
+ } else {
+ DBG("Failed to find session \"%s\" by name while executing \"%s\" action of trigger \"%s\"",
+ session_name, get_action_name(action),
+ get_trigger_name(work_item->trigger));
+ }
+ session_unlock_list();
+end:
+ return ret;
+}
+
+static int action_executor_stop_session_handler(struct action_executor *executor,
+ const struct action_work_item *work_item,
+ const struct lttng_action *action)
+{
+ int ret = 0;
+ const char *session_name;
+ enum lttng_action_status action_status;
+ struct ltt_session *session;
+
+ action_status = lttng_action_stop_session_get_session_name(
+ action, &session_name);
+ if (action_status != LTTNG_ACTION_STATUS_OK) {
+ ERR("Failed to get session name from \"%s\" action",
+ get_action_name(action));
+ ret = -1;
+ goto end;
+ }
+
+ session_lock_list();
+ session = session_find_by_name(session_name);
+ if (session) {
+ enum lttng_error_code cmd_ret;
+
+ session_lock(session);
+ cmd_ret = cmd_stop_trace(session);
+ session_unlock(session);
+
+ switch (cmd_ret) {
+ case LTTNG_OK:
+ DBG("Successfully stopped session \"%s\" on behalf of trigger \"%s\"",
+ session_name,
+ get_trigger_name(work_item->trigger));
+ break;
+ case LTTNG_ERR_TRACE_ALREADY_STOPPED:
+ DBG("Attempted to stop session \"%s\" on behalf of trigger \"%s\" but it was already stopped",
+ session_name,
+ get_trigger_name(work_item->trigger));
+ break;
+ default:
+ WARN("Failed to stop session \"%s\" on behalf of trigger \"%s\": %s",
+ session_name,
+ get_trigger_name(work_item->trigger),
+ lttng_strerror(-cmd_ret));
+ break;
+ }
+ session_put(session);
+ } else {
+ DBG("Failed to find session \"%s\" by name while executing \"%s\" action of trigger \"%s\"",
+ session_name, get_action_name(action),
+ get_trigger_name(work_item->trigger));
+ }
+ session_unlock_list();
+end:
+ return ret;
+}
+
+static int action_executor_rotate_session_handler(struct action_executor *executor,
+ const struct action_work_item *work_item,
+ const struct lttng_action *action)
+{
+ int ret = 0;
+ const char *session_name;
+ enum lttng_action_status action_status;
+ struct ltt_session *session;
+
+ action_status = lttng_action_rotate_session_get_session_name(
+ action, &session_name);
+ if (action_status != LTTNG_ACTION_STATUS_OK) {
+ ERR("Failed to get session name from \"%s\" action",
+ get_action_name(action));
+ ret = -1;
+ goto end;
+ }
+
+ session_lock_list();
+ session = session_find_by_name(session_name);
+ if (session) {
+ enum lttng_error_code cmd_ret;
+
+ session_lock(session);
+ cmd_ret = cmd_rotate_session(session, NULL, false,
+ LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED);
+ session_unlock(session);
+
+ switch (cmd_ret) {
+ case LTTNG_OK:
+ DBG("Successfully started rotation of session \"%s\" on behalf of trigger \"%s\"",
+ session_name,
+ get_trigger_name(work_item->trigger));
+ break;
+ case LTTNG_ERR_ROTATION_PENDING:
+ DBG("Attempted to start a rotation of session \"%s\" on behalf of trigger \"%s\" but a rotation is already ongoing",
+ session_name,
+ get_trigger_name(work_item->trigger));
+ break;
+ case LTTNG_ERR_ROTATION_MULTIPLE_AFTER_STOP:
+ case LTTNG_ERR_ROTATION_AFTER_STOP_CLEAR:
+ DBG("Attempted to start a rotation of session \"%s\" on behalf of trigger \"%s\" but a rotation has already been completed since the last stop or clear",
+ session_name,
+ get_trigger_name(work_item->trigger));
+ break;
+ default:
+ WARN("Failed to start a rotation of session \"%s\" on behalf of trigger \"%s\": %s",
+ session_name,
+ get_trigger_name(work_item->trigger),
+ lttng_strerror(-cmd_ret));
+ break;
+ }
+ session_put(session);
+ } else {
+ DBG("Failed to find session \"%s\" by name while executing \"%s\" action of trigger \"%s\"",
+ session_name, get_action_name(action),
+ get_trigger_name(work_item->trigger));
+ }
+ session_unlock_list();
+end:
+ return ret;
+}
+
+static int action_executor_snapshot_session_handler(struct action_executor *executor,
+ const struct action_work_item *work_item,
+ const struct lttng_action *action)
+{
+ int ret = 0;
+ const char *session_name;
+ enum lttng_action_status action_status;
+ struct ltt_session *session;
+ const struct lttng_snapshot_output default_snapshot_output = {
+ .max_size = UINT64_MAX,
+ };
+ const struct lttng_snapshot_output *snapshot_output =
+ &default_snapshot_output;
+
+ action_status = lttng_action_snapshot_session_get_session_name(
+ action, &session_name);
+ if (action_status != LTTNG_ACTION_STATUS_OK) {
+ ERR("Failed to get session name from \"%s\" action",
+ get_action_name(action));
+ ret = -1;
+ goto end;
+ }
+
+ action_status = lttng_action_snapshot_session_get_output_const(
+ action, &snapshot_output);
+ if (action_status != LTTNG_ACTION_STATUS_OK &&
+ action_status != LTTNG_ACTION_STATUS_UNSET) {
+ ERR("Failed to get output from \"%s\" action",
+ get_action_name(action));
+ ret = -1;
+ goto end;
+ }
+
+ session_lock_list();
+ session = session_find_by_name(session_name);
+ if (session) {
+ enum lttng_error_code cmd_ret;
+
+ session_lock(session);
+ cmd_ret = cmd_snapshot_record(session, snapshot_output, 0);
+ session_unlock(session);
+
+ switch (cmd_ret) {
+ case LTTNG_OK:
+ DBG("Successfully recorded snapshot of session \"%s\" on behalf of trigger \"%s\"",
+ session_name,
+ get_trigger_name(work_item->trigger));
+ break;
+ default:
+ WARN("Failed to record snapshot of session \"%s\" on behalf of trigger \"%s\": %s",
+ session_name,
+ get_trigger_name(work_item->trigger),
+ lttng_strerror(-cmd_ret));
+ break;
+ }
+ session_put(session);
+ } else {
+ DBG("Failed to find session \"%s\" by name while executing \"%s\" action of trigger \"%s\"",
+ session_name, get_action_name(action),
+ get_trigger_name(work_item->trigger));
+ }
+ session_unlock_list();
+end:
+ return ret;
+}
+
+static int action_executor_group_handler(struct action_executor *executor,
+ const struct action_work_item *work_item,
+ const struct lttng_action *action_group)
+{
+ int ret = 0;
+ unsigned int i, count;
+ enum lttng_action_status action_status;
+
+ action_status = lttng_action_group_get_count(action_group, &count);
+ if (action_status != LTTNG_ACTION_STATUS_OK) {
+ /* Fatal error. */
+ ERR("Failed to get count of action in action group");
+ ret = -1;
+ goto end;
+ }
+
+ DBG("Action group has %u action%s", count, count != 1 ? "s" : "");
+ for (i = 0; i < count; i++) {
+ const struct lttng_action *action =
+ lttng_action_group_get_at_index_const(
+ action_group, i);
+
+ ret = action_executor_generic_handler(
+ executor, work_item, action);
+ if (ret) {
+ ERR("Stopping the execution of the action group of trigger \"%s\" following a fatal error",
+ get_trigger_name(work_item->trigger));
+ goto end;
+ }
+ }
+end:
+ return ret;
+}
+
+static int action_executor_generic_handler(struct action_executor *executor,
+ const struct action_work_item *work_item,
+ const struct lttng_action *action)
+{
+ DBG("Executing action \"%s\" of trigger \"%s\" action work item %" PRIu64,
+ get_action_name(action),
+ get_trigger_name(work_item->trigger),
+ work_item->id);
+
+ return action_executors[lttng_action_get_type(action)](
+ executor, work_item, action);
+}
+
+static int action_work_item_execute(struct action_executor *executor,
+ struct action_work_item *work_item)
+{
+ int ret;
+ const struct lttng_action *action =
+ lttng_trigger_get_const_action(work_item->trigger);
+
+ DBG("Starting execution of action work item %" PRIu64 " of trigger \"%s\"",
+ work_item->id, get_trigger_name(work_item->trigger));
+ ret = action_executor_generic_handler(executor, work_item, action);
+ DBG("Completed execution of action work item %" PRIu64 " of trigger \"%s\"",
+ work_item->id, get_trigger_name(work_item->trigger));
+ return ret;
+}
+
+static void action_work_item_destroy(struct action_work_item *work_item)
+{
+ lttng_trigger_put(work_item->trigger);
+ notification_client_list_put(work_item->client_list);
+ free(work_item);
+}
+
+static void *action_executor_thread(void *_data)
+{
+ struct action_executor *executor = _data;
+
+ assert(executor);
+
+ health_register(health_sessiond, HEALTH_SESSIOND_TYPE_ACTION_EXECUTOR);
+
+ rcu_register_thread();
+ rcu_thread_online();
+
+ DBG("Entering work execution loop");
+ pthread_mutex_lock(&executor->work.lock);
+ while (!executor->should_quit) {
+ int ret;
+ struct action_work_item *work_item;
+
+ health_code_update();
+ if (executor->work.pending_count == 0) {
+ health_poll_entry();
+ DBG("No work items enqueued, entering wait");
+ pthread_cond_wait(&executor->work.cond,
+ &executor->work.lock);
+ DBG("Woke-up from wait");
+ health_poll_exit();
+ continue;
+ }
+
+ /* Pop item from front of the listwith work lock held. */
+ work_item = cds_list_first_entry(&executor->work.list,
+ struct action_work_item, list_node);
+ cds_list_del(&work_item->list_node);
+ executor->work.pending_count--;
+
+ /*
+ * Work can be performed without holding the work lock,
+ * allowing new items to be queued.
+ */
+ pthread_mutex_unlock(&executor->work.lock);
+ ret = action_work_item_execute(executor, work_item);
+ action_work_item_destroy(work_item);
+ if (ret) {
+ /* Fatal error. */
+ break;
+ }
+ health_code_update();
+ pthread_mutex_lock(&executor->work.lock);
+ }
+ pthread_mutex_unlock(&executor->work.lock);
+ DBG("Left work execution loop");
+
+ health_code_update();
+
+ rcu_thread_offline();
+ rcu_unregister_thread();
+ health_unregister(health_sessiond);
+
+ return NULL;
+}
+
+static bool shutdown_action_executor_thread(void *_data)
+{
+ struct action_executor *executor = _data;
+
+ /* TODO. */
+ executor->should_quit = true;
+ pthread_cond_signal(&executor->work.cond);
+ return true;
+}
+
+static void clean_up_action_executor_thread(void *_data)
+{
+ struct action_executor *executor = _data;
+
+ assert(cds_list_empty(&executor->work.list));
+
+ pthread_mutex_destroy(&executor->work.lock);
+ pthread_cond_destroy(&executor->work.cond);
+ free(executor);
+}
+
+struct action_executor *action_executor_create(
+ struct notification_thread_handle *handle)
+{
+ struct action_executor *executor = zmalloc(sizeof(*executor));
+
+ if (!executor) {
+ goto end;
+ }
+
+ CDS_INIT_LIST_HEAD(&executor->work.list);
+ pthread_cond_init(&executor->work.cond, NULL);
+ pthread_mutex_init(&executor->work.lock, NULL);
+ executor->notification_thread_handle = handle;
+
+ executor->thread = lttng_thread_create(THREAD_NAME,
+ action_executor_thread, shutdown_action_executor_thread,
+ clean_up_action_executor_thread, executor);
+end:
+ return executor;
+}
+
+void action_executor_destroy(struct action_executor *executor)
+{
+ struct action_work_item *work_item, *tmp;
+
+ /* TODO Wait for work list to drain? */
+ lttng_thread_shutdown(executor->thread);
+ pthread_mutex_lock(&executor->work.lock);
+ if (executor->work.pending_count != 0) {
+ WARN("%" PRIu64
+ " trigger action%s still queued for execution and will be discarded",
+ executor->work.pending_count,
+ executor->work.pending_count == 1 ? " is" :
+ "s are");
+ }
+
+ cds_list_for_each_entry_safe (
+ work_item, tmp, &executor->work.list, list_node) {
+ WARN("Discarding action work item %" PRIu64
+ " associated to trigger \"%s\"",
+ work_item->id, get_trigger_name(work_item->trigger));
+ cds_list_del(&work_item->list_node);
+ action_work_item_destroy(work_item);
+ }
+ pthread_mutex_unlock(&executor->work.lock);
+ lttng_thread_put(executor->thread);
+}
+
+/* RCU read-lock must be held by the caller. */
+enum action_executor_status action_executor_enqueue(
+ struct action_executor *executor,
+ struct lttng_trigger *trigger,
+ struct notification_client_list *client_list)
+{
+ enum action_executor_status executor_status = ACTION_EXECUTOR_STATUS_OK;
+ const uint64_t work_item_id = executor->next_work_item_id++;
+ struct action_work_item *work_item;
+ bool signal = false;
+
+ pthread_mutex_lock(&executor->work.lock);
+ /* Check for queue overflow. */
+ if (executor->work.pending_count >= MAX_QUEUED_WORK_COUNT) {
+ /* Most likely spammy, remove if it is the case. */
+ DBG("Refusing to enqueue action for trigger \"%s\" as work item %" PRIu64
+ " (overflow)",
+ get_trigger_name(trigger), work_item_id);
+ executor_status = ACTION_EXECUTOR_STATUS_OVERFLOW;
+ goto error_unlock;
+ }
+
+ work_item = zmalloc(sizeof(*work_item));
+ if (!work_item) {
+ PERROR("Failed to allocate action executor work item on behalf of trigger \"%s\"",
+ get_trigger_name(trigger));
+ executor_status = ACTION_EXECUTOR_STATUS_ERROR;
+ goto error_unlock;
+ }
+
+ lttng_trigger_get(trigger);
+ if (client_list) {
+ const bool reference_acquired =
+ notification_client_list_get(client_list);
+
+ assert(reference_acquired);
+ }
+
+ *work_item = (typeof(*work_item)){
+ .id = work_item_id,
+ .trigger = trigger,
+ .client_list = client_list,
+ .list_node = CDS_LIST_HEAD_INIT(work_item->list_node),
+ };
+ cds_list_add_tail(&work_item->list_node, &executor->work.list);
+ executor->work.pending_count++;
+ DBG("Enqueued action for trigger \"%s\" as work item %" PRIu64,
+ get_trigger_name(trigger), work_item_id);
+ signal = true;
+
+error_unlock:
+ pthread_mutex_unlock(&executor->work.lock);
+ if (signal) {
+ pthread_cond_signal(&executor->work.cond);
+ }
+ return executor_status;
+}
--- /dev/null
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef ACTION_EXECUTOR_H
+#define ACTION_EXECUTOR_H
+
+struct action_executor;
+struct notification_thread_handle;
+struct lttng_trigger;
+struct notification_client_list;
+
+enum action_executor_status {
+ ACTION_EXECUTOR_STATUS_OK,
+ ACTION_EXECUTOR_STATUS_OVERFLOW,
+ ACTION_EXECUTOR_STATUS_ERROR,
+ ACTION_EXECUTOR_STATUS_INVALID,
+};
+
+struct action_executor *action_executor_create(
+ struct notification_thread_handle *handle);
+
+void action_executor_destroy(struct action_executor *executor);
+
+enum action_executor_status action_executor_enqueue(
+ struct action_executor *executor,
+ struct lttng_trigger *trigger,
+ struct notification_client_list *list);
+
+#endif /* ACTION_EXECUTOR_H */
{
struct ltt_session *session, *stmp;
struct ltt_session_list *list;
+ struct agent *trigger_agent;
+ struct lttng_ht_iter iter;
list = session_get_list();
assert(list);
session_put(session);
}
session_unlock_list();
+
+ /* Do we need more locking here? maybe against trigger add? */
+ rcu_read_lock();
+ cds_lfht_for_each_entry (trigger_agents_ht_by_domain->ht, &iter.iter,
+ trigger_agent, node.node) {
+ agent_update(trigger_agent, app->sock->fd);
+ }
+ rcu_read_unlock();
}
/*
#include <urcu/uatomic.h>
#include <urcu/rculist.h>
+#include <lttng/event-rule/event-rule.h>
+#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/event-rule/tracepoint.h>
+#include <lttng/condition/condition.h>
+#include <lttng/condition/event-rule.h>
+
#include <common/common.h>
#include <common/sessiond-comm/agent.h>
}
/*
- * Match function for the events hash table lookup by name and loglevel.
+ * Match function for the events hash table lookup by name, loglevel and
+ * filter_expression.
*/
static int ht_match_event(struct cds_lfht_node *node,
const void *_key)
}
event->enabled = 1;
+ event->user_refcount++;
ret = LTTNG_OK;
error:
goto end;
}
+ if (event->user_refcount - 1 != 0) {
+ /*
+ * Disable the agent event only when all users (trigger etc.)
+ * have disabled it.
+ */
+
+ event->user_refcount--;
+ ret = LTTNG_OK;
+ goto end;
+ }
+
rcu_read_lock();
cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, app,
}
}
+ event->user_refcount = 0;
event->enabled = 0;
error:
ht_match_event_by_name, &key, &iter->iter);
}
+/*
+ * Find the agent event matching the trigger.
+ *
+ * RCU read side lock MUST be acquired. It must be kept for as long as
+ * the returned agent_event is used.
+ *
+ * Return object if found else NULL.
+ */
+struct agent_event *agent_find_event_by_trigger(
+ const struct lttng_trigger *trigger, struct agent *agt)
+{
+ enum lttng_condition_status c_status;
+ enum lttng_event_rule_status er_status;
+ enum lttng_domain_type d_type;
+ const struct lttng_condition *condition;
+ const struct lttng_event_rule *rule;
+ const char *name;
+ const char *filter_expression;
+ /* TODO validate if this is the unset value or no */
+ int loglevel_value = 0;
+ enum lttng_loglevel_type loglevel_type;
+
+ assert(agt);
+ assert(agt->events);
+
+ condition = lttng_trigger_get_const_condition(trigger);
+
+ assert(lttng_condition_get_type(condition) ==
+ LTTNG_CONDITION_TYPE_EVENT_RULE_HIT);
+
+ c_status = lttng_condition_event_rule_get_rule(condition, &rule);
+ assert(c_status == LTTNG_CONDITION_STATUS_OK);
+
+ assert(lttng_event_rule_get_type(rule) ==
+ LTTNG_EVENT_RULE_TYPE_TRACEPOINT);
+
+ d_type = lttng_event_rule_get_domain_type(rule);
+ assert(d_type == LTTNG_DOMAIN_JUL || d_type == LTTNG_DOMAIN_LOG4J ||
+ d_type == LTTNG_DOMAIN_PYTHON);
+
+ /* Get the name (aka pattern) */
+ er_status = lttng_event_rule_tracepoint_get_pattern(rule, &name);
+ assert(er_status == LTTNG_EVENT_RULE_STATUS_OK);
+
+ /* Get the internal filter_expression */
+ filter_expression = lttng_event_rule_get_filter(rule);
+
+ er_status = lttng_event_rule_tracepoint_get_loglevel_type(
+ rule, &loglevel_type);
+ assert(er_status == LTTNG_EVENT_RULE_STATUS_OK);
+ if (loglevel_type != LTTNG_EVENT_LOGLEVEL_ALL) {
+ er_status = lttng_event_rule_tracepoint_get_loglevel(
+ rule, &loglevel_value);
+ assert(er_status == LTTNG_EVENT_RULE_STATUS_OK);
+ }
+
+ return agent_find_event(name, loglevel_type, loglevel_value,
+ filter_expression, agt);
+}
+
/*
* Get the next agent event duplicate by name. This should be called
* after a call to agent_find_events_by_name() to iterate on events.
* Return object if found else NULL.
*/
struct agent_event *agent_find_event(const char *name,
- enum lttng_loglevel_type loglevel_type, int loglevel_value,
- char *filter_expression, struct agent *agt)
+ enum lttng_loglevel_type loglevel_type,
+ int loglevel_value,
+ const char *filter_expression,
+ struct agent *agt)
{
struct lttng_ht_node_str *node;
struct lttng_ht_iter iter;
return ret;
}
+/*
+ * Allocate agent_apps_ht_by_sock.
+ */
+int trigger_agent_ht_alloc(void)
+{
+ int ret = 0;
+
+ trigger_agents_ht_by_domain = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
+ if (!trigger_agents_ht_by_domain) {
+ ret = -1;
+ }
+
+ return ret;
+}
+
/*
* Destroy a agent application by socket.
*/
lttng_ht_destroy(agent_apps_ht_by_sock);
}
+/*
+ * Clean-up the trigger agent hash table and destroy it.
+ */
+void trigger_agent_ht_clean(void)
+{
+ struct lttng_ht_node_u64 *node;
+ struct lttng_ht_iter iter;
+
+ if (!trigger_agents_ht_by_domain) {
+ return;
+ }
+ rcu_read_lock();
+ cds_lfht_for_each_entry (trigger_agents_ht_by_domain->ht, &iter.iter,
+ node, node) {
+ struct agent *agent;
+
+ (void) lttng_ht_del(trigger_agents_ht_by_domain, &iter);
+
+ agent = caa_container_of(node, struct agent, node);
+ agent_destroy(agent);
+ }
+ rcu_read_unlock();
+
+ lttng_ht_destroy(trigger_agents_ht_by_domain);
+}
+
/*
* Update a agent application (given socket) using the given agent.
*
rcu_read_unlock();
}
+
+struct agent *trigger_find_agent(enum lttng_domain_type domain_type)
+{
+ struct agent *agt = NULL;
+ struct lttng_ht_node_u64 *node;
+ struct lttng_ht_iter iter;
+ uint64_t key;
+
+ assert(trigger_agents_ht_by_domain);
+
+ DBG3("Trigger agent lookup for domain %d", domain_type);
+
+ key = domain_type;
+
+ lttng_ht_lookup(trigger_agents_ht_by_domain, &key, &iter);
+ node = lttng_ht_iter_get_node_u64(&iter);
+ if (!node) {
+ goto end;
+ }
+ agt = caa_container_of(node, struct agent, node);
+
+end:
+ return agt;
+}
*/
extern struct lttng_ht *agent_apps_ht_by_sock;
+/*
+ * Hash table that contains the trigger agents by domain */
+extern struct lttng_ht *trigger_agents_ht_by_domain;
+
struct agent_ht_key {
const char *name;
int loglevel_value;
enum lttng_loglevel_type loglevel_type;
- char *filter_expression;
+ const char *filter_expression;
};
/*
struct lttng_filter_bytecode *filter;
char *filter_expression;
struct lttng_event_exclusion *exclusion;
+
+ /*
+ * Multiple triggers and events can use this agent event.
+ * The event can only be disabled when the count is zero.
+ */
+ unsigned int user_refcount;
};
/*
void agent_add_event(struct agent_event *event, struct agent *agt);
struct agent_event *agent_find_event(const char *name,
- enum lttng_loglevel_type loglevel_type, int loglevel_value,
- char *filter_expression, struct agent *agt);
+ enum lttng_loglevel_type loglevel_type,
+ int loglevel_value,
+ const char *filter_expression,
+ struct agent *agt);
void agent_find_events_by_name(const char *name, struct agent *agt,
struct lttng_ht_iter* iter);
void agent_event_next_duplicate(const char *name,
int agent_list_events(struct lttng_event **events,
enum lttng_domain_type domain);
+struct agent_event *agent_find_event_by_trigger(
+ const struct lttng_trigger *trigger, struct agent *agt);
+
+/* todo: find a better place for this */
+struct agent *trigger_find_agent(enum lttng_domain_type domain_type);
+void trigger_agent_ht_clean(void);
+int trigger_agent_ht_alloc(void);
+
#endif /* LTTNG_SESSIOND_AGENT_H */
#include "utils.h"
#include "manage-consumer.h"
#include "clear.h"
+#include "agent-thread.h"
static bool is_root;
case LTTNG_CONSUMER64_UST:
{
if (config.consumerd64_lib_dir.value) {
- char *tmp;
+ const char *tmp;
size_t tmplen;
char *tmpnew;
case LTTNG_CONSUMER32_UST:
{
if (config.consumerd32_lib_dir.value) {
- char *tmp;
+ const char *tmp;
size_t tmplen;
char *tmpnew;
{
int fd, ret;
struct lttng_userspace_probe_location *probe_location;
- const struct lttng_userspace_probe_location_lookup_method *lookup = NULL;
struct lttng_dynamic_buffer probe_location_buffer;
struct lttng_buffer_view buffer_view;
* Set the file descriptor received from the client through the unix
* socket in the probe location.
*/
- lookup = lttng_userspace_probe_location_get_lookup_method(probe_location);
- if (!lookup) {
- ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
- goto error;
- }
-
- /*
- * From the kernel tracer's perspective, all userspace probe event types
- * are all the same: a file and an offset.
- */
- switch (lttng_userspace_probe_location_lookup_method_get_type(lookup)) {
- case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
- ret = lttng_userspace_probe_location_function_set_binary_fd(
- probe_location, fd);
- break;
- case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
- ret = lttng_userspace_probe_location_tracepoint_set_binary_fd(
- probe_location, fd);
- break;
- default:
- ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
- goto error;
- }
-
+ ret = lttng_userspace_probe_location_set_binary_fd(probe_location, fd);
if (ret) {
ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
goto error;
int ret = LTTNG_OK;
int need_tracing_session = 1;
int need_domain;
+ int need_consumerd = 1;
DBG("Processing client command %d", cmd_ctx->lsm->cmd_type);
case LTTNG_SET_SESSION_SHM_PATH:
case LTTNG_REGENERATE_METADATA:
case LTTNG_REGENERATE_STATEDUMP:
- case LTTNG_REGISTER_TRIGGER:
- case LTTNG_UNREGISTER_TRIGGER:
case LTTNG_ROTATE_SESSION:
case LTTNG_ROTATION_GET_INFO:
case LTTNG_ROTATION_SET_SCHEDULE:
case LTTNG_SESSION_LIST_ROTATION_SCHEDULES:
case LTTNG_CLEAR_SESSION:
+ case LTTNG_LIST_TRIGGERS:
need_domain = 0;
break;
default:
need_domain = 1;
}
+ /* Needs a functioning consumerd */
+ switch (cmd_ctx->lsm->cmd_type) {
+ case LTTNG_REGISTER_TRIGGER:
+ case LTTNG_UNREGISTER_TRIGGER:
+ need_consumerd = 0;
+ break;
+ default:
+ need_consumerd = 1;
+ break;
+ }
+
if (config.no_kernel && need_domain
&& cmd_ctx->lsm->domain.type == LTTNG_DOMAIN_KERNEL) {
if (!is_root) {
case LTTNG_ROTATE_SESSION:
case LTTNG_ROTATION_GET_INFO:
case LTTNG_SESSION_LIST_ROTATION_SCHEDULES:
+ case LTTNG_REGISTER_TRIGGER:
+ case LTTNG_LIST_TRIGGERS:
break;
default:
/* Setup lttng message with no payload */
case LTTNG_SAVE_SESSION:
case LTTNG_REGISTER_TRIGGER:
case LTTNG_UNREGISTER_TRIGGER:
+ case LTTNG_LIST_TRIGGERS:
need_tracing_session = 0;
break;
default:
}
/* Consumer is in an ERROR state. Report back to client */
- if (uatomic_read(&kernel_consumerd_state) == CONSUMER_ERROR) {
+ if (need_consumerd && uatomic_read(&kernel_consumerd_state) ==
+ CONSUMER_ERROR) {
ret = LTTNG_ERR_NO_KERNCONSUMERD;
goto error;
}
case LTTNG_DOMAIN_JUL:
case LTTNG_DOMAIN_LOG4J:
case LTTNG_DOMAIN_PYTHON:
+ if (!agent_tracing_is_enabled()) {
+ ret = LTTNG_ERR_AGENT_TRACING_DISABLED;
+ goto error;
+ }
+ /* Fallthrough */
case LTTNG_DOMAIN_UST:
{
if (!ust_app_supported()) {
ret = LTTNG_ERR_NO_UST;
goto error;
}
+
/* Consumer is in an ERROR state. Report back to client */
- if (uatomic_read(&ust_consumerd_state) == CONSUMER_ERROR) {
+ if (need_consumerd && uatomic_read(&ust_consumerd_state) ==
+ CONSUMER_ERROR) {
ret = LTTNG_ERR_NO_USTCONSUMERD;
goto error;
}
}
case LTTNG_REGISTER_TRIGGER:
{
+ struct lttng_dynamic_buffer payload;
+ struct lttng_trigger *return_trigger;
+
+ lttng_dynamic_buffer_init(&payload);
ret = cmd_register_trigger(cmd_ctx, *sock,
- notification_thread_handle);
+ notification_thread_handle, &return_trigger);
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
+
+ ret = lttng_trigger_serialize(return_trigger, &payload, NULL);
+ if (ret) {
+ ERR("Failed to serialize trigger in reply to \"register trigger\" command");
+ ret = LTTNG_ERR_NOMEM;
+ lttng_trigger_destroy(return_trigger);
+ goto error;
+ }
+ ret = setup_lttng_msg_no_cmd_header(cmd_ctx, payload.data,
+ payload.size);
+ if (ret) {
+ lttng_trigger_destroy(return_trigger);
+ ret = LTTNG_ERR_NOMEM;
+ goto error;
+ }
+ lttng_trigger_destroy(return_trigger);
+ lttng_dynamic_buffer_reset(&payload);
+ ret = LTTNG_OK;
break;
}
case LTTNG_UNREGISTER_TRIGGER:
ret = cmd_clear_session(cmd_ctx->session, sock);
break;
}
+ case LTTNG_LIST_TRIGGERS:
+ {
+ struct lttng_dynamic_buffer payload;
+ struct lttng_triggers *return_triggers;
+
+ lttng_dynamic_buffer_init(&payload);
+ ret = cmd_list_triggers(cmd_ctx, *sock,
+ notification_thread_handle, &return_triggers);
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
+
+ ret = lttng_triggers_serialize(return_triggers, &payload);
+ if (ret) {
+ ERR("Failed to serialize triggers in reply to \"list triggers\" command");
+ ret = LTTNG_ERR_NOMEM;
+ lttng_triggers_destroy(return_triggers);
+ goto error;
+ }
+ ret = setup_lttng_msg_no_cmd_header(cmd_ctx, payload.data,
+ payload.size);
+ if (ret) {
+ ret = LTTNG_ERR_NOMEM;
+ lttng_triggers_destroy(return_triggers);
+ goto error;
+ }
+ lttng_dynamic_buffer_reset(&payload);
+ lttng_triggers_destroy(return_triggers);
+ ret = LTTNG_OK;
+ break;
+ }
default:
ret = LTTNG_ERR_UND;
break;
#include <lttng/location-internal.h>
#include <lttng/trigger/trigger-internal.h>
#include <lttng/condition/condition.h>
+#include <lttng/condition/condition-internal.h>
+#include <lttng/condition/event-rule.h>
+#include <lttng/condition/event-rule-internal.h>
+#include <lttng/event-rule/event-rule.h>
+#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/event-rule/uprobe-internal.h>
+#include <lttng/event-rule/tracepoint.h>
#include <lttng/action/action.h>
#include <lttng/channel.h>
#include <lttng/channel-internal.h>
return ret;
}
+/* TODO: is this the best place to perform this? (code wise) */
+/*
+ * Set sock to -1 if reception of more information is not necessary e.g on
+ * unregister. TODO find a better way.
+ *
+ * On success LTTNG_OK. On error, returns lttng_error code.
+ * */
+static enum lttng_error_code prepare_trigger_object(struct lttng_trigger *trigger, int sock)
+{
+ enum lttng_error_code ret;
+ /* Internal object of the trigger might have to "generate" and
+ * "populate" internal field e.g filter bytecode
+ */
+ struct lttng_condition *condition = NULL;
+ condition = lttng_trigger_get_condition(trigger);
+ if (!condition) {
+ ret = LTTNG_ERR_INVALID_TRIGGER;
+ goto end;
+ }
+
+ switch (lttng_condition_get_type(condition)) {
+ case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT:
+ {
+ struct lttng_event_rule *event_rule;
+ const struct lttng_credentials *credential = lttng_trigger_get_credentials(trigger);
+ lttng_condition_event_rule_get_rule_no_const(
+ condition, &event_rule);
+ ret = lttng_event_rule_populate(event_rule, credential->uid, credential->gid);
+ if (ret != LTTNG_OK) {
+ goto end;
+ }
+
+ switch (lttng_event_rule_get_type(event_rule)) {
+ case LTTNG_EVENT_RULE_TYPE_UPROBE:
+ {
+ int fd;
+ struct lttng_userspace_probe_location *location = lttng_event_rule_uprobe_get_location_no_const(event_rule);
+
+ if (sock < 0) {
+ /* Nothing to receive */
+ break;
+ }
+ /*
+ * Receive the file descriptor to the target binary from
+ * the client.
+ */
+ DBG("Receiving userspace probe target FD from client ...");
+ ret = lttcomm_recv_fds_unix_sock(sock, &fd, 1);
+ if (ret <= 0) {
+ DBG("Nothing recv() from client userspace probe fd... continuing");
+ ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
+ goto end;
+ }
+
+ /*
+ * Set the file descriptor received from the client
+ * through the unix socket in the probe location.
+ */
+ ret = lttng_userspace_probe_location_set_binary_fd(
+ location, fd);
+ if (ret) {
+ ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
+ goto end;
+ }
+
+ break;
+ }
+ default:
+ /* Nothing to do */
+ break;
+ }
+ ret = LTTNG_OK;
+ break;
+ }
+ default:
+ {
+ ret = LTTNG_OK;
+ break;
+ }
+ }
+end:
+ return ret;
+}
+
+/* Caller must call lttng_destroy_trigger on the returned trigger object */
int cmd_register_trigger(struct command_ctx *cmd_ctx, int sock,
- struct notification_thread_handle *notification_thread)
+ struct notification_thread_handle *notification_thread,
+ struct lttng_trigger **return_trigger)
{
int ret;
size_t trigger_len;
goto end;
}
+ /* Set the trigger credential */
+ lttng_trigger_set_credentials(trigger, cmd_ctx->creds.uid, cmd_ctx->creds.gid);
+
+ /* Prepare internal trigger object if needed on reception.
+ * Handles also special treatment for certain internal object of the
+ * trigger (e.g uprobe event rule binary fd.
+ */
+ ret = prepare_trigger_object(trigger, sock);
+ if (ret != LTTNG_OK) {
+ goto end;
+ }
+
+ /*
+ * Since we return the trigger object, take a reference to it
+ * Caller is responsible for calling lttng_destroy_trigger on it.
+ * This thread does not OWN the trigger.
+ */
+ lttng_trigger_get(trigger);
+
+ /* Inform the notification thread */
ret = notification_thread_command_register_trigger(notification_thread,
trigger);
- /* Ownership of trigger was transferred. */
+ if (ret != LTTNG_OK) {
+ goto end;
+ }
+
+ /* Synchronize tracers, only if needed */
+ /* TODO: maybe extract somewhere else */
+ {
+ struct lttng_condition *condition = NULL;
+ condition = lttng_trigger_get_condition(trigger);
+ if (!condition) {
+ ret = LTTNG_ERR_INVALID_TRIGGER;
+ goto end;
+ }
+
+ if (lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT) {
+ const struct lttng_event_rule *rule = NULL;
+ (void) lttng_condition_event_rule_get_rule(condition, &rule);
+ if (!rule) {
+ ret = LTTNG_ERR_INVALID_TRIGGER;
+ goto end;
+ }
+ if (lttng_event_rule_get_domain_type(rule) == LTTNG_DOMAIN_KERNEL) {
+ /* TODO: get the token value from the
+ * notification thread and only perform an
+ * enable and a disable.... This is NOT
+ * OPTIMIZED AT ALL
+ */
+ kernel_update_tokens();
+ } else {
+ /* TODO: get the token value from the
+ * notification thread and only perform an
+ * enable and a disable.... This is NOT
+ * OPTIMIZED AT ALL
+ */
+ ust_app_global_update_all_tokens();
+ /* Agent handling */
+ if (lttng_event_rule_is_agent(rule)) {
+ struct agent *agt;
+ const char *pattern;
+ enum lttng_domain_type domain_type;
+ domain_type = lttng_event_rule_get_domain_type(
+ rule);
+ (void) lttng_event_rule_tracepoint_get_pattern(
+ rule, &pattern);
+ agt = trigger_find_agent(domain_type);
+ if (!agt) {
+ agt = agent_create(domain_type);
+ if (!agt) {
+ ret = LTTNG_ERR_NOMEM;
+ goto end;
+ }
+ agent_add(agt, trigger_agents_ht_by_domain);
+ }
+
+ ret = trigger_agent_enable(
+ trigger, agt);
+ if (ret != LTTNG_OK) {
+ goto end;
+ }
+ }
+ }
+ }
+ }
+
+ /* Return an image of the updated object to the client */
+ *return_trigger = trigger;
+ /* Ownership of trigger was transferred to caller. */
trigger = NULL;
end:
lttng_trigger_destroy(trigger);
goto end;
}
+ lttng_trigger_set_credentials(trigger, cmd_ctx->creds.uid, cmd_ctx->creds.gid);
+
+ /* TODO: forgotting this bited me for agent since the filter is
+ * genereted on this side. Wonder if we could find a way to detect when
+ * do it or not.
+ */
+
+ /* Prepare internal trigger object if needed on reception.
+ * Handles also special treatment for certain internal object of the
+ * trigger (e.g uprobe event rule binary fd.
+ */
+ ret = prepare_trigger_object(trigger, -1);
+ if (ret != LTTNG_OK) {
+ goto end;
+ }
+
ret = notification_thread_command_unregister_trigger(notification_thread,
trigger);
+
+ /* Synchronize tracers, only if needed */
+ /* TODO: maybe extract somewhere else */
+ {
+ struct lttng_condition *condition = NULL;
+ condition = lttng_trigger_get_condition(trigger);
+ if (!condition) {
+ ret = LTTNG_ERR_INVALID_TRIGGER;
+ goto end;
+ }
+
+ if (lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT) {
+ const struct lttng_event_rule *rule = NULL;
+ (void) lttng_condition_event_rule_get_rule(condition, &rule);
+ if (!rule) {
+ ret = LTTNG_ERR_INVALID_TRIGGER;
+ goto end;
+ }
+ if (lttng_event_rule_get_domain_type(rule) == LTTNG_DOMAIN_KERNEL) {
+ /* TODO: get the token value from the
+ * notification thread and only perform an
+ * enable and a disable.... This is NOT
+ * OPTIMIZED AT ALL
+ */
+ kernel_update_tokens();
+ } else {
+ /* TODO: get the token value from the
+ * notification thread and only perform an
+ * enable and a disable.... This is NOT
+ * OPTIMIZED AT ALL
+ */
+ ust_app_global_update_all_tokens();
+ if (lttng_event_rule_is_agent(rule)) {
+ struct agent *agt;
+ const char *pattern;
+ enum lttng_domain_type domain_type;
+
+ domain_type = lttng_event_rule_get_domain_type(
+ rule);
+ (void) lttng_event_rule_tracepoint_get_pattern(
+ rule, &pattern);
+
+ agt = trigger_find_agent(domain_type);
+ if (!agt) {
+ ret = LTTNG_ERR_UST_EVENT_NOT_FOUND;
+ goto end;
+ }
+ ret = trigger_agent_disable(
+ trigger, agt);
+ if (ret != LTTNG_OK) {
+ goto end;
+ }
+ }
+ }
+ }
+ }
+
end:
lttng_trigger_destroy(trigger);
lttng_dynamic_buffer_reset(&trigger_buffer);
return ret;
}
+int cmd_list_triggers(struct command_ctx *cmd_ctx, int sock,
+ struct notification_thread_handle *notification_thread,
+ struct lttng_triggers **return_triggers)
+{
+ int ret = 0;
+ enum lttng_error_code ret_code;
+ struct lttng_triggers *triggers = NULL;
+
+ /* Get list of token trigger from the notification thread here */
+ ret_code = notification_thread_command_list_triggers(notification_thread_handle, cmd_ctx->creds.uid, cmd_ctx->creds.gid, &triggers);
+ if (ret_code != LTTNG_OK) {
+ ret = ret_code;
+ goto end;
+ }
+
+ /* Return a "view" of the current triggers */
+ *return_triggers = triggers;
+ triggers = NULL;
+ ret = LTTNG_OK;
+end:
+ lttng_triggers_destroy(triggers);
+ return ret;
+}
/*
* Send relayd sockets from snapshot output to consumer. Ignore request if the
* snapshot output is *not* set with a remote destination.
int cmd_regenerate_statedump(struct ltt_session *session);
int cmd_register_trigger(struct command_ctx *cmd_ctx, int sock,
- struct notification_thread_handle *notification_thread_handle);
+ struct notification_thread_handle *notification_thread_handle,
+ struct lttng_trigger **return_trigger);
int cmd_unregister_trigger(struct command_ctx *cmd_ctx, int sock,
struct notification_thread_handle *notification_thread_handle);
+int cmd_list_triggers(struct command_ctx *cmd_ctx, int sock,
+ struct notification_thread_handle *notification_thread_handle,
+ struct lttng_triggers **return_triggers);
+
int cmd_rotate_session(struct ltt_session *session,
struct lttng_rotate_session_return *rotate_return,
bool quiet_rotation,
{
struct ltt_session *sess, *stmp;
const struct ltt_session_list *session_list = session_get_list();
+ struct ust_app *app;
/* Consumer is in an ERROR state. Stop any application update. */
if (uatomic_read(&ust_consumerd_state) == CONSUMER_ERROR) {
return;
}
+ rcu_read_lock();
+ assert(app_sock >= 0);
+ app = ust_app_find_by_sock(app_sock);
+ if (app == NULL) {
+ /*
+ * Application can be unregistered before so
+ * this is possible hence simply stopping the
+ * update.
+ */
+ DBG3("UST app update failed to find app sock %d",
+ app_sock);
+ goto unlock_rcu;
+ }
+
+ /* Update all tokens for the app */
+ ust_app_global_update_tokens(app);
+
/* For all tracing session(s) */
cds_list_for_each_entry_safe(sess, stmp, &session_list->head, list) {
- struct ust_app *app;
-
if (!session_get(sess)) {
continue;
}
goto unlock_session;
}
- rcu_read_lock();
- assert(app_sock >= 0);
- app = ust_app_find_by_sock(app_sock);
- if (app == NULL) {
- /*
- * Application can be unregistered before so
- * this is possible hence simply stopping the
- * update.
- */
- DBG3("UST app update failed to find app sock %d",
- app_sock);
- goto unlock_rcu;
- }
ust_app_global_update(sess->ust_session, app);
- unlock_rcu:
- rcu_read_unlock();
unlock_session:
session_unlock(sess);
session_put(sess);
}
+
+unlock_rcu:
+ rcu_read_unlock();
}
/*
/* Set app version. This call will print an error if needed. */
(void) ust_app_version(app);
+ (void) ust_app_setup_trigger_group(app);
+
/* Send notify socket through the notify pipe. */
ret = send_socket_to_thread(
notifiers->apps_cmd_notify_pipe_write_fd,
#include <string.h>
#include <lttng/lttng.h>
+#include <lttng/condition/condition.h>
+#include <lttng/condition/event-rule.h>
+#include <lttng/event-rule/event-rule.h>
+#include <lttng/event-rule/event-rule-internal.h>
#include <common/error.h>
#include <common/sessiond-comm/sessiond-comm.h>
#include <common/filter.h>
#include "trace-kernel.h"
#include "trace-ust.h"
#include "agent.h"
+#include "utils.h"
/*
* Add unique UST event based on the event name, filter bytecode and loglevel.
return ret;
}
+static void agent_enable_all(struct agent *agt)
+{
+ struct agent_event *aevent;
+ struct lttng_ht_iter iter;
+
+ /* Flag every event that they are now enabled. */
+ rcu_read_lock();
+ cds_lfht_for_each_entry (
+ agt->events->ht, &iter.iter, aevent, node.node) {
+ aevent->enabled = 1;
+ }
+ rcu_read_unlock();
+}
+
/*
* Enable all agent event for a given UST session.
*
struct lttng_filter_bytecode *filter ,char *filter_expression)
{
int ret;
- struct agent_event *aevent;
- struct lttng_ht_iter iter;
assert(usess);
goto error;
}
- /* Flag every event that they are now enabled. */
- rcu_read_lock();
- cds_lfht_for_each_entry(agt->events->ht, &iter.iter, aevent,
- node.node) {
- aevent->enabled = 1;
- }
- rcu_read_unlock();
+ agent_enable_all(agt);
ret = LTTNG_OK;
return ret;
}
-/*
- * Enable a single agent event for a given UST session.
- *
- * Return LTTNG_OK on success or else a LTTNG_ERR* code.
- */
-int event_agent_enable(struct ltt_ust_session *usess,
- struct agent *agt, struct lttng_event *event,
+static int agent_enable(struct agent *agt,
+ struct lttng_event *event,
struct lttng_filter_bytecode *filter,
char *filter_expression)
{
int ret, created = 0;
struct agent_event *aevent;
- assert(usess);
assert(event);
assert(agt);
- DBG("Event agent enabling %s for session %" PRIu64 " with loglevel type %d "
- ", loglevel %d and filter \"%s\"", event->name,
- usess->id, event->loglevel_type, event->loglevel,
- filter_expression ? filter_expression : "NULL");
-
aevent = agent_find_event(event->name, event->loglevel_type,
event->loglevel, filter_expression, agt);
if (!aevent) {
return ret;
}
+/*
+ * Enable a single agent event for a given UST session.
+ *
+ * Return LTTNG_OK on success or else a LTTNG_ERR* code.
+ */
+int event_agent_enable(struct ltt_ust_session *usess,
+ struct agent *agt,
+ struct lttng_event *event,
+ struct lttng_filter_bytecode *filter,
+ char *filter_expression)
+{
+ assert(usess);
+ assert(event);
+ assert(agt);
+
+ DBG("Event agent enabling %s for session %" PRIu64
+ " with loglevel type %d "
+ ", loglevel %d and filter \"%s\"",
+ event->name, usess->id, event->loglevel_type,
+ event->loglevel,
+ filter_expression ? filter_expression : "NULL");
+
+ return agent_enable(agt, event, filter, filter_expression);
+}
+
+/*
+ * Enable a single agent event for a trigger.
+ *
+ * Return LTTNG_OK on success or else a LTTNG_ERR* code.
+ */
+int trigger_agent_enable(const struct lttng_trigger *trigger, struct agent *agt)
+{
+ int ret;
+ enum lttng_condition_status c_status;
+ enum lttng_domain_type d_type;
+ const struct lttng_condition *condition;
+ const struct lttng_event_rule *rule;
+ const char *filter_expression;
+ char *filter_expression_copy = NULL;
+ const struct lttng_filter_bytecode *filter_bytecode;
+ struct lttng_filter_bytecode *filter_bytecode_copy = NULL;
+ struct lttng_event *event = NULL;
+
+ assert(trigger);
+ assert(agt);
+
+ condition = lttng_trigger_get_const_condition(trigger);
+
+ assert(lttng_condition_get_type(condition) ==
+ LTTNG_CONDITION_TYPE_EVENT_RULE_HIT);
+
+ c_status = lttng_condition_event_rule_get_rule(condition, &rule);
+ assert(c_status == LTTNG_CONDITION_STATUS_OK);
+
+ assert(lttng_event_rule_get_type(rule) ==
+ LTTNG_EVENT_RULE_TYPE_TRACEPOINT);
+
+ d_type = lttng_event_rule_get_domain_type(rule);
+ assert(d_type == agt->domain);
+
+ event = lttng_event_rule_generate_lttng_event(rule);
+ if (!event) {
+ ret = LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ /* Get the internal filter_expression and bytecode */
+ filter_expression = lttng_event_rule_get_filter(rule);
+ if (filter_expression) {
+ filter_expression_copy = strdup(filter_expression);
+ if (!filter_expression_copy) {
+ ret = LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ /* Get the filter bytecode */
+ filter_bytecode = lttng_event_rule_get_filter_bytecode(rule);
+ if (filter_bytecode) {
+ filter_bytecode_copy =
+ copy_filter_bytecode(filter_bytecode);
+ if (!filter_bytecode_copy) {
+ ret = LTTNG_ERR_NOMEM;
+ goto end;
+ }
+ }
+ }
+
+ DBG("Event agent enabling %s for trigger %" PRIu64
+ " with loglevel type %d "
+ ", loglevel %d and filter \"%s\"",
+ event->name, lttng_trigger_get_key(trigger),
+ event->loglevel_type, event->loglevel,
+ filter_expression ? filter_expression : "NULL");
+
+ ret = agent_enable(agt, event, filter_bytecode_copy,
+ filter_expression_copy);
+ /* Ownership was passed even in case of error */
+ filter_expression_copy = NULL;
+ filter_bytecode_copy = NULL;
+
+end:
+ free(filter_expression_copy);
+ free(filter_bytecode_copy);
+ free(event);
+ return ret;
+}
+
/*
* Return the default event name associated with the provided UST domain. Return
* NULL on error.
return default_event_name;
}
+static int trigger_agent_disable_one(const struct lttng_trigger *trigger,
+ struct agent *agt,
+ struct agent_event *aevent)
+
+{
+ int ret;
+
+ assert(agt);
+ assert(trigger);
+ assert(aevent);
+
+ /*
+ * Actual ust event un-registration happens on the trigger
+ * un-registration at that point.
+ */
+
+ DBG("Event agent disabling %s (loglevel type %d, loglevel value %d) for trigger %" PRIu64,
+ aevent->name, aevent->loglevel_type,
+ aevent->loglevel_value, lttng_trigger_get_key(trigger));
+
+ /* Already disabled? */
+ if (!aevent->enabled) {
+ goto end;
+ }
+
+ ret = agent_disable_event(aevent, agt->domain);
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
+
+end:
+ return LTTNG_OK;
+
+error:
+ return ret;
+}
+
/*
* Disable a given agent event for a given UST session.
*
return ret;
}
+/*
+ * Disable agent event matching a given trigger.
+ *
+ * Return LTTNG_OK on success or else a LTTNG_ERR* code.
+ */
+int trigger_agent_disable(
+ const struct lttng_trigger *trigger, struct agent *agt)
+{
+ int ret = LTTNG_OK;
+ struct agent_event *aevent;
+
+ assert(trigger);
+ assert(agt);
+
+ DBG("Event agent disabling for trigger %" PRIu64,
+ lttng_trigger_get_key(trigger));
+
+ rcu_read_lock();
+ aevent = agent_find_event_by_trigger(trigger, agt);
+
+ if (aevent == NULL) {
+ DBG2("Event agent NOT found by trigger %" PRIu64,
+ lttng_trigger_get_key(trigger));
+ ret = LTTNG_ERR_UST_EVENT_NOT_FOUND;
+ goto end;
+ }
+
+ ret = trigger_agent_disable_one(trigger, agt, aevent);
+
+ if (ret != LTTNG_OK) {
+ goto end;
+ }
+
+end:
+ rcu_read_unlock();
+ return ret;
+}
+
/*
* Disable all agent events matching a given name for a given UST session.
*
const char *event_name);
int event_agent_disable_all(struct ltt_ust_session *usess, struct agent *agt);
+int trigger_agent_enable(
+ const struct lttng_trigger *trigger, struct agent *agt);
+int trigger_agent_disable(
+ const struct lttng_trigger *trigger, struct agent *agt);
+
const char *event_get_default_agent_ust_name(enum lttng_domain_type domain);
#endif /* _LTT_EVENT_H */
struct health_app *health_sessiond;
struct notification_thread_handle *notification_thread_handle;
+pthread_mutex_t notification_trigger_tokens_ht_lock = PTHREAD_MUTEX_INITIALIZER;
struct lttng_ht *agent_apps_ht_by_sock = NULL;
+struct lttng_ht *trigger_agents_ht_by_domain = NULL;
+
+struct lttng_ht *registered_ust_event_rule = NULL;
struct lttng_kernel_tracer_version kernel_tracer_version;
struct lttng_kernel_tracer_abi_version kernel_tracer_abi_version;
HEALTH_SESSIOND_TYPE_NOTIFICATION = 8,
HEALTH_SESSIOND_TYPE_ROTATION = 9,
HEALTH_SESSIOND_TYPE_TIMER = 10,
+ HEALTH_SESSIOND_TYPE_ACTION_EXECUTOR = 11,
NR_HEALTH_SESSIOND_TYPES,
};
#include <sys/types.h>
#include <common/common.h>
+#include <common/hashtable/utils.h>
#include <common/trace-chunk.h>
#include <common/kernel-ctl/kernel-ctl.h>
#include <common/kernel-ctl/kernel-ioctl.h>
#include <common/sessiond-comm/sessiond-comm.h>
+#include <lttng/userspace-probe.h>
+#include <lttng/userspace-probe-internal.h>
+#include <lttng/condition/event-rule.h>
+#include <lttng/condition/event-rule-internal.h>
+#include <lttng/event-rule/event-rule.h>
+#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/event-rule/uprobe-internal.h>
+
#include "lttng-sessiond.h"
#include "lttng-syscall.h"
#include "consumer.h"
#include "utils.h"
#include "rotate.h"
#include "modprobe.h"
+#include "notification-thread-commands.h"
/*
* Key used to reference a channel between the sessiond and the consumer. This
static const char *module_proc_lttng = "/proc/lttng";
static int kernel_tracer_fd = -1;
+static int kernel_tracer_trigger_group_fd = -1;
+static int kernel_tracer_trigger_group_notification_fd = -1;
+static struct ltt_kernel_token_event_rule_list kernel_tracer_token_list;
-#include <lttng/userspace-probe.h>
-#include <lttng/userspace-probe-internal.h>
/*
* Add context on a kernel channel.
*
return -1;
}
+/*
+ * Create a kernel channel, register it to the kernel tracer and add it to the
+ * kernel session.
+ */
+static
+int kernel_create_trigger_group(int *trigger_group_fd)
+{
+ int ret;
+ int local_fd = -1;
+
+ assert(trigger_group_fd);
+
+ /* Kernel tracer channel creation */
+ ret = kernctl_create_trigger_group(kernel_tracer_fd);
+ if (ret < 0) {
+ PERROR("ioctl kernel create trigger group");
+ ret = -1;
+ goto error;
+ }
+
+ /* Store locally */
+ local_fd = ret;
+
+ /* Prevent fd duplication after execlp() */
+ ret = fcntl(local_fd, F_SETFD, FD_CLOEXEC);
+ if (ret < 0) {
+ PERROR("fcntl session fd");
+ }
+
+ DBG("Kernel trigger group created (fd: %d)",
+ local_fd);
+ ret = 0;
+
+error:
+ *trigger_group_fd = local_fd;
+ return ret;
+}
+
/*
* Compute the offset of the instrumentation byte in the binary based on the
* function probe location using the ELF lookup method.
static
int extract_userspace_probe_offset_function_elf(
const struct lttng_userspace_probe_location *probe_location,
- struct ltt_kernel_session *session, uint64_t *offset)
+ uid_t uid, gid_t gid, uint64_t *offset)
{
int fd;
int ret = 0;
goto end;
}
- ret = run_as_extract_elf_symbol_offset(fd, symbol, session->uid,
- session->gid, offset);
+ ret = run_as_extract_elf_symbol_offset(fd, symbol, uid, gid, offset);
if (ret < 0) {
DBG("userspace probe offset calculation failed for "
"function %s", symbol);
static
int extract_userspace_probe_offset_tracepoint_sdt(
const struct lttng_userspace_probe_location *probe_location,
- struct ltt_kernel_session *session, uint64_t **offsets,
+ uid_t uid, gid_t gid, uint64_t **offsets,
uint32_t *offsets_count)
{
enum lttng_userspace_probe_location_lookup_method_type lookup_method_type;
}
ret = run_as_extract_sdt_probe_offsets(fd, provider_name, probe_name,
- session->uid, session->gid, offsets, offsets_count);
+ uid, gid, offsets, offsets_count);
if (ret < 0) {
DBG("userspace probe offset calculation failed for sdt "
"probe %s:%s", provider_name, probe_name);
return ret;
}
-/*
- * Extract the offsets of the instrumentation point for the different lookup
- * methods.
- */
static
-int userspace_probe_add_callsites(struct lttng_event *ev,
- struct ltt_kernel_session *session, int fd)
+int userspace_probe_add_callsite(
+ const struct lttng_userspace_probe_location *location,
+ uid_t uid, gid_t gid, int fd)
{
const struct lttng_userspace_probe_location_lookup_method *lookup_method = NULL;
enum lttng_userspace_probe_location_lookup_method_type type;
- const struct lttng_userspace_probe_location *location = NULL;
int ret;
- assert(ev);
- assert(ev->type == LTTNG_EVENT_USERSPACE_PROBE);
-
- location = lttng_event_get_userspace_probe_location(ev);
- if (!location) {
- ret = -1;
- goto end;
- }
- lookup_method =
- lttng_userspace_probe_location_get_lookup_method(location);
+ lookup_method = lttng_userspace_probe_location_get_lookup_method(location);
if (!lookup_method) {
ret = -1;
goto end;
struct lttng_kernel_event_callsite callsite;
uint64_t offset;
- ret = extract_userspace_probe_offset_function_elf(location, session, &offset);
+ ret = extract_userspace_probe_offset_function_elf(location,
+ uid, gid, &offset);
if (ret) {
ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
goto end;
callsite.u.uprobe.offset = offset;
ret = kernctl_add_callsite(fd, &callsite);
if (ret) {
- WARN("Adding callsite to userspace probe "
- "event %s failed.", ev->name);
+ WARN("Adding callsite to ELF userspace probe failed.");
ret = LTTNG_ERR_KERN_ENABLE_FAIL;
goto end;
}
* This call allocates the offsets buffer. This buffer must be freed
* by the caller
*/
- ret = extract_userspace_probe_offset_tracepoint_sdt(location, session,
- &offsets, &offsets_count);
+ ret = extract_userspace_probe_offset_tracepoint_sdt(location,
+ uid, gid, &offsets, &offsets_count);
if (ret) {
ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
goto end;
callsite.u.uprobe.offset = offsets[i];
ret = kernctl_add_callsite(fd, &callsite);
if (ret) {
- WARN("Adding callsite to userspace probe "
- "event %s failed.", ev->name);
+ WARN("Adding callsite to SDT userspace probe "
+ "failed.");
ret = LTTNG_ERR_KERN_ENABLE_FAIL;
free(offsets);
goto end;
return ret;
}
+/*
+ * Extract the offsets of the instrumentation point for the different lookup
+ * methods.
+ */
+static
+int userspace_probe_event_add_callsites(struct lttng_event *ev,
+ struct ltt_kernel_session *session, int fd)
+{
+ const struct lttng_userspace_probe_location *location = NULL;
+ int ret;
+
+ assert(ev);
+ assert(ev->type == LTTNG_EVENT_USERSPACE_PROBE);
+
+ location = lttng_event_get_userspace_probe_location(ev);
+ if (!location) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = userspace_probe_add_callsite(location, session->uid, session->gid,
+ fd);
+ if (ret) {
+ WARN("Adding callsite to userspace probe event \"%s\" "
+ "failed.", ev->name);
+ }
+
+end:
+ return ret;
+}
+
+/*
+ * Extract the offsets of the instrumentation point for the different lookup
+ * methods.
+ */
+static int userspace_probe_event_rule_add_callsites(
+ const struct lttng_event_rule *rule,
+ const struct lttng_credentials *creds,
+ int fd)
+{
+ const struct lttng_userspace_probe_location *location = NULL;
+ enum lttng_event_rule_status status;
+ int ret;
+
+ assert(rule);
+ assert(creds);
+ assert(lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_UPROBE);
+
+ status = lttng_event_rule_uprobe_get_location(rule, &location);
+ if (status != LTTNG_EVENT_RULE_STATUS_OK || !location) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = userspace_probe_add_callsite(location, creds->uid, creds->gid,
+ fd);
+ if (ret) {
+ WARN("Adding callsite to userspace probe object %d"
+ "failed.", fd);
+ }
+
+end:
+ return ret;
+}
+
/*
* Create a kernel event, enable it to the kernel tracer and add it to the
* channel event list of the kernel session.
}
if (ev->type == LTTNG_EVENT_USERSPACE_PROBE) {
- ret = userspace_probe_add_callsites(ev, channel->session, event->fd);
+ ret = userspace_probe_event_add_callsites(ev, channel->session,
+ event->fd);
if (ret) {
goto add_callsite_error;
}
return ret;
}
+/*
+ * Disable a kernel trigger.
+ */
+int kernel_disable_token_event_rule(struct ltt_kernel_token_event_rule *event)
+{
+ int ret;
+
+ assert(event);
+
+ ret = kernctl_disable(event->fd);
+ if (ret < 0) {
+ switch (-ret) {
+ case EEXIST:
+ ret = LTTNG_ERR_KERN_EVENT_EXIST;
+ break;
+ default:
+ PERROR("disable kernel event");
+ break;
+ }
+ goto error;
+ }
+
+ event->enabled = 0;
+ DBG("Kernel trigger token %" PRIu64" disabled (fd: %d)", event->token, event->fd);
+
+ return 0;
+
+error:
+ return ret;
+}
static struct lttng_tracker_list *get_id_tracker_list(
struct ltt_kernel_session *session,
enum lttng_tracker_type tracker_type)
if (ret < 0) {
goto error_modules;
}
-
if (ret < 1) {
WARN("Kernel tracer does not support buffer monitoring. "
"The monitoring timer of channels in the kernel domain "
"will be set to 0 (disabled).");
}
+ ret = kernel_create_trigger_group(&kernel_tracer_trigger_group_fd);
+ if (ret < 0) {
+ /* TODO: error handling if it is not supported etc. */
+ WARN("Failed trigger group creation");
+ kernel_tracer_trigger_group_fd = -1;
+ /* This is not fatal */
+ } else {
+ ret = kernel_create_trigger_group_notification_fd(&kernel_tracer_trigger_group_notification_fd);
+ if (ret < 0) {
+ goto error_modules;
+ }
+ }
+
+ CDS_INIT_LIST_HEAD(&kernel_tracer_token_list.head);
+
DBG("Kernel tracer fd %d", kernel_tracer_fd);
+ DBG("Kernel tracer trigger group fd %d", kernel_tracer_trigger_group_fd);
+ DBG("Kernel tracer trigger group notificationi fd %d", kernel_tracer_trigger_group_notification_fd);
ret = syscall_init_table(kernel_tracer_fd);
if (ret < 0) {
ERR("Unable to populate syscall table. Syscall tracing won't "
"work for this session daemon.");
}
+
return 0;
error_version:
{
int ret;
+ struct ltt_kernel_token_event_rule *rule, *rtmp;
+ cds_list_for_each_entry_safe(rule, rtmp, &kernel_tracer_token_list.head, list) {
+ kernel_disable_token_event_rule(rule);
+ trace_kernel_destroy_token_event_rule(rule);
+ }
+
+ DBG2("Closing kernel trigger group notification fd");
+ if (kernel_tracer_trigger_group_notification_fd >= 0) {
+ ret = close(kernel_tracer_trigger_group_notification_fd);
+ if (ret) {
+ PERROR("close");
+ }
+ kernel_tracer_trigger_group_notification_fd = -1;
+ }
+
+ /* TODO: do we iterate over the list to remove all token? */
+ DBG2("Closing kernel trigger group fd");
+ if (kernel_tracer_trigger_group_fd >= 0) {
+ ret = close(kernel_tracer_trigger_group_fd);
+ if (ret) {
+ PERROR("close");
+ }
+ kernel_tracer_trigger_group_fd = -1;
+ }
+
DBG2("Closing kernel fd");
if (kernel_tracer_fd >= 0) {
ret = close(kernel_tracer_fd);
}
kernel_tracer_fd = -1;
}
+
+
DBG("Unloading kernel modules");
modprobe_remove_lttng_all();
free(syscall_table);
rcu_read_unlock();
return status;
}
+
+enum lttng_error_code kernel_create_trigger_group_notification_fd(
+ int *trigger_group_notification_fd)
+{
+ enum lttng_error_code ret = LTTNG_OK;
+ int local_fd = -1;
+
+ assert(trigger_group_notification_fd);
+
+ ret = kernctl_create_trigger_group_notification_fd(kernel_tracer_trigger_group_fd);
+ if (ret < 0) {
+ PERROR("ioctl kernel create trigger group");
+ ret = -1;
+ goto error;
+ }
+
+ /* Store locally */
+ local_fd = ret;
+
+ /* Prevent fd duplication after execlp() */
+ ret = fcntl(local_fd, F_SETFD, FD_CLOEXEC);
+ if (ret < 0) {
+ PERROR("fcntl session fd");
+ }
+
+ DBG("Kernel trigger group notification created (fd: %d)",
+ local_fd);
+ ret = 0;
+
+error:
+ *trigger_group_notification_fd = local_fd;
+ return ret;
+}
+
+enum lttng_error_code kernel_destroy_trigger_group_notification_fd(
+ int trigger_group_notification_fd)
+{
+ enum lttng_error_code ret = LTTNG_OK;
+ DBG("Closing trigger group notification fd %d", trigger_group_notification_fd);
+ if (trigger_group_notification_fd >= 0) {
+ ret = close(trigger_group_notification_fd);
+ if (ret) {
+ PERROR("close");
+ }
+ }
+ return ret;
+}
+
+static int kernel_create_token_event_rule(struct lttng_event_rule *rule,
+ const struct lttng_credentials *creds, uint64_t token)
+{
+ int err, fd;
+ enum lttng_error_code ret;
+ struct ltt_kernel_token_event_rule *event;
+ struct lttng_kernel_trigger trigger;
+
+ assert(rule);
+
+ ret = trace_kernel_create_token_event_rule(rule, token, &event);
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
+
+ trace_kernel_init_trigger_from_event_rule(event->event_rule, &trigger);
+ trigger.id = event->token;
+
+ fd = kernctl_create_trigger(kernel_tracer_trigger_group_fd, &trigger);
+ if (fd < 0) {
+ switch (-fd) {
+ case EEXIST:
+ ret = LTTNG_ERR_KERN_EVENT_EXIST;
+ break;
+ case ENOSYS:
+ WARN("Trigger type not implemented");
+ ret = LTTNG_ERR_KERN_EVENT_ENOSYS;
+ break;
+ case ENOENT:
+ WARN("Event %s not found!", trigger.name);
+ ret = LTTNG_ERR_KERN_ENABLE_FAIL;
+ break;
+ default:
+ ret = LTTNG_ERR_KERN_ENABLE_FAIL;
+ PERROR("create trigger ioctl");
+ }
+ goto free_event;
+ }
+
+ event->fd = fd;
+ /* Prevent fd duplication after execlp() */
+ err = fcntl(event->fd, F_SETFD, FD_CLOEXEC);
+ if (err < 0) {
+ PERROR("fcntl session fd");
+ }
+
+ if (event->filter) {
+ err = kernctl_filter(event->fd, event->filter);
+ if (err < 0) {
+ switch (-err) {
+ case ENOMEM:
+ ret = LTTNG_ERR_FILTER_NOMEM;
+ break;
+ default:
+ ret = LTTNG_ERR_FILTER_INVAL;
+ break;
+ }
+ goto filter_error;
+ }
+ }
+
+ if (lttng_event_rule_get_type(event->event_rule) ==
+ LTTNG_EVENT_RULE_TYPE_UPROBE) {
+ ret = userspace_probe_event_rule_add_callsites(
+ rule, creds, event->fd);
+ if (ret) {
+ goto add_callsite_error;
+ }
+ }
+
+ err = kernctl_enable(event->fd);
+ if (err < 0) {
+ switch (-err) {
+ case EEXIST:
+ ret = LTTNG_ERR_KERN_EVENT_EXIST;
+ break;
+ default:
+ PERROR("enable kernel trigger");
+ ret = LTTNG_ERR_KERN_ENABLE_FAIL;
+ break;
+ }
+ goto enable_error;
+ }
+
+ /* Add event to event list */
+ cds_list_add(&event->list, &kernel_tracer_token_list.head);
+
+ DBG("Trigger %s created (fd: %d)", trigger.name, event->fd);
+
+ return 0;
+
+add_callsite_error:
+enable_error:
+filter_error:
+ {
+ int closeret;
+
+ closeret = close(event->fd);
+ if (closeret) {
+ PERROR("close event fd");
+ }
+ }
+free_event:
+ free(event);
+error:
+ return ret;
+}
+
+enum lttng_error_code kernel_update_tokens(void)
+{
+ enum lttng_error_code ret = LTTNG_OK;
+ enum lttng_trigger_status t_status;
+ struct ltt_kernel_token_event_rule *token_event_rule_element;
+ struct lttng_triggers *triggers;
+ unsigned int count;
+
+ /* TODO error handling */
+
+ /* Get list of token trigger from the notification thread here */
+ rcu_read_lock();
+ pthread_mutex_lock(¬ification_trigger_tokens_ht_lock);
+ ret = notification_thread_command_get_tokens(notification_thread_handle, &triggers);
+ if (ret != LTTNG_OK) {
+ ret = -1;
+ goto end;
+ }
+
+ assert(triggers);
+
+ t_status = lttng_triggers_get_count(triggers, &count);
+ if (t_status != LTTNG_TRIGGER_STATUS_OK) {
+ ret = -1;
+ goto end;
+ }
+
+ for (unsigned int i = 0; i < count; i++) {
+ struct lttng_condition *condition;
+ struct lttng_event_rule *event_rule;
+ struct lttng_trigger *trigger;
+ struct ltt_kernel_token_event_rule *k_token;
+ const struct lttng_credentials *creds;
+ uint64_t token;
+
+ trigger = lttng_triggers_get_pointer_of_index(triggers, i);
+ assert(trigger);
+
+ /* TODO: error checking and type checking */
+ token = lttng_trigger_get_key(trigger);
+ condition = lttng_trigger_get_condition(trigger);
+ (void) lttng_condition_event_rule_get_rule_no_const(condition, &event_rule);
+
+ if (lttng_event_rule_get_domain_type(event_rule) != LTTNG_DOMAIN_KERNEL) {
+ /* Skip ust related trigger */
+ continue;
+ }
+
+ creds = lttng_trigger_get_credentials(trigger);
+ /* Iterate over all known token trigger */
+ k_token = trace_kernel_find_trigger_by_token(&kernel_tracer_token_list, token);
+ if (!k_token) {
+ ret = kernel_create_token_event_rule(event_rule, creds, token);
+ if (ret < 0) {
+ goto end;
+ }
+ }
+ }
+
+ /* Remove all unknown trigger from the app
+ * TODO find a way better way then this, do it on the unregister command
+ * and be specific on the token to remove instead of going over all
+ * trigger known to the app. This is sub optimal.
+ */
+ cds_list_for_each_entry (token_event_rule_element, &kernel_tracer_token_list.head,
+ list) {
+ uint64_t token;
+ bool found = false;
+
+ token = token_event_rule_element->token;
+
+ /*
+ * Check if the app event trigger still exists on the
+ * notification side.
+ * TODO: might want to change the backing data struct of the
+ * lttng_triggers object to allow quick lookup?
+ * For kernel mostly all of this can be removed once we delete
+ * on a per trigger basis.
+ */
+
+ for (unsigned int i = 0; i < count; i++) {
+ struct lttng_trigger *trigger;
+ uint64_t inner_token;
+
+ trigger = lttng_triggers_get_pointer_of_index(
+ triggers, i);
+ assert(trigger);
+
+ inner_token = lttng_trigger_get_key(trigger);
+
+ if (inner_token == token) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ /* Still valid */
+ continue;
+ }
+
+ kernel_disable_token_event_rule(token_event_rule_element);
+ trace_kernel_destroy_token_event_rule(token_event_rule_element);
+ }
+end:
+ rcu_read_unlock();
+ pthread_mutex_unlock(¬ification_trigger_tokens_ht_lock);
+ return ret;
+
+}
+
+int kernel_get_notification_fd(void)
+{
+ return kernel_tracer_trigger_group_notification_fd;
+}
enum lttng_error_code kernel_create_channel_subdirectories(
const struct ltt_kernel_session *ksess);
+enum lttng_error_code kernel_create_trigger_group_notification_fd(
+ int *trigger_group_notification_fd);
+enum lttng_error_code kernel_destroy_trigger_group_notification_fd(
+ int trigger_group_notification_fd);
+enum lttng_error_code kernel_update_tokens(void);
+int kernel_get_notification_fd(void);
+
#endif /* _LTT_KERNEL_CTL_H */
/* Notification thread handle. */
extern struct notification_thread_handle *notification_thread_handle;
+extern pthread_mutex_t notification_trigger_tokens_ht_lock;
/*
* This contains extra data needed for processing a command received by the
pthread_mutex_destroy(&session_list->lock);
+ DBG("Cleaning up all trigger agents");
+ trigger_agent_ht_clean();
+
DBG("Cleaning up all agent apps");
agent_app_ht_clean();
DBG("Closing all UST sockets");
struct lttng_thread *notification_thread = NULL;
struct lttng_thread *register_apps_thread = NULL;
+ logger_set_thread_name("Main", false);
init_kernel_workarounds();
rcu_register_thread();
goto stop_threads;
}
+ if (trigger_agent_ht_alloc()) {
+ ERR("Failed to allocate trigger agent hash table");
+ retval = -1;
+ goto stop_threads;
+ }
/*
* These actions must be executed as root. We do that *after* setting up
* the sockets path because we MUST make the check for another daemon using
notification_thread_handle = notification_thread_handle_create(
ust32_channel_monitor_pipe,
ust64_channel_monitor_pipe,
- kernel_channel_monitor_pipe);
+ kernel_channel_monitor_pipe,
+ kernel_get_notification_fd());
if (!notification_thread_handle) {
retval = -1;
ERR("Failed to create notification thread shared data");
#define LTTNG_MOD_OPTIONAL 0
/* LTTng kernel tracer mandatory core modules list */
+/* TODO: the new trigger client might not be present in previous lttng-modules
+ * should it be optional?
+ * Can we reuse this to also know of the trigger feature is supported?
+ */
struct kern_modules_param kern_modules_control_core[] = {
- { "lttng-ring-buffer-client-discard" },
- { "lttng-ring-buffer-client-overwrite" },
- { "lttng-ring-buffer-metadata-client" },
- { "lttng-ring-buffer-client-mmap-discard" },
- { "lttng-ring-buffer-client-mmap-overwrite" },
- { "lttng-ring-buffer-metadata-mmap-client" },
+ { (char *) "lttng-ring-buffer-client-discard" },
+ { (char *) "lttng-ring-buffer-client-overwrite" },
+ { (char *) "lttng-ring-buffer-metadata-client" },
+ { (char *) "lttng-ring-buffer-client-mmap-discard" },
+ { (char *) "lttng-ring-buffer-client-mmap-overwrite" },
+ { (char *) "lttng-ring-buffer-metadata-mmap-client" },
+ { (char *) "lttng-ring-buffer-trigger-client" },
};
/* LTTng kernel tracer probe modules list */
struct kern_modules_param kern_modules_probes_default[] = {
- { "lttng-probe-asoc" },
- { "lttng-probe-block" },
- { "lttng-probe-btrfs" },
- { "lttng-probe-compaction" },
- { "lttng-probe-ext3" },
- { "lttng-probe-ext4" },
- { "lttng-probe-gpio" },
- { "lttng-probe-i2c" },
- { "lttng-probe-irq" },
- { "lttng-probe-jbd" },
- { "lttng-probe-jbd2" },
- { "lttng-probe-kmem" },
- { "lttng-probe-kvm" },
- { "lttng-probe-kvm-x86" },
- { "lttng-probe-kvm-x86-mmu" },
- { "lttng-probe-lock" },
- { "lttng-probe-module" },
- { "lttng-probe-napi" },
- { "lttng-probe-net" },
- { "lttng-probe-power" },
- { "lttng-probe-preemptirq" },
- { "lttng-probe-printk" },
- { "lttng-probe-random" },
- { "lttng-probe-rcu" },
- { "lttng-probe-regmap" },
- { "lttng-probe-regulator" },
- { "lttng-probe-rpm" },
- { "lttng-probe-sched" },
- { "lttng-probe-scsi" },
- { "lttng-probe-signal" },
- { "lttng-probe-skb" },
- { "lttng-probe-sock" },
- { "lttng-probe-statedump" },
- { "lttng-probe-sunrpc" },
- { "lttng-probe-timer" },
- { "lttng-probe-udp" },
- { "lttng-probe-vmscan" },
- { "lttng-probe-v4l2" },
- { "lttng-probe-workqueue" },
- { "lttng-probe-writeback" },
- { "lttng-probe-x86-irq-vectors" },
- { "lttng-probe-x86-exceptions" },
+ { (char *) "lttng-probe-asoc" },
+ { (char *) "lttng-probe-block" },
+ { (char *) "lttng-probe-btrfs" },
+ { (char *) "lttng-probe-compaction" },
+ { (char *) "lttng-probe-ext3" },
+ { (char *) "lttng-probe-ext4" },
+ { (char *) "lttng-probe-gpio" },
+ { (char *) "lttng-probe-i2c" },
+ { (char *) "lttng-probe-irq" },
+ { (char *) "lttng-probe-jbd" },
+ { (char *) "lttng-probe-jbd2" },
+ { (char *) "lttng-probe-kmem" },
+ { (char *) "lttng-probe-kvm" },
+ { (char *) "lttng-probe-kvm-x86" },
+ { (char *) "lttng-probe-kvm-x86-mmu" },
+ { (char *) "lttng-probe-lock" },
+ { (char *) "lttng-probe-module" },
+ { (char *) "lttng-probe-napi" },
+ { (char *) "lttng-probe-net" },
+ { (char *) "lttng-probe-power" },
+ { (char *) "lttng-probe-preemptirq" },
+ { (char *) "lttng-probe-printk" },
+ { (char *) "lttng-probe-random" },
+ { (char *) "lttng-probe-rcu" },
+ { (char *) "lttng-probe-regmap" },
+ { (char *) "lttng-probe-regulator" },
+ { (char *) "lttng-probe-rpm" },
+ { (char *) "lttng-probe-sched" },
+ { (char *) "lttng-probe-scsi" },
+ { (char *) "lttng-probe-signal" },
+ { (char *) "lttng-probe-skb" },
+ { (char *) "lttng-probe-sock" },
+ { (char *) "lttng-probe-statedump" },
+ { (char *) "lttng-probe-sunrpc" },
+ { (char *) "lttng-probe-timer" },
+ { (char *) "lttng-probe-udp" },
+ { (char *) "lttng-probe-vmscan" },
+ { (char *) "lttng-probe-v4l2" },
+ { (char *) "lttng-probe-workqueue" },
+ { (char *) "lttng-probe-writeback" },
+ { (char *) "lttng-probe-x86-irq-vectors" },
+ { (char *) "lttng-probe-x86-exceptions" },
};
/* dynamic probe modules list */
static
void init_notification_thread_command(struct notification_thread_command *cmd)
{
- memset(cmd, 0, sizeof(*cmd));
CDS_INIT_LIST_HEAD(&cmd->cmd_list_node);
lttng_waiter_init(&cmd->reply_waiter);
}
return -1;
}
+static
+struct notification_thread_command *notification_thread_command_copy(
+ const struct notification_thread_command *original_cmd)
+{
+ struct notification_thread_command *new_cmd;
+
+ new_cmd = zmalloc(sizeof(*new_cmd));
+ if (!new_cmd) {
+ goto end;
+ }
+
+ *new_cmd = *original_cmd;
+ init_notification_thread_command(new_cmd);
+end:
+ return new_cmd;
+}
+
+static
+int run_command_no_wait(struct notification_thread_handle *handle,
+ const struct notification_thread_command *in_cmd)
+{
+ int ret;
+ uint64_t notification_counter = 1;
+ struct notification_thread_command *new_cmd =
+ notification_thread_command_copy(in_cmd);
+
+ if (!new_cmd) {
+ goto error;
+ }
+ new_cmd->is_async = true;
+
+ pthread_mutex_lock(&handle->cmd_queue.lock);
+ /* Add to queue. */
+ cds_list_add_tail(&new_cmd->cmd_list_node,
+ &handle->cmd_queue.list);
+ /* Wake-up thread. */
+ ret = lttng_write(lttng_pipe_get_writefd(handle->cmd_queue.event_pipe),
+ ¬ification_counter, sizeof(notification_counter));
+ if (ret != sizeof(notification_counter)) {
+ PERROR("write to notification thread's queue event fd");
+ /*
+ * Remove the command from the list so the notification
+ * thread does not process it.
+ */
+ cds_list_del(&new_cmd->cmd_list_node);
+ goto error_unlock_queue;
+ }
+ pthread_mutex_unlock(&handle->cmd_queue.lock);
+ return 0;
+error_unlock_queue:
+ free(new_cmd);
+ pthread_mutex_unlock(&handle->cmd_queue.lock);
+error:
+ return -1;
+}
+
enum lttng_error_code notification_thread_command_register_trigger(
struct notification_thread_handle *handle,
struct lttng_trigger *trigger)
{
int ret;
enum lttng_error_code ret_code;
- struct notification_thread_command cmd;
+ struct notification_thread_command cmd = {};
init_notification_thread_command(&cmd);
{
int ret;
enum lttng_error_code ret_code;
- struct notification_thread_command cmd;
+ struct notification_thread_command cmd = {};
init_notification_thread_command(&cmd);
{
int ret;
enum lttng_error_code ret_code;
- struct notification_thread_command cmd;
+ struct notification_thread_command cmd = {};
init_notification_thread_command(&cmd);
{
int ret;
enum lttng_error_code ret_code;
- struct notification_thread_command cmd;
+ struct notification_thread_command cmd = {};
init_notification_thread_command(&cmd);
{
int ret;
enum lttng_error_code ret_code;
- struct notification_thread_command cmd;
+ struct notification_thread_command cmd = {};
init_notification_thread_command(&cmd);
{
int ret;
enum lttng_error_code ret_code;
- struct notification_thread_command cmd;
+ struct notification_thread_command cmd = {};
init_notification_thread_command(&cmd);
return ret_code;
}
+enum lttng_error_code notification_thread_command_add_application(
+ struct notification_thread_handle *handle,
+ struct lttng_pipe *pipe)
+{
+ int ret;
+ enum lttng_error_code ret_code;
+ struct notification_thread_command cmd = {};
+
+ init_notification_thread_command(&cmd);
+
+ cmd.type = NOTIFICATION_COMMAND_TYPE_ADD_APPLICATION;
+ cmd.parameters.application.read_side_trigger_event_application_pipe = lttng_pipe_get_readfd(pipe);
+
+ ret = run_command_wait(handle, &cmd);
+ if (ret) {
+ ret_code = LTTNG_ERR_UNK;
+ goto end;
+ }
+ ret_code = cmd.reply_code;
+end:
+ return ret_code;
+}
+
+enum lttng_error_code notification_thread_command_remove_application(
+ struct notification_thread_handle *handle,
+ struct lttng_pipe *pipe)
+{
+ int ret;
+ enum lttng_error_code ret_code;
+ struct notification_thread_command cmd = {};
+
+ init_notification_thread_command(&cmd);
+
+ cmd.type = NOTIFICATION_COMMAND_TYPE_REMOVE_APPLICATION;
+ cmd.parameters.application.read_side_trigger_event_application_pipe = lttng_pipe_get_readfd(pipe);
+
+ ret = run_command_wait(handle, &cmd);
+ if (ret) {
+ ret_code = LTTNG_ERR_UNK;
+ goto end;
+ }
+ ret_code = cmd.reply_code;
+end:
+ return ret_code;
+}
+
+enum lttng_error_code notification_thread_command_get_tokens(
+ struct notification_thread_handle *handle,
+ struct lttng_triggers **tokens_triggers)
+{
+ int ret;
+ enum lttng_error_code ret_code;
+ struct notification_thread_command cmd = {};
+
+ assert(handle);
+ assert(tokens_triggers);
+
+ init_notification_thread_command(&cmd);
+
+ cmd.type = NOTIFICATION_COMMAND_TYPE_GET_TOKENS;
+
+ ret = run_command_wait(handle, &cmd);
+ if (ret) {
+ ret_code = LTTNG_ERR_UNK;
+ goto end;
+ }
+ ret_code = cmd.reply_code;
+ *tokens_triggers = cmd.reply.get_tokens.triggers;
+
+end:
+ return ret_code;
+}
+
+enum lttng_error_code notification_thread_command_list_triggers(
+ struct notification_thread_handle *handle,
+ uid_t uid,
+ gid_t gid,
+ struct lttng_triggers **triggers)
+{
+ int ret;
+ enum lttng_error_code ret_code;
+ struct notification_thread_command cmd = {};
+
+ assert(handle);
+ assert(triggers);
+
+ init_notification_thread_command(&cmd);
+
+ cmd.type = NOTIFICATION_COMMAND_TYPE_LIST_TRIGGERS;
+ cmd.parameters.list_triggers.uid = uid;
+ cmd.parameters.list_triggers.gid = gid;
+
+ ret = run_command_wait(handle, &cmd);
+ if (ret) {
+ ret_code = LTTNG_ERR_UNK;
+ goto end;
+ }
+ ret_code = cmd.reply_code;
+ *triggers = cmd.reply.list_triggers.triggers;
+
+end:
+ return ret_code;
+}
+
void notification_thread_command_quit(
struct notification_thread_handle *handle)
{
int ret;
- struct notification_thread_command cmd;
+ struct notification_thread_command cmd = {};
init_notification_thread_command(&cmd);
#include "notification-thread-internal.h"
#include "notification-thread-events.h"
#include <common/waiter.h>
+#include <stdbool.h>
struct notification_thread_data;
struct lttng_trigger;
NOTIFICATION_COMMAND_TYPE_REMOVE_CHANNEL,
NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING,
NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED,
+ NOTIFICATION_COMMAND_TYPE_ADD_APPLICATION,
+ NOTIFICATION_COMMAND_TYPE_REMOVE_APPLICATION,
+ NOTIFICATION_COMMAND_TYPE_GET_TOKENS,
+ NOTIFICATION_COMMAND_TYPE_LIST_TRIGGERS,
NOTIFICATION_COMMAND_TYPE_QUIT,
};
uint64_t trace_archive_chunk_id;
struct lttng_trace_archive_location *location;
} session_rotation;
+ /* Add/Remove application */
+ struct {
+ int read_side_trigger_event_application_pipe;
+ } application;
+ /* List triggers */
+ struct {
+ /* Credential */
+ uid_t uid;
+ gid_t gid;
+ } list_triggers;
+
} parameters;
+ union {
+ struct {
+ struct lttng_triggers *triggers;
+ } get_tokens;
+ struct {
+ struct lttng_triggers *triggers;
+ } list_triggers;
+ } reply;
+
/* lttng_waiter on which to wait for command reply (optional). */
struct lttng_waiter reply_waiter;
enum lttng_error_code reply_code;
+ bool is_async;
};
enum lttng_error_code notification_thread_command_register_trigger(
uint64_t trace_archive_chunk_id,
struct lttng_trace_archive_location *location);
+enum lttng_error_code notification_thread_command_add_application(
+ struct notification_thread_handle *handle,
+ struct lttng_pipe *trigger_event_application_pipe);
+
+enum lttng_error_code notification_thread_command_remove_application(
+ struct notification_thread_handle *handle,
+ struct lttng_pipe *trigger_event_application_pipe);
+
+/* Must hold the notification_trigger_tokens_ht_lock to protect against
+ * insertion removal of triggers TODO: is it the case even with refcounting? */
+/* todo find a better way....*/
+enum lttng_error_code notification_thread_command_get_tokens(
+ struct notification_thread_handle *handle,
+ struct lttng_triggers **triggers);
+
+/* TODO: for now we borrow with no refcount the trigger. THIS IS DANGEROUS */
+enum lttng_error_code notification_thread_command_list_triggers(
+ struct notification_thread_handle *handle,
+ uid_t uid,
+ gid_t gid,
+ struct lttng_triggers **triggers);
+
void notification_thread_command_quit(
struct notification_thread_handle *handle);
#include <common/macros.h>
#include <lttng/condition/condition.h>
#include <lttng/action/action-internal.h>
+#include <lttng/action/group-internal.h>
#include <lttng/notification/notification-internal.h>
#include <lttng/condition/condition-internal.h>
#include <lttng/condition/buffer-usage-internal.h>
#include <lttng/condition/session-consumed-size-internal.h>
#include <lttng/condition/session-rotation-internal.h>
+#include <lttng/condition/event-rule-internal.h>
#include <lttng/notification/channel-internal.h>
+#include <lttng/trigger/trigger-internal.h>
#include <time.h>
#include <unistd.h>
struct lttng_trigger_list_element {
/* No ownership of the trigger object is assumed. */
- const struct lttng_trigger *trigger;
+ struct lttng_trigger *trigger;
struct cds_list_head node;
};
struct lttng_trigger_ht_element {
struct lttng_trigger *trigger;
struct cds_lfht_node node;
+ struct cds_lfht_node node_by_name;
/* call_rcu delayed reclaim. */
struct rcu_head rcu_node;
};
struct cds_list_head node;
};
-struct notification_client_list_element {
- struct notification_client *client;
- struct cds_list_head node;
-};
-
-struct notification_client_list {
- const struct lttng_trigger *trigger;
- struct cds_list_head list;
- struct cds_lfht_node notification_trigger_ht_node;
- /* call_rcu delayed reclaim. */
- struct rcu_head rcu_node;
-};
-
-struct notification_client {
- int socket;
- /* Client protocol version. */
- uint8_t major, minor;
- uid_t uid;
- gid_t gid;
- /*
- * Indicates if the credentials and versions of the client have been
- * checked.
- */
- bool v