Fix: action error query: leak of action path
[lttng-tools.git] / src / common / error-query.cpp
1 /*
2 * error-query.c
3 *
4 * Copyright (C) 2021 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 *
6 * SPDX-License-Identifier: GPL-2.1-only
7 *
8 */
9
10 #include <common/dynamic-array.hpp>
11 #include <common/error.hpp>
12 #include <common/macros.hpp>
13 #include <common/mi-lttng.hpp>
14 #include <common/sessiond-comm/sessiond-comm.hpp>
15 #include <lttng/action/action-internal.hpp>
16 #include <lttng/action/list-internal.hpp>
17 #include <lttng/action/path-internal.hpp>
18 #include <lttng/error-query-internal.hpp>
19 #include <lttng/error-query.h>
20 #include <lttng/trigger/trigger-internal.hpp>
21 #include <stddef.h>
22
23 struct lttng_error_query {
24 enum lttng_error_query_target_type target_type;
25 };
26
27 struct lttng_error_query_result {
28 enum lttng_error_query_result_type type;
29 char *name;
30 char *description;
31 };
32
33 struct lttng_error_query_results {
34 struct lttng_dynamic_pointer_array results;
35 };
36
37 namespace {
38 struct lttng_error_query_comm {
39 /* enum lttng_error_query_target_type */
40 int8_t target_type;
41 /* Target-specific payload. */
42 char payload[];
43 };
44
45 struct lttng_error_query_trigger {
46 struct lttng_error_query parent;
47 /* Mutable only because of the reference count. */
48 struct lttng_trigger *trigger;
49 };
50
51 struct lttng_error_query_condition {
52 struct lttng_error_query parent;
53 /* Mutable only because of the reference count. */
54 struct lttng_trigger *trigger;
55 };
56
57 struct lttng_error_query_action {
58 struct lttng_error_query parent;
59 /* Mutable only because of the reference count. */
60 struct lttng_trigger *trigger;
61 struct lttng_action_path *action_path;
62 };
63
64 struct lttng_error_query_result_comm {
65 /* enum lttng_error_query_result_type */
66 uint8_t type;
67 /* Length of name (including null-terminator). */
68 uint32_t name_len;
69 /* Length of description (including null-terminator). */
70 uint32_t description_len;
71 /* Name, description, and type-specific payload follow. */
72 char payload[];
73 } LTTNG_PACKED;
74
75 struct lttng_error_query_result_counter_comm {
76 uint64_t value;
77 } LTTNG_PACKED;
78
79 struct lttng_error_query_result_counter {
80 struct lttng_error_query_result parent;
81 uint64_t value;
82 };
83
84 struct lttng_error_query_results_comm {
85 uint32_t count;
86 /* `count` instances of `struct lttng_error_query_result` follow. */
87 char payload[];
88 } LTTNG_PACKED;
89 } /* namespace */
90
91 static
92 enum lttng_error_code lttng_error_query_result_mi_serialize(
93 const struct lttng_error_query_result *result,
94 struct mi_writer *writer);
95
96 static
97 enum lttng_error_code lttng_error_query_result_counter_mi_serialize(
98 const struct lttng_error_query_result *result,
99 struct mi_writer *writer);
100
101 struct lttng_error_query *lttng_error_query_trigger_create(
102 const struct lttng_trigger *trigger)
103 {
104 struct lttng_error_query_trigger *query = NULL;
105 struct lttng_trigger *trigger_copy = NULL;
106
107 if (!trigger) {
108 goto end;
109 }
110
111 trigger_copy = lttng_trigger_copy(trigger);
112 if (!trigger_copy) {
113 goto end;
114 }
115
116 query = zmalloc<lttng_error_query_trigger>();
117 if (!query) {
118 PERROR("Failed to allocate trigger error query");
119 goto error;
120 }
121
122 query->parent.target_type = LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER;
123 query->trigger = trigger_copy;
124 trigger_copy = NULL;
125
126 error:
127 lttng_trigger_put(trigger_copy);
128 end:
129 return query ? &query->parent : NULL;
130 }
131
132 struct lttng_error_query *lttng_error_query_condition_create(
133 const struct lttng_trigger *trigger)
134 {
135 struct lttng_error_query_condition *query = NULL;
136 struct lttng_trigger *trigger_copy = NULL;
137
138 if (!trigger) {
139 goto end;
140 }
141
142 trigger_copy = lttng_trigger_copy(trigger);
143 if (!trigger_copy) {
144 goto end;
145 }
146
147 query = zmalloc<lttng_error_query_condition>();
148 if (!query) {
149 PERROR("Failed to allocate condition error query");
150 goto error;
151 }
152
153 query->parent.target_type = LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION;
154 query->trigger = trigger_copy;
155 trigger_copy = NULL;
156
157 error:
158 lttng_trigger_put(trigger_copy);
159 end:
160 return query ? &query->parent : NULL;
161 }
162
163 static
164 struct lttng_action *get_trigger_action_from_path(
165 struct lttng_trigger *trigger,
166 const struct lttng_action_path *action_path)
167 {
168 size_t index_count, i;
169 enum lttng_action_path_status path_status;
170 struct lttng_action *current_action = NULL;
171
172 path_status = lttng_action_path_get_index_count(
173 action_path, &index_count);
174 if (path_status != LTTNG_ACTION_PATH_STATUS_OK) {
175 goto end;
176 }
177
178 current_action = lttng_trigger_get_action(trigger);
179 for (i = 0; i < index_count; i++) {
180 uint64_t path_index;
181
182 path_status = lttng_action_path_get_index_at_index(
183 action_path, i, &path_index);
184 current_action = lttng_action_list_borrow_mutable_at_index(
185 current_action, path_index);
186 if (!current_action) {
187 /* Invalid action path. */
188 goto end;
189 }
190 }
191
192 end:
193 return current_action;
194 }
195
196 static
197 bool is_valid_action_path(const struct lttng_trigger *trigger,
198 const struct lttng_action_path *action_path)
199 {
200 /*
201 * While 'trigger's constness is casted-away, the trigger and resulting
202 * action are not modified; we merely check for the action's existence.
203 */
204 return !!get_trigger_action_from_path(
205 (struct lttng_trigger *) trigger, action_path);
206 }
207
208 struct lttng_error_query *lttng_error_query_action_create(
209 const struct lttng_trigger *trigger,
210 const struct lttng_action_path *action_path)
211 {
212 struct lttng_error_query_action *query = NULL;
213 struct lttng_trigger *trigger_copy = NULL;
214 int ret_copy;
215
216 if (!trigger || !action_path ||
217 !is_valid_action_path(trigger, action_path)) {
218 goto end;
219 }
220
221 trigger_copy = lttng_trigger_copy(trigger);
222 if (!trigger_copy) {
223 goto end;
224 }
225
226 query = zmalloc<lttng_error_query_action>();
227 if (!query) {
228 PERROR("Failed to allocate action error query");
229 goto error;
230 }
231
232 ret_copy = lttng_action_path_copy(action_path, &query->action_path);
233 if (ret_copy) {
234 goto error;
235 }
236
237 query->parent.target_type = LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION;
238 query->trigger = trigger_copy;
239 trigger_copy = NULL;
240 goto end;
241
242 error:
243 lttng_trigger_put(trigger_copy);
244 lttng_error_query_destroy(query ? &query->parent : NULL);
245 end:
246 return query ? &query->parent : NULL;
247 }
248
249 void lttng_error_query_destroy(struct lttng_error_query *query)
250 {
251 if (!query) {
252 return;
253 }
254
255 switch (query->target_type) {
256 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER:
257 {
258 struct lttng_error_query_trigger *trigger_query =
259 container_of(query, typeof(*trigger_query),
260 parent);
261
262 lttng_trigger_put(trigger_query->trigger);
263 free(trigger_query);
264 break;
265 }
266 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION:
267 {
268 struct lttng_error_query_condition *condition_query =
269 container_of(query, typeof(*condition_query),
270 parent);
271
272 lttng_trigger_put(condition_query->trigger);
273 free(condition_query);
274 break;
275 }
276 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION:
277 {
278 struct lttng_error_query_action *action_query =
279 container_of(query, typeof(*action_query),
280 parent);
281
282 lttng_trigger_put(action_query->trigger);
283 lttng_action_path_destroy(action_query->action_path);
284 free(action_query);
285 break;
286 }
287 default:
288 abort();
289 }
290 }
291
292 static
293 int lttng_error_query_result_counter_serialize(
294 const struct lttng_error_query_result *result,
295 struct lttng_payload *payload)
296 {
297 const struct lttng_error_query_result_counter *counter_result;
298
299 LTTNG_ASSERT(result->type == LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER);
300 counter_result = container_of(result, typeof(*counter_result), parent);
301
302 lttng_error_query_result_counter_comm comm = {
303 .value = counter_result->value,
304 };
305
306 return lttng_dynamic_buffer_append(&payload->buffer,
307 &comm,
308 sizeof(struct lttng_error_query_result_counter_comm));
309 }
310
311 int lttng_error_query_result_serialize(
312 const struct lttng_error_query_result *result,
313 struct lttng_payload *payload)
314 {
315 int ret;
316 struct lttng_error_query_result_comm header = {
317 .type = (uint8_t) result->type,
318 .name_len = (typeof(header.name_len)) strlen(result->name) + 1,
319 .description_len = (typeof(header.name_len)) strlen(result->description) + 1,
320 };
321
322 /* Header. */
323 ret = lttng_dynamic_buffer_append(
324 &payload->buffer, &header, sizeof(header));
325 if (ret) {
326 ERR("Failed to append error query result communication header to payload");
327 goto end;
328 }
329
330 /* Name. */
331 ret = lttng_dynamic_buffer_append(
332 &payload->buffer, result->name, header.name_len);
333 if (ret) {
334 ERR("Failed to append error query result name to payload");
335 goto end;
336 }
337
338 /* Description. */
339 ret = lttng_dynamic_buffer_append(&payload->buffer, result->description,
340 header.description_len);
341 if (ret) {
342 ERR("Failed to append error query result description to payload");
343 goto end;
344 }
345
346 /* Type-specific payload. */
347 switch (result->type) {
348 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER:
349 ret = lttng_error_query_result_counter_serialize(
350 result, payload);
351 if (ret) {
352 ERR("Failed to serialize counter error query result");
353 goto end;
354 }
355 break;
356 default:
357 abort();
358 }
359
360 end:
361 return ret;
362 }
363
364 static
365 int lttng_error_query_result_init(
366 struct lttng_error_query_result *result,
367 enum lttng_error_query_result_type result_type,
368 const char *name,
369 const char *description)
370 {
371 int ret;
372
373 LTTNG_ASSERT(name);
374 LTTNG_ASSERT(description);
375
376 result->type = result_type;
377
378 result->name = strdup(name);
379 if (!result->name) {
380 PERROR("Failed to copy error query result name");
381 ret = -1;
382 goto end;
383 }
384
385 result->description = strdup(description);
386 if (!result->description) {
387 PERROR("Failed to copy error query result description");
388 ret = -1;
389 goto end;
390 }
391
392 ret = 0;
393 end:
394 return ret;
395 }
396
397 void lttng_error_query_result_destroy(struct lttng_error_query_result *counter)
398 {
399 if (!counter) {
400 return;
401 }
402
403 switch (counter->type) {
404 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER:
405 /* Nothing to tear down. */
406 break;
407 default:
408 abort();
409 }
410
411 free(counter->name);
412 free(counter->description);
413 free(counter);
414 }
415
416 struct lttng_error_query_result *
417 lttng_error_query_result_counter_create(
418 const char *name, const char *description, uint64_t value)
419 {
420 int init_ret;
421 struct lttng_error_query_result_counter *counter;
422
423 counter = zmalloc<lttng_error_query_result_counter>();
424 if (!counter) {
425 PERROR("Failed to allocate error query counter result");
426 goto end;
427 }
428
429 init_ret = lttng_error_query_result_init(&counter->parent,
430 LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER, name,
431 description);
432 if (init_ret) {
433 goto error;
434 }
435
436 counter->value = value;
437 goto end;
438 error:
439 lttng_error_query_result_destroy(&counter->parent);
440 end:
441 return counter ? &counter->parent : NULL;
442 }
443
444 static
445 void destroy_result(void *ptr)
446 {
447 struct lttng_error_query_result *result = (typeof(result)) ptr;
448
449 lttng_error_query_result_destroy(result);
450 }
451
452 struct lttng_error_query_results *lttng_error_query_results_create(void)
453 {
454 struct lttng_error_query_results *set = zmalloc<lttng_error_query_results>();
455
456 if (!set) {
457 PERROR("Failed to allocate an error query result set");
458 goto end;
459 }
460
461 lttng_dynamic_pointer_array_init(&set->results, destroy_result);
462 end:
463 return set;
464 }
465
466 int lttng_error_query_results_add_result(
467 struct lttng_error_query_results *results,
468 struct lttng_error_query_result *result)
469 {
470 return lttng_dynamic_pointer_array_add_pointer(
471 &results->results, result);
472 }
473
474 ssize_t lttng_error_query_result_create_from_payload(
475 struct lttng_payload_view *view,
476 struct lttng_error_query_result **result)
477 {
478 ssize_t used_size = 0;
479 struct lttng_error_query_result_comm *header;
480 struct lttng_payload_view header_view =
481 lttng_payload_view_from_view(view, 0, sizeof(*header));
482 const char *name;
483 const char *description;
484
485 if (!lttng_payload_view_is_valid(&header_view)) {
486 used_size = -1;
487 goto end;
488 }
489
490 header = (typeof(header)) header_view.buffer.data;
491 used_size += sizeof(*header);
492
493 {
494 struct lttng_payload_view name_view =
495 lttng_payload_view_from_view(view, used_size,
496 header->name_len);
497
498 if (!lttng_payload_view_is_valid(&name_view) ||
499 !lttng_buffer_view_contains_string(
500 &name_view.buffer,
501 name_view.buffer.data,
502 header->name_len)) {
503 used_size = -1;
504 goto end;
505 }
506
507 name = name_view.buffer.data;
508 used_size += header->name_len;
509 }
510
511 {
512 struct lttng_payload_view description_view =
513 lttng_payload_view_from_view(view, used_size,
514 header->description_len);
515
516 if (!lttng_payload_view_is_valid(&description_view) ||
517 !lttng_buffer_view_contains_string(
518 &description_view.buffer,
519 description_view.buffer.data,
520 header->description_len)) {
521 used_size = -1;
522 goto end;
523 }
524
525 description = description_view.buffer.data;
526 used_size += header->description_len;
527 }
528
529 switch (header->type) {
530 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER:
531 {
532 struct lttng_error_query_result_counter_comm *counter;
533 struct lttng_payload_view counter_payload_view =
534 lttng_payload_view_from_view(view, used_size,
535 sizeof(*counter));
536
537 if (!lttng_payload_view_is_valid(&counter_payload_view)) {
538 used_size = -1;
539 goto end;
540 }
541
542 counter = (typeof(counter)) counter_payload_view.buffer.data;
543 *result = lttng_error_query_result_counter_create(
544 name, description, counter->value);
545 if (!*result) {
546 used_size = -1;
547 goto end;
548 }
549
550 used_size += sizeof(*counter);
551 break;
552 }
553 default:
554 used_size = -1;
555 goto end;
556 }
557
558 end:
559 return used_size;
560 }
561
562 int lttng_error_query_results_serialize(
563 const struct lttng_error_query_results *results,
564 struct lttng_payload *payload)
565 {
566 int ret;
567 size_t result_index;
568 const size_t result_count = lttng_dynamic_pointer_array_get_count(
569 &results->results);
570 const struct lttng_error_query_results_comm header = {
571 .count = (decltype(header.count)) result_count,
572 };
573
574 /* Header. */
575 ret = lttng_dynamic_buffer_append(&payload->buffer, &header, sizeof(header));
576 if (ret) {
577 ERR("Failed to append error query result set header to payload");
578 goto end;
579 }
580
581 /* Results. */
582 for (result_index = 0; result_index < result_count; result_index++) {
583 const struct lttng_error_query_result *result = (typeof(result))
584 lttng_dynamic_pointer_array_get_pointer(
585 &results->results,
586 result_index);
587
588 ret = lttng_error_query_result_serialize(result, payload);
589 if (ret) {
590 ERR("Failed to append error query result to payload");
591 goto end;
592 }
593 }
594 end:
595 return ret;
596 }
597
598 ssize_t lttng_error_query_results_create_from_payload(
599 struct lttng_payload_view *view,
600 struct lttng_error_query_results **_results)
601 {
602 size_t result_index;
603 ssize_t total_used_size = 0;
604 struct lttng_error_query_results_comm *header;
605 struct lttng_payload_view header_view =
606 lttng_payload_view_from_view(view, 0, sizeof(*header));
607 struct lttng_error_query_results *results = NULL;
608
609 if (!lttng_payload_view_is_valid(&header_view)) {
610 ERR("Failed to map view to error query result set header");
611 total_used_size = -1;
612 goto end;
613 }
614
615 header = (typeof(header)) header_view.buffer.data;
616 total_used_size += sizeof(*header);
617 results = lttng_error_query_results_create();
618 if (!results) {
619 total_used_size = -1;
620 goto end;
621 }
622
623 for (result_index = 0; result_index < header->count; result_index++) {
624 ssize_t used_size;
625 struct lttng_error_query_result *result;
626 struct lttng_payload_view result_view =
627 lttng_payload_view_from_view(
628 view, total_used_size, -1);
629
630 if (!lttng_payload_view_is_valid(&result_view)) {
631 total_used_size = -1;
632 goto end;
633 }
634
635 used_size = lttng_error_query_result_create_from_payload(
636 &result_view, &result);
637 if (used_size < 0) {
638 total_used_size = -1;
639 goto end;
640 }
641
642 total_used_size += used_size;
643
644 if (lttng_dynamic_pointer_array_add_pointer(
645 &results->results, result)) {
646 lttng_error_query_result_destroy(result);
647 total_used_size = -1;
648 goto end;
649 }
650 }
651
652 *_results = results;
653 results = NULL;
654 end:
655 lttng_error_query_results_destroy(results);
656 return total_used_size;
657 }
658
659 static
660 int lttng_error_query_trigger_serialize(const struct lttng_error_query *query,
661 struct lttng_payload *payload)
662 {
663 int ret;
664 const struct lttng_error_query_trigger *query_trigger =
665 container_of(query, typeof(*query_trigger), parent);
666
667 if (!lttng_trigger_validate(query_trigger->trigger)) {
668 ret = -1;
669 goto end;
670 }
671
672 ret = lttng_trigger_serialize(query_trigger->trigger, payload);
673 if (ret) {
674 goto end;
675 }
676
677 end:
678 return ret;
679 }
680
681 static
682 int lttng_error_query_condition_serialize(const struct lttng_error_query *query,
683 struct lttng_payload *payload)
684 {
685 int ret;
686 const struct lttng_error_query_condition *query_trigger =
687 container_of(query, typeof(*query_trigger), parent);
688
689 if (!lttng_trigger_validate(query_trigger->trigger)) {
690 ret = -1;
691 goto end;
692 }
693
694 ret = lttng_trigger_serialize(query_trigger->trigger, payload);
695 if (ret) {
696 goto end;
697 }
698
699 end:
700 return ret;
701 }
702
703 static
704 int lttng_error_query_action_serialize(const struct lttng_error_query *query,
705 struct lttng_payload *payload)
706 {
707 int ret;
708 const struct lttng_error_query_action *query_action =
709 container_of(query, typeof(*query_action), parent);
710
711 if (!lttng_trigger_validate(query_action->trigger)) {
712 ret = -1;
713 goto end;
714 }
715
716 ret = lttng_trigger_serialize(query_action->trigger, payload);
717 if (ret) {
718 goto end;
719 }
720
721 ret = lttng_action_path_serialize(query_action->action_path, payload);
722 if (ret) {
723 goto end;
724 }
725
726 end:
727 return ret;
728 }
729
730 enum lttng_error_query_target_type lttng_error_query_get_target_type(
731 const struct lttng_error_query *query)
732 {
733 return query->target_type;
734 }
735
736 const struct lttng_trigger *lttng_error_query_trigger_borrow_target(
737 const struct lttng_error_query *query)
738 {
739 const struct lttng_error_query_trigger *query_trigger =
740 container_of(query, typeof(*query_trigger), parent);
741
742 return query_trigger->trigger;
743 }
744
745 const struct lttng_trigger *lttng_error_query_condition_borrow_target(
746 const struct lttng_error_query *query)
747 {
748 const struct lttng_error_query_condition *query_trigger =
749 container_of(query, typeof(*query_trigger), parent);
750
751 return query_trigger->trigger;
752 }
753
754 const struct lttng_trigger *lttng_error_query_action_borrow_trigger_target(
755 const struct lttng_error_query *query)
756 {
757 const struct lttng_error_query_action *query_action =
758 container_of(query, typeof(*query_action), parent);
759
760 return query_action->trigger;
761 }
762
763 struct lttng_action *lttng_error_query_action_borrow_action_target(
764 const struct lttng_error_query *query,
765 struct lttng_trigger *trigger)
766 {
767 const struct lttng_error_query_action *query_action =
768 container_of(query, typeof(*query_action), parent);
769
770 return get_trigger_action_from_path(
771 trigger, query_action->action_path);
772 }
773
774 int lttng_error_query_serialize(const struct lttng_error_query *query,
775 struct lttng_payload *payload)
776 {
777 int ret;
778 const struct lttng_error_query_comm header = {
779 .target_type = (decltype(header.target_type)) query->target_type,
780 };
781
782 ret = lttng_dynamic_buffer_append(
783 &payload->buffer, &header, sizeof(header));
784 if (ret) {
785 ERR("Failed to append error query header to payload");
786 goto end;
787 }
788
789 switch (query->target_type) {
790 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER:
791 ret = lttng_error_query_trigger_serialize(query, payload);
792 if (ret) {
793 goto end;
794 }
795
796 break;
797 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION:
798 ret = lttng_error_query_condition_serialize(query, payload);
799 if (ret) {
800 goto end;
801 }
802
803 break;
804 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION:
805 ret = lttng_error_query_action_serialize(query, payload);
806 if (ret) {
807 goto end;
808 }
809
810 break;
811 default:
812 abort();
813 }
814 end:
815 return ret;
816 }
817
818 ssize_t lttng_error_query_create_from_payload(struct lttng_payload_view *view,
819 struct lttng_error_query **query)
820 {
821 ssize_t used_size = 0;
822 struct lttng_error_query_comm *header;
823 struct lttng_trigger *trigger = NULL;
824 struct lttng_payload_view header_view =
825 lttng_payload_view_from_view(view, 0, sizeof(*header));
826
827 if (!lttng_payload_view_is_valid(&header_view)) {
828 ERR("Failed to map error query header");
829 used_size = -1;
830 goto end;
831 }
832
833 used_size = sizeof(*header);
834
835 header = (typeof(header)) header_view.buffer.data;
836 switch ((enum lttng_error_query_target_type) header->target_type) {
837 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER:
838 {
839 ssize_t trigger_used_size;
840 struct lttng_payload_view trigger_view =
841 lttng_payload_view_from_view(
842 view, used_size, -1);
843
844 if (!lttng_payload_view_is_valid(&trigger_view)) {
845 used_size = -1;
846 goto end;
847 }
848
849 trigger_used_size = lttng_trigger_create_from_payload(
850 &trigger_view, &trigger);
851 if (trigger_used_size < 0) {
852 used_size = -1;
853 goto end;
854 }
855
856 used_size += trigger_used_size;
857
858 *query = lttng_error_query_trigger_create(trigger);
859 if (!*query) {
860 used_size = -1;
861 goto end;
862 }
863
864 break;
865 }
866 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION:
867 {
868 ssize_t trigger_used_size;
869 struct lttng_payload_view trigger_view =
870 lttng_payload_view_from_view(
871 view, used_size, -1);
872
873 if (!lttng_payload_view_is_valid(&trigger_view)) {
874 used_size = -1;
875 goto end;
876 }
877
878 trigger_used_size = lttng_trigger_create_from_payload(
879 &trigger_view, &trigger);
880 if (trigger_used_size < 0) {
881 used_size = -1;
882 goto end;
883 }
884
885 used_size += trigger_used_size;
886
887 *query = lttng_error_query_condition_create(trigger);
888 if (!*query) {
889 used_size = -1;
890 goto end;
891 }
892
893 break;
894 }
895 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION:
896 {
897 struct lttng_action_path *action_path = NULL;
898
899 {
900 ssize_t trigger_used_size;
901 struct lttng_payload_view trigger_view =
902 lttng_payload_view_from_view(
903 view, used_size, -1);
904
905 if (!lttng_payload_view_is_valid(&trigger_view)) {
906 used_size = -1;
907 goto end;
908 }
909
910 trigger_used_size = lttng_trigger_create_from_payload(
911 &trigger_view, &trigger);
912 if (trigger_used_size < 0) {
913 used_size = -1;
914 goto end;
915 }
916
917 used_size += trigger_used_size;
918 }
919
920 {
921 ssize_t action_path_used_size;
922 struct lttng_payload_view action_path_view =
923 lttng_payload_view_from_view(
924 view, used_size, -1);
925
926 if (!lttng_payload_view_is_valid(&action_path_view)) {
927 used_size = -1;
928 goto end;
929 }
930
931 action_path_used_size = lttng_action_path_create_from_payload(
932 &action_path_view, &action_path);
933 if (action_path_used_size < 0) {
934 used_size = -1;
935 goto end;
936 }
937
938 used_size += action_path_used_size;
939 }
940
941 *query = lttng_error_query_action_create(
942 trigger, action_path);
943 lttng_action_path_destroy(action_path);
944 if (!*query) {
945 used_size = -1;
946 goto end;
947 }
948
949 break;
950 }
951 default:
952 used_size = -1;
953 goto end;
954 }
955
956 end:
957 lttng_trigger_put(trigger);
958 return used_size;
959 }
960
961 enum lttng_error_query_results_status lttng_error_query_results_get_count(
962 const struct lttng_error_query_results *results,
963 unsigned int *count)
964 {
965 enum lttng_error_query_results_status status;
966
967 if (!results || !count) {
968 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER;
969 goto end;
970 }
971
972 *count = lttng_dynamic_pointer_array_get_count(&results->results);
973 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_OK;
974 end:
975 return status;
976 }
977
978 enum lttng_error_query_results_status
979 lttng_error_query_results_get_result(
980 const struct lttng_error_query_results *results,
981 const struct lttng_error_query_result **result,
982 unsigned int index)
983 {
984 unsigned int result_count;
985 enum lttng_error_query_results_status status;
986
987 if (!results || !result) {
988 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER;
989 goto end;
990 }
991
992 status = lttng_error_query_results_get_count(results, &result_count);
993 if (status != LTTNG_ERROR_QUERY_RESULTS_STATUS_OK) {
994 goto end;
995 }
996
997 if (index >= result_count) {
998 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER;
999 goto end;
1000 }
1001
1002 *result = (typeof(*result)) lttng_dynamic_pointer_array_get_pointer(
1003 &results->results, index);
1004 LTTNG_ASSERT(*result);
1005 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_OK;
1006 end:
1007 return status;
1008 }
1009
1010 void lttng_error_query_results_destroy(
1011 struct lttng_error_query_results *results)
1012 {
1013 if (!results) {
1014 return;
1015 }
1016
1017 lttng_dynamic_pointer_array_reset(&results->results);
1018 free(results);
1019 }
1020
1021 enum lttng_error_query_result_type
1022 lttng_error_query_result_get_type(const struct lttng_error_query_result *result)
1023 {
1024 return result ? result->type : LTTNG_ERROR_QUERY_RESULT_TYPE_UNKNOWN;
1025 }
1026
1027 enum lttng_error_query_result_status lttng_error_query_result_get_name(
1028 const struct lttng_error_query_result *result,
1029 const char **name)
1030 {
1031 enum lttng_error_query_result_status status;
1032
1033 if (!result || !name) {
1034 status = LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER;
1035 goto end;
1036 }
1037
1038 *name = result->name;
1039 status = LTTNG_ERROR_QUERY_RESULT_STATUS_OK;
1040 end:
1041 return status;
1042 }
1043
1044 enum lttng_error_query_result_status lttng_error_query_result_get_description(
1045 const struct lttng_error_query_result *result,
1046 const char **description)
1047 {
1048 enum lttng_error_query_result_status status;
1049
1050 if (!result || !description) {
1051 status = LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER;
1052 goto end;
1053 }
1054
1055 *description = result->description;
1056 status = LTTNG_ERROR_QUERY_RESULT_STATUS_OK;
1057 end:
1058 return status;
1059 }
1060
1061 enum lttng_error_query_result_status lttng_error_query_result_counter_get_value(
1062 const struct lttng_error_query_result *result,
1063 uint64_t *value)
1064 {
1065 enum lttng_error_query_result_status status;
1066 const struct lttng_error_query_result_counter *counter_result;
1067
1068 if (!result || !value ||
1069 result->type != LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER) {
1070 status = LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER;
1071 goto end;
1072 }
1073
1074 counter_result = container_of(result, typeof(*counter_result), parent);
1075
1076 *value = counter_result->value;
1077 status = LTTNG_ERROR_QUERY_RESULT_STATUS_OK;
1078 end:
1079 return status;
1080 }
1081
1082 static
1083 enum lttng_error_code lttng_error_query_result_counter_mi_serialize(
1084 const struct lttng_error_query_result *result,
1085 struct mi_writer *writer)
1086 {
1087 int ret;
1088 enum lttng_error_code ret_code;
1089 enum lttng_error_query_result_status status;
1090 uint64_t value;
1091
1092 LTTNG_ASSERT(result);
1093 LTTNG_ASSERT(writer);
1094
1095 status = lttng_error_query_result_counter_get_value(result, &value);
1096 LTTNG_ASSERT(status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK);
1097
1098 /* Open error query result counter element. */
1099 ret = mi_lttng_writer_open_element(
1100 writer, mi_lttng_element_error_query_result_counter);
1101 if (ret) {
1102 goto mi_error;
1103 }
1104
1105 /* Value. */
1106 ret = mi_lttng_writer_write_element_unsigned_int(writer,
1107 mi_lttng_element_error_query_result_counter_value,
1108 value);
1109 if (ret) {
1110 goto mi_error;
1111 }
1112
1113 /* Close error query result counter element. */
1114 ret = mi_lttng_writer_close_element(writer);
1115 if (ret) {
1116 goto mi_error;
1117 }
1118
1119 ret_code = LTTNG_OK;
1120 goto end;
1121
1122 mi_error:
1123 ret_code = LTTNG_ERR_MI_IO_FAIL;
1124 end:
1125 return ret_code;
1126 }
1127
1128 static
1129 enum lttng_error_code lttng_error_query_result_mi_serialize(
1130 const struct lttng_error_query_result *result,
1131 struct mi_writer *writer)
1132 {
1133 int ret;
1134 enum lttng_error_code ret_code;
1135 enum lttng_error_query_result_status result_status;
1136 enum lttng_error_query_result_type type;
1137 const char *name = NULL;
1138 const char *description = NULL;
1139
1140 LTTNG_ASSERT(result);
1141 LTTNG_ASSERT(writer);
1142
1143 type = lttng_error_query_result_get_type(result);
1144
1145 result_status = lttng_error_query_result_get_name(result, &name);
1146 LTTNG_ASSERT(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK);
1147
1148 result_status = lttng_error_query_result_get_description(
1149 result, &description);
1150 LTTNG_ASSERT(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK);
1151
1152 /* Open error query result element. */
1153 ret = mi_lttng_writer_open_element(
1154 writer, mi_lttng_element_error_query_result);
1155 if (ret) {
1156 goto mi_error;
1157 }
1158
1159 /* Name. */
1160 ret = mi_lttng_writer_write_element_string(
1161 writer, mi_lttng_element_error_query_result_name, name);
1162 if (ret) {
1163 goto mi_error;
1164 }
1165
1166 /* Description. */
1167 ret = mi_lttng_writer_write_element_string(writer,
1168 mi_lttng_element_error_query_result_description,
1169 description);
1170 if (ret) {
1171 goto mi_error;
1172 }
1173
1174 /* Serialize the result according to its sub type. */
1175 switch (type) {
1176 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER:
1177 ret_code = lttng_error_query_result_counter_mi_serialize(
1178 result, writer);
1179 break;
1180 default:
1181 abort();
1182 }
1183
1184 if (ret_code != LTTNG_OK) {
1185 goto end;
1186 }
1187
1188 /* Close error query result element. */
1189 ret = mi_lttng_writer_close_element(writer);
1190 if (ret) {
1191 goto mi_error;
1192 }
1193
1194 ret_code = LTTNG_OK;
1195 goto end;
1196
1197 mi_error:
1198 ret_code = LTTNG_ERR_MI_IO_FAIL;
1199 end:
1200 return ret_code;
1201 }
1202
1203 enum lttng_error_code lttng_error_query_results_mi_serialize(
1204 const struct lttng_error_query_results *results,
1205 struct mi_writer *writer)
1206 {
1207 int ret;
1208 enum lttng_error_code ret_code;
1209 unsigned int i, count;
1210 enum lttng_error_query_results_status results_status;
1211
1212 LTTNG_ASSERT(results);
1213 LTTNG_ASSERT(writer);
1214
1215 /* Open error query results element. */
1216 ret = mi_lttng_writer_open_element(
1217 writer, mi_lttng_element_error_query_results);
1218 if (ret) {
1219 goto mi_error;
1220 }
1221
1222 results_status = lttng_error_query_results_get_count(results, &count);
1223 LTTNG_ASSERT(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK);
1224
1225 for (i = 0; i < count; i++) {
1226 const struct lttng_error_query_result *result;
1227
1228 results_status = lttng_error_query_results_get_result(
1229 results, &result, i);
1230 LTTNG_ASSERT(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK);
1231
1232 /* A single error query result. */
1233 ret_code = lttng_error_query_result_mi_serialize(result, writer);
1234 if (ret_code != LTTNG_OK) {
1235 goto end;
1236 }
1237 }
1238
1239 /* Close error query results. */
1240 ret = mi_lttng_writer_close_element(writer);
1241 if (ret) {
1242 goto mi_error;
1243 }
1244
1245 ret_code = LTTNG_OK;
1246 goto end;
1247
1248 mi_error:
1249 ret_code = LTTNG_ERR_MI_IO_FAIL;
1250 end:
1251 return ret_code;
1252 }
This page took 0.104726 seconds and 4 git commands to generate.