3f6b96015de81d9df9b7c4cdef084d26cfff349a
[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/event-expr-to-bytecode.h>
11 #include <common/macros.h>
12 #include <inttypes.h>
13 #include <limits.h>
14 #include <lttng/condition/condition-internal.h>
15 #include <lttng/event-rule/event-rule-internal.h>
16 #include <lttng/condition/event-rule-internal.h>
17 #include <lttng/condition/event-rule.h>
18 #include <lttng/event-expr-internal.h>
19 #include <lttng/event-expr.h>
20 #include <lttng/event-field-value-internal.h>
21 #include <lttng/event-rule/event-rule-internal.h>
22 #include <lttng/lttng-error.h>
23 #include <stdbool.h>
24 #include <stdint.h>
25 #include <vendor/msgpack/msgpack.h>
26
27 #define IS_EVENT_RULE_CONDITION(condition) \
28 (lttng_condition_get_type(condition) == \
29 LTTNG_CONDITION_TYPE_EVENT_RULE_HIT)
30
31 static bool is_event_rule_evaluation(const struct lttng_evaluation *evaluation)
32 {
33 enum lttng_condition_type type = lttng_evaluation_get_type(evaluation);
34
35 return type == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT;
36 }
37
38 static bool lttng_condition_event_rule_validate(
39 const struct lttng_condition *condition);
40 static int lttng_condition_event_rule_serialize(
41 const struct lttng_condition *condition,
42 struct lttng_payload *payload);
43 static bool lttng_condition_event_rule_is_equal(
44 const struct lttng_condition *_a,
45 const struct lttng_condition *_b);
46 static void lttng_condition_event_rule_destroy(
47 struct lttng_condition *condition);
48
49 static bool lttng_condition_event_rule_validate(
50 const struct lttng_condition *condition)
51 {
52 bool valid = false;
53 struct lttng_condition_event_rule *event_rule;
54
55 if (!condition) {
56 goto end;
57 }
58
59 event_rule = container_of(
60 condition, struct lttng_condition_event_rule, parent);
61 if (!event_rule->rule) {
62 ERR("Invalid event rule condition: a rule must be set");
63 goto end;
64 }
65
66 valid = lttng_event_rule_validate(event_rule->rule);
67 end:
68 return valid;
69 }
70
71 static const char *msgpack_object_type_str(msgpack_object_type type)
72 {
73 const char *name;
74
75 switch (type) {
76 case MSGPACK_OBJECT_NIL:
77 name = "MSGPACK_OBJECT_NIL";
78 break;
79 case MSGPACK_OBJECT_BOOLEAN:
80 name = "MSGPACK_OBJECT_BOOLEAN";
81 break;
82 case MSGPACK_OBJECT_POSITIVE_INTEGER:
83 name = "MSGPACK_OBJECT_POSITIVE_INTEGER";
84 break;
85 case MSGPACK_OBJECT_NEGATIVE_INTEGER:
86 name = "MSGPACK_OBJECT_NEGATIVE_INTEGER";
87 break;
88 case MSGPACK_OBJECT_FLOAT32:
89 name = "MSGPACK_OBJECT_FLOAT32";
90 break;
91 case MSGPACK_OBJECT_FLOAT:
92 /* Same value as MSGPACK_OBJECT_FLOAT64 */
93 name = "MSGPACK_OBJECT_FLOAT(64)";
94 break;
95 case MSGPACK_OBJECT_STR:
96 name = "MSGPACK_OBJECT_STR";
97 break;
98 case MSGPACK_OBJECT_ARRAY:
99 name = "MSGPACK_OBJECT_ARRAY";
100 break;
101 case MSGPACK_OBJECT_MAP:
102 name = "MSGPACK_OBJECT_MAP";
103 break;
104 case MSGPACK_OBJECT_BIN:
105 name = "MSGPACK_OBJECT_BIN";
106 break;
107 case MSGPACK_OBJECT_EXT:
108 name = "MSGPACK_OBJECT_EXT";
109 break;
110 default:
111 abort();
112 }
113
114 return name;
115 }
116
117 /*
118 * Serializes the C string `str` into `buf`.
119 *
120 * Encoding is the length of `str` plus one (for the null character),
121 * and then the string, including its null terminator.
122 */
123 static
124 int serialize_cstr(const char *str, struct lttng_dynamic_buffer *buf)
125 {
126 int ret;
127 const uint32_t len = strlen(str) + 1;
128
129 /* Serialize the length, including the null terminator. */
130 DBG("Serializing C string's length (including null terminator): "
131 "%" PRIu32, len);
132 ret = lttng_dynamic_buffer_append(buf, &len, sizeof(len));
133 if (ret) {
134 goto end;
135 }
136
137 /* Serialize the string. */
138 DBG("Serializing C string: '%s'", str);
139 ret = lttng_dynamic_buffer_append(buf, str, len);
140 if (ret) {
141 goto end;
142 }
143
144 end:
145 return ret;
146 }
147
148 /*
149 * Serializes the event expression `expr` into `buf`.
150 */
151 static
152 int serialize_event_expr(const struct lttng_event_expr *expr,
153 struct lttng_payload *payload)
154 {
155 const uint8_t type = expr->type;
156 int ret;
157
158 /* Serialize the expression's type. */
159 DBG("Serializing event expression's type: %d", expr->type);
160 ret = lttng_dynamic_buffer_append(&payload->buffer, &type, sizeof(type));
161 if (ret) {
162 goto end;
163 }
164
165 /* Serialize the expression */
166 switch (expr->type) {
167 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
168 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
169 {
170 const struct lttng_event_expr_field *field_expr =
171 container_of(expr,
172 const struct lttng_event_expr_field,
173 parent);
174
175 /* Serialize the field name. */
176 DBG("Serializing field event expression's field name: '%s'",
177 field_expr->name);
178 ret = serialize_cstr(field_expr->name, &payload->buffer);
179 if (ret) {
180 goto end;
181 }
182
183 break;
184 }
185 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
186 {
187 const struct lttng_event_expr_app_specific_context_field *field_expr =
188 container_of(expr,
189 const struct lttng_event_expr_app_specific_context_field,
190 parent);
191
192 /* Serialize the provider name. */
193 DBG("Serializing app-specific context field event expression's "
194 "provider name: '%s'",
195 field_expr->provider_name);
196 ret = serialize_cstr(field_expr->provider_name, &payload->buffer);
197 if (ret) {
198 goto end;
199 }
200
201 /* Serialize the type name. */
202 DBG("Serializing app-specific context field event expression's "
203 "type name: '%s'",
204 field_expr->provider_name);
205 ret = serialize_cstr(field_expr->type_name, &payload->buffer);
206 if (ret) {
207 goto end;
208 }
209
210 break;
211 }
212 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
213 {
214 const struct lttng_event_expr_array_field_element *elem_expr =
215 container_of(expr,
216 const struct lttng_event_expr_array_field_element,
217 parent);
218 const uint32_t index = elem_expr->index;
219
220 /* Serialize the index. */
221 DBG("Serializing array field element event expression's "
222 "index: %u", elem_expr->index);
223 ret = lttng_dynamic_buffer_append(&payload->buffer, &index, sizeof(index));
224 if (ret) {
225 goto end;
226 }
227
228 /* Serialize the parent array field expression. */
229 DBG("Serializing array field element event expression's "
230 "parent array field event expression");
231 ret = serialize_event_expr(elem_expr->array_field_expr, payload);
232 if (ret) {
233 goto end;
234 }
235
236 break;
237 }
238 default:
239 break;
240 }
241
242 end:
243 return ret;
244 }
245
246 static
247 struct lttng_capture_descriptor *
248 lttng_condition_event_rule_get_internal_capture_descriptor_at_index(
249 const struct lttng_condition *condition, unsigned int index)
250 {
251 const struct lttng_condition_event_rule *event_rule_cond =
252 container_of(condition,
253 const struct lttng_condition_event_rule,
254 parent);
255 struct lttng_capture_descriptor *desc = NULL;
256 unsigned int count;
257 enum lttng_condition_status status;
258
259 if (!condition || !IS_EVENT_RULE_CONDITION(condition)) {
260 goto end;
261 }
262
263 status = lttng_condition_event_rule_get_capture_descriptor_count(
264 condition, &count);
265 if (status != LTTNG_CONDITION_STATUS_OK) {
266 goto end;
267 }
268
269 if (index >= count) {
270 goto end;
271 }
272
273 desc = lttng_dynamic_pointer_array_get_pointer(
274 &event_rule_cond->capture_descriptors, index);
275 end:
276 return desc;
277 }
278
279 static int lttng_condition_event_rule_serialize(
280 const struct lttng_condition *condition,
281 struct lttng_payload *payload)
282 {
283 int ret;
284 struct lttng_condition_event_rule *event_rule;
285 enum lttng_condition_status status;
286 /* Used for iteration and communication (size matters). */
287 uint32_t i, capture_descr_count;
288
289 if (!condition || !IS_EVENT_RULE_CONDITION(condition)) {
290 ret = -1;
291 goto end;
292 }
293
294 DBG("Serializing event rule condition");
295 event_rule = container_of(
296 condition, struct lttng_condition_event_rule, parent);
297
298 DBG("Serializing event rule condition's event rule");
299 ret = lttng_event_rule_serialize(event_rule->rule, payload);
300 if (ret) {
301 goto end;
302 }
303
304 status = lttng_condition_event_rule_get_capture_descriptor_count(
305 condition, &capture_descr_count);
306 if (status != LTTNG_CONDITION_STATUS_OK) {
307 ret = -1;
308 goto end;
309 };
310
311 DBG("Serializing event rule condition's capture descriptor count: %" PRIu32,
312 capture_descr_count);
313 ret = lttng_dynamic_buffer_append(&payload->buffer, &capture_descr_count,
314 sizeof(capture_descr_count));
315 if (ret) {
316 goto end;
317 }
318
319 for (i = 0; i < capture_descr_count; i++) {
320 const struct lttng_capture_descriptor *desc =
321 lttng_condition_event_rule_get_internal_capture_descriptor_at_index(
322 condition, i);
323
324 DBG("Serializing event rule condition's capture descriptor %" PRIu32,
325 i);
326 ret = serialize_event_expr(desc->event_expression, payload);
327 if (ret) {
328 goto end;
329 }
330 }
331
332 end:
333 return ret;
334 }
335
336 static
337 bool capture_descriptors_are_equal(
338 const struct lttng_condition *condition_a,
339 const struct lttng_condition *condition_b)
340 {
341 bool is_equal = true;
342 unsigned int capture_descr_count_a;
343 unsigned int capture_descr_count_b;
344 size_t i;
345 enum lttng_condition_status status;
346
347 status = lttng_condition_event_rule_get_capture_descriptor_count(
348 condition_a, &capture_descr_count_a);
349 if (status != LTTNG_CONDITION_STATUS_OK) {
350 goto not_equal;
351 }
352
353 status = lttng_condition_event_rule_get_capture_descriptor_count(
354 condition_b, &capture_descr_count_b);
355 if (status != LTTNG_CONDITION_STATUS_OK) {
356 goto not_equal;
357 }
358
359 if (capture_descr_count_a != capture_descr_count_b) {
360 goto not_equal;
361 }
362
363 for (i = 0; i < capture_descr_count_a; i++) {
364 const struct lttng_event_expr *expr_a =
365 lttng_condition_event_rule_get_capture_descriptor_at_index(
366 condition_a,
367 i);
368 const struct lttng_event_expr *expr_b =
369 lttng_condition_event_rule_get_capture_descriptor_at_index(
370 condition_b,
371 i);
372
373 if (!lttng_event_expr_is_equal(expr_a, expr_b)) {
374 goto not_equal;
375 }
376 }
377
378 goto end;
379
380 not_equal:
381 is_equal = false;
382
383 end:
384 return is_equal;
385 }
386
387 static bool lttng_condition_event_rule_is_equal(
388 const struct lttng_condition *_a,
389 const struct lttng_condition *_b)
390 {
391 bool is_equal = false;
392 struct lttng_condition_event_rule *a, *b;
393
394 a = container_of(_a, struct lttng_condition_event_rule, parent);
395 b = container_of(_b, struct lttng_condition_event_rule, parent);
396
397 /* Both event rules must be set or both must be unset. */
398 if ((a->rule && !b->rule) || (!a->rule && b->rule)) {
399 WARN("Comparing event_rule conditions with uninitialized rule");
400 goto end;
401 }
402
403 is_equal = lttng_event_rule_is_equal(a->rule, b->rule);
404 if (!is_equal) {
405 goto end;
406 }
407
408 is_equal = capture_descriptors_are_equal(_a, _b);
409
410 end:
411 return is_equal;
412 }
413
414 static void lttng_condition_event_rule_destroy(
415 struct lttng_condition *condition)
416 {
417 struct lttng_condition_event_rule *event_rule;
418
419 event_rule = container_of(
420 condition, struct lttng_condition_event_rule, parent);
421
422 lttng_event_rule_put(event_rule->rule);
423 lttng_dynamic_pointer_array_reset(&event_rule->capture_descriptors);
424 free(event_rule);
425 }
426
427 static
428 void destroy_capture_descriptor(void *ptr)
429 {
430 struct lttng_capture_descriptor *desc =
431 (struct lttng_capture_descriptor *) ptr;
432
433 lttng_event_expr_destroy(desc->event_expression);
434 free(desc->bytecode);
435 free(desc);
436 }
437
438 struct lttng_condition *lttng_condition_event_rule_create(
439 struct lttng_event_rule *rule)
440 {
441 struct lttng_condition *parent = NULL;
442 struct lttng_condition_event_rule *condition = NULL;
443
444 if (!rule) {
445 goto end;
446 }
447
448 condition = zmalloc(sizeof(struct lttng_condition_event_rule));
449 if (!condition) {
450 return NULL;
451 }
452
453 lttng_condition_init(&condition->parent,
454 LTTNG_CONDITION_TYPE_EVENT_RULE_HIT);
455 condition->parent.validate = lttng_condition_event_rule_validate,
456 condition->parent.serialize = lttng_condition_event_rule_serialize,
457 condition->parent.equal = lttng_condition_event_rule_is_equal,
458 condition->parent.destroy = lttng_condition_event_rule_destroy,
459
460 lttng_event_rule_get(rule);
461 condition->rule = rule;
462 rule = NULL;
463
464 lttng_dynamic_pointer_array_init(&condition->capture_descriptors,
465 destroy_capture_descriptor);
466
467 parent = &condition->parent;
468 end:
469 return parent;
470 }
471
472 static
473 uint64_t uint_from_buffer(const struct lttng_buffer_view *view, size_t size,
474 size_t *offset)
475 {
476 uint64_t ret;
477 const struct lttng_buffer_view uint_view =
478 lttng_buffer_view_from_view(view, *offset, size);
479
480 if (!lttng_buffer_view_is_valid(&uint_view)) {
481 ret = UINT64_C(-1);
482 goto end;
483 }
484
485 switch (size) {
486 case 1:
487 ret = (uint64_t) *uint_view.data;
488 break;
489 case sizeof(uint32_t):
490 {
491 uint32_t u32;
492
493 memcpy(&u32, uint_view.data, sizeof(u32));
494 ret = (uint64_t) u32;
495 break;
496 }
497 case sizeof(ret):
498 memcpy(&ret, uint_view.data, sizeof(ret));
499 break;
500 default:
501 abort();
502 }
503
504 *offset += size;
505
506 end:
507 return ret;
508 }
509
510 static
511 const char *str_from_buffer(const struct lttng_buffer_view *view,
512 size_t *offset)
513 {
514 uint64_t len;
515 const char *ret;
516
517 len = uint_from_buffer(view, sizeof(uint32_t), offset);
518 if (len == UINT64_C(-1)) {
519 goto error;
520 }
521
522 ret = &view->data[*offset];
523
524 if (!lttng_buffer_view_contains_string(view, ret, len)) {
525 goto error;
526 }
527
528 *offset += len;
529 goto end;
530
531 error:
532 ret = NULL;
533
534 end:
535 return ret;
536 }
537
538 static
539 struct lttng_event_expr *event_expr_from_payload(
540 struct lttng_payload_view *view, size_t *offset)
541 {
542 struct lttng_event_expr *expr = NULL;
543 const char *str;
544 uint64_t type;
545
546 type = uint_from_buffer(&view->buffer, sizeof(uint8_t), offset);
547 if (type == UINT64_C(-1)) {
548 goto error;
549 }
550
551 switch (type) {
552 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
553 str = str_from_buffer(&view->buffer, offset);
554 if (!str) {
555 goto error;
556 }
557
558 expr = lttng_event_expr_event_payload_field_create(str);
559 break;
560 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
561 str = str_from_buffer(&view->buffer, offset);
562 if (!str) {
563 goto error;
564 }
565
566 expr = lttng_event_expr_channel_context_field_create(str);
567 break;
568 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
569 {
570 const char *provider_name;
571 const char *type_name;
572
573 provider_name = str_from_buffer(&view->buffer, offset);
574 if (!provider_name) {
575 goto error;
576 }
577
578 type_name = str_from_buffer(&view->buffer, offset);
579 if (!type_name) {
580 goto error;
581 }
582
583 expr = lttng_event_expr_app_specific_context_field_create(
584 provider_name, type_name);
585 break;
586 }
587 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
588 {
589 struct lttng_event_expr *array_field_expr;
590 const uint64_t index = uint_from_buffer(
591 &view->buffer, sizeof(uint32_t), offset);
592
593 if (index == UINT64_C(-1)) {
594 goto error;
595 }
596
597 /* Array field expression is the encoded after this. */
598 array_field_expr = event_expr_from_payload(view, offset);
599 if (!array_field_expr) {
600 goto error;
601 }
602
603 /* Move ownership of `array_field_expr` to new expression. */
604 expr = lttng_event_expr_array_field_element_create(
605 array_field_expr, (unsigned int) index);
606 if (!expr) {
607 /* `array_field_expr` not moved: destroy it. */
608 lttng_event_expr_destroy(array_field_expr);
609 }
610
611 break;
612 }
613 default:
614 abort();
615 }
616
617 goto end;
618
619 error:
620 lttng_event_expr_destroy(expr);
621 expr = NULL;
622
623 end:
624 return expr;
625 }
626
627 LTTNG_HIDDEN
628 ssize_t lttng_condition_event_rule_create_from_payload(
629 struct lttng_payload_view *view,
630 struct lttng_condition **_condition)
631 {
632 ssize_t consumed_length;
633 size_t offset = 0;
634 ssize_t event_rule_length;
635 uint32_t i, capture_descr_count;
636 struct lttng_condition *condition = NULL;
637 struct lttng_event_rule *event_rule = NULL;
638
639 if (!view || !_condition) {
640 goto error;
641 }
642
643 /* Struct lttng_event_rule. */
644 {
645 struct lttng_payload_view event_rule_view =
646 lttng_payload_view_from_view(view, offset, -1);
647
648 event_rule_length = lttng_event_rule_create_from_payload(
649 &event_rule_view, &event_rule);
650 }
651
652 if (event_rule_length < 0 || !event_rule) {
653 goto error;
654 }
655
656 /* Create condition (no capture descriptors yet) at this point. */
657 condition = lttng_condition_event_rule_create(event_rule);
658 if (!condition) {
659 goto error;
660 }
661
662
663 /* Capture descriptor count. */
664 assert(event_rule_length >= 0);
665 offset += (size_t) event_rule_length;
666 capture_descr_count = uint_from_buffer(&view->buffer, sizeof(uint32_t), &offset);
667 if (capture_descr_count == UINT32_C(-1)) {
668 goto error;
669 }
670
671 /* Capture descriptors. */
672 for (i = 0; i < capture_descr_count; i++) {
673 enum lttng_condition_status status;
674 struct lttng_event_expr *expr = event_expr_from_payload(
675 view, &offset);
676
677 if (!expr) {
678 goto error;
679 }
680
681 /* Move ownership of `expr` to `condition`. */
682 status = lttng_condition_event_rule_append_capture_descriptor(
683 condition, expr);
684 if (status != LTTNG_CONDITION_STATUS_OK) {
685 /* `expr` not moved: destroy it. */
686 lttng_event_expr_destroy(expr);
687 goto error;
688 }
689 }
690
691 consumed_length = (ssize_t) offset;
692 *_condition = condition;
693 condition = NULL;
694 goto end;
695
696 error:
697 consumed_length = -1;
698
699 end:
700 lttng_event_rule_put(event_rule);
701 lttng_condition_put(condition);
702 return consumed_length;
703 }
704
705 LTTNG_HIDDEN
706 enum lttng_condition_status lttng_condition_event_rule_borrow_rule_mutable(
707 const struct lttng_condition *condition,
708 struct lttng_event_rule **rule)
709 {
710 struct lttng_condition_event_rule *event_rule;
711 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
712
713 if (!condition || !IS_EVENT_RULE_CONDITION(condition) || !rule) {
714 status = LTTNG_CONDITION_STATUS_INVALID;
715 goto end;
716 }
717
718 event_rule = container_of(
719 condition, struct lttng_condition_event_rule, parent);
720 if (!event_rule->rule) {
721 status = LTTNG_CONDITION_STATUS_UNSET;
722 goto end;
723 }
724
725 *rule = event_rule->rule;
726 end:
727 return status;
728 }
729
730 enum lttng_condition_status lttng_condition_event_rule_get_rule(
731 const struct lttng_condition *condition,
732 const struct lttng_event_rule **rule)
733 {
734 struct lttng_event_rule *mutable_rule = NULL;
735 const enum lttng_condition_status status =
736 lttng_condition_event_rule_borrow_rule_mutable(
737 condition, &mutable_rule);
738
739 *rule = mutable_rule;
740 return status;
741 }
742
743 enum lttng_condition_status
744 lttng_condition_event_rule_append_capture_descriptor(
745 struct lttng_condition *condition,
746 struct lttng_event_expr *expr)
747 {
748 int ret;
749 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
750 struct lttng_condition_event_rule *event_rule_cond =
751 container_of(condition,
752 struct lttng_condition_event_rule, parent);
753 struct lttng_capture_descriptor *descriptor = NULL;
754
755 /* Only accept l-values. */
756 if (!condition || !IS_EVENT_RULE_CONDITION(condition) || !expr ||
757 !lttng_event_expr_is_lvalue(expr)) {
758 status = LTTNG_CONDITION_STATUS_INVALID;
759 goto end;
760 }
761
762 descriptor = malloc(sizeof(*descriptor));
763 if (descriptor == NULL) {
764 status = LTTNG_CONDITION_STATUS_ERROR;
765 goto end;
766 }
767
768 descriptor->event_expression = expr;
769 descriptor->bytecode = NULL;
770
771 ret = lttng_dynamic_pointer_array_add_pointer(
772 &event_rule_cond->capture_descriptors, descriptor);
773 if (ret) {
774 status = LTTNG_CONDITION_STATUS_ERROR;
775 goto end;
776 }
777
778 /* Ownership is transfered to the internal capture_descriptors array */
779 descriptor = NULL;
780 end:
781 free(descriptor);
782 return status;
783 }
784
785 enum lttng_condition_status
786 lttng_condition_event_rule_get_capture_descriptor_count(
787 const struct lttng_condition *condition, unsigned int *count)
788 {
789 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
790 const struct lttng_condition_event_rule *event_rule_cond =
791 container_of(condition,
792 const struct lttng_condition_event_rule,
793 parent);
794
795 if (!condition || !IS_EVENT_RULE_CONDITION(condition) || !count) {
796 status = LTTNG_CONDITION_STATUS_INVALID;
797 goto end;
798 }
799
800 *count = lttng_dynamic_pointer_array_get_count(
801 &event_rule_cond->capture_descriptors);
802
803 end:
804 return status;
805 }
806
807 const struct lttng_event_expr *
808 lttng_condition_event_rule_get_capture_descriptor_at_index(
809 const struct lttng_condition *condition, unsigned int index)
810 {
811 const struct lttng_event_expr *expr = NULL;
812 const struct lttng_capture_descriptor *desc = NULL;
813
814 desc = lttng_condition_event_rule_get_internal_capture_descriptor_at_index(
815 condition, index);
816 if (desc == NULL) {
817 goto end;
818 }
819 expr = desc->event_expression;
820
821 end:
822 return expr;
823 }
824
825 LTTNG_HIDDEN
826 ssize_t lttng_evaluation_event_rule_create_from_payload(
827 const struct lttng_condition_event_rule *condition,
828 struct lttng_payload_view *view,
829 struct lttng_evaluation **_evaluation)
830 {
831 ssize_t ret, offset = 0;
832 const char *trigger_name;
833 struct lttng_evaluation *evaluation = NULL;
834 const struct lttng_evaluation_event_rule_comm *header;
835 const struct lttng_payload_view header_view =
836 lttng_payload_view_from_view(
837 view, 0, sizeof(*header));
838 uint32_t capture_payload_size;
839 const char *capture_payload = NULL;
840
841 if (!_evaluation) {
842 ret = -1;
843 goto error;
844 }
845
846 if (!lttng_payload_view_is_valid(&header_view)) {
847 ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain header");
848 ret = -1;
849 goto error;
850 }
851
852 header = (typeof(header)) header_view.buffer.data;
853
854 /* Map the originating trigger's name. */
855 offset += sizeof(*header);
856 {
857 const struct lttng_payload_view current_view =
858 lttng_payload_view_from_view(view, offset,
859 header->trigger_name_length);
860
861 if (!lttng_payload_view_is_valid(&current_view)) {
862 ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain trigger name");
863 ret = -1;
864 goto error;
865 }
866
867 trigger_name = current_view.buffer.data;
868 if (!lttng_buffer_view_contains_string(&current_view.buffer,
869 trigger_name, header->trigger_name_length)) {
870 ERR("Failed to initialize from malformed event rule evaluation: invalid trigger name");
871 ret = -1;
872 goto error;
873 }
874 }
875
876 offset += header->trigger_name_length;
877 {
878 const struct lttng_payload_view current_view =
879 lttng_payload_view_from_view(view, offset, -1);
880
881 if (current_view.buffer.size < sizeof(capture_payload_size)) {
882 ret = -1;
883 goto error;
884 }
885
886 memcpy(&capture_payload_size, current_view.buffer.data,
887 sizeof(capture_payload_size));
888 }
889 offset += sizeof(capture_payload_size);
890
891 if (capture_payload_size > 0) {
892 const struct lttng_payload_view current_view =
893 lttng_payload_view_from_view(view, offset, -1);
894
895 if (current_view.buffer.size < capture_payload_size) {
896 ret = -1;
897 goto error;
898 }
899
900 capture_payload = current_view.buffer.data;
901 }
902
903 evaluation = lttng_evaluation_event_rule_create(condition, trigger_name,
904 capture_payload, capture_payload_size, true);
905 if (!evaluation) {
906 ret = -1;
907 goto error;
908 }
909
910 offset += capture_payload_size;
911 *_evaluation = evaluation;
912 evaluation = NULL;
913 ret = offset;
914
915 error:
916 lttng_evaluation_destroy(evaluation);
917 return ret;
918 }
919
920 static int lttng_evaluation_event_rule_serialize(
921 const struct lttng_evaluation *evaluation,
922 struct lttng_payload *payload)
923 {
924 int ret = 0;
925 struct lttng_evaluation_event_rule *hit;
926 struct lttng_evaluation_event_rule_comm comm;
927 uint32_t capture_payload_size;
928
929 hit = container_of(
930 evaluation, struct lttng_evaluation_event_rule, parent);
931
932 assert(hit->name);
933 comm.trigger_name_length = strlen(hit->name) + 1;
934
935 ret = lttng_dynamic_buffer_append(
936 &payload->buffer, &comm, sizeof(comm));
937 if (ret) {
938 goto end;
939 }
940
941 ret = lttng_dynamic_buffer_append(
942 &payload->buffer, hit->name, comm.trigger_name_length);
943 if (ret) {
944 goto end;
945 }
946
947 capture_payload_size = (uint32_t) hit->capture_payload.size;
948 ret = lttng_dynamic_buffer_append(&payload->buffer, &capture_payload_size,
949 sizeof(capture_payload_size));
950 if (ret) {
951 goto end;
952 }
953
954 ret = lttng_dynamic_buffer_append(&payload->buffer, hit->capture_payload.data,
955 hit->capture_payload.size);
956 if (ret) {
957 goto end;
958 }
959
960 end:
961 return ret;
962 }
963
964 static
965 bool msgpack_str_is_equal(const struct msgpack_object *obj, const char *str)
966 {
967 bool is_equal = true;
968
969 assert(obj->type == MSGPACK_OBJECT_STR);
970
971 if (obj->via.str.size != strlen(str)) {
972 is_equal = false;
973 goto end;
974 }
975
976 if (strncmp(obj->via.str.ptr, str, obj->via.str.size) != 0) {
977 is_equal = false;
978 goto end;
979 }
980
981 end:
982 return is_equal;
983 }
984
985 static
986 const msgpack_object *get_msgpack_map_obj(const struct msgpack_object *map_obj,
987 const char *name)
988 {
989 const msgpack_object *ret = NULL;
990 size_t i;
991
992 assert(map_obj->type == MSGPACK_OBJECT_MAP);
993
994 for (i = 0; i < map_obj->via.map.size; i++) {
995 const struct msgpack_object_kv *kv = &map_obj->via.map.ptr[i];
996
997 assert(kv->key.type == MSGPACK_OBJECT_STR);
998
999 if (msgpack_str_is_equal(&kv->key, name)) {
1000 ret = &kv->val;
1001 goto end;
1002 }
1003 }
1004
1005 end:
1006 return ret;
1007 }
1008
1009 static void lttng_evaluation_event_rule_destroy(
1010 struct lttng_evaluation *evaluation)
1011 {
1012 struct lttng_evaluation_event_rule *hit;
1013
1014 hit = container_of(
1015 evaluation, struct lttng_evaluation_event_rule, parent);
1016 free(hit->name);
1017 lttng_dynamic_buffer_reset(&hit->capture_payload);
1018 lttng_event_field_value_destroy(hit->captured_values);
1019 free(hit);
1020 }
1021
1022 static
1023 int event_field_value_from_obj(const msgpack_object *obj,
1024 struct lttng_event_field_value **field_val)
1025 {
1026 int ret = 0;
1027
1028 assert(obj);
1029 assert(field_val);
1030
1031 switch (obj->type) {
1032 case MSGPACK_OBJECT_NIL:
1033 /* Unavailable. */
1034 *field_val = NULL;
1035 goto end;
1036 case MSGPACK_OBJECT_POSITIVE_INTEGER:
1037 *field_val = lttng_event_field_value_uint_create(
1038 obj->via.u64);
1039 break;
1040 case MSGPACK_OBJECT_NEGATIVE_INTEGER:
1041 *field_val = lttng_event_field_value_int_create(
1042 obj->via.i64);
1043 break;
1044 case MSGPACK_OBJECT_FLOAT32:
1045 case MSGPACK_OBJECT_FLOAT64:
1046 *field_val = lttng_event_field_value_real_create(
1047 obj->via.f64);
1048 break;
1049 case MSGPACK_OBJECT_STR:
1050 *field_val = lttng_event_field_value_string_create_with_size(
1051 obj->via.str.ptr, obj->via.str.size);
1052 break;
1053 case MSGPACK_OBJECT_ARRAY:
1054 {
1055 size_t i;
1056
1057 *field_val = lttng_event_field_value_array_create();
1058 if (!*field_val) {
1059 goto error;
1060 }
1061
1062 for (i = 0; i < obj->via.array.size; i++) {
1063 const msgpack_object *elem_obj = &obj->via.array.ptr[i];
1064 struct lttng_event_field_value *elem_field_val;
1065
1066 ret = event_field_value_from_obj(elem_obj,
1067 &elem_field_val);
1068 if (ret) {
1069 goto error;
1070 }
1071
1072 if (elem_field_val) {
1073 ret = lttng_event_field_value_array_append(
1074 *field_val, elem_field_val);
1075 } else {
1076 ret = lttng_event_field_value_array_append_unavailable(
1077 *field_val);
1078 }
1079
1080 if (ret) {
1081 lttng_event_field_value_destroy(elem_field_val);
1082 goto error;
1083 }
1084 }
1085
1086 break;
1087 }
1088 case MSGPACK_OBJECT_MAP:
1089 {
1090 /*
1091 * As of this version, the only valid map object is
1092 * for an enumeration value, for example:
1093 *
1094 * type: enum
1095 * value: 177
1096 * labels:
1097 * - Labatt 50
1098 * - Molson Dry
1099 * - Carling Black Label
1100 */
1101 const msgpack_object *inner_obj;
1102 size_t label_i;
1103
1104 inner_obj = get_msgpack_map_obj(obj, "type");
1105 if (!inner_obj) {
1106 ERR("Missing `type` entry in map object");
1107 goto error;
1108 }
1109
1110 if (inner_obj->type != MSGPACK_OBJECT_STR) {
1111 ERR("Map object's `type` entry is not a string: type = %s",
1112 msgpack_object_type_str(inner_obj->type));
1113 goto error;
1114 }
1115
1116 if (!msgpack_str_is_equal(inner_obj, "enum")) {
1117 ERR("Map object's `type` entry: expecting `enum`");
1118 goto error;
1119 }
1120
1121 inner_obj = get_msgpack_map_obj(obj, "value");
1122 if (!inner_obj) {
1123 ERR("Missing `value` entry in map object");
1124 goto error;
1125 }
1126
1127 if (inner_obj->type == MSGPACK_OBJECT_POSITIVE_INTEGER) {
1128 *field_val = lttng_event_field_value_enum_uint_create(
1129 inner_obj->via.u64);
1130 } else if (inner_obj->type == MSGPACK_OBJECT_NEGATIVE_INTEGER) {
1131 *field_val = lttng_event_field_value_enum_int_create(
1132 inner_obj->via.i64);
1133 } else {
1134 ERR("Map object's `value` entry is not an integer: type = %s",
1135 msgpack_object_type_str(inner_obj->type));
1136 goto error;
1137 }
1138
1139 if (!*field_val) {
1140 goto error;
1141 }
1142
1143 inner_obj = get_msgpack_map_obj(obj, "labels");
1144 if (!inner_obj) {
1145 /* No labels */
1146 goto end;
1147 }
1148
1149 if (inner_obj->type != MSGPACK_OBJECT_ARRAY) {
1150 ERR("Map object's `labels` entry is not an array: type = %s",
1151 msgpack_object_type_str(inner_obj->type));
1152 goto error;
1153 }
1154
1155 for (label_i = 0; label_i < inner_obj->via.array.size;
1156 label_i++) {
1157 int iret;
1158 const msgpack_object *elem_obj =
1159 &inner_obj->via.array.ptr[label_i];
1160
1161 if (elem_obj->type != MSGPACK_OBJECT_STR) {
1162 ERR("Map object's `labels` entry's type is not a string: type = %s",
1163 msgpack_object_type_str(elem_obj->type));
1164 goto error;
1165 }
1166
1167 iret = lttng_event_field_value_enum_append_label_with_size(
1168 *field_val, elem_obj->via.str.ptr,
1169 elem_obj->via.str.size);
1170 if (iret) {
1171 goto error;
1172 }
1173 }
1174
1175 break;
1176 }
1177 default:
1178 ERR("Unexpected object type: type = %s",
1179 msgpack_object_type_str(obj->type));
1180 goto error;
1181 }
1182
1183 if (!*field_val) {
1184 goto error;
1185 }
1186
1187 goto end;
1188
1189 error:
1190 lttng_event_field_value_destroy(*field_val);
1191 *field_val = NULL;
1192 ret = -1;
1193
1194 end:
1195 return ret;
1196 }
1197
1198 static
1199 struct lttng_event_field_value *event_field_value_from_capture_payload(
1200 const struct lttng_condition_event_rule *condition,
1201 const char *capture_payload, size_t capture_payload_size)
1202 {
1203 struct lttng_event_field_value *ret = NULL;
1204 msgpack_unpacked unpacked;
1205 msgpack_unpack_return unpack_return;
1206 const msgpack_object *root_obj;
1207 const msgpack_object_array *root_array_obj;
1208 size_t i;
1209 size_t count;
1210
1211 assert(condition);
1212 assert(capture_payload);
1213
1214 /* Initialize value. */
1215 msgpack_unpacked_init(&unpacked);
1216
1217 /* Decode. */
1218 unpack_return = msgpack_unpack_next(&unpacked, capture_payload,
1219 capture_payload_size, NULL);
1220 if (unpack_return != MSGPACK_UNPACK_SUCCESS) {
1221 ERR("msgpack_unpack_next() failed to decode the "
1222 "MessagePack-encoded capture payload: "
1223 "size = %zu, ret = %d",
1224 capture_payload_size, unpack_return);
1225 goto error;
1226 }
1227
1228 /* Get root array. */
1229 root_obj = &unpacked.data;
1230
1231 if (root_obj->type != MSGPACK_OBJECT_ARRAY) {
1232 ERR("Expecting an array as the root object: type = %s",
1233 msgpack_object_type_str(root_obj->type));
1234 goto error;
1235 }
1236
1237 root_array_obj = &root_obj->via.array;
1238
1239 /* Create an empty root array event field value. */
1240 ret = lttng_event_field_value_array_create();
1241 if (!ret) {
1242 goto error;
1243 }
1244
1245 /*
1246 * For each capture descriptor in the condition object:
1247 *
1248 * 1. Get its corresponding captured field value MessagePack
1249 * object.
1250 *
1251 * 2. Create a corresponding event field value.
1252 *
1253 * 3. Append it to `ret` (the root array event field value).
1254 */
1255 count = lttng_dynamic_pointer_array_get_count(
1256 &condition->capture_descriptors);
1257 assert(count > 0);
1258
1259 for (i = 0; i < count; i++) {
1260 const struct lttng_capture_descriptor *capture_descriptor =
1261 lttng_condition_event_rule_get_internal_capture_descriptor_at_index(
1262 &condition->parent, i);
1263 const msgpack_object *elem_obj;
1264 struct lttng_event_field_value *elem_field_val;
1265 int iret;
1266
1267 assert(capture_descriptor);
1268
1269 elem_obj = &root_array_obj->ptr[i];
1270 iret = event_field_value_from_obj(elem_obj,
1271 &elem_field_val);
1272 if (iret) {
1273 goto error;
1274 }
1275
1276 if (elem_field_val) {
1277 iret = lttng_event_field_value_array_append(ret,
1278 elem_field_val);
1279 } else {
1280 iret = lttng_event_field_value_array_append_unavailable(
1281 ret);
1282 }
1283
1284 if (iret) {
1285 lttng_event_field_value_destroy(elem_field_val);
1286 goto error;
1287 }
1288 }
1289
1290 goto end;
1291
1292 error:
1293 lttng_event_field_value_destroy(ret);
1294 ret = NULL;
1295
1296 end:
1297 msgpack_unpacked_destroy(&unpacked);
1298 return ret;
1299 }
1300
1301 LTTNG_HIDDEN
1302 struct lttng_evaluation *lttng_evaluation_event_rule_create(
1303 const struct lttng_condition_event_rule *condition,
1304 const char *trigger_name,
1305 const char *capture_payload, size_t capture_payload_size,
1306 bool decode_capture_payload)
1307 {
1308 struct lttng_evaluation_event_rule *hit;
1309 struct lttng_evaluation *evaluation = NULL;
1310
1311 hit = zmalloc(sizeof(struct lttng_evaluation_event_rule));
1312 if (!hit) {
1313 goto error;
1314 }
1315
1316 hit->name = strdup(trigger_name);
1317 if (!hit->name) {
1318 goto error;
1319 }
1320
1321 lttng_dynamic_buffer_init(&hit->capture_payload);
1322
1323 if (capture_payload) {
1324 const int ret = lttng_dynamic_buffer_append(
1325 &hit->capture_payload, capture_payload,
1326 capture_payload_size);
1327 if (ret) {
1328 ERR("Failed to initialize capture payload of event rule evaluation");
1329 goto error;
1330 }
1331
1332 if (decode_capture_payload) {
1333 hit->captured_values =
1334 event_field_value_from_capture_payload(
1335 condition,
1336 capture_payload,
1337 capture_payload_size);
1338 if (!hit->captured_values) {
1339 ERR("Failed to decode the capture payload: size = %zu",
1340 capture_payload_size);
1341 goto error;
1342 }
1343 }
1344 }
1345
1346 hit->parent.type = LTTNG_CONDITION_TYPE_EVENT_RULE_HIT;
1347 hit->parent.serialize = lttng_evaluation_event_rule_serialize;
1348 hit->parent.destroy = lttng_evaluation_event_rule_destroy;
1349
1350 evaluation = &hit->parent;
1351 hit = NULL;
1352
1353 error:
1354 if (hit) {
1355 lttng_evaluation_event_rule_destroy(&hit->parent);
1356 }
1357
1358 return evaluation;
1359 }
1360
1361 enum lttng_evaluation_status lttng_evaluation_event_rule_get_captured_values(
1362 const struct lttng_evaluation *evaluation,
1363 const struct lttng_event_field_value **field_val)
1364 {
1365 struct lttng_evaluation_event_rule *hit;
1366 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
1367
1368 if (!evaluation || !is_event_rule_evaluation(evaluation) ||
1369 !field_val) {
1370 status = LTTNG_EVALUATION_STATUS_INVALID;
1371 goto end;
1372 }
1373
1374 hit = container_of(evaluation, struct lttng_evaluation_event_rule,
1375 parent);
1376 if (!hit->captured_values) {
1377 status = LTTNG_EVALUATION_STATUS_INVALID;
1378 goto end;
1379 }
1380
1381 *field_val = hit->captured_values;
1382
1383 end:
1384 return status;
1385 }
1386
1387 enum lttng_evaluation_status lttng_evaluation_event_rule_get_trigger_name(
1388 const struct lttng_evaluation *evaluation, const char **name)
1389 {
1390 struct lttng_evaluation_event_rule *hit;
1391 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
1392
1393 if (!evaluation || !is_event_rule_evaluation(evaluation) || !name) {
1394 status = LTTNG_EVALUATION_STATUS_INVALID;
1395 goto end;
1396 }
1397
1398 hit = container_of(
1399 evaluation, struct lttng_evaluation_event_rule, parent);
1400 *name = hit->name;
1401 end:
1402 return status;
1403 }
1404
1405 LTTNG_HIDDEN
1406 enum lttng_error_code
1407 lttng_condition_event_rule_generate_capture_descriptor_bytecode(
1408 struct lttng_condition *condition)
1409 {
1410 enum lttng_error_code ret;
1411 enum lttng_condition_status status;
1412 unsigned int capture_count, i;
1413
1414 if (!condition || !IS_EVENT_RULE_CONDITION(condition)) {
1415 ret = LTTNG_ERR_FATAL;
1416 goto end;
1417 }
1418
1419 status = lttng_condition_event_rule_get_capture_descriptor_count(
1420 condition, &capture_count);
1421 if (status != LTTNG_CONDITION_STATUS_OK) {
1422 ret = LTTNG_ERR_FATAL;
1423 goto end;
1424 }
1425
1426 for (i = 0; i < capture_count; i++) {
1427 struct lttng_capture_descriptor *local_capture_desc =
1428 lttng_condition_event_rule_get_internal_capture_descriptor_at_index(
1429 condition, i);
1430
1431 if (local_capture_desc == NULL) {
1432 ret = LTTNG_ERR_FATAL;
1433 goto end;
1434 }
1435
1436 /* Generate the bytecode. */
1437 status = lttng_event_expr_to_bytecode(
1438 local_capture_desc->event_expression,
1439 &local_capture_desc->bytecode);
1440 if (status < 0 || local_capture_desc->bytecode == NULL) {
1441 ret = LTTNG_ERR_INVALID_CAPTURE_EXPRESSION;
1442 goto end;
1443 }
1444 }
1445
1446 /* Everything went better than expected */
1447 ret = LTTNG_OK;
1448
1449 end:
1450 return ret;
1451 }
1452
1453 LTTNG_HIDDEN
1454 const struct lttng_bytecode *
1455 lttng_condition_event_rule_get_capture_bytecode_at_index(
1456 const struct lttng_condition *condition, unsigned int index)
1457 {
1458 const struct lttng_condition_event_rule *event_rule_cond =
1459 container_of(condition,
1460 const struct lttng_condition_event_rule,
1461 parent);
1462 struct lttng_capture_descriptor *desc = NULL;
1463 struct lttng_bytecode *bytecode = NULL;
1464 unsigned int count;
1465 enum lttng_condition_status status;
1466
1467 if (!condition || !IS_EVENT_RULE_CONDITION(condition)) {
1468 goto end;
1469 }
1470
1471 status = lttng_condition_event_rule_get_capture_descriptor_count(
1472 condition, &count);
1473 if (status != LTTNG_CONDITION_STATUS_OK) {
1474 goto end;
1475 }
1476
1477 if (index >= count) {
1478 goto end;
1479 }
1480
1481 desc = lttng_dynamic_pointer_array_get_pointer(
1482 &event_rule_cond->capture_descriptors, index);
1483 if (desc == NULL) {
1484 goto end;
1485 }
1486
1487 bytecode = desc->bytecode;
1488 end:
1489 return bytecode;
1490 }
This page took 0.063477 seconds and 3 git commands to generate.