DEFAULT_INCLUDES="-I\$(top_srcdir) -I\$(top_builddir) -I\$(top_builddir)/src -I\$(top_builddir)/include -include config.h"
lttngincludedir="${includedir}/lttng"
-
AC_SUBST(lttngincludedir)
+
+lttngactionincludedir="${includedir}/lttng/action"
+AC_SUBST(lttngactionincludedir)
+
+lttngconditionincludedir="${includedir}/lttng/condition"
+AC_SUBST(lttngconditionincludedir)
+
+lttngnotificationincludedir="${includedir}/lttng/notification"
+AC_SUBST(lttngnotificationincludedir)
+
+lttngtriggerincludedir="${includedir}/lttng/trigger"
+AC_SUBST(lttngtriggerincludedir)
+
AC_SUBST(DEFAULT_INCLUDES)
lttnglibexecdir="${libdir}/lttng/libexec"
lttng/snapshot.h \
lttng/save.h \
lttng/load.h \
+ lttng/endpoint.h \
version.h.tmpl
+lttngactioninclude_HEADERS= \
+ lttng/action/action.h \
+ lttng/action/notify.h
+
+lttngconditioninclude_HEADERS= \
+ lttng/condition/condition.h \
+ lttng/condition/buffer-usage.h \
+ lttng/condition/evaluation.h
+
+lttngnotificationinclude_HEADERS= \
+ lttng/notification/channel.h \
+ lttng/notification/notification.h
+
+lttngtriggerinclude_HEADERS= \
+ lttng/trigger/trigger.h
+
noinst_HEADERS = \
lttng/snapshot-internal.h \
lttng/health-internal.h \
lttng/save-internal.h \
- lttng/load-internal.h
+ lttng/load-internal.h \
+ lttng/action/action-internal.h \
+ lttng/action/notify-internal.h \
+ lttng/condition/condition-internal.h \
+ lttng/condition/buffer-usage-internal.h \
+ lttng/condition/evaluation-internal.h \
+ lttng/notification/notification-internal.h \
+ lttng/trigger/trigger-internal.h \
+ lttng/endpoint-internal.h \
+ lttng/notification/channel-internal.h
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_ACTION_INTERNAL_H
+#define LTTNG_ACTION_INTERNAL_H
+
+#include <lttng/action/action.h>
+#include <common/macros.h>
+#include <common/buffer-view.h>
+#include <stdbool.h>
+
+typedef bool (*action_validate_cb)(struct lttng_action *action);
+typedef void (*action_destroy_cb)(struct lttng_action *action);
+typedef ssize_t (*action_serialize_cb)(struct lttng_action *action, char *buf);
+
+struct lttng_action {
+ enum lttng_action_type type;
+ action_validate_cb validate;
+ action_serialize_cb serialize;
+ action_destroy_cb destroy;
+};
+
+struct lttng_action_comm {
+ /* enum lttng_action_type */
+ int8_t action_type;
+} LTTNG_PACKED;
+
+LTTNG_HIDDEN
+bool lttng_action_validate(struct lttng_action *action);
+
+LTTNG_HIDDEN
+ssize_t lttng_action_serialize(struct lttng_action *action, char *buf);
+
+LTTNG_HIDDEN
+ssize_t lttng_action_create_from_buffer(const struct lttng_buffer_view *view,
+ struct lttng_action **action);
+
+#endif /* LTTNG_ACTION_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_ACTION_H
+#define LTTNG_ACTION_H
+
+struct lttng_action;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum lttng_action_type {
+ LTTNG_ACTION_TYPE_UNKNOWN = -1,
+ LTTNG_ACTION_TYPE_NOTIFY = 0,
+};
+
+extern enum lttng_action_type lttng_action_get_type(
+ struct lttng_action *action);
+
+extern void lttng_action_destroy(struct lttng_action *action);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_ACTION_H */
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_ACTION_NOTIFY_INTERNAL_H
+#define LTTNG_ACTION_NOTIFY_INTERNAL_H
+
+#include <lttng/action/notify.h>
+#include <lttng/action/action-internal.h>
+
+struct lttng_action_notify {
+ struct lttng_action parent;
+};
+
+#endif /* LTTNG_ACTION_NOTIFY_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_ACTION_NOTIFY_H
+#define LTTNG_ACTION_NOTIFY_H
+
+struct lttng_action;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct lttng_action *lttng_action_notify_create(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_ACTION_NOTIFY_H */
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_CONDITION_BUFFER_USAGE_INTERNAL_H
+#define LTTNG_CONDITION_BUFFER_USAGE_INTERNAL_H
+
+#include <lttng/condition/buffer-usage.h>
+#include <lttng/condition/condition-internal.h>
+#include <lttng/condition/evaluation-internal.h>
+#include <lttng/domain.h>
+#include "common/buffer-view.h"
+
+struct lttng_condition_buffer_usage {
+ struct lttng_condition parent;
+ struct {
+ bool set;
+ uint64_t value;
+ } threshold_bytes;
+ struct {
+ bool set;
+ double value;
+ } threshold_ratio;
+ char *session_name;
+ char *channel_name;
+ struct {
+ bool set;
+ enum lttng_domain_type type;
+ } domain;
+};
+
+struct lttng_condition_buffer_usage_comm {
+ uint8_t threshold_set_in_bytes;
+ /*
+ * Expressed in bytes if "threshold_set_in_bytes" is not 0.
+ * Otherwise, it is expressed a ratio in the interval [0.0, 1.0]
+ * that is mapped to the range on a 32-bit unsigned integer.
+ * The ratio is obtained by (threshold / UINT32_MAX).
+ */
+ uint32_t threshold;
+ /* Both lengths include the trailing \0. */
+ uint32_t session_name_len;
+ uint32_t channel_name_len;
+ /* enum lttng_domain_type */
+ int8_t domain_type;
+ /* session and channel names. */
+ char names[];
+} LTTNG_PACKED;
+
+struct lttng_evaluation_buffer_usage {
+ struct lttng_evaluation parent;
+ uint64_t buffer_use;
+ uint64_t buffer_capacity;
+};
+
+struct lttng_evaluation_buffer_usage_comm {
+ uint64_t buffer_use;
+ uint64_t buffer_capacity;
+} LTTNG_PACKED;
+
+LTTNG_HIDDEN
+struct lttng_evaluation *lttng_evaluation_buffer_usage_create(
+ enum lttng_condition_type type, uint64_t use,
+ uint64_t capacity);
+
+LTTNG_HIDDEN
+ssize_t lttng_condition_buffer_usage_low_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_condition **condition);
+
+LTTNG_HIDDEN
+ssize_t lttng_condition_buffer_usage_high_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_condition **condition);
+
+LTTNG_HIDDEN
+ssize_t lttng_evaluation_buffer_usage_low_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_evaluation **evaluation);
+
+LTTNG_HIDDEN
+ssize_t lttng_evaluation_buffer_usage_high_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_evaluation **evaluation);
+
+#endif /* LTTNG_CONDITION_BUFFER_USAGE_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_CONDITION_BUFFER_USAGE_H
+#define LTTNG_CONDITION_BUFFER_USAGE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct lttng_condition;
+struct lttng_evaluation;
+
+extern struct lttng_condition *
+lttng_condition_buffer_usage_low_create(void);
+
+extern struct lttng_condition *
+lttng_condition_buffer_usage_high_create(void);
+
+/* threshold_ratio expressed as [0.0, 1.0]. */
+extern enum lttng_condition_status
+lttng_condition_buffer_usage_get_threshold_ratio(
+ const struct lttng_condition *condition,
+ double *threshold_ratio);
+
+/* threshold_ratio expressed as [0.0, 1.0]. */
+extern enum lttng_condition_status
+lttng_condition_buffer_usage_set_threshold_ratio(
+ struct lttng_condition *condition,
+ double threshold_ratio);
+
+extern enum lttng_condition_status
+lttng_condition_buffer_usage_get_threshold(
+ const struct lttng_condition *condition,
+ uint64_t *threshold_bytes);
+
+extern enum lttng_condition_status
+lttng_condition_buffer_usage_set_threshold(
+ struct lttng_condition *condition,
+ uint64_t threshold_bytes);
+
+extern enum lttng_condition_status
+lttng_condition_buffer_usage_get_session_name(
+ const struct lttng_condition *condition,
+ const char **session_name);
+
+extern enum lttng_condition_status
+lttng_condition_buffer_usage_set_session_name(
+ struct lttng_condition *condition,
+ const char *session_name);
+
+extern enum lttng_condition_status
+lttng_condition_buffer_usage_get_channel_name(
+ const struct lttng_condition *condition,
+ const char **channel_name);
+
+extern enum lttng_condition_status
+lttng_condition_buffer_usage_set_channel_name(
+ struct lttng_condition *condition,
+ const char *channel_name);
+
+extern enum lttng_condition_status
+lttng_condition_buffer_usage_get_domain_type(
+ const struct lttng_condition *condition,
+ enum lttng_domain_type *type);
+
+extern enum lttng_condition_status
+lttng_condition_buffer_usage_set_domain_type(
+ struct lttng_condition *condition,
+ enum lttng_domain_type type);
+
+
+/* LTTng Condition Evaluation */
+extern enum lttng_evaluation_status
+lttng_evaluation_buffer_usage_get_usage_ratio(
+ const struct lttng_evaluation *evaluation,
+ double *usage_ratio);
+
+extern enum lttng_evaluation_status
+lttng_evaluation_buffer_usage_get_usage(
+ const struct lttng_evaluation *evaluation,
+ uint64_t *usage_bytes);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_CONDITION_BUFFER_USAGE_H */
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_CONDITION_INTERNAL_H
+#define LTTNG_CONDITION_INTERNAL_H
+
+#include <lttng/condition/condition.h>
+#include <common/macros.h>
+#include <common/buffer-view.h>
+#include <stdbool.h>
+#include <urcu/list.h>
+#include <stdint.h>
+
+typedef void (*condition_destroy_cb)(struct lttng_condition *condition);
+typedef bool (*condition_validate_cb)(const struct lttng_condition *condition);
+typedef ssize_t (*condition_serialize_cb)(
+ const struct lttng_condition *condition, char *buf);
+typedef bool (*condition_equal_cb)(const struct lttng_condition *a,
+ const struct lttng_condition *b);
+typedef ssize_t (*condition_create_from_buffer_cb)(
+ const struct lttng_buffer_view *view,
+ struct lttng_condition **condition);
+
+struct lttng_condition {
+ enum lttng_condition_type type;
+ condition_validate_cb validate;
+ condition_serialize_cb serialize;
+ condition_equal_cb equal;
+ condition_destroy_cb destroy;
+};
+
+struct lttng_condition_comm {
+ /* enum lttng_condition_type */
+ int8_t condition_type;
+ char payload[];
+};
+
+LTTNG_HIDDEN
+void lttng_condition_init(struct lttng_condition *condition,
+ enum lttng_condition_type type);
+
+LTTNG_HIDDEN
+bool lttng_condition_validate(const struct lttng_condition *condition);
+
+LTTNG_HIDDEN
+ssize_t lttng_condition_create_from_buffer(
+ const struct lttng_buffer_view *buffer,
+ struct lttng_condition **condition);
+
+LTTNG_HIDDEN
+ssize_t lttng_condition_serialize(const struct lttng_condition *condition,
+ char *buf);
+
+LTTNG_HIDDEN
+bool lttng_condition_is_equal(const struct lttng_condition *a,
+ const struct lttng_condition *b);
+
+#endif /* LTTNG_CONDITION_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_CONDITION_H
+#define LTTNG_CONDITION_H
+
+#include <lttng/lttng.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct lttng_condition;
+
+enum lttng_condition_type {
+ LTTNG_CONDITION_TYPE_UNKNOWN = -1,
+ LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW = 102,
+ LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH = 101,
+};
+
+enum lttng_condition_status {
+ LTTNG_CONDITION_STATUS_OK = 0,
+ LTTNG_CONDITION_STATUS_ERROR = -1,
+ LTTNG_CONDITION_STATUS_UNKNOWN = -2,
+ LTTNG_CONDITION_STATUS_INVALID = -3,
+ LTTNG_CONDITION_STATUS_UNSET = -4,
+};
+
+extern enum lttng_condition_type lttng_condition_get_type(
+ const struct lttng_condition *condition);
+
+extern void lttng_condition_destroy(struct lttng_condition *condition);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_CONDITION_H */
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_EVALUATION_INTERNAL_H
+#define LTTNG_EVALUATION_INTERNAL_H
+
+#include <lttng/condition/evaluation.h>
+#include <common/macros.h>
+#include <common/buffer-view.h>
+#include <stdbool.h>
+
+typedef void (*evaluation_destroy_cb)(struct lttng_evaluation *evaluation);
+typedef ssize_t (*evaluation_serialize_cb)(struct lttng_evaluation *evaluation,
+ char *buf);
+
+struct lttng_evaluation_comm {
+ /* enum lttng_condition_type type */
+ int8_t type;
+ char payload[];
+} LTTNG_PACKED;
+
+struct lttng_evaluation {
+ enum lttng_condition_type type;
+ evaluation_serialize_cb serialize;
+ evaluation_destroy_cb destroy;
+};
+
+LTTNG_HIDDEN
+ssize_t lttng_evaluation_create_from_buffer(const struct lttng_buffer_view *view,
+ struct lttng_evaluation **evaluation);
+
+LTTNG_HIDDEN
+ssize_t lttng_evaluation_serialize(struct lttng_evaluation *evaluation,
+ char *buf);
+
+#endif /* LTTNG_EVALUATION_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_EVALUATION_H
+#define LTTNG_EVALUATION_H
+
+#include <lttng/condition/condition.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct lttng_evaluation;
+
+enum lttng_evaluation_status {
+ LTTNG_EVALUATION_STATUS_OK = 0,
+ LTTNG_EVALUATION_STATUS_ERROR = -1,
+ LTTNG_EVALUATION_STATUS_INVALID = -2,
+ LTTNG_EVALUATION_STATUS_UNKNOWN = -2,
+ LTTNG_EVALUATION_STATUS_UNSET = -3,
+};
+
+extern enum lttng_condition_type lttng_evaluation_get_type(
+ const struct lttng_evaluation *evaluation);
+
+extern void lttng_evaluation_destroy(struct lttng_evaluation *evaluation);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_EVALUATION_H */
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_ENDPOINT_INTERNAL_H
+#define LTTNG_ENDPOINT_INTERNAL_H
+
+#include <lttng/endpoint.h>
+#include <common/macros.h>
+
+enum lttng_endpoint_type {
+ LTTNG_ENDPOINT_TYPE_DEFAULT_SESSIOND_NOTIFICATION = 0,
+};
+
+struct lttng_endpoint {
+ enum lttng_endpoint_type type;
+};
+
+#endif /* LTTNG_ENDPOINT_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_ENDPOINT_H
+#define LTTNG_ENDPOINT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Default LTTng session daemon endpoint singleton. */
+extern struct lttng_endpoint *lttng_session_daemon_notification_endpoint;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_ENDPOINT_H */
LTTNG_ERR_REGEN_STATEDUMP_FAIL = 122, /* Failed to regenerate the state dump */
LTTNG_ERR_REGEN_STATEDUMP_NOMEM = 123, /* Failed to regenerate the state dump, not enough memory */
LTTNG_ERR_NOT_SNAPSHOT_SESSION = 124, /* Session is not in snapshot mode. */
+ LTTNG_ERR_INVALID_TRIGGER = 125, /* Invalid trigger provided. */
+ LTTNG_ERR_TRIGGER_EXISTS = 126, /* Trigger already registered. */
+ LTTNG_ERR_TRIGGER_NOT_FOUND = 127, /* Trigger not found. */
+ LTTNG_ERR_COMMAND_CANCELLED = 128, /* Command cancelled. */
/* MUST be last element */
LTTNG_ERR_NR, /* Last element */
#include <lttng/save.h>
#include <lttng/session.h>
#include <lttng/snapshot.h>
+#include <lttng/endpoint.h>
+#include <lttng/action/action.h>
+#include <lttng/action/notify.h>
+#include <lttng/condition/condition.h>
+#include <lttng/condition/buffer-usage.h>
+#include <lttng/condition/evaluation.h>
+#include <lttng/notification/channel.h>
+#include <lttng/notification/notification.h>
+#include <lttng/trigger/trigger.h>
#ifdef __cplusplus
extern "C" {
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_NOTIFICATION_CHANNEL_INTERNAL_H
+#define LTTNG_NOTIFICATION_CHANNEL_INTERNAL_H
+
+#include <lttng/notification/channel.h>
+#include <common/macros.h>
+#include <common/dynamic-buffer.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <pthread.h>
+#include <urcu/list.h>
+
+#define LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR 1
+#define LTTNG_NOTIFICATION_CHANNEL_VERSION_MINOR 0
+
+enum lttng_notification_channel_message_type {
+ LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNKNOWN = -1,
+ LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE = 0,
+ LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE = 1,
+ LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE = 2,
+ LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_COMMAND_REPLY = 3,
+ LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION = 4,
+ LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED = 5,
+};
+
+struct lttng_notification_channel_message {
+ /* enum lttng_notification_channel_message_type */
+ int8_t type;
+ /* Size of the payload following this field. */
+ uint32_t size;
+ char payload[];
+} LTTNG_PACKED;
+
+struct lttng_notification_channel_command_handshake {
+ uint8_t major;
+ uint8_t minor;
+} LTTNG_PACKED;
+
+struct lttng_notification_channel_command_reply {
+ /* enum lttng_notification_channel_status */
+ int8_t status;
+} LTTNG_PACKED;
+
+struct pending_notification {
+ /* NULL means "notification dropped". */
+ struct lttng_notification *notification;
+ struct cds_list_head node;
+};
+
+/*
+ * The notification channel protocol is bidirectional and accomodates
+ * synchronous and asynchronous communication modes:
+ *
+ * - Synchronous: commands emitted by the client to which a reply is expected
+ * (e.g. subscribing/unsubscribing to conditions),
+ * - Asynchronous: notifications which are sent by the lttng_endpoint to the
+ * client as one of the subscribed condition has occured.
+ *
+ * The nature of this hybrid communication mode means that asynchronous messages
+ * (e.g. notifications) may be interleaved between synchronous messages (e.g. a
+ * command and its reply).
+ *
+ * Notifications that are received between a command and its reply and enqueued
+ * in the pending_notifications list.
+ */
+struct lttng_notification_channel {
+ pthread_mutex_t lock;
+ int socket;
+ struct {
+ /* Count of pending notifications. */
+ unsigned int count;
+ /* List of struct pending_notification. */
+ struct cds_list_head list;
+ } pending_notifications;
+ struct lttng_dynamic_buffer reception_buffer;
+ /* Sessiond notification protocol version. */
+ struct {
+ bool set;
+ int8_t major, minor;
+ } version;
+};
+
+#endif /* LTTNG_NOTIFICATION_CHANNEL_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_NOTIFICATION_CHANNEL_H
+#define LTTNG_NOTIFICATION_CHANNEL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct lttng_endpoint;
+struct lttng_condition;
+struct lttng_notification;
+struct lttng_notification_channel;
+
+/* LTTng Notification channel */
+enum lttng_notification_channel_status {
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED = 1,
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_OK = 0,
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR = -1,
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED = -2,
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED = -3,
+ /* Condition unknown. */
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_UNKNOWN_CONDITION = -4,
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID = -5,
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_UNSUPPORTED_VERSION = -6,
+};
+
+extern struct lttng_notification_channel *lttng_notification_channel_create(
+ struct lttng_endpoint *endpoint);
+
+extern enum lttng_notification_channel_status
+lttng_notification_channel_get_next_notification(
+ struct lttng_notification_channel *channel,
+ struct lttng_notification **notification);
+
+extern enum lttng_notification_channel_status
+lttng_notification_channel_subscribe(
+ struct lttng_notification_channel *channel,
+ const struct lttng_condition *condition);
+
+extern enum lttng_notification_channel_status
+lttng_notification_channel_unsubscribe(
+ struct lttng_notification_channel *channel,
+ const struct lttng_condition *condition);
+
+extern void lttng_notification_channel_destroy(
+ struct lttng_notification_channel *channel);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_NOTIFICATION_CHANNEL_H */
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_NOTIFICATION_INTERNAL_H
+#define LTTNG_NOTIFICATION_INTERNAL_H
+
+#include <lttng/notification/notification.h>
+#include <common/macros.h>
+#include <common/buffer-view.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+struct lttng_notification {
+ struct lttng_condition *condition;
+ struct lttng_evaluation *evaluation;
+ /*
+ * The ownership of the notification's inner-elements depends
+ * on the way it was created. The notification owns both
+ * the condition and evaluation if it was obtained from a notification
+ * channel (i.e. created using lttng_notification_create_from_buffer)
+ * as the user may never access the condition and evaluation,
+ * thus never getting a chance to free them.
+ *
+ * However, when the _private_ lttng_notification_create() function
+ * is used, no ownership of condition and evaluation is assumed by
+ * the notification object. The main reason for this change in
+ * behavior is that internal users of this API only use the object
+ * to use its serialization facilities.
+ */
+ bool owns_elements;
+};
+
+struct lttng_notification_comm {
+ /* Size of the payload following this field. */
+ uint32_t length;
+ /* Condition and evaluation objects follow. */
+ char payload[];
+} LTTNG_PACKED;
+
+LTTNG_HIDDEN
+struct lttng_notification *lttng_notification_create(
+ struct lttng_condition *condition,
+ struct lttng_evaluation *evaluation);
+
+LTTNG_HIDDEN
+ssize_t lttng_notification_serialize(struct lttng_notification *notification,
+ char *buf);
+
+LTTNG_HIDDEN
+ssize_t lttng_notification_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_notification **notification);
+
+#endif /* LTTNG_NOTIFICATION_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_NOTIFICATION_H
+#define LTTNG_NOTIFICATION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct lttng_condition;
+struct lttng_evaluation;
+struct lttng_notification;
+
+/*
+ * The notification retains ownership of both the condition and evaluation.
+ * Destroying the notification will also destroy the notification and evaluation
+ * objects.
+ */
+extern const struct lttng_condition *lttng_notification_get_condition(
+ struct lttng_notification *notification);
+
+extern const struct lttng_evaluation *lttng_notification_get_evaluation(
+ struct lttng_notification *notification);
+
+extern void lttng_notification_destroy(struct lttng_notification *notification);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_NOTIFICATION_H */
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_TRIGGER_INTERNAL_H
+#define LTTNG_TRIGGER_INTERNAL_H
+
+#include <lttng/trigger/trigger.h>
+#include <common/macros.h>
+#include <common/buffer-view.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+struct lttng_trigger {
+ struct lttng_condition *condition;
+ struct lttng_action *action;
+};
+
+struct lttng_trigger_comm {
+ /* length excludes its own length. */
+ uint32_t length;
+ /* A condition and action object follow. */
+ char payload[];
+} LTTNG_PACKED;
+
+LTTNG_HIDDEN
+ssize_t lttng_trigger_create_from_buffer(const struct lttng_buffer_view *view,
+ struct lttng_trigger **trigger);
+
+LTTNG_HIDDEN
+ssize_t lttng_trigger_serialize(struct lttng_trigger *trigger, char *buf);
+
+LTTNG_HIDDEN
+bool lttng_trigger_validate(struct lttng_trigger *trigger);
+
+#endif /* LTTNG_TRIGGER_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LTTNG_TRIGGER_H
+#define LTTNG_TRIGGER_H
+
+struct lttng_action;
+struct lttng_condition;
+struct lttng_trigger;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum lttng_register_trigger_status {
+ LTTNG_REGISTER_TRIGGER_STATUS_OK = 0,
+ LTTNG_REGISTER_TRIGGER_STATUS_INVALID = -1,
+};
+
+/* The caller retains the ownership of both condition and action. */
+extern struct lttng_trigger *lttng_trigger_create(
+ struct lttng_condition *condition, struct lttng_action *action);
+
+extern struct lttng_condition *lttng_trigger_get_condition(
+ struct lttng_trigger *trigger);
+
+extern struct lttng_action *lttng_trigger_get_action(
+ struct lttng_trigger *trigger);
+
+extern void lttng_trigger_destroy(struct lttng_trigger *trigger);
+
+extern int lttng_register_trigger(struct lttng_trigger *trigger);
+
+extern int lttng_unregister_trigger(struct lttng_trigger *trigger);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_TRIGGER_H */
mi-lttng.h mi-lttng.c \
daemonize.c daemonize.h \
unix.c unix.h \
+ filter.c filter.h context.c context.h \
+ action.c notify.c condition.c buffer-usage.c \
+ evaluation.c notification.c trigger.c endpoint.c \
dynamic-buffer.h dynamic-buffer.c \
buffer-view.h buffer-view.c
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <lttng/action/action-internal.h>
+#include <lttng/action/notify-internal.h>
+#include <common/error.h>
+#include <assert.h>
+
+enum lttng_action_type lttng_action_get_type(struct lttng_action *action)
+{
+ return action ? action->type : LTTNG_ACTION_TYPE_UNKNOWN;
+}
+
+void lttng_action_destroy(struct lttng_action *action)
+{
+ if (!action) {
+ return;
+ }
+
+ assert(action->destroy);
+ action->destroy(action);
+}
+
+LTTNG_HIDDEN
+bool lttng_action_validate(struct lttng_action *action)
+{
+ bool valid;
+
+ if (!action) {
+ valid = false;
+ goto end;
+ }
+
+ if (!action->validate) {
+ /* Sub-class guarantees that it can never be invalid. */
+ valid = true;
+ goto end;
+ }
+
+ valid = action->validate(action);
+end:
+ return valid;
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_action_serialize(struct lttng_action *action, char *buf)
+{
+ ssize_t ret, action_size;
+ struct lttng_action_comm action_comm;
+
+ if (!action) {
+ ret = -1;
+ goto end;
+ }
+
+ action_comm.action_type = (int8_t) action->type;
+ ret = sizeof(struct lttng_action_comm);
+ if (buf) {
+ memcpy(buf, &action_comm, ret);
+ buf += ret;
+ }
+
+ action_size = action->serialize(action, buf);
+ if (action_size < 0) {
+ ret = action_size;
+ goto end;
+ }
+ ret += action_size;
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_action_create_from_buffer(const struct lttng_buffer_view *view,
+ struct lttng_action **_action)
+{
+ ssize_t ret, action_size = sizeof(struct lttng_action_comm);
+ struct lttng_action *action;
+ const struct lttng_action_comm *action_comm;
+
+ if (!view || !_action) {
+ ret = -1;
+ goto end;
+ }
+
+ action_comm = (const struct lttng_action_comm *) view->data;
+ DBG("Deserializing action from buffer");
+ switch (action_comm->action_type) {
+ case LTTNG_ACTION_TYPE_NOTIFY:
+ action = lttng_action_notify_create();
+ break;
+ default:
+ ret = -1;
+ goto end;
+ }
+
+ if (!action) {
+ ret = -1;
+ goto end;
+ }
+ ret = action_size;
+ *_action = action;
+end:
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <lttng/condition/condition-internal.h>
+#include <lttng/condition/buffer-usage-internal.h>
+#include <common/macros.h>
+#include <common/error.h>
+#include <assert.h>
+#include <math.h>
+#include <float.h>
+#include <time.h>
+
+#define IS_USAGE_CONDITION(condition) ( \
+ lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW || \
+ lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH \
+ )
+
+static
+double fixed_to_double(uint32_t val)
+{
+ return (double) val / (double) UINT32_MAX;
+}
+
+static
+uint64_t double_to_fixed(double val)
+{
+ return (val * (double) UINT32_MAX);
+}
+
+static
+bool is_usage_evaluation(const struct lttng_evaluation *evaluation)
+{
+ enum lttng_condition_type type = lttng_evaluation_get_type(evaluation);
+
+ return type == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW ||
+ type == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH;
+}
+
+static
+void lttng_condition_buffer_usage_destroy(struct lttng_condition *condition)
+{
+ struct lttng_condition_buffer_usage *usage;
+
+ usage = container_of(condition, struct lttng_condition_buffer_usage,
+ parent);
+
+ free(usage->session_name);
+ free(usage->channel_name);
+ free(usage);
+}
+
+static
+bool lttng_condition_buffer_usage_validate(
+ const struct lttng_condition *condition)
+{
+ bool valid = false;
+ struct lttng_condition_buffer_usage *usage;
+
+ if (!condition) {
+ goto end;
+ }
+
+ usage = container_of(condition, struct lttng_condition_buffer_usage,
+ parent);
+ if (!usage->session_name) {
+ ERR("Invalid buffer condition: a target session name must be set.");
+ goto end;
+ }
+ if (!usage->channel_name) {
+ ERR("Invalid buffer condition: a target channel name must be set.");
+ goto end;
+ }
+ if (!usage->threshold_ratio.set && !usage->threshold_bytes.set) {
+ ERR("Invalid buffer condition: a threshold must be set.");
+ goto end;
+ }
+
+ valid = true;
+end:
+ return valid;
+}
+
+static
+ssize_t lttng_condition_buffer_usage_serialize(
+ const struct lttng_condition *condition, char *buf)
+{
+ struct lttng_condition_buffer_usage *usage;
+ ssize_t ret, size;
+ size_t session_name_len, channel_name_len;
+
+ if (!condition || !IS_USAGE_CONDITION(condition)) {
+ ret = -1;
+ goto end;
+ }
+
+ DBG("Serializing buffer usage condition");
+ usage = container_of(condition, struct lttng_condition_buffer_usage,
+ parent);
+ size = sizeof(struct lttng_condition_buffer_usage_comm);
+ session_name_len = strlen(usage->session_name) + 1;
+ channel_name_len = strlen(usage->channel_name) + 1;
+ if (session_name_len > LTTNG_NAME_MAX ||
+ channel_name_len > LTTNG_NAME_MAX) {
+ ret = -1;
+ goto end;
+ }
+ size += session_name_len + channel_name_len;
+ if (buf) {
+ struct lttng_condition_buffer_usage_comm usage_comm = {
+ .threshold_set_in_bytes = usage->threshold_bytes.set ? 1 : 0,
+ .session_name_len = session_name_len,
+ .channel_name_len = channel_name_len,
+ .domain_type = (int8_t) usage->domain.type,
+ };
+
+ if (usage->threshold_bytes.set) {
+ usage_comm.threshold = usage->threshold_bytes.value;
+ } else {
+ uint64_t val = double_to_fixed(
+ usage->threshold_ratio.value);
+
+ if (val > UINT32_MAX) {
+ /* overflow. */
+ ret = -1;
+ goto end;
+ }
+ usage_comm.threshold = val;
+ }
+
+ memcpy(buf, &usage_comm, sizeof(usage_comm));
+ buf += sizeof(usage_comm);
+ memcpy(buf, usage->session_name, session_name_len);
+ buf += session_name_len;
+ memcpy(buf, usage->channel_name, channel_name_len);
+ buf += channel_name_len;
+ }
+ ret = size;
+end:
+ return ret;
+}
+
+static
+bool lttng_condition_buffer_usage_is_equal(const struct lttng_condition *_a,
+ const struct lttng_condition *_b)
+{
+ bool is_equal = false;
+ struct lttng_condition_buffer_usage *a, *b;
+
+ a = container_of(_a, struct lttng_condition_buffer_usage, parent);
+ b = container_of(_b, struct lttng_condition_buffer_usage, parent);
+
+ if ((a->threshold_ratio.set && !b->threshold_ratio.set) ||
+ (a->threshold_bytes.set && !b->threshold_bytes.set)) {
+ goto end;
+ }
+
+ if (a->threshold_ratio.set && b->threshold_ratio.set) {
+ double a_value, b_value, diff;
+
+ a_value = a->threshold_ratio.value;
+ b_value = b->threshold_ratio.value;
+ diff = fabs(a_value - b_value);
+
+ if (diff > DBL_EPSILON) {
+ goto end;
+ }
+ } else if (a->threshold_bytes.set && b->threshold_bytes.set) {
+ uint64_t a_value, b_value;
+
+ a_value = a->threshold_bytes.value;
+ b_value = b->threshold_bytes.value;
+ if (a_value != b_value) {
+ goto end;
+ }
+ }
+
+ if ((a->session_name && !b->session_name) ||
+ (!a->session_name && b->session_name)) {
+ goto end;
+ }
+
+ if (a->channel_name && b->channel_name) {
+ if (strcmp(a->channel_name, b->channel_name)) {
+ goto end;
+ }
+ } if ((a->channel_name && !b->channel_name) ||
+ (!a->channel_name && b->channel_name)) {
+ goto end;
+ }
+
+ if (a->channel_name && b->channel_name) {
+ if (strcmp(a->channel_name, b->channel_name)) {
+ goto end;
+ }
+ }
+
+ if ((a->domain.set && !b->domain.set) ||
+ (!a->domain.set && b->domain.set)) {
+ goto end;
+ }
+
+ if (a->domain.set && b->domain.set) {
+ if (a->domain.type != b->domain.type) {
+ goto end;
+ }
+ }
+ is_equal = true;
+end:
+ return is_equal;
+}
+
+static
+struct lttng_condition *lttng_condition_buffer_usage_create(
+ enum lttng_condition_type type)
+{
+ struct lttng_condition_buffer_usage *condition;
+
+ condition = zmalloc(sizeof(struct lttng_condition_buffer_usage));
+ if (!condition) {
+ goto end;
+ }
+
+ lttng_condition_init(&condition->parent, type);
+ condition->parent.validate = lttng_condition_buffer_usage_validate;
+ condition->parent.serialize = lttng_condition_buffer_usage_serialize;
+ condition->parent.equal = lttng_condition_buffer_usage_is_equal;
+ condition->parent.destroy = lttng_condition_buffer_usage_destroy;
+end:
+ return &condition->parent;
+}
+
+struct lttng_condition *lttng_condition_buffer_usage_low_create(void)
+{
+ return lttng_condition_buffer_usage_create(
+ LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW);
+}
+
+struct lttng_condition *lttng_condition_buffer_usage_high_create(void)
+{
+ return lttng_condition_buffer_usage_create(
+ LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH);
+}
+
+static
+ssize_t init_condition_from_buffer(struct lttng_condition *condition,
+ const struct lttng_buffer_view *src_view)
+{
+ ssize_t ret, condition_size;
+ enum lttng_condition_status status;
+ enum lttng_domain_type domain_type;
+ const struct lttng_condition_buffer_usage_comm *condition_comm;
+ const char *session_name, *channel_name;
+ struct lttng_buffer_view names_view;
+
+ if (src_view->size < sizeof(*condition_comm)) {
+ ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
+ ret = -1;
+ goto end;
+ }
+
+ condition_comm = (const struct lttng_condition_buffer_usage_comm *) src_view->data;
+ names_view = lttng_buffer_view_from_view(src_view,
+ sizeof(*condition_comm), -1);
+
+ if (condition_comm->session_name_len > LTTNG_NAME_MAX ||
+ condition_comm->channel_name_len > LTTNG_NAME_MAX) {
+ ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
+ ret = -1;
+ goto end;
+ }
+
+ if (names_view.size <
+ (condition_comm->session_name_len +
+ condition_comm->channel_name_len)) {
+ ERR("Failed to initialize from malformed condition buffer: buffer too short to contain element names");
+ ret = -1;
+ goto end;
+ }
+
+ if (condition_comm->threshold_set_in_bytes) {
+ status = lttng_condition_buffer_usage_set_threshold(condition,
+ condition_comm->threshold);
+ } else {
+ status = lttng_condition_buffer_usage_set_threshold_ratio(
+ condition,
+ fixed_to_double(condition_comm->threshold));
+ }
+ if (status != LTTNG_CONDITION_STATUS_OK) {
+ ERR("Failed to initialize buffer usage condition threshold");
+ ret = -1;
+ goto end;
+ }
+
+ if (condition_comm->domain_type <= LTTNG_DOMAIN_NONE ||
+ condition_comm->domain_type > LTTNG_DOMAIN_PYTHON) {
+ /* Invalid domain value. */
+ ERR("Invalid domain type value (%i) found in condition buffer",
+ (int) condition_comm->domain_type);
+ ret = -1;
+ goto end;
+ }
+
+ domain_type = (enum lttng_domain_type) condition_comm->domain_type;
+ status = lttng_condition_buffer_usage_set_domain_type(condition,
+ domain_type);
+ if (status != LTTNG_CONDITION_STATUS_OK) {
+ ERR("Failed to set buffer usage condition domain");
+ ret = -1;
+ goto end;
+ }
+
+ session_name = names_view.data;
+ if (*(session_name + condition_comm->session_name_len - 1) != '\0') {
+ ERR("Malformed session name encountered in condition buffer");
+ ret = -1;
+ goto end;
+ }
+
+ channel_name = session_name + condition_comm->session_name_len;
+ if (*(channel_name + condition_comm->channel_name_len - 1) != '\0') {
+ ERR("Malformed channel name encountered in condition buffer");
+ ret = -1;
+ goto end;
+ }
+
+ status = lttng_condition_buffer_usage_set_session_name(condition,
+ session_name);
+ if (status != LTTNG_CONDITION_STATUS_OK) {
+ ERR("Failed to set buffer usage session name");
+ ret = -1;
+ goto end;
+ }
+
+ status = lttng_condition_buffer_usage_set_channel_name(condition,
+ channel_name);
+ if (status != LTTNG_CONDITION_STATUS_OK) {
+ ERR("Failed to set buffer usage channel name");
+ ret = -1;
+ goto end;
+ }
+
+ if (!lttng_condition_validate(condition)) {
+ ret = -1;
+ goto end;
+ }
+
+ condition_size = sizeof(*condition_comm) +
+ (ssize_t) condition_comm->session_name_len +
+ (ssize_t) condition_comm->channel_name_len;
+ ret = condition_size;
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_condition_buffer_usage_low_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_condition **_condition)
+{
+ ssize_t ret;
+ struct lttng_condition *condition =
+ lttng_condition_buffer_usage_low_create();
+
+ if (!_condition || !condition) {
+ ret = -1;
+ goto error;
+ }
+
+ ret = init_condition_from_buffer(condition, view);
+ if (ret < 0) {
+ goto error;
+ }
+
+ *_condition = condition;
+ return ret;
+error:
+ lttng_condition_destroy(condition);
+ return ret;
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_condition_buffer_usage_high_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_condition **_condition)
+{
+ ssize_t ret;
+ struct lttng_condition *condition =
+ lttng_condition_buffer_usage_high_create();
+
+ if (!_condition || !condition) {
+ ret = -1;
+ goto error;
+ }
+
+ ret = init_condition_from_buffer(condition, view);
+ if (ret < 0) {
+ goto error;
+ }
+
+ *_condition = condition;
+ return ret;
+error:
+ lttng_condition_destroy(condition);
+ return ret;
+}
+
+static
+struct lttng_evaluation *create_evaluation_from_buffer(
+ enum lttng_condition_type type,
+ const struct lttng_buffer_view *view)
+{
+ const struct lttng_evaluation_buffer_usage_comm *comm =
+ (const struct lttng_evaluation_buffer_usage_comm *) view->data;
+ struct lttng_evaluation *evaluation = NULL;
+
+ if (view->size < sizeof(*comm)) {
+ goto end;
+ }
+
+ evaluation = lttng_evaluation_buffer_usage_create(type,
+ comm->buffer_use, comm->buffer_capacity);
+end:
+ return evaluation;
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_evaluation_buffer_usage_low_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_evaluation **_evaluation)
+{
+ ssize_t ret;
+ struct lttng_evaluation *evaluation = NULL;
+
+ if (!_evaluation) {
+ ret = -1;
+ goto error;
+ }
+
+ evaluation = create_evaluation_from_buffer(
+ LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW, view);
+ if (!evaluation) {
+ ret = -1;
+ goto error;
+ }
+
+ *_evaluation = evaluation;
+ ret = sizeof(struct lttng_evaluation_buffer_usage_comm);
+ return ret;
+error:
+ lttng_evaluation_destroy(evaluation);
+ return ret;
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_evaluation_buffer_usage_high_create_from_buffer(
+ const struct lttng_buffer_view *view,
+ struct lttng_evaluation **_evaluation)
+{
+ ssize_t ret;
+ struct lttng_evaluation *evaluation = NULL;
+
+ if (!_evaluation) {
+ ret = -1;
+ goto error;
+ }
+
+ evaluation = create_evaluation_from_buffer(
+ LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH, view);
+ if (!evaluation) {
+ ret = -1;
+ goto error;
+ }
+
+ *_evaluation = evaluation;
+ ret = sizeof(struct lttng_evaluation_buffer_usage_comm);
+ return ret;
+error:
+ lttng_evaluation_destroy(evaluation);
+ return ret;
+}
+
+enum lttng_condition_status
+lttng_condition_buffer_usage_get_threshold_ratio(
+ const struct lttng_condition *condition,
+ double *threshold_ratio)
+{
+ struct lttng_condition_buffer_usage *usage;
+ enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
+
+ if (!condition || !IS_USAGE_CONDITION(condition) ||
+ !threshold_ratio) {
+ status = LTTNG_CONDITION_STATUS_INVALID;
+ goto end;
+ }
+
+ usage = container_of(condition, struct lttng_condition_buffer_usage,
+ parent);
+ if (!usage->threshold_ratio.set) {
+ status = LTTNG_CONDITION_STATUS_UNSET;
+ goto end;
+ }
+ *threshold_ratio = usage->threshold_ratio.value;
+end:
+ return status;
+}
+
+/* threshold_ratio expressed as [0.0, 1.0]. */
+enum lttng_condition_status
+lttng_condition_buffer_usage_set_threshold_ratio(
+ struct lttng_condition *condition, double threshold_ratio)
+{
+ struct lttng_condition_buffer_usage *usage;
+ enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
+
+ if (!condition || !IS_USAGE_CONDITION(condition) ||
+ threshold_ratio < 0.0 ||
+ threshold_ratio > 1.0) {
+ status = LTTNG_CONDITION_STATUS_INVALID;
+ goto end;
+ }
+
+ usage = container_of(condition, struct lttng_condition_buffer_usage,
+ parent);
+ usage->threshold_ratio.set = true;
+ usage->threshold_bytes.set = false;
+ usage->threshold_ratio.value = threshold_ratio;
+end:
+ return status;
+}
+
+enum lttng_condition_status
+lttng_condition_buffer_usage_get_threshold(
+ const struct lttng_condition *condition,
+ uint64_t *threshold_bytes)
+{
+ struct lttng_condition_buffer_usage *usage;
+ enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
+
+ if (!condition || !IS_USAGE_CONDITION(condition) || !threshold_bytes) {
+ status = LTTNG_CONDITION_STATUS_INVALID;
+ goto end;
+ }
+
+ usage = container_of(condition, struct lttng_condition_buffer_usage,
+ parent);
+ if (!usage->threshold_bytes.set) {
+ status = LTTNG_CONDITION_STATUS_UNSET;
+ goto end;
+ }
+ *threshold_bytes = usage->threshold_bytes.value;
+end:
+ return status;
+}
+
+enum lttng_condition_status
+lttng_condition_buffer_usage_set_threshold(
+ struct lttng_condition *condition, uint64_t threshold_bytes)
+{
+ struct lttng_condition_buffer_usage *usage;
+ enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
+
+ if (!condition || !IS_USAGE_CONDITION(condition)) {
+ status = LTTNG_CONDITION_STATUS_INVALID;
+ goto end;
+ }
+
+ usage = container_of(condition, struct lttng_condition_buffer_usage,
+ parent);
+ usage->threshold_ratio.set = false;
+ usage->threshold_bytes.set = true;
+ usage->threshold_bytes.value = threshold_bytes;
+end:
+ return status;
+}
+
+enum lttng_condition_status
+lttng_condition_buffer_usage_get_session_name(
+ const struct lttng_condition *condition,
+ const char **session_name)
+{
+ struct lttng_condition_buffer_usage *usage;
+ enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
+
+ if (!condition || !IS_USAGE_CONDITION(condition) || !session_name) {
+ status = LTTNG_CONDITION_STATUS_INVALID;
+ goto end;
+ }
+
+ usage = container_of(condition, struct lttng_condition_buffer_usage,
+ parent);
+ if (!usage->session_name) {
+ status = LTTNG_CONDITION_STATUS_UNSET;
+ goto end;
+ }
+ *session_name = usage->session_name;
+end:
+ return status;
+}
+
+enum lttng_condition_status
+lttng_condition_buffer_usage_set_session_name(
+ struct lttng_condition *condition, const char *session_name)
+{
+ char *session_name_copy;
+ struct lttng_condition_buffer_usage *usage;
+ enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
+
+ if (!condition || !IS_USAGE_CONDITION(condition) || !session_name ||
+ strlen(session_name) == 0) {
+ status = LTTNG_CONDITION_STATUS_INVALID;
+ goto end;
+ }
+
+ usage = container_of(condition, struct lttng_condition_buffer_usage,
+ parent);
+ session_name_copy = strdup(session_name);
+ if (!session_name_copy) {
+ status = LTTNG_CONDITION_STATUS_ERROR;
+ goto end;
+ }
+
+ if (usage->session_name) {
+ free(usage->session_name);
+ }
+ usage->session_name = session_name_copy;
+end:
+ return status;
+}
+
+enum lttng_condition_status
+lttng_condition_buffer_usage_get_channel_name(
+ const struct lttng_condition *condition,
+ const char **channel_name)
+{
+ struct lttng_condition_buffer_usage *usage;
+ enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
+
+ if (!condition || !IS_USAGE_CONDITION(condition) || !channel_name) {
+ status = LTTNG_CONDITION_STATUS_INVALID;
+ goto end;
+ }
+
+ usage = container_of(condition, struct lttng_condition_buffer_usage,
+ parent);
+ if (!usage->channel_name) {
+ status = LTTNG_CONDITION_STATUS_UNSET;
+ goto end;
+ }
+ *channel_name = usage->channel_name;
+end:
+ return status;
+}
+
+enum lttng_condition_status
+lttng_condition_buffer_usage_set_channel_name(
+ struct lttng_condition *condition, const char *channel_name)
+{
+ char *channel_name_copy;
+ struct lttng_condition_buffer_usage *usage;
+ enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
+
+ if (!condition || !IS_USAGE_CONDITION(condition) || !channel_name ||
+ strlen(channel_name) == 0) {
+ status = LTTNG_CONDITION_STATUS_INVALID;
+ goto end;
+ }
+
+ usage = container_of(condition, struct lttng_condition_buffer_usage,
+ parent);
+ channel_name_copy = strdup(channel_name);
+ if (!channel_name_copy) {
+ status = LTTNG_CONDITION_STATUS_ERROR;
+ goto end;
+ }
+
+ if (usage->channel_name) {
+ free(usage->channel_name);
+ }
+ usage->channel_name = channel_name_copy;
+end:
+ return status;
+}
+
+enum lttng_condition_status
+lttng_condition_buffer_usage_get_domain_type(
+ const struct lttng_condition *condition,
+ enum lttng_domain_type *type)
+{
+ struct lttng_condition_buffer_usage *usage;
+ enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
+
+ if (!condition || !IS_USAGE_CONDITION(condition) || !type) {
+ status = LTTNG_CONDITION_STATUS_INVALID;
+ goto end;
+ }
+
+ usage = container_of(condition, struct lttng_condition_buffer_usage,
+ parent);
+ if (!usage->domain.set) {
+ status = LTTNG_CONDITION_STATUS_UNSET;
+ goto end;
+ }
+ *type = usage->domain.type;
+end:
+ return status;
+}
+
+enum lttng_condition_status
+lttng_condition_buffer_usage_set_domain_type(
+ struct lttng_condition *condition, enum lttng_domain_type type)
+{
+ struct lttng_condition_buffer_usage *usage;
+ enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
+
+ if (!condition || !IS_USAGE_CONDITION(condition) ||
+ type == LTTNG_DOMAIN_NONE) {
+ status = LTTNG_CONDITION_STATUS_INVALID;
+ goto end;
+ }
+
+ usage = container_of(condition, struct lttng_condition_buffer_usage,
+ parent);
+ usage->domain.set = true;
+ usage->domain.type = type;
+end:
+ return status;
+}
+
+static
+ssize_t lttng_evaluation_buffer_usage_serialize(
+ struct lttng_evaluation *evaluation, char *buf)
+{
+ ssize_t ret;
+ struct lttng_evaluation_buffer_usage *usage;
+
+ usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
+ parent);
+ if (buf) {
+ struct lttng_evaluation_buffer_usage_comm comm = {
+ .buffer_use = usage->buffer_use,
+ .buffer_capacity = usage->buffer_capacity,
+ };
+
+ memcpy(buf, &comm, sizeof(comm));
+ }
+
+ ret = sizeof(struct lttng_evaluation_buffer_usage_comm);
+ return ret;
+}
+
+static
+void lttng_evaluation_buffer_usage_destroy(
+ struct lttng_evaluation *evaluation)
+{
+ struct lttng_evaluation_buffer_usage *usage;
+
+ usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
+ parent);
+ free(usage);
+}
+
+LTTNG_HIDDEN
+struct lttng_evaluation *lttng_evaluation_buffer_usage_create(
+ enum lttng_condition_type type, uint64_t use, uint64_t capacity)
+{
+ struct lttng_evaluation_buffer_usage *usage;
+
+ usage = zmalloc(sizeof(struct lttng_evaluation_buffer_usage));
+ if (!usage) {
+ goto end;
+ }
+
+ usage->parent.type = type;
+ usage->buffer_use = use;
+ usage->buffer_capacity = capacity;
+ usage->parent.serialize = lttng_evaluation_buffer_usage_serialize;
+ usage->parent.destroy = lttng_evaluation_buffer_usage_destroy;
+end:
+ return &usage->parent;
+}
+
+/*
+ * Get the sampled buffer usage which caused the associated condition to
+ * evaluate to "true".
+ */
+enum lttng_evaluation_status
+lttng_evaluation_buffer_usage_get_usage_ratio(
+ const struct lttng_evaluation *evaluation, double *usage_ratio)
+{
+ struct lttng_evaluation_buffer_usage *usage;
+ enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
+
+ if (!evaluation || !is_usage_evaluation(evaluation) || !usage_ratio) {
+ status = LTTNG_EVALUATION_STATUS_INVALID;
+ goto end;
+ }
+
+ usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
+ parent);
+ *usage_ratio = (double) usage->buffer_use /
+ (double) usage->buffer_capacity;
+end:
+ return status;
+}
+
+enum lttng_evaluation_status
+lttng_evaluation_buffer_usage_get_usage(
+ const struct lttng_evaluation *evaluation,
+ uint64_t *usage_bytes)
+{
+ struct lttng_evaluation_buffer_usage *usage;
+ enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
+
+ if (!evaluation || !is_usage_evaluation(evaluation) || !usage_bytes) {
+ status = LTTNG_EVALUATION_STATUS_INVALID;
+ goto end;
+ }
+
+ usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
+ parent);
+ *usage_bytes = usage->buffer_use;
+end:
+ return status;
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <lttng/condition/condition-internal.h>
+#include <lttng/condition/buffer-usage-internal.h>
+#include <common/macros.h>
+#include <common/error.h>
+#include <common/dynamic-buffer.h>
+#include <common/buffer-view.h>
+#include <stdbool.h>
+#include <assert.h>
+
+enum lttng_condition_type lttng_condition_get_type(
+ const struct lttng_condition *condition)
+{
+ return condition ? condition->type : LTTNG_CONDITION_TYPE_UNKNOWN;
+}
+
+void lttng_condition_destroy(struct lttng_condition *condition)
+{
+ if (!condition) {
+ return;
+ }
+
+ assert(condition->destroy);
+ condition->destroy(condition);
+}
+
+LTTNG_HIDDEN
+bool lttng_condition_validate(const struct lttng_condition *condition)
+{
+ bool valid;
+
+ if (!condition) {
+ valid = false;
+ goto end;
+ }
+
+ if (!condition->validate) {
+ /* Sub-class guarantees that it can never be invalid. */
+ valid = true;
+ goto end;
+ }
+
+ valid = condition->validate(condition);
+end:
+ return valid;
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_condition_serialize(const struct lttng_condition *condition,
+ char *buf)
+{
+ ssize_t ret, condition_size;
+ struct lttng_condition_comm condition_comm;
+
+ if (!condition) {
+ ret = -1;
+ goto end;
+ }
+
+ condition_comm.condition_type = (int8_t) condition->type;
+ ret = sizeof(struct lttng_condition_comm);
+ if (buf) {
+ memcpy(buf, &condition_comm, ret);
+ buf += ret;
+ }
+
+ condition_size = condition->serialize(condition, buf);
+ if (condition_size < 0) {
+ ret = condition_size;
+ goto end;
+ }
+ ret += condition_size;
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+bool lttng_condition_is_equal(const struct lttng_condition *a,
+ const struct lttng_condition *b)
+{
+ bool is_equal = false;
+
+ if (!a || !b) {
+ goto end;
+ }
+
+ if (a->type != b->type) {
+ goto end;
+ }
+
+ is_equal = a->equal ? a->equal(a, b) : true;
+end:
+ return is_equal;
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_condition_create_from_buffer(
+ const struct lttng_buffer_view *buffer,
+ struct lttng_condition **condition)
+{
+ ssize_t ret, condition_size = 0;
+ const struct lttng_condition_comm *condition_comm;
+ condition_create_from_buffer_cb create_from_buffer = NULL;
+
+ if (!buffer || !condition) {
+ ret = -1;
+ goto end;
+ }
+
+ DBG("Deserializing condition from buffer");
+ condition_comm = (const struct lttng_condition_comm *) buffer->data;
+ condition_size += sizeof(*condition_comm);
+
+ switch ((enum lttng_condition_type) condition_comm->condition_type) {
+ case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
+ create_from_buffer = lttng_condition_buffer_usage_low_create_from_buffer;
+ break;
+ case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
+ create_from_buffer = lttng_condition_buffer_usage_high_create_from_buffer;
+ break;
+ default:
+ ERR("Attempted to create condition of unknown type (%i)",
+ (int) condition_comm->condition_type);
+ ret = -1;
+ goto end;
+ }
+
+ if (create_from_buffer) {
+ const struct lttng_buffer_view view =
+ lttng_buffer_view_from_view(buffer,
+ sizeof(*condition_comm), -1);
+
+ ret = create_from_buffer(&view, condition);
+ if (ret < 0) {
+ goto end;
+ }
+ condition_size += ret;
+
+ } else {
+ abort();
+ }
+
+ ret = condition_size;
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+void lttng_condition_init(struct lttng_condition *condition,
+ enum lttng_condition_type type)
+{
+ condition->type = type;
+}
#define DEFAULT_LTTNG_EXTRA_KMOD_PROBES "LTTNG_EXTRA_KMOD_PROBES"
/* Default unix socket path */
-#define DEFAULT_GLOBAL_CLIENT_UNIX_SOCK DEFAULT_LTTNG_RUNDIR "/client-lttng-sessiond"
-#define DEFAULT_HOME_CLIENT_UNIX_SOCK DEFAULT_LTTNG_HOME_RUNDIR "/client-lttng-sessiond"
-#define DEFAULT_GLOBAL_HEALTH_UNIX_SOCK DEFAULT_LTTNG_RUNDIR "/sessiond-health"
-#define DEFAULT_HOME_HEALTH_UNIX_SOCK DEFAULT_LTTNG_HOME_RUNDIR "/sessiond-health"
+#define DEFAULT_GLOBAL_CLIENT_UNIX_SOCK DEFAULT_LTTNG_RUNDIR "/client-lttng-sessiond"
+#define DEFAULT_HOME_CLIENT_UNIX_SOCK DEFAULT_LTTNG_HOME_RUNDIR "/client-lttng-sessiond"
+#define DEFAULT_GLOBAL_HEALTH_UNIX_SOCK DEFAULT_LTTNG_RUNDIR "/sessiond-health"
+#define DEFAULT_HOME_HEALTH_UNIX_SOCK DEFAULT_LTTNG_HOME_RUNDIR "/sessiond-health"
+#define DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK DEFAULT_LTTNG_RUNDIR "/sessiond-notification"
+#define DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK DEFAULT_LTTNG_HOME_RUNDIR "/sessiond-notification"
/* Default consumer health unix socket path */
#define DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK DEFAULT_LTTNG_RUNDIR "/ustconsumerd32/health"
/* Default thread stack size; the default mandated by pthread_create(3) */
#define DEFAULT_LTTNG_THREAD_STACK_SIZE 2097152
+/* Default maximal size of message notification channel message payloads. */
+#define DEFAULT_MAX_NOTIFICATION_CLIENT_MESSAGE_PAYLOAD_SIZE 65536
+
+/* Default maximal size of message notification channel message payloads. */
+#define DEFAULT_CLIENT_MAX_QUEUED_NOTIFICATIONS_COUNT 100
+
/*
* Returns the default subbuf size.
*
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <lttng/endpoint-internal.h>
+
+static
+struct lttng_endpoint lttng_session_daemon_notification_endpoint_instance = {
+ .type = LTTNG_ENDPOINT_TYPE_DEFAULT_SESSIOND_NOTIFICATION
+};
+
+struct lttng_endpoint *lttng_session_daemon_notification_endpoint =
+ <tng_session_daemon_notification_endpoint_instance;
[ ERROR_INDEX(LTTNG_ERR_REGEN_STATEDUMP_FAIL) ] = "Failed to regenerate the state dump",
[ ERROR_INDEX(LTTNG_ERR_REGEN_STATEDUMP_NOMEM) ] = "Failed to regenerate the state dump, not enough memory",
[ ERROR_INDEX(LTTNG_ERR_NOT_SNAPSHOT_SESSION) ] = "Snapshot command can't be applied to a non-snapshot session",
+ [ ERROR_INDEX(LTTNG_ERR_INVALID_TRIGGER) ] = "Invalid trigger",
+ [ ERROR_INDEX(LTTNG_ERR_TRIGGER_EXISTS) ] = "Trigger already registered",
+ [ ERROR_INDEX(LTTNG_ERR_TRIGGER_NOT_FOUND) ] = "Trigger not found",
+ [ ERROR_INDEX(LTTNG_ERR_COMMAND_CANCELLED) ] = "Command cancelled",
/* Last element */
[ ERROR_INDEX(LTTNG_ERR_NR) ] = "Unknown error code"
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <lttng/condition/evaluation-internal.h>
+#include <lttng/condition/buffer-usage-internal.h>
+#include <common/macros.h>
+#include <common/error.h>
+#include <stdbool.h>
+#include <assert.h>
+
+LTTNG_HIDDEN
+ssize_t lttng_evaluation_serialize(struct lttng_evaluation *evaluation,
+ char *buf)
+{
+ ssize_t ret, offset = 0;
+ struct lttng_evaluation_comm evaluation_comm;
+
+ evaluation_comm.type = (int8_t) evaluation->type;
+ if (buf) {
+ memcpy(buf, &evaluation_comm, sizeof(evaluation_comm));
+ }
+ offset += sizeof(evaluation_comm);
+
+ if (evaluation->serialize) {
+ ret = evaluation->serialize(evaluation,
+ buf ? (buf + offset) : NULL);
+ if (ret < 0) {
+ goto end;
+ }
+ offset += ret;
+ }
+
+ ret = offset;
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_evaluation_create_from_buffer(
+ const struct lttng_buffer_view *src_view,
+ struct lttng_evaluation **evaluation)
+{
+ ssize_t ret, evaluation_size = 0;
+ const struct lttng_evaluation_comm *evaluation_comm;
+ const struct lttng_buffer_view evaluation_view =
+ lttng_buffer_view_from_view(src_view,
+ sizeof(*evaluation_comm), -1);
+
+ if (!src_view || !evaluation) {
+ ret = -1;
+ goto end;
+ }
+
+ evaluation_comm = (const struct lttng_evaluation_comm *) src_view->data;
+ evaluation_size += sizeof(*evaluation_comm);
+
+ switch ((enum lttng_condition_type) evaluation_comm->type) {
+ case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
+ ret = lttng_evaluation_buffer_usage_low_create_from_buffer(
+ &evaluation_view, evaluation);
+ if (ret < 0) {
+ goto end;
+ }
+ evaluation_size += ret;
+ break;
+ case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
+ ret = lttng_evaluation_buffer_usage_high_create_from_buffer(
+ &evaluation_view, evaluation);
+ if (ret < 0) {
+ goto end;
+ }
+ evaluation_size += ret;
+ break;
+ default:
+ ERR("Attempted to create evaluation of unknown type (%i)",
+ (int) evaluation_comm->type);
+ ret = -1;
+ goto end;
+ }
+ ret = evaluation_size;
+end:
+ return ret;
+}
+
+enum lttng_condition_type lttng_evaluation_get_type(
+ const struct lttng_evaluation *evaluation)
+{
+ return evaluation ? evaluation->type : LTTNG_CONDITION_TYPE_UNKNOWN;
+}
+
+void lttng_evaluation_destroy(struct lttng_evaluation *evaluation)
+{
+ if (!evaluation) {
+ return;
+ }
+
+ assert(evaluation->destroy);
+ evaluation->destroy(evaluation);
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <lttng/notification/notification-internal.h>
+#include <lttng/condition/condition-internal.h>
+#include <lttng/condition/evaluation-internal.h>
+#include <lttng/condition/condition.h>
+#include <lttng/condition/evaluation.h>
+#include <assert.h>
+
+LTTNG_HIDDEN
+struct lttng_notification *lttng_notification_create(
+ struct lttng_condition *condition,
+ struct lttng_evaluation *evaluation)
+{
+ struct lttng_notification *notification = NULL;
+
+ if (!condition || !evaluation) {
+ goto end;
+ }
+
+ notification = zmalloc(sizeof(struct lttng_notification));
+ if (!notification) {
+ goto end;
+ }
+
+ notification->condition = condition;
+ notification->evaluation = evaluation;
+ notification->owns_elements = false;
+end:
+ return notification;
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_notification_serialize(struct lttng_notification *notification,
+ char *buf)
+{
+ ssize_t ret, condition_size, evaluation_size, offset = 0;
+ struct lttng_notification_comm notification_comm;
+
+ if (!notification) {
+ ret = -1;
+ goto end;
+ }
+
+ offset += sizeof(notification_comm);
+ condition_size = lttng_condition_serialize(notification->condition,
+ buf ? (buf + offset) : NULL);
+ if (condition_size < 0) {
+ ret = condition_size;
+ goto end;
+ }
+ offset += condition_size;
+
+ evaluation_size = lttng_evaluation_serialize(notification->evaluation,
+ buf ? (buf + offset) : NULL);
+ if (evaluation_size < 0) {
+ ret = evaluation_size;
+ goto end;
+ }
+ offset += evaluation_size;
+
+ if (buf) {
+ notification_comm.length =
+ (uint32_t) (condition_size + evaluation_size);
+ memcpy(buf, ¬ification_comm, sizeof(notification_comm));
+ }
+ ret = offset;
+end:
+ return ret;
+
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_notification_create_from_buffer(
+ const struct lttng_buffer_view *src_view,
+ struct lttng_notification **notification)
+{
+ ssize_t ret, notification_size = 0, condition_size, evaluation_size;
+ const struct lttng_notification_comm *notification_comm;
+ struct lttng_condition *condition;
+ struct lttng_evaluation *evaluation;
+ struct lttng_buffer_view condition_view;
+ struct lttng_buffer_view evaluation_view;
+
+ if (!src_view || !notification) {
+ ret = -1;
+ goto end;
+ }
+
+ notification_comm =
+ (const struct lttng_notification_comm *) src_view->data;
+ notification_size += sizeof(*notification_comm);
+
+ /* struct lttng_condition */
+ condition_view = lttng_buffer_view_from_view(src_view,
+ sizeof(*notification_comm), -1);
+ condition_size = lttng_condition_create_from_buffer(&condition_view,
+ &condition);
+ if (condition_size < 0) {
+ ret = condition_size;
+ goto end;
+ }
+ notification_size += condition_size;
+
+ /* struct lttng_evaluation */
+ evaluation_view = lttng_buffer_view_from_view(&condition_view,
+ condition_size, -1);
+ evaluation_size = lttng_evaluation_create_from_buffer(&evaluation_view,
+ &evaluation);
+ if (evaluation_size < 0) {
+ ret = evaluation_size;
+ goto end;
+ }
+ notification_size += evaluation_size;
+
+ /* Unexpected size of inner-elements; the buffer is corrupted. */
+ if ((ssize_t) notification_comm->length !=
+ condition_size + evaluation_size) {
+ ret = -1;
+ goto error;
+ }
+
+ *notification = lttng_notification_create(condition, evaluation);
+ if (!*notification) {
+ ret = -1;
+ goto error;
+ }
+ ret = notification_size;
+ (*notification)->owns_elements = true;
+end:
+ return ret;
+error:
+ lttng_condition_destroy(condition);
+ lttng_evaluation_destroy(evaluation);
+ return ret;
+}
+
+void lttng_notification_destroy(struct lttng_notification *notification)
+{
+ if (!notification) {
+ return;
+ }
+
+ if (notification->owns_elements) {
+ lttng_condition_destroy(notification->condition);
+ lttng_evaluation_destroy(notification->evaluation);
+ }
+ free(notification);
+}
+
+const struct lttng_condition *lttng_notification_get_condition(
+ struct lttng_notification *notification)
+{
+ return notification ? notification->condition : NULL;
+}
+
+const struct lttng_evaluation *lttng_notification_get_evaluation(
+ struct lttng_notification *notification)
+{
+ return notification ? notification->evaluation : NULL;
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <lttng/action/action-internal.h>
+#include <lttng/action/notify-internal.h>
+#include <common/macros.h>
+#include <assert.h>
+
+static
+void lttng_action_notify_destroy(struct lttng_action *action)
+{
+ free(action);
+}
+
+static
+ssize_t lttng_action_notify_serialize(struct lttng_action *action, char *buf)
+{
+ return 0;
+}
+
+struct lttng_action *lttng_action_notify_create(void)
+{
+ struct lttng_action_notify *notify;
+
+ notify = zmalloc(sizeof(struct lttng_action_notify));
+ if (!notify) {
+ goto end;
+ }
+
+ notify->parent.type = LTTNG_ACTION_TYPE_NOTIFY;
+ notify->parent.serialize = lttng_action_notify_serialize;
+ notify->parent.destroy = lttng_action_notify_destroy;
+end:
+ return ¬ify->parent;
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <lttng/trigger/trigger-internal.h>
+#include <lttng/condition/condition-internal.h>
+#include <lttng/action/action-internal.h>
+#include <common/error.h>
+#include <assert.h>
+
+LTTNG_HIDDEN
+bool lttng_trigger_validate(struct lttng_trigger *trigger)
+{
+ bool valid;
+
+ if (!trigger) {
+ valid = false;
+ goto end;
+ }
+
+ valid = lttng_condition_validate(trigger->condition) &&
+ lttng_action_validate(trigger->action);
+end:
+ return valid;
+}
+
+struct lttng_trigger *lttng_trigger_create(
+ struct lttng_condition *condition,
+ struct lttng_action *action)
+{
+ struct lttng_trigger *trigger = NULL;
+
+ if (!condition || !action) {
+ goto end;
+ }
+
+ trigger = zmalloc(sizeof(struct lttng_trigger));
+ if (!trigger) {
+ goto end;
+ }
+
+ trigger->condition = condition;
+ trigger->action = action;
+end:
+ return trigger;
+}
+
+struct lttng_condition *lttng_trigger_get_condition(
+ struct lttng_trigger *trigger)
+{
+ return trigger ? trigger->condition : NULL;
+}
+
+extern struct lttng_action *lttng_trigger_get_action(
+ struct lttng_trigger *trigger)
+{
+ return trigger ? trigger->action : NULL;
+}
+
+void lttng_trigger_destroy(struct lttng_trigger *trigger)
+{
+ if (!trigger) {
+ return;
+ }
+
+ free(trigger);
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_trigger_create_from_buffer(
+ const struct lttng_buffer_view *src_view,
+ struct lttng_trigger **trigger)
+{
+ ssize_t ret, offset = 0, condition_size, action_size;
+ struct lttng_condition *condition = NULL;
+ struct lttng_action *action = NULL;
+ const struct lttng_trigger_comm *trigger_comm;
+ struct lttng_buffer_view condition_view;
+ struct lttng_buffer_view action_view;
+
+ if (!src_view || !trigger) {
+ ret = -1;
+ goto end;
+ }
+
+ /* lttng_trigger_comm header */
+ trigger_comm = (const struct lttng_trigger_comm *) src_view->data;
+ offset += sizeof(*trigger_comm);
+
+ condition_view = lttng_buffer_view_from_view(src_view, offset, -1);
+
+ /* struct lttng_condition */
+ condition_size = lttng_condition_create_from_buffer(&condition_view,
+ &condition);
+ if (condition_size < 0) {
+ ret = condition_size;
+ goto end;
+ }
+ offset += condition_size;
+
+ /* struct lttng_action */
+ action_view = lttng_buffer_view_from_view(src_view, offset, -1);
+ action_size = lttng_action_create_from_buffer(&action_view, &action);
+ if (action_size < 0) {
+ ret = action_size;
+ goto end;
+ }
+ offset += action_size;
+
+ /* Unexpected size of inner-elements; the buffer is corrupted. */
+ if ((ssize_t) trigger_comm->length != condition_size + action_size) {
+ ret = -1;
+ goto error;
+ }
+
+ *trigger = lttng_trigger_create(condition, action);
+ if (!*trigger) {
+ ret = -1;
+ goto error;
+ }
+ ret = offset;
+end:
+ return ret;
+error:
+ lttng_condition_destroy(condition);
+ lttng_action_destroy(action);
+ return ret;
+}
+
+/*
+ * Returns the size of a trigger (header + condition + action).
+ * Both elements are stored contiguously, see their "*_comm" structure
+ * for the detailed format.
+ */
+LTTNG_HIDDEN
+ssize_t lttng_trigger_serialize(struct lttng_trigger *trigger, char *buf)
+{
+ struct lttng_trigger_comm trigger_comm;
+ ssize_t action_size, condition_size, offset = 0, ret;
+
+ if (!trigger) {
+ ret = -1;
+ goto end;
+ }
+
+ offset += sizeof(trigger_comm);
+ condition_size = lttng_condition_serialize(trigger->condition,
+ buf ? (buf + offset) : NULL);
+ if (condition_size < 0) {
+ ret = -1;
+ goto end;
+ }
+ offset += condition_size;
+
+ action_size = lttng_action_serialize(trigger->action,
+ buf ? (buf + offset) : NULL);
+ if (action_size < 0) {
+ ret = -1;
+ goto end;
+ }
+ offset += action_size;
+
+ if (buf) {
+ trigger_comm.length = (uint32_t) (condition_size + action_size);
+ memcpy(buf, &trigger_comm, sizeof(trigger_comm));
+ }
+ ret = offset;
+end:
+ return ret;
+}
lib_LTLIBRARIES = liblttng-ctl.la
liblttng_ctl_la_SOURCES = lttng-ctl.c snapshot.c lttng-ctl-helper.h \
- lttng-ctl-health.c save.c load.c deprecated-symbols.c
+ lttng-ctl-health.c save.c load.c deprecated-symbols.c \
+ channel.c
liblttng_ctl_la_LDFLAGS = \
$(LT_NO_UNDEFINED)
--- /dev/null
+/*
+ * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <lttng/notification/notification-internal.h>
+#include <lttng/notification/channel-internal.h>
+#include <lttng/condition/condition-internal.h>
+#include <lttng/endpoint.h>
+#include <common/defaults.h>
+#include <common/error.h>
+#include <common/dynamic-buffer.h>
+#include <common/utils.h>
+#include <common/defaults.h>
+#include <assert.h>
+#include "lttng-ctl-helper.h"
+
+static
+int handshake(struct lttng_notification_channel *channel);
+
+/*
+ * Populates the reception buffer with the next complete message.
+ * The caller must acquire the client's lock.
+ */
+static
+int receive_message(struct lttng_notification_channel *channel)
+{
+ ssize_t ret;
+ struct lttng_notification_channel_message msg;
+
+ ret = lttng_dynamic_buffer_set_size(&channel->reception_buffer, 0);
+ if (ret) {
+ goto error;
+ }
+
+ ret = lttcomm_recv_unix_sock(channel->socket, &msg, sizeof(msg));
+ if (ret <= 0) {
+ ret = -1;
+ goto error;
+ }
+
+ if (msg.size > DEFAULT_MAX_NOTIFICATION_CLIENT_MESSAGE_PAYLOAD_SIZE) {
+ ret = -1;
+ goto error;
+ }
+
+ /* Add message header at buffer's start. */
+ ret = lttng_dynamic_buffer_append(&channel->reception_buffer, &msg,
+ sizeof(msg));
+ if (ret) {
+ goto error;
+ }
+
+ /* Reserve space for the payload. */
+ ret = lttng_dynamic_buffer_set_size(&channel->reception_buffer,
+ channel->reception_buffer.size + msg.size);
+ if (ret) {
+ goto error;
+ }
+
+ /* Receive message payload. */
+ ret = lttcomm_recv_unix_sock(channel->socket,
+ channel->reception_buffer.data + sizeof(msg), msg.size);
+ if (ret < (ssize_t) msg.size) {
+ ret = -1;
+ goto error;
+ }
+ ret = 0;
+end:
+ return ret;
+error:
+ lttng_dynamic_buffer_set_size(&channel->reception_buffer, 0);
+ goto end;
+}
+
+static
+enum lttng_notification_channel_message_type get_current_message_type(
+ struct lttng_notification_channel *channel)
+{
+ struct lttng_notification_channel_message *msg;
+
+ assert(channel->reception_buffer.size >= sizeof(*msg));
+
+ msg = (struct lttng_notification_channel_message *)
+ channel->reception_buffer.data;
+ return (enum lttng_notification_channel_message_type) msg->type;
+}
+
+static
+struct lttng_notification *create_notification_from_current_message(
+ struct lttng_notification_channel *channel)
+{
+ ssize_t ret;
+ struct lttng_notification *notification = NULL;
+ struct lttng_buffer_view view;
+
+ if (channel->reception_buffer.size <=
+ sizeof(struct lttng_notification_channel_message)) {
+ goto end;
+ }
+
+ view = lttng_buffer_view_from_dynamic_buffer(&channel->reception_buffer,
+ sizeof(struct lttng_notification_channel_message), -1);
+
+ ret = lttng_notification_create_from_buffer(&view, ¬ification);
+ if (ret != channel->reception_buffer.size -
+ sizeof(struct lttng_notification_channel_message)) {
+ lttng_notification_destroy(notification);
+ notification = NULL;
+ goto end;
+ }
+end:
+ return notification;
+}
+
+struct lttng_notification_channel *lttng_notification_channel_create(
+ struct lttng_endpoint *endpoint)
+{
+ int fd, ret;
+ bool is_in_tracing_group = false, is_root = false;
+ char *sock_path = NULL;
+ struct lttng_notification_channel *channel = NULL;
+
+ if (!endpoint ||
+ endpoint != lttng_session_daemon_notification_endpoint) {
+ goto end;
+ }
+
+ sock_path = zmalloc(LTTNG_PATH_MAX);
+ if (!sock_path) {
+ goto end;
+ }
+
+ channel = zmalloc(sizeof(struct lttng_notification_channel));
+ if (!channel) {
+ goto end;
+ }
+ channel->socket = -1;
+ pthread_mutex_init(&channel->lock, NULL);
+ lttng_dynamic_buffer_init(&channel->reception_buffer);
+ CDS_INIT_LIST_HEAD(&channel->pending_notifications.list);
+
+ is_root = (getuid() == 0);
+ if (!is_root) {
+ is_in_tracing_group = lttng_check_tracing_group();
+ }
+
+ if (is_root || is_in_tracing_group) {
+ lttng_ctl_copy_string(sock_path,
+ DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK,
+ LTTNG_PATH_MAX);
+ ret = lttcomm_connect_unix_sock(sock_path);
+ if (ret >= 0) {
+ fd = ret;
+ goto set_fd;
+ }
+ }
+
+ /* Fallback to local session daemon. */
+ ret = snprintf(sock_path, LTTNG_PATH_MAX,
+ DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK,
+ utils_get_home_dir());
+ if (ret < 0 || ret >= LTTNG_PATH_MAX) {
+ goto error;
+ }
+
+ ret = lttcomm_connect_unix_sock(sock_path);
+ if (ret < 0) {
+ goto error;
+ }
+ fd = ret;
+
+set_fd:
+ channel->socket = fd;
+
+ ret = handshake(channel);
+ if (ret) {
+ goto error;
+ }
+end:
+ free(sock_path);
+ return channel;
+error:
+ lttng_notification_channel_destroy(channel);
+ channel = NULL;
+ goto end;
+}
+
+enum lttng_notification_channel_status
+lttng_notification_channel_get_next_notification(
+ struct lttng_notification_channel *channel,
+ struct lttng_notification **_notification)
+{
+ int ret;
+ struct lttng_notification *notification = NULL;
+ enum lttng_notification_channel_status status =
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
+
+ if (!channel || !_notification) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
+ goto end;
+ }
+
+ if (channel->pending_notifications.count) {
+ struct pending_notification *pending_notification;
+
+ assert(!cds_list_empty(&channel->pending_notifications.list));
+
+ /* Deliver one of the pending notifications. */
+ pending_notification = cds_list_first_entry(
+ &channel->pending_notifications.list,
+ struct pending_notification,
+ node);
+ notification = pending_notification->notification;
+ if (!notification) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED;
+ }
+ cds_list_del(&pending_notification->node);
+ channel->pending_notifications.count--;
+ free(pending_notification);
+ goto end;
+ }
+
+ pthread_mutex_lock(&channel->lock);
+
+ ret = receive_message(channel);
+ if (ret) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_unlock;
+ }
+
+ switch (get_current_message_type(channel)) {
+ case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION:
+ notification = create_notification_from_current_message(
+ channel);
+ if (!notification) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_unlock;
+ }
+ break;
+ case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED:
+ /* No payload to consume. */
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED;
+ break;
+ default:
+ /* Protocol error. */
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_unlock;
+ }
+
+end_unlock:
+ pthread_mutex_unlock(&channel->lock);
+end:
+ if (_notification) {
+ *_notification = notification;
+ }
+ return status;
+}
+
+static
+int enqueue_dropped_notification(
+ struct lttng_notification_channel *channel)
+{
+ int ret = 0;
+ struct pending_notification *pending_notification;
+ struct cds_list_head *last_element =
+ channel->pending_notifications.list.prev;
+
+ pending_notification = caa_container_of(last_element,
+ struct pending_notification, node);
+ if (!pending_notification->notification) {
+ /*
+ * The last enqueued notification indicates dropped
+ * notifications; there is nothing to do as we group
+ * dropped notifications together.
+ */
+ goto end;
+ }
+
+ if (channel->pending_notifications.count >=
+ DEFAULT_CLIENT_MAX_QUEUED_NOTIFICATIONS_COUNT &&
+ pending_notification->notification) {
+ /*
+ * Discard the last enqueued notification to indicate
+ * that notifications were dropped at this point.
+ */
+ lttng_notification_destroy(
+ pending_notification->notification);
+ pending_notification->notification = NULL;
+ goto end;
+ }
+
+ pending_notification = zmalloc(sizeof(*pending_notification));
+ if (!pending_notification) {
+ ret = -1;
+ goto end;
+ }
+ CDS_INIT_LIST_HEAD(&pending_notification->node);
+ cds_list_add(&pending_notification->node,
+ &channel->pending_notifications.list);
+ channel->pending_notifications.count++;
+end:
+ return ret;
+}
+
+static
+int enqueue_notification_from_current_message(
+ struct lttng_notification_channel *channel)
+{
+ int ret = 0;
+ struct lttng_notification *notification;
+ struct pending_notification *pending_notification;
+
+ if (channel->pending_notifications.count >=
+ DEFAULT_CLIENT_MAX_QUEUED_NOTIFICATIONS_COUNT) {
+ /* Drop the notification. */
+ ret = enqueue_dropped_notification(channel);
+ goto end;
+ }
+
+ pending_notification = zmalloc(sizeof(*pending_notification));
+ if (!pending_notification) {
+ ret = -1;
+ goto error;
+ }
+ CDS_INIT_LIST_HEAD(&pending_notification->node);
+
+ notification = create_notification_from_current_message(channel);
+ if (!notification) {
+ ret = -1;
+ goto error;
+ }
+
+ pending_notification->notification = notification;
+ cds_list_add(&pending_notification->node,
+ &channel->pending_notifications.list);
+ channel->pending_notifications.count++;
+end:
+ return ret;
+error:
+ free(pending_notification);
+ goto end;
+}
+
+static
+int receive_command_reply(struct lttng_notification_channel *channel,
+ enum lttng_notification_channel_status *status)
+{
+ int ret;
+ struct lttng_notification_channel_command_reply *reply;
+
+ while (true) {
+ enum lttng_notification_channel_message_type msg_type;
+
+ ret = receive_message(channel);
+ if (ret) {
+ goto end;
+ }
+
+ msg_type = get_current_message_type(channel);
+ switch (msg_type) {
+ case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_COMMAND_REPLY:
+ goto exit_loop;
+ case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION:
+ ret = enqueue_notification_from_current_message(
+ channel);
+ if (ret) {
+ goto end;
+ }
+ break;
+ case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED:
+ ret = enqueue_dropped_notification(channel);
+ if (ret) {
+ goto end;
+ }
+ break;
+ case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE:
+ {
+ struct lttng_notification_channel_command_handshake *handshake;
+
+ handshake = (struct lttng_notification_channel_command_handshake *)
+ (channel->reception_buffer.data +
+ sizeof(struct lttng_notification_channel_message));
+ channel->version.major = handshake->major;
+ channel->version.minor = handshake->minor;
+ channel->version.set = true;
+ break;
+ }
+ default:
+ ret = -1;
+ goto end;
+ }
+ }
+
+exit_loop:
+ if (channel->reception_buffer.size <
+ (sizeof(struct lttng_notification_channel_message) +
+ sizeof(*reply))) {
+ /* Invalid message received. */
+ ret = -1;
+ goto end;
+ }
+
+ reply = (struct lttng_notification_channel_command_reply *)
+ (channel->reception_buffer.data +
+ sizeof(struct lttng_notification_channel_message));
+ *status = (enum lttng_notification_channel_status) reply->status;
+end:
+ return ret;
+}
+
+static
+int handshake(struct lttng_notification_channel *channel)
+{
+ ssize_t ret;
+ enum lttng_notification_channel_status status =
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
+ struct lttng_notification_channel_command_handshake handshake = {
+ .major = LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR,
+ .minor = LTTNG_NOTIFICATION_CHANNEL_VERSION_MINOR,
+ };
+ struct lttng_notification_channel_message msg_header = {
+ .type = LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE,
+ .size = sizeof(handshake),
+ };
+ char send_buffer[sizeof(msg_header) + sizeof(handshake)];
+
+ memcpy(send_buffer, &msg_header, sizeof(msg_header));
+ memcpy(send_buffer + sizeof(msg_header), &handshake, sizeof(handshake));
+
+ pthread_mutex_lock(&channel->lock);
+
+ ret = lttcomm_send_unix_sock(channel->socket, send_buffer,
+ sizeof(send_buffer));
+ if (ret < 0) {
+ goto end_unlock;
+ }
+
+ /* Receive handshake info from the sessiond. */
+ ret = receive_command_reply(channel, &status);
+ if (ret < 0) {
+ goto end_unlock;
+ }
+
+ if (!channel->version.set) {
+ ret = -1;
+ goto end_unlock;
+ }
+
+ if (channel->version.major != LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR) {
+ ret = -1;
+ goto end_unlock;
+ }
+
+end_unlock:
+ pthread_mutex_unlock(&channel->lock);
+ return ret;
+}
+
+static
+enum lttng_notification_channel_status send_condition_command(
+ struct lttng_notification_channel *channel,
+ enum lttng_notification_channel_message_type type,
+ const struct lttng_condition *condition)
+{
+ int socket;
+ ssize_t command_size, ret;
+ enum lttng_notification_channel_status status =
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
+ char *command_buffer = NULL;
+ struct lttng_notification_channel_message cmd_message = {
+ .type = type,
+ };
+
+ if (!channel) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
+ goto end;
+ }
+
+ assert(type == LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE ||
+ type == LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE);
+
+ pthread_mutex_lock(&channel->lock);
+ socket = channel->socket;
+ if (!lttng_condition_validate(condition)) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
+ goto end_unlock;
+ }
+
+ ret = lttng_condition_serialize(condition, NULL);
+ if (ret < 0) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
+ goto end_unlock;
+ }
+ assert(ret < UINT32_MAX);
+ cmd_message.size = (uint32_t) ret;
+ command_size = ret + sizeof(
+ struct lttng_notification_channel_message);
+ command_buffer = zmalloc(command_size);
+ if (!command_buffer) {
+ goto end_unlock;
+ }
+
+ memcpy(command_buffer, &cmd_message, sizeof(cmd_message));
+ ret = lttng_condition_serialize(condition,
+ command_buffer + sizeof(cmd_message));
+ if (ret < 0) {
+ goto end_unlock;
+ }
+
+ ret = lttcomm_send_unix_sock(socket, command_buffer, command_size);
+ if (ret < 0) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_unlock;
+ }
+
+ ret = receive_command_reply(channel, &status);
+ if (ret < 0) {
+ status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
+ goto end_unlock;
+ }
+end_unlock:
+ pthread_mutex_unlock(&channel->lock);
+end:
+ free(command_buffer);
+ return status;
+}
+
+enum lttng_notification_channel_status lttng_notification_channel_subscribe(
+ struct lttng_notification_channel *channel,
+ const struct lttng_condition *condition)
+{
+ return send_condition_command(channel,
+ LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE,
+ condition);
+}
+
+enum lttng_notification_channel_status lttng_notification_channel_unsubscribe(
+ struct lttng_notification_channel *channel,
+ const struct lttng_condition *condition)
+{
+ return send_condition_command(channel,
+ LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE,
+ condition);
+}
+
+void lttng_notification_channel_destroy(
+ struct lttng_notification_channel *channel)
+{
+ if (!channel) {
+ return;
+ }
+
+ if (channel->socket >= 0) {
+ (void) lttcomm_close_unix_sock(channel->socket);
+ }
+ pthread_mutex_destroy(&channel->lock);
+ lttng_dynamic_buffer_reset(&channel->reception_buffer);
+ free(channel);
+}
#include <common/utils.h>
#include <lttng/lttng.h>
#include <lttng/health-internal.h>
+#include <lttng/trigger/trigger-internal.h>
+#include <lttng/endpoint.h>
+#include <lttng/channel-internal.h>
#include "filter/filter-ast.h"
#include "filter/filter-parser.h"
return ret;
}
+int lttng_register_trigger(struct lttng_trigger *trigger)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+ char *trigger_buf = NULL;
+ ssize_t trigger_size;
+
+ if (!trigger) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (!lttng_trigger_validate(trigger)) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ trigger_size = lttng_trigger_serialize(trigger, NULL);
+ if (trigger_size < 0) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ trigger_buf = zmalloc(trigger_size);
+ if (!trigger_buf) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_REGISTER_TRIGGER;
+ if (lttng_trigger_serialize(trigger, trigger_buf) < 0) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ lsm.u.trigger.length = (uint32_t) trigger_size;
+ ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, trigger_buf,
+ trigger_size, NULL);
+end:
+ free(trigger_buf);
+ return ret;
+}
+
+int lttng_unregister_trigger(struct lttng_trigger *trigger)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+ char *trigger_buf = NULL;
+ ssize_t trigger_size;
+
+ if (!trigger) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (!lttng_trigger_validate(trigger)) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ trigger_size = lttng_trigger_serialize(trigger, NULL);
+ if (trigger_size < 0) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ trigger_buf = zmalloc(trigger_size);
+ if (!trigger_buf) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_UNREGISTER_TRIGGER;
+ if (lttng_trigger_serialize(trigger, trigger_buf) < 0) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ lsm.u.trigger.length = (uint32_t) trigger_size;
+ ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, trigger_buf,
+ trigger_size, NULL);
+end:
+ free(trigger_buf);
+ return ret;
+}
+
/*
* lib constructor.
*/