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.hpp>
11 #include <common/error.hpp>
12 #include <common/macros.hpp>
13 #include <common/mi-lttng.hpp>
14 #include <common/sessiond-comm/sessiond-comm.hpp>
15 #include <lttng/action/action-internal.hpp>
16 #include <lttng/action/list-internal.hpp>
17 #include <lttng/action/path-internal.hpp>
18 #include <lttng/error-query-internal.hpp>
19 #include <lttng/error-query.h>
20 #include <lttng/trigger/trigger-internal.hpp>
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
<lttng_error_query_trigger
>();
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
<lttng_error_query_condition
>();
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
<lttng_error_query_action
>();
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 lttng_error_query_result_counter_comm comm
= {
271 .value
= counter_result
->value
,
274 return lttng_dynamic_buffer_append(&payload
->buffer
,
276 sizeof(struct lttng_error_query_result_counter_comm
));
279 int lttng_error_query_result_serialize(
280 const struct lttng_error_query_result
*result
,
281 struct lttng_payload
*payload
)
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,
291 ret
= lttng_dynamic_buffer_append(
292 &payload
->buffer
, &header
, sizeof(header
));
294 ERR("Failed to append error query result communication header to payload");
299 ret
= lttng_dynamic_buffer_append(
300 &payload
->buffer
, result
->name
, header
.name_len
);
302 ERR("Failed to append error query result name to payload");
307 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, result
->description
,
308 header
.description_len
);
310 ERR("Failed to append error query result description to payload");
314 /* Type-specific payload. */
315 switch (result
->type
) {
316 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
317 ret
= lttng_error_query_result_counter_serialize(
320 ERR("Failed to serialize counter error query result");
333 int lttng_error_query_result_init(
334 struct lttng_error_query_result
*result
,
335 enum lttng_error_query_result_type result_type
,
337 const char *description
)
342 LTTNG_ASSERT(description
);
344 result
->type
= result_type
;
346 result
->name
= strdup(name
);
348 PERROR("Failed to copy error query result name");
353 result
->description
= strdup(description
);
354 if (!result
->description
) {
355 PERROR("Failed to copy error query result description");
365 void lttng_error_query_result_destroy(struct lttng_error_query_result
*counter
)
371 switch (counter
->type
) {
372 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
373 /* Nothing to tear down. */
380 free(counter
->description
);
384 struct lttng_error_query_result
*
385 lttng_error_query_result_counter_create(
386 const char *name
, const char *description
, uint64_t value
)
389 struct lttng_error_query_result_counter
*counter
;
391 counter
= zmalloc
<lttng_error_query_result_counter
>();
393 PERROR("Failed to allocate error query counter result");
397 init_ret
= lttng_error_query_result_init(&counter
->parent
,
398 LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
, name
,
404 counter
->value
= value
;
407 lttng_error_query_result_destroy(&counter
->parent
);
409 return counter
? &counter
->parent
: NULL
;
413 void destroy_result(void *ptr
)
415 struct lttng_error_query_result
*result
= (typeof(result
)) ptr
;
417 lttng_error_query_result_destroy(result
);
420 struct lttng_error_query_results
*lttng_error_query_results_create(void)
422 struct lttng_error_query_results
*set
= zmalloc
<lttng_error_query_results
>();
425 PERROR("Failed to allocate an error query result set");
429 lttng_dynamic_pointer_array_init(&set
->results
, destroy_result
);
434 int lttng_error_query_results_add_result(
435 struct lttng_error_query_results
*results
,
436 struct lttng_error_query_result
*result
)
438 return lttng_dynamic_pointer_array_add_pointer(
439 &results
->results
, result
);
442 ssize_t
lttng_error_query_result_create_from_payload(
443 struct lttng_payload_view
*view
,
444 struct lttng_error_query_result
**result
)
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
));
451 const char *description
;
453 if (!lttng_payload_view_is_valid(&header_view
)) {
458 header
= (typeof(header
)) header_view
.buffer
.data
;
459 used_size
+= sizeof(*header
);
462 struct lttng_payload_view name_view
=
463 lttng_payload_view_from_view(view
, used_size
,
466 if (!lttng_payload_view_is_valid(&name_view
) ||
467 !lttng_buffer_view_contains_string(
469 name_view
.buffer
.data
,
475 name
= name_view
.buffer
.data
;
476 used_size
+= header
->name_len
;
480 struct lttng_payload_view description_view
=
481 lttng_payload_view_from_view(view
, used_size
,
482 header
->description_len
);
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
)) {
493 description
= description_view
.buffer
.data
;
494 used_size
+= header
->description_len
;
497 switch (header
->type
) {
498 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
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
,
505 if (!lttng_payload_view_is_valid(&counter_payload_view
)) {
510 counter
= (typeof(counter
)) counter_payload_view
.buffer
.data
;
511 *result
= lttng_error_query_result_counter_create(
512 name
, description
, counter
->value
);
518 used_size
+= sizeof(*counter
);
530 int lttng_error_query_results_serialize(
531 const struct lttng_error_query_results
*results
,
532 struct lttng_payload
*payload
)
536 const size_t result_count
= lttng_dynamic_pointer_array_get_count(
538 const struct lttng_error_query_results_comm header
= {
539 .count
= (decltype(header
.count
)) result_count
,
543 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &header
, sizeof(header
));
545 ERR("Failed to append error query result set header to payload");
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(
556 ret
= lttng_error_query_result_serialize(result
, payload
);
558 ERR("Failed to append error query result to payload");
566 ssize_t
lttng_error_query_results_create_from_payload(
567 struct lttng_payload_view
*view
,
568 struct lttng_error_query_results
**_results
)
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
;
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;
583 header
= (typeof(header
)) header_view
.buffer
.data
;
584 total_used_size
+= sizeof(*header
);
585 results
= lttng_error_query_results_create();
587 total_used_size
= -1;
591 for (result_index
= 0; result_index
< header
->count
; result_index
++) {
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);
598 if (!lttng_payload_view_is_valid(&result_view
)) {
599 total_used_size
= -1;
603 used_size
= lttng_error_query_result_create_from_payload(
604 &result_view
, &result
);
606 total_used_size
= -1;
610 total_used_size
+= used_size
;
612 if (lttng_dynamic_pointer_array_add_pointer(
613 &results
->results
, result
)) {
614 lttng_error_query_result_destroy(result
);
615 total_used_size
= -1;
623 lttng_error_query_results_destroy(results
);
624 return total_used_size
;
628 int lttng_error_query_trigger_serialize(const struct lttng_error_query
*query
,
629 struct lttng_payload
*payload
)
632 const struct lttng_error_query_trigger
*query_trigger
=
633 container_of(query
, typeof(*query_trigger
), parent
);
635 if (!lttng_trigger_validate(query_trigger
->trigger
)) {
640 ret
= lttng_trigger_serialize(query_trigger
->trigger
, payload
);
650 int lttng_error_query_condition_serialize(const struct lttng_error_query
*query
,
651 struct lttng_payload
*payload
)
654 const struct lttng_error_query_condition
*query_trigger
=
655 container_of(query
, typeof(*query_trigger
), parent
);
657 if (!lttng_trigger_validate(query_trigger
->trigger
)) {
662 ret
= lttng_trigger_serialize(query_trigger
->trigger
, payload
);
672 int lttng_error_query_action_serialize(const struct lttng_error_query
*query
,
673 struct lttng_payload
*payload
)
676 const struct lttng_error_query_action
*query_action
=
677 container_of(query
, typeof(*query_action
), parent
);
679 if (!lttng_trigger_validate(query_action
->trigger
)) {
684 ret
= lttng_trigger_serialize(query_action
->trigger
, payload
);
689 ret
= lttng_action_path_serialize(&query_action
->action_path
, payload
);
698 enum lttng_error_query_target_type
lttng_error_query_get_target_type(
699 const struct lttng_error_query
*query
)
701 return query
->target_type
;
704 const struct lttng_trigger
*lttng_error_query_trigger_borrow_target(
705 const struct lttng_error_query
*query
)
707 const struct lttng_error_query_trigger
*query_trigger
=
708 container_of(query
, typeof(*query_trigger
), parent
);
710 return query_trigger
->trigger
;
713 const struct lttng_trigger
*lttng_error_query_condition_borrow_target(
714 const struct lttng_error_query
*query
)
716 const struct lttng_error_query_condition
*query_trigger
=
717 container_of(query
, typeof(*query_trigger
), parent
);
719 return query_trigger
->trigger
;
722 const struct lttng_trigger
*lttng_error_query_action_borrow_trigger_target(
723 const struct lttng_error_query
*query
)
725 const struct lttng_error_query_action
*query_action
=
726 container_of(query
, typeof(*query_action
), parent
);
728 return query_action
->trigger
;
731 struct lttng_action
*lttng_error_query_action_borrow_action_target(
732 const struct lttng_error_query
*query
,
733 struct lttng_trigger
*trigger
)
735 const struct lttng_error_query_action
*query_action
=
736 container_of(query
, typeof(*query_action
), parent
);
738 return get_trigger_action_from_path(
739 trigger
, &query_action
->action_path
);
742 int lttng_error_query_serialize(const struct lttng_error_query
*query
,
743 struct lttng_payload
*payload
)
746 const struct lttng_error_query_comm header
= {
747 .target_type
= (decltype(header
.target_type
)) query
->target_type
,
750 ret
= lttng_dynamic_buffer_append(
751 &payload
->buffer
, &header
, sizeof(header
));
753 ERR("Failed to append error query header to payload");
757 switch (query
->target_type
) {
758 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
:
759 ret
= lttng_error_query_trigger_serialize(query
, payload
);
765 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
766 ret
= lttng_error_query_condition_serialize(query
, payload
);
772 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
773 ret
= lttng_error_query_action_serialize(query
, payload
);
786 ssize_t
lttng_error_query_create_from_payload(struct lttng_payload_view
*view
,
787 struct lttng_error_query
**query
)
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
));
795 if (!lttng_payload_view_is_valid(&header_view
)) {
796 ERR("Failed to map error query header");
801 used_size
= sizeof(*header
);
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
:
807 ssize_t trigger_used_size
;
808 struct lttng_payload_view trigger_view
=
809 lttng_payload_view_from_view(
810 view
, used_size
, -1);
812 if (!lttng_payload_view_is_valid(&trigger_view
)) {
817 trigger_used_size
= lttng_trigger_create_from_payload(
818 &trigger_view
, &trigger
);
819 if (trigger_used_size
< 0) {
824 used_size
+= trigger_used_size
;
826 *query
= lttng_error_query_trigger_create(trigger
);
834 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
836 ssize_t trigger_used_size
;
837 struct lttng_payload_view trigger_view
=
838 lttng_payload_view_from_view(
839 view
, used_size
, -1);
841 if (!lttng_payload_view_is_valid(&trigger_view
)) {
846 trigger_used_size
= lttng_trigger_create_from_payload(
847 &trigger_view
, &trigger
);
848 if (trigger_used_size
< 0) {
853 used_size
+= trigger_used_size
;
855 *query
= lttng_error_query_condition_create(trigger
);
863 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
865 struct lttng_action_path
*action_path
= NULL
;
868 ssize_t trigger_used_size
;
869 struct lttng_payload_view trigger_view
=
870 lttng_payload_view_from_view(
871 view
, used_size
, -1);
873 if (!lttng_payload_view_is_valid(&trigger_view
)) {
878 trigger_used_size
= lttng_trigger_create_from_payload(
879 &trigger_view
, &trigger
);
880 if (trigger_used_size
< 0) {
885 used_size
+= trigger_used_size
;
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);
894 if (!lttng_payload_view_is_valid(&action_path_view
)) {
899 action_path_used_size
= lttng_action_path_create_from_payload(
900 &action_path_view
, &action_path
);
901 if (action_path_used_size
< 0) {
906 used_size
+= action_path_used_size
;
909 *query
= lttng_error_query_action_create(
910 trigger
, action_path
);
911 lttng_action_path_destroy(action_path
);
925 lttng_trigger_put(trigger
);
929 enum lttng_error_query_results_status
lttng_error_query_results_get_count(
930 const struct lttng_error_query_results
*results
,
933 enum lttng_error_query_results_status status
;
935 if (!results
|| !count
) {
936 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
940 *count
= lttng_dynamic_pointer_array_get_count(&results
->results
);
941 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
;
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
,
952 unsigned int result_count
;
953 enum lttng_error_query_results_status status
;
955 if (!results
|| !result
) {
956 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
960 status
= lttng_error_query_results_get_count(results
, &result_count
);
961 if (status
!= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
) {
965 if (index
>= result_count
) {
966 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
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
;
978 void lttng_error_query_results_destroy(
979 struct lttng_error_query_results
*results
)
985 lttng_dynamic_pointer_array_reset(&results
->results
);
989 enum lttng_error_query_result_type
990 lttng_error_query_result_get_type(const struct lttng_error_query_result
*result
)
992 return result
? result
->type
: LTTNG_ERROR_QUERY_RESULT_TYPE_UNKNOWN
;
995 enum lttng_error_query_result_status
lttng_error_query_result_get_name(
996 const struct lttng_error_query_result
*result
,
999 enum lttng_error_query_result_status status
;
1001 if (!result
|| !name
) {
1002 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1006 *name
= result
->name
;
1007 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
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
)
1016 enum lttng_error_query_result_status status
;
1018 if (!result
|| !description
) {
1019 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1023 *description
= result
->description
;
1024 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
1029 enum lttng_error_query_result_status
lttng_error_query_result_counter_get_value(
1030 const struct lttng_error_query_result
*result
,
1033 enum lttng_error_query_result_status status
;
1034 const struct lttng_error_query_result_counter
*counter_result
;
1036 if (!result
|| !value
||
1037 result
->type
!= LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
) {
1038 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1042 counter_result
= container_of(result
, typeof(*counter_result
), parent
);
1044 *value
= counter_result
->value
;
1045 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
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
)
1056 enum lttng_error_code ret_code
;
1057 enum lttng_error_query_result_status status
;
1060 LTTNG_ASSERT(result
);
1061 LTTNG_ASSERT(writer
);
1063 status
= lttng_error_query_result_counter_get_value(result
, &value
);
1064 LTTNG_ASSERT(status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1066 /* Open error query result counter element. */
1067 ret
= mi_lttng_writer_open_element(
1068 writer
, mi_lttng_element_error_query_result_counter
);
1074 ret
= mi_lttng_writer_write_element_unsigned_int(writer
,
1075 mi_lttng_element_error_query_result_counter_value
,
1081 /* Close error query result counter element. */
1082 ret
= mi_lttng_writer_close_element(writer
);
1087 ret_code
= LTTNG_OK
;
1091 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
1097 enum lttng_error_code
lttng_error_query_result_mi_serialize(
1098 const struct lttng_error_query_result
*result
,
1099 struct mi_writer
*writer
)
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
;
1108 LTTNG_ASSERT(result
);
1109 LTTNG_ASSERT(writer
);
1111 type
= lttng_error_query_result_get_type(result
);
1113 result_status
= lttng_error_query_result_get_name(result
, &name
);
1114 LTTNG_ASSERT(result_status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1116 result_status
= lttng_error_query_result_get_description(
1117 result
, &description
);
1118 LTTNG_ASSERT(result_status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1120 /* Open error query result element. */
1121 ret
= mi_lttng_writer_open_element(
1122 writer
, mi_lttng_element_error_query_result
);
1128 ret
= mi_lttng_writer_write_element_string(
1129 writer
, mi_lttng_element_error_query_result_name
, name
);
1135 ret
= mi_lttng_writer_write_element_string(writer
,
1136 mi_lttng_element_error_query_result_description
,
1142 /* Serialize the result according to its sub type. */
1144 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
1145 ret_code
= lttng_error_query_result_counter_mi_serialize(
1152 if (ret_code
!= LTTNG_OK
) {
1156 /* Close error query result element. */
1157 ret
= mi_lttng_writer_close_element(writer
);
1162 ret_code
= LTTNG_OK
;
1166 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
1171 enum lttng_error_code
lttng_error_query_results_mi_serialize(
1172 const struct lttng_error_query_results
*results
,
1173 struct mi_writer
*writer
)
1176 enum lttng_error_code ret_code
;
1177 unsigned int i
, count
;
1178 enum lttng_error_query_results_status results_status
;
1180 LTTNG_ASSERT(results
);
1181 LTTNG_ASSERT(writer
);
1183 /* Open error query results element. */
1184 ret
= mi_lttng_writer_open_element(
1185 writer
, mi_lttng_element_error_query_results
);
1190 results_status
= lttng_error_query_results_get_count(results
, &count
);
1191 LTTNG_ASSERT(results_status
== LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
);
1193 for (i
= 0; i
< count
; i
++) {
1194 const struct lttng_error_query_result
*result
;
1196 results_status
= lttng_error_query_results_get_result(
1197 results
, &result
, i
);
1198 LTTNG_ASSERT(results_status
== LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
);
1200 /* A single error query result. */
1201 ret_code
= lttng_error_query_result_mi_serialize(result
, writer
);
1202 if (ret_code
!= LTTNG_OK
) {
1207 /* Close error query results. */
1208 ret
= mi_lttng_writer_close_element(writer
);
1213 ret_code
= LTTNG_OK
;
1217 ret_code
= LTTNG_ERR_MI_IO_FAIL
;