condition: introduce lttng_capture_descriptor struct
[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 enum lttng_condition_status status;
202 /* Used for iteration and communication (size matters). */
203 uint32_t i, capture_descr_count;
204
205 if (!condition || !IS_EVENT_RULE_CONDITION(condition)) {
206 ret = -1;
207 goto end;
208 }
209
210 DBG("Serializing event rule condition");
211 event_rule = container_of(
212 condition, struct lttng_condition_event_rule, parent);
213
214 DBG("Serializing event rule condition's event rule");
215 ret = lttng_event_rule_serialize(event_rule->rule, payload);
216 if (ret) {
217 goto end;
218 }
219
220 status = lttng_condition_event_rule_get_capture_descriptor_count(
221 condition, &capture_descr_count);
222 if (status != LTTNG_CONDITION_STATUS_OK) {
223 ret = -1;
224 goto end;
225 };
226
227 DBG("Serializing event rule condition's capture descriptor count: %" PRIu32,
228 capture_descr_count);
229 ret = lttng_dynamic_buffer_append(&payload->buffer, &capture_descr_count,
230 sizeof(capture_descr_count));
231 if (ret) {
232 goto end;
233 }
234
235 for (i = 0; i < capture_descr_count; i++) {
236 const struct lttng_event_expr *expr =
237 lttng_condition_event_rule_get_capture_descriptor_at_index(
238 condition, i);
239
240 DBG("Serializing event rule condition's capture descriptor %" PRIu32,
241 i);
242 ret = serialize_event_expr(expr, payload);
243 if (ret) {
244 goto end;
245 }
246 }
247
248 end:
249 return ret;
250 }
251
252 static
253 bool capture_descriptors_are_equal(
254 const struct lttng_condition *condition_a,
255 const struct lttng_condition *condition_b)
256 {
257 bool is_equal = true;
258 unsigned int capture_descr_count_a;
259 unsigned int capture_descr_count_b;
260 size_t i;
261 enum lttng_condition_status status;
262
263 status = lttng_condition_event_rule_get_capture_descriptor_count(
264 condition_a, &capture_descr_count_a);
265 if (status != LTTNG_CONDITION_STATUS_OK) {
266 goto not_equal;
267 }
268
269 status = lttng_condition_event_rule_get_capture_descriptor_count(
270 condition_b, &capture_descr_count_b);
271 if (status != LTTNG_CONDITION_STATUS_OK) {
272 goto not_equal;
273 }
274
275 if (capture_descr_count_a != capture_descr_count_b) {
276 goto not_equal;
277 }
278
279 for (i = 0; i < capture_descr_count_a; i++) {
280 const struct lttng_event_expr *expr_a =
281 lttng_condition_event_rule_get_capture_descriptor_at_index(
282 condition_a,
283 i);
284 const struct lttng_event_expr *expr_b =
285 lttng_condition_event_rule_get_capture_descriptor_at_index(
286 condition_b,
287 i);
288
289 if (!lttng_event_expr_is_equal(expr_a, expr_b)) {
290 goto not_equal;
291 }
292 }
293
294 goto end;
295
296 not_equal:
297 is_equal = false;
298
299 end:
300 return is_equal;
301 }
302
303 static bool lttng_condition_event_rule_is_equal(
304 const struct lttng_condition *_a,
305 const struct lttng_condition *_b)
306 {
307 bool is_equal = false;
308 struct lttng_condition_event_rule *a, *b;
309
310 a = container_of(_a, struct lttng_condition_event_rule, parent);
311 b = container_of(_b, struct lttng_condition_event_rule, parent);
312
313 /* Both event rules must be set or both must be unset. */
314 if ((a->rule && !b->rule) || (!a->rule && b->rule)) {
315 WARN("Comparing event_rule conditions with uninitialized rule");
316 goto end;
317 }
318
319 is_equal = lttng_event_rule_is_equal(a->rule, b->rule);
320 if (!is_equal) {
321 goto end;
322 }
323
324 is_equal = capture_descriptors_are_equal(_a, _b);
325
326 end:
327 return is_equal;
328 }
329
330 static void lttng_condition_event_rule_destroy(
331 struct lttng_condition *condition)
332 {
333 struct lttng_condition_event_rule *event_rule;
334
335 event_rule = container_of(
336 condition, struct lttng_condition_event_rule, parent);
337
338 lttng_event_rule_put(event_rule->rule);
339 lttng_dynamic_pointer_array_reset(&event_rule->capture_descriptors);
340 free(event_rule);
341 }
342
343 static
344 void destroy_capture_descriptor(void *ptr)
345 {
346 struct lttng_capture_descriptor *desc =
347 (struct lttng_capture_descriptor *) ptr;
348
349 lttng_event_expr_destroy(desc->event_expression);
350 free(desc->bytecode);
351 free(desc);
352 }
353
354 struct lttng_condition *lttng_condition_event_rule_create(
355 struct lttng_event_rule *rule)
356 {
357 struct lttng_condition *parent = NULL;
358 struct lttng_condition_event_rule *condition = NULL;
359
360 if (!rule) {
361 goto end;
362 }
363
364 condition = zmalloc(sizeof(struct lttng_condition_event_rule));
365 if (!condition) {
366 return NULL;
367 }
368
369 lttng_condition_init(&condition->parent,
370 LTTNG_CONDITION_TYPE_EVENT_RULE_HIT);
371 condition->parent.validate = lttng_condition_event_rule_validate,
372 condition->parent.serialize = lttng_condition_event_rule_serialize,
373 condition->parent.equal = lttng_condition_event_rule_is_equal,
374 condition->parent.destroy = lttng_condition_event_rule_destroy,
375
376 lttng_event_rule_get(rule);
377 condition->rule = rule;
378 rule = NULL;
379
380 lttng_dynamic_pointer_array_init(&condition->capture_descriptors,
381 destroy_capture_descriptor);
382
383 parent = &condition->parent;
384 end:
385 return parent;
386 }
387
388 static
389 uint64_t uint_from_buffer(const struct lttng_buffer_view *view, size_t size,
390 size_t *offset)
391 {
392 uint64_t ret;
393 const struct lttng_buffer_view uint_view =
394 lttng_buffer_view_from_view(view, *offset, size);
395
396 if (!lttng_buffer_view_is_valid(&uint_view)) {
397 ret = UINT64_C(-1);
398 goto end;
399 }
400
401 switch (size) {
402 case 1:
403 ret = (uint64_t) *uint_view.data;
404 break;
405 case sizeof(uint32_t):
406 {
407 uint32_t u32;
408
409 memcpy(&u32, uint_view.data, sizeof(u32));
410 ret = (uint64_t) u32;
411 break;
412 }
413 case sizeof(ret):
414 memcpy(&ret, uint_view.data, sizeof(ret));
415 break;
416 default:
417 abort();
418 }
419
420 *offset += size;
421
422 end:
423 return ret;
424 }
425
426 static
427 const char *str_from_buffer(const struct lttng_buffer_view *view,
428 size_t *offset)
429 {
430 uint64_t len;
431 const char *ret;
432
433 len = uint_from_buffer(view, sizeof(uint32_t), offset);
434 if (len == UINT64_C(-1)) {
435 goto error;
436 }
437
438 ret = &view->data[*offset];
439
440 if (!lttng_buffer_view_contains_string(view, ret, len)) {
441 goto error;
442 }
443
444 *offset += len;
445 goto end;
446
447 error:
448 ret = NULL;
449
450 end:
451 return ret;
452 }
453
454 static
455 struct lttng_event_expr *event_expr_from_payload(
456 struct lttng_payload_view *view, size_t *offset)
457 {
458 struct lttng_event_expr *expr = NULL;
459 const char *str;
460 uint64_t type;
461
462 type = uint_from_buffer(&view->buffer, sizeof(uint8_t), offset);
463 if (type == UINT64_C(-1)) {
464 goto error;
465 }
466
467 switch (type) {
468 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
469 str = str_from_buffer(&view->buffer, offset);
470 if (!str) {
471 goto error;
472 }
473
474 expr = lttng_event_expr_event_payload_field_create(str);
475 break;
476 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
477 str = str_from_buffer(&view->buffer, offset);
478 if (!str) {
479 goto error;
480 }
481
482 expr = lttng_event_expr_channel_context_field_create(str);
483 break;
484 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
485 {
486 const char *provider_name;
487 const char *type_name;
488
489 provider_name = str_from_buffer(&view->buffer, offset);
490 if (!provider_name) {
491 goto error;
492 }
493
494 type_name = str_from_buffer(&view->buffer, offset);
495 if (!type_name) {
496 goto error;
497 }
498
499 expr = lttng_event_expr_app_specific_context_field_create(
500 provider_name, type_name);
501 break;
502 }
503 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
504 {
505 struct lttng_event_expr *array_field_expr;
506 const uint64_t index = uint_from_buffer(
507 &view->buffer, sizeof(uint32_t), offset);
508
509 if (index == UINT64_C(-1)) {
510 goto error;
511 }
512
513 /* Array field expression is the encoded after this. */
514 array_field_expr = event_expr_from_payload(view, offset);
515 if (!array_field_expr) {
516 goto error;
517 }
518
519 /* Move ownership of `array_field_expr` to new expression. */
520 expr = lttng_event_expr_array_field_element_create(
521 array_field_expr, (unsigned int) index);
522 if (!expr) {
523 /* `array_field_expr` not moved: destroy it. */
524 lttng_event_expr_destroy(array_field_expr);
525 }
526
527 break;
528 }
529 default:
530 abort();
531 }
532
533 goto end;
534
535 error:
536 lttng_event_expr_destroy(expr);
537 expr = NULL;
538
539 end:
540 return expr;
541 }
542
543 LTTNG_HIDDEN
544 ssize_t lttng_condition_event_rule_create_from_payload(
545 struct lttng_payload_view *view,
546 struct lttng_condition **_condition)
547 {
548 ssize_t consumed_length;
549 size_t offset = 0;
550 ssize_t event_rule_length;
551 uint32_t i, capture_descr_count;
552 struct lttng_condition *condition = NULL;
553 struct lttng_event_rule *event_rule = NULL;
554
555 if (!view || !_condition) {
556 goto error;
557 }
558
559 /* Struct lttng_event_rule. */
560 {
561 struct lttng_payload_view event_rule_view =
562 lttng_payload_view_from_view(view, offset, -1);
563
564 event_rule_length = lttng_event_rule_create_from_payload(
565 &event_rule_view, &event_rule);
566 }
567
568 if (event_rule_length < 0 || !event_rule) {
569 goto error;
570 }
571
572 /* Create condition (no capture descriptors yet) at this point. */
573 condition = lttng_condition_event_rule_create(event_rule);
574 if (!condition) {
575 goto error;
576 }
577
578
579 /* Capture descriptor count. */
580 assert(event_rule_length >= 0);
581 offset += (size_t) event_rule_length;
582 capture_descr_count = uint_from_buffer(&view->buffer, sizeof(uint32_t), &offset);
583 if (capture_descr_count == UINT32_C(-1)) {
584 goto error;
585 }
586
587 /* Capture descriptors. */
588 for (i = 0; i < capture_descr_count; i++) {
589 struct lttng_event_expr *expr = event_expr_from_payload(
590 view, &offset);
591 enum lttng_condition_status status;
592
593 if (!expr) {
594 goto error;
595 }
596
597 /* Move ownership of `expr` to `condition`. */
598 status = lttng_condition_event_rule_append_capture_descriptor(
599 condition, expr);
600 if (status != LTTNG_CONDITION_STATUS_OK) {
601 /* `expr` not moved: destroy it. */
602 lttng_event_expr_destroy(expr);
603 goto error;
604 }
605 }
606
607 consumed_length = (ssize_t) offset;
608 *_condition = condition;
609 condition = NULL;
610 goto end;
611
612 error:
613 consumed_length = -1;
614
615 end:
616 lttng_event_rule_put(event_rule);
617 lttng_condition_put(condition);
618 return consumed_length;
619 }
620
621 LTTNG_HIDDEN
622 enum lttng_condition_status lttng_condition_event_rule_borrow_rule_mutable(
623 const struct lttng_condition *condition,
624 struct lttng_event_rule **rule)
625 {
626 struct lttng_condition_event_rule *event_rule;
627 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
628
629 if (!condition || !IS_EVENT_RULE_CONDITION(condition) || !rule) {
630 status = LTTNG_CONDITION_STATUS_INVALID;
631 goto end;
632 }
633
634 event_rule = container_of(
635 condition, struct lttng_condition_event_rule, parent);
636 if (!event_rule->rule) {
637 status = LTTNG_CONDITION_STATUS_UNSET;
638 goto end;
639 }
640
641 *rule = event_rule->rule;
642 end:
643 return status;
644 }
645
646 enum lttng_condition_status lttng_condition_event_rule_get_rule(
647 const struct lttng_condition *condition,
648 const struct lttng_event_rule **rule)
649 {
650 struct lttng_event_rule *mutable_rule = NULL;
651 const enum lttng_condition_status status =
652 lttng_condition_event_rule_borrow_rule_mutable(
653 condition, &mutable_rule);
654
655 *rule = mutable_rule;
656 return status;
657 }
658
659 enum lttng_condition_status
660 lttng_condition_event_rule_append_capture_descriptor(
661 struct lttng_condition *condition,
662 struct lttng_event_expr *expr)
663 {
664 int ret;
665 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
666 struct lttng_condition_event_rule *event_rule_cond =
667 container_of(condition,
668 struct lttng_condition_event_rule, parent);
669 struct lttng_capture_descriptor *descriptor = NULL;
670
671 /* Only accept l-values. */
672 if (!condition || !IS_EVENT_RULE_CONDITION(condition) || !expr ||
673 !lttng_event_expr_is_lvalue(expr)) {
674 status = LTTNG_CONDITION_STATUS_INVALID;
675 goto end;
676 }
677
678 descriptor = malloc(sizeof(*descriptor));
679 if (descriptor == NULL) {
680 status = LTTNG_CONDITION_STATUS_ERROR;
681 goto end;
682 }
683
684 descriptor->event_expression = expr;
685 descriptor->bytecode = NULL;
686
687 ret = lttng_dynamic_pointer_array_add_pointer(
688 &event_rule_cond->capture_descriptors, descriptor);
689 if (ret) {
690 status = LTTNG_CONDITION_STATUS_ERROR;
691 goto end;
692 }
693
694 /* Ownership is transfered to the internal capture_descriptors array */
695 descriptor = NULL;
696 end:
697 free(descriptor);
698 return status;
699 }
700
701 enum lttng_condition_status
702 lttng_condition_event_rule_get_capture_descriptor_count(
703 const struct lttng_condition *condition, unsigned int *count)
704 {
705 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
706 const struct lttng_condition_event_rule *event_rule_cond =
707 container_of(condition,
708 const struct lttng_condition_event_rule,
709 parent);
710
711 if (!condition || !IS_EVENT_RULE_CONDITION(condition) || !count) {
712 status = LTTNG_CONDITION_STATUS_INVALID;
713 goto end;
714 }
715
716 *count = lttng_dynamic_pointer_array_get_count(
717 &event_rule_cond->capture_descriptors);
718
719 end:
720 return status;
721 }
722
723 const struct lttng_event_expr *
724 lttng_condition_event_rule_get_capture_descriptor_at_index(
725 const struct lttng_condition *condition, unsigned int index)
726 {
727 const struct lttng_condition_event_rule *event_rule_cond =
728 container_of(condition,
729 const struct lttng_condition_event_rule,
730 parent);
731 const struct lttng_event_expr *expr = NULL;
732 struct lttng_capture_descriptor *desc = NULL;
733 unsigned int count;
734 enum lttng_condition_status status;
735
736 if (!condition || !IS_EVENT_RULE_CONDITION(condition)) {
737 goto end;
738 }
739
740 status = lttng_condition_event_rule_get_capture_descriptor_count(condition, &count);
741 if (status != LTTNG_CONDITION_STATUS_OK) {
742 goto end;
743 }
744
745 if (index >= count) {
746 goto end;
747 }
748
749 desc = lttng_dynamic_pointer_array_get_pointer(
750 &event_rule_cond->capture_descriptors, index);
751 expr = desc->event_expression;
752
753 end:
754 return expr;
755 }
756
757 LTTNG_HIDDEN
758 ssize_t lttng_evaluation_event_rule_create_from_payload(
759 struct lttng_payload_view *view,
760 struct lttng_evaluation **_evaluation)
761 {
762 ssize_t ret, offset = 0;
763 const char *trigger_name;
764 struct lttng_evaluation *evaluation = NULL;
765 const struct lttng_evaluation_event_rule_comm *header;
766 const struct lttng_payload_view header_view =
767 lttng_payload_view_from_view(
768 view, 0, sizeof(*header));
769
770 if (!_evaluation) {
771 ret = -1;
772 goto error;
773 }
774
775 if (!lttng_payload_view_is_valid(&header_view)) {
776 ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain header");
777 ret = -1;
778 goto error;
779 }
780
781 header = (typeof(header)) header_view.buffer.data;
782
783 /* Map the originating trigger's name. */
784 offset += sizeof(*header);
785 {
786 struct lttng_payload_view current_view =
787 lttng_payload_view_from_view(view, offset,
788 header->trigger_name_length);
789
790 if (!lttng_payload_view_is_valid(&current_view)) {
791 ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain trigger name");
792 ret = -1;
793 goto error;
794 }
795
796 trigger_name = current_view.buffer.data;
797 if (!lttng_buffer_view_contains_string(&current_view.buffer,
798 trigger_name, header->trigger_name_length)) {
799 ERR("Failed to initialize from malformed event rule evaluation: invalid trigger name");
800 ret = -1;
801 goto error;
802 }
803 }
804
805 offset += header->trigger_name_length;
806
807 evaluation = lttng_evaluation_event_rule_create(trigger_name);
808 if (!evaluation) {
809 ret = -1;
810 goto error;
811 }
812
813 *_evaluation = evaluation;
814 evaluation = NULL;
815 ret = offset;
816
817 error:
818 lttng_evaluation_destroy(evaluation);
819 return ret;
820 }
821
822 static int lttng_evaluation_event_rule_serialize(
823 const struct lttng_evaluation *evaluation,
824 struct lttng_payload *payload)
825 {
826 int ret = 0;
827 struct lttng_evaluation_event_rule *hit;
828 struct lttng_evaluation_event_rule_comm comm;
829
830 hit = container_of(
831 evaluation, struct lttng_evaluation_event_rule, parent);
832
833 assert(hit->name);
834 comm.trigger_name_length = strlen(hit->name) + 1;
835
836 ret = lttng_dynamic_buffer_append(
837 &payload->buffer, &comm, sizeof(comm));
838 if (ret) {
839 goto end;
840 }
841
842 ret = lttng_dynamic_buffer_append(
843 &payload->buffer, hit->name, comm.trigger_name_length);
844 end:
845 return ret;
846 }
847
848 static void lttng_evaluation_event_rule_destroy(
849 struct lttng_evaluation *evaluation)
850 {
851 struct lttng_evaluation_event_rule *hit;
852
853 hit = container_of(
854 evaluation, struct lttng_evaluation_event_rule, parent);
855 free(hit->name);
856 free(hit);
857 }
858
859 LTTNG_HIDDEN
860 struct lttng_evaluation *lttng_evaluation_event_rule_create(
861 const char *trigger_name)
862 {
863 struct lttng_evaluation_event_rule *hit;
864 struct lttng_evaluation *evaluation = NULL;
865
866 hit = zmalloc(sizeof(struct lttng_evaluation_event_rule));
867 if (!hit) {
868 goto end;
869 }
870
871 hit->name = strdup(trigger_name);
872 if (!hit->name) {
873 goto end;
874 }
875
876 hit->parent.type = LTTNG_CONDITION_TYPE_EVENT_RULE_HIT;
877 hit->parent.serialize = lttng_evaluation_event_rule_serialize;
878 hit->parent.destroy = lttng_evaluation_event_rule_destroy;
879
880 evaluation = &hit->parent;
881 hit = NULL;
882
883 end:
884 if (hit) {
885 lttng_evaluation_event_rule_destroy(&hit->parent);
886 }
887
888 return evaluation;
889 }
890
891 enum lttng_evaluation_status lttng_evaluation_event_rule_get_trigger_name(
892 const struct lttng_evaluation *evaluation, const char **name)
893 {
894 struct lttng_evaluation_event_rule *hit;
895 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
896
897 if (!evaluation || !is_event_rule_evaluation(evaluation) || !name) {
898 status = LTTNG_EVALUATION_STATUS_INVALID;
899 goto end;
900 }
901
902 hit = container_of(
903 evaluation, struct lttng_evaluation_event_rule, parent);
904 *name = hit->name;
905 end:
906 return status;
907 }
This page took 0.048723 seconds and 4 git commands to generate.