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