From: Jonathan Rajotte Date: Tue, 3 Dec 2019 21:07:34 +0000 (-0500) Subject: Move conditions source files to src/common/conditions directory X-Git-Tag: v2.13.0-rc1~414 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=ae20d1bd206b317393846accdc45082d7c37b571;p=lttng-tools.git Move conditions source files to src/common/conditions directory Signed-off-by: Jonathan Rajotte Signed-off-by: Jérémie Galarneau Change-Id: I43165eacf82a1bf537e7187313664e32ca2833a9 --- diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 0376e59d2..9df1790fb 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -34,10 +34,12 @@ libcommon_la_SOURCES = \ actions/snapshot-session.c \ actions/start-session.c \ actions/stop-session.c \ - buffer-usage.c \ buffer-view.h buffer-view.c \ common.h \ - condition.c \ + conditions/buffer-usage.c \ + conditions/condition.c \ + conditions/session-consumed-size.c \ + conditions/session-rotation.c \ context.c context.h \ credentials.c credentials.h \ daemonize.c daemonize.h \ @@ -68,9 +70,7 @@ libcommon_la_SOURCES = \ pipe.c pipe.h \ readwrite.c readwrite.h \ runas.c runas.h \ - session-consumed-size.c \ session-descriptor.c \ - session-rotation.c \ snapshot.c snapshot.h \ spawn-viewer.c spawn-viewer.h \ time.c \ diff --git a/src/common/buffer-usage.c b/src/common/buffer-usage.c deleted file mode 100644 index 5f6860800..000000000 --- a/src/common/buffer-usage.c +++ /dev/null @@ -1,826 +0,0 @@ -/* - * Copyright (C) 2017 Jérémie Galarneau - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#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; - } - if (!usage->domain.set) { - ERR("Invalid buffer usage condition: a domain must be set."); - goto end; - } - - valid = true; -end: - return valid; -} - -static -int lttng_condition_buffer_usage_serialize( - const struct lttng_condition *condition, - struct lttng_payload *payload) -{ - int ret; - struct lttng_condition_buffer_usage *usage; - size_t session_name_len, channel_name_len; - struct lttng_condition_buffer_usage_comm usage_comm; - - 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); - - 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; - } - - usage_comm.threshold_set_in_bytes = !!usage->threshold_bytes.set; - usage_comm.session_name_len = session_name_len; - usage_comm.channel_name_len = channel_name_len; - usage_comm.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; - } - - ret = lttng_dynamic_buffer_append(&payload->buffer, &usage_comm, - sizeof(usage_comm)); - if (ret) { - goto end; - } - - ret = lttng_dynamic_buffer_append(&payload->buffer, usage->session_name, - session_name_len); - if (ret) { - goto end; - } - - ret = lttng_dynamic_buffer_append(&payload->buffer, usage->channel_name, - channel_name_len); - if (ret) { - goto end; - } -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; - } - } - - /* Condition is not valid if this is not true. */ - assert(a->session_name); - assert(b->session_name); - if (strcmp(a->session_name, b->session_name)) { - goto end; - } - - assert(a->channel_name); - assert(b->channel_name); - if (strcmp(a->channel_name, b->channel_name)) { - goto end; - } - - assert(a->domain.set); - assert(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) { - return NULL; - } - - 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; - 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_payload(struct lttng_condition *condition, - struct lttng_payload_view *src_view) -{ - ssize_t ret, condition_size; - enum lttng_condition_status status; - enum lttng_domain_type domain_type; - const char *session_name, *channel_name; - struct lttng_buffer_view names_view; - const struct lttng_condition_buffer_usage_comm *condition_comm; - const struct lttng_payload_view condition_comm_view = - lttng_payload_view_from_view( - src_view, 0, sizeof(*condition_comm)); - - if (!lttng_payload_view_is_valid(&condition_comm_view)) { - ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header"); - ret = -1; - goto end; - } - - condition_comm = (typeof(condition_comm)) condition_comm_view.buffer.data; - names_view = lttng_buffer_view_from_view(&src_view->buffer, - 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_payload( - struct lttng_payload_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_payload(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_payload( - struct lttng_payload_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_payload(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_payload( - enum lttng_condition_type type, - struct lttng_payload_view *view) -{ - const struct lttng_evaluation_buffer_usage_comm *comm = - (typeof(comm)) view->buffer.data; - struct lttng_evaluation *evaluation = NULL; - - if (view->buffer.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_payload( - struct lttng_payload_view *view, - struct lttng_evaluation **_evaluation) -{ - ssize_t ret; - struct lttng_evaluation *evaluation = NULL; - - if (!_evaluation) { - ret = -1; - goto error; - } - - evaluation = create_evaluation_from_payload( - 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_payload( - struct lttng_payload_view *view, - struct lttng_evaluation **_evaluation) -{ - ssize_t ret; - struct lttng_evaluation *evaluation = NULL; - - if (!_evaluation) { - ret = -1; - goto error; - } - - evaluation = create_evaluation_from_payload( - 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 -int lttng_evaluation_buffer_usage_serialize( - const struct lttng_evaluation *evaluation, - struct lttng_payload *payload) -{ - struct lttng_evaluation_buffer_usage *usage; - struct lttng_evaluation_buffer_usage_comm comm; - - usage = container_of(evaluation, struct lttng_evaluation_buffer_usage, - parent); - comm.buffer_use = usage->buffer_use; - comm.buffer_capacity = usage->buffer_capacity; - - return lttng_dynamic_buffer_append( - &payload->buffer, &comm, sizeof(comm)); -} - -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; -} diff --git a/src/common/condition.c b/src/common/condition.c deleted file mode 100644 index cffe6cf5e..000000000 --- a/src/common/condition.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2017 Jérémie Galarneau - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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) -{ - lttng_condition_put(condition); -} - -static void condition_destroy_ref(struct urcu_ref *ref) -{ - struct lttng_condition *condition = - container_of(ref, struct lttng_condition, ref); - - condition->destroy(condition); -} - -LTTNG_HIDDEN -void lttng_condition_get(struct lttng_condition *condition) -{ - urcu_ref_get(&condition->ref); -} - -LTTNG_HIDDEN -void lttng_condition_put(struct lttng_condition *condition) -{ - if (!condition) { - return; - } - - assert(condition->destroy); - urcu_ref_put(&condition->ref, condition_destroy_ref); -} - - -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 -int lttng_condition_serialize(const struct lttng_condition *condition, - struct lttng_payload *payload) -{ - int ret; - struct lttng_condition_comm condition_comm = {}; - - if (!condition) { - ret = -1; - goto end; - } - - condition_comm.condition_type = (int8_t) condition->type; - - ret = lttng_dynamic_buffer_append(&payload->buffer, &condition_comm, - sizeof(condition_comm)); - if (ret) { - goto end; - } - - ret = condition->serialize(condition, payload); - if (ret) { - goto end; - } -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; - } - - if (a == b) { - is_equal = true; - goto end; - } - - is_equal = a->equal ? a->equal(a, b) : true; -end: - return is_equal; -} - -LTTNG_HIDDEN -ssize_t lttng_condition_create_from_payload( - struct lttng_payload_view *view, - struct lttng_condition **condition) -{ - ssize_t ret, condition_size = 0; - condition_create_from_payload_cb create_from_payload = NULL; - const struct lttng_condition_comm *condition_comm; - const struct lttng_payload_view condition_comm_view = - lttng_payload_view_from_view( - view, 0, sizeof(*condition_comm)); - - if (!view || !condition) { - ret = -1; - goto end; - } - - if (!lttng_payload_view_is_valid(&condition_comm_view)) { - /* Payload not large enough to contain the header. */ - ret = -1; - goto end; - } - - DBG("Deserializing condition from buffer"); - condition_comm = (typeof(condition_comm)) condition_comm_view.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_payload = lttng_condition_buffer_usage_low_create_from_payload; - break; - case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH: - create_from_payload = lttng_condition_buffer_usage_high_create_from_payload; - break; - case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE: - create_from_payload = lttng_condition_session_consumed_size_create_from_payload; - break; - case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING: - create_from_payload = lttng_condition_session_rotation_ongoing_create_from_payload; - break; - case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED: - create_from_payload = lttng_condition_session_rotation_completed_create_from_payload; - break; - default: - ERR("Attempted to create condition of unknown type (%i)", - (int) condition_comm->condition_type); - ret = -1; - goto end; - } - - if (create_from_payload) { - struct lttng_payload_view condition_view = - lttng_payload_view_from_view(view, - sizeof(*condition_comm), -1); - - ret = create_from_payload(&condition_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; - urcu_ref_init(&condition->ref); -} diff --git a/src/common/conditions/buffer-usage.c b/src/common/conditions/buffer-usage.c new file mode 100644 index 000000000..5f6860800 --- /dev/null +++ b/src/common/conditions/buffer-usage.c @@ -0,0 +1,826 @@ +/* + * Copyright (C) 2017 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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; + } + if (!usage->domain.set) { + ERR("Invalid buffer usage condition: a domain must be set."); + goto end; + } + + valid = true; +end: + return valid; +} + +static +int lttng_condition_buffer_usage_serialize( + const struct lttng_condition *condition, + struct lttng_payload *payload) +{ + int ret; + struct lttng_condition_buffer_usage *usage; + size_t session_name_len, channel_name_len; + struct lttng_condition_buffer_usage_comm usage_comm; + + 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); + + 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; + } + + usage_comm.threshold_set_in_bytes = !!usage->threshold_bytes.set; + usage_comm.session_name_len = session_name_len; + usage_comm.channel_name_len = channel_name_len; + usage_comm.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; + } + + ret = lttng_dynamic_buffer_append(&payload->buffer, &usage_comm, + sizeof(usage_comm)); + if (ret) { + goto end; + } + + ret = lttng_dynamic_buffer_append(&payload->buffer, usage->session_name, + session_name_len); + if (ret) { + goto end; + } + + ret = lttng_dynamic_buffer_append(&payload->buffer, usage->channel_name, + channel_name_len); + if (ret) { + goto end; + } +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; + } + } + + /* Condition is not valid if this is not true. */ + assert(a->session_name); + assert(b->session_name); + if (strcmp(a->session_name, b->session_name)) { + goto end; + } + + assert(a->channel_name); + assert(b->channel_name); + if (strcmp(a->channel_name, b->channel_name)) { + goto end; + } + + assert(a->domain.set); + assert(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) { + return NULL; + } + + 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; + 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_payload(struct lttng_condition *condition, + struct lttng_payload_view *src_view) +{ + ssize_t ret, condition_size; + enum lttng_condition_status status; + enum lttng_domain_type domain_type; + const char *session_name, *channel_name; + struct lttng_buffer_view names_view; + const struct lttng_condition_buffer_usage_comm *condition_comm; + const struct lttng_payload_view condition_comm_view = + lttng_payload_view_from_view( + src_view, 0, sizeof(*condition_comm)); + + if (!lttng_payload_view_is_valid(&condition_comm_view)) { + ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header"); + ret = -1; + goto end; + } + + condition_comm = (typeof(condition_comm)) condition_comm_view.buffer.data; + names_view = lttng_buffer_view_from_view(&src_view->buffer, + 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_payload( + struct lttng_payload_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_payload(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_payload( + struct lttng_payload_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_payload(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_payload( + enum lttng_condition_type type, + struct lttng_payload_view *view) +{ + const struct lttng_evaluation_buffer_usage_comm *comm = + (typeof(comm)) view->buffer.data; + struct lttng_evaluation *evaluation = NULL; + + if (view->buffer.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_payload( + struct lttng_payload_view *view, + struct lttng_evaluation **_evaluation) +{ + ssize_t ret; + struct lttng_evaluation *evaluation = NULL; + + if (!_evaluation) { + ret = -1; + goto error; + } + + evaluation = create_evaluation_from_payload( + 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_payload( + struct lttng_payload_view *view, + struct lttng_evaluation **_evaluation) +{ + ssize_t ret; + struct lttng_evaluation *evaluation = NULL; + + if (!_evaluation) { + ret = -1; + goto error; + } + + evaluation = create_evaluation_from_payload( + 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 +int lttng_evaluation_buffer_usage_serialize( + const struct lttng_evaluation *evaluation, + struct lttng_payload *payload) +{ + struct lttng_evaluation_buffer_usage *usage; + struct lttng_evaluation_buffer_usage_comm comm; + + usage = container_of(evaluation, struct lttng_evaluation_buffer_usage, + parent); + comm.buffer_use = usage->buffer_use; + comm.buffer_capacity = usage->buffer_capacity; + + return lttng_dynamic_buffer_append( + &payload->buffer, &comm, sizeof(comm)); +} + +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; +} diff --git a/src/common/conditions/condition.c b/src/common/conditions/condition.c new file mode 100644 index 000000000..cffe6cf5e --- /dev/null +++ b/src/common/conditions/condition.c @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2017 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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) +{ + lttng_condition_put(condition); +} + +static void condition_destroy_ref(struct urcu_ref *ref) +{ + struct lttng_condition *condition = + container_of(ref, struct lttng_condition, ref); + + condition->destroy(condition); +} + +LTTNG_HIDDEN +void lttng_condition_get(struct lttng_condition *condition) +{ + urcu_ref_get(&condition->ref); +} + +LTTNG_HIDDEN +void lttng_condition_put(struct lttng_condition *condition) +{ + if (!condition) { + return; + } + + assert(condition->destroy); + urcu_ref_put(&condition->ref, condition_destroy_ref); +} + + +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 +int lttng_condition_serialize(const struct lttng_condition *condition, + struct lttng_payload *payload) +{ + int ret; + struct lttng_condition_comm condition_comm = {}; + + if (!condition) { + ret = -1; + goto end; + } + + condition_comm.condition_type = (int8_t) condition->type; + + ret = lttng_dynamic_buffer_append(&payload->buffer, &condition_comm, + sizeof(condition_comm)); + if (ret) { + goto end; + } + + ret = condition->serialize(condition, payload); + if (ret) { + goto end; + } +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; + } + + if (a == b) { + is_equal = true; + goto end; + } + + is_equal = a->equal ? a->equal(a, b) : true; +end: + return is_equal; +} + +LTTNG_HIDDEN +ssize_t lttng_condition_create_from_payload( + struct lttng_payload_view *view, + struct lttng_condition **condition) +{ + ssize_t ret, condition_size = 0; + condition_create_from_payload_cb create_from_payload = NULL; + const struct lttng_condition_comm *condition_comm; + const struct lttng_payload_view condition_comm_view = + lttng_payload_view_from_view( + view, 0, sizeof(*condition_comm)); + + if (!view || !condition) { + ret = -1; + goto end; + } + + if (!lttng_payload_view_is_valid(&condition_comm_view)) { + /* Payload not large enough to contain the header. */ + ret = -1; + goto end; + } + + DBG("Deserializing condition from buffer"); + condition_comm = (typeof(condition_comm)) condition_comm_view.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_payload = lttng_condition_buffer_usage_low_create_from_payload; + break; + case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH: + create_from_payload = lttng_condition_buffer_usage_high_create_from_payload; + break; + case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE: + create_from_payload = lttng_condition_session_consumed_size_create_from_payload; + break; + case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING: + create_from_payload = lttng_condition_session_rotation_ongoing_create_from_payload; + break; + case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED: + create_from_payload = lttng_condition_session_rotation_completed_create_from_payload; + break; + default: + ERR("Attempted to create condition of unknown type (%i)", + (int) condition_comm->condition_type); + ret = -1; + goto end; + } + + if (create_from_payload) { + struct lttng_payload_view condition_view = + lttng_payload_view_from_view(view, + sizeof(*condition_comm), -1); + + ret = create_from_payload(&condition_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; + urcu_ref_init(&condition->ref); +} diff --git a/src/common/conditions/session-consumed-size.c b/src/common/conditions/session-consumed-size.c new file mode 100644 index 000000000..e147d1e5f --- /dev/null +++ b/src/common/conditions/session-consumed-size.c @@ -0,0 +1,460 @@ +/* + * Copyright (C) 2017 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IS_CONSUMED_SIZE_CONDITION(condition) ( \ + lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE \ + ) + +#define IS_CONSUMED_SIZE_EVALUATION(evaluation) ( \ + lttng_evaluation_get_type(evaluation) == LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE \ + ) + +static +void lttng_condition_session_consumed_size_destroy(struct lttng_condition *condition) +{ + struct lttng_condition_session_consumed_size *consumed_size; + + consumed_size = container_of(condition, + struct lttng_condition_session_consumed_size, parent); + + free(consumed_size->session_name); + free(consumed_size); +} + +static +bool lttng_condition_session_consumed_size_validate( + const struct lttng_condition *condition) +{ + bool valid = false; + struct lttng_condition_session_consumed_size *consumed; + + if (!condition) { + goto end; + } + + consumed = container_of(condition, struct lttng_condition_session_consumed_size, + parent); + if (!consumed->session_name) { + ERR("Invalid session consumed size condition: a target session name must be set."); + goto end; + } + if (!consumed->consumed_threshold_bytes.set) { + ERR("Invalid session consumed size condition: a threshold must be set."); + goto end; + } + + valid = true; +end: + return valid; +} + +static +int lttng_condition_session_consumed_size_serialize( + const struct lttng_condition *condition, + struct lttng_payload *payload) +{ + int ret; + size_t session_name_len; + struct lttng_condition_session_consumed_size *consumed; + struct lttng_condition_session_consumed_size_comm consumed_comm; + + if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition)) { + ret = -1; + goto end; + } + + DBG("Serializing session consumed size condition"); + consumed = container_of(condition, + struct lttng_condition_session_consumed_size, + parent); + + session_name_len = strlen(consumed->session_name) + 1; + if (session_name_len > LTTNG_NAME_MAX) { + ret = -1; + goto end; + } + + consumed_comm.consumed_threshold_bytes = + consumed->consumed_threshold_bytes.value; + consumed_comm.session_name_len = (uint32_t) session_name_len; + + ret = lttng_dynamic_buffer_append(&payload->buffer, &consumed_comm, + sizeof(consumed_comm)); + if (ret) { + goto end; + } + + ret = lttng_dynamic_buffer_append(&payload->buffer, consumed->session_name, + session_name_len); + if (ret) { + goto end; + } +end: + return ret; +} + +static +bool lttng_condition_session_consumed_size_is_equal(const struct lttng_condition *_a, + const struct lttng_condition *_b) +{ + bool is_equal = false; + struct lttng_condition_session_consumed_size *a, *b; + + a = container_of(_a, struct lttng_condition_session_consumed_size, parent); + b = container_of(_b, struct lttng_condition_session_consumed_size, parent); + + if (a->consumed_threshold_bytes.set && b->consumed_threshold_bytes.set) { + uint64_t a_value, b_value; + + a_value = a->consumed_threshold_bytes.value; + b_value = b->consumed_threshold_bytes.value; + if (a_value != b_value) { + goto end; + } + } + + assert(a->session_name); + assert(b->session_name); + if (strcmp(a->session_name, b->session_name)) { + goto end; + } + + is_equal = true; +end: + return is_equal; +} + +struct lttng_condition *lttng_condition_session_consumed_size_create(void) +{ + struct lttng_condition_session_consumed_size *condition; + + condition = zmalloc(sizeof(struct lttng_condition_session_consumed_size)); + if (!condition) { + return NULL; + } + + lttng_condition_init(&condition->parent, LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE); + condition->parent.validate = lttng_condition_session_consumed_size_validate; + condition->parent.serialize = lttng_condition_session_consumed_size_serialize; + condition->parent.equal = lttng_condition_session_consumed_size_is_equal; + condition->parent.destroy = lttng_condition_session_consumed_size_destroy; + return &condition->parent; +} + +static +ssize_t init_condition_from_payload(struct lttng_condition *condition, + struct lttng_payload_view *src_view) +{ + ssize_t ret, condition_size; + enum lttng_condition_status status; + const char *session_name; + struct lttng_buffer_view session_name_view; + const struct lttng_condition_session_consumed_size_comm *condition_comm; + struct lttng_payload_view condition_comm_view = lttng_payload_view_from_view( + src_view, 0, sizeof(*condition_comm)); + + if (!lttng_payload_view_is_valid(&condition_comm_view)) { + ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header"); + ret = -1; + goto end; + } + + condition_comm = (typeof(condition_comm)) condition_comm_view.buffer.data; + session_name_view = lttng_buffer_view_from_view(&src_view->buffer, + sizeof(*condition_comm), condition_comm->session_name_len); + + if (condition_comm->session_name_len > LTTNG_NAME_MAX) { + ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME"); + ret = -1; + goto end; + } + + if (!lttng_buffer_view_is_valid(&session_name_view)) { + ERR("Failed to initialize from malformed condition buffer: buffer too short to contain element names"); + ret = -1; + goto end; + } + + status = lttng_condition_session_consumed_size_set_threshold(condition, + condition_comm->consumed_threshold_bytes); + if (status != LTTNG_CONDITION_STATUS_OK) { + ERR("Failed to initialize session consumed size condition threshold"); + ret = -1; + goto end; + } + + session_name = session_name_view.data; + if (*(session_name + condition_comm->session_name_len - 1) != '\0') { + ERR("Malformed session name encountered in condition buffer"); + ret = -1; + goto end; + } + + status = lttng_condition_session_consumed_size_set_session_name(condition, + session_name); + if (status != LTTNG_CONDITION_STATUS_OK) { + ERR("Failed to set session consumed size condition's session 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; + ret = condition_size; +end: + return ret; +} + +LTTNG_HIDDEN +ssize_t lttng_condition_session_consumed_size_create_from_payload( + struct lttng_payload_view *view, + struct lttng_condition **_condition) +{ + ssize_t ret; + struct lttng_condition *condition = + lttng_condition_session_consumed_size_create(); + + if (!_condition || !condition) { + ret = -1; + goto error; + } + + ret = init_condition_from_payload(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_payload( + const struct lttng_payload_view *view) +{ + const struct lttng_evaluation_session_consumed_size_comm *comm = + (typeof(comm)) view->buffer.data; + struct lttng_evaluation *evaluation = NULL; + + if (view->buffer.size < sizeof(*comm)) { + goto end; + } + + evaluation = lttng_evaluation_session_consumed_size_create( + comm->session_consumed); +end: + return evaluation; +} + +LTTNG_HIDDEN +ssize_t lttng_evaluation_session_consumed_size_create_from_payload( + struct lttng_payload_view *view, + struct lttng_evaluation **_evaluation) +{ + ssize_t ret; + struct lttng_evaluation *evaluation = NULL; + + if (!_evaluation) { + ret = -1; + goto error; + } + + evaluation = create_evaluation_from_payload(view); + if (!evaluation) { + ret = -1; + goto error; + } + + *_evaluation = evaluation; + ret = sizeof(struct lttng_evaluation_session_consumed_size_comm); + return ret; +error: + lttng_evaluation_destroy(evaluation); + return ret; +} + +enum lttng_condition_status +lttng_condition_session_consumed_size_get_threshold( + const struct lttng_condition *condition, + uint64_t *consumed_threshold_bytes) +{ + struct lttng_condition_session_consumed_size *consumed; + enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; + + if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition) || !consumed_threshold_bytes) { + status = LTTNG_CONDITION_STATUS_INVALID; + goto end; + } + + consumed = container_of(condition, struct lttng_condition_session_consumed_size, + parent); + if (!consumed->consumed_threshold_bytes.set) { + status = LTTNG_CONDITION_STATUS_UNSET; + goto end; + } + *consumed_threshold_bytes = consumed->consumed_threshold_bytes.value; +end: + return status; +} + +enum lttng_condition_status +lttng_condition_session_consumed_size_set_threshold( + struct lttng_condition *condition, uint64_t consumed_threshold_bytes) +{ + struct lttng_condition_session_consumed_size *consumed; + enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; + + if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition)) { + status = LTTNG_CONDITION_STATUS_INVALID; + goto end; + } + + consumed = container_of(condition, struct lttng_condition_session_consumed_size, + parent); + consumed->consumed_threshold_bytes.set = true; + consumed->consumed_threshold_bytes.value = consumed_threshold_bytes; +end: + return status; +} + +enum lttng_condition_status +lttng_condition_session_consumed_size_get_session_name( + const struct lttng_condition *condition, + const char **session_name) +{ + struct lttng_condition_session_consumed_size *consumed; + enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; + + if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition) || !session_name) { + status = LTTNG_CONDITION_STATUS_INVALID; + goto end; + } + + consumed = container_of(condition, struct lttng_condition_session_consumed_size, + parent); + if (!consumed->session_name) { + status = LTTNG_CONDITION_STATUS_UNSET; + goto end; + } + *session_name = consumed->session_name; +end: + return status; +} + +enum lttng_condition_status +lttng_condition_session_consumed_size_set_session_name( + struct lttng_condition *condition, const char *session_name) +{ + char *session_name_copy; + struct lttng_condition_session_consumed_size *consumed; + enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; + + if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition) || + !session_name || strlen(session_name) == 0) { + status = LTTNG_CONDITION_STATUS_INVALID; + goto end; + } + + consumed = container_of(condition, struct lttng_condition_session_consumed_size, + parent); + session_name_copy = strdup(session_name); + if (!session_name_copy) { + status = LTTNG_CONDITION_STATUS_ERROR; + goto end; + } + + if (consumed->session_name) { + free(consumed->session_name); + } + consumed->session_name = session_name_copy; +end: + return status; +} + +static +int lttng_evaluation_session_consumed_size_serialize( + const struct lttng_evaluation *evaluation, + struct lttng_payload *payload) +{ + struct lttng_evaluation_session_consumed_size *consumed; + struct lttng_evaluation_session_consumed_size_comm comm; + + consumed = container_of(evaluation, + struct lttng_evaluation_session_consumed_size, parent); + comm.session_consumed = consumed->session_consumed; + return lttng_dynamic_buffer_append( + &payload->buffer, &comm, sizeof(comm)); +} + +static +void lttng_evaluation_session_consumed_size_destroy( + struct lttng_evaluation *evaluation) +{ + struct lttng_evaluation_session_consumed_size *consumed; + + consumed = container_of(evaluation, struct lttng_evaluation_session_consumed_size, + parent); + free(consumed); +} + +LTTNG_HIDDEN +struct lttng_evaluation *lttng_evaluation_session_consumed_size_create( + uint64_t consumed) +{ + struct lttng_evaluation_session_consumed_size *consumed_eval; + + consumed_eval = zmalloc(sizeof(struct lttng_evaluation_session_consumed_size)); + if (!consumed_eval) { + goto end; + } + + consumed_eval->parent.type = LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE; + consumed_eval->session_consumed = consumed; + consumed_eval->parent.serialize = lttng_evaluation_session_consumed_size_serialize; + consumed_eval->parent.destroy = lttng_evaluation_session_consumed_size_destroy; +end: + return &consumed_eval->parent; +} + +enum lttng_evaluation_status +lttng_evaluation_session_consumed_size_get_consumed_size( + const struct lttng_evaluation *evaluation, + uint64_t *session_consumed) +{ + struct lttng_evaluation_session_consumed_size *consumed; + enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK; + + if (!evaluation || !IS_CONSUMED_SIZE_EVALUATION(evaluation) || + !session_consumed) { + status = LTTNG_EVALUATION_STATUS_INVALID; + goto end; + } + + consumed = container_of(evaluation, struct lttng_evaluation_session_consumed_size, + parent); + *session_consumed = consumed->session_consumed; +end: + return status; +} diff --git a/src/common/conditions/session-rotation.c b/src/common/conditions/session-rotation.c new file mode 100644 index 000000000..7df5ebab0 --- /dev/null +++ b/src/common/conditions/session-rotation.c @@ -0,0 +1,588 @@ +/* + * Copyright (C) 2017 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#include +#include +#include +#include +#include +#include +#include + +static +bool lttng_condition_session_rotation_validate( + const struct lttng_condition *condition); +static +int lttng_condition_session_rotation_serialize( + const struct lttng_condition *condition, + struct lttng_payload *payload); +static +bool lttng_condition_session_rotation_is_equal(const struct lttng_condition *_a, + const struct lttng_condition *_b); +static +void lttng_condition_session_rotation_destroy( + struct lttng_condition *condition); + +static const +struct lttng_condition rotation_condition_template = { + /* .type omitted; shall be set on creation. */ + .validate = lttng_condition_session_rotation_validate, + .serialize = lttng_condition_session_rotation_serialize, + .equal = lttng_condition_session_rotation_is_equal, + .destroy = lttng_condition_session_rotation_destroy, +}; + +static +int lttng_evaluation_session_rotation_serialize( + const struct lttng_evaluation *evaluation, + struct lttng_payload *payload); +static +void lttng_evaluation_session_rotation_destroy( + struct lttng_evaluation *evaluation); + +static const +struct lttng_evaluation rotation_evaluation_template = { + /* .type omitted; shall be set on creation. */ + .serialize = lttng_evaluation_session_rotation_serialize, + .destroy = lttng_evaluation_session_rotation_destroy, +}; + +static +bool is_rotation_condition(const struct lttng_condition *condition) +{ + enum lttng_condition_type type = lttng_condition_get_type(condition); + + return type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING || + type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED; +} + +static +bool is_rotation_evaluation(const struct lttng_evaluation *evaluation) +{ + enum lttng_condition_type type = lttng_evaluation_get_type(evaluation); + + return type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING || + type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED; +} + +static +bool lttng_condition_session_rotation_validate( + const struct lttng_condition *condition) +{ + bool valid = false; + struct lttng_condition_session_rotation *rotation; + + if (!condition) { + goto end; + } + + rotation = container_of(condition, + struct lttng_condition_session_rotation, parent); + if (!rotation->session_name) { + ERR("Invalid session rotation condition: a target session name must be set."); + goto end; + } + + valid = true; +end: + return valid; +} + +static +int lttng_condition_session_rotation_serialize( + const struct lttng_condition *condition, + struct lttng_payload *payload) +{ + int ret; + size_t session_name_len; + struct lttng_condition_session_rotation *rotation; + struct lttng_condition_session_rotation_comm rotation_comm; + + if (!condition || !is_rotation_condition(condition)) { + ret = -1; + goto end; + } + + DBG("Serializing session rotation condition"); + rotation = container_of(condition, struct lttng_condition_session_rotation, + parent); + + session_name_len = strlen(rotation->session_name) + 1; + if (session_name_len > LTTNG_NAME_MAX) { + ret = -1; + goto end; + } + + rotation_comm.session_name_len = session_name_len; + ret = lttng_dynamic_buffer_append(&payload->buffer, &rotation_comm, + sizeof(rotation_comm)); + if (ret) { + goto end; + } + ret = lttng_dynamic_buffer_append(&payload->buffer, + rotation->session_name, session_name_len); + if (ret) { + goto end; + } +end: + return ret; +} + +static +bool lttng_condition_session_rotation_is_equal(const struct lttng_condition *_a, + const struct lttng_condition *_b) +{ + bool is_equal = false; + struct lttng_condition_session_rotation *a, *b; + + a = container_of(_a, struct lttng_condition_session_rotation, parent); + b = container_of(_b, struct lttng_condition_session_rotation, parent); + + /* Both session names must be set or both must be unset. */ + if ((a->session_name && !b->session_name) || + (!a->session_name && b->session_name)) { + WARN("Comparing session rotation conditions with uninitialized session names."); + goto end; + } + + if (a->session_name && b->session_name && + strcmp(a->session_name, b->session_name)) { + goto end; + } + + is_equal = true; +end: + return is_equal; +} + +static +void lttng_condition_session_rotation_destroy( + struct lttng_condition *condition) +{ + struct lttng_condition_session_rotation *rotation; + + rotation = container_of(condition, + struct lttng_condition_session_rotation, parent); + + free(rotation->session_name); + free(rotation); +} + +static +struct lttng_condition *lttng_condition_session_rotation_create( + enum lttng_condition_type type) +{ + struct lttng_condition_session_rotation *condition; + + condition = zmalloc(sizeof(struct lttng_condition_session_rotation)); + if (!condition) { + return NULL; + } + + memcpy(&condition->parent, &rotation_condition_template, + sizeof(condition->parent)); + lttng_condition_init(&condition->parent, type); + return &condition->parent; +} + +struct lttng_condition *lttng_condition_session_rotation_ongoing_create(void) +{ + return lttng_condition_session_rotation_create( + LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING); +} + +struct lttng_condition *lttng_condition_session_rotation_completed_create(void) +{ + return lttng_condition_session_rotation_create( + LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED); +} + +static +ssize_t init_condition_from_payload(struct lttng_condition *condition, + struct lttng_payload_view *src_view) +{ + ssize_t ret, condition_size; + enum lttng_condition_status status; + const char *session_name; + struct lttng_buffer_view name_view; + const struct lttng_condition_session_rotation_comm *condition_comm; + struct lttng_payload_view condition_comm_view = + lttng_payload_view_from_view( + src_view, 0, sizeof(*condition_comm)); + + if (!lttng_payload_view_is_valid(&condition_comm_view)) { + ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header"); + ret = -1; + goto end; + } + + condition_comm = (typeof(condition_comm)) src_view->buffer.data; + name_view = lttng_buffer_view_from_view(&src_view->buffer, + sizeof(*condition_comm), condition_comm->session_name_len); + + if (!lttng_buffer_view_is_valid(&name_view)) { + ERR("Failed to initialize from malformed condition buffer: buffer too short to contain session name"); + ret = -1; + goto end; + } + + if (condition_comm->session_name_len > LTTNG_NAME_MAX) { + ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME"); + ret = -1; + goto end; + } + + session_name = name_view.data; + if (*(session_name + condition_comm->session_name_len - 1) != '\0') { + ERR("Malformed session name encountered in condition buffer"); + ret = -1; + goto end; + } + + status = lttng_condition_session_rotation_set_session_name(condition, + session_name); + if (status != LTTNG_CONDITION_STATUS_OK) { + ERR("Failed to set buffer consumed session 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; + ret = condition_size; +end: + return ret; +} + +static +ssize_t lttng_condition_session_rotation_create_from_payload( + struct lttng_payload_view *view, + struct lttng_condition **_condition, + enum lttng_condition_type type) +{ + ssize_t ret; + struct lttng_condition *condition = NULL; + + switch (type) { + case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING: + condition = lttng_condition_session_rotation_ongoing_create(); + break; + case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED: + condition = lttng_condition_session_rotation_completed_create(); + break; + default: + ret = -1; + goto error; + } + + if (!_condition || !condition) { + ret = -1; + goto error; + } + + ret = init_condition_from_payload(condition, view); + if (ret < 0) { + goto error; + } + + *_condition = condition; + return ret; +error: + lttng_condition_destroy(condition); + return ret; +} + +LTTNG_HIDDEN +ssize_t lttng_condition_session_rotation_ongoing_create_from_payload( + struct lttng_payload_view *view, + struct lttng_condition **condition) +{ + return lttng_condition_session_rotation_create_from_payload(view, + condition, + LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING); +} + +LTTNG_HIDDEN +ssize_t lttng_condition_session_rotation_completed_create_from_payload( + struct lttng_payload_view *view, + struct lttng_condition **condition) +{ + return lttng_condition_session_rotation_create_from_payload(view, + condition, + LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED); +} + +static +struct lttng_evaluation *lttng_evaluation_session_rotation_create( + enum lttng_condition_type type, uint64_t id, + struct lttng_trace_archive_location *location) +{ + struct lttng_evaluation_session_rotation *evaluation; + + evaluation = zmalloc(sizeof(struct lttng_evaluation_session_rotation)); + if (!evaluation) { + return NULL; + } + + memcpy(&evaluation->parent, &rotation_evaluation_template, + sizeof(evaluation->parent)); + lttng_evaluation_init(&evaluation->parent, type); + evaluation->id = id; + evaluation->location = location; + return &evaluation->parent; +} + +static +ssize_t create_evaluation_from_payload( + enum lttng_condition_type type, + struct lttng_payload_view *view, + struct lttng_evaluation **_evaluation) +{ + ssize_t ret, size; + struct lttng_evaluation *evaluation = NULL; + struct lttng_trace_archive_location *location = NULL; + const struct lttng_evaluation_session_rotation_comm *comm; + struct lttng_payload_view comm_view = lttng_payload_view_from_view( + view, 0, sizeof(*comm)); + + if (!lttng_payload_view_is_valid(&comm_view)) { + goto error; + } + + comm = (typeof(comm)) comm_view.buffer.data; + size = sizeof(*comm); + if (comm->has_location) { + const struct lttng_buffer_view location_view = + lttng_buffer_view_from_view( + &view->buffer, sizeof(*comm), -1); + + if (!lttng_buffer_view_is_valid(&location_view)) { + goto error; + } + + ret = lttng_trace_archive_location_create_from_buffer( + &location_view, &location); + if (ret < 0) { + goto error; + } + size += ret; + } + + evaluation = lttng_evaluation_session_rotation_create(type, comm->id, + location); + if (!evaluation) { + goto error; + } + + ret = size; + *_evaluation = evaluation; + return ret; +error: + lttng_trace_archive_location_destroy(location); + evaluation = NULL; + return -1; +} + +static +ssize_t lttng_evaluation_session_rotation_create_from_payload( + enum lttng_condition_type type, + struct lttng_payload_view *view, + struct lttng_evaluation **_evaluation) +{ + ssize_t ret; + struct lttng_evaluation *evaluation = NULL; + + if (!_evaluation) { + ret = -1; + goto error; + } + + ret = create_evaluation_from_payload(type, view, &evaluation); + if (ret < 0) { + goto error; + } + + *_evaluation = evaluation; + return ret; +error: + lttng_evaluation_destroy(evaluation); + return ret; +} + +LTTNG_HIDDEN +ssize_t lttng_evaluation_session_rotation_ongoing_create_from_payload( + struct lttng_payload_view *view, + struct lttng_evaluation **evaluation) +{ + return lttng_evaluation_session_rotation_create_from_payload( + LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING, + view, evaluation); +} + +LTTNG_HIDDEN +ssize_t lttng_evaluation_session_rotation_completed_create_from_payload( + struct lttng_payload_view *view, + struct lttng_evaluation **evaluation) +{ + return lttng_evaluation_session_rotation_create_from_payload( + LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED, + view, evaluation); +} + +LTTNG_HIDDEN +struct lttng_evaluation *lttng_evaluation_session_rotation_ongoing_create( + uint64_t id) +{ + return lttng_evaluation_session_rotation_create( + LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING, id, + NULL); +} + +LTTNG_HIDDEN +struct lttng_evaluation *lttng_evaluation_session_rotation_completed_create( + uint64_t id, struct lttng_trace_archive_location *location) +{ + return lttng_evaluation_session_rotation_create( + LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED, id, + location); +} + +enum lttng_condition_status +lttng_condition_session_rotation_get_session_name( + const struct lttng_condition *condition, + const char **session_name) +{ + struct lttng_condition_session_rotation *rotation; + enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; + + if (!condition || !is_rotation_condition(condition) || !session_name) { + status = LTTNG_CONDITION_STATUS_INVALID; + goto end; + } + + rotation = container_of(condition, struct lttng_condition_session_rotation, + parent); + if (!rotation->session_name) { + status = LTTNG_CONDITION_STATUS_UNSET; + goto end; + } + *session_name = rotation->session_name; +end: + return status; +} + +enum lttng_condition_status +lttng_condition_session_rotation_set_session_name( + struct lttng_condition *condition, const char *session_name) +{ + char *session_name_copy; + struct lttng_condition_session_rotation *rotation; + enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; + + if (!condition || !is_rotation_condition(condition) || + !session_name || strlen(session_name) == 0) { + status = LTTNG_CONDITION_STATUS_INVALID; + goto end; + } + + rotation = container_of(condition, + struct lttng_condition_session_rotation, parent); + session_name_copy = strdup(session_name); + if (!session_name_copy) { + status = LTTNG_CONDITION_STATUS_ERROR; + goto end; + } + + free(rotation->session_name); + rotation->session_name = session_name_copy; +end: + return status; +} + +static +int lttng_evaluation_session_rotation_serialize( + const struct lttng_evaluation *evaluation, + struct lttng_payload *payload) +{ + int ret; + struct lttng_evaluation_session_rotation *rotation; + struct lttng_evaluation_session_rotation_comm comm = { 0 }; + + rotation = container_of(evaluation, + struct lttng_evaluation_session_rotation, parent); + comm.id = rotation->id; + comm.has_location = !!rotation->location; + ret = lttng_dynamic_buffer_append( + &payload->buffer, &comm, sizeof(comm)); + if (ret) { + goto end; + } + if (!rotation->location) { + goto end; + } + ret = lttng_trace_archive_location_serialize(rotation->location, + &payload->buffer); +end: + return ret; +} + +static +void lttng_evaluation_session_rotation_destroy( + struct lttng_evaluation *evaluation) +{ + struct lttng_evaluation_session_rotation *rotation; + + rotation = container_of(evaluation, + struct lttng_evaluation_session_rotation, parent); + lttng_trace_archive_location_destroy(rotation->location); + free(rotation); +} + +enum lttng_evaluation_status +lttng_evaluation_session_rotation_get_id( + const struct lttng_evaluation *evaluation, uint64_t *id) +{ + const struct lttng_evaluation_session_rotation *rotation; + enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK; + + if (!evaluation || !id || !is_rotation_evaluation(evaluation)) { + status = LTTNG_EVALUATION_STATUS_INVALID; + goto end; + } + + rotation = container_of(evaluation, + struct lttng_evaluation_session_rotation, parent); + *id = rotation->id; +end: + return status; +} + +enum lttng_evaluation_status +lttng_evaluation_session_rotation_completed_get_location( + const struct lttng_evaluation *evaluation, + const struct lttng_trace_archive_location **location) +{ + const struct lttng_evaluation_session_rotation *rotation; + enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK; + + if (!evaluation || !location || + evaluation->type != LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED) { + status = LTTNG_EVALUATION_STATUS_INVALID; + goto end; + } + + rotation = container_of(evaluation, + struct lttng_evaluation_session_rotation, parent); + *location = rotation->location; +end: + return status; +} diff --git a/src/common/session-consumed-size.c b/src/common/session-consumed-size.c deleted file mode 100644 index e147d1e5f..000000000 --- a/src/common/session-consumed-size.c +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright (C) 2017 Jérémie Galarneau - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define IS_CONSUMED_SIZE_CONDITION(condition) ( \ - lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE \ - ) - -#define IS_CONSUMED_SIZE_EVALUATION(evaluation) ( \ - lttng_evaluation_get_type(evaluation) == LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE \ - ) - -static -void lttng_condition_session_consumed_size_destroy(struct lttng_condition *condition) -{ - struct lttng_condition_session_consumed_size *consumed_size; - - consumed_size = container_of(condition, - struct lttng_condition_session_consumed_size, parent); - - free(consumed_size->session_name); - free(consumed_size); -} - -static -bool lttng_condition_session_consumed_size_validate( - const struct lttng_condition *condition) -{ - bool valid = false; - struct lttng_condition_session_consumed_size *consumed; - - if (!condition) { - goto end; - } - - consumed = container_of(condition, struct lttng_condition_session_consumed_size, - parent); - if (!consumed->session_name) { - ERR("Invalid session consumed size condition: a target session name must be set."); - goto end; - } - if (!consumed->consumed_threshold_bytes.set) { - ERR("Invalid session consumed size condition: a threshold must be set."); - goto end; - } - - valid = true; -end: - return valid; -} - -static -int lttng_condition_session_consumed_size_serialize( - const struct lttng_condition *condition, - struct lttng_payload *payload) -{ - int ret; - size_t session_name_len; - struct lttng_condition_session_consumed_size *consumed; - struct lttng_condition_session_consumed_size_comm consumed_comm; - - if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition)) { - ret = -1; - goto end; - } - - DBG("Serializing session consumed size condition"); - consumed = container_of(condition, - struct lttng_condition_session_consumed_size, - parent); - - session_name_len = strlen(consumed->session_name) + 1; - if (session_name_len > LTTNG_NAME_MAX) { - ret = -1; - goto end; - } - - consumed_comm.consumed_threshold_bytes = - consumed->consumed_threshold_bytes.value; - consumed_comm.session_name_len = (uint32_t) session_name_len; - - ret = lttng_dynamic_buffer_append(&payload->buffer, &consumed_comm, - sizeof(consumed_comm)); - if (ret) { - goto end; - } - - ret = lttng_dynamic_buffer_append(&payload->buffer, consumed->session_name, - session_name_len); - if (ret) { - goto end; - } -end: - return ret; -} - -static -bool lttng_condition_session_consumed_size_is_equal(const struct lttng_condition *_a, - const struct lttng_condition *_b) -{ - bool is_equal = false; - struct lttng_condition_session_consumed_size *a, *b; - - a = container_of(_a, struct lttng_condition_session_consumed_size, parent); - b = container_of(_b, struct lttng_condition_session_consumed_size, parent); - - if (a->consumed_threshold_bytes.set && b->consumed_threshold_bytes.set) { - uint64_t a_value, b_value; - - a_value = a->consumed_threshold_bytes.value; - b_value = b->consumed_threshold_bytes.value; - if (a_value != b_value) { - goto end; - } - } - - assert(a->session_name); - assert(b->session_name); - if (strcmp(a->session_name, b->session_name)) { - goto end; - } - - is_equal = true; -end: - return is_equal; -} - -struct lttng_condition *lttng_condition_session_consumed_size_create(void) -{ - struct lttng_condition_session_consumed_size *condition; - - condition = zmalloc(sizeof(struct lttng_condition_session_consumed_size)); - if (!condition) { - return NULL; - } - - lttng_condition_init(&condition->parent, LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE); - condition->parent.validate = lttng_condition_session_consumed_size_validate; - condition->parent.serialize = lttng_condition_session_consumed_size_serialize; - condition->parent.equal = lttng_condition_session_consumed_size_is_equal; - condition->parent.destroy = lttng_condition_session_consumed_size_destroy; - return &condition->parent; -} - -static -ssize_t init_condition_from_payload(struct lttng_condition *condition, - struct lttng_payload_view *src_view) -{ - ssize_t ret, condition_size; - enum lttng_condition_status status; - const char *session_name; - struct lttng_buffer_view session_name_view; - const struct lttng_condition_session_consumed_size_comm *condition_comm; - struct lttng_payload_view condition_comm_view = lttng_payload_view_from_view( - src_view, 0, sizeof(*condition_comm)); - - if (!lttng_payload_view_is_valid(&condition_comm_view)) { - ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header"); - ret = -1; - goto end; - } - - condition_comm = (typeof(condition_comm)) condition_comm_view.buffer.data; - session_name_view = lttng_buffer_view_from_view(&src_view->buffer, - sizeof(*condition_comm), condition_comm->session_name_len); - - if (condition_comm->session_name_len > LTTNG_NAME_MAX) { - ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME"); - ret = -1; - goto end; - } - - if (!lttng_buffer_view_is_valid(&session_name_view)) { - ERR("Failed to initialize from malformed condition buffer: buffer too short to contain element names"); - ret = -1; - goto end; - } - - status = lttng_condition_session_consumed_size_set_threshold(condition, - condition_comm->consumed_threshold_bytes); - if (status != LTTNG_CONDITION_STATUS_OK) { - ERR("Failed to initialize session consumed size condition threshold"); - ret = -1; - goto end; - } - - session_name = session_name_view.data; - if (*(session_name + condition_comm->session_name_len - 1) != '\0') { - ERR("Malformed session name encountered in condition buffer"); - ret = -1; - goto end; - } - - status = lttng_condition_session_consumed_size_set_session_name(condition, - session_name); - if (status != LTTNG_CONDITION_STATUS_OK) { - ERR("Failed to set session consumed size condition's session 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; - ret = condition_size; -end: - return ret; -} - -LTTNG_HIDDEN -ssize_t lttng_condition_session_consumed_size_create_from_payload( - struct lttng_payload_view *view, - struct lttng_condition **_condition) -{ - ssize_t ret; - struct lttng_condition *condition = - lttng_condition_session_consumed_size_create(); - - if (!_condition || !condition) { - ret = -1; - goto error; - } - - ret = init_condition_from_payload(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_payload( - const struct lttng_payload_view *view) -{ - const struct lttng_evaluation_session_consumed_size_comm *comm = - (typeof(comm)) view->buffer.data; - struct lttng_evaluation *evaluation = NULL; - - if (view->buffer.size < sizeof(*comm)) { - goto end; - } - - evaluation = lttng_evaluation_session_consumed_size_create( - comm->session_consumed); -end: - return evaluation; -} - -LTTNG_HIDDEN -ssize_t lttng_evaluation_session_consumed_size_create_from_payload( - struct lttng_payload_view *view, - struct lttng_evaluation **_evaluation) -{ - ssize_t ret; - struct lttng_evaluation *evaluation = NULL; - - if (!_evaluation) { - ret = -1; - goto error; - } - - evaluation = create_evaluation_from_payload(view); - if (!evaluation) { - ret = -1; - goto error; - } - - *_evaluation = evaluation; - ret = sizeof(struct lttng_evaluation_session_consumed_size_comm); - return ret; -error: - lttng_evaluation_destroy(evaluation); - return ret; -} - -enum lttng_condition_status -lttng_condition_session_consumed_size_get_threshold( - const struct lttng_condition *condition, - uint64_t *consumed_threshold_bytes) -{ - struct lttng_condition_session_consumed_size *consumed; - enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; - - if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition) || !consumed_threshold_bytes) { - status = LTTNG_CONDITION_STATUS_INVALID; - goto end; - } - - consumed = container_of(condition, struct lttng_condition_session_consumed_size, - parent); - if (!consumed->consumed_threshold_bytes.set) { - status = LTTNG_CONDITION_STATUS_UNSET; - goto end; - } - *consumed_threshold_bytes = consumed->consumed_threshold_bytes.value; -end: - return status; -} - -enum lttng_condition_status -lttng_condition_session_consumed_size_set_threshold( - struct lttng_condition *condition, uint64_t consumed_threshold_bytes) -{ - struct lttng_condition_session_consumed_size *consumed; - enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; - - if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition)) { - status = LTTNG_CONDITION_STATUS_INVALID; - goto end; - } - - consumed = container_of(condition, struct lttng_condition_session_consumed_size, - parent); - consumed->consumed_threshold_bytes.set = true; - consumed->consumed_threshold_bytes.value = consumed_threshold_bytes; -end: - return status; -} - -enum lttng_condition_status -lttng_condition_session_consumed_size_get_session_name( - const struct lttng_condition *condition, - const char **session_name) -{ - struct lttng_condition_session_consumed_size *consumed; - enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; - - if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition) || !session_name) { - status = LTTNG_CONDITION_STATUS_INVALID; - goto end; - } - - consumed = container_of(condition, struct lttng_condition_session_consumed_size, - parent); - if (!consumed->session_name) { - status = LTTNG_CONDITION_STATUS_UNSET; - goto end; - } - *session_name = consumed->session_name; -end: - return status; -} - -enum lttng_condition_status -lttng_condition_session_consumed_size_set_session_name( - struct lttng_condition *condition, const char *session_name) -{ - char *session_name_copy; - struct lttng_condition_session_consumed_size *consumed; - enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; - - if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition) || - !session_name || strlen(session_name) == 0) { - status = LTTNG_CONDITION_STATUS_INVALID; - goto end; - } - - consumed = container_of(condition, struct lttng_condition_session_consumed_size, - parent); - session_name_copy = strdup(session_name); - if (!session_name_copy) { - status = LTTNG_CONDITION_STATUS_ERROR; - goto end; - } - - if (consumed->session_name) { - free(consumed->session_name); - } - consumed->session_name = session_name_copy; -end: - return status; -} - -static -int lttng_evaluation_session_consumed_size_serialize( - const struct lttng_evaluation *evaluation, - struct lttng_payload *payload) -{ - struct lttng_evaluation_session_consumed_size *consumed; - struct lttng_evaluation_session_consumed_size_comm comm; - - consumed = container_of(evaluation, - struct lttng_evaluation_session_consumed_size, parent); - comm.session_consumed = consumed->session_consumed; - return lttng_dynamic_buffer_append( - &payload->buffer, &comm, sizeof(comm)); -} - -static -void lttng_evaluation_session_consumed_size_destroy( - struct lttng_evaluation *evaluation) -{ - struct lttng_evaluation_session_consumed_size *consumed; - - consumed = container_of(evaluation, struct lttng_evaluation_session_consumed_size, - parent); - free(consumed); -} - -LTTNG_HIDDEN -struct lttng_evaluation *lttng_evaluation_session_consumed_size_create( - uint64_t consumed) -{ - struct lttng_evaluation_session_consumed_size *consumed_eval; - - consumed_eval = zmalloc(sizeof(struct lttng_evaluation_session_consumed_size)); - if (!consumed_eval) { - goto end; - } - - consumed_eval->parent.type = LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE; - consumed_eval->session_consumed = consumed; - consumed_eval->parent.serialize = lttng_evaluation_session_consumed_size_serialize; - consumed_eval->parent.destroy = lttng_evaluation_session_consumed_size_destroy; -end: - return &consumed_eval->parent; -} - -enum lttng_evaluation_status -lttng_evaluation_session_consumed_size_get_consumed_size( - const struct lttng_evaluation *evaluation, - uint64_t *session_consumed) -{ - struct lttng_evaluation_session_consumed_size *consumed; - enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK; - - if (!evaluation || !IS_CONSUMED_SIZE_EVALUATION(evaluation) || - !session_consumed) { - status = LTTNG_EVALUATION_STATUS_INVALID; - goto end; - } - - consumed = container_of(evaluation, struct lttng_evaluation_session_consumed_size, - parent); - *session_consumed = consumed->session_consumed; -end: - return status; -} diff --git a/src/common/session-rotation.c b/src/common/session-rotation.c deleted file mode 100644 index 7df5ebab0..000000000 --- a/src/common/session-rotation.c +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Copyright (C) 2017 Jérémie Galarneau - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#include -#include -#include -#include -#include -#include -#include - -static -bool lttng_condition_session_rotation_validate( - const struct lttng_condition *condition); -static -int lttng_condition_session_rotation_serialize( - const struct lttng_condition *condition, - struct lttng_payload *payload); -static -bool lttng_condition_session_rotation_is_equal(const struct lttng_condition *_a, - const struct lttng_condition *_b); -static -void lttng_condition_session_rotation_destroy( - struct lttng_condition *condition); - -static const -struct lttng_condition rotation_condition_template = { - /* .type omitted; shall be set on creation. */ - .validate = lttng_condition_session_rotation_validate, - .serialize = lttng_condition_session_rotation_serialize, - .equal = lttng_condition_session_rotation_is_equal, - .destroy = lttng_condition_session_rotation_destroy, -}; - -static -int lttng_evaluation_session_rotation_serialize( - const struct lttng_evaluation *evaluation, - struct lttng_payload *payload); -static -void lttng_evaluation_session_rotation_destroy( - struct lttng_evaluation *evaluation); - -static const -struct lttng_evaluation rotation_evaluation_template = { - /* .type omitted; shall be set on creation. */ - .serialize = lttng_evaluation_session_rotation_serialize, - .destroy = lttng_evaluation_session_rotation_destroy, -}; - -static -bool is_rotation_condition(const struct lttng_condition *condition) -{ - enum lttng_condition_type type = lttng_condition_get_type(condition); - - return type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING || - type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED; -} - -static -bool is_rotation_evaluation(const struct lttng_evaluation *evaluation) -{ - enum lttng_condition_type type = lttng_evaluation_get_type(evaluation); - - return type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING || - type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED; -} - -static -bool lttng_condition_session_rotation_validate( - const struct lttng_condition *condition) -{ - bool valid = false; - struct lttng_condition_session_rotation *rotation; - - if (!condition) { - goto end; - } - - rotation = container_of(condition, - struct lttng_condition_session_rotation, parent); - if (!rotation->session_name) { - ERR("Invalid session rotation condition: a target session name must be set."); - goto end; - } - - valid = true; -end: - return valid; -} - -static -int lttng_condition_session_rotation_serialize( - const struct lttng_condition *condition, - struct lttng_payload *payload) -{ - int ret; - size_t session_name_len; - struct lttng_condition_session_rotation *rotation; - struct lttng_condition_session_rotation_comm rotation_comm; - - if (!condition || !is_rotation_condition(condition)) { - ret = -1; - goto end; - } - - DBG("Serializing session rotation condition"); - rotation = container_of(condition, struct lttng_condition_session_rotation, - parent); - - session_name_len = strlen(rotation->session_name) + 1; - if (session_name_len > LTTNG_NAME_MAX) { - ret = -1; - goto end; - } - - rotation_comm.session_name_len = session_name_len; - ret = lttng_dynamic_buffer_append(&payload->buffer, &rotation_comm, - sizeof(rotation_comm)); - if (ret) { - goto end; - } - ret = lttng_dynamic_buffer_append(&payload->buffer, - rotation->session_name, session_name_len); - if (ret) { - goto end; - } -end: - return ret; -} - -static -bool lttng_condition_session_rotation_is_equal(const struct lttng_condition *_a, - const struct lttng_condition *_b) -{ - bool is_equal = false; - struct lttng_condition_session_rotation *a, *b; - - a = container_of(_a, struct lttng_condition_session_rotation, parent); - b = container_of(_b, struct lttng_condition_session_rotation, parent); - - /* Both session names must be set or both must be unset. */ - if ((a->session_name && !b->session_name) || - (!a->session_name && b->session_name)) { - WARN("Comparing session rotation conditions with uninitialized session names."); - goto end; - } - - if (a->session_name && b->session_name && - strcmp(a->session_name, b->session_name)) { - goto end; - } - - is_equal = true; -end: - return is_equal; -} - -static -void lttng_condition_session_rotation_destroy( - struct lttng_condition *condition) -{ - struct lttng_condition_session_rotation *rotation; - - rotation = container_of(condition, - struct lttng_condition_session_rotation, parent); - - free(rotation->session_name); - free(rotation); -} - -static -struct lttng_condition *lttng_condition_session_rotation_create( - enum lttng_condition_type type) -{ - struct lttng_condition_session_rotation *condition; - - condition = zmalloc(sizeof(struct lttng_condition_session_rotation)); - if (!condition) { - return NULL; - } - - memcpy(&condition->parent, &rotation_condition_template, - sizeof(condition->parent)); - lttng_condition_init(&condition->parent, type); - return &condition->parent; -} - -struct lttng_condition *lttng_condition_session_rotation_ongoing_create(void) -{ - return lttng_condition_session_rotation_create( - LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING); -} - -struct lttng_condition *lttng_condition_session_rotation_completed_create(void) -{ - return lttng_condition_session_rotation_create( - LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED); -} - -static -ssize_t init_condition_from_payload(struct lttng_condition *condition, - struct lttng_payload_view *src_view) -{ - ssize_t ret, condition_size; - enum lttng_condition_status status; - const char *session_name; - struct lttng_buffer_view name_view; - const struct lttng_condition_session_rotation_comm *condition_comm; - struct lttng_payload_view condition_comm_view = - lttng_payload_view_from_view( - src_view, 0, sizeof(*condition_comm)); - - if (!lttng_payload_view_is_valid(&condition_comm_view)) { - ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header"); - ret = -1; - goto end; - } - - condition_comm = (typeof(condition_comm)) src_view->buffer.data; - name_view = lttng_buffer_view_from_view(&src_view->buffer, - sizeof(*condition_comm), condition_comm->session_name_len); - - if (!lttng_buffer_view_is_valid(&name_view)) { - ERR("Failed to initialize from malformed condition buffer: buffer too short to contain session name"); - ret = -1; - goto end; - } - - if (condition_comm->session_name_len > LTTNG_NAME_MAX) { - ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME"); - ret = -1; - goto end; - } - - session_name = name_view.data; - if (*(session_name + condition_comm->session_name_len - 1) != '\0') { - ERR("Malformed session name encountered in condition buffer"); - ret = -1; - goto end; - } - - status = lttng_condition_session_rotation_set_session_name(condition, - session_name); - if (status != LTTNG_CONDITION_STATUS_OK) { - ERR("Failed to set buffer consumed session 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; - ret = condition_size; -end: - return ret; -} - -static -ssize_t lttng_condition_session_rotation_create_from_payload( - struct lttng_payload_view *view, - struct lttng_condition **_condition, - enum lttng_condition_type type) -{ - ssize_t ret; - struct lttng_condition *condition = NULL; - - switch (type) { - case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING: - condition = lttng_condition_session_rotation_ongoing_create(); - break; - case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED: - condition = lttng_condition_session_rotation_completed_create(); - break; - default: - ret = -1; - goto error; - } - - if (!_condition || !condition) { - ret = -1; - goto error; - } - - ret = init_condition_from_payload(condition, view); - if (ret < 0) { - goto error; - } - - *_condition = condition; - return ret; -error: - lttng_condition_destroy(condition); - return ret; -} - -LTTNG_HIDDEN -ssize_t lttng_condition_session_rotation_ongoing_create_from_payload( - struct lttng_payload_view *view, - struct lttng_condition **condition) -{ - return lttng_condition_session_rotation_create_from_payload(view, - condition, - LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING); -} - -LTTNG_HIDDEN -ssize_t lttng_condition_session_rotation_completed_create_from_payload( - struct lttng_payload_view *view, - struct lttng_condition **condition) -{ - return lttng_condition_session_rotation_create_from_payload(view, - condition, - LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED); -} - -static -struct lttng_evaluation *lttng_evaluation_session_rotation_create( - enum lttng_condition_type type, uint64_t id, - struct lttng_trace_archive_location *location) -{ - struct lttng_evaluation_session_rotation *evaluation; - - evaluation = zmalloc(sizeof(struct lttng_evaluation_session_rotation)); - if (!evaluation) { - return NULL; - } - - memcpy(&evaluation->parent, &rotation_evaluation_template, - sizeof(evaluation->parent)); - lttng_evaluation_init(&evaluation->parent, type); - evaluation->id = id; - evaluation->location = location; - return &evaluation->parent; -} - -static -ssize_t create_evaluation_from_payload( - enum lttng_condition_type type, - struct lttng_payload_view *view, - struct lttng_evaluation **_evaluation) -{ - ssize_t ret, size; - struct lttng_evaluation *evaluation = NULL; - struct lttng_trace_archive_location *location = NULL; - const struct lttng_evaluation_session_rotation_comm *comm; - struct lttng_payload_view comm_view = lttng_payload_view_from_view( - view, 0, sizeof(*comm)); - - if (!lttng_payload_view_is_valid(&comm_view)) { - goto error; - } - - comm = (typeof(comm)) comm_view.buffer.data; - size = sizeof(*comm); - if (comm->has_location) { - const struct lttng_buffer_view location_view = - lttng_buffer_view_from_view( - &view->buffer, sizeof(*comm), -1); - - if (!lttng_buffer_view_is_valid(&location_view)) { - goto error; - } - - ret = lttng_trace_archive_location_create_from_buffer( - &location_view, &location); - if (ret < 0) { - goto error; - } - size += ret; - } - - evaluation = lttng_evaluation_session_rotation_create(type, comm->id, - location); - if (!evaluation) { - goto error; - } - - ret = size; - *_evaluation = evaluation; - return ret; -error: - lttng_trace_archive_location_destroy(location); - evaluation = NULL; - return -1; -} - -static -ssize_t lttng_evaluation_session_rotation_create_from_payload( - enum lttng_condition_type type, - struct lttng_payload_view *view, - struct lttng_evaluation **_evaluation) -{ - ssize_t ret; - struct lttng_evaluation *evaluation = NULL; - - if (!_evaluation) { - ret = -1; - goto error; - } - - ret = create_evaluation_from_payload(type, view, &evaluation); - if (ret < 0) { - goto error; - } - - *_evaluation = evaluation; - return ret; -error: - lttng_evaluation_destroy(evaluation); - return ret; -} - -LTTNG_HIDDEN -ssize_t lttng_evaluation_session_rotation_ongoing_create_from_payload( - struct lttng_payload_view *view, - struct lttng_evaluation **evaluation) -{ - return lttng_evaluation_session_rotation_create_from_payload( - LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING, - view, evaluation); -} - -LTTNG_HIDDEN -ssize_t lttng_evaluation_session_rotation_completed_create_from_payload( - struct lttng_payload_view *view, - struct lttng_evaluation **evaluation) -{ - return lttng_evaluation_session_rotation_create_from_payload( - LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED, - view, evaluation); -} - -LTTNG_HIDDEN -struct lttng_evaluation *lttng_evaluation_session_rotation_ongoing_create( - uint64_t id) -{ - return lttng_evaluation_session_rotation_create( - LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING, id, - NULL); -} - -LTTNG_HIDDEN -struct lttng_evaluation *lttng_evaluation_session_rotation_completed_create( - uint64_t id, struct lttng_trace_archive_location *location) -{ - return lttng_evaluation_session_rotation_create( - LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED, id, - location); -} - -enum lttng_condition_status -lttng_condition_session_rotation_get_session_name( - const struct lttng_condition *condition, - const char **session_name) -{ - struct lttng_condition_session_rotation *rotation; - enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; - - if (!condition || !is_rotation_condition(condition) || !session_name) { - status = LTTNG_CONDITION_STATUS_INVALID; - goto end; - } - - rotation = container_of(condition, struct lttng_condition_session_rotation, - parent); - if (!rotation->session_name) { - status = LTTNG_CONDITION_STATUS_UNSET; - goto end; - } - *session_name = rotation->session_name; -end: - return status; -} - -enum lttng_condition_status -lttng_condition_session_rotation_set_session_name( - struct lttng_condition *condition, const char *session_name) -{ - char *session_name_copy; - struct lttng_condition_session_rotation *rotation; - enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK; - - if (!condition || !is_rotation_condition(condition) || - !session_name || strlen(session_name) == 0) { - status = LTTNG_CONDITION_STATUS_INVALID; - goto end; - } - - rotation = container_of(condition, - struct lttng_condition_session_rotation, parent); - session_name_copy = strdup(session_name); - if (!session_name_copy) { - status = LTTNG_CONDITION_STATUS_ERROR; - goto end; - } - - free(rotation->session_name); - rotation->session_name = session_name_copy; -end: - return status; -} - -static -int lttng_evaluation_session_rotation_serialize( - const struct lttng_evaluation *evaluation, - struct lttng_payload *payload) -{ - int ret; - struct lttng_evaluation_session_rotation *rotation; - struct lttng_evaluation_session_rotation_comm comm = { 0 }; - - rotation = container_of(evaluation, - struct lttng_evaluation_session_rotation, parent); - comm.id = rotation->id; - comm.has_location = !!rotation->location; - ret = lttng_dynamic_buffer_append( - &payload->buffer, &comm, sizeof(comm)); - if (ret) { - goto end; - } - if (!rotation->location) { - goto end; - } - ret = lttng_trace_archive_location_serialize(rotation->location, - &payload->buffer); -end: - return ret; -} - -static -void lttng_evaluation_session_rotation_destroy( - struct lttng_evaluation *evaluation) -{ - struct lttng_evaluation_session_rotation *rotation; - - rotation = container_of(evaluation, - struct lttng_evaluation_session_rotation, parent); - lttng_trace_archive_location_destroy(rotation->location); - free(rotation); -} - -enum lttng_evaluation_status -lttng_evaluation_session_rotation_get_id( - const struct lttng_evaluation *evaluation, uint64_t *id) -{ - const struct lttng_evaluation_session_rotation *rotation; - enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK; - - if (!evaluation || !id || !is_rotation_evaluation(evaluation)) { - status = LTTNG_EVALUATION_STATUS_INVALID; - goto end; - } - - rotation = container_of(evaluation, - struct lttng_evaluation_session_rotation, parent); - *id = rotation->id; -end: - return status; -} - -enum lttng_evaluation_status -lttng_evaluation_session_rotation_completed_get_location( - const struct lttng_evaluation *evaluation, - const struct lttng_trace_archive_location **location) -{ - const struct lttng_evaluation_session_rotation *rotation; - enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK; - - if (!evaluation || !location || - evaluation->type != LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED) { - status = LTTNG_EVALUATION_STATUS_INVALID; - goto end; - } - - rotation = container_of(evaluation, - struct lttng_evaluation_session_rotation, parent); - *location = rotation->location; -end: - return status; -}