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