#include <common/macros.h>
#include <common/error.h>
#include <assert.h>
+#include <math.h>
+#include <float.h>
+
+static
+double fixed_to_double(uint64_t val)
+{
+ return (double) val / (double) UINT64_MAX;
+}
+
+static
+uint64_t double_to_fixed(double val)
+{
+ return (val * (double) UINT64_MAX);
+}
static
bool is_usage_condition(struct lttng_condition *condition)
ERR("Invalid buffer condition: a target channel name must be set.");
goto end;
}
- if (!usage->threshold_percent.set && !usage->threshold_bytes.set) {
+ if (!usage->threshold_ratio.set && !usage->threshold_bytes.set) {
ERR("Invalid buffer condition: a threshold must be set.");
goto end;
}
};
if (usage->threshold_bytes.set) {
- usage_comm.threshold.bytes =
- usage->threshold_bytes.value;
+ usage_comm.threshold = usage->threshold_bytes.value;
} else {
- usage_comm.threshold.percent =
- usage->threshold_percent.value;
+ usage_comm.threshold = double_to_fixed(
+ usage->threshold_ratio.value);
}
memcpy(buf, &usage_comm, sizeof(usage_comm));
return size;
}
+static
+bool lttng_condition_buffer_usage_is_equal(struct lttng_condition *_a,
+ struct lttng_condition *_b)
+{
+ bool is_equal = false;
+ struct lttng_condition_buffer_usage *a, *b;
+
+ a = container_of(_a, struct lttng_condition_buffer_usage, parent);
+ b = container_of(_b, struct lttng_condition_buffer_usage, parent);
+
+ if ((a->threshold_ratio.set && !b->threshold_ratio.set) ||
+ (a->threshold_bytes.set && !b->threshold_bytes.set)) {
+ goto end;
+ }
+
+ if (a->threshold_ratio.set && b->threshold_ratio.set) {
+ double a_value, b_value, diff;
+
+ a_value = a->threshold_ratio.value;
+ b_value = b->threshold_ratio.value;
+ diff = fabs(a_value - b_value);
+
+ if (diff > DBL_EPSILON) {
+ goto end;
+ }
+ } else if (a->threshold_bytes.set && b->threshold_bytes.set) {
+ uint64_t a_value, b_value;
+
+ a_value = a->threshold_bytes.value;
+ b_value = b->threshold_bytes.value;
+ if (a_value != b_value) {
+ goto end;
+ }
+ }
+
+ if ((a->session_name && !b->session_name) ||
+ (!a->session_name && b->session_name)) {
+ goto end;
+ }
+
+ if (a->channel_name && b->channel_name) {
+ if (strcmp(a->channel_name, b->channel_name)) {
+ goto end;
+ }
+ } if ((a->channel_name && !b->channel_name) ||
+ (!a->channel_name && b->channel_name)) {
+ goto end;
+ }
+
+ if (a->channel_name && b->channel_name) {
+ if (strcmp(a->channel_name, b->channel_name)) {
+ goto end;
+ }
+ }
+
+ if ((a->domain.set && !b->domain.set) ||
+ (!a->domain.set && b->domain.set)) {
+ goto end;
+ }
+
+ if (a->domain.set && b->domain.set) {
+ if (a->domain.type != b->domain.type) {
+ goto end;
+ }
+ }
+ is_equal = true;
+end:
+ return is_equal;
+}
+
static
struct lttng_condition *lttng_condition_buffer_usage_create(
enum lttng_condition_type type)
lttng_condition_init(&condition->parent, type);
condition->parent.validate = lttng_condition_buffer_usage_validate;
condition->parent.serialize = lttng_condition_buffer_usage_serialize;
+ condition->parent.equal = lttng_condition_buffer_usage_is_equal;
condition->parent.destroy = lttng_condition_buffer_usage_destroy;
end:
return &condition->parent;
}
static
-ssize_t init_from_buffer(struct lttng_condition *condition, const char *buf)
+ssize_t init_condition_from_buffer(struct lttng_condition *condition,
+ const char *buf)
{
ssize_t ret, condition_size;
enum lttng_condition_status status;
if (condition_comm->threshold_set_in_bytes) {
status = lttng_condition_buffer_usage_set_threshold(condition,
- condition_comm->threshold.bytes);
+ condition_comm->threshold);
} else {
- status = lttng_condition_buffer_usage_set_threshold_percentage(
- condition, condition_comm->threshold.percent);
+ 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");
goto error;
}
- DBG("Initializing low buffer usage condition from buffer");
- ret = init_from_buffer(condition, buf);
+ ret = init_condition_from_buffer(condition, buf);
if (ret < 0) {
goto error;
}
goto error;
}
- DBG("Initializing high buffer usage condition from buffer");
- ret = init_from_buffer(condition, buf);
+ ret = init_condition_from_buffer(condition, buf);
if (ret < 0) {
goto error;
}
return ret;
}
+static
+struct lttng_evaluation *create_evaluation_from_buffer(
+ enum lttng_condition_type type, const char *buf)
+{
+ struct lttng_evaluation_buffer_usage_comm *comm =
+ (struct lttng_evaluation_buffer_usage_comm *) buf;
+ struct lttng_evaluation *evaluation;
+
+ evaluation = lttng_evaluation_buffer_usage_create(type,
+ comm->buffer_use, comm->buffer_capacity);
+ return evaluation;
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_evaluation_buffer_usage_low_create_from_buffer(const char *buf,
+ struct lttng_evaluation **_evaluation)
+{
+ ssize_t ret;
+ struct lttng_evaluation *evaluation;
+
+ if (!_evaluation) {
+ ret = -1;
+ goto error;
+ }
+
+ evaluation = create_evaluation_from_buffer(
+ LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW, buf);
+ if (!evaluation) {
+ goto error;
+ }
+
+ *_evaluation = evaluation;
+ ret = sizeof(struct lttng_evaluation_buffer_usage_comm);
+ return ret;
+error:
+ lttng_evaluation_destroy(evaluation);
+ return ret;
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_evaluation_buffer_usage_high_create_from_buffer(const char *buf,
+ struct lttng_evaluation **_evaluation)
+{
+ ssize_t ret;
+ struct lttng_evaluation *evaluation;
+
+ if (!_evaluation) {
+ ret = -1;
+ goto error;
+ }
+
+ evaluation = create_evaluation_from_buffer(
+ LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH, buf);
+ if (!evaluation) {
+ 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_percentage(
- struct lttng_condition *condition, double *threshold_percent)
+lttng_condition_buffer_usage_get_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_percent) {
+ !threshold_ratio) {
status = LTTNG_CONDITION_STATUS_INVALID;
goto end;
}
usage = container_of(condition, struct lttng_condition_buffer_usage,
parent);
- if (!usage->threshold_percent.set) {
+ if (!usage->threshold_ratio.set) {
status = LTTNG_CONDITION_STATUS_UNSET;
goto end;
}
- *threshold_percent = usage->threshold_percent.value;
+ *threshold_ratio = usage->threshold_ratio.value;
end:
return status;
}
-/* threshold_percent expressed as [0.0, 1.0]. */
+/* threshold_ratio expressed as [0.0, 1.0]. */
enum lttng_condition_status
-lttng_condition_buffer_usage_set_threshold_percentage(
- struct lttng_condition *condition, double threshold_percent)
+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_percent < 0.0 || threshold_percent > 1.0) {
+ 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_percent.set = true;
+ usage->threshold_ratio.set = true;
usage->threshold_bytes.set = false;
- usage->threshold_percent.value = threshold_percent;
+ usage->threshold_ratio.value = threshold_ratio;
end:
return status;
}
usage = container_of(condition, struct lttng_condition_buffer_usage,
parent);
- usage->threshold_percent.set = false;
+ usage->threshold_ratio.set = false;
usage->threshold_bytes.set = true;
usage->threshold_bytes.value = threshold_bytes;
end:
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;
usage = container_of(condition, struct lttng_condition_buffer_usage,
parent);
- usage->session_name = strdup(session_name);
- if (!usage->session_name) {
+ 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;
}
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;
usage = container_of(condition, struct lttng_condition_buffer_usage,
parent);
- usage->channel_name = strdup(channel_name);
- if (!usage->channel_name) {
+ 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;
}
return status;
}
+static
+ssize_t lttng_evaluation_buffer_usage_serialize(
+ struct lttng_evaluation *evaluation, char *buf)
+{
+ ssize_t ret;
+ struct lttng_evaluation_buffer_usage *usage;
+
+ usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
+ parent);
+ if (buf) {
+ struct lttng_evaluation_buffer_usage_comm comm = {
+ .buffer_use = usage->buffer_use,
+ .buffer_capacity = usage->buffer_capacity,
+ };
+
+ memcpy(buf, &comm, sizeof(comm));
+ }
+
+ ret = sizeof(struct lttng_evaluation_buffer_usage_comm);
+ return ret;
+}
+
static
void lttng_evaluation_buffer_usage_destroy(
struct lttng_evaluation *evaluation)
}
LTTNG_HIDDEN
-struct lttng_evaluation *lttng_evaluation_buffer_usage_create(uint64_t use,
- uint64_t capacity)
+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;
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;
* evaluate to "true".
*/
enum lttng_evaluation_status
-lttng_evaluation_buffer_usage_get_usage_percentage(
- struct lttng_evaluation *evaluation, double *usage_percent)
+lttng_evaluation_buffer_usage_get_usage_ratio(
+ 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_percent) {
+ 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_percent = (double) usage->buffer_use /
+ *usage_ratio = (double) usage->buffer_use /
(double) usage->buffer_capacity;
end:
return status;