Fix: unchecked buffer size for communication header
[lttng-tools.git] / src / common / buffer-usage.c
CommitLineData
a58c490f 1/*
ab5be9fa 2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
a58c490f 3 *
ab5be9fa 4 * SPDX-License-Identifier: LGPL-2.1-only
a58c490f 5 *
a58c490f
JG
6 */
7
8#include <lttng/condition/condition-internal.h>
9#include <lttng/condition/buffer-usage-internal.h>
10#include <common/macros.h>
11#include <common/error.h>
12#include <assert.h>
13#include <math.h>
14#include <float.h>
15#include <time.h>
16
17#define IS_USAGE_CONDITION(condition) ( \
18 lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW || \
19 lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH \
20 )
21
22static
23double fixed_to_double(uint32_t val)
24{
25 return (double) val / (double) UINT32_MAX;
26}
27
28static
29uint64_t double_to_fixed(double val)
30{
31 return (val * (double) UINT32_MAX);
32}
33
34static
35bool is_usage_evaluation(const struct lttng_evaluation *evaluation)
36{
37 enum lttng_condition_type type = lttng_evaluation_get_type(evaluation);
38
39 return type == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW ||
40 type == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH;
41}
42
43static
44void lttng_condition_buffer_usage_destroy(struct lttng_condition *condition)
45{
46 struct lttng_condition_buffer_usage *usage;
47
48 usage = container_of(condition, struct lttng_condition_buffer_usage,
49 parent);
50
51 free(usage->session_name);
52 free(usage->channel_name);
53 free(usage);
54}
55
56static
57bool lttng_condition_buffer_usage_validate(
58 const struct lttng_condition *condition)
59{
60 bool valid = false;
61 struct lttng_condition_buffer_usage *usage;
62
63 if (!condition) {
64 goto end;
65 }
66
67 usage = container_of(condition, struct lttng_condition_buffer_usage,
68 parent);
69 if (!usage->session_name) {
70 ERR("Invalid buffer condition: a target session name must be set.");
71 goto end;
72 }
73 if (!usage->channel_name) {
74 ERR("Invalid buffer condition: a target channel name must be set.");
75 goto end;
76 }
77 if (!usage->threshold_ratio.set && !usage->threshold_bytes.set) {
78 ERR("Invalid buffer condition: a threshold must be set.");
79 goto end;
80 }
821d5e92
JG
81 if (!usage->domain.set) {
82 ERR("Invalid buffer usage condition: a domain must be set.");
83 goto end;
84 }
a58c490f
JG
85
86 valid = true;
87end:
88 return valid;
89}
90
91static
3647288f
JG
92int lttng_condition_buffer_usage_serialize(
93 const struct lttng_condition *condition,
c0a66c84 94 struct lttng_payload *payload)
a58c490f 95{
3647288f 96 int ret;
a58c490f 97 struct lttng_condition_buffer_usage *usage;
a58c490f 98 size_t session_name_len, channel_name_len;
3647288f 99 struct lttng_condition_buffer_usage_comm usage_comm;
a58c490f
JG
100
101 if (!condition || !IS_USAGE_CONDITION(condition)) {
102 ret = -1;
103 goto end;
104 }
105
106 DBG("Serializing buffer usage condition");
107 usage = container_of(condition, struct lttng_condition_buffer_usage,
108 parent);
3647288f 109
a58c490f
JG
110 session_name_len = strlen(usage->session_name) + 1;
111 channel_name_len = strlen(usage->channel_name) + 1;
112 if (session_name_len > LTTNG_NAME_MAX ||
113 channel_name_len > LTTNG_NAME_MAX) {
114 ret = -1;
115 goto end;
116 }
3647288f
JG
117
118 usage_comm.threshold_set_in_bytes = !!usage->threshold_bytes.set;
119 usage_comm.session_name_len = session_name_len;
120 usage_comm.channel_name_len = channel_name_len;
121 usage_comm.domain_type = (int8_t) usage->domain.type;
122
123 if (usage->threshold_bytes.set) {
124 usage_comm.threshold = usage->threshold_bytes.value;
125 } else {
126 uint64_t val = double_to_fixed(
127 usage->threshold_ratio.value);
128
129 if (val > UINT32_MAX) {
130 /* overflow. */
131 ret = -1;
132 goto end;
a58c490f 133 }
3647288f
JG
134 usage_comm.threshold = val;
135 }
a58c490f 136
c0a66c84 137 ret = lttng_dynamic_buffer_append(&payload->buffer, &usage_comm,
3647288f
JG
138 sizeof(usage_comm));
139 if (ret) {
140 goto end;
141 }
c0a66c84
JG
142
143 ret = lttng_dynamic_buffer_append(&payload->buffer, usage->session_name,
3647288f
JG
144 session_name_len);
145 if (ret) {
146 goto end;
147 }
c0a66c84
JG
148
149 ret = lttng_dynamic_buffer_append(&payload->buffer, usage->channel_name,
3647288f
JG
150 channel_name_len);
151 if (ret) {
152 goto end;
a58c490f 153 }
a58c490f
JG
154end:
155 return ret;
156}
157
158static
159bool lttng_condition_buffer_usage_is_equal(const struct lttng_condition *_a,
160 const struct lttng_condition *_b)
161{
162 bool is_equal = false;
163 struct lttng_condition_buffer_usage *a, *b;
164
165 a = container_of(_a, struct lttng_condition_buffer_usage, parent);
166 b = container_of(_b, struct lttng_condition_buffer_usage, parent);
167
168 if ((a->threshold_ratio.set && !b->threshold_ratio.set) ||
169 (a->threshold_bytes.set && !b->threshold_bytes.set)) {
170 goto end;
171 }
172
173 if (a->threshold_ratio.set && b->threshold_ratio.set) {
174 double a_value, b_value, diff;
175
176 a_value = a->threshold_ratio.value;
177 b_value = b->threshold_ratio.value;
178 diff = fabs(a_value - b_value);
179
180 if (diff > DBL_EPSILON) {
181 goto end;
182 }
183 } else if (a->threshold_bytes.set && b->threshold_bytes.set) {
184 uint64_t a_value, b_value;
185
186 a_value = a->threshold_bytes.value;
187 b_value = b->threshold_bytes.value;
188 if (a_value != b_value) {
189 goto end;
190 }
191 }
192
821d5e92
JG
193 /* Condition is not valid if this is not true. */
194 assert(a->session_name);
195 assert(b->session_name);
196 if (strcmp(a->session_name, b->session_name)) {
a58c490f
JG
197 goto end;
198 }
199
821d5e92
JG
200 assert(a->channel_name);
201 assert(b->channel_name);
202 if (strcmp(a->channel_name, b->channel_name)) {
a58c490f
JG
203 goto end;
204 }
205
821d5e92
JG
206 assert(a->domain.set);
207 assert(b->domain.set);
208 if (a->domain.type != b->domain.type) {
a58c490f
JG
209 goto end;
210 }
a58c490f
JG
211 is_equal = true;
212end:
213 return is_equal;
214}
215
216static
217struct lttng_condition *lttng_condition_buffer_usage_create(
218 enum lttng_condition_type type)
219{
220 struct lttng_condition_buffer_usage *condition;
221
222 condition = zmalloc(sizeof(struct lttng_condition_buffer_usage));
223 if (!condition) {
9a09eef5 224 return NULL;
a58c490f
JG
225 }
226
227 lttng_condition_init(&condition->parent, type);
228 condition->parent.validate = lttng_condition_buffer_usage_validate;
229 condition->parent.serialize = lttng_condition_buffer_usage_serialize;
230 condition->parent.equal = lttng_condition_buffer_usage_is_equal;
231 condition->parent.destroy = lttng_condition_buffer_usage_destroy;
a58c490f
JG
232 return &condition->parent;
233}
234
235struct lttng_condition *lttng_condition_buffer_usage_low_create(void)
236{
237 return lttng_condition_buffer_usage_create(
238 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW);
239}
240
241struct lttng_condition *lttng_condition_buffer_usage_high_create(void)
242{
243 return lttng_condition_buffer_usage_create(
244 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH);
245}
246
247static
c0a66c84
JG
248ssize_t init_condition_from_payload(struct lttng_condition *condition,
249 struct lttng_payload_view *src_view)
a58c490f
JG
250{
251 ssize_t ret, condition_size;
252 enum lttng_condition_status status;
253 enum lttng_domain_type domain_type;
a58c490f
JG
254 const char *session_name, *channel_name;
255 struct lttng_buffer_view names_view;
3e6e0df2
JG
256 const struct lttng_condition_buffer_usage_comm *condition_comm;
257 const struct lttng_payload_view condition_comm_view =
258 lttng_payload_view_from_view(
259 src_view, 0, sizeof(*condition_comm));
a58c490f 260
3e6e0df2 261 if (!lttng_payload_view_is_valid(&condition_comm_view)) {
a58c490f
JG
262 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
263 ret = -1;
264 goto end;
265 }
266
3e6e0df2 267 condition_comm = (typeof(condition_comm)) condition_comm_view.buffer.data;
c0a66c84 268 names_view = lttng_buffer_view_from_view(&src_view->buffer,
a58c490f
JG
269 sizeof(*condition_comm), -1);
270
271 if (condition_comm->session_name_len > LTTNG_NAME_MAX ||
272 condition_comm->channel_name_len > LTTNG_NAME_MAX) {
273 ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
274 ret = -1;
275 goto end;
276 }
277
278 if (names_view.size <
279 (condition_comm->session_name_len +
280 condition_comm->channel_name_len)) {
281 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain element names");
282 ret = -1;
283 goto end;
284 }
285
286 if (condition_comm->threshold_set_in_bytes) {
287 status = lttng_condition_buffer_usage_set_threshold(condition,
288 condition_comm->threshold);
289 } else {
290 status = lttng_condition_buffer_usage_set_threshold_ratio(
291 condition,
292 fixed_to_double(condition_comm->threshold));
293 }
c0a66c84 294
a58c490f
JG
295 if (status != LTTNG_CONDITION_STATUS_OK) {
296 ERR("Failed to initialize buffer usage condition threshold");
297 ret = -1;
298 goto end;
299 }
300
301 if (condition_comm->domain_type <= LTTNG_DOMAIN_NONE ||
302 condition_comm->domain_type > LTTNG_DOMAIN_PYTHON) {
303 /* Invalid domain value. */
304 ERR("Invalid domain type value (%i) found in condition buffer",
305 (int) condition_comm->domain_type);
306 ret = -1;
307 goto end;
308 }
309
310 domain_type = (enum lttng_domain_type) condition_comm->domain_type;
311 status = lttng_condition_buffer_usage_set_domain_type(condition,
312 domain_type);
313 if (status != LTTNG_CONDITION_STATUS_OK) {
314 ERR("Failed to set buffer usage condition domain");
315 ret = -1;
316 goto end;
317 }
318
319 session_name = names_view.data;
320 if (*(session_name + condition_comm->session_name_len - 1) != '\0') {
321 ERR("Malformed session name encountered in condition buffer");
322 ret = -1;
323 goto end;
324 }
325
326 channel_name = session_name + condition_comm->session_name_len;
327 if (*(channel_name + condition_comm->channel_name_len - 1) != '\0') {
328 ERR("Malformed channel name encountered in condition buffer");
329 ret = -1;
330 goto end;
331 }
332
333 status = lttng_condition_buffer_usage_set_session_name(condition,
334 session_name);
335 if (status != LTTNG_CONDITION_STATUS_OK) {
336 ERR("Failed to set buffer usage session name");
337 ret = -1;
338 goto end;
339 }
340
341 status = lttng_condition_buffer_usage_set_channel_name(condition,
342 channel_name);
343 if (status != LTTNG_CONDITION_STATUS_OK) {
344 ERR("Failed to set buffer usage channel name");
345 ret = -1;
346 goto end;
347 }
348
349 if (!lttng_condition_validate(condition)) {
350 ret = -1;
351 goto end;
352 }
353
354 condition_size = sizeof(*condition_comm) +
355 (ssize_t) condition_comm->session_name_len +
356 (ssize_t) condition_comm->channel_name_len;
357 ret = condition_size;
358end:
359 return ret;
360}
361
362LTTNG_HIDDEN
c0a66c84
JG
363ssize_t lttng_condition_buffer_usage_low_create_from_payload(
364 struct lttng_payload_view *view,
a58c490f
JG
365 struct lttng_condition **_condition)
366{
367 ssize_t ret;
368 struct lttng_condition *condition =
369 lttng_condition_buffer_usage_low_create();
370
371 if (!_condition || !condition) {
372 ret = -1;
373 goto error;
374 }
375
c0a66c84 376 ret = init_condition_from_payload(condition, view);
a58c490f
JG
377 if (ret < 0) {
378 goto error;
379 }
380
381 *_condition = condition;
382 return ret;
383error:
384 lttng_condition_destroy(condition);
385 return ret;
386}
387
388LTTNG_HIDDEN
c0a66c84
JG
389ssize_t lttng_condition_buffer_usage_high_create_from_payload(
390 struct lttng_payload_view *view,
a58c490f
JG
391 struct lttng_condition **_condition)
392{
393 ssize_t ret;
394 struct lttng_condition *condition =
395 lttng_condition_buffer_usage_high_create();
396
397 if (!_condition || !condition) {
398 ret = -1;
399 goto error;
400 }
401
c0a66c84 402 ret = init_condition_from_payload(condition, view);
a58c490f
JG
403 if (ret < 0) {
404 goto error;
405 }
406
407 *_condition = condition;
408 return ret;
409error:
410 lttng_condition_destroy(condition);
411 return ret;
412}
413
414static
c0a66c84 415struct lttng_evaluation *create_evaluation_from_payload(
a58c490f 416 enum lttng_condition_type type,
c0a66c84 417 struct lttng_payload_view *view)
a58c490f
JG
418{
419 const struct lttng_evaluation_buffer_usage_comm *comm =
c0a66c84 420 (typeof(comm)) view->buffer.data;
a58c490f
JG
421 struct lttng_evaluation *evaluation = NULL;
422
c0a66c84 423 if (view->buffer.size < sizeof(*comm)) {
a58c490f
JG
424 goto end;
425 }
426
427 evaluation = lttng_evaluation_buffer_usage_create(type,
428 comm->buffer_use, comm->buffer_capacity);
429end:
430 return evaluation;
431}
432
433LTTNG_HIDDEN
c0a66c84
JG
434ssize_t lttng_evaluation_buffer_usage_low_create_from_payload(
435 struct lttng_payload_view *view,
a58c490f
JG
436 struct lttng_evaluation **_evaluation)
437{
438 ssize_t ret;
439 struct lttng_evaluation *evaluation = NULL;
440
441 if (!_evaluation) {
442 ret = -1;
443 goto error;
444 }
445
c0a66c84 446 evaluation = create_evaluation_from_payload(
a58c490f
JG
447 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW, view);
448 if (!evaluation) {
449 ret = -1;
450 goto error;
451 }
452
453 *_evaluation = evaluation;
454 ret = sizeof(struct lttng_evaluation_buffer_usage_comm);
455 return ret;
456error:
457 lttng_evaluation_destroy(evaluation);
458 return ret;
459}
460
461LTTNG_HIDDEN
c0a66c84
JG
462ssize_t lttng_evaluation_buffer_usage_high_create_from_payload(
463 struct lttng_payload_view *view,
a58c490f
JG
464 struct lttng_evaluation **_evaluation)
465{
466 ssize_t ret;
467 struct lttng_evaluation *evaluation = NULL;
468
469 if (!_evaluation) {
470 ret = -1;
471 goto error;
472 }
473
c0a66c84 474 evaluation = create_evaluation_from_payload(
a58c490f
JG
475 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH, view);
476 if (!evaluation) {
477 ret = -1;
478 goto error;
479 }
480
481 *_evaluation = evaluation;
482 ret = sizeof(struct lttng_evaluation_buffer_usage_comm);
483 return ret;
484error:
485 lttng_evaluation_destroy(evaluation);
486 return ret;
487}
488
489enum lttng_condition_status
490lttng_condition_buffer_usage_get_threshold_ratio(
491 const struct lttng_condition *condition,
492 double *threshold_ratio)
493{
494 struct lttng_condition_buffer_usage *usage;
495 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
496
497 if (!condition || !IS_USAGE_CONDITION(condition) ||
498 !threshold_ratio) {
499 status = LTTNG_CONDITION_STATUS_INVALID;
500 goto end;
501 }
502
503 usage = container_of(condition, struct lttng_condition_buffer_usage,
504 parent);
505 if (!usage->threshold_ratio.set) {
506 status = LTTNG_CONDITION_STATUS_UNSET;
507 goto end;
508 }
509 *threshold_ratio = usage->threshold_ratio.value;
510end:
511 return status;
512}
513
514/* threshold_ratio expressed as [0.0, 1.0]. */
515enum lttng_condition_status
516lttng_condition_buffer_usage_set_threshold_ratio(
517 struct lttng_condition *condition, double threshold_ratio)
518{
519 struct lttng_condition_buffer_usage *usage;
520 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
521
522 if (!condition || !IS_USAGE_CONDITION(condition) ||
523 threshold_ratio < 0.0 ||
524 threshold_ratio > 1.0) {
525 status = LTTNG_CONDITION_STATUS_INVALID;
526 goto end;
527 }
528
529 usage = container_of(condition, struct lttng_condition_buffer_usage,
530 parent);
531 usage->threshold_ratio.set = true;
532 usage->threshold_bytes.set = false;
533 usage->threshold_ratio.value = threshold_ratio;
534end:
535 return status;
536}
537
538enum lttng_condition_status
539lttng_condition_buffer_usage_get_threshold(
540 const struct lttng_condition *condition,
541 uint64_t *threshold_bytes)
542{
543 struct lttng_condition_buffer_usage *usage;
544 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
545
546 if (!condition || !IS_USAGE_CONDITION(condition) || !threshold_bytes) {
547 status = LTTNG_CONDITION_STATUS_INVALID;
548 goto end;
549 }
550
551 usage = container_of(condition, struct lttng_condition_buffer_usage,
552 parent);
553 if (!usage->threshold_bytes.set) {
554 status = LTTNG_CONDITION_STATUS_UNSET;
555 goto end;
556 }
557 *threshold_bytes = usage->threshold_bytes.value;
558end:
559 return status;
560}
561
562enum lttng_condition_status
563lttng_condition_buffer_usage_set_threshold(
564 struct lttng_condition *condition, uint64_t threshold_bytes)
565{
566 struct lttng_condition_buffer_usage *usage;
567 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
568
569 if (!condition || !IS_USAGE_CONDITION(condition)) {
570 status = LTTNG_CONDITION_STATUS_INVALID;
571 goto end;
572 }
573
574 usage = container_of(condition, struct lttng_condition_buffer_usage,
575 parent);
576 usage->threshold_ratio.set = false;
577 usage->threshold_bytes.set = true;
578 usage->threshold_bytes.value = threshold_bytes;
579end:
580 return status;
581}
582
583enum lttng_condition_status
584lttng_condition_buffer_usage_get_session_name(
585 const struct lttng_condition *condition,
586 const char **session_name)
587{
588 struct lttng_condition_buffer_usage *usage;
589 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
590
591 if (!condition || !IS_USAGE_CONDITION(condition) || !session_name) {
592 status = LTTNG_CONDITION_STATUS_INVALID;
593 goto end;
594 }
595
596 usage = container_of(condition, struct lttng_condition_buffer_usage,
597 parent);
598 if (!usage->session_name) {
599 status = LTTNG_CONDITION_STATUS_UNSET;
600 goto end;
601 }
602 *session_name = usage->session_name;
603end:
604 return status;
605}
606
607enum lttng_condition_status
608lttng_condition_buffer_usage_set_session_name(
609 struct lttng_condition *condition, const char *session_name)
610{
611 char *session_name_copy;
612 struct lttng_condition_buffer_usage *usage;
613 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
614
615 if (!condition || !IS_USAGE_CONDITION(condition) || !session_name ||
616 strlen(session_name) == 0) {
617 status = LTTNG_CONDITION_STATUS_INVALID;
618 goto end;
619 }
620
621 usage = container_of(condition, struct lttng_condition_buffer_usage,
622 parent);
623 session_name_copy = strdup(session_name);
624 if (!session_name_copy) {
625 status = LTTNG_CONDITION_STATUS_ERROR;
626 goto end;
627 }
628
629 if (usage->session_name) {
630 free(usage->session_name);
631 }
632 usage->session_name = session_name_copy;
633end:
634 return status;
635}
636
637enum lttng_condition_status
638lttng_condition_buffer_usage_get_channel_name(
639 const struct lttng_condition *condition,
640 const char **channel_name)
641{
642 struct lttng_condition_buffer_usage *usage;
643 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
644
645 if (!condition || !IS_USAGE_CONDITION(condition) || !channel_name) {
646 status = LTTNG_CONDITION_STATUS_INVALID;
647 goto end;
648 }
649
650 usage = container_of(condition, struct lttng_condition_buffer_usage,
651 parent);
652 if (!usage->channel_name) {
653 status = LTTNG_CONDITION_STATUS_UNSET;
654 goto end;
655 }
656 *channel_name = usage->channel_name;
657end:
658 return status;
659}
660
661enum lttng_condition_status
662lttng_condition_buffer_usage_set_channel_name(
663 struct lttng_condition *condition, const char *channel_name)
664{
665 char *channel_name_copy;
666 struct lttng_condition_buffer_usage *usage;
667 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
668
669 if (!condition || !IS_USAGE_CONDITION(condition) || !channel_name ||
670 strlen(channel_name) == 0) {
671 status = LTTNG_CONDITION_STATUS_INVALID;
672 goto end;
673 }
674
675 usage = container_of(condition, struct lttng_condition_buffer_usage,
676 parent);
677 channel_name_copy = strdup(channel_name);
678 if (!channel_name_copy) {
679 status = LTTNG_CONDITION_STATUS_ERROR;
680 goto end;
681 }
682
683 if (usage->channel_name) {
684 free(usage->channel_name);
685 }
686 usage->channel_name = channel_name_copy;
687end:
688 return status;
689}
690
691enum lttng_condition_status
692lttng_condition_buffer_usage_get_domain_type(
693 const struct lttng_condition *condition,
694 enum lttng_domain_type *type)
695{
696 struct lttng_condition_buffer_usage *usage;
697 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
698
699 if (!condition || !IS_USAGE_CONDITION(condition) || !type) {
700 status = LTTNG_CONDITION_STATUS_INVALID;
701 goto end;
702 }
703
704 usage = container_of(condition, struct lttng_condition_buffer_usage,
705 parent);
706 if (!usage->domain.set) {
707 status = LTTNG_CONDITION_STATUS_UNSET;
708 goto end;
709 }
710 *type = usage->domain.type;
711end:
712 return status;
713}
714
715enum lttng_condition_status
716lttng_condition_buffer_usage_set_domain_type(
717 struct lttng_condition *condition, enum lttng_domain_type type)
718{
719 struct lttng_condition_buffer_usage *usage;
720 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
721
722 if (!condition || !IS_USAGE_CONDITION(condition) ||
723 type == LTTNG_DOMAIN_NONE) {
724 status = LTTNG_CONDITION_STATUS_INVALID;
725 goto end;
726 }
727
728 usage = container_of(condition, struct lttng_condition_buffer_usage,
729 parent);
730 usage->domain.set = true;
731 usage->domain.type = type;
732end:
733 return status;
734}
735
736static
3647288f 737int lttng_evaluation_buffer_usage_serialize(
9b63a4aa 738 const struct lttng_evaluation *evaluation,
c0a66c84 739 struct lttng_payload *payload)
a58c490f 740{
a58c490f 741 struct lttng_evaluation_buffer_usage *usage;
3647288f 742 struct lttng_evaluation_buffer_usage_comm comm;
a58c490f
JG
743
744 usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
745 parent);
3647288f
JG
746 comm.buffer_use = usage->buffer_use;
747 comm.buffer_capacity = usage->buffer_capacity;
a58c490f 748
c0a66c84
JG
749 return lttng_dynamic_buffer_append(
750 &payload->buffer, &comm, sizeof(comm));
a58c490f
JG
751}
752
753static
754void lttng_evaluation_buffer_usage_destroy(
755 struct lttng_evaluation *evaluation)
756{
757 struct lttng_evaluation_buffer_usage *usage;
758
759 usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
760 parent);
761 free(usage);
762}
763
764LTTNG_HIDDEN
765struct lttng_evaluation *lttng_evaluation_buffer_usage_create(
766 enum lttng_condition_type type, uint64_t use, uint64_t capacity)
767{
768 struct lttng_evaluation_buffer_usage *usage;
769
770 usage = zmalloc(sizeof(struct lttng_evaluation_buffer_usage));
771 if (!usage) {
772 goto end;
773 }
774
775 usage->parent.type = type;
776 usage->buffer_use = use;
777 usage->buffer_capacity = capacity;
778 usage->parent.serialize = lttng_evaluation_buffer_usage_serialize;
779 usage->parent.destroy = lttng_evaluation_buffer_usage_destroy;
780end:
781 return &usage->parent;
782}
783
784/*
785 * Get the sampled buffer usage which caused the associated condition to
786 * evaluate to "true".
787 */
788enum lttng_evaluation_status
789lttng_evaluation_buffer_usage_get_usage_ratio(
790 const struct lttng_evaluation *evaluation, double *usage_ratio)
791{
792 struct lttng_evaluation_buffer_usage *usage;
793 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
794
795 if (!evaluation || !is_usage_evaluation(evaluation) || !usage_ratio) {
796 status = LTTNG_EVALUATION_STATUS_INVALID;
797 goto end;
798 }
799
800 usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
801 parent);
802 *usage_ratio = (double) usage->buffer_use /
803 (double) usage->buffer_capacity;
804end:
805 return status;
806}
807
808enum lttng_evaluation_status
809lttng_evaluation_buffer_usage_get_usage(
810 const struct lttng_evaluation *evaluation,
811 uint64_t *usage_bytes)
812{
813 struct lttng_evaluation_buffer_usage *usage;
814 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
815
816 if (!evaluation || !is_usage_evaluation(evaluation) || !usage_bytes) {
817 status = LTTNG_EVALUATION_STATUS_INVALID;
818 goto end;
819 }
820
821 usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
822 parent);
823 *usage_bytes = usage->buffer_use;
824end:
825 return status;
826}
This page took 0.062867 seconds and 4 git commands to generate.