SoW-2020-0002: Trace Hit Counters: trigger error reporting integration
[lttng-tools.git] / src / common / trigger.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
8#include <lttng/trigger/trigger-internal.h>
9#include <lttng/condition/condition-internal.h>
2463b787
JR
10#include <lttng/condition/event-rule-internal.h>
11#include <lttng/condition/event-rule.h>
12#include <lttng/condition/buffer-usage.h>
13#include <lttng/event-rule/event-rule-internal.h>
14#include <lttng/event-expr-internal.h>
a58c490f 15#include <lttng/action/action-internal.h>
3da864a9 16#include <common/credentials.h>
9e620ea7
JG
17#include <common/payload.h>
18#include <common/payload-view.h>
2463b787 19#include <lttng/domain.h>
a58c490f 20#include <common/error.h>
2463b787 21#include <common/dynamic-array.h>
3da864a9 22#include <common/optional.h>
a58c490f 23#include <assert.h>
2463b787 24#include <inttypes.h>
a58c490f 25
2463b787
JR
26static void destroy_lttng_condition_event_rule_capture_bytecode_element(void *ptr)
27{
28 struct lttng_condition_event_rule_capture_bytecode_element *element =
29 ptr;
30 lttng_event_expr_destroy(element->expression);
31 free(element->bytecode);
32 free(element);
33}
a58c490f 34LTTNG_HIDDEN
2463b787 35bool lttng_trigger_validate(const struct lttng_trigger *trigger)
a58c490f
JG
36{
37 bool valid;
38
39 if (!trigger) {
40 valid = false;
41 goto end;
42 }
43
2463b787
JR
44 if (!trigger->creds.uid.is_set) {
45 valid = false;
46 goto end;
47 }
48
a58c490f
JG
49 valid = lttng_condition_validate(trigger->condition) &&
50 lttng_action_validate(trigger->action);
51end:
52 return valid;
53}
54
55struct lttng_trigger *lttng_trigger_create(
56 struct lttng_condition *condition,
57 struct lttng_action *action)
58{
59 struct lttng_trigger *trigger = NULL;
60
61 if (!condition || !action) {
62 goto end;
63 }
64
65 trigger = zmalloc(sizeof(struct lttng_trigger));
66 if (!trigger) {
67 goto end;
68 }
69
f01d28b4
JR
70 urcu_ref_init(&trigger->ref);
71
2463b787
JR
72 trigger->firing_policy.type = LTTNG_TRIGGER_FIRE_EVERY_N;
73 trigger->firing_policy.threshold = 1;
74 lttng_trigger_set_error_count(trigger, 0);
75
7ca172c1 76 lttng_condition_get(condition);
a58c490f 77 trigger->condition = condition;
7ca172c1
JR
78
79 lttng_action_get(action);
a58c490f 80 trigger->action = action;
3da864a9 81
2463b787
JR
82 lttng_dynamic_pointer_array_init(&trigger->capture_bytecode_set,
83 destroy_lttng_condition_event_rule_capture_bytecode_element);
84
a58c490f
JG
85end:
86 return trigger;
87}
88
7ca172c1
JR
89/*
90 * Note: the lack of reference counting 'get' on the condition object is normal.
91 * This API was exposed as such in 2.11. The client is not expected to call
92 * lttng_condition_destroy on the returned object.
93 */
a58c490f
JG
94struct lttng_condition *lttng_trigger_get_condition(
95 struct lttng_trigger *trigger)
96{
97 return trigger ? trigger->condition : NULL;
98}
99
9b63a4aa
JG
100const struct lttng_condition *lttng_trigger_get_const_condition(
101 const struct lttng_trigger *trigger)
102{
2463b787 103 return trigger ? trigger->condition : NULL;
9b63a4aa
JG
104}
105
7ca172c1
JR
106
107/*
108 * Note: the lack of reference counting 'get' on the action object is normal.
109 * This API was exposed as such in 2.11. The client is not expected to call
110 * lttng_action_destroy on the returned object.
111 */
e2ba1c78 112struct lttng_action *lttng_trigger_get_action(
a58c490f
JG
113 struct lttng_trigger *trigger)
114{
115 return trigger ? trigger->action : NULL;
116}
117
9b63a4aa
JG
118const struct lttng_action *lttng_trigger_get_const_action(
119 const struct lttng_trigger *trigger)
120{
2463b787 121 return trigger ? trigger->action : NULL;
9b63a4aa
JG
122}
123
f01d28b4 124static void trigger_destroy_ref(struct urcu_ref *ref)
a58c490f 125{
f01d28b4
JR
126 struct lttng_trigger *trigger =
127 container_of(ref, struct lttng_trigger, ref);
7ca172c1
JR
128 struct lttng_action *action = lttng_trigger_get_action(trigger);
129 struct lttng_condition *condition =
130 lttng_trigger_get_condition(trigger);
131
2463b787
JR
132 lttng_dynamic_pointer_array_reset(&trigger->capture_bytecode_set);
133
7ca172c1
JR
134 assert(action);
135 assert(condition);
136
137 /* Release ownership. */
138 lttng_action_put(action);
139 lttng_condition_put(condition);
140
2463b787 141 free(trigger->name);
a58c490f
JG
142 free(trigger);
143}
144
f01d28b4
JR
145void lttng_trigger_destroy(struct lttng_trigger *trigger)
146{
147 lttng_trigger_put(trigger);
148}
149
2463b787
JR
150static bool is_firing_policy_valid(enum lttng_trigger_firing_policy_type policy)
151{
152 bool valid = false;
153
154 switch (policy) {
155 case LTTNG_TRIGGER_FIRE_EVERY_N:
156 case LTTNG_TRIGGER_FIRE_ONCE_AFTER_N:
157 valid = true;
158 break;
159 default:
160 valid = false;
161 break;
162 }
163
164 return valid;
165}
166
a58c490f 167LTTNG_HIDDEN
c0a66c84
JG
168ssize_t lttng_trigger_create_from_payload(
169 struct lttng_payload_view *src_view,
a58c490f
JG
170 struct lttng_trigger **trigger)
171{
2463b787
JR
172 ssize_t ret, offset = 0, condition_size, action_size, name_size = 0;
173 enum lttng_trigger_status status;
a58c490f
JG
174 struct lttng_condition *condition = NULL;
175 struct lttng_action *action = NULL;
176 const struct lttng_trigger_comm *trigger_comm;
2463b787
JR
177 const char *name = NULL;
178 uint64_t firing_threshold;
179 int64_t error_count;
180 enum lttng_trigger_firing_policy_type firing_policy;
181 struct lttng_credentials creds = {
182 .uid = LTTNG_OPTIONAL_INIT_UNSET,
183 .gid = LTTNG_OPTIONAL_INIT_UNSET,
184 };
a58c490f
JG
185
186 if (!src_view || !trigger) {
187 ret = -1;
188 goto end;
189 }
190
191 /* lttng_trigger_comm header */
c0a66c84 192 trigger_comm = (typeof(trigger_comm)) src_view->buffer.data;
2463b787
JR
193
194 /* Get the trigger creds */
195 LTTNG_OPTIONAL_SET(&creds.uid, trigger_comm->uid);
196
a58c490f 197 offset += sizeof(*trigger_comm);
2463b787
JR
198
199 firing_policy = trigger_comm->policy_type;
200 if (!is_firing_policy_valid(firing_policy)) {
201 ret =-1;
202 goto end;
203 }
204
205 firing_threshold = trigger_comm->policy_threshold;
206 error_count = trigger_comm->error_count;
207 if (trigger_comm->name_length != 0) {
208 /* Name */
209 struct lttng_payload_view name_view =
210 lttng_payload_view_from_view(
211 src_view, offset, trigger_comm->name_length);
212
213 name = name_view.buffer.data;
214 if (!lttng_buffer_view_contains_string(&name_view.buffer, name, trigger_comm->name_length)){
215 ret = -1;
216 goto end;
217 }
218 offset += trigger_comm->name_length;
219 name_size = trigger_comm->name_length;
220 }
221
c0a66c84
JG
222 {
223 /* struct lttng_condition */
224 struct lttng_payload_view condition_view =
225 lttng_payload_view_from_view(
226 src_view, offset, -1);
227
228 condition_size = lttng_condition_create_from_payload(&condition_view,
229 &condition);
230 }
a58c490f 231
a58c490f
JG
232 if (condition_size < 0) {
233 ret = condition_size;
234 goto end;
235 }
c0a66c84 236
a58c490f 237 offset += condition_size;
c0a66c84
JG
238 {
239 /* struct lttng_action */
240 struct lttng_payload_view action_view =
241 lttng_payload_view_from_view(
242 src_view, offset, -1);
243
244 action_size = lttng_action_create_from_payload(&action_view, &action);
245 }
a58c490f 246
a58c490f
JG
247 if (action_size < 0) {
248 ret = action_size;
249 goto end;
250 }
251 offset += action_size;
252
253 /* Unexpected size of inner-elements; the buffer is corrupted. */
2463b787 254 if ((ssize_t) trigger_comm->length != condition_size + action_size + name_size) {
a58c490f
JG
255 ret = -1;
256 goto error;
257 }
258
259 *trigger = lttng_trigger_create(condition, action);
260 if (!*trigger) {
261 ret = -1;
262 goto error;
263 }
c0a66c84 264
2463b787
JR
265 lttng_trigger_set_credentials(*trigger, &creds);
266
7ca172c1
JR
267 /*
268 * The trigger object owns references to the action and condition
269 * objects.
270 */
271 lttng_condition_put(condition);
272 condition = NULL;
273
274 lttng_action_put(action);
275 action = NULL;
276
2463b787
JR
277 if (name) {
278 status = lttng_trigger_set_name(*trigger, name);
279 if (status != LTTNG_TRIGGER_STATUS_OK) {
280 ret = -1;
281 goto end;
282 }
283 }
284
285 status = lttng_trigger_set_firing_policy(*trigger, firing_policy, firing_threshold);
286 if (status != LTTNG_TRIGGER_STATUS_OK) {
287 ret = -1;
288 goto end;
289 }
290
291 lttng_trigger_set_error_count(*trigger, error_count);
292
a58c490f 293 ret = offset;
7ca172c1 294
a58c490f
JG
295error:
296 lttng_condition_destroy(condition);
297 lttng_action_destroy(action);
7ca172c1 298end:
a58c490f
JG
299 return ret;
300}
301
302/*
a58c490f
JG
303 * Both elements are stored contiguously, see their "*_comm" structure
304 * for the detailed format.
305 */
306LTTNG_HIDDEN
2463b787 307int lttng_trigger_serialize(const struct lttng_trigger *trigger,
c0a66c84 308 struct lttng_payload *payload)
a58c490f 309{
3647288f 310 int ret;
2463b787 311 size_t header_offset, size_before_payload, size_name;
c0a66c84 312 struct lttng_trigger_comm trigger_comm = {};
3647288f 313 struct lttng_trigger_comm *header;
2463b787
JR
314 const struct lttng_credentials *creds = NULL;
315
316 creds = lttng_trigger_get_credentials(trigger);
317 assert(creds);
318
319 trigger_comm.uid = LTTNG_OPTIONAL_GET(creds->uid);
320
321 if (trigger->name != NULL) {
322 size_name = strlen(trigger->name) + 1;
323 } else {
324 size_name = 0;
325 }
326
327 trigger_comm.name_length = size_name;
328 trigger_comm.policy_type = (uint8_t) trigger->firing_policy.type;
329 trigger_comm.policy_threshold = (uint64_t) trigger->firing_policy.threshold;
330 trigger_comm.error_count = (int64_t) lttng_trigger_get_error_count(trigger);
a58c490f 331
c0a66c84
JG
332 header_offset = payload->buffer.size;
333 ret = lttng_dynamic_buffer_append(&payload->buffer, &trigger_comm,
3647288f
JG
334 sizeof(trigger_comm));
335 if (ret) {
a58c490f
JG
336 goto end;
337 }
338
c0a66c84 339 size_before_payload = payload->buffer.size;
2463b787
JR
340
341 /* Trigger name */
342 ret = lttng_dynamic_buffer_append(
343 &payload->buffer, trigger->name, size_name);
344 if (ret) {
345 goto end;
346 }
347
c0a66c84 348 ret = lttng_condition_serialize(trigger->condition, payload);
3647288f 349 if (ret) {
a58c490f
JG
350 goto end;
351 }
a58c490f 352
c0a66c84 353 ret = lttng_action_serialize(trigger->action, payload);
3647288f 354 if (ret) {
a58c490f
JG
355 goto end;
356 }
a58c490f 357
3647288f 358 /* Update payload size. */
c0a66c84
JG
359 header = (typeof(header)) (payload->buffer.data + header_offset);
360 header->length = payload->buffer.size - size_before_payload;
a58c490f
JG
361end:
362 return ret;
363}
3da864a9 364
2463b787
JR
365enum lttng_trigger_status lttng_trigger_set_name(struct lttng_trigger *trigger, const char* name)
366{
367 char *name_copy = NULL;
368 enum lttng_trigger_status status = LTTNG_TRIGGER_STATUS_OK;
369
370 if (!trigger || !name ||
371 strlen(name) == 0) {
372 status = LTTNG_TRIGGER_STATUS_INVALID;
373 goto end;
374 }
375
376 name_copy = strdup(name);
377 if (!name_copy) {
378 status = LTTNG_TRIGGER_STATUS_ERROR;
379 goto end;
380 }
381
382 free(trigger->name);
383
384 trigger->name = name_copy;
385 name_copy = NULL;
386end:
387 return status;
388}
389
390enum lttng_trigger_status lttng_trigger_get_name(
391 const struct lttng_trigger *trigger, const char **name)
392{
393 enum lttng_trigger_status status = LTTNG_TRIGGER_STATUS_OK;
394
395 if (!trigger || !name) {
396 status = LTTNG_TRIGGER_STATUS_INVALID;
397 goto end;
398 }
399
400 if (!trigger->name) {
401 status = LTTNG_TRIGGER_STATUS_UNSET;
402 }
403
404 *name = trigger->name;
405end:
406 return status;
407}
408
409LTTNG_HIDDEN
410int lttng_trigger_assign_name(struct lttng_trigger *dst,
411 const struct lttng_trigger *src)
412{
413 int ret = 0;
414 enum lttng_trigger_status status;
415
416 status = lttng_trigger_set_name(dst, src->name);
417 if (status != LTTNG_TRIGGER_STATUS_OK) {
418 ret = -1;
419 ERR("Failed to set name for trigger");
420 goto end;
421 }
422end:
423 return ret;
424}
425
426LTTNG_HIDDEN
427void lttng_trigger_set_tracer_token(struct lttng_trigger *trigger, uint64_t token)
428{
429 assert(trigger);
430 LTTNG_OPTIONAL_SET(&trigger->tracer_token, token);
431}
432
433LTTNG_HIDDEN
434uint64_t lttng_trigger_get_tracer_token(const struct lttng_trigger *trigger)
435{
436 assert(trigger);
437
438 return LTTNG_OPTIONAL_GET(trigger->tracer_token);
439}
440
441LTTNG_HIDDEN
442void lttng_trigger_set_error_counter_index(struct lttng_trigger *trigger,
443 uint64_t error_counter_index)
444{
445 assert(trigger);
446 LTTNG_OPTIONAL_SET(&trigger->error_counter_index, error_counter_index);
447}
448
449LTTNG_HIDDEN
450uint64_t lttng_trigger_get_error_counter_index(
451 const struct lttng_trigger *trigger)
452{
453 assert(trigger);
454
455 return LTTNG_OPTIONAL_GET(trigger->error_counter_index);
456}
457
458LTTNG_HIDDEN
459int lttng_trigger_generate_name(struct lttng_trigger *trigger, uint64_t offset)
460{
461 int ret = 0;
462 char *generated_name = NULL;
463
464 ret = asprintf(&generated_name, "T%" PRIu64 "", offset);
465 if (ret < 0) {
466 ERR("Failed to generate trigger name");
467 ret = -1;
468 goto end;
469 }
470
471 free(trigger->name);
472 trigger->name = generated_name;
473end:
474 return ret;
475}
476
f01d28b4
JR
477LTTNG_HIDDEN
478void lttng_trigger_get(struct lttng_trigger *trigger)
479{
480 urcu_ref_get(&trigger->ref);
481}
482
483LTTNG_HIDDEN
484void lttng_trigger_put(struct lttng_trigger *trigger)
485{
486 if (!trigger) {
487 return;
488 }
489
490 urcu_ref_put(&trigger->ref , trigger_destroy_ref);
491}
492
2463b787
JR
493static void delete_trigger_array_element(void *ptr)
494{
495 struct lttng_trigger *trigger = ptr;
496 lttng_trigger_put(trigger);
497}
498
499LTTNG_HIDDEN
500bool lttng_trigger_is_equal(
501 const struct lttng_trigger *a, const struct lttng_trigger *b)
502{
503 if (a->firing_policy.type != b->firing_policy.type) {
504 return false;
505 }
506
507 if (a->firing_policy.threshold != b->firing_policy.threshold) {
508 return false;
509 }
510
511 /*
512 * Name is not taken into account since it is cosmetic only.
513 */
514 if (!lttng_condition_is_equal(a->condition, b->condition)) {
515 return false;
516 }
517
518 if (!lttng_action_is_equal(a->action, b->action)) {
519 return false;
520 }
521
522 if (!lttng_credentials_is_equal(lttng_trigger_get_credentials(a),
523 lttng_trigger_get_credentials(b))) {
524 return false;
525 }
526
527 return true;
528}
529
530LTTNG_HIDDEN
531struct lttng_triggers *lttng_triggers_create(void)
532{
533 struct lttng_triggers *triggers = NULL;
534
535 triggers = zmalloc(sizeof(*triggers));
536 if (!triggers) {
537 goto end;
538 }
539
540 lttng_dynamic_pointer_array_init(&triggers->array, delete_trigger_array_element);
541
542end:
543 return triggers;
544}
545
546LTTNG_HIDDEN
547struct lttng_trigger *lttng_triggers_get_pointer_of_index(
548 const struct lttng_triggers *triggers, unsigned int index)
549{
550 struct lttng_trigger *trigger = NULL;
551 assert(triggers);
552 if (index >= lttng_dynamic_pointer_array_get_count(&triggers->array)) {
553 goto end;
554 }
555
556 trigger = (struct lttng_trigger *)
557 lttng_dynamic_pointer_array_get_pointer(
558 &triggers->array, index);
559end:
560 return trigger;
561}
562
563LTTNG_HIDDEN
564int lttng_triggers_add(
565 struct lttng_triggers *triggers, struct lttng_trigger *trigger)
566{
567 int ret;
568
569 assert(triggers);
570 assert(trigger);
571
572 lttng_trigger_get(trigger);
573
574 ret = lttng_dynamic_pointer_array_add_pointer(&triggers->array, trigger);
575 if (ret) {
576 lttng_trigger_put(trigger);
577 }
578
579 return ret;
580}
581
582const struct lttng_trigger *lttng_triggers_get_at_index(
583 const struct lttng_triggers *triggers, unsigned int index)
584{
585 assert(triggers);
586 return lttng_triggers_get_pointer_of_index(triggers, index);
587}
588
589enum lttng_trigger_status lttng_triggers_get_count(const struct lttng_triggers *triggers, unsigned int *count)
590{
591 enum lttng_trigger_status status = LTTNG_TRIGGER_STATUS_OK;
592
593 if (!triggers || !count) {
594 status = LTTNG_TRIGGER_STATUS_INVALID;
595 goto end;
596 }
597
598 *count = lttng_dynamic_pointer_array_get_count(&triggers->array);
599end:
600 return status;
601}
602
603void lttng_triggers_destroy(struct lttng_triggers *triggers)
604{
605 if (!triggers) {
606 return;
607 }
608
609 lttng_dynamic_pointer_array_reset(&triggers->array);
610 free(triggers);
611}
612
613int lttng_triggers_serialize(const struct lttng_triggers *triggers,
614 struct lttng_payload *payload)
615{
616 int ret;
617 unsigned int count;
618 size_t header_offset, size_before_payload;
619 struct lttng_triggers_comm triggers_comm = {};
620 struct lttng_triggers_comm *header;
621 enum lttng_trigger_status status;
622
623 header_offset = payload->buffer.size;
624
625 status = lttng_triggers_get_count(triggers, &count);
626 if (status != LTTNG_TRIGGER_STATUS_OK) {
627 ret = LTTNG_ERR_INVALID;
628 goto end;
629 }
630
631 triggers_comm.count = count;
632
633 ret = lttng_dynamic_buffer_append(&payload->buffer, &triggers_comm,
634 sizeof(triggers_comm));
635 if (ret) {
636 goto end;
637 }
638
639 size_before_payload = payload->buffer.size;
640
641 for (int i = 0; i < count; i++) {
642 const struct lttng_trigger *trigger =
643 lttng_triggers_get_at_index(triggers, i);
644 assert(trigger);
645
646 ret = lttng_trigger_serialize(trigger, payload);
647 if (ret) {
648 goto end;
649 }
650 }
651
652 /* Update payload size. */
653 header = (struct lttng_triggers_comm *) ((char *) payload->buffer.data + header_offset);
654 header->length = payload->buffer.size - size_before_payload;
655end:
656 return ret;
657}
658
659LTTNG_HIDDEN
660ssize_t lttng_triggers_create_from_payload(
661 struct lttng_payload_view *src_view,
662 struct lttng_triggers **triggers)
663{
664 ssize_t ret, offset = 0, trigger_size, triggers_size = 0;
665 const struct lttng_triggers_comm *triggers_comm;
666 struct lttng_triggers *local_triggers = NULL;
667
668 if (!src_view || !triggers) {
669 ret = -1;
670 goto error;
671 }
672
673 /* lttng_trigger_comms header */
674 triggers_comm = (const struct lttng_triggers_comm *) src_view->buffer.data;
675 offset += sizeof(*triggers_comm);
676
677 local_triggers = lttng_triggers_create();
678 if (!local_triggers) {
679 ret = -1;
680 goto error;
681 }
682
683 for (int i = 0; i < triggers_comm->count; i++) {
684 struct lttng_trigger *trigger = NULL;
685 struct lttng_payload_view trigger_view =
686 lttng_payload_view_from_view(src_view, offset, -1);
687 trigger_size = lttng_trigger_create_from_payload(&trigger_view,
688 &trigger);
689 if (trigger_size < 0) {
690 ret = trigger_size;
691 goto error;
692 }
693
694 /* Pass ownership of the trigger to the collection */
695 ret = lttng_triggers_add(local_triggers, trigger);
696 lttng_trigger_put(trigger);
697 if (ret < 0) {
698 ret = -1;
699 goto error;
700 }
701
702 offset += trigger_size;
703 triggers_size += trigger_size;
704 }
705
706 /* Unexpected size of inner-elements; the buffer is corrupted. */
707 if ((ssize_t) triggers_comm->length != triggers_size) {
708 ret = -1;
709 goto error;
710 }
711
712 /* Pass ownership to caller */
713 *triggers = local_triggers;
714 local_triggers = NULL;
715
716 ret = offset;
717error:
718
719 lttng_triggers_destroy(local_triggers);
720 return ret;
721}
722
3da864a9
JR
723LTTNG_HIDDEN
724const struct lttng_credentials *lttng_trigger_get_credentials(
725 const struct lttng_trigger *trigger)
726{
2463b787 727 return &trigger->creds;
3da864a9
JR
728}
729
730LTTNG_HIDDEN
2463b787 731void lttng_trigger_set_credentials(struct lttng_trigger *trigger,
3da864a9
JR
732 const struct lttng_credentials *creds)
733{
734 assert(creds);
2463b787
JR
735 trigger->creds = *creds;
736}
737
738enum lttng_trigger_status lttng_trigger_set_user_identity(
739 struct lttng_trigger *trigger, uid_t uid)
740{
741 enum lttng_trigger_status ret = LTTNG_TRIGGER_STATUS_OK;
742 struct lttng_credentials creds = {
743 .uid = LTTNG_OPTIONAL_INIT_UNSET,
744 .gid = LTTNG_OPTIONAL_INIT_UNSET,
745 };
746
747 if (!trigger) {
748 ret = LTTNG_TRIGGER_STATUS_INVALID;
749 goto end;
750 }
751
752 if (geteuid() != 0) {
753 ret = LTTNG_TRIGGER_STATUS_EPERM;
754 goto end;
755 }
756
757 LTTNG_OPTIONAL_SET(&creds.uid, uid);
758
759 lttng_trigger_set_credentials(trigger, &creds);
760
761end:
762 return ret;
763}
764
765enum lttng_trigger_status lttng_trigger_get_user_identity(
766 const struct lttng_trigger *trigger, uid_t *uid)
767{
768 enum lttng_trigger_status ret = LTTNG_TRIGGER_STATUS_OK;
769 const struct lttng_credentials *creds = NULL;
770
771 if (!trigger || !uid ) {
772 ret = LTTNG_TRIGGER_STATUS_INVALID;
773 goto end;
774 }
775
776 if (!trigger->creds.uid.is_set ) {
777 ret = LTTNG_TRIGGER_STATUS_UNSET;
778 goto end;
779 }
780
781 creds = lttng_trigger_get_credentials(trigger);
782 *uid = lttng_credentials_get_uid(creds);
783
784end:
785 return ret;
786}
787
788LTTNG_HIDDEN
789uint64_t lttng_trigger_get_error_count(
790 const struct lttng_trigger *trigger)
791{
792 return LTTNG_OPTIONAL_GET(trigger->error_count);
793}
794
795LTTNG_HIDDEN
796void lttng_trigger_set_error_count(
797 struct lttng_trigger *trigger,
798 uint64_t error_count)
799{
800 LTTNG_OPTIONAL_SET(&trigger->error_count, error_count);
801}
802
803enum lttng_trigger_status lttng_trigger_set_firing_policy(
804 struct lttng_trigger *trigger,
805 enum lttng_trigger_firing_policy_type policy_type,
806 uint64_t threshold)
807{
808 enum lttng_trigger_status ret = LTTNG_TRIGGER_STATUS_OK;
809 assert(trigger);
810
811 if (threshold < 1) {
812 ret = LTTNG_TRIGGER_STATUS_INVALID;
813 goto end;
814 }
815
816 trigger->firing_policy.type = policy_type;
817 trigger->firing_policy.threshold = threshold;
818
819end:
820 return ret;
821}
822
823enum lttng_trigger_status lttng_trigger_get_firing_policy(
824 const struct lttng_trigger *trigger,
825 enum lttng_trigger_firing_policy_type *policy_type,
826 uint64_t *threshold)
827{
828 enum lttng_trigger_status status = LTTNG_TRIGGER_STATUS_OK;
829
830 if (!trigger || !policy_type || !threshold) {
831 status = LTTNG_TRIGGER_STATUS_INVALID;
832 goto end;
833 }
834
835 *policy_type = trigger->firing_policy.type;
836 *threshold = trigger->firing_policy.threshold;
837
838end:
839 return status;
840}
841
842LTTNG_HIDDEN
843bool lttng_trigger_should_fire(const struct lttng_trigger *trigger)
844{
845 assert(trigger);
846 bool ready_to_fire = false;
847
848 switch (trigger->firing_policy.type) {
849 case LTTNG_TRIGGER_FIRE_EVERY_N:
850 if (trigger->firing_policy.current_count < trigger->firing_policy.threshold) {
851 ready_to_fire = true;
852 }
853 break;
854 case LTTNG_TRIGGER_FIRE_ONCE_AFTER_N:
855 if (trigger->firing_policy.current_count < trigger->firing_policy.threshold) {
856 ready_to_fire = true;
857 }
858 break;
859 default:
860 abort();
861 };
862
863 return ready_to_fire;
864}
865
866LTTNG_HIDDEN
867void lttng_trigger_fire(struct lttng_trigger *trigger)
868{
869 assert(trigger);
870
871 trigger->firing_policy.current_count++;
872
873 switch (trigger->firing_policy.type) {
874 case LTTNG_TRIGGER_FIRE_EVERY_N:
875 if (trigger->firing_policy.current_count == trigger->firing_policy.threshold) {
876 trigger->firing_policy.current_count = 0;
877 }
878 break;
879 case LTTNG_TRIGGER_FIRE_ONCE_AFTER_N:
880 /*
881 * TODO: deactivate the trigger condition on
882 * remove any work overhead on the
883 * traced application or kernel since the trigger will
884 * never fire again.
885 */
886 break;
887 default:
888 abort();
889 };
890}
891
892LTTNG_HIDDEN
893enum lttng_domain_type lttng_trigger_get_underlying_domain_type_restriction(
894 const struct lttng_trigger *trigger)
895{
896 enum lttng_domain_type type = LTTNG_DOMAIN_NONE;
897 const struct lttng_event_rule *event_rule;
898 enum lttng_condition_status c_status;
899 enum lttng_condition_type c_type;
900
901 assert(trigger);
902 assert(trigger->condition);
903 c_type = lttng_condition_get_type(trigger->condition);
904 if (c_type == LTTNG_CONDITION_TYPE_UNKNOWN) {
905 assert(0);
906 }
907
908 switch (c_type) {
909 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
910 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
911 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
912 type = LTTNG_DOMAIN_NONE;
913 break;
914 case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT:
915 c_status = lttng_condition_event_rule_get_rule(
916 trigger->condition, &event_rule);
917 if (c_status != LTTNG_CONDITION_STATUS_OK) {
918 /* The condition object is invalid */
919 assert(0);
920 }
921
922 type = lttng_event_rule_get_domain_type(event_rule);
923 break;
924 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
925 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
926 c_status = lttng_condition_buffer_usage_get_domain_type(
927 trigger->condition, &type);
928 if (c_status != LTTNG_CONDITION_STATUS_OK) {
929 /* The condition object is invalid */
930 assert(0);
931 }
932 break;
933 default:
934 type = LTTNG_DOMAIN_NONE;
935 break;
936 }
937
938 return type;
939}
940
941LTTNG_HIDDEN
942struct lttng_trigger *lttng_trigger_copy(const struct lttng_trigger *trigger)
943{
944 int ret;
945 struct lttng_payload copy_buffer;
946 struct lttng_trigger *copy = NULL;
947
948 lttng_payload_init(&copy_buffer);
949
950 ret = lttng_trigger_serialize(trigger, &copy_buffer);
951 if (ret < 0) {
952 goto end;
953 }
954
955 {
956 struct lttng_payload_view view =
957 lttng_payload_view_from_payload(
958 &copy_buffer, 0, -1);
959 ret = lttng_trigger_create_from_payload(
960 &view, &copy);
961 if (ret < 0) {
962 copy = NULL;
963 goto end;
964 }
965 }
966
967end:
968 lttng_payload_reset(&copy_buffer);
969 return copy;
970}
971
972LTTNG_HIDDEN
973unsigned int lttng_trigger_get_capture_bytecode_count(
974 const struct lttng_trigger *trigger)
975{
976 unsigned int count = 0;
977 if (!trigger) {
978 goto end;
979 }
980
981 count = lttng_dynamic_pointer_array_get_count(
982 &trigger->capture_bytecode_set);
983
984end:
985 return count;
986}
987
988LTTNG_HIDDEN
989const struct lttng_bytecode *
990lttng_trigger_get_capture_bytecode_at_index(
991 const struct lttng_trigger *trigger, unsigned int index)
992{
993 struct lttng_condition_event_rule_capture_bytecode_element *element = NULL;
994 struct lttng_bytecode *bytecode = NULL;
995
996 element = lttng_dynamic_pointer_array_get_pointer(
997 &trigger->capture_bytecode_set, index);
998
999 if (element == NULL) {
1000 goto end;
1001 }
1002 bytecode = element->bytecode;
1003end:
1004 return bytecode;
3da864a9 1005}
This page took 0.084714 seconds and 5 git commands to generate.