2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
8 #include <common/credentials.hpp>
9 #include <common/dynamic-array.hpp>
10 #include <common/error.hpp>
11 #include <common/mi-lttng.hpp>
12 #include <common/optional.hpp>
13 #include <common/payload-view.hpp>
14 #include <common/payload.hpp>
16 #include <lttng/action/action-internal.hpp>
17 #include <lttng/condition/buffer-usage.h>
18 #include <lttng/condition/condition-internal.hpp>
19 #include <lttng/condition/event-rule-matches-internal.hpp>
20 #include <lttng/condition/event-rule-matches.h>
21 #include <lttng/domain.h>
22 #include <lttng/error-query-internal.hpp>
23 #include <lttng/event-expr-internal.hpp>
24 #include <lttng/event-rule/event-rule-internal.hpp>
25 #include <lttng/trigger/trigger-internal.hpp>
30 bool lttng_trigger_validate(const struct lttng_trigger
*trigger
)
39 if (!trigger
->creds
.uid
.is_set
) {
44 valid
= lttng_condition_validate(trigger
->condition
) &&
45 lttng_action_validate(trigger
->action
);
50 struct lttng_trigger
*lttng_trigger_create(struct lttng_condition
*condition
,
51 struct lttng_action
*action
)
53 struct lttng_trigger
*trigger
= nullptr;
55 if (!condition
|| !action
) {
59 trigger
= zmalloc
<lttng_trigger
>();
64 urcu_ref_init(&trigger
->ref
);
66 lttng_condition_get(condition
);
67 trigger
->condition
= condition
;
69 lttng_action_get(action
);
70 trigger
->action
= action
;
72 pthread_mutex_init(&trigger
->lock
, nullptr);
73 trigger
->registered
= false;
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.
84 struct lttng_condition
*lttng_trigger_get_condition(struct lttng_trigger
*trigger
)
86 return trigger
? trigger
->condition
: nullptr;
89 const struct lttng_condition
*lttng_trigger_get_const_condition(const struct lttng_trigger
*trigger
)
91 return trigger
? trigger
->condition
: nullptr;
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.
99 struct lttng_action
*lttng_trigger_get_action(struct lttng_trigger
*trigger
)
101 return trigger
? trigger
->action
: nullptr;
104 const struct lttng_action
*lttng_trigger_get_const_action(const struct lttng_trigger
*trigger
)
106 return trigger
? trigger
->action
: nullptr;
109 static void trigger_destroy_ref(struct urcu_ref
*ref
)
111 struct lttng_trigger
*trigger
= lttng::utils::container_of(ref
, <tng_trigger::ref
);
112 struct lttng_action
*action
= lttng_trigger_get_action(trigger
);
113 struct lttng_condition
*condition
= lttng_trigger_get_condition(trigger
);
115 LTTNG_ASSERT(action
);
116 LTTNG_ASSERT(condition
);
118 /* Release ownership. */
119 lttng_action_put(action
);
120 lttng_condition_put(condition
);
122 pthread_mutex_destroy(&trigger
->lock
);
128 void lttng_trigger_destroy(struct lttng_trigger
*trigger
)
130 lttng_trigger_put(trigger
);
133 ssize_t
lttng_trigger_create_from_payload(struct lttng_payload_view
*src_view
,
134 struct lttng_trigger
**_trigger
)
136 ssize_t ret
, offset
= 0, condition_size
, action_size
, name_size
= 0;
137 struct lttng_condition
*condition
= nullptr;
138 struct lttng_action
*action
= nullptr;
139 const struct lttng_trigger_comm
*trigger_comm
;
140 const char *name
= nullptr;
141 struct lttng_credentials creds
= {
142 .uid
= LTTNG_OPTIONAL_INIT_UNSET
,
143 .gid
= LTTNG_OPTIONAL_INIT_UNSET
,
145 struct lttng_trigger
*trigger
= nullptr;
146 const struct lttng_payload_view trigger_comm_view
=
147 lttng_payload_view_from_view(src_view
, 0, sizeof(*trigger_comm
));
149 if (!src_view
|| !_trigger
) {
154 if (!lttng_payload_view_is_valid(&trigger_comm_view
)) {
155 /* Payload not large enough to contain the header. */
160 /* lttng_trigger_comm header */
161 trigger_comm
= (typeof(trigger_comm
)) trigger_comm_view
.buffer
.data
;
163 /* Set the trigger's creds. */
164 if (trigger_comm
->uid
> (uint64_t) ((uid_t
) -1)) {
165 /* UID out of range for this platform. */
170 LTTNG_OPTIONAL_SET(&creds
.uid
, trigger_comm
->uid
);
172 offset
+= sizeof(*trigger_comm
);
174 if (trigger_comm
->name_length
!= 0) {
176 const struct lttng_payload_view name_view
=
177 lttng_payload_view_from_view(src_view
, offset
, trigger_comm
->name_length
);
179 if (!lttng_payload_view_is_valid(&name_view
)) {
184 name
= name_view
.buffer
.data
;
185 if (!lttng_buffer_view_contains_string(
186 &name_view
.buffer
, name
, trigger_comm
->name_length
)) {
191 offset
+= trigger_comm
->name_length
;
192 name_size
= trigger_comm
->name_length
;
196 /* struct lttng_condition */
197 struct lttng_payload_view condition_view
=
198 lttng_payload_view_from_view(src_view
, offset
, -1);
200 condition_size
= lttng_condition_create_from_payload(&condition_view
, &condition
);
203 if (condition_size
< 0) {
204 ret
= condition_size
;
208 offset
+= condition_size
;
210 /* struct lttng_action */
211 struct lttng_payload_view action_view
=
212 lttng_payload_view_from_view(src_view
, offset
, -1);
214 action_size
= lttng_action_create_from_payload(&action_view
, &action
);
217 if (action_size
< 0) {
221 offset
+= action_size
;
223 /* Unexpected size of inner-elements; the buffer is corrupted. */
224 if ((ssize_t
) trigger_comm
->length
!= condition_size
+ action_size
+ name_size
) {
229 trigger
= lttng_trigger_create(condition
, action
);
235 lttng_trigger_set_credentials(trigger
, &creds
);
238 * The trigger object owns references to the action and condition
241 lttng_condition_put(condition
);
244 lttng_action_put(action
);
248 const enum lttng_trigger_status status
= lttng_trigger_set_name(trigger
, name
);
250 if (status
!= LTTNG_TRIGGER_STATUS_OK
) {
256 if (trigger_comm
->is_hidden
) {
257 lttng_trigger_set_hidden(trigger
);
263 lttng_condition_put(condition
);
264 lttng_action_put(action
);
269 lttng_trigger_put(trigger
);
276 * Both elements are stored contiguously, see their "*_comm" structure
277 * for the detailed format.
279 int lttng_trigger_serialize(const struct lttng_trigger
*trigger
, struct lttng_payload
*payload
)
282 size_t header_offset
, size_before_payload
, size_name
;
283 struct lttng_trigger_comm trigger_comm
= {};
284 struct lttng_trigger_comm
*header
;
285 const struct lttng_credentials
*creds
= nullptr;
287 creds
= lttng_trigger_get_credentials(trigger
);
290 trigger_comm
.uid
= LTTNG_OPTIONAL_GET(creds
->uid
);
292 if (trigger
->name
!= nullptr) {
293 size_name
= strlen(trigger
->name
) + 1;
298 trigger_comm
.name_length
= size_name
;
300 trigger_comm
.is_hidden
= lttng_trigger_is_hidden(trigger
);
302 header_offset
= payload
->buffer
.size
;
303 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &trigger_comm
, sizeof(trigger_comm
));
308 size_before_payload
= payload
->buffer
.size
;
311 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, trigger
->name
, size_name
);
316 ret
= lttng_condition_serialize(trigger
->condition
, payload
);
321 ret
= lttng_action_serialize(trigger
->action
, payload
);
326 /* Update payload size. */
327 header
= (typeof(header
)) (payload
->buffer
.data
+ header_offset
);
328 header
->length
= payload
->buffer
.size
- size_before_payload
;
333 bool lttng_trigger_is_equal(const struct lttng_trigger
*a
, const struct lttng_trigger
*b
)
335 if (!!a
->name
!= !!b
->name
) {
336 /* Both must be either anonymous or named. */
340 if (a
->name
&& strcmp(a
->name
, b
->name
) != 0) {
344 if (!lttng_condition_is_equal(a
->condition
, b
->condition
)) {
348 if (!lttng_action_is_equal(a
->action
, b
->action
)) {
352 if (!lttng_credentials_is_equal(lttng_trigger_get_credentials(a
),
353 lttng_trigger_get_credentials(b
))) {
357 if (a
->is_hidden
!= b
->is_hidden
) {
364 bool lttng_trigger_is_hidden(const struct lttng_trigger
*trigger
)
366 LTTNG_ASSERT(trigger
);
367 return trigger
->is_hidden
;
370 void lttng_trigger_set_hidden(struct lttng_trigger
*trigger
)
372 LTTNG_ASSERT(!trigger
->is_hidden
);
373 trigger
->is_hidden
= true;
376 enum lttng_trigger_status
lttng_trigger_set_name(struct lttng_trigger
*trigger
, const char *name
)
378 char *name_copy
= nullptr;
379 enum lttng_trigger_status status
= LTTNG_TRIGGER_STATUS_OK
;
382 status
= LTTNG_TRIGGER_STATUS_INVALID
;
387 name_copy
= strdup(name
);
389 status
= LTTNG_TRIGGER_STATUS_ERROR
;
396 trigger
->name
= name_copy
;
402 enum lttng_trigger_status
lttng_trigger_get_name(const struct lttng_trigger
*trigger
,
405 enum lttng_trigger_status status
= LTTNG_TRIGGER_STATUS_OK
;
407 if (!trigger
|| !name
) {
408 status
= LTTNG_TRIGGER_STATUS_INVALID
;
412 if (!trigger
->name
) {
413 status
= LTTNG_TRIGGER_STATUS_UNSET
;
416 *name
= trigger
->name
;
421 int lttng_trigger_assign_name(struct lttng_trigger
*dst
, const struct lttng_trigger
*src
)
424 enum lttng_trigger_status status
;
426 status
= lttng_trigger_set_name(dst
, src
->name
);
427 if (status
!= LTTNG_TRIGGER_STATUS_OK
) {
429 ERR("Failed to set name for trigger");
436 void lttng_trigger_set_tracer_token(struct lttng_trigger
*trigger
, uint64_t token
)
438 LTTNG_ASSERT(trigger
);
439 LTTNG_OPTIONAL_SET(&trigger
->tracer_token
, token
);
442 uint64_t lttng_trigger_get_tracer_token(const struct lttng_trigger
*trigger
)
444 LTTNG_ASSERT(trigger
);
446 return LTTNG_OPTIONAL_GET(trigger
->tracer_token
);
449 int lttng_trigger_generate_name(struct lttng_trigger
*trigger
, uint64_t unique_id
)
452 char *generated_name
= nullptr;
454 ret
= asprintf(&generated_name
, "trigger%" PRIu64
"", unique_id
);
456 ERR("Failed to generate trigger name");
463 trigger
->name
= generated_name
;
468 void lttng_trigger_get(struct lttng_trigger
*trigger
)
470 urcu_ref_get(&trigger
->ref
);
473 void lttng_trigger_put(struct lttng_trigger
*trigger
)
479 urcu_ref_put(&trigger
->ref
, trigger_destroy_ref
);
482 static void delete_trigger_array_element(void *ptr
)
484 struct lttng_trigger
*trigger
= (lttng_trigger
*) ptr
;
486 lttng_trigger_put(trigger
);
489 struct lttng_triggers
*lttng_triggers_create()
491 struct lttng_triggers
*triggers
= nullptr;
493 triggers
= zmalloc
<lttng_triggers
>();
498 lttng_dynamic_pointer_array_init(&triggers
->array
, delete_trigger_array_element
);
504 struct lttng_trigger
*lttng_triggers_borrow_mutable_at_index(const struct lttng_triggers
*triggers
,
507 struct lttng_trigger
*trigger
= nullptr;
509 LTTNG_ASSERT(triggers
);
510 if (index
>= lttng_dynamic_pointer_array_get_count(&triggers
->array
)) {
514 trigger
= (struct lttng_trigger
*) lttng_dynamic_pointer_array_get_pointer(&triggers
->array
,
520 int lttng_triggers_add(struct lttng_triggers
*triggers
, struct lttng_trigger
*trigger
)
524 LTTNG_ASSERT(triggers
);
525 LTTNG_ASSERT(trigger
);
527 lttng_trigger_get(trigger
);
529 ret
= lttng_dynamic_pointer_array_add_pointer(&triggers
->array
, trigger
);
531 lttng_trigger_put(trigger
);
537 int lttng_triggers_remove_hidden_triggers(struct lttng_triggers
*triggers
)
540 unsigned int trigger_count
, i
= 0;
541 enum lttng_trigger_status trigger_status
;
543 LTTNG_ASSERT(triggers
);
545 trigger_status
= lttng_triggers_get_count(triggers
, &trigger_count
);
546 LTTNG_ASSERT(trigger_status
== LTTNG_TRIGGER_STATUS_OK
);
548 while (i
< trigger_count
) {
549 const struct lttng_trigger
*trigger
= lttng_triggers_get_at_index(triggers
, i
);
551 if (lttng_trigger_is_hidden(trigger
)) {
552 ret
= lttng_dynamic_pointer_array_remove_pointer(&triggers
->array
, i
);
568 const struct lttng_trigger
*lttng_triggers_get_at_index(const struct lttng_triggers
*triggers
,
571 return lttng_triggers_borrow_mutable_at_index(triggers
, index
);
574 enum lttng_trigger_status
lttng_triggers_get_count(const struct lttng_triggers
*triggers
,
577 enum lttng_trigger_status status
= LTTNG_TRIGGER_STATUS_OK
;
579 if (!triggers
|| !count
) {
580 status
= LTTNG_TRIGGER_STATUS_INVALID
;
584 *count
= lttng_dynamic_pointer_array_get_count(&triggers
->array
);
589 void lttng_triggers_destroy(struct lttng_triggers
*triggers
)
595 lttng_dynamic_pointer_array_reset(&triggers
->array
);
599 int lttng_triggers_serialize(const struct lttng_triggers
*triggers
, struct lttng_payload
*payload
)
602 unsigned int i
, count
;
603 size_t size_before_payload
;
604 struct lttng_triggers_comm triggers_comm
= {};
605 struct lttng_triggers_comm
*header
;
606 enum lttng_trigger_status status
;
607 const size_t header_offset
= payload
->buffer
.size
;
609 status
= lttng_triggers_get_count(triggers
, &count
);
610 if (status
!= LTTNG_TRIGGER_STATUS_OK
) {
611 ret
= LTTNG_ERR_INVALID
;
615 triggers_comm
.count
= count
;
617 /* Placeholder header; updated at the end. */
618 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &triggers_comm
, sizeof(triggers_comm
));
623 size_before_payload
= payload
->buffer
.size
;
625 for (i
= 0; i
< count
; i
++) {
626 const struct lttng_trigger
*trigger
= lttng_triggers_get_at_index(triggers
, i
);
628 LTTNG_ASSERT(trigger
);
630 ret
= lttng_trigger_serialize(trigger
, payload
);
636 /* Update payload size. */
637 header
= (struct lttng_triggers_comm
*) ((char *) payload
->buffer
.data
+ header_offset
);
638 header
->length
= payload
->buffer
.size
- size_before_payload
;
643 ssize_t
lttng_triggers_create_from_payload(struct lttng_payload_view
*src_view
,
644 struct lttng_triggers
**triggers
)
646 ssize_t ret
, offset
= 0, triggers_size
= 0;
648 const struct lttng_triggers_comm
*triggers_comm
;
649 struct lttng_triggers
*local_triggers
= nullptr;
651 if (!src_view
|| !triggers
) {
656 /* lttng_trigger_comms header */
657 triggers_comm
= (const struct lttng_triggers_comm
*) src_view
->buffer
.data
;
658 offset
+= sizeof(*triggers_comm
);
660 local_triggers
= lttng_triggers_create();
661 if (!local_triggers
) {
666 for (i
= 0; i
< triggers_comm
->count
; i
++) {
667 struct lttng_trigger
*trigger
= nullptr;
668 struct lttng_payload_view trigger_view
=
669 lttng_payload_view_from_view(src_view
, offset
, -1);
670 ssize_t trigger_size
;
672 trigger_size
= lttng_trigger_create_from_payload(&trigger_view
, &trigger
);
673 if (trigger_size
< 0) {
678 /* Transfer ownership of the trigger to the collection. */
679 ret
= lttng_triggers_add(local_triggers
, trigger
);
680 lttng_trigger_put(trigger
);
686 offset
+= trigger_size
;
687 triggers_size
+= trigger_size
;
690 /* Unexpected size of inner-elements; the buffer is corrupted. */
691 if ((ssize_t
) triggers_comm
->length
!= triggers_size
) {
696 /* Pass ownership to caller. */
697 *triggers
= local_triggers
;
698 local_triggers
= nullptr;
703 lttng_triggers_destroy(local_triggers
);
707 const struct lttng_credentials
*lttng_trigger_get_credentials(const struct lttng_trigger
*trigger
)
709 return &trigger
->creds
;
712 void lttng_trigger_set_credentials(struct lttng_trigger
*trigger
,
713 const struct lttng_credentials
*creds
)
715 /* Triggers do not use the group id to authenticate the user. */
717 LTTNG_OPTIONAL_SET(&trigger
->creds
.uid
, LTTNG_OPTIONAL_GET(creds
->uid
));
718 LTTNG_OPTIONAL_UNSET(&trigger
->creds
.gid
);
721 enum lttng_trigger_status
lttng_trigger_set_owner_uid(struct lttng_trigger
*trigger
, uid_t uid
)
723 enum lttng_trigger_status ret
= LTTNG_TRIGGER_STATUS_OK
;
724 const uid_t euid
= geteuid();
725 const struct lttng_credentials creds
= {
726 .uid
= LTTNG_OPTIONAL_INIT_VALUE(uid
),
727 .gid
= LTTNG_OPTIONAL_INIT_UNSET
,
731 ret
= LTTNG_TRIGGER_STATUS_INVALID
;
735 /* Client-side validation only to report a clearer error. */
736 if (euid
!= 0 && euid
!= uid
) {
737 ret
= LTTNG_TRIGGER_STATUS_PERMISSION_DENIED
;
741 lttng_trigger_set_credentials(trigger
, &creds
);
747 enum lttng_trigger_status
lttng_trigger_get_owner_uid(const struct lttng_trigger
*trigger
,
750 enum lttng_trigger_status ret
= LTTNG_TRIGGER_STATUS_OK
;
751 const struct lttng_credentials
*creds
= nullptr;
753 if (!trigger
|| !uid
) {
754 ret
= LTTNG_TRIGGER_STATUS_INVALID
;
758 if (!trigger
->creds
.uid
.is_set
) {
759 ret
= LTTNG_TRIGGER_STATUS_UNSET
;
763 creds
= lttng_trigger_get_credentials(trigger
);
764 *uid
= lttng_credentials_get_uid(creds
);
770 enum lttng_domain_type
771 lttng_trigger_get_underlying_domain_type_restriction(const struct lttng_trigger
*trigger
)
773 enum lttng_domain_type type
= LTTNG_DOMAIN_NONE
;
774 const struct lttng_event_rule
*event_rule
;
775 enum lttng_condition_status c_status
;
776 enum lttng_condition_type c_type
;
778 LTTNG_ASSERT(trigger
);
779 LTTNG_ASSERT(trigger
->condition
);
781 c_type
= lttng_condition_get_type(trigger
->condition
);
782 assert(c_type
!= LTTNG_CONDITION_TYPE_UNKNOWN
);
785 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE
:
786 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
:
787 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
:
788 /* Apply to any domain. */
789 type
= LTTNG_DOMAIN_NONE
;
791 case LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES
:
792 /* Return the domain of the event rule. */
793 c_status
= lttng_condition_event_rule_matches_get_rule(trigger
->condition
,
795 LTTNG_ASSERT(c_status
== LTTNG_CONDITION_STATUS_OK
);
796 type
= lttng_event_rule_get_domain_type(event_rule
);
798 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
799 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
800 /* Return the domain of the channel being monitored. */
801 c_status
= lttng_condition_buffer_usage_get_domain_type(trigger
->condition
, &type
);
802 LTTNG_ASSERT(c_status
== LTTNG_CONDITION_STATUS_OK
);
812 * Generate bytecode related to the trigger.
813 * On success LTTNG_OK. On error, returns lttng_error code.
815 enum lttng_error_code
lttng_trigger_generate_bytecode(struct lttng_trigger
*trigger
,
816 const struct lttng_credentials
*creds
)
818 enum lttng_error_code ret
;
819 struct lttng_condition
*condition
= nullptr;
821 condition
= lttng_trigger_get_condition(trigger
);
823 ret
= LTTNG_ERR_INVALID_TRIGGER
;
827 switch (lttng_condition_get_type(condition
)) {
828 case LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES
:
830 struct lttng_event_rule
*event_rule
;
831 const enum lttng_condition_status condition_status
=
832 lttng_condition_event_rule_matches_borrow_rule_mutable(condition
,
835 LTTNG_ASSERT(condition_status
== LTTNG_CONDITION_STATUS_OK
);
837 /* Generate the filter bytecode. */
838 ret
= lttng_event_rule_generate_filter_bytecode(event_rule
, creds
);
839 if (ret
!= LTTNG_OK
) {
843 /* Generate the capture bytecode. */
844 ret
= lttng_condition_event_rule_matches_generate_capture_descriptor_bytecode(
846 if (ret
!= LTTNG_OK
) {
861 struct lttng_trigger
*lttng_trigger_copy(const struct lttng_trigger
*trigger
)
864 struct lttng_payload copy_buffer
;
865 struct lttng_condition
*condition_copy
= nullptr;
866 struct lttng_action
*action_copy
= nullptr;
867 struct lttng_trigger
*copy
= nullptr;
868 enum lttng_trigger_status trigger_status
;
869 const char *trigger_name
;
870 uid_t trigger_owner_uid
;
872 lttng_payload_init(©_buffer
);
874 ret
= lttng_condition_serialize(trigger
->condition
, ©_buffer
);
880 struct lttng_payload_view view
=
881 lttng_payload_view_from_payload(©_buffer
, 0, -1);
883 ret
= lttng_condition_create_from_payload(&view
, &condition_copy
);
889 lttng_payload_clear(©_buffer
);
891 ret
= lttng_action_serialize(trigger
->action
, ©_buffer
);
897 struct lttng_payload_view view
=
898 lttng_payload_view_from_payload(©_buffer
, 0, -1);
900 ret
= lttng_action_create_from_payload(&view
, &action_copy
);
906 copy
= lttng_trigger_create(condition_copy
, action_copy
);
908 ERR("Failed to allocate trigger during trigger copy");
912 trigger_status
= lttng_trigger_get_name(trigger
, &trigger_name
);
913 switch (trigger_status
) {
914 case LTTNG_TRIGGER_STATUS_OK
:
915 trigger_status
= lttng_trigger_set_name(copy
, trigger_name
);
916 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
917 ERR("Failed to set name of new trigger during copy");
918 goto error_cleanup_trigger
;
921 case LTTNG_TRIGGER_STATUS_UNSET
:
924 ERR("Failed to get name of original trigger during copy");
925 goto error_cleanup_trigger
;
928 trigger_status
= lttng_trigger_get_owner_uid(trigger
, &trigger_owner_uid
);
929 switch (trigger_status
) {
930 case LTTNG_TRIGGER_STATUS_OK
:
931 LTTNG_OPTIONAL_SET(©
->creds
.uid
, trigger_owner_uid
);
933 case LTTNG_TRIGGER_STATUS_UNSET
:
936 ERR("Failed to get owner uid of original trigger during copy");
937 goto error_cleanup_trigger
;
940 copy
->tracer_token
= trigger
->tracer_token
;
941 copy
->registered
= trigger
->registered
;
942 copy
->is_hidden
= trigger
->is_hidden
;
945 error_cleanup_trigger
:
946 lttng_trigger_destroy(copy
);
949 lttng_condition_put(condition_copy
);
950 lttng_action_put(action_copy
);
951 lttng_payload_reset(©_buffer
);
955 bool lttng_trigger_needs_tracer_notifier(const struct lttng_trigger
*trigger
)
957 bool needs_tracer_notifier
= false;
958 const struct lttng_condition
*condition
= lttng_trigger_get_const_condition(trigger
);
960 switch (lttng_condition_get_type(condition
)) {
961 case LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES
:
962 needs_tracer_notifier
= true;
964 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE
:
965 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
966 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
967 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
:
968 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
:
970 case LTTNG_CONDITION_TYPE_UNKNOWN
:
975 return needs_tracer_notifier
;
978 void lttng_trigger_set_as_registered(struct lttng_trigger
*trigger
)
980 pthread_mutex_lock(&trigger
->lock
);
981 trigger
->registered
= true;
982 pthread_mutex_unlock(&trigger
->lock
);
985 void lttng_trigger_set_as_unregistered(struct lttng_trigger
*trigger
)
987 pthread_mutex_lock(&trigger
->lock
);
988 trigger
->registered
= false;
989 pthread_mutex_unlock(&trigger
->lock
);
993 * The trigger must be locked before calling lttng_trigger_registered.
994 * The lock is necessary since a trigger can be unregistered at anytime.
995 * Manipulations requiring that the trigger be registered must always acquire
996 * the trigger lock for the duration of the manipulation using
997 * `lttng_trigger_lock` and `lttng_trigger_unlock`.
999 bool lttng_trigger_is_registered(struct lttng_trigger
*trigger
)
1001 ASSERT_LOCKED(trigger
->lock
);
1002 return trigger
->registered
;
1005 void lttng_trigger_lock(struct lttng_trigger
*trigger
)
1007 pthread_mutex_lock(&trigger
->lock
);
1010 void lttng_trigger_unlock(struct lttng_trigger
*trigger
)
1012 pthread_mutex_unlock(&trigger
->lock
);
1015 enum lttng_error_code
1016 lttng_trigger_mi_serialize(const struct lttng_trigger
*trigger
,
1017 struct mi_writer
*writer
,
1018 const struct mi_lttng_error_query_callbacks
*error_query_callbacks
)
1021 enum lttng_error_code ret_code
;
1022 enum lttng_trigger_status trigger_status
;
1023 const struct lttng_condition
*condition
= nullptr;
1024 const struct lttng_action
*action
= nullptr;
1025 struct lttng_dynamic_array action_path_indexes
;
1028 LTTNG_ASSERT(trigger
);
1029 LTTNG_ASSERT(writer
);
1031 lttng_dynamic_array_init(&action_path_indexes
, sizeof(uint64_t), nullptr);
1033 /* Open trigger element. */
1034 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_trigger
);
1039 trigger_status
= lttng_trigger_get_owner_uid(trigger
, &owner_uid
);
1040 LTTNG_ASSERT(trigger_status
== LTTNG_TRIGGER_STATUS_OK
);
1043 ret
= mi_lttng_writer_write_element_string(writer
, config_element_name
, trigger
->name
);
1049 ret
= mi_lttng_writer_write_element_signed_int(
1050 writer
, mi_lttng_element_trigger_owner_uid
, (int64_t) owner_uid
);
1056 condition
= lttng_trigger_get_const_condition(trigger
);
1057 LTTNG_ASSERT(condition
);
1058 ret_code
= lttng_condition_mi_serialize(trigger
, condition
, writer
, error_query_callbacks
);
1059 if (ret_code
!= LTTNG_OK
) {
1064 action
= lttng_trigger_get_const_action(trigger
);
1065 LTTNG_ASSERT(action
);
1066 ret_code
= lttng_action_mi_serialize(
1067 trigger
, action
, writer
, error_query_callbacks
, &action_path_indexes
);
1068 if (ret_code
!= LTTNG_OK
) {
1072 if (error_query_callbacks
&& error_query_callbacks
->trigger_cb
) {
1073 struct lttng_error_query_results
*results
= nullptr;
1075 ret_code
= error_query_callbacks
->trigger_cb(trigger
, &results
);
1076 if (ret_code
!= LTTNG_OK
) {
1080 ret_code
= lttng_error_query_results_mi_serialize(results
, writer
);
1081 lttng_error_query_results_destroy(results
);
1082 if (ret_code
!= LTTNG_OK
) {
1087 /* Close trigger element. */
1088 ret
= mi_lttng_writer_close_element(writer
);
1093 ret_code
= LTTNG_OK
;
1097 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
1099 lttng_dynamic_array_reset(&action_path_indexes
);
1103 /* Used by qsort, which expects the semantics of strcmp(). */
1104 static int compare_triggers_by_name(const void *a
, const void *b
)
1106 const struct lttng_trigger
*trigger_a
= *((const struct lttng_trigger
**) a
);
1107 const struct lttng_trigger
*trigger_b
= *((const struct lttng_trigger
**) b
);
1108 const char *name_a
, *name_b
;
1109 enum lttng_trigger_status trigger_status
;
1111 /* Anonymous triggers are not reachable here. */
1112 trigger_status
= lttng_trigger_get_name(trigger_a
, &name_a
);
1113 LTTNG_ASSERT(trigger_status
== LTTNG_TRIGGER_STATUS_OK
);
1115 trigger_status
= lttng_trigger_get_name(trigger_b
, &name_b
);
1116 LTTNG_ASSERT(trigger_status
== LTTNG_TRIGGER_STATUS_OK
);
1118 return strcmp(name_a
, name_b
);
1121 enum lttng_error_code
1122 lttng_triggers_mi_serialize(const struct lttng_triggers
*triggers
,
1123 struct mi_writer
*writer
,
1124 const struct mi_lttng_error_query_callbacks
*error_query_callbacks
)
1127 enum lttng_error_code ret_code
;
1128 enum lttng_trigger_status status
;
1129 unsigned int count
, i
;
1130 struct lttng_dynamic_pointer_array sorted_triggers
;
1132 LTTNG_ASSERT(triggers
);
1133 LTTNG_ASSERT(writer
);
1136 * Sort trigger by name to ensure an order at the MI level and ignore
1137 * any anonymous trigger present.
1139 lttng_dynamic_pointer_array_init(&sorted_triggers
, nullptr);
1141 status
= lttng_triggers_get_count(triggers
, &count
);
1142 LTTNG_ASSERT(status
== LTTNG_TRIGGER_STATUS_OK
);
1144 for (i
= 0; i
< count
; i
++) {
1146 const char *unused_name
;
1147 const struct lttng_trigger
*trigger
= lttng_triggers_get_at_index(triggers
, i
);
1149 status
= lttng_trigger_get_name(trigger
, &unused_name
);
1151 case LTTNG_TRIGGER_STATUS_OK
:
1153 case LTTNG_TRIGGER_STATUS_UNSET
:
1154 /* Don't list anonymous triggers. */
1161 lttng_dynamic_pointer_array_add_pointer(&sorted_triggers
, (void *) trigger
);
1164 ERR("Failed to lttng_trigger to sorting array.");
1165 ret_code
= LTTNG_ERR_NOMEM
;
1170 qsort(sorted_triggers
.array
.buffer
.data
,
1172 sizeof(struct lttng_trigger
*),
1173 compare_triggers_by_name
);
1175 /* Open triggers element. */
1176 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_triggers
);
1178 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
1182 for (i
= 0; i
< lttng_dynamic_pointer_array_get_count(&sorted_triggers
); i
++) {
1183 const struct lttng_trigger
*trigger
=
1184 (const struct lttng_trigger
*) lttng_dynamic_pointer_array_get_pointer(
1185 &sorted_triggers
, i
);
1187 lttng_trigger_mi_serialize(trigger
, writer
, error_query_callbacks
);
1190 /* Close triggers element. */
1191 ret
= mi_lttng_writer_close_element(writer
);
1193 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
1197 ret_code
= LTTNG_OK
;
1200 lttng_dynamic_pointer_array_reset(&sorted_triggers
);