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