Various fixes for prototype branch
[lttng-tools.git] / src / common / buffer-usage.c
index 66449c3139113db69676f5702ef150a9a0c35b0f..c541d34ed46204d7b87b4570823003f19c377de7 100644 (file)
 #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)
@@ -72,7 +86,7 @@ bool lttng_condition_buffer_usage_validate(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;
        }
@@ -111,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));
@@ -129,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)
@@ -143,6 +226,7 @@ struct lttng_condition *lttng_condition_buffer_usage_create(
        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;
@@ -161,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;
@@ -172,10 +257,11 @@ 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");
@@ -246,8 +332,7 @@ ssize_t lttng_condition_buffer_usage_low_create_from_buffer(const char *buf,
                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;
        }
@@ -272,8 +357,7 @@ ssize_t lttng_condition_buffer_usage_high_create_from_buffer(const char *buf,
                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;
        }
@@ -285,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;
 }
@@ -369,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:
@@ -403,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;
 
@@ -414,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;
 }
@@ -450,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;
 
@@ -461,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;
 }
@@ -514,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)
@@ -526,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;
 
@@ -536,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;
@@ -548,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.03149 seconds and 5 git commands to generate.