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