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_result
{
28 enum lttng_error_query_result_type type
;
33 struct lttng_error_query_results
{
34 struct lttng_dynamic_pointer_array results
;
38 struct lttng_error_query_comm
{
39 /* enum lttng_error_query_target_type */
41 /* Target-specific payload. */
45 struct lttng_error_query_trigger
{
46 struct lttng_error_query parent
;
47 /* Mutable only because of the reference count. */
48 struct lttng_trigger
*trigger
;
51 struct lttng_error_query_condition
{
52 struct lttng_error_query parent
;
53 /* Mutable only because of the reference count. */
54 struct lttng_trigger
*trigger
;
57 struct lttng_error_query_action
{
58 struct lttng_error_query parent
;
59 /* Mutable only because of the reference count. */
60 struct lttng_trigger
*trigger
;
61 struct lttng_action_path action_path
;
64 struct lttng_error_query_result_comm
{
65 /* enum lttng_error_query_result_type */
67 /* Length of name (including null-terminator). */
69 /* Length of description (including null-terminator). */
70 uint32_t description_len
;
71 /* Name, description, and type-specific payload follow. */
75 struct lttng_error_query_result_counter_comm
{
79 struct lttng_error_query_result_counter
{
80 struct lttng_error_query_result parent
;
84 struct lttng_error_query_results_comm
{
86 /* `count` instances of `struct lttng_error_query_result` follow. */
92 enum lttng_error_code
lttng_error_query_result_mi_serialize(
93 const struct lttng_error_query_result
*result
,
94 struct mi_writer
*writer
);
97 enum lttng_error_code
lttng_error_query_result_counter_mi_serialize(
98 const struct lttng_error_query_result
*result
,
99 struct mi_writer
*writer
);
101 struct lttng_error_query
*lttng_error_query_trigger_create(
102 const struct lttng_trigger
*trigger
)
104 struct lttng_error_query_trigger
*query
= NULL
;
105 struct lttng_trigger
*trigger_copy
= NULL
;
111 trigger_copy
= lttng_trigger_copy(trigger
);
116 query
= zmalloc
<lttng_error_query_trigger
>();
118 PERROR("Failed to allocate trigger error query");
122 query
->parent
.target_type
= LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
;
123 query
->trigger
= trigger_copy
;
127 lttng_trigger_put(trigger_copy
);
129 return query
? &query
->parent
: NULL
;
132 struct lttng_error_query
*lttng_error_query_condition_create(
133 const struct lttng_trigger
*trigger
)
135 struct lttng_error_query_condition
*query
= NULL
;
136 struct lttng_trigger
*trigger_copy
= NULL
;
142 trigger_copy
= lttng_trigger_copy(trigger
);
147 query
= zmalloc
<lttng_error_query_condition
>();
149 PERROR("Failed to allocate condition error query");
153 query
->parent
.target_type
= LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
;
154 query
->trigger
= trigger_copy
;
158 lttng_trigger_put(trigger_copy
);
160 return query
? &query
->parent
: NULL
;
164 struct lttng_action
*get_trigger_action_from_path(
165 struct lttng_trigger
*trigger
,
166 const struct lttng_action_path
*action_path
)
168 size_t index_count
, i
;
169 enum lttng_action_path_status path_status
;
170 struct lttng_action
*current_action
= NULL
;
172 path_status
= lttng_action_path_get_index_count(
173 action_path
, &index_count
);
174 if (path_status
!= LTTNG_ACTION_PATH_STATUS_OK
) {
178 current_action
= lttng_trigger_get_action(trigger
);
179 for (i
= 0; i
< index_count
; i
++) {
182 path_status
= lttng_action_path_get_index_at_index(
183 action_path
, i
, &path_index
);
184 current_action
= lttng_action_list_borrow_mutable_at_index(
185 current_action
, path_index
);
186 if (!current_action
) {
187 /* Invalid action path. */
193 return current_action
;
197 bool is_valid_action_path(const struct lttng_trigger
*trigger
,
198 const struct lttng_action_path
*action_path
)
201 * While 'trigger's constness is casted-away, the trigger and resulting
202 * action are not modified; we merely check for the action's existence.
204 return !!get_trigger_action_from_path(
205 (struct lttng_trigger
*) trigger
, action_path
);
208 struct lttng_error_query
*lttng_error_query_action_create(
209 const struct lttng_trigger
*trigger
,
210 const struct lttng_action_path
*action_path
)
212 struct lttng_error_query_action
*query
= NULL
;
213 struct lttng_trigger
*trigger_copy
= NULL
;
216 if (!trigger
|| !action_path
||
217 !is_valid_action_path(trigger
, action_path
)) {
221 trigger_copy
= lttng_trigger_copy(trigger
);
226 query
= zmalloc
<lttng_error_query_action
>();
228 PERROR("Failed to allocate action error query");
232 ret_copy
= lttng_action_path_copy(action_path
, &query
->action_path
);
237 query
->parent
.target_type
= LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
;
238 query
->trigger
= trigger_copy
;
243 lttng_trigger_put(trigger_copy
);
244 lttng_error_query_destroy(query
? &query
->parent
: NULL
);
246 return query
? &query
->parent
: NULL
;
249 void lttng_error_query_destroy(struct lttng_error_query
*query
)
251 struct lttng_error_query_trigger
*trigger_query
;
257 trigger_query
= container_of(query
, typeof(*trigger_query
), parent
);
258 lttng_trigger_put(trigger_query
->trigger
);
263 int lttng_error_query_result_counter_serialize(
264 const struct lttng_error_query_result
*result
,
265 struct lttng_payload
*payload
)
267 const struct lttng_error_query_result_counter
*counter_result
;
269 LTTNG_ASSERT(result
->type
== LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
);
270 counter_result
= container_of(result
, typeof(*counter_result
), parent
);
272 lttng_error_query_result_counter_comm comm
= {
273 .value
= counter_result
->value
,
276 return lttng_dynamic_buffer_append(&payload
->buffer
,
278 sizeof(struct lttng_error_query_result_counter_comm
));
281 int lttng_error_query_result_serialize(
282 const struct lttng_error_query_result
*result
,
283 struct lttng_payload
*payload
)
286 struct lttng_error_query_result_comm header
= {
287 .type
= (uint8_t) result
->type
,
288 .name_len
= (typeof(header
.name_len
)) strlen(result
->name
) + 1,
289 .description_len
= (typeof(header
.name_len
)) strlen(result
->description
) + 1,
293 ret
= lttng_dynamic_buffer_append(
294 &payload
->buffer
, &header
, sizeof(header
));
296 ERR("Failed to append error query result communication header to payload");
301 ret
= lttng_dynamic_buffer_append(
302 &payload
->buffer
, result
->name
, header
.name_len
);
304 ERR("Failed to append error query result name to payload");
309 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, result
->description
,
310 header
.description_len
);
312 ERR("Failed to append error query result description to payload");
316 /* Type-specific payload. */
317 switch (result
->type
) {
318 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
319 ret
= lttng_error_query_result_counter_serialize(
322 ERR("Failed to serialize counter error query result");
335 int lttng_error_query_result_init(
336 struct lttng_error_query_result
*result
,
337 enum lttng_error_query_result_type result_type
,
339 const char *description
)
344 LTTNG_ASSERT(description
);
346 result
->type
= result_type
;
348 result
->name
= strdup(name
);
350 PERROR("Failed to copy error query result name");
355 result
->description
= strdup(description
);
356 if (!result
->description
) {
357 PERROR("Failed to copy error query result description");
367 void lttng_error_query_result_destroy(struct lttng_error_query_result
*counter
)
373 switch (counter
->type
) {
374 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
375 /* Nothing to tear down. */
382 free(counter
->description
);
386 struct lttng_error_query_result
*
387 lttng_error_query_result_counter_create(
388 const char *name
, const char *description
, uint64_t value
)
391 struct lttng_error_query_result_counter
*counter
;
393 counter
= zmalloc
<lttng_error_query_result_counter
>();
395 PERROR("Failed to allocate error query counter result");
399 init_ret
= lttng_error_query_result_init(&counter
->parent
,
400 LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
, name
,
406 counter
->value
= value
;
409 lttng_error_query_result_destroy(&counter
->parent
);
411 return counter
? &counter
->parent
: NULL
;
415 void destroy_result(void *ptr
)
417 struct lttng_error_query_result
*result
= (typeof(result
)) ptr
;
419 lttng_error_query_result_destroy(result
);
422 struct lttng_error_query_results
*lttng_error_query_results_create(void)
424 struct lttng_error_query_results
*set
= zmalloc
<lttng_error_query_results
>();
427 PERROR("Failed to allocate an error query result set");
431 lttng_dynamic_pointer_array_init(&set
->results
, destroy_result
);
436 int lttng_error_query_results_add_result(
437 struct lttng_error_query_results
*results
,
438 struct lttng_error_query_result
*result
)
440 return lttng_dynamic_pointer_array_add_pointer(
441 &results
->results
, result
);
444 ssize_t
lttng_error_query_result_create_from_payload(
445 struct lttng_payload_view
*view
,
446 struct lttng_error_query_result
**result
)
448 ssize_t used_size
= 0;
449 struct lttng_error_query_result_comm
*header
;
450 struct lttng_payload_view header_view
=
451 lttng_payload_view_from_view(view
, 0, sizeof(*header
));
453 const char *description
;
455 if (!lttng_payload_view_is_valid(&header_view
)) {
460 header
= (typeof(header
)) header_view
.buffer
.data
;
461 used_size
+= sizeof(*header
);
464 struct lttng_payload_view name_view
=
465 lttng_payload_view_from_view(view
, used_size
,
468 if (!lttng_payload_view_is_valid(&name_view
) ||
469 !lttng_buffer_view_contains_string(
471 name_view
.buffer
.data
,
477 name
= name_view
.buffer
.data
;
478 used_size
+= header
->name_len
;
482 struct lttng_payload_view description_view
=
483 lttng_payload_view_from_view(view
, used_size
,
484 header
->description_len
);
486 if (!lttng_payload_view_is_valid(&description_view
) ||
487 !lttng_buffer_view_contains_string(
488 &description_view
.buffer
,
489 description_view
.buffer
.data
,
490 header
->description_len
)) {
495 description
= description_view
.buffer
.data
;
496 used_size
+= header
->description_len
;
499 switch (header
->type
) {
500 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
502 struct lttng_error_query_result_counter_comm
*counter
;
503 struct lttng_payload_view counter_payload_view
=
504 lttng_payload_view_from_view(view
, used_size
,
507 if (!lttng_payload_view_is_valid(&counter_payload_view
)) {
512 counter
= (typeof(counter
)) counter_payload_view
.buffer
.data
;
513 *result
= lttng_error_query_result_counter_create(
514 name
, description
, counter
->value
);
520 used_size
+= sizeof(*counter
);
532 int lttng_error_query_results_serialize(
533 const struct lttng_error_query_results
*results
,
534 struct lttng_payload
*payload
)
538 const size_t result_count
= lttng_dynamic_pointer_array_get_count(
540 const struct lttng_error_query_results_comm header
= {
541 .count
= (decltype(header
.count
)) result_count
,
545 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &header
, sizeof(header
));
547 ERR("Failed to append error query result set header to payload");
552 for (result_index
= 0; result_index
< result_count
; result_index
++) {
553 const struct lttng_error_query_result
*result
= (typeof(result
))
554 lttng_dynamic_pointer_array_get_pointer(
558 ret
= lttng_error_query_result_serialize(result
, payload
);
560 ERR("Failed to append error query result to payload");
568 ssize_t
lttng_error_query_results_create_from_payload(
569 struct lttng_payload_view
*view
,
570 struct lttng_error_query_results
**_results
)
573 ssize_t total_used_size
= 0;
574 struct lttng_error_query_results_comm
*header
;
575 struct lttng_payload_view header_view
=
576 lttng_payload_view_from_view(view
, 0, sizeof(*header
));
577 struct lttng_error_query_results
*results
= NULL
;
579 if (!lttng_payload_view_is_valid(&header_view
)) {
580 ERR("Failed to map view to error query result set header");
581 total_used_size
= -1;
585 header
= (typeof(header
)) header_view
.buffer
.data
;
586 total_used_size
+= sizeof(*header
);
587 results
= lttng_error_query_results_create();
589 total_used_size
= -1;
593 for (result_index
= 0; result_index
< header
->count
; result_index
++) {
595 struct lttng_error_query_result
*result
;
596 struct lttng_payload_view result_view
=
597 lttng_payload_view_from_view(
598 view
, total_used_size
, -1);
600 if (!lttng_payload_view_is_valid(&result_view
)) {
601 total_used_size
= -1;
605 used_size
= lttng_error_query_result_create_from_payload(
606 &result_view
, &result
);
608 total_used_size
= -1;
612 total_used_size
+= used_size
;
614 if (lttng_dynamic_pointer_array_add_pointer(
615 &results
->results
, result
)) {
616 lttng_error_query_result_destroy(result
);
617 total_used_size
= -1;
625 lttng_error_query_results_destroy(results
);
626 return total_used_size
;
630 int lttng_error_query_trigger_serialize(const struct lttng_error_query
*query
,
631 struct lttng_payload
*payload
)
634 const struct lttng_error_query_trigger
*query_trigger
=
635 container_of(query
, typeof(*query_trigger
), parent
);
637 if (!lttng_trigger_validate(query_trigger
->trigger
)) {
642 ret
= lttng_trigger_serialize(query_trigger
->trigger
, payload
);
652 int lttng_error_query_condition_serialize(const struct lttng_error_query
*query
,
653 struct lttng_payload
*payload
)
656 const struct lttng_error_query_condition
*query_trigger
=
657 container_of(query
, typeof(*query_trigger
), parent
);
659 if (!lttng_trigger_validate(query_trigger
->trigger
)) {
664 ret
= lttng_trigger_serialize(query_trigger
->trigger
, payload
);
674 int lttng_error_query_action_serialize(const struct lttng_error_query
*query
,
675 struct lttng_payload
*payload
)
678 const struct lttng_error_query_action
*query_action
=
679 container_of(query
, typeof(*query_action
), parent
);
681 if (!lttng_trigger_validate(query_action
->trigger
)) {
686 ret
= lttng_trigger_serialize(query_action
->trigger
, payload
);
691 ret
= lttng_action_path_serialize(&query_action
->action_path
, payload
);
700 enum lttng_error_query_target_type
lttng_error_query_get_target_type(
701 const struct lttng_error_query
*query
)
703 return query
->target_type
;
706 const struct lttng_trigger
*lttng_error_query_trigger_borrow_target(
707 const struct lttng_error_query
*query
)
709 const struct lttng_error_query_trigger
*query_trigger
=
710 container_of(query
, typeof(*query_trigger
), parent
);
712 return query_trigger
->trigger
;
715 const struct lttng_trigger
*lttng_error_query_condition_borrow_target(
716 const struct lttng_error_query
*query
)
718 const struct lttng_error_query_condition
*query_trigger
=
719 container_of(query
, typeof(*query_trigger
), parent
);
721 return query_trigger
->trigger
;
724 const struct lttng_trigger
*lttng_error_query_action_borrow_trigger_target(
725 const struct lttng_error_query
*query
)
727 const struct lttng_error_query_action
*query_action
=
728 container_of(query
, typeof(*query_action
), parent
);
730 return query_action
->trigger
;
733 struct lttng_action
*lttng_error_query_action_borrow_action_target(
734 const struct lttng_error_query
*query
,
735 struct lttng_trigger
*trigger
)
737 const struct lttng_error_query_action
*query_action
=
738 container_of(query
, typeof(*query_action
), parent
);
740 return get_trigger_action_from_path(
741 trigger
, &query_action
->action_path
);
744 int lttng_error_query_serialize(const struct lttng_error_query
*query
,
745 struct lttng_payload
*payload
)
748 const struct lttng_error_query_comm header
= {
749 .target_type
= (decltype(header
.target_type
)) query
->target_type
,
752 ret
= lttng_dynamic_buffer_append(
753 &payload
->buffer
, &header
, sizeof(header
));
755 ERR("Failed to append error query header to payload");
759 switch (query
->target_type
) {
760 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
:
761 ret
= lttng_error_query_trigger_serialize(query
, payload
);
767 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
768 ret
= lttng_error_query_condition_serialize(query
, payload
);
774 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
775 ret
= lttng_error_query_action_serialize(query
, payload
);
788 ssize_t
lttng_error_query_create_from_payload(struct lttng_payload_view
*view
,
789 struct lttng_error_query
**query
)
791 ssize_t used_size
= 0;
792 struct lttng_error_query_comm
*header
;
793 struct lttng_trigger
*trigger
= NULL
;
794 struct lttng_payload_view header_view
=
795 lttng_payload_view_from_view(view
, 0, sizeof(*header
));
797 if (!lttng_payload_view_is_valid(&header_view
)) {
798 ERR("Failed to map error query header");
803 used_size
= sizeof(*header
);
805 header
= (typeof(header
)) header_view
.buffer
.data
;
806 switch ((enum lttng_error_query_target_type
) header
->target_type
) {
807 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
:
809 ssize_t trigger_used_size
;
810 struct lttng_payload_view trigger_view
=
811 lttng_payload_view_from_view(
812 view
, used_size
, -1);
814 if (!lttng_payload_view_is_valid(&trigger_view
)) {
819 trigger_used_size
= lttng_trigger_create_from_payload(
820 &trigger_view
, &trigger
);
821 if (trigger_used_size
< 0) {
826 used_size
+= trigger_used_size
;
828 *query
= lttng_error_query_trigger_create(trigger
);
836 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
838 ssize_t trigger_used_size
;
839 struct lttng_payload_view trigger_view
=
840 lttng_payload_view_from_view(
841 view
, used_size
, -1);
843 if (!lttng_payload_view_is_valid(&trigger_view
)) {
848 trigger_used_size
= lttng_trigger_create_from_payload(
849 &trigger_view
, &trigger
);
850 if (trigger_used_size
< 0) {
855 used_size
+= trigger_used_size
;
857 *query
= lttng_error_query_condition_create(trigger
);
865 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
867 struct lttng_action_path
*action_path
= NULL
;
870 ssize_t trigger_used_size
;
871 struct lttng_payload_view trigger_view
=
872 lttng_payload_view_from_view(
873 view
, used_size
, -1);
875 if (!lttng_payload_view_is_valid(&trigger_view
)) {
880 trigger_used_size
= lttng_trigger_create_from_payload(
881 &trigger_view
, &trigger
);
882 if (trigger_used_size
< 0) {
887 used_size
+= trigger_used_size
;
891 ssize_t action_path_used_size
;
892 struct lttng_payload_view action_path_view
=
893 lttng_payload_view_from_view(
894 view
, used_size
, -1);
896 if (!lttng_payload_view_is_valid(&action_path_view
)) {
901 action_path_used_size
= lttng_action_path_create_from_payload(
902 &action_path_view
, &action_path
);
903 if (action_path_used_size
< 0) {
908 used_size
+= action_path_used_size
;
911 *query
= lttng_error_query_action_create(
912 trigger
, action_path
);
913 lttng_action_path_destroy(action_path
);
927 lttng_trigger_put(trigger
);
931 enum lttng_error_query_results_status
lttng_error_query_results_get_count(
932 const struct lttng_error_query_results
*results
,
935 enum lttng_error_query_results_status status
;
937 if (!results
|| !count
) {
938 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
942 *count
= lttng_dynamic_pointer_array_get_count(&results
->results
);
943 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
;
948 enum lttng_error_query_results_status
949 lttng_error_query_results_get_result(
950 const struct lttng_error_query_results
*results
,
951 const struct lttng_error_query_result
**result
,
954 unsigned int result_count
;
955 enum lttng_error_query_results_status status
;
957 if (!results
|| !result
) {
958 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
962 status
= lttng_error_query_results_get_count(results
, &result_count
);
963 if (status
!= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
) {
967 if (index
>= result_count
) {
968 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
972 *result
= (typeof(*result
)) lttng_dynamic_pointer_array_get_pointer(
973 &results
->results
, index
);
974 LTTNG_ASSERT(*result
);
975 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
;
980 void lttng_error_query_results_destroy(
981 struct lttng_error_query_results
*results
)
987 lttng_dynamic_pointer_array_reset(&results
->results
);
991 enum lttng_error_query_result_type
992 lttng_error_query_result_get_type(const struct lttng_error_query_result
*result
)
994 return result
? result
->type
: LTTNG_ERROR_QUERY_RESULT_TYPE_UNKNOWN
;
997 enum lttng_error_query_result_status
lttng_error_query_result_get_name(
998 const struct lttng_error_query_result
*result
,
1001 enum lttng_error_query_result_status status
;
1003 if (!result
|| !name
) {
1004 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1008 *name
= result
->name
;
1009 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
1014 enum lttng_error_query_result_status
lttng_error_query_result_get_description(
1015 const struct lttng_error_query_result
*result
,
1016 const char **description
)
1018 enum lttng_error_query_result_status status
;
1020 if (!result
|| !description
) {
1021 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1025 *description
= result
->description
;
1026 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
1031 enum lttng_error_query_result_status
lttng_error_query_result_counter_get_value(
1032 const struct lttng_error_query_result
*result
,
1035 enum lttng_error_query_result_status status
;
1036 const struct lttng_error_query_result_counter
*counter_result
;
1038 if (!result
|| !value
||
1039 result
->type
!= LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
) {
1040 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1044 counter_result
= container_of(result
, typeof(*counter_result
), parent
);
1046 *value
= counter_result
->value
;
1047 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
1053 enum lttng_error_code
lttng_error_query_result_counter_mi_serialize(
1054 const struct lttng_error_query_result
*result
,
1055 struct mi_writer
*writer
)
1058 enum lttng_error_code ret_code
;
1059 enum lttng_error_query_result_status status
;
1062 LTTNG_ASSERT(result
);
1063 LTTNG_ASSERT(writer
);
1065 status
= lttng_error_query_result_counter_get_value(result
, &value
);
1066 LTTNG_ASSERT(status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1068 /* Open error query result counter element. */
1069 ret
= mi_lttng_writer_open_element(
1070 writer
, mi_lttng_element_error_query_result_counter
);
1076 ret
= mi_lttng_writer_write_element_unsigned_int(writer
,
1077 mi_lttng_element_error_query_result_counter_value
,
1083 /* Close error query result counter element. */
1084 ret
= mi_lttng_writer_close_element(writer
);
1089 ret_code
= LTTNG_OK
;
1093 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
1099 enum lttng_error_code
lttng_error_query_result_mi_serialize(
1100 const struct lttng_error_query_result
*result
,
1101 struct mi_writer
*writer
)
1104 enum lttng_error_code ret_code
;
1105 enum lttng_error_query_result_status result_status
;
1106 enum lttng_error_query_result_type type
;
1107 const char *name
= NULL
;
1108 const char *description
= NULL
;
1110 LTTNG_ASSERT(result
);
1111 LTTNG_ASSERT(writer
);
1113 type
= lttng_error_query_result_get_type(result
);
1115 result_status
= lttng_error_query_result_get_name(result
, &name
);
1116 LTTNG_ASSERT(result_status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1118 result_status
= lttng_error_query_result_get_description(
1119 result
, &description
);
1120 LTTNG_ASSERT(result_status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1122 /* Open error query result element. */
1123 ret
= mi_lttng_writer_open_element(
1124 writer
, mi_lttng_element_error_query_result
);
1130 ret
= mi_lttng_writer_write_element_string(
1131 writer
, mi_lttng_element_error_query_result_name
, name
);
1137 ret
= mi_lttng_writer_write_element_string(writer
,
1138 mi_lttng_element_error_query_result_description
,
1144 /* Serialize the result according to its sub type. */
1146 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
1147 ret_code
= lttng_error_query_result_counter_mi_serialize(
1154 if (ret_code
!= LTTNG_OK
) {
1158 /* Close error query result element. */
1159 ret
= mi_lttng_writer_close_element(writer
);
1164 ret_code
= LTTNG_OK
;
1168 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
1173 enum lttng_error_code
lttng_error_query_results_mi_serialize(
1174 const struct lttng_error_query_results
*results
,
1175 struct mi_writer
*writer
)
1178 enum lttng_error_code ret_code
;
1179 unsigned int i
, count
;
1180 enum lttng_error_query_results_status results_status
;
1182 LTTNG_ASSERT(results
);
1183 LTTNG_ASSERT(writer
);
1185 /* Open error query results element. */
1186 ret
= mi_lttng_writer_open_element(
1187 writer
, mi_lttng_element_error_query_results
);
1192 results_status
= lttng_error_query_results_get_count(results
, &count
);
1193 LTTNG_ASSERT(results_status
== LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
);
1195 for (i
= 0; i
< count
; i
++) {
1196 const struct lttng_error_query_result
*result
;
1198 results_status
= lttng_error_query_results_get_result(
1199 results
, &result
, i
);
1200 LTTNG_ASSERT(results_status
== LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
);
1202 /* A single error query result. */
1203 ret_code
= lttng_error_query_result_mi_serialize(result
, writer
);
1204 if (ret_code
!= LTTNG_OK
) {
1209 /* Close error query results. */
1210 ret
= mi_lttng_writer_close_element(writer
);
1215 ret_code
= LTTNG_OK
;
1219 ret_code
= LTTNG_ERR_MI_IO_FAIL
;