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