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