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