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