docs: Add supported versions and fix-backport policy
[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.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 = (lttng_error_query_trigger *) 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 = (lttng_error_query_condition *) 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 = (lttng_error_query_action *) 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 struct lttng_error_query_trigger *trigger_query;
250
251 if (!query) {
252 return;
253 }
254
255 trigger_query = container_of(query, typeof(*trigger_query), parent);
256 lttng_trigger_put(trigger_query->trigger);
257 free(trigger_query);
258 }
259
260 static
261 int lttng_error_query_result_counter_serialize(
262 const struct lttng_error_query_result *result,
263 struct lttng_payload *payload)
264 {
265 const struct lttng_error_query_result_counter *counter_result;
266
267 LTTNG_ASSERT(result->type == LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER);
268 counter_result = container_of(result, typeof(*counter_result), parent);
269
270 lttng_error_query_result_counter_comm comm = {
271 .value = counter_result->value,
272 };
273
274 return lttng_dynamic_buffer_append(&payload->buffer,
275 &comm,
276 sizeof(struct lttng_error_query_result_counter_comm));
277 }
278
279 int lttng_error_query_result_serialize(
280 const struct lttng_error_query_result *result,
281 struct lttng_payload *payload)
282 {
283 int ret;
284 struct lttng_error_query_result_comm header = {
285 .type = (uint8_t) result->type,
286 .name_len = (typeof(header.name_len)) strlen(result->name) + 1,
287 .description_len = (typeof(header.name_len)) strlen(result->description) + 1,
288 };
289
290 /* Header. */
291 ret = lttng_dynamic_buffer_append(
292 &payload->buffer, &header, sizeof(header));
293 if (ret) {
294 ERR("Failed to append error query result communication header to payload");
295 goto end;
296 }
297
298 /* Name. */
299 ret = lttng_dynamic_buffer_append(
300 &payload->buffer, result->name, header.name_len);
301 if (ret) {
302 ERR("Failed to append error query result name to payload");
303 goto end;
304 }
305
306 /* Description. */
307 ret = lttng_dynamic_buffer_append(&payload->buffer, result->description,
308 header.description_len);
309 if (ret) {
310 ERR("Failed to append error query result description to payload");
311 goto end;
312 }
313
314 /* Type-specific payload. */
315 switch (result->type) {
316 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER:
317 ret = lttng_error_query_result_counter_serialize(
318 result, payload);
319 if (ret) {
320 ERR("Failed to serialize counter error query result");
321 goto end;
322 }
323 break;
324 default:
325 abort();
326 }
327
328 end:
329 return ret;
330 }
331
332 static
333 int lttng_error_query_result_init(
334 struct lttng_error_query_result *result,
335 enum lttng_error_query_result_type result_type,
336 const char *name,
337 const char *description)
338 {
339 int ret;
340
341 LTTNG_ASSERT(name);
342 LTTNG_ASSERT(description);
343
344 result->type = result_type;
345
346 result->name = strdup(name);
347 if (!result->name) {
348 PERROR("Failed to copy error query result name");
349 ret = -1;
350 goto end;
351 }
352
353 result->description = strdup(description);
354 if (!result->description) {
355 PERROR("Failed to copy error query result description");
356 ret = -1;
357 goto end;
358 }
359
360 ret = 0;
361 end:
362 return ret;
363 }
364
365 void lttng_error_query_result_destroy(struct lttng_error_query_result *counter)
366 {
367 if (!counter) {
368 return;
369 }
370
371 switch (counter->type) {
372 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER:
373 /* Nothing to tear down. */
374 break;
375 default:
376 abort();
377 }
378
379 free(counter->name);
380 free(counter->description);
381 free(counter);
382 }
383
384 struct lttng_error_query_result *
385 lttng_error_query_result_counter_create(
386 const char *name, const char *description, uint64_t value)
387 {
388 int init_ret;
389 struct lttng_error_query_result_counter *counter;
390
391 counter = (lttng_error_query_result_counter *) zmalloc(sizeof(*counter));
392 if (!counter) {
393 PERROR("Failed to allocate error query counter result");
394 goto end;
395 }
396
397 init_ret = lttng_error_query_result_init(&counter->parent,
398 LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER, name,
399 description);
400 if (init_ret) {
401 goto error;
402 }
403
404 counter->value = value;
405 goto end;
406 error:
407 lttng_error_query_result_destroy(&counter->parent);
408 end:
409 return counter ? &counter->parent : NULL;
410 }
411
412 static
413 void destroy_result(void *ptr)
414 {
415 struct lttng_error_query_result *result = (typeof(result)) ptr;
416
417 lttng_error_query_result_destroy(result);
418 }
419
420 struct lttng_error_query_results *lttng_error_query_results_create(void)
421 {
422 struct lttng_error_query_results *set = (lttng_error_query_results *) zmalloc(sizeof(*set));
423
424 if (!set) {
425 PERROR("Failed to allocate an error query result set");
426 goto end;
427 }
428
429 lttng_dynamic_pointer_array_init(&set->results, destroy_result);
430 end:
431 return set;
432 }
433
434 int lttng_error_query_results_add_result(
435 struct lttng_error_query_results *results,
436 struct lttng_error_query_result *result)
437 {
438 return lttng_dynamic_pointer_array_add_pointer(
439 &results->results, result);
440 }
441
442 ssize_t lttng_error_query_result_create_from_payload(
443 struct lttng_payload_view *view,
444 struct lttng_error_query_result **result)
445 {
446 ssize_t used_size = 0;
447 struct lttng_error_query_result_comm *header;
448 struct lttng_payload_view header_view =
449 lttng_payload_view_from_view(view, 0, sizeof(*header));
450 const char *name;
451 const char *description;
452
453 if (!lttng_payload_view_is_valid(&header_view)) {
454 used_size = -1;
455 goto end;
456 }
457
458 header = (typeof(header)) header_view.buffer.data;
459 used_size += sizeof(*header);
460
461 {
462 struct lttng_payload_view name_view =
463 lttng_payload_view_from_view(view, used_size,
464 header->name_len);
465
466 if (!lttng_payload_view_is_valid(&name_view) ||
467 !lttng_buffer_view_contains_string(
468 &name_view.buffer,
469 name_view.buffer.data,
470 header->name_len)) {
471 used_size = -1;
472 goto end;
473 }
474
475 name = name_view.buffer.data;
476 used_size += header->name_len;
477 }
478
479 {
480 struct lttng_payload_view description_view =
481 lttng_payload_view_from_view(view, used_size,
482 header->description_len);
483
484 if (!lttng_payload_view_is_valid(&description_view) ||
485 !lttng_buffer_view_contains_string(
486 &description_view.buffer,
487 description_view.buffer.data,
488 header->description_len)) {
489 used_size = -1;
490 goto end;
491 }
492
493 description = description_view.buffer.data;
494 used_size += header->description_len;
495 }
496
497 switch (header->type) {
498 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER:
499 {
500 struct lttng_error_query_result_counter_comm *counter;
501 struct lttng_payload_view counter_payload_view =
502 lttng_payload_view_from_view(view, used_size,
503 sizeof(*counter));
504
505 if (!lttng_payload_view_is_valid(&counter_payload_view)) {
506 used_size = -1;
507 goto end;
508 }
509
510 counter = (typeof(counter)) counter_payload_view.buffer.data;
511 *result = lttng_error_query_result_counter_create(
512 name, description, counter->value);
513 if (!*result) {
514 used_size = -1;
515 goto end;
516 }
517
518 used_size += sizeof(*counter);
519 break;
520 }
521 default:
522 used_size = -1;
523 goto end;
524 }
525
526 end:
527 return used_size;
528 }
529
530 int lttng_error_query_results_serialize(
531 const struct lttng_error_query_results *results,
532 struct lttng_payload *payload)
533 {
534 int ret;
535 size_t result_index;
536 const size_t result_count = lttng_dynamic_pointer_array_get_count(
537 &results->results);
538 const struct lttng_error_query_results_comm header = {
539 .count = (typeof(header.count)) result_count,
540 };
541
542 /* Header. */
543 ret = lttng_dynamic_buffer_append(&payload->buffer, &header, sizeof(header));
544 if (ret) {
545 ERR("Failed to append error query result set header to payload");
546 goto end;
547 }
548
549 /* Results. */
550 for (result_index = 0; result_index < result_count; result_index++) {
551 const struct lttng_error_query_result *result = (typeof(result))
552 lttng_dynamic_pointer_array_get_pointer(
553 &results->results,
554 result_index);
555
556 ret = lttng_error_query_result_serialize(result, payload);
557 if (ret) {
558 ERR("Failed to append error query result to payload");
559 goto end;
560 }
561 }
562 end:
563 return ret;
564 }
565
566 ssize_t lttng_error_query_results_create_from_payload(
567 struct lttng_payload_view *view,
568 struct lttng_error_query_results **_results)
569 {
570 size_t result_index;
571 ssize_t total_used_size = 0;
572 struct lttng_error_query_results_comm *header;
573 struct lttng_payload_view header_view =
574 lttng_payload_view_from_view(view, 0, sizeof(*header));
575 struct lttng_error_query_results *results = NULL;
576
577 if (!lttng_payload_view_is_valid(&header_view)) {
578 ERR("Failed to map view to error query result set header");
579 total_used_size = -1;
580 goto end;
581 }
582
583 header = (typeof(header)) header_view.buffer.data;
584 total_used_size += sizeof(*header);
585 results = lttng_error_query_results_create();
586 if (!results) {
587 total_used_size = -1;
588 goto end;
589 }
590
591 for (result_index = 0; result_index < header->count; result_index++) {
592 ssize_t used_size;
593 struct lttng_error_query_result *result;
594 struct lttng_payload_view result_view =
595 lttng_payload_view_from_view(
596 view, total_used_size, -1);
597
598 if (!lttng_payload_view_is_valid(&result_view)) {
599 total_used_size = -1;
600 goto end;
601 }
602
603 used_size = lttng_error_query_result_create_from_payload(
604 &result_view, &result);
605 if (used_size < 0) {
606 total_used_size = -1;
607 goto end;
608 }
609
610 total_used_size += used_size;
611
612 if (lttng_dynamic_pointer_array_add_pointer(
613 &results->results, result)) {
614 lttng_error_query_result_destroy(result);
615 total_used_size = -1;
616 goto end;
617 }
618 }
619
620 *_results = results;
621 results = NULL;
622 end:
623 lttng_error_query_results_destroy(results);
624 return total_used_size;
625 }
626
627 static
628 int lttng_error_query_trigger_serialize(const struct lttng_error_query *query,
629 struct lttng_payload *payload)
630 {
631 int ret;
632 const struct lttng_error_query_trigger *query_trigger =
633 container_of(query, typeof(*query_trigger), parent);
634
635 if (!lttng_trigger_validate(query_trigger->trigger)) {
636 ret = -1;
637 goto end;
638 }
639
640 ret = lttng_trigger_serialize(query_trigger->trigger, payload);
641 if (ret) {
642 goto end;
643 }
644
645 end:
646 return ret;
647 }
648
649 static
650 int lttng_error_query_condition_serialize(const struct lttng_error_query *query,
651 struct lttng_payload *payload)
652 {
653 int ret;
654 const struct lttng_error_query_condition *query_trigger =
655 container_of(query, typeof(*query_trigger), parent);
656
657 if (!lttng_trigger_validate(query_trigger->trigger)) {
658 ret = -1;
659 goto end;
660 }
661
662 ret = lttng_trigger_serialize(query_trigger->trigger, payload);
663 if (ret) {
664 goto end;
665 }
666
667 end:
668 return ret;
669 }
670
671 static
672 int lttng_error_query_action_serialize(const struct lttng_error_query *query,
673 struct lttng_payload *payload)
674 {
675 int ret;
676 const struct lttng_error_query_action *query_action =
677 container_of(query, typeof(*query_action), parent);
678
679 if (!lttng_trigger_validate(query_action->trigger)) {
680 ret = -1;
681 goto end;
682 }
683
684 ret = lttng_trigger_serialize(query_action->trigger, payload);
685 if (ret) {
686 goto end;
687 }
688
689 ret = lttng_action_path_serialize(&query_action->action_path, payload);
690 if (ret) {
691 goto end;
692 }
693
694 end:
695 return ret;
696 }
697
698 enum lttng_error_query_target_type lttng_error_query_get_target_type(
699 const struct lttng_error_query *query)
700 {
701 return query->target_type;
702 }
703
704 const struct lttng_trigger *lttng_error_query_trigger_borrow_target(
705 const struct lttng_error_query *query)
706 {
707 const struct lttng_error_query_trigger *query_trigger =
708 container_of(query, typeof(*query_trigger), parent);
709
710 return query_trigger->trigger;
711 }
712
713 const struct lttng_trigger *lttng_error_query_condition_borrow_target(
714 const struct lttng_error_query *query)
715 {
716 const struct lttng_error_query_condition *query_trigger =
717 container_of(query, typeof(*query_trigger), parent);
718
719 return query_trigger->trigger;
720 }
721
722 const struct lttng_trigger *lttng_error_query_action_borrow_trigger_target(
723 const struct lttng_error_query *query)
724 {
725 const struct lttng_error_query_action *query_action =
726 container_of(query, typeof(*query_action), parent);
727
728 return query_action->trigger;
729 }
730
731 struct lttng_action *lttng_error_query_action_borrow_action_target(
732 const struct lttng_error_query *query,
733 struct lttng_trigger *trigger)
734 {
735 const struct lttng_error_query_action *query_action =
736 container_of(query, typeof(*query_action), parent);
737
738 return get_trigger_action_from_path(
739 trigger, &query_action->action_path);
740 }
741
742 int lttng_error_query_serialize(const struct lttng_error_query *query,
743 struct lttng_payload *payload)
744 {
745 int ret;
746 const struct lttng_error_query_comm header = {
747 .target_type = (typeof(header.target_type)) query->target_type,
748 };
749
750 ret = lttng_dynamic_buffer_append(
751 &payload->buffer, &header, sizeof(header));
752 if (ret) {
753 ERR("Failed to append error query header to payload");
754 goto end;
755 }
756
757 switch (query->target_type) {
758 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER:
759 ret = lttng_error_query_trigger_serialize(query, payload);
760 if (ret) {
761 goto end;
762 }
763
764 break;
765 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION:
766 ret = lttng_error_query_condition_serialize(query, payload);
767 if (ret) {
768 goto end;
769 }
770
771 break;
772 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION:
773 ret = lttng_error_query_action_serialize(query, payload);
774 if (ret) {
775 goto end;
776 }
777
778 break;
779 default:
780 abort();
781 }
782 end:
783 return ret;
784 }
785
786 ssize_t lttng_error_query_create_from_payload(struct lttng_payload_view *view,
787 struct lttng_error_query **query)
788 {
789 ssize_t used_size = 0;
790 struct lttng_error_query_comm *header;
791 struct lttng_trigger *trigger = NULL;
792 struct lttng_payload_view header_view =
793 lttng_payload_view_from_view(view, 0, sizeof(*header));
794
795 if (!lttng_payload_view_is_valid(&header_view)) {
796 ERR("Failed to map error query header");
797 used_size = -1;
798 goto end;
799 }
800
801 used_size = sizeof(*header);
802
803 header = (typeof(header)) header_view.buffer.data;
804 switch ((enum lttng_error_query_target_type) header->target_type) {
805 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER:
806 {
807 ssize_t trigger_used_size;
808 struct lttng_payload_view trigger_view =
809 lttng_payload_view_from_view(
810 view, used_size, -1);
811
812 if (!lttng_payload_view_is_valid(&trigger_view)) {
813 used_size = -1;
814 goto end;
815 }
816
817 trigger_used_size = lttng_trigger_create_from_payload(
818 &trigger_view, &trigger);
819 if (trigger_used_size < 0) {
820 used_size = -1;
821 goto end;
822 }
823
824 used_size += trigger_used_size;
825
826 *query = lttng_error_query_trigger_create(trigger);
827 if (!*query) {
828 used_size = -1;
829 goto end;
830 }
831
832 break;
833 }
834 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION:
835 {
836 ssize_t trigger_used_size;
837 struct lttng_payload_view trigger_view =
838 lttng_payload_view_from_view(
839 view, used_size, -1);
840
841 if (!lttng_payload_view_is_valid(&trigger_view)) {
842 used_size = -1;
843 goto end;
844 }
845
846 trigger_used_size = lttng_trigger_create_from_payload(
847 &trigger_view, &trigger);
848 if (trigger_used_size < 0) {
849 used_size = -1;
850 goto end;
851 }
852
853 used_size += trigger_used_size;
854
855 *query = lttng_error_query_condition_create(trigger);
856 if (!*query) {
857 used_size = -1;
858 goto end;
859 }
860
861 break;
862 }
863 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION:
864 {
865 struct lttng_action_path *action_path = NULL;
866
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
888 {
889 ssize_t action_path_used_size;
890 struct lttng_payload_view action_path_view =
891 lttng_payload_view_from_view(
892 view, used_size, -1);
893
894 if (!lttng_payload_view_is_valid(&action_path_view)) {
895 used_size = -1;
896 goto end;
897 }
898
899 action_path_used_size = lttng_action_path_create_from_payload(
900 &action_path_view, &action_path);
901 if (action_path_used_size < 0) {
902 used_size = -1;
903 goto end;
904 }
905
906 used_size += action_path_used_size;
907 }
908
909 *query = lttng_error_query_action_create(
910 trigger, action_path);
911 lttng_action_path_destroy(action_path);
912 if (!*query) {
913 used_size = -1;
914 goto end;
915 }
916
917 break;
918 }
919 default:
920 used_size = -1;
921 goto end;
922 }
923
924 end:
925 lttng_trigger_put(trigger);
926 return used_size;
927 }
928
929 enum lttng_error_query_results_status lttng_error_query_results_get_count(
930 const struct lttng_error_query_results *results,
931 unsigned int *count)
932 {
933 enum lttng_error_query_results_status status;
934
935 if (!results || !count) {
936 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER;
937 goto end;
938 }
939
940 *count = lttng_dynamic_pointer_array_get_count(&results->results);
941 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_OK;
942 end:
943 return status;
944 }
945
946 enum lttng_error_query_results_status
947 lttng_error_query_results_get_result(
948 const struct lttng_error_query_results *results,
949 const struct lttng_error_query_result **result,
950 unsigned int index)
951 {
952 unsigned int result_count;
953 enum lttng_error_query_results_status status;
954
955 if (!results || !result) {
956 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER;
957 goto end;
958 }
959
960 status = lttng_error_query_results_get_count(results, &result_count);
961 if (status != LTTNG_ERROR_QUERY_RESULTS_STATUS_OK) {
962 goto end;
963 }
964
965 if (index >= result_count) {
966 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER;
967 goto end;
968 }
969
970 *result = (typeof(*result)) lttng_dynamic_pointer_array_get_pointer(
971 &results->results, index);
972 LTTNG_ASSERT(*result);
973 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_OK;
974 end:
975 return status;
976 }
977
978 void lttng_error_query_results_destroy(
979 struct lttng_error_query_results *results)
980 {
981 if (!results) {
982 return;
983 }
984
985 lttng_dynamic_pointer_array_reset(&results->results);
986 free(results);
987 }
988
989 enum lttng_error_query_result_type
990 lttng_error_query_result_get_type(const struct lttng_error_query_result *result)
991 {
992 return result ? result->type : LTTNG_ERROR_QUERY_RESULT_TYPE_UNKNOWN;
993 }
994
995 enum lttng_error_query_result_status lttng_error_query_result_get_name(
996 const struct lttng_error_query_result *result,
997 const char **name)
998 {
999 enum lttng_error_query_result_status status;
1000
1001 if (!result || !name) {
1002 status = LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER;
1003 goto end;
1004 }
1005
1006 *name = result->name;
1007 status = LTTNG_ERROR_QUERY_RESULT_STATUS_OK;
1008 end:
1009 return status;
1010 }
1011
1012 enum lttng_error_query_result_status lttng_error_query_result_get_description(
1013 const struct lttng_error_query_result *result,
1014 const char **description)
1015 {
1016 enum lttng_error_query_result_status status;
1017
1018 if (!result || !description) {
1019 status = LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER;
1020 goto end;
1021 }
1022
1023 *description = result->description;
1024 status = LTTNG_ERROR_QUERY_RESULT_STATUS_OK;
1025 end:
1026 return status;
1027 }
1028
1029 enum lttng_error_query_result_status lttng_error_query_result_counter_get_value(
1030 const struct lttng_error_query_result *result,
1031 uint64_t *value)
1032 {
1033 enum lttng_error_query_result_status status;
1034 const struct lttng_error_query_result_counter *counter_result;
1035
1036 if (!result || !value ||
1037 result->type != LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER) {
1038 status = LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER;
1039 goto end;
1040 }
1041
1042 counter_result = container_of(result, typeof(*counter_result), parent);
1043
1044 *value = counter_result->value;
1045 status = LTTNG_ERROR_QUERY_RESULT_STATUS_OK;
1046 end:
1047 return status;
1048 }
1049
1050 static
1051 enum lttng_error_code lttng_error_query_result_counter_mi_serialize(
1052 const struct lttng_error_query_result *result,
1053 struct mi_writer *writer)
1054 {
1055 int ret;
1056 enum lttng_error_code ret_code;
1057 enum lttng_error_query_result_status status;
1058 uint64_t value;
1059
1060 LTTNG_ASSERT(result);
1061 LTTNG_ASSERT(writer);
1062
1063 status = lttng_error_query_result_counter_get_value(result, &value);
1064 LTTNG_ASSERT(status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK);
1065
1066 /* Open error query result counter element. */
1067 ret = mi_lttng_writer_open_element(
1068 writer, mi_lttng_element_error_query_result_counter);
1069 if (ret) {
1070 goto mi_error;
1071 }
1072
1073 /* Value. */
1074 ret = mi_lttng_writer_write_element_unsigned_int(writer,
1075 mi_lttng_element_error_query_result_counter_value,
1076 value);
1077 if (ret) {
1078 goto mi_error;
1079 }
1080
1081 /* Close error query result counter element. */
1082 ret = mi_lttng_writer_close_element(writer);
1083 if (ret) {
1084 goto mi_error;
1085 }
1086
1087 ret_code = LTTNG_OK;
1088 goto end;
1089
1090 mi_error:
1091 ret_code = LTTNG_ERR_MI_IO_FAIL;
1092 end:
1093 return ret_code;
1094 }
1095
1096 static
1097 enum lttng_error_code lttng_error_query_result_mi_serialize(
1098 const struct lttng_error_query_result *result,
1099 struct mi_writer *writer)
1100 {
1101 int ret;
1102 enum lttng_error_code ret_code;
1103 enum lttng_error_query_result_status result_status;
1104 enum lttng_error_query_result_type type;
1105 const char *name = NULL;
1106 const char *description = NULL;
1107
1108 LTTNG_ASSERT(result);
1109 LTTNG_ASSERT(writer);
1110
1111 type = lttng_error_query_result_get_type(result);
1112
1113 result_status = lttng_error_query_result_get_name(result, &name);
1114 LTTNG_ASSERT(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK);
1115
1116 result_status = lttng_error_query_result_get_description(
1117 result, &description);
1118 LTTNG_ASSERT(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK);
1119
1120 /* Open error query result element. */
1121 ret = mi_lttng_writer_open_element(
1122 writer, mi_lttng_element_error_query_result);
1123 if (ret) {
1124 goto mi_error;
1125 }
1126
1127 /* Name. */
1128 ret = mi_lttng_writer_write_element_string(
1129 writer, mi_lttng_element_error_query_result_name, name);
1130 if (ret) {
1131 goto mi_error;
1132 }
1133
1134 /* Description. */
1135 ret = mi_lttng_writer_write_element_string(writer,
1136 mi_lttng_element_error_query_result_description,
1137 description);
1138 if (ret) {
1139 goto mi_error;
1140 }
1141
1142 /* Serialize the result according to its sub type. */
1143 switch (type) {
1144 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER:
1145 ret_code = lttng_error_query_result_counter_mi_serialize(
1146 result, writer);
1147 break;
1148 default:
1149 abort();
1150 }
1151
1152 if (ret_code != LTTNG_OK) {
1153 goto end;
1154 }
1155
1156 /* Close error query result element. */
1157 ret = mi_lttng_writer_close_element(writer);
1158 if (ret) {
1159 goto mi_error;
1160 }
1161
1162 ret_code = LTTNG_OK;
1163 goto end;
1164
1165 mi_error:
1166 ret_code = LTTNG_ERR_MI_IO_FAIL;
1167 end:
1168 return ret_code;
1169 }
1170
1171 enum lttng_error_code lttng_error_query_results_mi_serialize(
1172 const struct lttng_error_query_results *results,
1173 struct mi_writer *writer)
1174 {
1175 int ret;
1176 enum lttng_error_code ret_code;
1177 unsigned int i, count;
1178 enum lttng_error_query_results_status results_status;
1179
1180 LTTNG_ASSERT(results);
1181 LTTNG_ASSERT(writer);
1182
1183 /* Open error query results element. */
1184 ret = mi_lttng_writer_open_element(
1185 writer, mi_lttng_element_error_query_results);
1186 if (ret) {
1187 goto mi_error;
1188 }
1189
1190 results_status = lttng_error_query_results_get_count(results, &count);
1191 LTTNG_ASSERT(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK);
1192
1193 for (i = 0; i < count; i++) {
1194 const struct lttng_error_query_result *result;
1195
1196 results_status = lttng_error_query_results_get_result(
1197 results, &result, i);
1198 LTTNG_ASSERT(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK);
1199
1200 /* A single error query result. */
1201 ret_code = lttng_error_query_result_mi_serialize(result, writer);
1202 if (ret_code != LTTNG_OK) {
1203 goto end;
1204 }
1205 }
1206
1207 /* Close error query results. */
1208 ret = mi_lttng_writer_close_element(writer);
1209 if (ret) {
1210 goto mi_error;
1211 }
1212
1213 ret_code = LTTNG_OK;
1214 goto end;
1215
1216 mi_error:
1217 ret_code = LTTNG_ERR_MI_IO_FAIL;
1218 end:
1219 return ret_code;
1220 }
This page took 0.081753 seconds and 4 git commands to generate.