Fix: consumerd: consumed size miscomputed during statistics sampling
[lttng-tools.git] / src / common / actions / rate-policy.cpp
1 /*
2 * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <common/buffer-view.hpp>
9 #include <common/dynamic-buffer.hpp>
10 #include <common/error.hpp>
11 #include <common/macros.hpp>
12 #include <common/mi-lttng.hpp>
13 #include <common/payload-view.hpp>
14 #include <common/payload.hpp>
15
16 #include <lttng/action/rate-policy-internal.hpp>
17 #include <lttng/action/rate-policy.h>
18
19 #include <limits.h>
20 #include <stdbool.h>
21 #include <sys/types.h>
22
23 #define IS_EVERY_N_RATE_POLICY(policy) \
24 (lttng_rate_policy_get_type(policy) == LTTNG_RATE_POLICY_TYPE_EVERY_N)
25
26 #define IS_ONCE_AFTER_N_RATE_POLICY(policy) \
27 (lttng_rate_policy_get_type(policy) == LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N)
28
29 using rate_policy_destroy_cb = void (*)(struct lttng_rate_policy *);
30 using rate_policy_serialize_cb = int (*)(struct lttng_rate_policy *, struct lttng_payload *);
31 using rate_policy_equal_cb = bool (*)(const struct lttng_rate_policy *,
32 const struct lttng_rate_policy *);
33 using rate_policy_create_from_payload_cb = ssize_t (*)(struct lttng_payload_view *,
34 struct lttng_rate_policy **);
35 using rate_policy_copy_cb = struct lttng_rate_policy *(*) (const struct lttng_rate_policy *);
36 using rate_policy_mi_serialize_cb = enum lttng_error_code (*)(const struct lttng_rate_policy *,
37 struct mi_writer *);
38
39 struct lttng_rate_policy {
40 enum lttng_rate_policy_type type;
41 rate_policy_serialize_cb serialize;
42 rate_policy_equal_cb equal;
43 rate_policy_destroy_cb destroy;
44 rate_policy_copy_cb copy;
45 rate_policy_mi_serialize_cb mi_serialize;
46 };
47
48 namespace {
49 struct lttng_rate_policy_every_n {
50 struct lttng_rate_policy parent;
51 uint64_t interval;
52 };
53
54 struct lttng_rate_policy_once_after_n {
55 struct lttng_rate_policy parent;
56 uint64_t threshold;
57 };
58
59 struct lttng_rate_policy_comm {
60 /* enum lttng_rate_policy_type */
61 int8_t rate_policy_type;
62 } LTTNG_PACKED;
63
64 struct lttng_rate_policy_once_after_n_comm {
65 uint64_t threshold;
66 } LTTNG_PACKED;
67
68 struct lttng_rate_policy_every_n_comm {
69 uint64_t interval;
70 } LTTNG_PACKED;
71 } /* namespace */
72
73 /* Forward declaration. */
74 static void lttng_rate_policy_init(struct lttng_rate_policy *rate_policy,
75 enum lttng_rate_policy_type type,
76 rate_policy_serialize_cb serialize,
77 rate_policy_equal_cb equal,
78 rate_policy_destroy_cb destroy,
79 rate_policy_copy_cb copy,
80 rate_policy_mi_serialize_cb mi);
81
82 /* Forward declaration. Every n */
83 static bool lttng_rate_policy_every_n_should_execute(const struct lttng_rate_policy *policy,
84 uint64_t counter);
85
86 /* Forward declaration. Once after N */
87 static bool lttng_rate_policy_once_after_n_should_execute(const struct lttng_rate_policy *policy,
88 uint64_t counter);
89
90 const char *lttng_rate_policy_type_string(enum lttng_rate_policy_type rate_policy_type)
91 {
92 switch (rate_policy_type) {
93 case LTTNG_RATE_POLICY_TYPE_EVERY_N:
94 return "EVERY-N";
95 case LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N:
96 return "ONCE-AFTER-N";
97 default:
98 return "???";
99 }
100 }
101
102 enum lttng_rate_policy_type lttng_rate_policy_get_type(const struct lttng_rate_policy *policy)
103 {
104 return policy ? policy->type : LTTNG_RATE_POLICY_TYPE_UNKNOWN;
105 }
106
107 void lttng_rate_policy_init(struct lttng_rate_policy *rate_policy,
108 enum lttng_rate_policy_type type,
109 rate_policy_serialize_cb serialize,
110 rate_policy_equal_cb equal,
111 rate_policy_destroy_cb destroy,
112 rate_policy_copy_cb copy,
113 rate_policy_mi_serialize_cb mi)
114 {
115 rate_policy->type = type;
116 rate_policy->serialize = serialize;
117 rate_policy->equal = equal;
118 rate_policy->destroy = destroy;
119 rate_policy->copy = copy;
120 rate_policy->mi_serialize = mi;
121 }
122
123 void lttng_rate_policy_destroy(struct lttng_rate_policy *rate_policy)
124 {
125 if (!rate_policy) {
126 return;
127 }
128
129 rate_policy->destroy(rate_policy);
130 }
131
132 int lttng_rate_policy_serialize(struct lttng_rate_policy *rate_policy,
133 struct lttng_payload *payload)
134 {
135 int ret;
136 struct lttng_rate_policy_comm rate_policy_comm = {
137 .rate_policy_type = (int8_t) rate_policy->type,
138 };
139
140 ret = lttng_dynamic_buffer_append(
141 &payload->buffer, &rate_policy_comm, sizeof(rate_policy_comm));
142 if (ret) {
143 goto end;
144 }
145
146 ret = rate_policy->serialize(rate_policy, payload);
147 if (ret) {
148 goto end;
149 }
150 end:
151 return ret;
152 }
153
154 static ssize_t
155 lttng_rate_policy_once_after_n_create_from_payload(struct lttng_payload_view *view,
156 struct lttng_rate_policy **rate_policy)
157 {
158 ssize_t consumed_len = -1;
159 struct lttng_rate_policy *policy = nullptr;
160 const struct lttng_rate_policy_once_after_n_comm *comm;
161 const struct lttng_payload_view comm_view =
162 lttng_payload_view_from_view(view, 0, sizeof(*comm));
163
164 if (!view || !rate_policy) {
165 consumed_len = -1;
166 goto end;
167 }
168
169 if (!lttng_payload_view_is_valid(&comm_view)) {
170 /* Payload not large enough to contain the header. */
171 consumed_len = -1;
172 goto end;
173 }
174
175 comm = (const struct lttng_rate_policy_once_after_n_comm *) comm_view.buffer.data;
176
177 policy = lttng_rate_policy_once_after_n_create(comm->threshold);
178 if (policy == nullptr) {
179 consumed_len = -1;
180 goto end;
181 }
182
183 *rate_policy = policy;
184 consumed_len = sizeof(*comm);
185
186 end:
187 return consumed_len;
188 }
189
190 static ssize_t lttng_rate_policy_every_n_create_from_payload(struct lttng_payload_view *view,
191 struct lttng_rate_policy **rate_policy)
192 {
193 ssize_t consumed_len = -1;
194 struct lttng_rate_policy *policy = nullptr;
195 const struct lttng_rate_policy_every_n_comm *comm;
196 const struct lttng_payload_view comm_view =
197 lttng_payload_view_from_view(view, 0, sizeof(*comm));
198
199 if (!view || !rate_policy) {
200 consumed_len = -1;
201 goto end;
202 }
203
204 if (!lttng_payload_view_is_valid(&comm_view)) {
205 /* Payload not large enough to contain the header. */
206 consumed_len = -1;
207 goto end;
208 }
209
210 comm = (const struct lttng_rate_policy_every_n_comm *) comm_view.buffer.data;
211
212 policy = lttng_rate_policy_every_n_create(comm->interval);
213 if (policy == nullptr) {
214 consumed_len = -1;
215 goto end;
216 }
217
218 *rate_policy = policy;
219 consumed_len = sizeof(*comm);
220
221 end:
222 return consumed_len;
223 }
224
225 ssize_t lttng_rate_policy_create_from_payload(struct lttng_payload_view *view,
226 struct lttng_rate_policy **rate_policy)
227 {
228 ssize_t consumed_len, specific_rate_policy_consumed_len;
229 rate_policy_create_from_payload_cb create_from_payload_cb;
230 const struct lttng_rate_policy_comm *rate_policy_comm;
231 const struct lttng_payload_view rate_policy_comm_view =
232 lttng_payload_view_from_view(view, 0, sizeof(*rate_policy_comm));
233
234 if (!view || !rate_policy) {
235 consumed_len = -1;
236 goto end;
237 }
238
239 if (!lttng_payload_view_is_valid(&rate_policy_comm_view)) {
240 /* Payload not large enough to contain the header. */
241 consumed_len = -1;
242 goto end;
243 }
244
245 rate_policy_comm =
246 (const struct lttng_rate_policy_comm *) rate_policy_comm_view.buffer.data;
247
248 DBG("Create rate_policy from payload: rate-policy-type=%s",
249 lttng_rate_policy_type_string(
250 (lttng_rate_policy_type) rate_policy_comm->rate_policy_type));
251
252 switch (rate_policy_comm->rate_policy_type) {
253 case LTTNG_RATE_POLICY_TYPE_EVERY_N:
254 create_from_payload_cb = lttng_rate_policy_every_n_create_from_payload;
255 break;
256 case LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N:
257 create_from_payload_cb = lttng_rate_policy_once_after_n_create_from_payload;
258 break;
259 default:
260 ERR("Failed to create rate-policy from payload, unhandled rate-policy type: rate-policy-type=%u (%s)",
261 rate_policy_comm->rate_policy_type,
262 lttng_rate_policy_type_string(
263 (lttng_rate_policy_type) rate_policy_comm->rate_policy_type));
264 consumed_len = -1;
265 goto end;
266 }
267
268 {
269 /* Create buffer view for the rate_policy-type-specific data.
270 */
271 struct lttng_payload_view specific_rate_policy_view = lttng_payload_view_from_view(
272 view, sizeof(struct lttng_rate_policy_comm), -1);
273
274 specific_rate_policy_consumed_len =
275 create_from_payload_cb(&specific_rate_policy_view, rate_policy);
276 }
277 if (specific_rate_policy_consumed_len < 0) {
278 ERR("Failed to create specific rate_policy from buffer.");
279 consumed_len = -1;
280 goto end;
281 }
282
283 LTTNG_ASSERT(*rate_policy);
284
285 consumed_len = sizeof(struct lttng_rate_policy_comm) + specific_rate_policy_consumed_len;
286
287 end:
288 return consumed_len;
289 }
290
291 bool lttng_rate_policy_is_equal(const struct lttng_rate_policy *a,
292 const struct lttng_rate_policy *b)
293 {
294 bool is_equal = false;
295
296 if (!a || !b) {
297 goto end;
298 }
299
300 if (a->type != b->type) {
301 goto end;
302 }
303
304 if (a == b) {
305 is_equal = true;
306 goto end;
307 }
308
309 LTTNG_ASSERT(a->equal);
310 is_equal = a->equal(a, b);
311 end:
312 return is_equal;
313 }
314
315 bool lttng_rate_policy_should_execute(const struct lttng_rate_policy *policy, uint64_t counter)
316 {
317 switch (policy->type) {
318 case LTTNG_RATE_POLICY_TYPE_EVERY_N:
319 return lttng_rate_policy_every_n_should_execute(policy, counter);
320 case LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N:
321 return lttng_rate_policy_once_after_n_should_execute(policy, counter);
322 default:
323 abort();
324 break;
325 }
326 }
327
328 /* Every N */
329 static struct lttng_rate_policy_every_n *
330 rate_policy_every_n_from_rate_policy(struct lttng_rate_policy *policy)
331 {
332 LTTNG_ASSERT(policy);
333
334 return lttng::utils::container_of(policy, &lttng_rate_policy_every_n::parent);
335 }
336
337 static const struct lttng_rate_policy_every_n *
338 rate_policy_every_n_from_rate_policy_const(const struct lttng_rate_policy *policy)
339 {
340 LTTNG_ASSERT(policy);
341
342 return lttng::utils::container_of(policy, &lttng_rate_policy_every_n::parent);
343 }
344
345 static int lttng_rate_policy_every_n_serialize(struct lttng_rate_policy *policy,
346 struct lttng_payload *payload)
347 {
348 int ret;
349
350 struct lttng_rate_policy_every_n *every_n_policy;
351 struct lttng_rate_policy_every_n_comm comm = {};
352
353 LTTNG_ASSERT(policy);
354 LTTNG_ASSERT(payload);
355
356 every_n_policy = rate_policy_every_n_from_rate_policy(policy);
357 comm.interval = every_n_policy->interval;
358
359 ret = lttng_dynamic_buffer_append(&payload->buffer, &comm, sizeof(comm));
360 return ret;
361 }
362
363 static bool lttng_rate_policy_every_n_is_equal(const struct lttng_rate_policy *_a,
364 const struct lttng_rate_policy *_b)
365 {
366 bool is_equal = false;
367 const struct lttng_rate_policy_every_n *a, *b;
368
369 a = rate_policy_every_n_from_rate_policy_const(_a);
370 b = rate_policy_every_n_from_rate_policy_const(_b);
371
372 if (a->interval != b->interval) {
373 goto end;
374 }
375
376 is_equal = true;
377
378 end:
379 return is_equal;
380 }
381
382 static void lttng_rate_policy_every_n_destroy(struct lttng_rate_policy *policy)
383 {
384 struct lttng_rate_policy_every_n *every_n_policy;
385
386 if (!policy) {
387 goto end;
388 }
389
390 every_n_policy = rate_policy_every_n_from_rate_policy(policy);
391
392 free(every_n_policy);
393
394 end:
395 return;
396 }
397
398 static struct lttng_rate_policy *
399 lttng_rate_policy_every_n_copy(const struct lttng_rate_policy *source)
400 {
401 struct lttng_rate_policy *copy = nullptr;
402 const struct lttng_rate_policy_every_n *every_n_policy;
403
404 if (!source) {
405 goto end;
406 }
407
408 every_n_policy = rate_policy_every_n_from_rate_policy_const(source);
409 copy = lttng_rate_policy_every_n_create(every_n_policy->interval);
410
411 end:
412 return copy;
413 }
414
415 static enum lttng_error_code
416 lttng_rate_policy_every_n_mi_serialize(const struct lttng_rate_policy *rate_policy,
417 struct mi_writer *writer)
418 {
419 int ret;
420 enum lttng_error_code ret_code;
421 const struct lttng_rate_policy_every_n *every_n_policy = nullptr;
422
423 LTTNG_ASSERT(rate_policy);
424 LTTNG_ASSERT(IS_EVERY_N_RATE_POLICY(rate_policy));
425 LTTNG_ASSERT(writer);
426
427 every_n_policy = rate_policy_every_n_from_rate_policy_const(rate_policy);
428
429 /* Open rate_policy_every_n element. */
430 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_rate_policy_every_n);
431 if (ret) {
432 goto mi_error;
433 }
434
435 /* Interval. */
436 ret = mi_lttng_writer_write_element_unsigned_int(
437 writer, mi_lttng_element_rate_policy_every_n_interval, every_n_policy->interval);
438 if (ret) {
439 goto mi_error;
440 }
441
442 /* Close rate_policy_every_n element. */
443 ret = mi_lttng_writer_close_element(writer);
444 if (ret) {
445 goto mi_error;
446 }
447
448 ret_code = LTTNG_OK;
449 goto end;
450
451 mi_error:
452 ret_code = LTTNG_ERR_MI_IO_FAIL;
453 end:
454 return ret_code;
455 }
456
457 struct lttng_rate_policy *lttng_rate_policy_every_n_create(uint64_t interval)
458 {
459 struct lttng_rate_policy_every_n *policy = nullptr;
460 struct lttng_rate_policy *_policy = nullptr;
461
462 if (interval == 0) {
463 /*
464 * An interval of 0 is invalid since it would never be fired.
465 */
466 goto end;
467 }
468
469 policy = zmalloc<lttng_rate_policy_every_n>();
470 if (!policy) {
471 goto end;
472 }
473
474 lttng_rate_policy_init(&policy->parent,
475 LTTNG_RATE_POLICY_TYPE_EVERY_N,
476 lttng_rate_policy_every_n_serialize,
477 lttng_rate_policy_every_n_is_equal,
478 lttng_rate_policy_every_n_destroy,
479 lttng_rate_policy_every_n_copy,
480 lttng_rate_policy_every_n_mi_serialize);
481
482 policy->interval = interval;
483
484 _policy = &policy->parent;
485 policy = nullptr;
486
487 end:
488 free(policy);
489 return _policy;
490 }
491
492 enum lttng_rate_policy_status
493 lttng_rate_policy_every_n_get_interval(const struct lttng_rate_policy *policy, uint64_t *interval)
494 {
495 const struct lttng_rate_policy_every_n *every_n_policy;
496 enum lttng_rate_policy_status status;
497
498 if (!policy || !IS_EVERY_N_RATE_POLICY(policy) || !interval) {
499 status = LTTNG_RATE_POLICY_STATUS_INVALID;
500 goto end;
501 }
502
503 every_n_policy = rate_policy_every_n_from_rate_policy_const(policy);
504 *interval = every_n_policy->interval;
505 status = LTTNG_RATE_POLICY_STATUS_OK;
506 end:
507
508 return status;
509 }
510
511 static bool lttng_rate_policy_every_n_should_execute(const struct lttng_rate_policy *policy,
512 uint64_t counter)
513 {
514 const struct lttng_rate_policy_every_n *every_n_policy;
515 LTTNG_ASSERT(policy);
516 bool execute = false;
517
518 every_n_policy = rate_policy_every_n_from_rate_policy_const(policy);
519
520 if (every_n_policy->interval == 0) {
521 abort();
522 }
523
524 execute = (counter % every_n_policy->interval) == 0;
525
526 DBG("Policy every N = %" PRIu64 ": execution %s. Execution count: %" PRIu64,
527 every_n_policy->interval,
528 execute ? "accepted" : "denied",
529 counter);
530
531 return execute;
532 }
533
534 /* Once after N */
535
536 static struct lttng_rate_policy_once_after_n *
537 rate_policy_once_after_n_from_rate_policy(struct lttng_rate_policy *policy)
538 {
539 LTTNG_ASSERT(policy);
540
541 return lttng::utils::container_of(policy, &lttng_rate_policy_once_after_n::parent);
542 }
543
544 static const struct lttng_rate_policy_once_after_n *
545 rate_policy_once_after_n_from_rate_policy_const(const struct lttng_rate_policy *policy)
546 {
547 LTTNG_ASSERT(policy);
548
549 return lttng::utils::container_of(policy, &lttng_rate_policy_once_after_n::parent);
550 }
551 static int lttng_rate_policy_once_after_n_serialize(struct lttng_rate_policy *policy,
552 struct lttng_payload *payload)
553 {
554 int ret;
555
556 struct lttng_rate_policy_once_after_n *once_after_n_policy;
557 struct lttng_rate_policy_once_after_n_comm comm = {};
558
559 LTTNG_ASSERT(policy);
560 LTTNG_ASSERT(payload);
561
562 once_after_n_policy = rate_policy_once_after_n_from_rate_policy(policy);
563 comm.threshold = once_after_n_policy->threshold;
564
565 ret = lttng_dynamic_buffer_append(&payload->buffer, &comm, sizeof(comm));
566 return ret;
567 }
568
569 static bool lttng_rate_policy_once_after_n_is_equal(const struct lttng_rate_policy *_a,
570 const struct lttng_rate_policy *_b)
571 {
572 bool is_equal = false;
573 const struct lttng_rate_policy_once_after_n *a, *b;
574
575 a = rate_policy_once_after_n_from_rate_policy_const(_a);
576 b = rate_policy_once_after_n_from_rate_policy_const(_b);
577
578 if (a->threshold != b->threshold) {
579 goto end;
580 }
581
582 is_equal = true;
583
584 end:
585 return is_equal;
586 }
587
588 static void lttng_rate_policy_once_after_n_destroy(struct lttng_rate_policy *policy)
589 {
590 struct lttng_rate_policy_once_after_n *once_after_n_policy;
591
592 if (!policy) {
593 goto end;
594 }
595
596 once_after_n_policy = rate_policy_once_after_n_from_rate_policy(policy);
597
598 free(once_after_n_policy);
599
600 end:
601 return;
602 }
603
604 static struct lttng_rate_policy *
605 lttng_rate_policy_once_after_n_copy(const struct lttng_rate_policy *source)
606 {
607 struct lttng_rate_policy *copy = nullptr;
608 const struct lttng_rate_policy_once_after_n *once_after_n_policy;
609
610 if (!source) {
611 goto end;
612 }
613
614 once_after_n_policy = rate_policy_once_after_n_from_rate_policy_const(source);
615 copy = lttng_rate_policy_once_after_n_create(once_after_n_policy->threshold);
616
617 end:
618 return copy;
619 }
620
621 static enum lttng_error_code
622 lttng_rate_policy_once_after_n_mi_serialize(const struct lttng_rate_policy *rate_policy,
623 struct mi_writer *writer)
624 {
625 int ret;
626 enum lttng_error_code ret_code;
627 const struct lttng_rate_policy_once_after_n *once_after_n_policy = nullptr;
628
629 LTTNG_ASSERT(rate_policy);
630 LTTNG_ASSERT(IS_ONCE_AFTER_N_RATE_POLICY(rate_policy));
631 LTTNG_ASSERT(writer);
632
633 once_after_n_policy = rate_policy_once_after_n_from_rate_policy_const(rate_policy);
634
635 /* Open rate_policy_once_after_n. */
636 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_rate_policy_once_after_n);
637 if (ret) {
638 goto mi_error;
639 }
640
641 /* Threshold. */
642 ret = mi_lttng_writer_write_element_unsigned_int(
643 writer,
644 mi_lttng_element_rate_policy_once_after_n_threshold,
645 once_after_n_policy->threshold);
646 if (ret) {
647 goto mi_error;
648 }
649
650 /* Close rate_policy_once_after_n element. */
651 ret = mi_lttng_writer_close_element(writer);
652 if (ret) {
653 goto mi_error;
654 }
655
656 ret_code = LTTNG_OK;
657 goto end;
658
659 mi_error:
660 ret_code = LTTNG_ERR_MI_IO_FAIL;
661 end:
662 return ret_code;
663 }
664
665 struct lttng_rate_policy *lttng_rate_policy_once_after_n_create(uint64_t threshold)
666 {
667 struct lttng_rate_policy_once_after_n *policy = nullptr;
668 struct lttng_rate_policy *_policy = nullptr;
669
670 if (threshold == 0) {
671 /* threshold is expected to be > 0 */
672 goto end;
673 }
674
675 policy = zmalloc<lttng_rate_policy_once_after_n>();
676 if (!policy) {
677 goto end;
678 }
679
680 lttng_rate_policy_init(&policy->parent,
681 LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N,
682 lttng_rate_policy_once_after_n_serialize,
683 lttng_rate_policy_once_after_n_is_equal,
684 lttng_rate_policy_once_after_n_destroy,
685 lttng_rate_policy_once_after_n_copy,
686 lttng_rate_policy_once_after_n_mi_serialize);
687
688 policy->threshold = threshold;
689
690 _policy = &policy->parent;
691 policy = nullptr;
692
693 end:
694 free(policy);
695 return _policy;
696 }
697
698 enum lttng_rate_policy_status
699 lttng_rate_policy_once_after_n_get_threshold(const struct lttng_rate_policy *policy,
700 uint64_t *threshold)
701 {
702 const struct lttng_rate_policy_once_after_n *once_after_n_policy;
703 enum lttng_rate_policy_status status;
704
705 if (!policy || !IS_ONCE_AFTER_N_RATE_POLICY(policy) || !threshold) {
706 status = LTTNG_RATE_POLICY_STATUS_INVALID;
707 goto end;
708 }
709
710 once_after_n_policy = rate_policy_once_after_n_from_rate_policy_const(policy);
711 *threshold = once_after_n_policy->threshold;
712 status = LTTNG_RATE_POLICY_STATUS_OK;
713 end:
714
715 return status;
716 }
717
718 struct lttng_rate_policy *lttng_rate_policy_copy(const struct lttng_rate_policy *source)
719 {
720 LTTNG_ASSERT(source->copy);
721 return source->copy(source);
722 }
723
724 static bool lttng_rate_policy_once_after_n_should_execute(const struct lttng_rate_policy *policy,
725 uint64_t counter)
726 {
727 const struct lttng_rate_policy_once_after_n *once_after_n_policy;
728 bool execute = false;
729 LTTNG_ASSERT(policy);
730
731 once_after_n_policy = rate_policy_once_after_n_from_rate_policy_const(policy);
732
733 execute = counter == once_after_n_policy->threshold;
734
735 DBG("Policy once after N = %" PRIu64 ": execution %s. Execution count: %" PRIu64,
736 once_after_n_policy->threshold,
737 execute ? "accepted" : "denied",
738 counter);
739
740 return counter == once_after_n_policy->threshold;
741 }
742
743 enum lttng_error_code lttng_rate_policy_mi_serialize(const struct lttng_rate_policy *rate_policy,
744 struct mi_writer *writer)
745 {
746 int ret;
747 enum lttng_error_code ret_code;
748
749 LTTNG_ASSERT(rate_policy);
750 LTTNG_ASSERT(writer);
751 LTTNG_ASSERT(rate_policy->mi_serialize);
752
753 /* Open rate policy element. */
754 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_rate_policy);
755 if (ret) {
756 goto mi_error;
757 }
758
759 /* Serialize underlying rate policy. */
760 ret_code = rate_policy->mi_serialize(rate_policy, writer);
761 if (ret_code != LTTNG_OK) {
762 goto end;
763 }
764
765 /* Close rate policy element. */
766 ret = mi_lttng_writer_close_element(writer);
767 if (ret) {
768 goto mi_error;
769 }
770
771 ret_code = LTTNG_OK;
772 goto end;
773
774 mi_error:
775 ret_code = LTTNG_ERR_MI_IO_FAIL;
776 end:
777 return ret_code;
778 }
This page took 0.049184 seconds and 4 git commands to generate.