From 3c47cdafec6200f424a5cb5a3ed4601d0691a6eb Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Wed, 8 Mar 2017 22:45:01 -0500 Subject: [PATCH] Various fixes for prototype branch --- .../lttng/condition/buffer-usage-internal.h | 32 ++- include/lttng/condition/buffer-usage.h | 16 +- include/lttng/condition/condition-internal.h | 10 +- include/lttng/condition/condition.h | 4 +- include/lttng/condition/evaluation-internal.h | 12 + include/lttng/notification/channel.h | 7 +- .../notification/notification-internal.h | 16 ++ include/lttng/trigger/trigger-internal.h | 6 +- include/lttng/trigger/trigger.h | 7 +- src/common/buffer-usage.c | 256 +++++++++++++++--- src/common/condition.c | 21 +- src/common/evaluation.c | 73 +++++ src/common/notification.c | 97 +++++++ src/common/trigger.c | 80 ++++-- 14 files changed, 546 insertions(+), 91 deletions(-) diff --git a/include/lttng/condition/buffer-usage-internal.h b/include/lttng/condition/buffer-usage-internal.h index bac144bc6..8c725240b 100644 --- a/include/lttng/condition/buffer-usage-internal.h +++ b/include/lttng/condition/buffer-usage-internal.h @@ -25,7 +25,6 @@ struct lttng_condition_buffer_usage { struct lttng_condition parent; - bool frozen; struct { bool set; uint64_t value; @@ -33,7 +32,7 @@ struct lttng_condition_buffer_usage { struct { bool set; double value; - } threshold_percent; + } threshold_ratio; char *session_name; char *channel_name; struct { @@ -44,10 +43,13 @@ struct lttng_condition_buffer_usage { 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; @@ -63,8 +65,14 @@ struct lttng_evaluation_buffer_usage { 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 @@ -75,4 +83,14 @@ 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 */ diff --git a/include/lttng/condition/buffer-usage.h b/include/lttng/condition/buffer-usage.h index 7c8834eab..fc06ee10e 100644 --- a/include/lttng/condition/buffer-usage.h +++ b/include/lttng/condition/buffer-usage.h @@ -31,17 +31,17 @@ lttng_condition_buffer_usage_low_create(void); 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( @@ -86,9 +86,9 @@ lttng_condition_buffer_usage_set_domain_type( /* 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( diff --git a/include/lttng/condition/condition-internal.h b/include/lttng/condition/condition-internal.h index 652b4369c..5cf12fb7a 100644 --- a/include/lttng/condition/condition-internal.h +++ b/include/lttng/condition/condition-internal.h @@ -27,11 +27,14 @@ typedef void (*condition_destroy_cb)(struct lttng_condition *condition); 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; }; @@ -39,6 +42,7 @@ struct lttng_condition { struct lttng_condition_comm { /* enum lttng_condition_type */ int8_t condition_type; + char payload[]; }; LTTNG_HIDDEN @@ -53,6 +57,10 @@ ssize_t lttng_condition_create_from_buffer(const char *buf, 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 */ diff --git a/include/lttng/condition/condition.h b/include/lttng/condition/condition.h index 9830dbfb1..177b4ab83 100644 --- a/include/lttng/condition/condition.h +++ b/include/lttng/condition/condition.h @@ -28,8 +28,8 @@ struct lttng_condition; 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 { diff --git a/include/lttng/condition/evaluation-internal.h b/include/lttng/condition/evaluation-internal.h index e73411d5c..f52707ca7 100644 --- a/include/lttng/condition/evaluation-internal.h +++ b/include/lttng/condition/evaluation-internal.h @@ -23,15 +23,27 @@ #include 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 */ diff --git a/include/lttng/notification/channel.h b/include/lttng/notification/channel.h index b1c2d6af5..5e6ba9651 100644 --- a/include/lttng/notification/channel.h +++ b/include/lttng/notification/channel.h @@ -29,12 +29,12 @@ struct lttng_notification_channel; /* 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, }; @@ -45,8 +45,7 @@ extern struct lttng_notification_channel *lttng_notification_channel_create( 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( diff --git a/include/lttng/notification/notification-internal.h b/include/lttng/notification/notification-internal.h index d37db1ee5..fc213ac04 100644 --- a/include/lttng/notification/notification-internal.h +++ b/include/lttng/notification/notification-internal.h @@ -20,15 +20,31 @@ #include #include +#include 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 */ diff --git a/include/lttng/trigger/trigger-internal.h b/include/lttng/trigger/trigger-internal.h index 4d90fe84f..5f37057b8 100644 --- a/include/lttng/trigger/trigger-internal.h +++ b/include/lttng/trigger/trigger-internal.h @@ -32,8 +32,10 @@ struct lttng_trigger { }; 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 diff --git a/include/lttng/trigger/trigger.h b/include/lttng/trigger/trigger.h index ea9c16edf..29d42c987 100644 --- a/include/lttng/trigger/trigger.h +++ b/include/lttng/trigger/trigger.h @@ -21,7 +21,6 @@ struct lttng_action; struct lttng_condition; struct lttng_trigger; -struct lttng_endpoint; #ifdef __cplusplus extern "C" { @@ -36,6 +35,12 @@ enum lttng_register_trigger_status { 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); diff --git a/src/common/buffer-usage.c b/src/common/buffer-usage.c index 66449c313..c541d34ed 100644 --- a/src/common/buffer-usage.c +++ b/src/common/buffer-usage.c @@ -20,6 +20,20 @@ #include #include #include +#include +#include + +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; diff --git a/src/common/condition.c b/src/common/condition.c index 4a24202fe..6ee931ec6 100644 --- a/src/common/condition.c +++ b/src/common/condition.c @@ -87,6 +87,25 @@ end: 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) @@ -104,7 +123,7 @@ ssize_t lttng_condition_create_from_buffer(const char *buf, 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); diff --git a/src/common/evaluation.c b/src/common/evaluation.c index 41e59c1d5..49cba5dd1 100644 --- a/src/common/evaluation.c +++ b/src/common/evaluation.c @@ -16,10 +16,83 @@ */ #include +#include #include +#include #include #include +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) { diff --git a/src/common/notification.c b/src/common/notification.c index 4d9640613..a41de7e6f 100644 --- a/src/common/notification.c +++ b/src/common/notification.c @@ -16,6 +16,8 @@ */ #include +#include +#include #include #include #include @@ -42,6 +44,101 @@ end: 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) { diff --git a/src/common/trigger.c b/src/common/trigger.c index ede1ac567..21b527f3b 100644 --- a/src/common/trigger.c +++ b/src/common/trigger.c @@ -59,6 +59,18 @@ end: 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) { @@ -74,34 +86,48 @@ LTTNG_HIDDEN 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: @@ -111,49 +137,43 @@ 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; } -- 2.34.1