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
)
249 struct lttng_error_query_trigger
*trigger_query
;
255 trigger_query
= container_of(query
, typeof(*trigger_query
), parent
);
256 lttng_trigger_put(trigger_query
->trigger
);
261 int lttng_error_query_result_counter_serialize(
262 const struct lttng_error_query_result
*result
,
263 struct lttng_payload
*payload
)
265 const struct lttng_error_query_result_counter
*counter_result
;
267 LTTNG_ASSERT(result
->type
== LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
);
268 counter_result
= container_of(result
, typeof(*counter_result
), parent
);
270 return lttng_dynamic_buffer_append(&payload
->buffer
,
271 &(struct lttng_error_query_result_counter_comm
) {
272 .value
= counter_result
->value
274 sizeof(struct lttng_error_query_result_counter_comm
));
277 int lttng_error_query_result_serialize(
278 const struct lttng_error_query_result
*result
,
279 struct lttng_payload
*payload
)
282 struct lttng_error_query_result_comm header
= {
283 .type
= (uint8_t) result
->type
,
284 .name_len
= (typeof(header
.name_len
)) strlen(result
->name
) + 1,
285 .description_len
= (typeof(header
.name_len
)) strlen(result
->description
) + 1,
289 ret
= lttng_dynamic_buffer_append(
290 &payload
->buffer
, &header
, sizeof(header
));
292 ERR("Failed to append error query result communication header to payload");
297 ret
= lttng_dynamic_buffer_append(
298 &payload
->buffer
, result
->name
, header
.name_len
);
300 ERR("Failed to append error query result name to payload");
305 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, result
->description
,
306 header
.description_len
);
308 ERR("Failed to append error query result description to payload");
312 /* Type-specific payload. */
313 switch (result
->type
) {
314 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
315 ret
= lttng_error_query_result_counter_serialize(
318 ERR("Failed to serialize counter error query result");
331 int lttng_error_query_result_init(
332 struct lttng_error_query_result
*result
,
333 enum lttng_error_query_result_type result_type
,
335 const char *description
)
340 LTTNG_ASSERT(description
);
342 result
->type
= result_type
;
344 result
->name
= strdup(name
);
346 PERROR("Failed to copy error query result name");
351 result
->description
= strdup(description
);
352 if (!result
->description
) {
353 PERROR("Failed to copy error query result description");
363 void lttng_error_query_result_destroy(struct lttng_error_query_result
*counter
)
369 switch (counter
->type
) {
370 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
371 /* Nothing to tear down. */
378 free(counter
->description
);
382 struct lttng_error_query_result
*
383 lttng_error_query_result_counter_create(
384 const char *name
, const char *description
, uint64_t value
)
387 struct lttng_error_query_result_counter
*counter
;
389 counter
= zmalloc(sizeof(*counter
));
391 PERROR("Failed to allocate error query counter result");
395 init_ret
= lttng_error_query_result_init(&counter
->parent
,
396 LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
, name
,
402 counter
->value
= value
;
405 lttng_error_query_result_destroy(&counter
->parent
);
407 return counter
? &counter
->parent
: NULL
;
411 void destroy_result(void *ptr
)
413 struct lttng_error_query_result
*result
= (typeof(result
)) ptr
;
415 lttng_error_query_result_destroy(result
);
418 struct lttng_error_query_results
*lttng_error_query_results_create(void)
420 struct lttng_error_query_results
*set
= zmalloc(sizeof(*set
));
423 PERROR("Failed to allocate an error query result set");
427 lttng_dynamic_pointer_array_init(&set
->results
, destroy_result
);
432 int lttng_error_query_results_add_result(
433 struct lttng_error_query_results
*results
,
434 struct lttng_error_query_result
*result
)
436 return lttng_dynamic_pointer_array_add_pointer(
437 &results
->results
, result
);
440 ssize_t
lttng_error_query_result_create_from_payload(
441 struct lttng_payload_view
*view
,
442 struct lttng_error_query_result
**result
)
444 ssize_t used_size
= 0;
445 struct lttng_error_query_result_comm
*header
;
446 struct lttng_payload_view header_view
=
447 lttng_payload_view_from_view(view
, 0, sizeof(*header
));
449 const char *description
;
451 if (!lttng_payload_view_is_valid(&header_view
)) {
456 header
= (typeof(header
)) header_view
.buffer
.data
;
457 used_size
+= sizeof(*header
);
460 struct lttng_payload_view name_view
=
461 lttng_payload_view_from_view(view
, used_size
,
464 if (!lttng_payload_view_is_valid(&name_view
) ||
465 !lttng_buffer_view_contains_string(
467 name_view
.buffer
.data
,
473 name
= name_view
.buffer
.data
;
474 used_size
+= header
->name_len
;
478 struct lttng_payload_view description_view
=
479 lttng_payload_view_from_view(view
, used_size
,
480 header
->description_len
);
482 if (!lttng_payload_view_is_valid(&description_view
) ||
483 !lttng_buffer_view_contains_string(
484 &description_view
.buffer
,
485 description_view
.buffer
.data
,
486 header
->description_len
)) {
491 description
= description_view
.buffer
.data
;
492 used_size
+= header
->description_len
;
495 switch (header
->type
) {
496 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
498 struct lttng_error_query_result_counter_comm
*counter
;
499 struct lttng_payload_view counter_payload_view
=
500 lttng_payload_view_from_view(view
, used_size
,
503 if (!lttng_payload_view_is_valid(&counter_payload_view
)) {
508 counter
= (typeof(counter
)) counter_payload_view
.buffer
.data
;
509 *result
= lttng_error_query_result_counter_create(
510 name
, description
, counter
->value
);
516 used_size
+= sizeof(*counter
);
528 int lttng_error_query_results_serialize(
529 const struct lttng_error_query_results
*results
,
530 struct lttng_payload
*payload
)
534 const size_t result_count
= lttng_dynamic_pointer_array_get_count(
536 const struct lttng_error_query_results_comm header
= {
537 .count
= (typeof(header
.count
)) result_count
,
541 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &header
, sizeof(header
));
543 ERR("Failed to append error query result set header to payload");
548 for (result_index
= 0; result_index
< result_count
; result_index
++) {
549 const struct lttng_error_query_result
*result
= (typeof(result
))
550 lttng_dynamic_pointer_array_get_pointer(
554 ret
= lttng_error_query_result_serialize(result
, payload
);
556 ERR("Failed to append error query result to payload");
564 ssize_t
lttng_error_query_results_create_from_payload(
565 struct lttng_payload_view
*view
,
566 struct lttng_error_query_results
**_results
)
569 ssize_t total_used_size
= 0;
570 struct lttng_error_query_results_comm
*header
;
571 struct lttng_payload_view header_view
=
572 lttng_payload_view_from_view(view
, 0, sizeof(*header
));
573 struct lttng_error_query_results
*results
= NULL
;
575 if (!lttng_payload_view_is_valid(&header_view
)) {
576 ERR("Failed to map view to error query result set header");
577 total_used_size
= -1;
581 header
= (typeof(header
)) header_view
.buffer
.data
;
582 total_used_size
+= sizeof(*header
);
583 results
= lttng_error_query_results_create();
585 total_used_size
= -1;
589 for (result_index
= 0; result_index
< header
->count
; result_index
++) {
591 struct lttng_error_query_result
*result
;
592 struct lttng_payload_view result_view
=
593 lttng_payload_view_from_view(
594 view
, total_used_size
, -1);
596 if (!lttng_payload_view_is_valid(&result_view
)) {
597 total_used_size
= -1;
601 used_size
= lttng_error_query_result_create_from_payload(
602 &result_view
, &result
);
604 total_used_size
= -1;
608 total_used_size
+= used_size
;
610 if (lttng_dynamic_pointer_array_add_pointer(
611 &results
->results
, result
)) {
612 lttng_error_query_result_destroy(result
);
613 total_used_size
= -1;
621 lttng_error_query_results_destroy(results
);
622 return total_used_size
;
626 int lttng_error_query_trigger_serialize(const struct lttng_error_query
*query
,
627 struct lttng_payload
*payload
)
630 const struct lttng_error_query_trigger
*query_trigger
=
631 container_of(query
, typeof(*query_trigger
), parent
);
633 if (!lttng_trigger_validate(query_trigger
->trigger
)) {
638 ret
= lttng_trigger_serialize(query_trigger
->trigger
, payload
);
648 int lttng_error_query_condition_serialize(const struct lttng_error_query
*query
,
649 struct lttng_payload
*payload
)
652 const struct lttng_error_query_condition
*query_trigger
=
653 container_of(query
, typeof(*query_trigger
), parent
);
655 if (!lttng_trigger_validate(query_trigger
->trigger
)) {
660 ret
= lttng_trigger_serialize(query_trigger
->trigger
, payload
);
670 int lttng_error_query_action_serialize(const struct lttng_error_query
*query
,
671 struct lttng_payload
*payload
)
674 const struct lttng_error_query_action
*query_action
=
675 container_of(query
, typeof(*query_action
), parent
);
677 if (!lttng_trigger_validate(query_action
->trigger
)) {
682 ret
= lttng_trigger_serialize(query_action
->trigger
, payload
);
687 ret
= lttng_action_path_serialize(&query_action
->action_path
, payload
);
696 enum lttng_error_query_target_type
lttng_error_query_get_target_type(
697 const struct lttng_error_query
*query
)
699 return query
->target_type
;
702 const struct lttng_trigger
*lttng_error_query_trigger_borrow_target(
703 const struct lttng_error_query
*query
)
705 const struct lttng_error_query_trigger
*query_trigger
=
706 container_of(query
, typeof(*query_trigger
), parent
);
708 return query_trigger
->trigger
;
711 const struct lttng_trigger
*lttng_error_query_condition_borrow_target(
712 const struct lttng_error_query
*query
)
714 const struct lttng_error_query_condition
*query_trigger
=
715 container_of(query
, typeof(*query_trigger
), parent
);
717 return query_trigger
->trigger
;
720 const struct lttng_trigger
*lttng_error_query_action_borrow_trigger_target(
721 const struct lttng_error_query
*query
)
723 const struct lttng_error_query_action
*query_action
=
724 container_of(query
, typeof(*query_action
), parent
);
726 return query_action
->trigger
;
729 struct lttng_action
*lttng_error_query_action_borrow_action_target(
730 const struct lttng_error_query
*query
,
731 struct lttng_trigger
*trigger
)
733 const struct lttng_error_query_action
*query_action
=
734 container_of(query
, typeof(*query_action
), parent
);
736 return get_trigger_action_from_path(
737 trigger
, &query_action
->action_path
);
740 int lttng_error_query_serialize(const struct lttng_error_query
*query
,
741 struct lttng_payload
*payload
)
744 const struct lttng_error_query_comm header
= {
745 .target_type
= (typeof(header
.target_type
)) query
->target_type
,
748 ret
= lttng_dynamic_buffer_append(
749 &payload
->buffer
, &header
, sizeof(header
));
751 ERR("Failed to append error query header to payload");
755 switch (query
->target_type
) {
756 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
:
757 ret
= lttng_error_query_trigger_serialize(query
, payload
);
763 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
764 ret
= lttng_error_query_condition_serialize(query
, payload
);
770 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
771 ret
= lttng_error_query_action_serialize(query
, payload
);
784 ssize_t
lttng_error_query_create_from_payload(struct lttng_payload_view
*view
,
785 struct lttng_error_query
**query
)
787 ssize_t used_size
= 0;
788 struct lttng_error_query_comm
*header
;
789 struct lttng_trigger
*trigger
= NULL
;
790 struct lttng_payload_view header_view
=
791 lttng_payload_view_from_view(view
, 0, sizeof(*header
));
793 if (!lttng_payload_view_is_valid(&header_view
)) {
794 ERR("Failed to map error query header");
799 used_size
= sizeof(*header
);
801 header
= (typeof(header
)) header_view
.buffer
.data
;
802 switch ((enum lttng_error_query_target_type
) header
->target_type
) {
803 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
:
805 ssize_t trigger_used_size
;
806 struct lttng_payload_view trigger_view
=
807 lttng_payload_view_from_view(
808 view
, used_size
, -1);
810 if (!lttng_payload_view_is_valid(&trigger_view
)) {
815 trigger_used_size
= lttng_trigger_create_from_payload(
816 &trigger_view
, &trigger
);
817 if (trigger_used_size
< 0) {
822 used_size
+= trigger_used_size
;
824 *query
= lttng_error_query_trigger_create(trigger
);
832 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
834 ssize_t trigger_used_size
;
835 struct lttng_payload_view trigger_view
=
836 lttng_payload_view_from_view(
837 view
, used_size
, -1);
839 if (!lttng_payload_view_is_valid(&trigger_view
)) {
844 trigger_used_size
= lttng_trigger_create_from_payload(
845 &trigger_view
, &trigger
);
846 if (trigger_used_size
< 0) {
851 used_size
+= trigger_used_size
;
853 *query
= lttng_error_query_condition_create(trigger
);
861 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
863 struct lttng_action_path
*action_path
= NULL
;
866 ssize_t trigger_used_size
;
867 struct lttng_payload_view trigger_view
=
868 lttng_payload_view_from_view(
869 view
, used_size
, -1);
871 if (!lttng_payload_view_is_valid(&trigger_view
)) {
876 trigger_used_size
= lttng_trigger_create_from_payload(
877 &trigger_view
, &trigger
);
878 if (trigger_used_size
< 0) {
883 used_size
+= trigger_used_size
;
887 ssize_t action_path_used_size
;
888 struct lttng_payload_view action_path_view
=
889 lttng_payload_view_from_view(
890 view
, used_size
, -1);
892 if (!lttng_payload_view_is_valid(&action_path_view
)) {
897 action_path_used_size
= lttng_action_path_create_from_payload(
898 &action_path_view
, &action_path
);
899 if (action_path_used_size
< 0) {
904 used_size
+= action_path_used_size
;
907 *query
= lttng_error_query_action_create(
908 trigger
, action_path
);
909 lttng_action_path_destroy(action_path
);
923 lttng_trigger_put(trigger
);
927 enum lttng_error_query_results_status
lttng_error_query_results_get_count(
928 const struct lttng_error_query_results
*results
,
931 enum lttng_error_query_results_status status
;
933 if (!results
|| !count
) {
934 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
938 *count
= lttng_dynamic_pointer_array_get_count(&results
->results
);
939 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
;
944 enum lttng_error_query_results_status
945 lttng_error_query_results_get_result(
946 const struct lttng_error_query_results
*results
,
947 const struct lttng_error_query_result
**result
,
950 unsigned int result_count
;
951 enum lttng_error_query_results_status status
;
953 if (!results
|| !result
) {
954 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
958 status
= lttng_error_query_results_get_count(results
, &result_count
);
959 if (status
!= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
) {
963 if (index
>= result_count
) {
964 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
968 *result
= (typeof(*result
)) lttng_dynamic_pointer_array_get_pointer(
969 &results
->results
, index
);
970 LTTNG_ASSERT(*result
);
971 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
;
976 void lttng_error_query_results_destroy(
977 struct lttng_error_query_results
*results
)
983 lttng_dynamic_pointer_array_reset(&results
->results
);
987 enum lttng_error_query_result_type
988 lttng_error_query_result_get_type(const struct lttng_error_query_result
*result
)
990 return result
? result
->type
: LTTNG_ERROR_QUERY_RESULT_TYPE_UNKNOWN
;
993 enum lttng_error_query_result_status
lttng_error_query_result_get_name(
994 const struct lttng_error_query_result
*result
,
997 enum lttng_error_query_result_status status
;
999 if (!result
|| !name
) {
1000 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1004 *name
= result
->name
;
1005 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
1010 enum lttng_error_query_result_status
lttng_error_query_result_get_description(
1011 const struct lttng_error_query_result
*result
,
1012 const char **description
)
1014 enum lttng_error_query_result_status status
;
1016 if (!result
|| !description
) {
1017 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1021 *description
= result
->description
;
1022 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
1027 enum lttng_error_query_result_status
lttng_error_query_result_counter_get_value(
1028 const struct lttng_error_query_result
*result
,
1031 enum lttng_error_query_result_status status
;
1032 const struct lttng_error_query_result_counter
*counter_result
;
1034 if (!result
|| !value
||
1035 result
->type
!= LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
) {
1036 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1040 counter_result
= container_of(result
, typeof(*counter_result
), parent
);
1042 *value
= counter_result
->value
;
1043 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
1049 enum lttng_error_code
lttng_error_query_result_counter_mi_serialize(
1050 const struct lttng_error_query_result
*result
,
1051 struct mi_writer
*writer
)
1054 enum lttng_error_code ret_code
;
1055 enum lttng_error_query_result_status status
;
1058 LTTNG_ASSERT(result
);
1059 LTTNG_ASSERT(writer
);
1061 status
= lttng_error_query_result_counter_get_value(result
, &value
);
1062 LTTNG_ASSERT(status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1064 /* Open error query result counter element. */
1065 ret
= mi_lttng_writer_open_element(
1066 writer
, mi_lttng_element_error_query_result_counter
);
1072 ret
= mi_lttng_writer_write_element_unsigned_int(writer
,
1073 mi_lttng_element_error_query_result_counter_value
,
1079 /* Close error query result counter element. */
1080 ret
= mi_lttng_writer_close_element(writer
);
1085 ret_code
= LTTNG_OK
;
1089 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
1095 enum lttng_error_code
lttng_error_query_result_mi_serialize(
1096 const struct lttng_error_query_result
*result
,
1097 struct mi_writer
*writer
)
1100 enum lttng_error_code ret_code
;
1101 enum lttng_error_query_result_status result_status
;
1102 enum lttng_error_query_result_type type
;
1103 const char *name
= NULL
;
1104 const char *description
= NULL
;
1106 LTTNG_ASSERT(result
);
1107 LTTNG_ASSERT(writer
);
1109 type
= lttng_error_query_result_get_type(result
);
1111 result_status
= lttng_error_query_result_get_name(result
, &name
);
1112 LTTNG_ASSERT(result_status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1114 result_status
= lttng_error_query_result_get_description(
1115 result
, &description
);
1116 LTTNG_ASSERT(result_status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1118 /* Open error query result element. */
1119 ret
= mi_lttng_writer_open_element(
1120 writer
, mi_lttng_element_error_query_result
);
1126 ret
= mi_lttng_writer_write_element_string(
1127 writer
, mi_lttng_element_error_query_result_name
, name
);
1133 ret
= mi_lttng_writer_write_element_string(writer
,
1134 mi_lttng_element_error_query_result_description
,
1140 /* Serialize the result according to its sub type. */
1142 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
1143 ret_code
= lttng_error_query_result_counter_mi_serialize(
1150 if (ret_code
!= LTTNG_OK
) {
1154 /* Close error query result element. */
1155 ret
= mi_lttng_writer_close_element(writer
);
1160 ret_code
= LTTNG_OK
;
1164 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
1169 enum lttng_error_code
lttng_error_query_results_mi_serialize(
1170 const struct lttng_error_query_results
*results
,
1171 struct mi_writer
*writer
)
1174 enum lttng_error_code ret_code
;
1175 unsigned int i
, count
;
1176 enum lttng_error_query_results_status results_status
;
1178 LTTNG_ASSERT(results
);
1179 LTTNG_ASSERT(writer
);
1181 /* Open error query results element. */
1182 ret
= mi_lttng_writer_open_element(
1183 writer
, mi_lttng_element_error_query_results
);
1188 results_status
= lttng_error_query_results_get_count(results
, &count
);
1189 LTTNG_ASSERT(results_status
== LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
);
1191 for (i
= 0; i
< count
; i
++) {
1192 const struct lttng_error_query_result
*result
;
1194 results_status
= lttng_error_query_results_get_result(
1195 results
, &result
, i
);
1196 LTTNG_ASSERT(results_status
== LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
);
1198 /* A single error query result. */
1199 ret_code
= lttng_error_query_result_mi_serialize(result
, writer
);
1200 if (ret_code
!= LTTNG_OK
) {
1205 /* Close error query results. */
1206 ret
= mi_lttng_writer_close_element(writer
);
1211 ret_code
= LTTNG_OK
;
1215 ret_code
= LTTNG_ERR_MI_IO_FAIL
;