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