4 * Copyright (C) 2021 Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 * SPDX-License-Identifier: GPL-2.1-only
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>
23 struct lttng_error_query
{
24 enum lttng_error_query_target_type target_type
;
27 struct lttng_error_query_comm
{
28 /* enum lttng_error_query_target_type */
30 /* Target-specific payload. */
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
;
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
;
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
;
53 struct lttng_error_query_result
{
54 enum lttng_error_query_result_type type
;
59 struct lttng_error_query_result_comm
{
60 /* enum lttng_error_query_result_type */
62 /* Length of name (including null-terminator). */
64 /* Length of description (including null-terminator). */
65 uint32_t description_len
;
66 /* Name, description, and type-specific payload follow. */
70 struct lttng_error_query_result_counter_comm
{
74 struct lttng_error_query_result_counter
{
75 struct lttng_error_query_result parent
;
79 struct lttng_error_query_results_comm
{
81 /* `count` instances of `struct lttng_error_query_result` follow. */
85 struct lttng_error_query_results
{
86 struct lttng_dynamic_pointer_array results
;
90 enum lttng_error_code
lttng_error_query_result_mi_serialize(
91 const struct lttng_error_query_result
*result
,
92 struct mi_writer
*writer
);
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
);
99 struct lttng_error_query
*lttng_error_query_trigger_create(
100 const struct lttng_trigger
*trigger
)
102 struct lttng_error_query_trigger
*query
= NULL
;
103 struct lttng_trigger
*trigger_copy
= NULL
;
109 trigger_copy
= lttng_trigger_copy(trigger
);
114 query
= zmalloc(sizeof(*query
));
116 PERROR("Failed to allocate trigger error query");
120 query
->parent
.target_type
= LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
;
121 query
->trigger
= trigger_copy
;
125 lttng_trigger_put(trigger_copy
);
127 return query
? &query
->parent
: NULL
;
130 struct lttng_error_query
*lttng_error_query_condition_create(
131 const struct lttng_trigger
*trigger
)
133 struct lttng_error_query_condition
*query
= NULL
;
134 struct lttng_trigger
*trigger_copy
= NULL
;
140 trigger_copy
= lttng_trigger_copy(trigger
);
145 query
= zmalloc(sizeof(*query
));
147 PERROR("Failed to allocate condition error query");
151 query
->parent
.target_type
= LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
;
152 query
->trigger
= trigger_copy
;
156 lttng_trigger_put(trigger_copy
);
158 return query
? &query
->parent
: NULL
;
162 struct lttng_action
*get_trigger_action_from_path(
163 struct lttng_trigger
*trigger
,
164 const struct lttng_action_path
*action_path
)
166 size_t index_count
, i
;
167 enum lttng_action_path_status path_status
;
168 struct lttng_action
*current_action
= NULL
;
170 path_status
= lttng_action_path_get_index_count(
171 action_path
, &index_count
);
172 if (path_status
!= LTTNG_ACTION_PATH_STATUS_OK
) {
176 current_action
= lttng_trigger_get_action(trigger
);
177 for (i
= 0; i
< index_count
; i
++) {
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. */
191 return current_action
;
195 bool is_valid_action_path(const struct lttng_trigger
*trigger
,
196 const struct lttng_action_path
*action_path
)
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.
202 return !!get_trigger_action_from_path(
203 (struct lttng_trigger
*) trigger
, action_path
);
206 struct lttng_error_query
*lttng_error_query_action_create(
207 const struct lttng_trigger
*trigger
,
208 const struct lttng_action_path
*action_path
)
210 struct lttng_error_query_action
*query
= NULL
;
211 struct lttng_trigger
*trigger_copy
= NULL
;
214 if (!trigger
|| !action_path
||
215 !is_valid_action_path(trigger
, action_path
)) {
219 trigger_copy
= lttng_trigger_copy(trigger
);
224 query
= zmalloc(sizeof(*query
));
226 PERROR("Failed to allocate action error query");
230 ret_copy
= lttng_action_path_copy(action_path
, &query
->action_path
);
235 query
->parent
.target_type
= LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
;
236 query
->trigger
= trigger_copy
;
241 lttng_trigger_put(trigger_copy
);
242 lttng_error_query_destroy(query
? &query
->parent
: NULL
);
244 return query
? &query
->parent
: NULL
;
247 void lttng_error_query_destroy(struct lttng_error_query
*query
)
253 switch (query
->target_type
) {
254 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
:
256 struct lttng_error_query_trigger
*trigger_query
=
257 container_of(query
, typeof(*trigger_query
),
260 lttng_trigger_put(trigger_query
->trigger
);
264 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
266 struct lttng_error_query_condition
*condition_query
=
267 container_of(query
, typeof(*condition_query
),
270 lttng_trigger_put(condition_query
->trigger
);
271 free(condition_query
);
274 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
276 struct lttng_error_query_action
*action_query
=
277 container_of(query
, typeof(*action_query
),
280 lttng_trigger_put(action_query
->trigger
);
281 lttng_action_path_destroy(action_query
->action_path
);
291 int lttng_error_query_result_counter_serialize(
292 const struct lttng_error_query_result
*result
,
293 struct lttng_payload
*payload
)
295 const struct lttng_error_query_result_counter
*counter_result
;
297 assert(result
->type
== LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
);
298 counter_result
= container_of(result
, typeof(*counter_result
), parent
);
300 return lttng_dynamic_buffer_append(&payload
->buffer
,
301 &(struct lttng_error_query_result_counter_comm
) {
302 .value
= counter_result
->value
304 sizeof(struct lttng_error_query_result_counter_comm
));
308 int lttng_error_query_result_serialize(
309 const struct lttng_error_query_result
*result
,
310 struct lttng_payload
*payload
)
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,
320 ret
= lttng_dynamic_buffer_append(
321 &payload
->buffer
, &header
, sizeof(header
));
323 ERR("Failed to append error query result communication header to payload");
328 ret
= lttng_dynamic_buffer_append(
329 &payload
->buffer
, result
->name
, header
.name_len
);
331 ERR("Failed to append error query result name to payload");
336 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, result
->description
,
337 header
.description_len
);
339 ERR("Failed to append error query result description to payload");
343 /* Type-specific payload. */
344 switch (result
->type
) {
345 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
346 ret
= lttng_error_query_result_counter_serialize(
349 ERR("Failed to serialize counter error query result");
362 int lttng_error_query_result_init(
363 struct lttng_error_query_result
*result
,
364 enum lttng_error_query_result_type result_type
,
366 const char *description
)
373 result
->type
= result_type
;
375 result
->name
= strdup(name
);
377 PERROR("Failed to copy error query result name");
382 result
->description
= strdup(description
);
383 if (!result
->description
) {
384 PERROR("Failed to copy error query result description");
395 void lttng_error_query_result_destroy(struct lttng_error_query_result
*counter
)
401 switch (counter
->type
) {
402 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
403 /* Nothing to tear down. */
410 free(counter
->description
);
415 struct lttng_error_query_result
*
416 lttng_error_query_result_counter_create(
417 const char *name
, const char *description
, uint64_t value
)
420 struct lttng_error_query_result_counter
*counter
;
422 counter
= zmalloc(sizeof(*counter
));
424 PERROR("Failed to allocate error query counter result");
428 init_ret
= lttng_error_query_result_init(&counter
->parent
,
429 LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
, name
,
435 counter
->value
= value
;
438 lttng_error_query_result_destroy(&counter
->parent
);
440 return counter
? &counter
->parent
: NULL
;
444 void destroy_result(void *ptr
)
446 struct lttng_error_query_result
*result
= (typeof(result
)) ptr
;
448 lttng_error_query_result_destroy(result
);
452 struct lttng_error_query_results
*lttng_error_query_results_create(void)
454 struct lttng_error_query_results
*set
= zmalloc(sizeof(*set
));
457 PERROR("Failed to allocate an error query result set");
461 lttng_dynamic_pointer_array_init(&set
->results
, destroy_result
);
467 int lttng_error_query_results_add_result(
468 struct lttng_error_query_results
*results
,
469 struct lttng_error_query_result
*result
)
471 return lttng_dynamic_pointer_array_add_pointer(
472 &results
->results
, result
);
476 ssize_t
lttng_error_query_result_create_from_payload(
477 struct lttng_payload_view
*view
,
478 struct lttng_error_query_result
**result
)
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
));
485 const char *description
;
487 if (!lttng_payload_view_is_valid(&header_view
)) {
492 header
= (typeof(header
)) header_view
.buffer
.data
;
493 used_size
+= sizeof(*header
);
496 struct lttng_payload_view name_view
=
497 lttng_payload_view_from_view(view
, used_size
,
500 if (!lttng_payload_view_is_valid(&name_view
) ||
501 !lttng_buffer_view_contains_string(
503 name_view
.buffer
.data
,
509 name
= name_view
.buffer
.data
;
510 used_size
+= header
->name_len
;
514 struct lttng_payload_view description_view
=
515 lttng_payload_view_from_view(view
, used_size
,
516 header
->description_len
);
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
)) {
527 description
= description_view
.buffer
.data
;
528 used_size
+= header
->description_len
;
531 switch (header
->type
) {
532 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
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
,
539 if (!lttng_payload_view_is_valid(&counter_payload_view
)) {
544 counter
= (typeof(counter
)) counter_payload_view
.buffer
.data
;
545 *result
= lttng_error_query_result_counter_create(
546 name
, description
, counter
->value
);
552 used_size
+= sizeof(*counter
);
565 int lttng_error_query_results_serialize(
566 const struct lttng_error_query_results
*results
,
567 struct lttng_payload
*payload
)
571 const size_t result_count
= lttng_dynamic_pointer_array_get_count(
573 const struct lttng_error_query_results_comm header
= {
574 .count
= (typeof(header
.count
)) result_count
,
578 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &header
, sizeof(header
));
580 ERR("Failed to append error query result set header to payload");
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(
591 ret
= lttng_error_query_result_serialize(result
, payload
);
593 ERR("Failed to append error query result to payload");
602 ssize_t
lttng_error_query_results_create_from_payload(
603 struct lttng_payload_view
*view
,
604 struct lttng_error_query_results
**_results
)
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
;
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;
619 header
= (typeof(header
)) header_view
.buffer
.data
;
620 total_used_size
+= sizeof(*header
);
621 results
= lttng_error_query_results_create();
623 total_used_size
= -1;
627 for (result_index
= 0; result_index
< header
->count
; result_index
++) {
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);
634 if (!lttng_payload_view_is_valid(&result_view
)) {
635 total_used_size
= -1;
639 used_size
= lttng_error_query_result_create_from_payload(
640 &result_view
, &result
);
642 total_used_size
= -1;
646 total_used_size
+= used_size
;
648 if (lttng_dynamic_pointer_array_add_pointer(
649 &results
->results
, result
)) {
650 lttng_error_query_result_destroy(result
);
651 total_used_size
= -1;
659 lttng_error_query_results_destroy(results
);
660 return total_used_size
;
664 int lttng_error_query_trigger_serialize(const struct lttng_error_query
*query
,
665 struct lttng_payload
*payload
)
668 const struct lttng_error_query_trigger
*query_trigger
=
669 container_of(query
, typeof(*query_trigger
), parent
);
671 if (!lttng_trigger_validate(query_trigger
->trigger
)) {
676 ret
= lttng_trigger_serialize(query_trigger
->trigger
, payload
);
686 int lttng_error_query_condition_serialize(const struct lttng_error_query
*query
,
687 struct lttng_payload
*payload
)
690 const struct lttng_error_query_condition
*query_trigger
=
691 container_of(query
, typeof(*query_trigger
), parent
);
693 if (!lttng_trigger_validate(query_trigger
->trigger
)) {
698 ret
= lttng_trigger_serialize(query_trigger
->trigger
, payload
);
708 int lttng_error_query_action_serialize(const struct lttng_error_query
*query
,
709 struct lttng_payload
*payload
)
712 const struct lttng_error_query_action
*query_action
=
713 container_of(query
, typeof(*query_action
), parent
);
715 if (!lttng_trigger_validate(query_action
->trigger
)) {
720 ret
= lttng_trigger_serialize(query_action
->trigger
, payload
);
725 ret
= lttng_action_path_serialize(query_action
->action_path
, payload
);
735 enum lttng_error_query_target_type
lttng_error_query_get_target_type(
736 const struct lttng_error_query
*query
)
738 return query
->target_type
;
742 const struct lttng_trigger
*lttng_error_query_trigger_borrow_target(
743 const struct lttng_error_query
*query
)
745 const struct lttng_error_query_trigger
*query_trigger
=
746 container_of(query
, typeof(*query_trigger
), parent
);
748 return query_trigger
->trigger
;
752 const struct lttng_trigger
*lttng_error_query_condition_borrow_target(
753 const struct lttng_error_query
*query
)
755 const struct lttng_error_query_condition
*query_trigger
=
756 container_of(query
, typeof(*query_trigger
), parent
);
758 return query_trigger
->trigger
;
762 const struct lttng_trigger
*lttng_error_query_action_borrow_trigger_target(
763 const struct lttng_error_query
*query
)
765 const struct lttng_error_query_action
*query_action
=
766 container_of(query
, typeof(*query_action
), parent
);
768 return query_action
->trigger
;
772 struct lttng_action
*lttng_error_query_action_borrow_action_target(
773 const struct lttng_error_query
*query
,
774 struct lttng_trigger
*trigger
)
776 const struct lttng_error_query_action
*query_action
=
777 container_of(query
, typeof(*query_action
), parent
);
779 return get_trigger_action_from_path(
780 trigger
, query_action
->action_path
);
784 int lttng_error_query_serialize(const struct lttng_error_query
*query
,
785 struct lttng_payload
*payload
)
788 const struct lttng_error_query_comm header
= {
789 .target_type
= (typeof(header
.target_type
)) query
->target_type
,
792 ret
= lttng_dynamic_buffer_append(
793 &payload
->buffer
, &header
, sizeof(header
));
795 ERR("Failed to append error query header to payload");
799 switch (query
->target_type
) {
800 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
:
801 ret
= lttng_error_query_trigger_serialize(query
, payload
);
807 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
808 ret
= lttng_error_query_condition_serialize(query
, payload
);
814 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
815 ret
= lttng_error_query_action_serialize(query
, payload
);
829 ssize_t
lttng_error_query_create_from_payload(struct lttng_payload_view
*view
,
830 struct lttng_error_query
**query
)
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
));
838 if (!lttng_payload_view_is_valid(&header_view
)) {
839 ERR("Failed to map error query header");
844 used_size
= sizeof(*header
);
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
:
850 ssize_t trigger_used_size
;
851 struct lttng_payload_view trigger_view
=
852 lttng_payload_view_from_view(
853 view
, used_size
, -1);
855 if (!lttng_payload_view_is_valid(&trigger_view
)) {
860 trigger_used_size
= lttng_trigger_create_from_payload(
861 &trigger_view
, &trigger
);
862 if (trigger_used_size
< 0) {
867 used_size
+= trigger_used_size
;
869 *query
= lttng_error_query_trigger_create(trigger
);
877 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
879 ssize_t trigger_used_size
;
880 struct lttng_payload_view trigger_view
=
881 lttng_payload_view_from_view(
882 view
, used_size
, -1);
884 if (!lttng_payload_view_is_valid(&trigger_view
)) {
889 trigger_used_size
= lttng_trigger_create_from_payload(
890 &trigger_view
, &trigger
);
891 if (trigger_used_size
< 0) {
896 used_size
+= trigger_used_size
;
898 *query
= lttng_error_query_condition_create(trigger
);
906 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
908 struct lttng_action_path
*action_path
= NULL
;
911 ssize_t trigger_used_size
;
912 struct lttng_payload_view trigger_view
=
913 lttng_payload_view_from_view(
914 view
, used_size
, -1);
916 if (!lttng_payload_view_is_valid(&trigger_view
)) {
921 trigger_used_size
= lttng_trigger_create_from_payload(
922 &trigger_view
, &trigger
);
923 if (trigger_used_size
< 0) {
928 used_size
+= trigger_used_size
;
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);
937 if (!lttng_payload_view_is_valid(&action_path_view
)) {
942 action_path_used_size
= lttng_action_path_create_from_payload(
943 &action_path_view
, &action_path
);
944 if (action_path_used_size
< 0) {
949 used_size
+= action_path_used_size
;
952 *query
= lttng_error_query_action_create(
953 trigger
, action_path
);
954 lttng_action_path_destroy(action_path
);
968 lttng_trigger_put(trigger
);
972 enum lttng_error_query_results_status
lttng_error_query_results_get_count(
973 const struct lttng_error_query_results
*results
,
976 enum lttng_error_query_results_status status
;
978 if (!results
|| !count
) {
979 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
983 *count
= lttng_dynamic_pointer_array_get_count(&results
->results
);
984 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
;
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
,
995 unsigned int result_count
;
996 enum lttng_error_query_results_status status
;
998 if (!results
|| !result
) {
999 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
1003 status
= lttng_error_query_results_get_count(results
, &result_count
);
1004 if (status
!= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
) {
1008 if (index
>= result_count
) {
1009 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
1013 *result
= (typeof(*result
)) lttng_dynamic_pointer_array_get_pointer(
1014 &results
->results
, index
);
1016 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
;
1021 void lttng_error_query_results_destroy(
1022 struct lttng_error_query_results
*results
)
1028 lttng_dynamic_pointer_array_reset(&results
->results
);
1032 enum lttng_error_query_result_type
1033 lttng_error_query_result_get_type(const struct lttng_error_query_result
*result
)
1035 return result
? result
->type
: LTTNG_ERROR_QUERY_RESULT_TYPE_UNKNOWN
;
1038 enum lttng_error_query_result_status
lttng_error_query_result_get_name(
1039 const struct lttng_error_query_result
*result
,
1042 enum lttng_error_query_result_status status
;
1044 if (!result
|| !name
) {
1045 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1049 *name
= result
->name
;
1050 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
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
)
1059 enum lttng_error_query_result_status status
;
1061 if (!result
|| !description
) {
1062 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1066 *description
= result
->description
;
1067 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
1072 enum lttng_error_query_result_status
lttng_error_query_result_counter_get_value(
1073 const struct lttng_error_query_result
*result
,
1076 enum lttng_error_query_result_status status
;
1077 const struct lttng_error_query_result_counter
*counter_result
;
1079 if (!result
|| !value
||
1080 result
->type
!= LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
) {
1081 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1085 counter_result
= container_of(result
, typeof(*counter_result
), parent
);
1087 *value
= counter_result
->value
;
1088 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
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
)
1099 enum lttng_error_code ret_code
;
1100 enum lttng_error_query_result_status status
;
1106 status
= lttng_error_query_result_counter_get_value(result
, &value
);
1107 assert(status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1109 /* Open error query result counter element. */
1110 ret
= mi_lttng_writer_open_element(
1111 writer
, mi_lttng_element_error_query_result_counter
);
1117 ret
= mi_lttng_writer_write_element_unsigned_int(writer
,
1118 mi_lttng_element_error_query_result_counter_value
,
1124 /* Close error query result counter element. */
1125 ret
= mi_lttng_writer_close_element(writer
);
1130 ret_code
= LTTNG_OK
;
1134 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
1140 enum lttng_error_code
lttng_error_query_result_mi_serialize(
1141 const struct lttng_error_query_result
*result
,
1142 struct mi_writer
*writer
)
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
;
1154 type
= lttng_error_query_result_get_type(result
);
1156 result_status
= lttng_error_query_result_get_name(result
, &name
);
1157 assert(result_status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1159 result_status
= lttng_error_query_result_get_description(
1160 result
, &description
);
1161 assert(result_status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1163 /* Open error query result element. */
1164 ret
= mi_lttng_writer_open_element(
1165 writer
, mi_lttng_element_error_query_result
);
1171 ret
= mi_lttng_writer_write_element_string(
1172 writer
, mi_lttng_element_error_query_result_name
, name
);
1178 ret
= mi_lttng_writer_write_element_string(writer
,
1179 mi_lttng_element_error_query_result_description
,
1185 /* Serialize the result according to its sub type. */
1187 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
1188 ret_code
= lttng_error_query_result_counter_mi_serialize(
1195 if (ret_code
!= LTTNG_OK
) {
1199 /* Close error query result element. */
1200 ret
= mi_lttng_writer_close_element(writer
);
1205 ret_code
= LTTNG_OK
;
1209 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
1215 enum lttng_error_code
lttng_error_query_results_mi_serialize(
1216 const struct lttng_error_query_results
*results
,
1217 struct mi_writer
*writer
)
1220 enum lttng_error_code ret_code
;
1221 unsigned int i
, count
;
1222 enum lttng_error_query_results_status results_status
;
1227 /* Open error query results element. */
1228 ret
= mi_lttng_writer_open_element(
1229 writer
, mi_lttng_element_error_query_results
);
1234 results_status
= lttng_error_query_results_get_count(results
, &count
);
1235 assert(results_status
== LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
);
1237 for (i
= 0; i
< count
; i
++) {
1238 const struct lttng_error_query_result
*result
;
1240 results_status
= lttng_error_query_results_get_result(
1241 results
, &result
, i
);
1242 assert(results_status
== LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
);
1244 /* A single error query result. */
1245 ret_code
= lttng_error_query_result_mi_serialize(result
, writer
);
1246 if (ret_code
!= LTTNG_OK
) {
1251 /* Close error query results. */
1252 ret
= mi_lttng_writer_close_element(writer
);
1257 ret_code
= LTTNG_OK
;
1261 ret_code
= LTTNG_ERR_MI_IO_FAIL
;