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