MI: implement all objects related to trigger machine interface
[lttng-tools.git] / src / common / conditions / 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
a58c490f 8#include <assert.h>
6a751b95
JR
9#include <common/error.h>
10#include <common/macros.h>
11#include <common/mi-lttng.h>
a58c490f 12#include <float.h>
6a751b95
JR
13#include <lttng/condition/buffer-usage-internal.h>
14#include <lttng/condition/condition-internal.h>
15#include <math.h>
a58c490f
JG
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
a58c490f
JG
23static
24bool 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
32static
33void 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
45static
46bool 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 }
70ee6d20
JR
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.");
a58c490f
JG
68 goto end;
69 }
821d5e92
JG
70 if (!usage->domain.set) {
71 ERR("Invalid buffer usage condition: a domain must be set.");
72 goto end;
73 }
a58c490f
JG
74
75 valid = true;
76end:
77 return valid;
78}
79
80static
3647288f
JG
81int lttng_condition_buffer_usage_serialize(
82 const struct lttng_condition *condition,
c0a66c84 83 struct lttng_payload *payload)
a58c490f 84{
3647288f 85 int ret;
a58c490f 86 struct lttng_condition_buffer_usage *usage;
a58c490f 87 size_t session_name_len, channel_name_len;
d33bfbbf 88 struct lttng_condition_buffer_usage_comm usage_comm = {};
a58c490f
JG
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);
3647288f 98
a58c490f
JG
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 }
3647288f
JG
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) {
f66473ac 113 usage_comm.threshold_bytes = usage->threshold_bytes.value;
3647288f 114 } else {
f66473ac 115 usage_comm.threshold_ratio = usage->threshold_ratio.value;
3647288f 116 }
a58c490f 117
c0a66c84 118 ret = lttng_dynamic_buffer_append(&payload->buffer, &usage_comm,
3647288f
JG
119 sizeof(usage_comm));
120 if (ret) {
121 goto end;
122 }
c0a66c84
JG
123
124 ret = lttng_dynamic_buffer_append(&payload->buffer, usage->session_name,
3647288f
JG
125 session_name_len);
126 if (ret) {
127 goto end;
128 }
c0a66c84
JG
129
130 ret = lttng_dynamic_buffer_append(&payload->buffer, usage->channel_name,
3647288f
JG
131 channel_name_len);
132 if (ret) {
133 goto end;
a58c490f 134 }
a58c490f
JG
135end:
136 return ret;
137}
138
139static
140bool 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
821d5e92
JG
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)) {
a58c490f
JG
178 goto end;
179 }
180
821d5e92
JG
181 assert(a->channel_name);
182 assert(b->channel_name);
183 if (strcmp(a->channel_name, b->channel_name)) {
a58c490f
JG
184 goto end;
185 }
186
821d5e92
JG
187 assert(a->domain.set);
188 assert(b->domain.set);
189 if (a->domain.type != b->domain.type) {
a58c490f
JG
190 goto end;
191 }
a58c490f
JG
192 is_equal = true;
193end:
194 return is_equal;
195}
196
6a751b95
JR
197static 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
313mi_error:
314 ret_code = LTTNG_ERR_MI_IO_FAIL;
315end:
316 return ret_code;
317}
318
a58c490f
JG
319static
320struct 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) {
9a09eef5 327 return NULL;
a58c490f
JG
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;
6a751b95 335 condition->parent.mi_serialize = lttng_condition_buffer_usage_mi_serialize;
a58c490f
JG
336 return &condition->parent;
337}
338
339struct 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
345struct 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
351static
c0a66c84
JG
352ssize_t init_condition_from_payload(struct lttng_condition *condition,
353 struct lttng_payload_view *src_view)
a58c490f
JG
354{
355 ssize_t ret, condition_size;
356 enum lttng_condition_status status;
357 enum lttng_domain_type domain_type;
a58c490f
JG
358 const char *session_name, *channel_name;
359 struct lttng_buffer_view names_view;
3e6e0df2
JG
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));
a58c490f 364
3e6e0df2 365 if (!lttng_payload_view_is_valid(&condition_comm_view)) {
a58c490f
JG
366 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
367 ret = -1;
368 goto end;
369 }
370
3e6e0df2 371 condition_comm = (typeof(condition_comm)) condition_comm_view.buffer.data;
c0a66c84 372 names_view = lttng_buffer_view_from_view(&src_view->buffer,
a58c490f
JG
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,
f66473ac 392 condition_comm->threshold_bytes);
a58c490f
JG
393 } else {
394 status = lttng_condition_buffer_usage_set_threshold_ratio(
f66473ac 395 condition, condition_comm->threshold_ratio);
a58c490f 396 }
c0a66c84 397
a58c490f
JG
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;
461end:
462 return ret;
463}
464
465LTTNG_HIDDEN
c0a66c84
JG
466ssize_t lttng_condition_buffer_usage_low_create_from_payload(
467 struct lttng_payload_view *view,
a58c490f
JG
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
c0a66c84 479 ret = init_condition_from_payload(condition, view);
a58c490f
JG
480 if (ret < 0) {
481 goto error;
482 }
483
484 *_condition = condition;
485 return ret;
486error:
487 lttng_condition_destroy(condition);
488 return ret;
489}
490
491LTTNG_HIDDEN
c0a66c84
JG
492ssize_t lttng_condition_buffer_usage_high_create_from_payload(
493 struct lttng_payload_view *view,
a58c490f
JG
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
c0a66c84 505 ret = init_condition_from_payload(condition, view);
a58c490f
JG
506 if (ret < 0) {
507 goto error;
508 }
509
510 *_condition = condition;
511 return ret;
512error:
513 lttng_condition_destroy(condition);
514 return ret;
515}
516
517static
c0a66c84 518struct lttng_evaluation *create_evaluation_from_payload(
a58c490f 519 enum lttng_condition_type type,
c0a66c84 520 struct lttng_payload_view *view)
a58c490f
JG
521{
522 const struct lttng_evaluation_buffer_usage_comm *comm =
c0a66c84 523 (typeof(comm)) view->buffer.data;
a58c490f
JG
524 struct lttng_evaluation *evaluation = NULL;
525
c0a66c84 526 if (view->buffer.size < sizeof(*comm)) {
a58c490f
JG
527 goto end;
528 }
529
530 evaluation = lttng_evaluation_buffer_usage_create(type,
531 comm->buffer_use, comm->buffer_capacity);
532end:
533 return evaluation;
534}
535
536LTTNG_HIDDEN
c0a66c84
JG
537ssize_t lttng_evaluation_buffer_usage_low_create_from_payload(
538 struct lttng_payload_view *view,
a58c490f
JG
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
c0a66c84 549 evaluation = create_evaluation_from_payload(
a58c490f
JG
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;
559error:
560 lttng_evaluation_destroy(evaluation);
561 return ret;
562}
563
564LTTNG_HIDDEN
c0a66c84
JG
565ssize_t lttng_evaluation_buffer_usage_high_create_from_payload(
566 struct lttng_payload_view *view,
a58c490f
JG
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
c0a66c84 577 evaluation = create_evaluation_from_payload(
a58c490f
JG
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;
587error:
588 lttng_evaluation_destroy(evaluation);
589 return ret;
590}
591
592enum lttng_condition_status
593lttng_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;
613end:
614 return status;
615}
616
617/* threshold_ratio expressed as [0.0, 1.0]. */
618enum lttng_condition_status
619lttng_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;
637end:
638 return status;
639}
640
641enum lttng_condition_status
642lttng_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;
661end:
662 return status;
663}
664
665enum lttng_condition_status
666lttng_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;
682end:
683 return status;
684}
685
686enum lttng_condition_status
687lttng_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;
706end:
707 return status;
708}
709
710enum lttng_condition_status
711lttng_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;
736end:
737 return status;
738}
739
740enum lttng_condition_status
741lttng_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;
760end:
761 return status;
762}
763
764enum lttng_condition_status
765lttng_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;
790end:
791 return status;
792}
793
794enum lttng_condition_status
795lttng_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;
814end:
815 return status;
816}
817
818enum lttng_condition_status
819lttng_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;
835end:
836 return status;
837}
838
839static
3647288f 840int lttng_evaluation_buffer_usage_serialize(
9b63a4aa 841 const struct lttng_evaluation *evaluation,
c0a66c84 842 struct lttng_payload *payload)
a58c490f 843{
a58c490f 844 struct lttng_evaluation_buffer_usage *usage;
3647288f 845 struct lttng_evaluation_buffer_usage_comm comm;
a58c490f
JG
846
847 usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
848 parent);
3647288f
JG
849 comm.buffer_use = usage->buffer_use;
850 comm.buffer_capacity = usage->buffer_capacity;
a58c490f 851
c0a66c84
JG
852 return lttng_dynamic_buffer_append(
853 &payload->buffer, &comm, sizeof(comm));
a58c490f
JG
854}
855
856static
857void 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
867LTTNG_HIDDEN
868struct 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;
883end:
884 return &usage->parent;
885}
886
887/*
888 * Get the sampled buffer usage which caused the associated condition to
889 * evaluate to "true".
890 */
891enum lttng_evaluation_status
892lttng_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;
907end:
908 return status;
909}
910
911enum lttng_evaluation_status
912lttng_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;
927end:
928 return status;
929}
This page took 0.072107 seconds and 4 git commands to generate.