From: Jérémie Galarneau Date: Mon, 27 Feb 2017 22:47:40 +0000 (-0500) Subject: lttng-ctl: Implement the buffer usage condition interface X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=commitdiff_plain;h=f42dcd79def021f1a1a40508db91258f9517e033 lttng-ctl: Implement the buffer usage condition interface Signed-off-by: Jérémie Galarneau --- diff --git a/include/Makefile.am b/include/Makefile.am index a784c081b..55f9ce257 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -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 index 000000000..dfe9608df --- /dev/null +++ b/include/lttng/condition/buffer-usage-internal.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2017 - Jérémie Galarneau + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License, version 2.1 only, + * as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LTTNG_CONDITION_BUFFER_USAGE_INTERNAL_H +#define LTTNG_CONDITION_BUFFER_USAGE_INTERNAL_H + +#include +#include +#include + +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 */ diff --git a/src/common/macros.h b/src/common/macros.h index 90849ed30..7eaf27cdf 100644 --- a/src/common/macros.h +++ b/src/common/macros.h @@ -20,6 +20,7 @@ #define _MACROS_H #include +#include #include #include @@ -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 diff --git a/src/lib/lttng-ctl/Makefile.am b/src/lib/lttng-ctl/Makefile.am index a939d2c83..e339fa207 100644 --- a/src/lib/lttng-ctl/Makefile.am +++ b/src/lib/lttng-ctl/Makefile.am @@ -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 index 000000000..aaa5f2a9d --- /dev/null +++ b/src/lib/lttng-ctl/buffer-usage.c @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2017 - Jérémie Galarneau + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License, version 2.1 only, + * as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +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; +}