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