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