Fix: consumerd: consumed size miscomputed during statistics sampling
[lttng-tools.git] / src / common / actions / rate-policy.cpp
CommitLineData
7f4d5b07
JR
1/*
2 * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
c9e313bc
SM
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>
28ab034a 15
c9e313bc 16#include <lttng/action/rate-policy-internal.hpp>
7f4d5b07 17#include <lttng/action/rate-policy.h>
28ab034a
JG
18
19#include <limits.h>
7f4d5b07
JR
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
28ab034a
JG
26#define IS_ONCE_AFTER_N_RATE_POLICY(policy) \
27 (lttng_rate_policy_get_type(policy) == LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N)
7f4d5b07 28
e665dfbc
JG
29using rate_policy_destroy_cb = void (*)(struct lttng_rate_policy *);
30using rate_policy_serialize_cb = int (*)(struct lttng_rate_policy *, struct lttng_payload *);
31using rate_policy_equal_cb = bool (*)(const struct lttng_rate_policy *,
32 const struct lttng_rate_policy *);
33using rate_policy_create_from_payload_cb = ssize_t (*)(struct lttng_payload_view *,
34 struct lttng_rate_policy **);
35using rate_policy_copy_cb = struct lttng_rate_policy *(*) (const struct lttng_rate_policy *);
36using rate_policy_mi_serialize_cb = enum lttng_error_code (*)(const struct lttng_rate_policy *,
37 struct mi_writer *);
7f4d5b07
JR
38
39struct 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;
6a751b95 45 rate_policy_mi_serialize_cb mi_serialize;
7f4d5b07
JR
46};
47
f1494934 48namespace {
7f4d5b07
JR
49struct lttng_rate_policy_every_n {
50 struct lttng_rate_policy parent;
51 uint64_t interval;
52};
53
54struct lttng_rate_policy_once_after_n {
55 struct lttng_rate_policy parent;
56 uint64_t threshold;
57};
58
59struct lttng_rate_policy_comm {
60 /* enum lttng_rate_policy_type */
61 int8_t rate_policy_type;
62} LTTNG_PACKED;
63
64struct lttng_rate_policy_once_after_n_comm {
65 uint64_t threshold;
66} LTTNG_PACKED;
67
68struct lttng_rate_policy_every_n_comm {
69 uint64_t interval;
70} LTTNG_PACKED;
f1494934 71} /* namespace */
7f4d5b07
JR
72
73/* Forward declaration. */
74static void lttng_rate_policy_init(struct lttng_rate_policy *rate_policy,
28ab034a
JG
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);
7f4d5b07
JR
81
82/* Forward declaration. Every n */
28ab034a
JG
83static bool lttng_rate_policy_every_n_should_execute(const struct lttng_rate_policy *policy,
84 uint64_t counter);
7f4d5b07
JR
85
86/* Forward declaration. Once after N */
28ab034a
JG
87static bool lttng_rate_policy_once_after_n_should_execute(const struct lttng_rate_policy *policy,
88 uint64_t counter);
7f4d5b07 89
28ab034a 90const char *lttng_rate_policy_type_string(enum lttng_rate_policy_type rate_policy_type)
7f4d5b07
JR
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
28ab034a 102enum lttng_rate_policy_type lttng_rate_policy_get_type(const struct lttng_rate_policy *policy)
7f4d5b07
JR
103{
104 return policy ? policy->type : LTTNG_RATE_POLICY_TYPE_UNKNOWN;
105}
106
7f4d5b07 107void lttng_rate_policy_init(struct lttng_rate_policy *rate_policy,
28ab034a
JG
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)
7f4d5b07
JR
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;
6a751b95 120 rate_policy->mi_serialize = mi;
7f4d5b07
JR
121}
122
123void 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
7f4d5b07 132int lttng_rate_policy_serialize(struct lttng_rate_policy *rate_policy,
28ab034a 133 struct lttng_payload *payload)
7f4d5b07
JR
134{
135 int ret;
136 struct lttng_rate_policy_comm rate_policy_comm = {
28ab034a 137 .rate_policy_type = (int8_t) rate_policy->type,
7f4d5b07
JR
138 };
139
28ab034a
JG
140 ret = lttng_dynamic_buffer_append(
141 &payload->buffer, &rate_policy_comm, sizeof(rate_policy_comm));
7f4d5b07
JR
142 if (ret) {
143 goto end;
144 }
145
146 ret = rate_policy->serialize(rate_policy, payload);
147 if (ret) {
148 goto end;
149 }
150end:
151 return ret;
152}
153
28ab034a
JG
154static ssize_t
155lttng_rate_policy_once_after_n_create_from_payload(struct lttng_payload_view *view,
156 struct lttng_rate_policy **rate_policy)
7f4d5b07
JR
157{
158 ssize_t consumed_len = -1;
cd9adb8b 159 struct lttng_rate_policy *policy = nullptr;
7f4d5b07
JR
160 const struct lttng_rate_policy_once_after_n_comm *comm;
161 const struct lttng_payload_view comm_view =
28ab034a 162 lttng_payload_view_from_view(view, 0, sizeof(*comm));
7f4d5b07
JR
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
28ab034a 175 comm = (const struct lttng_rate_policy_once_after_n_comm *) comm_view.buffer.data;
7f4d5b07
JR
176
177 policy = lttng_rate_policy_once_after_n_create(comm->threshold);
cd9adb8b 178 if (policy == nullptr) {
7f4d5b07
JR
179 consumed_len = -1;
180 goto end;
181 }
182
183 *rate_policy = policy;
184 consumed_len = sizeof(*comm);
185
186end:
187 return consumed_len;
188}
189
28ab034a
JG
190static ssize_t lttng_rate_policy_every_n_create_from_payload(struct lttng_payload_view *view,
191 struct lttng_rate_policy **rate_policy)
7f4d5b07
JR
192{
193 ssize_t consumed_len = -1;
cd9adb8b 194 struct lttng_rate_policy *policy = nullptr;
7f4d5b07
JR
195 const struct lttng_rate_policy_every_n_comm *comm;
196 const struct lttng_payload_view comm_view =
28ab034a 197 lttng_payload_view_from_view(view, 0, sizeof(*comm));
7f4d5b07
JR
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
28ab034a 210 comm = (const struct lttng_rate_policy_every_n_comm *) comm_view.buffer.data;
7f4d5b07
JR
211
212 policy = lttng_rate_policy_every_n_create(comm->interval);
cd9adb8b 213 if (policy == nullptr) {
7f4d5b07
JR
214 consumed_len = -1;
215 goto end;
216 }
217
218 *rate_policy = policy;
219 consumed_len = sizeof(*comm);
220
221end:
222 return consumed_len;
223}
224
7f4d5b07 225ssize_t lttng_rate_policy_create_from_payload(struct lttng_payload_view *view,
28ab034a 226 struct lttng_rate_policy **rate_policy)
7f4d5b07
JR
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 =
28ab034a 232 lttng_payload_view_from_view(view, 0, sizeof(*rate_policy_comm));
7f4d5b07
JR
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
28ab034a
JG
245 rate_policy_comm =
246 (const struct lttng_rate_policy_comm *) rate_policy_comm_view.buffer.data;
7f4d5b07
JR
247
248 DBG("Create rate_policy from payload: rate-policy-type=%s",
28ab034a
JG
249 lttng_rate_policy_type_string(
250 (lttng_rate_policy_type) rate_policy_comm->rate_policy_type));
7f4d5b07
JR
251
252 switch (rate_policy_comm->rate_policy_type) {
253 case LTTNG_RATE_POLICY_TYPE_EVERY_N:
28ab034a 254 create_from_payload_cb = lttng_rate_policy_every_n_create_from_payload;
7f4d5b07
JR
255 break;
256 case LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N:
28ab034a 257 create_from_payload_cb = lttng_rate_policy_once_after_n_create_from_payload;
7f4d5b07
JR
258 break;
259 default:
260 ERR("Failed to create rate-policy from payload, unhandled rate-policy type: rate-policy-type=%u (%s)",
28ab034a
JG
261 rate_policy_comm->rate_policy_type,
262 lttng_rate_policy_type_string(
263 (lttng_rate_policy_type) rate_policy_comm->rate_policy_type));
7f4d5b07
JR
264 consumed_len = -1;
265 goto end;
266 }
267
268 {
269 /* Create buffer view for the rate_policy-type-specific data.
270 */
28ab034a
JG
271 struct lttng_payload_view specific_rate_policy_view = lttng_payload_view_from_view(
272 view, sizeof(struct lttng_rate_policy_comm), -1);
7f4d5b07 273
28ab034a
JG
274 specific_rate_policy_consumed_len =
275 create_from_payload_cb(&specific_rate_policy_view, rate_policy);
7f4d5b07
JR
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
a0377dfe 283 LTTNG_ASSERT(*rate_policy);
7f4d5b07 284
28ab034a 285 consumed_len = sizeof(struct lttng_rate_policy_comm) + specific_rate_policy_consumed_len;
7f4d5b07
JR
286
287end:
288 return consumed_len;
289}
290
7f4d5b07 291bool lttng_rate_policy_is_equal(const struct lttng_rate_policy *a,
28ab034a 292 const struct lttng_rate_policy *b)
7f4d5b07
JR
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
a0377dfe 309 LTTNG_ASSERT(a->equal);
7f4d5b07
JR
310 is_equal = a->equal(a, b);
311end:
312 return is_equal;
313}
314
28ab034a 315bool lttng_rate_policy_should_execute(const struct lttng_rate_policy *policy, uint64_t counter)
7f4d5b07
JR
316{
317 switch (policy->type) {
318 case LTTNG_RATE_POLICY_TYPE_EVERY_N:
28ab034a 319 return lttng_rate_policy_every_n_should_execute(policy, counter);
7f4d5b07 320 case LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N:
28ab034a 321 return lttng_rate_policy_once_after_n_should_execute(policy, counter);
7f4d5b07
JR
322 default:
323 abort();
324 break;
325 }
326}
327
328/* Every N */
28ab034a
JG
329static struct lttng_rate_policy_every_n *
330rate_policy_every_n_from_rate_policy(struct lttng_rate_policy *policy)
7f4d5b07 331{
a0377dfe 332 LTTNG_ASSERT(policy);
7f4d5b07 333
0114db0e 334 return lttng::utils::container_of(policy, &lttng_rate_policy_every_n::parent);
7f4d5b07
JR
335}
336
337static const struct lttng_rate_policy_every_n *
28ab034a 338rate_policy_every_n_from_rate_policy_const(const struct lttng_rate_policy *policy)
7f4d5b07 339{
a0377dfe 340 LTTNG_ASSERT(policy);
7f4d5b07 341
0114db0e 342 return lttng::utils::container_of(policy, &lttng_rate_policy_every_n::parent);
7f4d5b07
JR
343}
344
28ab034a
JG
345static int lttng_rate_policy_every_n_serialize(struct lttng_rate_policy *policy,
346 struct lttng_payload *payload)
7f4d5b07
JR
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
a0377dfe
FD
353 LTTNG_ASSERT(policy);
354 LTTNG_ASSERT(payload);
7f4d5b07
JR
355
356 every_n_policy = rate_policy_every_n_from_rate_policy(policy);
357 comm.interval = every_n_policy->interval;
358
28ab034a 359 ret = lttng_dynamic_buffer_append(&payload->buffer, &comm, sizeof(comm));
7f4d5b07
JR
360 return ret;
361}
362
28ab034a
JG
363static bool lttng_rate_policy_every_n_is_equal(const struct lttng_rate_policy *_a,
364 const struct lttng_rate_policy *_b)
7f4d5b07
JR
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
378end:
379 return is_equal;
380}
381
382static 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
394end:
395 return;
396}
397
28ab034a
JG
398static struct lttng_rate_policy *
399lttng_rate_policy_every_n_copy(const struct lttng_rate_policy *source)
7f4d5b07 400{
cd9adb8b 401 struct lttng_rate_policy *copy = nullptr;
7f4d5b07
JR
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
411end:
412 return copy;
413}
414
28ab034a
JG
415static enum lttng_error_code
416lttng_rate_policy_every_n_mi_serialize(const struct lttng_rate_policy *rate_policy,
417 struct mi_writer *writer)
6a751b95
JR
418{
419 int ret;
420 enum lttng_error_code ret_code;
cd9adb8b 421 const struct lttng_rate_policy_every_n *every_n_policy = nullptr;
6a751b95 422
a0377dfe
FD
423 LTTNG_ASSERT(rate_policy);
424 LTTNG_ASSERT(IS_EVERY_N_RATE_POLICY(rate_policy));
425 LTTNG_ASSERT(writer);
6a751b95 426
28ab034a 427 every_n_policy = rate_policy_every_n_from_rate_policy_const(rate_policy);
6a751b95
JR
428
429 /* Open rate_policy_every_n element. */
28ab034a 430 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_rate_policy_every_n);
6a751b95
JR
431 if (ret) {
432 goto mi_error;
433 }
434
435 /* Interval. */
28ab034a
JG
436 ret = mi_lttng_writer_write_element_unsigned_int(
437 writer, mi_lttng_element_rate_policy_every_n_interval, every_n_policy->interval);
6a751b95
JR
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
451mi_error:
452 ret_code = LTTNG_ERR_MI_IO_FAIL;
453end:
454 return ret_code;
455}
456
7f4d5b07
JR
457struct lttng_rate_policy *lttng_rate_policy_every_n_create(uint64_t interval)
458{
cd9adb8b
JG
459 struct lttng_rate_policy_every_n *policy = nullptr;
460 struct lttng_rate_policy *_policy = nullptr;
7f4d5b07
JR
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
64803277 469 policy = zmalloc<lttng_rate_policy_every_n>();
7f4d5b07
JR
470 if (!policy) {
471 goto end;
472 }
473
28ab034a
JG
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);
7f4d5b07
JR
481
482 policy->interval = interval;
483
484 _policy = &policy->parent;
cd9adb8b 485 policy = nullptr;
7f4d5b07
JR
486
487end:
488 free(policy);
489 return _policy;
490}
491
28ab034a
JG
492enum lttng_rate_policy_status
493lttng_rate_policy_every_n_get_interval(const struct lttng_rate_policy *policy, uint64_t *interval)
7f4d5b07
JR
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;
506end:
507
508 return status;
509}
510
28ab034a
JG
511static bool lttng_rate_policy_every_n_should_execute(const struct lttng_rate_policy *policy,
512 uint64_t counter)
7f4d5b07
JR
513{
514 const struct lttng_rate_policy_every_n *every_n_policy;
a0377dfe 515 LTTNG_ASSERT(policy);
7f4d5b07
JR
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
28ab034a
JG
526 DBG("Policy every N = %" PRIu64 ": execution %s. Execution count: %" PRIu64,
527 every_n_policy->interval,
528 execute ? "accepted" : "denied",
529 counter);
7f4d5b07
JR
530
531 return execute;
532}
533
534/* Once after N */
535
536static struct lttng_rate_policy_once_after_n *
537rate_policy_once_after_n_from_rate_policy(struct lttng_rate_policy *policy)
538{
a0377dfe 539 LTTNG_ASSERT(policy);
7f4d5b07 540
28ab034a 541 return lttng::utils::container_of(policy, &lttng_rate_policy_once_after_n::parent);
7f4d5b07
JR
542}
543
544static const struct lttng_rate_policy_once_after_n *
28ab034a 545rate_policy_once_after_n_from_rate_policy_const(const struct lttng_rate_policy *policy)
7f4d5b07 546{
a0377dfe 547 LTTNG_ASSERT(policy);
7f4d5b07 548
28ab034a 549 return lttng::utils::container_of(policy, &lttng_rate_policy_once_after_n::parent);
7f4d5b07 550}
28ab034a
JG
551static int lttng_rate_policy_once_after_n_serialize(struct lttng_rate_policy *policy,
552 struct lttng_payload *payload)
7f4d5b07
JR
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
a0377dfe
FD
559 LTTNG_ASSERT(policy);
560 LTTNG_ASSERT(payload);
7f4d5b07
JR
561
562 once_after_n_policy = rate_policy_once_after_n_from_rate_policy(policy);
563 comm.threshold = once_after_n_policy->threshold;
564
28ab034a 565 ret = lttng_dynamic_buffer_append(&payload->buffer, &comm, sizeof(comm));
7f4d5b07
JR
566 return ret;
567}
568
28ab034a
JG
569static bool lttng_rate_policy_once_after_n_is_equal(const struct lttng_rate_policy *_a,
570 const struct lttng_rate_policy *_b)
7f4d5b07
JR
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
584end:
585 return is_equal;
586}
587
28ab034a 588static void lttng_rate_policy_once_after_n_destroy(struct lttng_rate_policy *policy)
7f4d5b07
JR
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
600end:
601 return;
602}
603
28ab034a
JG
604static struct lttng_rate_policy *
605lttng_rate_policy_once_after_n_copy(const struct lttng_rate_policy *source)
7f4d5b07 606{
cd9adb8b 607 struct lttng_rate_policy *copy = nullptr;
7f4d5b07
JR
608 const struct lttng_rate_policy_once_after_n *once_after_n_policy;
609
610 if (!source) {
611 goto end;
612 }
613
28ab034a
JG
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);
7f4d5b07
JR
616
617end:
618 return copy;
619}
620
28ab034a
JG
621static enum lttng_error_code
622lttng_rate_policy_once_after_n_mi_serialize(const struct lttng_rate_policy *rate_policy,
623 struct mi_writer *writer)
6a751b95
JR
624{
625 int ret;
626 enum lttng_error_code ret_code;
cd9adb8b 627 const struct lttng_rate_policy_once_after_n *once_after_n_policy = nullptr;
6a751b95 628
a0377dfe
FD
629 LTTNG_ASSERT(rate_policy);
630 LTTNG_ASSERT(IS_ONCE_AFTER_N_RATE_POLICY(rate_policy));
631 LTTNG_ASSERT(writer);
6a751b95 632
28ab034a 633 once_after_n_policy = rate_policy_once_after_n_from_rate_policy_const(rate_policy);
6a751b95
JR
634
635 /* Open rate_policy_once_after_n. */
28ab034a 636 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_rate_policy_once_after_n);
6a751b95
JR
637 if (ret) {
638 goto mi_error;
639 }
640
641 /* Threshold. */
28ab034a
JG
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);
6a751b95
JR
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
659mi_error:
660 ret_code = LTTNG_ERR_MI_IO_FAIL;
661end:
662 return ret_code;
663}
664
28ab034a 665struct lttng_rate_policy *lttng_rate_policy_once_after_n_create(uint64_t threshold)
7f4d5b07 666{
cd9adb8b
JG
667 struct lttng_rate_policy_once_after_n *policy = nullptr;
668 struct lttng_rate_policy *_policy = nullptr;
7f4d5b07
JR
669
670 if (threshold == 0) {
671 /* threshold is expected to be > 0 */
672 goto end;
673 }
674
64803277 675 policy = zmalloc<lttng_rate_policy_once_after_n>();
7f4d5b07
JR
676 if (!policy) {
677 goto end;
678 }
679
680 lttng_rate_policy_init(&policy->parent,
28ab034a
JG
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);
7f4d5b07
JR
687
688 policy->threshold = threshold;
689
690 _policy = &policy->parent;
cd9adb8b 691 policy = nullptr;
7f4d5b07
JR
692
693end:
694 free(policy);
695 return _policy;
696}
697
28ab034a
JG
698enum lttng_rate_policy_status
699lttng_rate_policy_once_after_n_get_threshold(const struct lttng_rate_policy *policy,
700 uint64_t *threshold)
7f4d5b07
JR
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
28ab034a 710 once_after_n_policy = rate_policy_once_after_n_from_rate_policy_const(policy);
7f4d5b07
JR
711 *threshold = once_after_n_policy->threshold;
712 status = LTTNG_RATE_POLICY_STATUS_OK;
713end:
714
715 return status;
716}
717
28ab034a 718struct lttng_rate_policy *lttng_rate_policy_copy(const struct lttng_rate_policy *source)
7f4d5b07 719{
a0377dfe 720 LTTNG_ASSERT(source->copy);
7f4d5b07
JR
721 return source->copy(source);
722}
723
28ab034a
JG
724static bool lttng_rate_policy_once_after_n_should_execute(const struct lttng_rate_policy *policy,
725 uint64_t counter)
7f4d5b07
JR
726{
727 const struct lttng_rate_policy_once_after_n *once_after_n_policy;
728 bool execute = false;
a0377dfe 729 LTTNG_ASSERT(policy);
7f4d5b07 730
28ab034a 731 once_after_n_policy = rate_policy_once_after_n_from_rate_policy_const(policy);
7f4d5b07
JR
732
733 execute = counter == once_after_n_policy->threshold;
734
28ab034a
JG
735 DBG("Policy once after N = %" PRIu64 ": execution %s. Execution count: %" PRIu64,
736 once_after_n_policy->threshold,
737 execute ? "accepted" : "denied",
738 counter);
7f4d5b07
JR
739
740 return counter == once_after_n_policy->threshold;
741}
6a751b95 742
28ab034a
JG
743enum lttng_error_code lttng_rate_policy_mi_serialize(const struct lttng_rate_policy *rate_policy,
744 struct mi_writer *writer)
6a751b95
JR
745{
746 int ret;
747 enum lttng_error_code ret_code;
748
a0377dfe
FD
749 LTTNG_ASSERT(rate_policy);
750 LTTNG_ASSERT(writer);
751 LTTNG_ASSERT(rate_policy->mi_serialize);
6a751b95
JR
752
753 /* Open rate policy element. */
28ab034a 754 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_rate_policy);
6a751b95
JR
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
774mi_error:
775 ret_code = LTTNG_ERR_MI_IO_FAIL;
776end:
777 return ret_code;
778}
This page took 0.138486 seconds and 4 git commands to generate.