Force usage of assert() condition when NDEBUG is defined
[lttng-tools.git] / src / common / trigger.c
1 /*
2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <common/credentials.h>
9 #include <common/dynamic-array.h>
10 #include <common/error.h>
11 #include <common/mi-lttng.h>
12 #include <common/optional.h>
13 #include <common/payload-view.h>
14 #include <common/payload.h>
15 #include <inttypes.h>
16 #include <lttng/action/action-internal.h>
17 #include <lttng/condition/buffer-usage.h>
18 #include <lttng/condition/condition-internal.h>
19 #include <lttng/condition/event-rule-matches-internal.h>
20 #include <lttng/condition/event-rule-matches.h>
21 #include <lttng/domain.h>
22 #include <lttng/error-query-internal.h>
23 #include <lttng/event-expr-internal.h>
24 #include <lttng/event-rule/event-rule-internal.h>
25 #include <lttng/trigger/trigger-internal.h>
26 #include <pthread.h>
27
28 LTTNG_HIDDEN
29 bool lttng_trigger_validate(const struct lttng_trigger *trigger)
30 {
31 bool valid;
32
33 if (!trigger) {
34 valid = false;
35 goto end;
36 }
37
38 if (!trigger->creds.uid.is_set) {
39 valid = false;
40 goto end;
41 }
42
43 valid = lttng_condition_validate(trigger->condition) &&
44 lttng_action_validate(trigger->action);
45 end:
46 return valid;
47 }
48
49 struct lttng_trigger *lttng_trigger_create(
50 struct lttng_condition *condition,
51 struct lttng_action *action)
52 {
53 struct lttng_trigger *trigger = NULL;
54
55 if (!condition || !action) {
56 goto end;
57 }
58
59 trigger = zmalloc(sizeof(struct lttng_trigger));
60 if (!trigger) {
61 goto end;
62 }
63
64 urcu_ref_init(&trigger->ref);
65
66 lttng_condition_get(condition);
67 trigger->condition = condition;
68
69 lttng_action_get(action);
70 trigger->action = action;
71
72 pthread_mutex_init(&trigger->lock, NULL);
73 trigger->registered = false;
74
75 end:
76 return trigger;
77 }
78
79 /*
80 * Note: the lack of reference counting 'get' on the condition object is normal.
81 * This API was exposed as such in 2.11. The client is not expected to call
82 * lttng_condition_destroy on the returned object.
83 */
84 struct lttng_condition *lttng_trigger_get_condition(
85 struct lttng_trigger *trigger)
86 {
87 return trigger ? trigger->condition : NULL;
88 }
89
90 const struct lttng_condition *lttng_trigger_get_const_condition(
91 const struct lttng_trigger *trigger)
92 {
93 return trigger ? trigger->condition : NULL;
94 }
95
96 /*
97 * Note: the lack of reference counting 'get' on the action object is normal.
98 * This API was exposed as such in 2.11. The client is not expected to call
99 * lttng_action_destroy on the returned object.
100 */
101 struct lttng_action *lttng_trigger_get_action(
102 struct lttng_trigger *trigger)
103 {
104 return trigger ? trigger->action : NULL;
105 }
106
107 const struct lttng_action *lttng_trigger_get_const_action(
108 const struct lttng_trigger *trigger)
109 {
110 return trigger ? trigger->action : NULL;
111 }
112
113 static void trigger_destroy_ref(struct urcu_ref *ref)
114 {
115 struct lttng_trigger *trigger =
116 container_of(ref, struct lttng_trigger, ref);
117 struct lttng_action *action = lttng_trigger_get_action(trigger);
118 struct lttng_condition *condition =
119 lttng_trigger_get_condition(trigger);
120
121 LTTNG_ASSERT(action);
122 LTTNG_ASSERT(condition);
123
124 /* Release ownership. */
125 lttng_action_put(action);
126 lttng_condition_put(condition);
127
128 pthread_mutex_destroy(&trigger->lock);
129
130 free(trigger->name);
131 free(trigger);
132 }
133
134 void lttng_trigger_destroy(struct lttng_trigger *trigger)
135 {
136 lttng_trigger_put(trigger);
137 }
138
139 LTTNG_HIDDEN
140 ssize_t lttng_trigger_create_from_payload(
141 struct lttng_payload_view *src_view,
142 struct lttng_trigger **_trigger)
143 {
144 ssize_t ret, offset = 0, condition_size, action_size, name_size = 0;
145 struct lttng_condition *condition = NULL;
146 struct lttng_action *action = NULL;
147 const struct lttng_trigger_comm *trigger_comm;
148 const char *name = NULL;
149 struct lttng_credentials creds = {
150 .uid = LTTNG_OPTIONAL_INIT_UNSET,
151 .gid = LTTNG_OPTIONAL_INIT_UNSET,
152 };
153 struct lttng_trigger *trigger = NULL;
154 const struct lttng_payload_view trigger_comm_view =
155 lttng_payload_view_from_view(
156 src_view, 0, sizeof(*trigger_comm));
157
158 if (!src_view || !_trigger) {
159 ret = -1;
160 goto end;
161 }
162
163 if (!lttng_payload_view_is_valid(&trigger_comm_view)) {
164 /* Payload not large enough to contain the header. */
165 ret = -1;
166 goto end;
167 }
168
169 /* lttng_trigger_comm header */
170 trigger_comm = (typeof(trigger_comm)) trigger_comm_view.buffer.data;
171
172 /* Set the trigger's creds. */
173 if (trigger_comm->uid > (uint64_t) ((uid_t) -1)) {
174 /* UID out of range for this platform. */
175 ret = -1;
176 goto end;
177 }
178
179 LTTNG_OPTIONAL_SET(&creds.uid, trigger_comm->uid);
180
181 offset += sizeof(*trigger_comm);
182
183 if (trigger_comm->name_length != 0) {
184 /* Name. */
185 const struct lttng_payload_view name_view =
186 lttng_payload_view_from_view(
187 src_view, offset,
188 trigger_comm->name_length);
189
190 if (!lttng_payload_view_is_valid(&name_view)) {
191 ret = -1;
192 goto end;
193 }
194
195 name = name_view.buffer.data;
196 if (!lttng_buffer_view_contains_string(&name_view.buffer, name,
197 trigger_comm->name_length)) {
198 ret = -1;
199 goto end;
200 }
201
202 offset += trigger_comm->name_length;
203 name_size = trigger_comm->name_length;
204 }
205
206 {
207 /* struct lttng_condition */
208 struct lttng_payload_view condition_view =
209 lttng_payload_view_from_view(
210 src_view, offset, -1);
211
212 condition_size = lttng_condition_create_from_payload(&condition_view,
213 &condition);
214 }
215
216 if (condition_size < 0) {
217 ret = condition_size;
218 goto end;
219 }
220
221 offset += condition_size;
222 {
223 /* struct lttng_action */
224 struct lttng_payload_view action_view =
225 lttng_payload_view_from_view(
226 src_view, offset, -1);
227
228 action_size = lttng_action_create_from_payload(&action_view, &action);
229 }
230
231 if (action_size < 0) {
232 ret = action_size;
233 goto end;
234 }
235 offset += action_size;
236
237 /* Unexpected size of inner-elements; the buffer is corrupted. */
238 if ((ssize_t) trigger_comm->length != condition_size + action_size + name_size) {
239 ret = -1;
240 goto error;
241 }
242
243 trigger = lttng_trigger_create(condition, action);
244 if (!trigger) {
245 ret = -1;
246 goto error;
247 }
248
249 lttng_trigger_set_credentials(trigger, &creds);
250
251 /*
252 * The trigger object owns references to the action and condition
253 * objects.
254 */
255 lttng_condition_put(condition);
256 condition = NULL;
257
258 lttng_action_put(action);
259 action = NULL;
260
261 if (name) {
262 const enum lttng_trigger_status status =
263 lttng_trigger_set_name(trigger, name);
264
265 if (status != LTTNG_TRIGGER_STATUS_OK) {
266 ret = -1;
267 goto end;
268 }
269 }
270
271 ret = offset;
272
273 error:
274 lttng_condition_put(condition);
275 lttng_action_put(action);
276 end:
277 if (ret >= 0) {
278 *_trigger = trigger;
279 } else {
280 lttng_trigger_put(trigger);
281 }
282
283 return ret;
284 }
285
286 /*
287 * Both elements are stored contiguously, see their "*_comm" structure
288 * for the detailed format.
289 */
290 LTTNG_HIDDEN
291 int lttng_trigger_serialize(const struct lttng_trigger *trigger,
292 struct lttng_payload *payload)
293 {
294 int ret;
295 size_t header_offset, size_before_payload, size_name;
296 struct lttng_trigger_comm trigger_comm = {};
297 struct lttng_trigger_comm *header;
298 const struct lttng_credentials *creds = NULL;
299
300 creds = lttng_trigger_get_credentials(trigger);
301 LTTNG_ASSERT(creds);
302
303 trigger_comm.uid = LTTNG_OPTIONAL_GET(creds->uid);
304
305 if (trigger->name != NULL) {
306 size_name = strlen(trigger->name) + 1;
307 } else {
308 size_name = 0;
309 }
310
311 trigger_comm.name_length = size_name;
312
313 header_offset = payload->buffer.size;
314 ret = lttng_dynamic_buffer_append(&payload->buffer, &trigger_comm,
315 sizeof(trigger_comm));
316 if (ret) {
317 goto end;
318 }
319
320 size_before_payload = payload->buffer.size;
321
322 /* Trigger name. */
323 ret = lttng_dynamic_buffer_append(
324 &payload->buffer, trigger->name, size_name);
325 if (ret) {
326 goto end;
327 }
328
329 ret = lttng_condition_serialize(trigger->condition, payload);
330 if (ret) {
331 goto end;
332 }
333
334 ret = lttng_action_serialize(trigger->action, payload);
335 if (ret) {
336 goto end;
337 }
338
339 /* Update payload size. */
340 header = (typeof(header)) (payload->buffer.data + header_offset);
341 header->length = payload->buffer.size - size_before_payload;
342 end:
343 return ret;
344 }
345
346 LTTNG_HIDDEN
347 bool lttng_trigger_is_equal(
348 const struct lttng_trigger *a, const struct lttng_trigger *b)
349 {
350 if (!!a->name != !!b->name) {
351 /* Both must be either anonymous or named. */
352 return false;
353 }
354
355 if (a->name && strcmp(a->name, b->name) != 0) {
356 return false;
357 }
358
359 if (!lttng_condition_is_equal(a->condition, b->condition)) {
360 return false;
361 }
362
363 if (!lttng_action_is_equal(a->action, b->action)) {
364 return false;
365 }
366
367 if (!lttng_credentials_is_equal(lttng_trigger_get_credentials(a),
368 lttng_trigger_get_credentials(b))) {
369 return false;
370 }
371
372 if (a->is_hidden != b->is_hidden) {
373 return false;
374 }
375
376 return true;
377 }
378
379 LTTNG_HIDDEN
380 bool lttng_trigger_is_hidden(const struct lttng_trigger *trigger)
381 {
382 return trigger->is_hidden;
383 }
384
385 LTTNG_HIDDEN
386 void lttng_trigger_set_hidden(struct lttng_trigger *trigger)
387 {
388 LTTNG_ASSERT(!trigger->is_hidden);
389 trigger->is_hidden = true;
390 }
391
392 LTTNG_HIDDEN
393 enum lttng_trigger_status lttng_trigger_set_name(struct lttng_trigger *trigger,
394 const char* name)
395 {
396 char *name_copy = NULL;
397 enum lttng_trigger_status status = LTTNG_TRIGGER_STATUS_OK;
398
399 if (!trigger) {
400 status = LTTNG_TRIGGER_STATUS_INVALID;
401 goto end;
402 }
403
404 if (name) {
405 name_copy = strdup(name);
406 if (!name_copy) {
407 status = LTTNG_TRIGGER_STATUS_ERROR;
408 goto end;
409 }
410 }
411
412 free(trigger->name);
413
414 trigger->name = name_copy;
415 name_copy = NULL;
416 end:
417 return status;
418 }
419
420 enum lttng_trigger_status lttng_trigger_get_name(
421 const struct lttng_trigger *trigger, const char **name)
422 {
423 enum lttng_trigger_status status = LTTNG_TRIGGER_STATUS_OK;
424
425 if (!trigger || !name) {
426 status = LTTNG_TRIGGER_STATUS_INVALID;
427 goto end;
428 }
429
430 if (!trigger->name) {
431 status = LTTNG_TRIGGER_STATUS_UNSET;
432 }
433
434 *name = trigger->name;
435 end:
436 return status;
437 }
438
439 LTTNG_HIDDEN
440 int lttng_trigger_assign_name(struct lttng_trigger *dst,
441 const struct lttng_trigger *src)
442 {
443 int ret = 0;
444 enum lttng_trigger_status status;
445
446 status = lttng_trigger_set_name(dst, src->name);
447 if (status != LTTNG_TRIGGER_STATUS_OK) {
448 ret = -1;
449 ERR("Failed to set name for trigger");
450 goto end;
451 }
452 end:
453 return ret;
454 }
455
456 LTTNG_HIDDEN
457 void lttng_trigger_set_tracer_token(struct lttng_trigger *trigger,
458 uint64_t token)
459 {
460 LTTNG_ASSERT(trigger);
461 LTTNG_OPTIONAL_SET(&trigger->tracer_token, token);
462 }
463
464 LTTNG_HIDDEN
465 uint64_t lttng_trigger_get_tracer_token(const struct lttng_trigger *trigger)
466 {
467 LTTNG_ASSERT(trigger);
468
469 return LTTNG_OPTIONAL_GET(trigger->tracer_token);
470 }
471
472 LTTNG_HIDDEN
473 int lttng_trigger_generate_name(struct lttng_trigger *trigger,
474 uint64_t unique_id)
475 {
476 int ret = 0;
477 char *generated_name = NULL;
478
479 ret = asprintf(&generated_name, "trigger%" PRIu64 "", unique_id);
480 if (ret < 0) {
481 ERR("Failed to generate trigger name");
482 ret = -1;
483 goto end;
484 }
485
486 ret = 0;
487 free(trigger->name);
488 trigger->name = generated_name;
489 end:
490 return ret;
491 }
492
493 LTTNG_HIDDEN
494 void lttng_trigger_get(struct lttng_trigger *trigger)
495 {
496 urcu_ref_get(&trigger->ref);
497 }
498
499 LTTNG_HIDDEN
500 void lttng_trigger_put(struct lttng_trigger *trigger)
501 {
502 if (!trigger) {
503 return;
504 }
505
506 urcu_ref_put(&trigger->ref , trigger_destroy_ref);
507 }
508
509 static void delete_trigger_array_element(void *ptr)
510 {
511 struct lttng_trigger *trigger = ptr;
512
513 lttng_trigger_put(trigger);
514 }
515
516 LTTNG_HIDDEN
517 struct lttng_triggers *lttng_triggers_create(void)
518 {
519 struct lttng_triggers *triggers = NULL;
520
521 triggers = zmalloc(sizeof(*triggers));
522 if (!triggers) {
523 goto end;
524 }
525
526 lttng_dynamic_pointer_array_init(&triggers->array, delete_trigger_array_element);
527
528 end:
529 return triggers;
530 }
531
532 LTTNG_HIDDEN
533 struct lttng_trigger *lttng_triggers_borrow_mutable_at_index(
534 const struct lttng_triggers *triggers, unsigned int index)
535 {
536 struct lttng_trigger *trigger = NULL;
537
538 LTTNG_ASSERT(triggers);
539 if (index >= lttng_dynamic_pointer_array_get_count(&triggers->array)) {
540 goto end;
541 }
542
543 trigger = (struct lttng_trigger *)
544 lttng_dynamic_pointer_array_get_pointer(
545 &triggers->array, index);
546 end:
547 return trigger;
548 }
549
550 LTTNG_HIDDEN
551 int lttng_triggers_add(
552 struct lttng_triggers *triggers, struct lttng_trigger *trigger)
553 {
554 int ret;
555
556 LTTNG_ASSERT(triggers);
557 LTTNG_ASSERT(trigger);
558
559 lttng_trigger_get(trigger);
560
561 ret = lttng_dynamic_pointer_array_add_pointer(&triggers->array, trigger);
562 if (ret) {
563 lttng_trigger_put(trigger);
564 }
565
566 return ret;
567 }
568
569 LTTNG_HIDDEN
570 int lttng_triggers_remove_hidden_triggers(struct lttng_triggers *triggers)
571 {
572 int ret;
573 unsigned int trigger_count, i = 0;
574 enum lttng_trigger_status trigger_status;
575
576 LTTNG_ASSERT(triggers);
577
578 trigger_status = lttng_triggers_get_count(triggers, &trigger_count);
579 LTTNG_ASSERT(trigger_status == LTTNG_TRIGGER_STATUS_OK);
580
581 while (i < trigger_count) {
582 const struct lttng_trigger *trigger =
583 lttng_triggers_get_at_index(triggers, i);
584
585 if (lttng_trigger_is_hidden(trigger)) {
586 ret = lttng_dynamic_pointer_array_remove_pointer(
587 &triggers->array, i);
588 if (ret) {
589 goto end;
590 }
591
592 trigger_count--;
593 } else {
594 i++;
595 }
596 }
597
598 ret = 0;
599 end:
600 return ret;
601 }
602
603 const struct lttng_trigger *lttng_triggers_get_at_index(
604 const struct lttng_triggers *triggers, unsigned int index)
605 {
606 return lttng_triggers_borrow_mutable_at_index(triggers, index);
607 }
608
609 enum lttng_trigger_status lttng_triggers_get_count(const struct lttng_triggers *triggers, unsigned int *count)
610 {
611 enum lttng_trigger_status status = LTTNG_TRIGGER_STATUS_OK;
612
613 if (!triggers || !count) {
614 status = LTTNG_TRIGGER_STATUS_INVALID;
615 goto end;
616 }
617
618 *count = lttng_dynamic_pointer_array_get_count(&triggers->array);
619 end:
620 return status;
621 }
622
623 void lttng_triggers_destroy(struct lttng_triggers *triggers)
624 {
625 if (!triggers) {
626 return;
627 }
628
629 lttng_dynamic_pointer_array_reset(&triggers->array);
630 free(triggers);
631 }
632
633 int lttng_triggers_serialize(const struct lttng_triggers *triggers,
634 struct lttng_payload *payload)
635 {
636 int ret;
637 unsigned int i, count;
638 size_t size_before_payload;
639 struct lttng_triggers_comm triggers_comm = {};
640 struct lttng_triggers_comm *header;
641 enum lttng_trigger_status status;
642 const size_t header_offset = payload->buffer.size;
643
644 status = lttng_triggers_get_count(triggers, &count);
645 if (status != LTTNG_TRIGGER_STATUS_OK) {
646 ret = LTTNG_ERR_INVALID;
647 goto end;
648 }
649
650 triggers_comm.count = count;
651
652 /* Placeholder header; updated at the end. */
653 ret = lttng_dynamic_buffer_append(&payload->buffer, &triggers_comm,
654 sizeof(triggers_comm));
655 if (ret) {
656 goto end;
657 }
658
659 size_before_payload = payload->buffer.size;
660
661 for (i = 0; i < count; i++) {
662 const struct lttng_trigger *trigger =
663 lttng_triggers_get_at_index(triggers, i);
664
665 LTTNG_ASSERT(trigger);
666
667 ret = lttng_trigger_serialize(trigger, payload);
668 if (ret) {
669 goto end;
670 }
671 }
672
673 /* Update payload size. */
674 header = (struct lttng_triggers_comm *) ((char *) payload->buffer.data + header_offset);
675 header->length = payload->buffer.size - size_before_payload;
676 end:
677 return ret;
678 }
679
680 LTTNG_HIDDEN
681 ssize_t lttng_triggers_create_from_payload(
682 struct lttng_payload_view *src_view,
683 struct lttng_triggers **triggers)
684 {
685 ssize_t ret, offset = 0, triggers_size = 0;
686 unsigned int i;
687 const struct lttng_triggers_comm *triggers_comm;
688 struct lttng_triggers *local_triggers = NULL;
689
690 if (!src_view || !triggers) {
691 ret = -1;
692 goto error;
693 }
694
695 /* lttng_trigger_comms header */
696 triggers_comm = (const struct lttng_triggers_comm *) src_view->buffer.data;
697 offset += sizeof(*triggers_comm);
698
699 local_triggers = lttng_triggers_create();
700 if (!local_triggers) {
701 ret = -1;
702 goto error;
703 }
704
705 for (i = 0; i < triggers_comm->count; i++) {
706 struct lttng_trigger *trigger = NULL;
707 struct lttng_payload_view trigger_view =
708 lttng_payload_view_from_view(src_view, offset, -1);
709 ssize_t trigger_size;
710
711 trigger_size = lttng_trigger_create_from_payload(
712 &trigger_view, &trigger);
713 if (trigger_size < 0) {
714 ret = trigger_size;
715 goto error;
716 }
717
718 /* Transfer ownership of the trigger to the collection. */
719 ret = lttng_triggers_add(local_triggers, trigger);
720 lttng_trigger_put(trigger);
721 if (ret < 0) {
722 ret = -1;
723 goto error;
724 }
725
726 offset += trigger_size;
727 triggers_size += trigger_size;
728 }
729
730 /* Unexpected size of inner-elements; the buffer is corrupted. */
731 if ((ssize_t) triggers_comm->length != triggers_size) {
732 ret = -1;
733 goto error;
734 }
735
736 /* Pass ownership to caller. */
737 *triggers = local_triggers;
738 local_triggers = NULL;
739
740 ret = offset;
741 error:
742
743 lttng_triggers_destroy(local_triggers);
744 return ret;
745 }
746
747 LTTNG_HIDDEN
748 const struct lttng_credentials *lttng_trigger_get_credentials(
749 const struct lttng_trigger *trigger)
750 {
751 return &trigger->creds;
752 }
753
754 LTTNG_HIDDEN
755 void lttng_trigger_set_credentials(struct lttng_trigger *trigger,
756 const struct lttng_credentials *creds)
757 {
758 LTTNG_ASSERT(creds);
759 trigger->creds = *creds;
760 }
761
762 enum lttng_trigger_status lttng_trigger_set_owner_uid(
763 struct lttng_trigger *trigger, uid_t uid)
764 {
765 enum lttng_trigger_status ret = LTTNG_TRIGGER_STATUS_OK;
766 const uid_t euid = geteuid();
767 const struct lttng_credentials creds = {
768 .uid = LTTNG_OPTIONAL_INIT_VALUE(uid),
769 .gid = LTTNG_OPTIONAL_INIT_UNSET,
770 };
771
772 if (!trigger) {
773 ret = LTTNG_TRIGGER_STATUS_INVALID;
774 goto end;
775 }
776
777 /* Client-side validation only to report a clearer error. */
778 if (euid != 0 && euid != uid) {
779 ret = LTTNG_TRIGGER_STATUS_PERMISSION_DENIED;
780 goto end;
781 }
782
783 lttng_trigger_set_credentials(trigger, &creds);
784
785 end:
786 return ret;
787 }
788
789 enum lttng_trigger_status lttng_trigger_get_owner_uid(
790 const struct lttng_trigger *trigger, uid_t *uid)
791 {
792 enum lttng_trigger_status ret = LTTNG_TRIGGER_STATUS_OK;
793 const struct lttng_credentials *creds = NULL;
794
795 if (!trigger || !uid ) {
796 ret = LTTNG_TRIGGER_STATUS_INVALID;
797 goto end;
798 }
799
800 if (!trigger->creds.uid.is_set ) {
801 ret = LTTNG_TRIGGER_STATUS_UNSET;
802 goto end;
803 }
804
805 creds = lttng_trigger_get_credentials(trigger);
806 *uid = lttng_credentials_get_uid(creds);
807
808 end:
809 return ret;
810 }
811
812 LTTNG_HIDDEN
813 enum lttng_domain_type lttng_trigger_get_underlying_domain_type_restriction(
814 const struct lttng_trigger *trigger)
815 {
816 enum lttng_domain_type type = LTTNG_DOMAIN_NONE;
817 const struct lttng_event_rule *event_rule;
818 enum lttng_condition_status c_status;
819 enum lttng_condition_type c_type;
820
821 LTTNG_ASSERT(trigger);
822 LTTNG_ASSERT(trigger->condition);
823
824 c_type = lttng_condition_get_type(trigger->condition);
825 assert (c_type != LTTNG_CONDITION_TYPE_UNKNOWN);
826
827 switch (c_type) {
828 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
829 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
830 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
831 /* Apply to any domain. */
832 type = LTTNG_DOMAIN_NONE;
833 break;
834 case LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES:
835 /* Return the domain of the event rule. */
836 c_status = lttng_condition_event_rule_matches_get_rule(
837 trigger->condition, &event_rule);
838 LTTNG_ASSERT(c_status == LTTNG_CONDITION_STATUS_OK);
839 type = lttng_event_rule_get_domain_type(event_rule);
840 break;
841 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
842 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
843 /* Return the domain of the channel being monitored. */
844 c_status = lttng_condition_buffer_usage_get_domain_type(
845 trigger->condition, &type);
846 LTTNG_ASSERT(c_status == LTTNG_CONDITION_STATUS_OK);
847 break;
848 default:
849 abort();
850 }
851
852 return type;
853 }
854
855 /*
856 * Generate bytecode related to the trigger.
857 * On success LTTNG_OK. On error, returns lttng_error code.
858 */
859 LTTNG_HIDDEN
860 enum lttng_error_code lttng_trigger_generate_bytecode(
861 struct lttng_trigger *trigger,
862 const struct lttng_credentials *creds)
863 {
864 enum lttng_error_code ret;
865 struct lttng_condition *condition = NULL;
866
867 condition = lttng_trigger_get_condition(trigger);
868 if (!condition) {
869 ret = LTTNG_ERR_INVALID_TRIGGER;
870 goto end;
871 }
872
873 switch (lttng_condition_get_type(condition)) {
874 case LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES:
875 {
876 struct lttng_event_rule *event_rule;
877 const enum lttng_condition_status condition_status =
878 lttng_condition_event_rule_matches_borrow_rule_mutable(
879 condition, &event_rule);
880
881 LTTNG_ASSERT(condition_status == LTTNG_CONDITION_STATUS_OK);
882
883 /* Generate the filter bytecode. */
884 ret = lttng_event_rule_generate_filter_bytecode(
885 event_rule, creds);
886 if (ret != LTTNG_OK) {
887 goto end;
888 }
889
890 /* Generate the capture bytecode. */
891 ret = lttng_condition_event_rule_matches_generate_capture_descriptor_bytecode(
892 condition);
893 if (ret != LTTNG_OK) {
894 goto end;
895 }
896
897 ret = LTTNG_OK;
898 break;
899 }
900 default:
901 ret = LTTNG_OK;
902 break;
903 }
904 end:
905 return ret;
906 }
907
908 LTTNG_HIDDEN
909 struct lttng_trigger *lttng_trigger_copy(const struct lttng_trigger *trigger)
910 {
911 int ret;
912 struct lttng_payload copy_buffer;
913 struct lttng_condition *condition_copy = NULL;
914 struct lttng_action *action_copy = NULL;
915 struct lttng_trigger *copy = NULL;
916 enum lttng_trigger_status trigger_status;
917 const char *trigger_name;
918 uid_t trigger_owner_uid;
919
920 lttng_payload_init(&copy_buffer);
921
922 ret = lttng_condition_serialize(trigger->condition, &copy_buffer);
923 if (ret < 0) {
924 goto end;
925 }
926
927 {
928 struct lttng_payload_view view =
929 lttng_payload_view_from_payload(
930 &copy_buffer, 0, -1);
931
932 ret = lttng_condition_create_from_payload(
933 &view, &condition_copy);
934 if (ret < 0) {
935 goto end;
936 }
937 }
938
939 lttng_payload_clear(&copy_buffer);
940
941 ret = lttng_action_serialize(trigger->action, &copy_buffer);
942 if (ret < 0) {
943 goto end;
944 }
945
946 {
947 struct lttng_payload_view view =
948 lttng_payload_view_from_payload(
949 &copy_buffer, 0, -1);
950
951 ret = lttng_action_create_from_payload(
952 &view, &action_copy);
953 if (ret < 0) {
954 goto end;
955 }
956 }
957
958 copy = lttng_trigger_create(condition_copy, action_copy);
959 if (!copy) {
960 ERR("Failed to allocate trigger during trigger copy");
961 goto end;
962 }
963
964 trigger_status = lttng_trigger_get_name(trigger, &trigger_name);
965 switch (trigger_status) {
966 case LTTNG_TRIGGER_STATUS_OK:
967 trigger_status = lttng_trigger_set_name(copy, trigger_name);
968 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
969 ERR("Failed to set name of new trigger during copy");
970 goto error_cleanup_trigger;
971 }
972 break;
973 case LTTNG_TRIGGER_STATUS_UNSET:
974 break;
975 default:
976 ERR("Failed to get name of original trigger during copy");
977 goto error_cleanup_trigger;
978 }
979
980 trigger_status = lttng_trigger_get_owner_uid(
981 trigger, &trigger_owner_uid);
982 switch (trigger_status) {
983 case LTTNG_TRIGGER_STATUS_OK:
984 LTTNG_OPTIONAL_SET(&copy->creds.uid, trigger_owner_uid);
985 break;
986 case LTTNG_TRIGGER_STATUS_UNSET:
987 break;
988 default:
989 ERR("Failed to get owner uid of original trigger during copy");
990 goto error_cleanup_trigger;
991 }
992
993 copy->tracer_token = trigger->tracer_token;
994 copy->registered = trigger->registered;
995 copy->is_hidden = trigger->is_hidden;
996 goto end;
997
998 error_cleanup_trigger:
999 lttng_trigger_destroy(copy);
1000 copy = NULL;
1001 end:
1002 lttng_condition_put(condition_copy);
1003 lttng_action_put(action_copy);
1004 lttng_payload_reset(&copy_buffer);
1005 return copy;
1006 }
1007
1008 LTTNG_HIDDEN
1009 bool lttng_trigger_needs_tracer_notifier(const struct lttng_trigger *trigger)
1010 {
1011 bool needs_tracer_notifier = false;
1012 const struct lttng_condition *condition =
1013 lttng_trigger_get_const_condition(trigger);
1014
1015 switch (lttng_condition_get_type(condition)) {
1016 case LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES:
1017 needs_tracer_notifier = true;
1018 goto end;
1019 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
1020 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
1021 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
1022 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
1023 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
1024 goto end;
1025 case LTTNG_CONDITION_TYPE_UNKNOWN:
1026 default:
1027 abort();
1028 }
1029 end:
1030 return needs_tracer_notifier;
1031 }
1032
1033 LTTNG_HIDDEN
1034 void lttng_trigger_set_as_registered(struct lttng_trigger *trigger)
1035 {
1036 pthread_mutex_lock(&trigger->lock);
1037 trigger->registered = true;
1038 pthread_mutex_unlock(&trigger->lock);
1039 }
1040
1041 LTTNG_HIDDEN
1042 void lttng_trigger_set_as_unregistered(struct lttng_trigger *trigger)
1043 {
1044 pthread_mutex_lock(&trigger->lock);
1045 trigger->registered = false;
1046 pthread_mutex_unlock(&trigger->lock);
1047 }
1048
1049 /*
1050 * The trigger must be locked before calling lttng_trigger_registered.
1051 * The lock is necessary since a trigger can be unregistered at anytime.
1052 * Manipulations requiring that the trigger be registered must always acquire
1053 * the trigger lock for the duration of the manipulation using
1054 * `lttng_trigger_lock` and `lttng_trigger_unlock`.
1055 */
1056 LTTNG_HIDDEN
1057 bool lttng_trigger_is_registered(struct lttng_trigger *trigger)
1058 {
1059 ASSERT_LOCKED(trigger->lock);
1060 return trigger->registered;
1061 }
1062
1063 LTTNG_HIDDEN
1064 void lttng_trigger_lock(struct lttng_trigger *trigger)
1065 {
1066 pthread_mutex_lock(&trigger->lock);
1067 }
1068
1069 LTTNG_HIDDEN
1070 void lttng_trigger_unlock(struct lttng_trigger *trigger)
1071 {
1072 pthread_mutex_unlock(&trigger->lock);
1073 }
1074
1075 LTTNG_HIDDEN
1076 enum lttng_error_code lttng_trigger_mi_serialize(const struct lttng_trigger *trigger,
1077 struct mi_writer *writer,
1078 const struct mi_lttng_error_query_callbacks
1079 *error_query_callbacks)
1080 {
1081 int ret;
1082 enum lttng_error_code ret_code;
1083 enum lttng_trigger_status trigger_status;
1084 const struct lttng_condition *condition = NULL;
1085 const struct lttng_action *action = NULL;
1086 struct lttng_dynamic_array action_path_indexes;
1087 uid_t owner_uid;
1088
1089 LTTNG_ASSERT(trigger);
1090 LTTNG_ASSERT(writer);
1091
1092 lttng_dynamic_array_init(&action_path_indexes, sizeof(uint64_t), NULL);
1093
1094 /* Open trigger element. */
1095 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_trigger);
1096 if (ret) {
1097 goto mi_error;
1098 }
1099
1100 trigger_status = lttng_trigger_get_owner_uid(trigger, &owner_uid);
1101 LTTNG_ASSERT(trigger_status == LTTNG_TRIGGER_STATUS_OK);
1102
1103 /* Name. */
1104 ret = mi_lttng_writer_write_element_string(
1105 writer, config_element_name, trigger->name);
1106 if (ret) {
1107 goto mi_error;
1108 }
1109
1110 /* Owner uid. */
1111 ret = mi_lttng_writer_write_element_signed_int(writer,
1112 mi_lttng_element_trigger_owner_uid,
1113 (int64_t) owner_uid);
1114 if (ret) {
1115 goto mi_error;
1116 }
1117
1118 /* Condition. */
1119 condition = lttng_trigger_get_const_condition(trigger);
1120 LTTNG_ASSERT(condition);
1121 ret_code = lttng_condition_mi_serialize(
1122 trigger, condition, writer, error_query_callbacks);
1123 if (ret_code != LTTNG_OK) {
1124 goto end;
1125 }
1126
1127 /* Action. */
1128 action = lttng_trigger_get_const_action(trigger);
1129 LTTNG_ASSERT(action);
1130 ret_code = lttng_action_mi_serialize(trigger, action, writer,
1131 error_query_callbacks, &action_path_indexes);
1132 if (ret_code != LTTNG_OK) {
1133 goto end;
1134 }
1135
1136 if (error_query_callbacks && error_query_callbacks->trigger_cb) {
1137 struct lttng_error_query_results *results = NULL;
1138
1139 ret_code = error_query_callbacks->trigger_cb(trigger, &results);
1140 if (ret_code != LTTNG_OK) {
1141 goto end;
1142 }
1143
1144 ret_code = lttng_error_query_results_mi_serialize(
1145 results, writer);
1146 lttng_error_query_results_destroy(results);
1147 if (ret_code != LTTNG_OK) {
1148 goto end;
1149 }
1150 }
1151
1152 /* Close trigger element. */
1153 ret = mi_lttng_writer_close_element(writer);
1154 if (ret) {
1155 goto mi_error;
1156 }
1157
1158 ret_code = LTTNG_OK;
1159 goto end;
1160
1161 mi_error:
1162 ret_code = LTTNG_ERR_MI_IO_FAIL;
1163 end:
1164 lttng_dynamic_array_reset(&action_path_indexes);
1165 return ret_code;
1166 }
1167
1168 /* Used by qsort, which expects the semantics of strcmp(). */
1169 static int compare_triggers_by_name(const void *a, const void *b)
1170 {
1171 const struct lttng_trigger *trigger_a =
1172 *((const struct lttng_trigger **) a);
1173 const struct lttng_trigger *trigger_b =
1174 *((const struct lttng_trigger **) b);
1175 const char *name_a, *name_b;
1176 enum lttng_trigger_status trigger_status;
1177
1178 /* Anonymous triggers are not reachable here. */
1179 trigger_status = lttng_trigger_get_name(trigger_a, &name_a);
1180 LTTNG_ASSERT(trigger_status == LTTNG_TRIGGER_STATUS_OK);
1181
1182 trigger_status = lttng_trigger_get_name(trigger_b, &name_b);
1183 LTTNG_ASSERT(trigger_status == LTTNG_TRIGGER_STATUS_OK);
1184
1185 return strcmp(name_a, name_b);
1186 }
1187
1188 LTTNG_HIDDEN
1189 enum lttng_error_code lttng_triggers_mi_serialize(const struct lttng_triggers *triggers,
1190 struct mi_writer *writer,
1191 const struct mi_lttng_error_query_callbacks
1192 *error_query_callbacks)
1193 {
1194 int ret;
1195 enum lttng_error_code ret_code;
1196 enum lttng_trigger_status status;
1197 unsigned int count, i;
1198 struct lttng_dynamic_pointer_array sorted_triggers;
1199
1200 LTTNG_ASSERT(triggers);
1201 LTTNG_ASSERT(writer);
1202
1203 /*
1204 * Sort trigger by name to ensure an order at the MI level and ignore
1205 * any anonymous trigger present.
1206 */
1207 lttng_dynamic_pointer_array_init(&sorted_triggers, NULL);
1208
1209 status = lttng_triggers_get_count(triggers, &count);
1210 LTTNG_ASSERT(status == LTTNG_TRIGGER_STATUS_OK);
1211
1212 for (i = 0; i < count; i++) {
1213 int add_ret;
1214 const char *unused_name;
1215 const struct lttng_trigger *trigger =
1216 lttng_triggers_get_at_index(triggers, i);
1217
1218 status = lttng_trigger_get_name(trigger, &unused_name);
1219 switch (status) {
1220 case LTTNG_TRIGGER_STATUS_OK:
1221 break;
1222 case LTTNG_TRIGGER_STATUS_UNSET:
1223 /* Don't list anonymous triggers. */
1224 continue;
1225 default:
1226 abort();
1227 }
1228
1229 add_ret = lttng_dynamic_pointer_array_add_pointer(
1230 &sorted_triggers, (void *) trigger);
1231
1232 if (add_ret) {
1233 ERR("Failed to lttng_trigger to sorting array.");
1234 ret_code = LTTNG_ERR_NOMEM;
1235 goto error;
1236 }
1237 }
1238
1239 qsort(sorted_triggers.array.buffer.data, count,
1240 sizeof(struct lttng_trigger *),
1241 compare_triggers_by_name);
1242
1243 /* Open triggers element. */
1244 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_triggers);
1245 if (ret) {
1246 ret_code = LTTNG_ERR_MI_IO_FAIL;
1247 goto error;
1248 }
1249
1250 for (i = 0; i < lttng_dynamic_pointer_array_get_count(&sorted_triggers); i++) {
1251 const struct lttng_trigger *trigger =
1252 (const struct lttng_trigger *)
1253 lttng_dynamic_pointer_array_get_pointer(
1254 &sorted_triggers, i);
1255
1256 lttng_trigger_mi_serialize(trigger, writer, error_query_callbacks);
1257 }
1258
1259 /* Close triggers element. */
1260 ret = mi_lttng_writer_close_element(writer);
1261 if (ret) {
1262 ret_code = LTTNG_ERR_MI_IO_FAIL;
1263 goto error;
1264 }
1265
1266 ret_code = LTTNG_OK;
1267
1268 error:
1269 lttng_dynamic_pointer_array_reset(&sorted_triggers);
1270 return ret_code;
1271 }
This page took 0.07468 seconds and 4 git commands to generate.