lttng-ctl: Implement the buffer usage condition interface
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Mon, 27 Feb 2017 22:47:40 +0000 (17:47 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Wed, 1 Mar 2017 04:02:50 +0000 (23:02 -0500)
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
include/Makefile.am
include/lttng/condition/buffer-usage-internal.h [new file with mode: 0644]
src/common/macros.h
src/lib/lttng-ctl/Makefile.am
src/lib/lttng-ctl/buffer-usage.c [new file with mode: 0644]

index a784c081b0fd93ee13a83ad57513747bc9bd89db..55f9ce25735fe06b92483b7a1e165db5adc0d93a 100644 (file)
@@ -86,4 +86,6 @@ noinst_HEADERS = \
        lttng/load-internal.h \
        lttng/action/action-internal.h \
        lttng/action/notify-internal.h \
-       lttng/condition/condition-internal.h
+       lttng/condition/condition-internal.h \
+       lttng/condition/buffer-usage-internal.h
+
diff --git a/include/lttng/condition/buffer-usage-internal.h b/include/lttng/condition/buffer-usage-internal.h
new file mode 100644 (file)
index 0000000..dfe9608
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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/domain.h>
+
+struct lttng_condition_buffer_usage {
+       struct lttng_condition parent;
+       bool frozen;
+       struct {
+               bool set;
+               uint64_t value;
+       } threshold_bytes;
+       struct {
+               bool set;
+               double value;
+       } threshold_percent;
+       char *session_name;
+       char *channel_name;
+       struct {
+               bool set;
+               enum lttng_domain_type type;
+       } domain;
+};
+
+#endif /* LTTNG_CONDITION_BUFFER_USAGE_INTERNAL_H */
index 90849ed30ae5e543a577f9214bc33152864751f8..7eaf27cdf3787cbf02d5c4fc2bc48eb43632b734 100644 (file)
@@ -20,6 +20,7 @@
 #define _MACROS_H
 
 #include <stdlib.h>
+#include <stddef.h>
 #include <string.h>
 #include <common/compat/string.h>
 
@@ -58,6 +59,14 @@ void *zmalloc(size_t len)
 #define ARRAY_SIZE(array)   (sizeof(array) / (sizeof((array)[0])))
 #endif
 
+#ifndef container_of
+#define container_of(ptr, type, member)                                        \
+       ({                                                              \
+               const typeof(((type *)NULL)->member) * __ptr = (ptr);   \
+               (type *)((char *)__ptr - offsetof(type, member));       \
+       })
+#endif
+
 #ifndef max
 #define max(a, b) ((a) > (b) ? (a) : (b))
 #endif
index a939d2c837fb6290f897240b8a303cd84619d7c5..e339fa207d03470b7ad028c66582f3fa98b20654 100644 (file)
@@ -6,7 +6,7 @@ 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 \
-               action.c notify.c condition.c
+               action.c notify.c condition.c buffer-usage.c
 
 liblttng_ctl_la_LDFLAGS = \
                $(LT_NO_UNDEFINED)
diff --git a/src/lib/lttng-ctl/buffer-usage.c b/src/lib/lttng-ctl/buffer-usage.c
new file mode 100644 (file)
index 0000000..aaa5f2a
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ * 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 <assert.h>
+
+static
+bool is_usage_condition(struct lttng_condition *condition)
+{
+       enum lttng_condition_type type = lttng_condition_get_type(condition);
+
+       return type == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW ||
+                       type == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH;
+}
+
+static
+bool is_usage_condition(struct lttng_condition *condition)
+{
+       return is_low_usage_condition(condition) ||
+                       is_high_usage_condition(condition);
+}
+
+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(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) {
+               goto end;
+       }
+       if (!usage->channel_name) {
+               goto end;
+       }
+       if (!usage->threshold_percent.set && !usage->threshold_bytes.set) {
+               goto end;
+       }
+
+       valid = true;
+end:
+       return valid;
+}
+
+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;
+       }
+
+       condition->parent.type = type;
+       condition->parent.validate = lttng_condition_buffer_usage_validate;
+       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);
+}
+
+enum lttng_condition_status
+lttng_condition_buffer_usage_get_threshold_percentage(
+               struct lttng_condition *condition, double *threshold_percent)
+{
+       struct lttng_condition_buffer_usage *usage;
+       enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
+
+       if (!condition || !is_usage_condition(condition) ||
+                       !threshold_percent) {
+               status = LTTNG_CONDITION_STATUS_INVALID;
+               goto end;
+       }
+
+       usage = container_of(condition, struct lttng_condition_buffer_usage,
+                       parent);
+       if (!usage->threshold_percent.set) {
+               status = LTTNG_CONDITION_STATUS_UNSET;
+               goto end;
+       }
+       *threshold_percent = usage->threshold_percent.value;
+end:
+       return status;
+}
+
+/* threshold_percent expressed as [0.0, 1.0]. */
+enum lttng_condition_status
+lttng_condition_buffer_usage_set_threshold_percentage(
+               struct lttng_condition *condition, double threshold_percent)
+{
+       struct lttng_condition_buffer_usage *usage;
+       enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
+
+       if (!condition || !is_usage_condition(condition) ||
+               threshold_percent < 0.0 || threshold_percent > 1.0) {
+               status = LTTNG_CONDITION_STATUS_INVALID;
+               goto end;
+       }
+
+       usage = container_of(condition, struct lttng_condition_buffer_usage,
+                       parent);
+       usage->threshold_percent.set = true;
+       usage->threshold_bytes.set = false;
+       usage->threshold_percent.value = threshold_percent;
+end:
+       return status;
+}
+
+enum lttng_condition_status
+lttng_condition_buffer_usage_get_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) || !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_percent.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(
+               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;
+}
+
+extern enum lttng_condition_status
+lttng_condition_buffer_usage_set_session_name(
+               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 ||
+                       strlen(session_name) == 0) {
+               status = LTTNG_CONDITION_STATUS_INVALID;
+               goto end;
+       }
+
+       usage = container_of(condition, struct lttng_condition_buffer_usage,
+                       parent);
+       usage->session_name = strdup(session_name);
+       if (!usage->session_name) {
+               status = LTTNG_CONDITION_STATUS_ERROR;
+               goto end;
+       }
+end:
+       return status;
+}
+
+enum lttng_condition_status
+lttng_condition_buffer_usage_get_channel_name(
+               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;
+}
+
+extern enum lttng_condition_status
+lttng_condition_buffer_usage_set_channel_name(
+               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 ||
+                       strlen(channel_name) == 0) {
+               status = LTTNG_CONDITION_STATUS_INVALID;
+               goto end;
+       }
+
+       usage = container_of(condition, struct lttng_condition_buffer_usage,
+                       parent);
+       usage->channel_name = strdup(channel_name);
+       if (!usage->channel_name) {
+               status = LTTNG_CONDITION_STATUS_ERROR;
+               goto end;
+       }
+end:
+       return status;
+}
+
+extern enum lttng_condition_status
+lttng_condition_buffer_usage_get_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) {
+               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;
+}
+
+extern 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;
+}
This page took 0.039362 seconds and 5 git commands to generate.