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