SoW-2019-0007-2: Dynamic Snapshot: Triggers send partial event payload with notifications
[lttng-tools.git] / src / common / trigger.c
CommitLineData
a58c490f 1/*
ab5be9fa 2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
a58c490f 3 *
ab5be9fa 4 * SPDX-License-Identifier: LGPL-2.1-only
a58c490f 5 *
a58c490f
JG
6 */
7
8#include <lttng/trigger/trigger-internal.h>
9#include <lttng/condition/condition-internal.h>
5024c2ac
JR
10#include <lttng/condition/event-rule-internal.h>
11#include <lttng/condition/event-rule.h>
12#include <lttng/condition/buffer-usage.h>
13#include <lttng/event-rule/event-rule-internal.h>
14#include <lttng/event-expr-internal.h>
a58c490f 15#include <lttng/action/action-internal.h>
5024c2ac 16#include <lttng/domain.h>
a58c490f 17#include <common/error.h>
5024c2ac 18#include <common/dynamic-array.h>
a58c490f 19#include <assert.h>
5024c2ac
JR
20#include <inttypes.h>
21
22static void lttng_trigger_set_internal_object_ownership(
23 struct lttng_trigger *trigger)
24{
25 /*
26 * This is necessary to faciliate the object destroy phase. A trigger
27 * created by a client does not OWN the internal objects (condition and
28 * action) but when a trigger object is created on the sessiond side or
29 * for listing triggers (mostly via create_from_buffer) the object is
30 * the owner of the internal objects. Hence, we set the ownership bool
31 * to true, in such case, to facilitate object lifetime management and
32 * internal ownership.
33 *
34 * TODO: I'm open to any other solution
35 */
36 assert(trigger);
37 trigger->owns_internal_objects = true;
38}
39
40static void destroy_lttng_condition_event_rule_capture_bytecode_element(void *ptr)
41{
42 struct lttng_condition_event_rule_capture_bytecode_element *element =
43 ptr;
44 lttng_event_expr_destroy(element->expression);
45 free(element->bytecode);
46 free(element);
47}
a58c490f
JG
48
49LTTNG_HIDDEN
5024c2ac 50bool lttng_trigger_validate(const struct lttng_trigger *trigger)
a58c490f
JG
51{
52 bool valid;
53
54 if (!trigger) {
55 valid = false;
56 goto end;
57 }
58
59 valid = lttng_condition_validate(trigger->condition) &&
60 lttng_action_validate(trigger->action);
61end:
62 return valid;
63}
64
65struct lttng_trigger *lttng_trigger_create(
66 struct lttng_condition *condition,
67 struct lttng_action *action)
68{
69 struct lttng_trigger *trigger = NULL;
70
71 if (!condition || !action) {
72 goto end;
73 }
74
75 trigger = zmalloc(sizeof(struct lttng_trigger));
76 if (!trigger) {
77 goto end;
78 }
79
5024c2ac
JR
80 urcu_ref_init(&trigger->ref);
81 trigger->owns_internal_objects = false;
82 trigger->firing_policy.type = LTTNG_TRIGGER_FIRE_EVERY_N;
83 trigger->firing_policy.threshold = 1;
a58c490f
JG
84 trigger->condition = condition;
85 trigger->action = action;
5024c2ac
JR
86
87 trigger->creds.set = false;
88
89 lttng_dynamic_pointer_array_init(&trigger->capture_bytecode_set,
90 destroy_lttng_condition_event_rule_capture_bytecode_element);
91
a58c490f
JG
92end:
93 return trigger;
94}
95
96struct lttng_condition *lttng_trigger_get_condition(
97 struct lttng_trigger *trigger)
98{
99 return trigger ? trigger->condition : NULL;
100}
101
9b63a4aa
JG
102const struct lttng_condition *lttng_trigger_get_const_condition(
103 const struct lttng_trigger *trigger)
104{
5024c2ac 105 return trigger ? trigger->condition : NULL;
9b63a4aa
JG
106}
107
e2ba1c78 108struct lttng_action *lttng_trigger_get_action(
a58c490f
JG
109 struct lttng_trigger *trigger)
110{
111 return trigger ? trigger->action : NULL;
112}
113
9b63a4aa
JG
114const struct lttng_action *lttng_trigger_get_const_action(
115 const struct lttng_trigger *trigger)
116{
5024c2ac 117 return trigger ? trigger->action : NULL;
9b63a4aa
JG
118}
119
5024c2ac 120static void trigger_destroy_ref(struct urcu_ref *ref)
a58c490f 121{
5024c2ac
JR
122 struct lttng_trigger *trigger =
123 container_of(ref, struct lttng_trigger, ref);
124
125 lttng_dynamic_pointer_array_reset(&trigger->capture_bytecode_set);
126
127 if (trigger->owns_internal_objects) {
128 struct lttng_action *action = lttng_trigger_get_action(trigger);
129 struct lttng_condition *condition =
130 lttng_trigger_get_condition(trigger);
131
132 assert(action);
133 assert(condition);
134 lttng_action_destroy(action);
135 lttng_condition_destroy(condition);
a58c490f
JG
136 }
137
5024c2ac 138 free(trigger->name);
a58c490f
JG
139 free(trigger);
140}
141
5024c2ac
JR
142void lttng_trigger_destroy(struct lttng_trigger *trigger)
143{
144 lttng_trigger_put(trigger);
145}
146
a58c490f
JG
147LTTNG_HIDDEN
148ssize_t lttng_trigger_create_from_buffer(
149 const struct lttng_buffer_view *src_view,
150 struct lttng_trigger **trigger)
151{
5024c2ac
JR
152 ssize_t ret, offset = 0, condition_size, action_size, name_size = 0;
153 enum lttng_trigger_status status;
a58c490f
JG
154 struct lttng_condition *condition = NULL;
155 struct lttng_action *action = NULL;
156 const struct lttng_trigger_comm *trigger_comm;
157 struct lttng_buffer_view condition_view;
158 struct lttng_buffer_view action_view;
5024c2ac
JR
159 struct lttng_buffer_view name_view;
160 const char *name = NULL;
161 unsigned long long firing_threshold;
162 enum lttng_trigger_firing_policy_type firing_policy;
a58c490f
JG
163
164 if (!src_view || !trigger) {
165 ret = -1;
166 goto end;
167 }
168
169 /* lttng_trigger_comm header */
170 trigger_comm = (const struct lttng_trigger_comm *) src_view->data;
171 offset += sizeof(*trigger_comm);
172
5024c2ac
JR
173 firing_policy = trigger_comm->policy_type;
174 firing_threshold = trigger_comm->policy_threshold;
175 if (trigger_comm->name_length != 0) {
176 name_view = lttng_buffer_view_from_view(
177 src_view, offset, trigger_comm->name_length);
178 name = name_view.data;
179 if (trigger_comm->name_length == 1 ||
180 name[trigger_comm->name_length - 1] != '\0' ||
181 strlen(name) != trigger_comm->name_length - 1) {
182 ret = -1;
183 goto end;
184 }
185 offset += trigger_comm->name_length;
186 name_size = trigger_comm->name_length;
187 }
188
a58c490f
JG
189 condition_view = lttng_buffer_view_from_view(src_view, offset, -1);
190
191 /* struct lttng_condition */
192 condition_size = lttng_condition_create_from_buffer(&condition_view,
193 &condition);
194 if (condition_size < 0) {
195 ret = condition_size;
196 goto end;
197 }
198 offset += condition_size;
199
200 /* struct lttng_action */
201 action_view = lttng_buffer_view_from_view(src_view, offset, -1);
202 action_size = lttng_action_create_from_buffer(&action_view, &action);
203 if (action_size < 0) {
204 ret = action_size;
205 goto end;
206 }
207 offset += action_size;
208
209 /* Unexpected size of inner-elements; the buffer is corrupted. */
5024c2ac 210 if ((ssize_t) trigger_comm->length != condition_size + action_size + name_size) {
a58c490f
JG
211 ret = -1;
212 goto error;
213 }
214
215 *trigger = lttng_trigger_create(condition, action);
216 if (!*trigger) {
217 ret = -1;
218 goto error;
219 }
5024c2ac
JR
220
221 /* Take ownership of the internal object from there */
222 lttng_trigger_set_internal_object_ownership(*trigger);
223 condition = NULL;
224 action = NULL;
225
226 if (name) {
227 status = lttng_trigger_set_name(*trigger, name);
228 if (status != LTTNG_TRIGGER_STATUS_OK) {
229 ret = -1;
230 goto end;
231 }
232 }
233
234 status = lttng_trigger_set_firing_policy(*trigger, firing_policy, firing_threshold);
235 if (status != LTTNG_TRIGGER_STATUS_OK) {
236 ret = -1;
237 goto end;
238 }
239
a58c490f
JG
240 ret = offset;
241end:
242 return ret;
243error:
244 lttng_condition_destroy(condition);
245 lttng_action_destroy(action);
246 return ret;
247}
248
249/*
a58c490f
JG
250 * Both elements are stored contiguously, see their "*_comm" structure
251 * for the detailed format.
252 */
253LTTNG_HIDDEN
5024c2ac
JR
254int lttng_trigger_serialize(const struct lttng_trigger *trigger,
255 struct lttng_dynamic_buffer *buf,
256 int *fd_to_send)
a58c490f 257{
3647288f 258 int ret;
5024c2ac 259 size_t header_offset, size_before_payload, size_name;
1065191b 260 struct lttng_trigger_comm trigger_comm = { 0 };
3647288f 261 struct lttng_trigger_comm *header;
a58c490f 262
3647288f 263 header_offset = buf->size;
5024c2ac
JR
264
265 if (trigger->name != NULL) {
266 size_name = strlen(trigger->name) + 1;
267 } else {
268 size_name = 0;
269 }
270
271 trigger_comm.name_length = size_name;
272 trigger_comm.policy_type = (uint8_t) trigger->firing_policy.type;
273 trigger_comm.policy_threshold = (uint64_t) trigger->firing_policy.threshold;
274
3647288f
JG
275 ret = lttng_dynamic_buffer_append(buf, &trigger_comm,
276 sizeof(trigger_comm));
277 if (ret) {
a58c490f
JG
278 goto end;
279 }
280
3647288f 281 size_before_payload = buf->size;
5024c2ac
JR
282
283 /* Trigger name */
284 ret = lttng_dynamic_buffer_append(buf, trigger->name, size_name);
285 if (ret) {
286 goto end;
287 }
288
289 ret = lttng_condition_serialize(trigger->condition, buf, fd_to_send);
3647288f 290 if (ret) {
a58c490f
JG
291 goto end;
292 }
a58c490f 293
3647288f
JG
294 ret = lttng_action_serialize(trigger->action, buf);
295 if (ret) {
a58c490f
JG
296 goto end;
297 }
a58c490f 298
3647288f
JG
299 /* Update payload size. */
300 header = (struct lttng_trigger_comm *) ((char *) buf->data + header_offset);
301 header->length = buf->size - size_before_payload;
a58c490f
JG
302end:
303 return ret;
304}
5024c2ac
JR
305
306enum lttng_trigger_status lttng_trigger_set_name(struct lttng_trigger *trigger, const char* name)
307{
308 char *name_copy = NULL;
309 enum lttng_trigger_status status = LTTNG_TRIGGER_STATUS_OK;
310
311 if (!trigger || !name ||
312 strlen(name) == 0) {
313 status = LTTNG_TRIGGER_STATUS_INVALID;
314 goto end;
315 }
316
317 name_copy = strdup(name);
318 if (!name_copy) {
319 status = LTTNG_TRIGGER_STATUS_ERROR;
320 goto end;
321 }
322
323 if (trigger->name) {
324 free(trigger->name);
325 }
326
327 trigger->name = name_copy;
328 name_copy = NULL;
329end:
330 return status;
331}
332
333enum lttng_trigger_status lttng_trigger_get_name(const struct lttng_trigger *trigger, const char **name)
334{
335 enum lttng_trigger_status status = LTTNG_TRIGGER_STATUS_OK;
336
337 if (!trigger || !name) {
338 status = LTTNG_TRIGGER_STATUS_INVALID;
339 goto end;
340 }
341
342 if (!trigger->name) {
343 status = LTTNG_TRIGGER_STATUS_UNSET;
344 }
345
346 *name = trigger->name;
347end:
348 return status;
349}
350
351LTTNG_HIDDEN
352int lttng_trigger_assign(struct lttng_trigger *dst,
353 const struct lttng_trigger *src)
354{
355 int ret = 0;
356 enum lttng_trigger_status status;
357 /* todo some validation */
358
359 status = lttng_trigger_set_name(dst, src->name);
360 if (status != LTTNG_TRIGGER_STATUS_OK) {
361 ret = -1;
362 ERR("Failed to set name for trigger");
363 goto end;
364 }
365end:
366 return ret;
367}
368
369LTTNG_HIDDEN
370void lttng_trigger_set_key(struct lttng_trigger *trigger, uint64_t key)
371{
372 assert(trigger);
373 trigger->key.value = key;
374 trigger->key.set = true;
375}
376
377LTTNG_HIDDEN
378uint64_t lttng_trigger_get_key(const struct lttng_trigger *trigger)
379{
380 assert(trigger);
381
382 assert(trigger->key.set == true);
383 return trigger->key.value;
384}
385
386LTTNG_HIDDEN
387int lttng_trigger_generate_name(struct lttng_trigger *trigger, uint64_t offset)
388{
389 int ret = 0;
390 char *generated_name = NULL;
391 assert(trigger->key.set);
392
393 ret = asprintf(&generated_name, "T%" PRIu64 "", trigger->key.value + offset);
394 if (ret < 0) {
395 ERR("Failed to generate trigger name");
396 ret = -1;
397 goto end;
398 }
399
400 if (trigger->name) {
401 free(trigger->name);
402 }
403 trigger->name = generated_name;
404end:
405 return ret;
406}
407
408LTTNG_HIDDEN
409void lttng_trigger_get(struct lttng_trigger *trigger)
410{
411 urcu_ref_get(&trigger->ref);
412}
413
414LTTNG_HIDDEN
415void lttng_trigger_put(struct lttng_trigger *trigger)
416{
417 if (!trigger) {
418 return;
419 }
420
421 urcu_ref_put(&trigger->ref , trigger_destroy_ref);
422}
423
424static void delete_trigger_array_element(void *ptr)
425{
426 struct lttng_trigger *trigger = ptr;
427 lttng_trigger_destroy(trigger);
428}
429
430LTTNG_HIDDEN
431bool lttng_trigger_is_equal(
432 const struct lttng_trigger *a, const struct lttng_trigger *b)
433{
434 /* TODO: Optimization: for now a trigger with a firing policy that is
435 * not the same even if the conditions and actions is the same is
436 * treated as a "completely" different trigger. In a perfect world we
437 * would simply add a supplemental counter internally (sessiond side) to
438 * remove overhead on the tracer side.
439 */
440 if (a->firing_policy.type != b->firing_policy.type) {
441 return false;
442 }
443
444 if (a->firing_policy.threshold != b->firing_policy.threshold) {
445 return false;
446 }
447
448 /*
449 * Name is not taken into account since it is cosmetic only
450 */
451 if (!lttng_condition_is_equal(a->condition, b->condition)) {
452 return false;
453 }
454 if (!lttng_action_is_equal(a->action, b->action)) {
455 return false;
456 }
457
458 return true;
459}
460
461LTTNG_HIDDEN
462struct lttng_triggers *lttng_triggers_create(void)
463{
464 struct lttng_triggers *triggers = NULL;
465
466 triggers = zmalloc(sizeof(*triggers));
467 if (!triggers) {
468 goto error;
469 }
470
471 lttng_dynamic_pointer_array_init(&triggers->array, delete_trigger_array_element);
472
473 return triggers;
474error:
475 free(triggers);
476 return NULL;
477}
478
479LTTNG_HIDDEN
480struct lttng_trigger *lttng_triggers_get_pointer_of_index(
481 const struct lttng_triggers *triggers, unsigned int index)
482{
483 assert(triggers);
484 if (index >= lttng_dynamic_pointer_array_get_count(&triggers->array)) {
485 return NULL;
486 }
487 return lttng_dynamic_pointer_array_get_pointer(&triggers->array, index);
488}
489
490LTTNG_HIDDEN
491int lttng_triggers_add(
492 struct lttng_triggers *triggers, struct lttng_trigger *trigger)
493{
494 assert(triggers);
495 assert(trigger);
496
497 return lttng_dynamic_pointer_array_add_pointer(&triggers->array, trigger);
498}
499
500const struct lttng_trigger *lttng_triggers_get_at_index(
501 const struct lttng_triggers *triggers, unsigned int index)
502{
503 assert(triggers);
504 return lttng_triggers_get_pointer_of_index(triggers, index);
505}
506
507enum lttng_trigger_status lttng_triggers_get_count(const struct lttng_triggers *triggers, unsigned int *count)
508{
509 enum lttng_trigger_status status = LTTNG_TRIGGER_STATUS_OK;
510
511 if (!triggers || !count) {
512 status = LTTNG_TRIGGER_STATUS_INVALID;
513 goto end;
514 }
515
516 *count = lttng_dynamic_pointer_array_get_count(&triggers->array);
517end:
518 return status;
519}
520
521void lttng_triggers_destroy(struct lttng_triggers *triggers)
522{
523 if (!triggers) {
524 return;
525 }
526
527 lttng_dynamic_pointer_array_reset(&triggers->array);
528 free(triggers);
529}
530
531int lttng_triggers_serialize(const struct lttng_triggers *triggers,
532 struct lttng_dynamic_buffer *buffer)
533{
534 int ret;
535 unsigned int count;
536 size_t header_offset, size_before_payload;
537 struct lttng_triggers_comm triggers_comm = { 0 };
538 struct lttng_triggers_comm *header;
539 struct lttng_trigger *trigger;
540 enum lttng_trigger_status status;
541
542 header_offset = buffer->size;
543
544 status = lttng_triggers_get_count(triggers, &count);
545 if (status != LTTNG_TRIGGER_STATUS_OK) {
546 ret = LTTNG_ERR_INVALID;
547 goto end;
548 }
549
550 triggers_comm.count = count;
551
552 ret = lttng_dynamic_buffer_append(buffer, &triggers_comm,
553 sizeof(triggers_comm));
554 if (ret) {
555 goto end;
556 }
557
558 size_before_payload = buffer->size;
559
560 for (int i = 0; i < count; i++) {
561 trigger = lttng_triggers_get_pointer_of_index(triggers, i);
562 if (!trigger) {
563 assert(0);
564 }
565
566 ret = lttng_trigger_serialize(trigger, buffer, NULL);
567 if (ret) {
568 goto end;
569 }
570 }
571
572 /* Update payload size. */
573 header = (struct lttng_triggers_comm *) ((char *) buffer->data + header_offset);
574 header->length = buffer->size - size_before_payload;
575end:
576 return ret;
577}
578
579LTTNG_HIDDEN
580ssize_t lttng_triggers_create_from_buffer(
581 const struct lttng_buffer_view *src_view,
582 struct lttng_triggers **triggers)
583{
584 ssize_t ret, offset = 0, trigger_size, triggers_size = 0;
585 const struct lttng_triggers_comm *triggers_comm;
586 struct lttng_buffer_view trigger_view;
587 struct lttng_triggers *local_triggers = NULL;
588
589 if (!src_view || !triggers) {
590 ret = -1;
591 goto error;
592 }
593
594 /* lttng_trigger_comms header */
595 triggers_comm = (const struct lttng_triggers_comm *) src_view->data;
596 offset += sizeof(*triggers_comm);
597
598 local_triggers = lttng_triggers_create();
599 if (!local_triggers) {
600 ret = -1;
601 goto error;
602 }
603
604 for (int i = 0; i < triggers_comm->count; i++) {
605 struct lttng_trigger *trigger = NULL;
606 trigger_view = lttng_buffer_view_from_view(src_view, offset, -1);
607 trigger_size = lttng_trigger_create_from_buffer(&trigger_view,
608 &trigger);
609 if (trigger_size < 0) {
610 ret = trigger_size;
611 goto error;
612 }
613
614 /* Pass ownership of the trigger to the collection */
615 ret = lttng_triggers_add(local_triggers, trigger);
616 if (ret < 0) {
617 assert(0);
618 }
619 trigger = NULL;
620
621 offset += trigger_size;
622 triggers_size += trigger_size;
623 }
624
625 /* Unexpected size of inner-elements; the buffer is corrupted. */
626 if ((ssize_t) triggers_comm->length != triggers_size) {
627 ret = -1;
628 goto error;
629 }
630
631 /* Pass ownership to caller */
632 *triggers = local_triggers;
633 local_triggers = NULL;
634
635 ret = offset;
636error:
637
638 lttng_triggers_destroy(local_triggers);
639 return ret;
640}
641
642LTTNG_HIDDEN
643const struct lttng_credentials *lttng_trigger_get_credentials(
644 const struct lttng_trigger *trigger)
645{
646 assert(trigger->creds.set);
647 return &(trigger->creds.credentials);
648}
649
650LTTNG_HIDDEN
651void lttng_trigger_set_credentials(
652 struct lttng_trigger *trigger, uid_t uid, gid_t gid)
653{
654 trigger->creds.credentials.uid = uid;
655 trigger->creds.credentials.gid = gid;
656 trigger->creds.set = true;
657}
658
659enum lttng_trigger_status lttng_trigger_set_firing_policy(
660 struct lttng_trigger *trigger,
661 enum lttng_trigger_firing_policy_type policy_type,
662 unsigned long long threshold)
663{
664 enum lttng_trigger_status ret = LTTNG_TRIGGER_STATUS_OK;
665 assert(trigger);
666
667 if (threshold < 1) {
668 ret = LTTNG_TRIGGER_STATUS_INVALID;
669 goto end;
670 }
671
672 trigger->firing_policy.type = policy_type;
673 trigger->firing_policy.threshold = threshold;
674
675end:
676 return ret;
677}
678
679enum lttng_trigger_status lttng_trigger_get_firing_policy(
680 const struct lttng_trigger *trigger,
681 enum lttng_trigger_firing_policy_type *policy_type,
682 unsigned long long *threshold)
683{
684 enum lttng_trigger_status status = LTTNG_TRIGGER_STATUS_OK;
685
686 if (!trigger || !policy_type || !threshold) {
687 status = LTTNG_TRIGGER_STATUS_INVALID;
688 goto end;
689 }
690
691 *policy_type = trigger->firing_policy.type;
692 *threshold = trigger->firing_policy.threshold;
693
694end:
695 return status;
696}
697
698LTTNG_HIDDEN
699bool lttng_trigger_is_ready_to_fire(struct lttng_trigger *trigger)
700{
701 assert(trigger);
702 bool ready_to_fire = false;
703
704 trigger->firing_policy.current_count++;
705
706 switch (trigger->firing_policy.type) {
707 case LTTNG_TRIGGER_FIRE_EVERY_N:
708 if (trigger->firing_policy.current_count == trigger->firing_policy.threshold) {
709 trigger->firing_policy.current_count = 0;
710 ready_to_fire = true;
711 }
712 break;
713 case LTTNG_TRIGGER_FIRE_ONCE_AFTER_N:
714 if (trigger->firing_policy.current_count == trigger->firing_policy.threshold) {
715 /* TODO: remove the trigger of at least deactivate it on
716 * the tracers side to remove any work overhead on the
717 * traced application or kernel since the trigger will
718 * never fire again.
719 * Still this branch should be left here since event
720 * could still be in the pipe. These will be discarded.
721 */
722 ready_to_fire = true;
723 }
724 break;
725 default:
726 assert(0);
727 };
728
729 return ready_to_fire;
730}
731
732LTTNG_HIDDEN
733enum lttng_domain_type lttng_trigger_get_underlying_domain_type_restriction(
734 const struct lttng_trigger *trigger)
735{
736 enum lttng_domain_type type = LTTNG_DOMAIN_NONE;
737 const struct lttng_event_rule *event_rule;
738 enum lttng_condition_status c_status;
739 enum lttng_condition_type c_type;
740
741 assert(trigger);
742 assert(trigger->condition);
743 c_type = lttng_condition_get_type(trigger->condition);
744 if (c_type == LTTNG_CONDITION_TYPE_UNKNOWN) {
745 assert(0);
746 }
747
748 switch (c_type) {
749 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
750 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
751 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
752 type = LTTNG_DOMAIN_NONE;
753 break;
754 case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT:
755 c_status = lttng_condition_event_rule_get_rule(
756 trigger->condition, &event_rule);
757 if (c_status != LTTNG_CONDITION_STATUS_OK) {
758 /* The condition object is invalid */
759 assert(0);
760 }
761
762 type = lttng_event_rule_get_domain_type(event_rule);
763 break;
764 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
765 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
766 c_status = lttng_condition_buffer_usage_get_domain_type(
767 trigger->condition, &type);
768 if (c_status != LTTNG_CONDITION_STATUS_OK) {
769 /* The condition object is invalid */
770 assert(0);
771 }
772 break;
773 default:
774 type = LTTNG_DOMAIN_NONE;
775 break;
776 }
777
778 return type;
779}
780
781LTTNG_HIDDEN
782unsigned int lttng_trigger_get_capture_bytecode_count(
783 const struct lttng_trigger *trigger)
784{
785 unsigned int count = 0;
786 if (!trigger) {
787 goto end;
788 }
789
790 count = lttng_dynamic_pointer_array_get_count(
791 &trigger->capture_bytecode_set);
792
793end:
794 return count;
795}
796
797LTTNG_HIDDEN
798const struct lttng_bytecode *
799lttng_trigger_get_capture_bytecode_at_index(
800 const struct lttng_trigger *trigger, unsigned int index)
801{
802 struct lttng_condition_event_rule_capture_bytecode_element *element = NULL;
803 struct lttng_bytecode *bytecode = NULL;
804
805 element = lttng_dynamic_pointer_array_get_pointer(
806 &trigger->capture_bytecode_set, index);
807
808 if (element == NULL) {
809 goto end;
810 }
811 bytecode = element->bytecode;
812end:
813 return bytecode;
814}
This page took 0.073429 seconds and 5 git commands to generate.