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