lttng-ctl: add capture descriptor feature to event rule condition API
[lttng-tools.git] / src / common / conditions / event-rule.c
1 /*
2 * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <assert.h>
9 #include <common/error.h>
10 #include <common/macros.h>
11 #include <inttypes.h>
12 #include <lttng/condition/condition-internal.h>
13 #include <lttng/condition/event-rule-internal.h>
14 #include <lttng/condition/event-rule.h>
15 #include <lttng/event-expr-internal.h>
16 #include <lttng/event-expr.h>
17 #include <lttng/event-rule/event-rule-internal.h>
18 #include <stdbool.h>
19 #include <stdint.h>
20
21 #define IS_EVENT_RULE_CONDITION(condition) \
22 (lttng_condition_get_type(condition) == \
23 LTTNG_CONDITION_TYPE_EVENT_RULE_HIT)
24
25 static bool is_event_rule_evaluation(const struct lttng_evaluation *evaluation)
26 {
27 enum lttng_condition_type type = lttng_evaluation_get_type(evaluation);
28
29 return type == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT;
30 }
31
32 static bool lttng_condition_event_rule_validate(
33 const struct lttng_condition *condition);
34 static int lttng_condition_event_rule_serialize(
35 const struct lttng_condition *condition,
36 struct lttng_payload *payload);
37 static bool lttng_condition_event_rule_is_equal(
38 const struct lttng_condition *_a,
39 const struct lttng_condition *_b);
40 static void lttng_condition_event_rule_destroy(
41 struct lttng_condition *condition);
42
43 static bool lttng_condition_event_rule_validate(
44 const struct lttng_condition *condition)
45 {
46 bool valid = false;
47 struct lttng_condition_event_rule *event_rule;
48
49 if (!condition) {
50 goto end;
51 }
52
53 event_rule = container_of(
54 condition, struct lttng_condition_event_rule, parent);
55 if (!event_rule->rule) {
56 ERR("Invalid event rule condition: a rule must be set.");
57 goto end;
58 }
59
60 valid = lttng_event_rule_validate(event_rule->rule);
61 end:
62 return valid;
63 }
64
65 /*
66 * Serializes the C string `str` into `buf`.
67 *
68 * Encoding is the length of `str` plus one (for the null character),
69 * and then the string, including its null terminator.
70 */
71 static
72 int serialize_cstr(const char *str, struct lttng_dynamic_buffer *buf)
73 {
74 int ret;
75 const uint32_t len = strlen(str) + 1;
76
77 /* Serialize the length, including the null terminator. */
78 DBG("Serializing C string's length (including null terminator): "
79 "%" PRIu32, len);
80 ret = lttng_dynamic_buffer_append(buf, &len, sizeof(len));
81 if (ret) {
82 goto end;
83 }
84
85 /* Serialize the string. */
86 DBG("Serializing C string: '%s'", str);
87 ret = lttng_dynamic_buffer_append(buf, str, len);
88 if (ret) {
89 goto end;
90 }
91
92 end:
93 return ret;
94 }
95
96 /*
97 * Serializes the event expression `expr` into `buf`.
98 */
99 static
100 int serialize_event_expr(const struct lttng_event_expr *expr,
101 struct lttng_payload *payload)
102 {
103 const uint8_t type = expr->type;
104 int ret;
105
106 /* Serialize the expression's type. */
107 DBG("Serializing event expression's type: %d", expr->type);
108 ret = lttng_dynamic_buffer_append(&payload->buffer, &type, sizeof(type));
109 if (ret) {
110 goto end;
111 }
112
113 /* Serialize the expression */
114 switch (expr->type) {
115 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
116 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
117 {
118 const struct lttng_event_expr_field *field_expr =
119 container_of(expr,
120 const struct lttng_event_expr_field,
121 parent);
122
123 /* Serialize the field name. */
124 DBG("Serializing field event expression's field name: '%s'",
125 field_expr->name);
126 ret = serialize_cstr(field_expr->name, &payload->buffer);
127 if (ret) {
128 goto end;
129 }
130
131 break;
132 }
133 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
134 {
135 const struct lttng_event_expr_app_specific_context_field *field_expr =
136 container_of(expr,
137 const struct lttng_event_expr_app_specific_context_field,
138 parent);
139
140 /* Serialize the provider name. */
141 DBG("Serializing app-specific context field event expression's "
142 "provider name: '%s'",
143 field_expr->provider_name);
144 ret = serialize_cstr(field_expr->provider_name, &payload->buffer);
145 if (ret) {
146 goto end;
147 }
148
149 /* Serialize the type name. */
150 DBG("Serializing app-specific context field event expression's "
151 "type name: '%s'",
152 field_expr->provider_name);
153 ret = serialize_cstr(field_expr->type_name, &payload->buffer);
154 if (ret) {
155 goto end;
156 }
157
158 break;
159 }
160 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
161 {
162 const struct lttng_event_expr_array_field_element *elem_expr =
163 container_of(expr,
164 const struct lttng_event_expr_array_field_element,
165 parent);
166 const uint32_t index = elem_expr->index;
167
168 /* Serialize the index. */
169 DBG("Serializing array field element event expression's "
170 "index: %u", elem_expr->index);
171 ret = lttng_dynamic_buffer_append(&payload->buffer, &index, sizeof(index));
172 if (ret) {
173 goto end;
174 }
175
176 /* Serialize the parent array field expression. */
177 DBG("Serializing array field element event expression's "
178 "parent array field event expression.");
179 ret = serialize_event_expr(elem_expr->array_field_expr, payload);
180 if (ret) {
181 goto end;
182 }
183
184 break;
185 }
186 default:
187 break;
188 }
189
190 end:
191 return ret;
192 }
193
194 static int lttng_condition_event_rule_serialize(
195 const struct lttng_condition *condition,
196 struct lttng_payload *payload)
197 {
198 int ret;
199 struct lttng_condition_event_rule *event_rule;
200 /* Used for iteration and communication (size matters). */
201 uint32_t i, capture_descr_count;
202
203 if (!condition || !IS_EVENT_RULE_CONDITION(condition)) {
204 ret = -1;
205 goto end;
206 }
207
208 DBG("Serializing event rule condition");
209 event_rule = container_of(
210 condition, struct lttng_condition_event_rule, parent);
211
212 DBG("Serializing event rule condition's event rule");
213 ret = lttng_event_rule_serialize(event_rule->rule, payload);
214 if (ret) {
215 goto end;
216 }
217
218 capture_descr_count = lttng_dynamic_pointer_array_get_count(
219 &event_rule->capture_descriptors);
220 DBG("Serializing event rule condition's capture descriptor count: %" PRIu32,
221 capture_descr_count);
222 ret = lttng_dynamic_buffer_append(&payload->buffer, &capture_descr_count,
223 sizeof(capture_descr_count));
224 if (ret) {
225 goto end;
226 }
227
228 for (i = 0; i < capture_descr_count; i++) {
229 const struct lttng_event_expr *expr =
230 lttng_dynamic_pointer_array_get_pointer(
231 &event_rule->capture_descriptors, i);
232
233 DBG("Serializing event rule condition's capture descriptor %" PRIu32,
234 i);
235 ret = serialize_event_expr(expr, payload);
236 if (ret) {
237 goto end;
238 }
239 }
240
241 end:
242 return ret;
243 }
244
245 static
246 bool capture_descriptors_are_equal(
247 const struct lttng_condition_event_rule *condition_a,
248 const struct lttng_condition_event_rule *condition_b)
249 {
250 bool is_equal = true;
251 size_t capture_descr_count_a;
252 size_t capture_descr_count_b;
253 size_t i;
254
255 capture_descr_count_a = lttng_dynamic_pointer_array_get_count(
256 &condition_a->capture_descriptors);
257 capture_descr_count_b = lttng_dynamic_pointer_array_get_count(
258 &condition_b->capture_descriptors);
259
260 if (capture_descr_count_a != capture_descr_count_b) {
261 goto not_equal;
262 }
263
264 for (i = 0; i < capture_descr_count_a; i++) {
265 const struct lttng_event_expr *expr_a =
266 lttng_dynamic_pointer_array_get_pointer(
267 &condition_a->capture_descriptors,
268 i);
269 const struct lttng_event_expr *expr_b =
270 lttng_dynamic_pointer_array_get_pointer(
271 &condition_b->capture_descriptors,
272 i);
273
274 if (!lttng_event_expr_is_equal(expr_a, expr_b)) {
275 goto not_equal;
276 }
277 }
278
279 goto end;
280
281 not_equal:
282 is_equal = false;
283
284 end:
285 return is_equal;
286 }
287
288 static bool lttng_condition_event_rule_is_equal(
289 const struct lttng_condition *_a,
290 const struct lttng_condition *_b)
291 {
292 bool is_equal = false;
293 struct lttng_condition_event_rule *a, *b;
294
295 a = container_of(_a, struct lttng_condition_event_rule, parent);
296 b = container_of(_b, struct lttng_condition_event_rule, parent);
297
298 /* Both event rules must be set or both must be unset. */
299 if ((a->rule && !b->rule) || (!a->rule && b->rule)) {
300 WARN("Comparing event_rule conditions with uninitialized rule");
301 goto end;
302 }
303
304 is_equal = lttng_event_rule_is_equal(a->rule, b->rule);
305 if (!is_equal) {
306 goto end;
307 }
308
309 is_equal = capture_descriptors_are_equal(a, b);
310
311 end:
312 return is_equal;
313 }
314
315 static void lttng_condition_event_rule_destroy(
316 struct lttng_condition *condition)
317 {
318 struct lttng_condition_event_rule *event_rule;
319
320 event_rule = container_of(
321 condition, struct lttng_condition_event_rule, parent);
322
323 lttng_event_rule_put(event_rule->rule);
324 lttng_dynamic_pointer_array_reset(&event_rule->capture_descriptors);
325 free(event_rule);
326 }
327
328 static
329 void destroy_event_expr(void *ptr)
330 {
331 lttng_event_expr_destroy(ptr);
332 }
333
334 struct lttng_condition *lttng_condition_event_rule_create(
335 struct lttng_event_rule *rule)
336 {
337 struct lttng_condition *parent = NULL;
338 struct lttng_condition_event_rule *condition = NULL;
339
340 if (!rule) {
341 goto end;
342 }
343
344 condition = zmalloc(sizeof(struct lttng_condition_event_rule));
345 if (!condition) {
346 return NULL;
347 }
348
349 lttng_condition_init(&condition->parent,
350 LTTNG_CONDITION_TYPE_EVENT_RULE_HIT);
351 condition->parent.validate = lttng_condition_event_rule_validate,
352 condition->parent.serialize = lttng_condition_event_rule_serialize,
353 condition->parent.equal = lttng_condition_event_rule_is_equal,
354 condition->parent.destroy = lttng_condition_event_rule_destroy,
355
356 lttng_event_rule_get(rule);
357 condition->rule = rule;
358 rule = NULL;
359
360 lttng_dynamic_pointer_array_init(&condition->capture_descriptors,
361 destroy_event_expr);
362
363 parent = &condition->parent;
364 end:
365 return parent;
366 }
367
368 static
369 uint64_t uint_from_buffer(const struct lttng_buffer_view *view, size_t size,
370 size_t *offset)
371 {
372 uint64_t ret;
373 const struct lttng_buffer_view uint_view =
374 lttng_buffer_view_from_view(view, *offset, size);
375
376 if (!lttng_buffer_view_is_valid(&uint_view)) {
377 ret = UINT64_C(-1);
378 goto end;
379 }
380
381 switch (size) {
382 case 1:
383 ret = (uint64_t) *uint_view.data;
384 break;
385 case sizeof(uint32_t):
386 {
387 uint32_t u32;
388
389 memcpy(&u32, uint_view.data, sizeof(u32));
390 ret = (uint64_t) u32;
391 break;
392 }
393 case sizeof(ret):
394 memcpy(&ret, uint_view.data, sizeof(ret));
395 break;
396 default:
397 abort();
398 }
399
400 *offset += size;
401
402 end:
403 return ret;
404 }
405
406 static
407 const char *str_from_buffer(const struct lttng_buffer_view *view,
408 size_t *offset)
409 {
410 uint64_t len;
411 const char *ret;
412
413 len = uint_from_buffer(view, sizeof(uint32_t), offset);
414 if (len == UINT64_C(-1)) {
415 goto error;
416 }
417
418 ret = &view->data[*offset];
419
420 if (!lttng_buffer_view_contains_string(view, ret, len)) {
421 goto error;
422 }
423
424 *offset += len;
425 goto end;
426
427 error:
428 ret = NULL;
429
430 end:
431 return ret;
432 }
433
434 static
435 struct lttng_event_expr *event_expr_from_payload(
436 struct lttng_payload_view *view, size_t *offset)
437 {
438 struct lttng_event_expr *expr = NULL;
439 const char *str;
440 uint64_t type;
441
442 type = uint_from_buffer(&view->buffer, sizeof(uint8_t), offset);
443 if (type == UINT64_C(-1)) {
444 goto error;
445 }
446
447 switch (type) {
448 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
449 str = str_from_buffer(&view->buffer, offset);
450 if (!str) {
451 goto error;
452 }
453
454 expr = lttng_event_expr_event_payload_field_create(str);
455 break;
456 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
457 str = str_from_buffer(&view->buffer, offset);
458 if (!str) {
459 goto error;
460 }
461
462 expr = lttng_event_expr_channel_context_field_create(str);
463 break;
464 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
465 {
466 const char *provider_name;
467 const char *type_name;
468
469 provider_name = str_from_buffer(&view->buffer, offset);
470 if (!provider_name) {
471 goto error;
472 }
473
474 type_name = str_from_buffer(&view->buffer, offset);
475 if (!type_name) {
476 goto error;
477 }
478
479 expr = lttng_event_expr_app_specific_context_field_create(
480 provider_name, type_name);
481 break;
482 }
483 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
484 {
485 struct lttng_event_expr *array_field_expr;
486 const uint64_t index = uint_from_buffer(
487 &view->buffer, sizeof(uint32_t), offset);
488
489 if (index == UINT64_C(-1)) {
490 goto error;
491 }
492
493 /* Array field expression is the encoded after this. */
494 array_field_expr = event_expr_from_payload(view, offset);
495 if (!array_field_expr) {
496 goto error;
497 }
498
499 /* Move ownership of `array_field_expr` to new expression. */
500 expr = lttng_event_expr_array_field_element_create(
501 array_field_expr, (unsigned int) index);
502 if (!expr) {
503 /* `array_field_expr` not moved: destroy it. */
504 lttng_event_expr_destroy(array_field_expr);
505 }
506
507 break;
508 }
509 default:
510 abort();
511 }
512
513 goto end;
514
515 error:
516 lttng_event_expr_destroy(expr);
517 expr = NULL;
518
519 end:
520 return expr;
521 }
522
523 LTTNG_HIDDEN
524 ssize_t lttng_condition_event_rule_create_from_payload(
525 struct lttng_payload_view *view,
526 struct lttng_condition **_condition)
527 {
528 ssize_t consumed_length;
529 size_t offset = 0;
530 ssize_t event_rule_length;
531 uint32_t i, capture_descr_count;
532 struct lttng_condition *condition = NULL;
533 struct lttng_event_rule *event_rule = NULL;
534
535 if (!view || !_condition) {
536 goto error;
537 }
538
539 /* Struct lttng_event_rule. */
540 {
541 struct lttng_payload_view event_rule_view =
542 lttng_payload_view_from_view(view, offset, -1);
543
544 event_rule_length = lttng_event_rule_create_from_payload(
545 &event_rule_view, &event_rule);
546 }
547
548 if (event_rule_length < 0 || !event_rule) {
549 goto error;
550 }
551
552 /* Create condition (no capture descriptors yet) at this point. */
553 condition = lttng_condition_event_rule_create(event_rule);
554 if (!condition) {
555 goto error;
556 }
557
558
559 /* Capture descriptor count. */
560 assert(event_rule_length >= 0);
561 offset += (size_t) event_rule_length;
562 capture_descr_count = uint_from_buffer(&view->buffer, sizeof(uint32_t), &offset);
563 if (capture_descr_count == UINT32_C(-1)) {
564 goto error;
565 }
566
567 /* Capture descriptors. */
568 for (i = 0; i < capture_descr_count; i++) {
569 struct lttng_event_expr *expr = event_expr_from_payload(
570 view, &offset);
571 enum lttng_condition_status status;
572
573 if (!expr) {
574 goto error;
575 }
576
577 /* Move ownership of `expr` to `condition`. */
578 status = lttng_condition_event_rule_append_capture_descriptor(
579 condition, expr);
580 if (status != LTTNG_CONDITION_STATUS_OK) {
581 /* `expr` not moved: destroy it. */
582 lttng_event_expr_destroy(expr);
583 goto error;
584 }
585 }
586
587 consumed_length = (ssize_t) offset;
588 *_condition = condition;
589 condition = NULL;
590 goto end;
591
592 error:
593 consumed_length = -1;
594
595 end:
596 lttng_event_rule_put(event_rule);
597 lttng_condition_put(condition);
598 return consumed_length;
599 }
600
601 LTTNG_HIDDEN
602 enum lttng_condition_status lttng_condition_event_rule_borrow_rule_mutable(
603 const struct lttng_condition *condition,
604 struct lttng_event_rule **rule)
605 {
606 struct lttng_condition_event_rule *event_rule;
607 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
608
609 if (!condition || !IS_EVENT_RULE_CONDITION(condition) || !rule) {
610 status = LTTNG_CONDITION_STATUS_INVALID;
611 goto end;
612 }
613
614 event_rule = container_of(
615 condition, struct lttng_condition_event_rule, parent);
616 if (!event_rule->rule) {
617 status = LTTNG_CONDITION_STATUS_UNSET;
618 goto end;
619 }
620
621 *rule = event_rule->rule;
622 end:
623 return status;
624 }
625
626 enum lttng_condition_status lttng_condition_event_rule_get_rule(
627 const struct lttng_condition *condition,
628 const struct lttng_event_rule **rule)
629 {
630 struct lttng_event_rule *mutable_rule = NULL;
631 const enum lttng_condition_status status =
632 lttng_condition_event_rule_borrow_rule_mutable(
633 condition, &mutable_rule);
634
635 *rule = mutable_rule;
636 return status;
637 }
638
639 enum lttng_condition_status
640 lttng_condition_event_rule_append_capture_descriptor(
641 struct lttng_condition *condition,
642 struct lttng_event_expr *expr)
643 {
644 int ret;
645 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
646 struct lttng_condition_event_rule *event_rule_cond =
647 container_of(condition,
648 struct lttng_condition_event_rule, parent);
649
650 /* Only accept l-values. */
651 if (!condition || !IS_EVENT_RULE_CONDITION(condition) || !expr ||
652 !lttng_event_expr_is_lvalue(expr)) {
653 status = LTTNG_CONDITION_STATUS_INVALID;
654 goto end;
655 }
656
657 ret = lttng_dynamic_pointer_array_add_pointer(
658 &event_rule_cond->capture_descriptors, expr);
659 if (ret) {
660 status = LTTNG_CONDITION_STATUS_ERROR;
661 goto end;
662 }
663
664 end:
665 return status;
666 }
667
668 enum lttng_condition_status
669 lttng_condition_event_rule_get_capture_descriptor_count(
670 const struct lttng_condition *condition, unsigned int *count)
671 {
672 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
673 const struct lttng_condition_event_rule *event_rule_cond =
674 container_of(condition,
675 const struct lttng_condition_event_rule,
676 parent);
677
678 if (!condition || !IS_EVENT_RULE_CONDITION(condition) || !count) {
679 status = LTTNG_CONDITION_STATUS_INVALID;
680 goto end;
681 }
682
683 *count = lttng_dynamic_pointer_array_get_count(
684 &event_rule_cond->capture_descriptors);
685
686 end:
687 return status;
688 }
689
690 const struct lttng_event_expr *
691 lttng_condition_event_rule_get_capture_descriptor_at_index(
692 const struct lttng_condition *condition, unsigned int index)
693 {
694 const struct lttng_condition_event_rule *event_rule_cond =
695 container_of(condition,
696 const struct lttng_condition_event_rule,
697 parent);
698 const struct lttng_event_expr *expr = NULL;
699
700 if (!condition || !IS_EVENT_RULE_CONDITION(condition) ||
701 index >= lttng_dynamic_pointer_array_get_count(
702 &event_rule_cond->capture_descriptors)) {
703 goto end;
704 }
705
706 expr = lttng_dynamic_pointer_array_get_pointer(
707 &event_rule_cond->capture_descriptors, index);
708
709 end:
710 return expr;
711 }
712
713 LTTNG_HIDDEN
714 ssize_t lttng_evaluation_event_rule_create_from_payload(
715 struct lttng_payload_view *view,
716 struct lttng_evaluation **_evaluation)
717 {
718 ssize_t ret, offset = 0;
719 const char *trigger_name;
720 struct lttng_evaluation *evaluation = NULL;
721 const struct lttng_evaluation_event_rule_comm *header;
722 const struct lttng_payload_view header_view =
723 lttng_payload_view_from_view(
724 view, 0, sizeof(*header));
725
726 if (!_evaluation) {
727 ret = -1;
728 goto error;
729 }
730
731 if (!lttng_payload_view_is_valid(&header_view)) {
732 ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain header");
733 ret = -1;
734 goto error;
735 }
736
737 header = (typeof(header)) header_view.buffer.data;
738
739 /* Map the originating trigger's name. */
740 offset += sizeof(*header);
741 {
742 struct lttng_payload_view current_view =
743 lttng_payload_view_from_view(view, offset,
744 header->trigger_name_length);
745
746 if (!lttng_payload_view_is_valid(&current_view)) {
747 ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain trigger name");
748 ret = -1;
749 goto error;
750 }
751
752 trigger_name = current_view.buffer.data;
753 if (!lttng_buffer_view_contains_string(&current_view.buffer,
754 trigger_name, header->trigger_name_length)) {
755 ERR("Failed to initialize from malformed event rule evaluation: invalid trigger name");
756 ret = -1;
757 goto error;
758 }
759 }
760
761 offset += header->trigger_name_length;
762
763 evaluation = lttng_evaluation_event_rule_create(trigger_name);
764 if (!evaluation) {
765 ret = -1;
766 goto error;
767 }
768
769 *_evaluation = evaluation;
770 evaluation = NULL;
771 ret = offset;
772
773 error:
774 lttng_evaluation_destroy(evaluation);
775 return ret;
776 }
777
778 static int lttng_evaluation_event_rule_serialize(
779 const struct lttng_evaluation *evaluation,
780 struct lttng_payload *payload)
781 {
782 int ret = 0;
783 struct lttng_evaluation_event_rule *hit;
784 struct lttng_evaluation_event_rule_comm comm;
785
786 hit = container_of(
787 evaluation, struct lttng_evaluation_event_rule, parent);
788
789 assert(hit->name);
790 comm.trigger_name_length = strlen(hit->name) + 1;
791
792 ret = lttng_dynamic_buffer_append(
793 &payload->buffer, &comm, sizeof(comm));
794 if (ret) {
795 goto end;
796 }
797
798 ret = lttng_dynamic_buffer_append(
799 &payload->buffer, hit->name, comm.trigger_name_length);
800 end:
801 return ret;
802 }
803
804 static void lttng_evaluation_event_rule_destroy(
805 struct lttng_evaluation *evaluation)
806 {
807 struct lttng_evaluation_event_rule *hit;
808
809 hit = container_of(
810 evaluation, struct lttng_evaluation_event_rule, parent);
811 free(hit->name);
812 free(hit);
813 }
814
815 LTTNG_HIDDEN
816 struct lttng_evaluation *lttng_evaluation_event_rule_create(
817 const char *trigger_name)
818 {
819 struct lttng_evaluation_event_rule *hit;
820 struct lttng_evaluation *evaluation = NULL;
821
822 hit = zmalloc(sizeof(struct lttng_evaluation_event_rule));
823 if (!hit) {
824 goto end;
825 }
826
827 hit->name = strdup(trigger_name);
828 if (!hit->name) {
829 goto end;
830 }
831
832 hit->parent.type = LTTNG_CONDITION_TYPE_EVENT_RULE_HIT;
833 hit->parent.serialize = lttng_evaluation_event_rule_serialize;
834 hit->parent.destroy = lttng_evaluation_event_rule_destroy;
835
836 evaluation = &hit->parent;
837 hit = NULL;
838
839 end:
840 if (hit) {
841 lttng_evaluation_event_rule_destroy(&hit->parent);
842 }
843
844 return evaluation;
845 }
846
847 enum lttng_evaluation_status lttng_evaluation_event_rule_get_trigger_name(
848 const struct lttng_evaluation *evaluation, const char **name)
849 {
850 struct lttng_evaluation_event_rule *hit;
851 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
852
853 if (!evaluation || !is_event_rule_evaluation(evaluation) || !name) {
854 status = LTTNG_EVALUATION_STATUS_INVALID;
855 goto end;
856 }
857
858 hit = container_of(
859 evaluation, struct lttng_evaluation_event_rule, parent);
860 *name = hit->name;
861 end:
862 return status;
863 }
This page took 0.046614 seconds and 5 git commands to generate.