struct lttng_condition_buffer_usage {
struct lttng_condition parent;
- bool frozen;
struct {
bool set;
uint64_t value;
struct {
bool set;
double value;
- } threshold_percent;
+ } threshold_ratio;
char *session_name;
char *channel_name;
struct {
struct lttng_condition_buffer_usage_comm {
uint8_t threshold_set_in_bytes;
- union {
- double percent;
- uint64_t bytes;
- } threshold;
+ /*
+ * Expressed in bytes if "threshold_set_in_bytes" is not 0.
+ * Otherwise, it is expressed a ratio in the interval [0.0, 1.0]
+ * that is mapped to the range on a 64-bit unsigned integer.
+ * The ratio is obtained by (threshold / UINT64_MAX).
+ */
+ uint64_t threshold;
/* Both lengths include the trailing \0. */
uint32_t session_name_len;
uint32_t channel_name_len;
uint64_t buffer_capacity;
};
+struct lttng_evaluation_buffer_usage_comm {
+ uint64_t buffer_use;
+ uint64_t buffer_capacity;
+} LTTNG_PACKED;
+
LTTNG_HIDDEN
-struct lttng_evaluation *lttng_evaluation_buffer_usage_create(uint64_t use,
+struct lttng_evaluation *lttng_evaluation_buffer_usage_create(
+ enum lttng_condition_type type, uint64_t use,
uint64_t capacity);
LTTNG_HIDDEN
ssize_t lttng_condition_buffer_usage_high_create_from_buffer(const char *buf,
struct lttng_condition **condition);
+LTTNG_HIDDEN
+ssize_t lttng_evaluation_buffer_usage_low_create_from_buffer(const char *buf,
+ struct lttng_evaluation **evaluation);
+
+LTTNG_HIDDEN
+ssize_t lttng_evaluation_buffer_usage_high_create_from_buffer(const char *buf,
+ struct lttng_evaluation **evaluation);
+
+
+
#endif /* LTTNG_CONDITION_BUFFER_USAGE_INTERNAL_H */
extern struct lttng_condition *
lttng_condition_buffer_usage_high_create(void);
-/* threshold_percent expressed as [0.0, 1.0]. */
+/* threshold_ratio expressed as [0.0, 1.0]. */
extern enum lttng_condition_status
-lttng_condition_buffer_usage_get_threshold_percentage(
+lttng_condition_buffer_usage_get_threshold_ration(
struct lttng_condition *condition,
- double *threshold_percent);
+ double *threshold_ratio);
-/* threshold_percent expressed as [0.0, 1.0]. */
+/* threshold_ratio expressed as [0.0, 1.0]. */
extern enum lttng_condition_status
-lttng_condition_buffer_usage_set_threshold_percentage(
+lttng_condition_buffer_usage_set_threshold_ratio(
struct lttng_condition *condition,
- double threshold_percent);
+ double threshold_ratio);
extern enum lttng_condition_status
lttng_condition_buffer_usage_get_threshold(
/* LTTng Condition Evaluation */
extern enum lttng_evaluation_status
-lttng_evaluation_buffer_usage_get_usage_percentage(
+lttng_evaluation_buffer_usage_get_usage_ratio(
struct lttng_evaluation *evaluation,
- double *usage_percent);
+ double *usage_ratio);
extern enum lttng_evaluation_status
lttng_evaluation_buffer_usage_get_usage(
typedef bool (*condition_validate_cb)(struct lttng_condition *condition);
typedef ssize_t (*condition_serialize_cb)(struct lttng_condition *condition,
char *buf);
+typedef bool (*condition_equal_cb)(struct lttng_condition *a,
+ struct lttng_condition *b);
struct lttng_condition {
enum lttng_condition_type type;
condition_validate_cb validate;
condition_serialize_cb serialize;
+ condition_equal_cb equal;
condition_destroy_cb destroy;
struct cds_list_head list_node;
};
struct lttng_condition_comm {
/* enum lttng_condition_type */
int8_t condition_type;
+ char payload[];
};
LTTNG_HIDDEN
struct lttng_condition **condition);
LTTNG_HIDDEN
-ssize_t lttng_condition_serialize(struct lttng_condition *action, char *buf);
+ssize_t lttng_condition_serialize(struct lttng_condition *condition, char *buf);
+
+LTTNG_HIDDEN
+bool lttng_condition_is_equal(struct lttng_condition *a,
+ struct lttng_condition *b);
#endif /* LTTNG_CONDITION_INTERNAL_H */
enum lttng_condition_type {
LTTNG_CONDITION_TYPE_UNKNOWN = -1,
- LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW = 0,
- LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH = 1,
+ LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW = 102,
+ LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH = 101,
};
enum lttng_condition_status {
#include <stdbool.h>
typedef void (*evaluation_destroy_cb)(struct lttng_evaluation *evaluation);
+typedef ssize_t (*evaluation_serialize_cb)(struct lttng_evaluation *evaluation,
+ char *buf);
struct lttng_evaluation_comm {
/* enum lttng_condition_type type */
int8_t type;
+ char payload[];
} LTTNG_PACKED;
struct lttng_evaluation {
enum lttng_condition_type type;
+ evaluation_serialize_cb serialize;
evaluation_destroy_cb destroy;
};
+LTTNG_HIDDEN
+ssize_t lttng_evaluation_create_from_buffer(const char *buf,
+ struct lttng_evaluation **evaluation);
+
+LTTNG_HIDDEN
+ssize_t lttng_evaluation_serialize(struct lttng_evaluation *evaluation,
+ char *buf);
+
#endif /* LTTNG_EVALUATION_INTERNAL_H */
/* LTTng Notification channel */
enum lttng_notification_channel_status {
- LTTNG_NOTIFICATION_CHANNEL_STATUS_TIMEOUT = 2,
LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED = 1,
LTTNG_NOTIFICATION_CHANNEL_STATUS_OK = 0,
LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR = -1,
LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED = -2,
- LTTNG_NOTIFICATION_CHANNEL_STATUS_NOT_FOUND = -3,
+ /* Condition unknown. */
+ LTTNG_NOTIFICATION_CHANNEL_STATUS_UNKNOWN = -3,
LTTNG_NOTIFICATION_CHANNEL_STATUS_UNSUPPORTED = -4,
LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID = -5,
};
extern enum lttng_notification_channel_status
lttng_notification_channel_get_next_notification(
struct lttng_notification_channel *channel,
- struct lttng_notification **notification,
- unsigned int timeout_ms);
+ struct lttng_notification **notification);
extern enum lttng_notification_channel_status
lttng_notification_channel_subscribe(
#include <lttng/notification/notification.h>
#include <common/macros.h>
+#include <stdint.h>
struct lttng_notification {
struct lttng_condition *condition;
struct lttng_evaluation *evaluation;
};
+struct lttng_notification_comm {
+ /* length excludes its own length. */
+ uint32_t length;
+ /* A condition and evaluation object follow. */
+ char payload[];
+} LTTNG_PACKED;
+
LTTNG_HIDDEN
struct lttng_notification *lttng_notification_create(
struct lttng_condition *condition,
struct lttng_evaluation *evaluation);
+LTTNG_HIDDEN
+ssize_t lttng_notification_serialize(struct lttng_notification *notification,
+ char *buf);
+
+LTTNG_HIDDEN
+ssize_t lttng_notification_create_from_buffer(const char *buf,
+ struct lttng_notification **notification);
+
#endif /* LTTNG_NOTIFICATION_INTERNAL_H */
};
struct lttng_trigger_comm {
- /* len excludes its own length. */
- uint32_t len;
+ /* length excludes its own length. */
+ uint32_t length;
+ /* A condition and action object follow. */
+ char payload[];
} LTTNG_PACKED;
LTTNG_HIDDEN
struct lttng_action;
struct lttng_condition;
struct lttng_trigger;
-struct lttng_endpoint;
#ifdef __cplusplus
extern "C" {
extern struct lttng_trigger *lttng_trigger_create(
struct lttng_condition *condition, struct lttng_action *action);
+extern struct lttng_condition *lttng_trigger_get_condition(
+ struct lttng_trigger *trigger);
+
+extern struct lttng_action *lttng_trigger_get_action(
+ struct lttng_trigger *trigger);
+
extern void lttng_trigger_destroy(struct lttng_trigger *trigger);
extern int lttng_register_trigger(struct lttng_trigger *trigger);
#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;
return ret;
}
+LTTNG_HIDDEN
+bool lttng_condition_is_equal(struct lttng_condition *a,
+ struct lttng_condition *b)
+{
+ bool is_equal = false;
+
+ if (!a || !b) {
+ goto end;
+ }
+
+ if (a->type != b->type) {
+ goto end;
+ }
+
+ is_equal = a->equal ? a->equal(a, b) : true;
+end:
+ return is_equal;
+}
+
LTTNG_HIDDEN
ssize_t lttng_condition_create_from_buffer(const char *buf,
struct lttng_condition **condition)
condition_size += sizeof(*condition_comm);
buf += condition_size;
- switch (condition_comm->condition_type) {
+ switch ((enum lttng_condition_type) condition_comm->condition_type) {
case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
ret = lttng_condition_buffer_usage_low_create_from_buffer(buf,
condition);
*/
#include <lttng/condition/evaluation-internal.h>
+#include <lttng/condition/buffer-usage-internal.h>
#include <common/macros.h>
+#include <common/error.h>
#include <stdbool.h>
#include <assert.h>
+LTTNG_HIDDEN
+ssize_t lttng_evaluation_serialize(struct lttng_evaluation *evaluation,
+ char *buf)
+{
+ ssize_t ret, offset = 0;
+ struct lttng_evaluation_comm evaluation_comm;
+
+ evaluation_comm.type = (int8_t) evaluation->type;
+ if (buf) {
+ memcpy(buf, &evaluation_comm, sizeof(evaluation_comm));
+ }
+ offset += sizeof(evaluation_comm);
+
+ if (evaluation->serialize) {
+ ret = evaluation->serialize(evaluation,
+ buf ? (buf + offset) : NULL);
+ if (ret < 0) {
+ goto end;
+ }
+ offset += ret;
+ }
+
+ ret = offset;
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_evaluation_create_from_buffer(const char *buf,
+ struct lttng_evaluation **evaluation)
+{
+ ssize_t ret, evaluation_size = 0;
+ struct lttng_evaluation_comm *evaluation_comm =
+ (struct lttng_evaluation_comm *) buf;
+
+ if (!buf || !evaluation) {
+ ret = -1;
+ goto end;
+ }
+
+ evaluation_size += sizeof(*evaluation_comm);
+ buf += evaluation_size;
+
+ switch ((enum lttng_condition_type) evaluation_comm->type) {
+ case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
+ ret = lttng_evaluation_buffer_usage_low_create_from_buffer(buf,
+ evaluation);
+ if (ret < 0) {
+ goto end;
+ }
+ evaluation_size += ret;
+ break;
+ case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
+ ret = lttng_evaluation_buffer_usage_high_create_from_buffer(buf,
+ evaluation);
+ if (ret < 0) {
+ goto end;
+ }
+ evaluation_size += ret;
+ break;
+ default:
+ ERR("Attempted to create evaluation of unknown type (%i)",
+ (int) evaluation_comm->type);
+ ret = -1;
+ goto end;
+ }
+ ret = evaluation_size;
+end:
+ return ret;
+}
+
enum lttng_condition_type lttng_evaluation_get_type(
struct lttng_evaluation *evaluation)
{
*/
#include <lttng/notification/notification-internal.h>
+#include <lttng/condition/condition-internal.h>
+#include <lttng/condition/evaluation-internal.h>
#include <lttng/condition/condition.h>
#include <lttng/condition/evaluation.h>
#include <assert.h>
return notification;
}
+LTTNG_HIDDEN
+ssize_t lttng_notification_serialize(struct lttng_notification *notification,
+ char *buf)
+{
+ ssize_t ret, condition_size, evaluation_size, offset = 0;
+ struct lttng_notification_comm notification_comm;
+
+ if (!notification) {
+ ret = -1;
+ goto end;
+ }
+
+ offset += sizeof(notification_comm);
+ condition_size = lttng_condition_serialize(notification->condition,
+ buf ? (buf + offset) : NULL);
+ if (condition_size < 0) {
+ ret = condition_size;
+ goto end;
+ }
+ offset += condition_size;
+
+ evaluation_size = lttng_evaluation_serialize(notification->evaluation,
+ buf ? (buf + offset) : NULL);
+ if (evaluation_size < 0) {
+ ret = evaluation_size;
+ goto end;
+ }
+ offset += evaluation_size;
+
+ if (buf) {
+ notification_comm.length =
+ (uint32_t) (condition_size + evaluation_size);
+ memcpy(buf, ¬ification_comm, sizeof(notification_comm));
+ }
+ ret = offset;
+end:
+ return ret;
+
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_notification_create_from_buffer(const char *buf,
+ struct lttng_notification **notification)
+{
+ ssize_t ret, offset = 0, condition_size, evaluation_size;
+ struct lttng_notification_comm *notification_comm;
+ struct lttng_condition *condition;
+ struct lttng_evaluation *evaluation;
+
+ if (!buf || !notification) {
+ ret = -1;
+ goto end;
+ }
+
+ notification_comm = (struct lttng_notification_comm *) buf;
+ offset += sizeof(*notification_comm);
+
+ /* struct lttng_condition */
+ condition_size = lttng_condition_create_from_buffer(buf + offset,
+ &condition);
+ if (condition_size < 0) {
+ ret = condition_size;
+ goto end;
+ }
+ offset += condition_size;
+
+ /* struct lttng_evaluation */
+ evaluation_size = lttng_evaluation_create_from_buffer(buf + offset,
+ &evaluation);
+ if (evaluation_size < 0) {
+ ret = evaluation_size;
+ goto end;
+ }
+ offset += evaluation_size;
+
+ /* Unexpected size of inner-elements; the buffer is corrupted. */
+ if ((ssize_t) notification_comm->length !=
+ condition_size + evaluation_size) {
+ ret = -1;
+ goto error;
+ }
+
+ *notification = lttng_notification_create(condition, evaluation);
+ if (!*notification) {
+ goto error;
+ }
+ ret = offset;
+end:
+ return ret;
+error:
+ lttng_condition_destroy(condition);
+ lttng_evaluation_destroy(evaluation);
+ return ret;
+}
+
void lttng_notification_destroy(struct lttng_notification *notification)
{
if (!notification) {
return trigger;
}
+struct lttng_condition *lttng_trigger_get_condition(
+ struct lttng_trigger *trigger)
+{
+ return trigger ? trigger->condition : NULL;
+}
+
+extern struct lttng_action *lttng_trigger_get_action(
+ struct lttng_trigger *trigger)
+{
+ return trigger ? trigger->action : NULL;
+}
+
void lttng_trigger_destroy(struct lttng_trigger *trigger)
{
if (!trigger) {
ssize_t lttng_trigger_create_from_buffer(const char *buf,
struct lttng_trigger **trigger)
{
- ssize_t ret, trigger_size;
+ ssize_t ret, offset = 0, condition_size, action_size;
struct lttng_condition *condition = NULL;
struct lttng_action *action = NULL;
+ struct lttng_trigger_comm *trigger_comm;
if (!buf || !trigger) {
ret = -1;
goto end;
}
- DBG("Deserializing trigger from buffer");
- ret = lttng_condition_create_from_buffer(buf, &condition);
- if (ret < 0) {
+ /* lttng_trigger_comm header */
+ trigger_comm = (struct lttng_trigger_comm *) buf;
+ offset += sizeof(*trigger_comm);
+
+ /* struct lttng_condition */
+ condition_size = lttng_condition_create_from_buffer(buf + offset,
+ &condition);
+ if (condition_size < 0) {
+ ret = condition_size;
goto end;
}
+ offset += condition_size;
- trigger_size = ret;
- buf += ret;
- ret = lttng_action_create_from_buffer(buf, &action);
- if (ret < 0) {
+ /* struct lttng_action */
+ action_size = lttng_action_create_from_buffer(buf + offset, &action);
+ if (action_size < 0) {
+ ret = action_size;
goto end;
}
+ offset += action_size;
+
+ /* Unexpected size of inner-elements; the buffer is corrupted. */
+ if ((ssize_t) trigger_comm->length != condition_size + action_size) {
+ ret = -1;
+ goto error;
+ }
- trigger_size += ret;
*trigger = lttng_trigger_create(condition, action);
if (!*trigger) {
goto error;
}
- ret = trigger_size;
+ ret = offset;
end:
return ret;
error:
}
/*
- * Returns the size of a trigger's condition and action.
+ * Returns the size of a trigger (header + condition + action).
* Both elements are stored contiguously, see their "*_comm" structure
* for the detailed format.
*/
LTTNG_HIDDEN
ssize_t lttng_trigger_serialize(struct lttng_trigger *trigger, char *buf)
{
- ssize_t action_size, condition_size, ret;
+ struct lttng_trigger_comm trigger_comm;
+ ssize_t action_size, condition_size, offset = 0, ret;
if (!trigger) {
ret = -1;
goto end;
}
- condition_size = lttng_condition_serialize(trigger->condition, NULL);
+ offset += sizeof(trigger_comm);
+ condition_size = lttng_condition_serialize(trigger->condition,
+ buf ? (buf + offset) : NULL);
if (condition_size < 0) {
ret = -1;
goto end;
}
+ offset += condition_size;
- action_size = lttng_action_serialize(trigger->action, NULL);
+ action_size = lttng_action_serialize(trigger->action,
+ buf ? (buf + offset) : NULL);
if (action_size < 0) {
ret = -1;
goto end;
}
+ offset += action_size;
- ret = action_size + condition_size;
- if (!buf) {
- goto end;
- }
-
- condition_size = lttng_condition_serialize(trigger->condition, buf);
- if (condition_size < 0) {
- ret = -1;
- goto end;
- }
-
- buf += condition_size;
- action_size = lttng_action_serialize(trigger->action, buf);
- if (action_size < 0) {
- ret = -1;
- goto end;
+ if (buf) {
+ trigger_comm.length = (uint32_t) (condition_size + action_size);
+ memcpy(buf, &trigger_comm, sizeof(trigger_comm));
}
+ ret = offset;
end:
return ret;
}