Various fixes for prototype branch
[deliverable/lttng-tools.git] / src / common / buffer-usage.c
index eed921a56a884e15bffb2d6cd3ab1af330bee97e..c541d34ed46204d7b87b4570823003f19c377de7 100644 (file)
 #include <lttng/condition/condition-internal.h>
 #include <lttng/condition/buffer-usage-internal.h>
 #include <common/macros.h>
+#include <common/error.h>
 #include <assert.h>
+#include <math.h>
+#include <float.h>
+
+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)
@@ -64,12 +79,15 @@ bool lttng_condition_buffer_usage_validate(struct lttng_condition *condition)
        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_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;
        }
 
@@ -91,6 +109,7 @@ ssize_t lttng_condition_buffer_usage_serialize(struct lttng_condition *condition
                goto end;
        }
 
+       DBG("Serializing buffer usage condition");
        usage = container_of(condition, struct lttng_condition_buffer_usage,
                        parent);
        size = sizeof(struct lttng_condition_buffer_usage_comm);
@@ -106,11 +125,10 @@ ssize_t lttng_condition_buffer_usage_serialize(struct lttng_condition *condition
                };
 
                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));
@@ -124,6 +142,76 @@ end:
        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)
@@ -135,9 +223,10 @@ struct lttng_condition *lttng_condition_buffer_usage_create(
                goto end;
        }
 
-       condition->parent.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;
@@ -156,7 +245,8 @@ struct lttng_condition *lttng_condition_buffer_usage_high_create(void)
 }
 
 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;
@@ -167,12 +257,14 @@ ssize_t init_from_buffer(struct lttng_condition *condition, const char *buf)
 
        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");
                ret = -1;
                goto end;
        }
@@ -180,6 +272,8 @@ ssize_t init_from_buffer(struct lttng_condition *condition, const char *buf)
        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;
        }
@@ -188,6 +282,7 @@ ssize_t init_from_buffer(struct lttng_condition *condition, const char *buf)
        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;
        }
@@ -198,6 +293,7 @@ ssize_t init_from_buffer(struct lttng_condition *condition, const char *buf)
        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;
        }
@@ -205,6 +301,7 @@ ssize_t init_from_buffer(struct lttng_condition *condition, const char *buf)
        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;
        }
@@ -235,7 +332,7 @@ ssize_t lttng_condition_buffer_usage_low_create_from_buffer(const char *buf,
                goto error;
        }
 
-       ret = init_from_buffer(condition, buf);
+       ret = init_condition_from_buffer(condition, buf);
        if (ret < 0) {
                goto error;
        }
@@ -260,7 +357,7 @@ ssize_t lttng_condition_buffer_usage_high_create_from_buffer(const char *buf,
                goto error;
        }
 
-       ret = init_from_buffer(condition, buf);
+       ret = init_condition_from_buffer(condition, buf);
        if (ret < 0) {
                goto error;
        }
@@ -272,49 +369,115 @@ 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;
 }
@@ -356,7 +519,7 @@ lttng_condition_buffer_usage_set_threshold(
 
        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:
@@ -390,6 +553,7 @@ extern 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;
 
@@ -401,11 +565,16 @@ lttng_condition_buffer_usage_set_session_name(
 
        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;
 }
@@ -437,6 +606,7 @@ extern 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;
 
@@ -448,11 +618,16 @@ lttng_condition_buffer_usage_set_channel_name(
 
        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;
 }
@@ -501,6 +676,28 @@ end:
        return status;
 }
 
+static
+ssize_t lttng_evaluation_buffer_usage_serialize(
+               struct lttng_evaluation *evaluation, char *buf)
+{
+       ssize_t ret;
+       struct lttng_evaluation_buffer_usage *usage;
+
+       usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
+                       parent);
+       if (buf) {
+               struct lttng_evaluation_buffer_usage_comm comm = {
+                       .buffer_use = usage->buffer_use,
+                       .buffer_capacity = usage->buffer_capacity,
+               };
+
+               memcpy(buf, &comm, sizeof(comm));
+       }
+
+       ret = sizeof(struct lttng_evaluation_buffer_usage_comm);
+       return ret;
+}
+
 static
 void lttng_evaluation_buffer_usage_destroy(
                struct lttng_evaluation *evaluation)
@@ -513,8 +710,8 @@ void lttng_evaluation_buffer_usage_destroy(
 }
 
 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;
 
@@ -523,8 +720,10 @@ struct lttng_evaluation *lttng_evaluation_buffer_usage_create(uint64_t use,
                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;
@@ -535,20 +734,20 @@ end:
  * 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;
This page took 0.030415 seconds and 5 git commands to generate.