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