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
)
255 switch (query
->target_type
) {
256 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
:
258 struct lttng_error_query_trigger
*trigger_query
=
259 container_of(query
, typeof(*trigger_query
),
262 lttng_trigger_put(trigger_query
->trigger
);
266 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
268 struct lttng_error_query_condition
*condition_query
=
269 container_of(query
, typeof(*condition_query
),
272 lttng_trigger_put(condition_query
->trigger
);
273 free(condition_query
);
276 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
278 struct lttng_error_query_action
*action_query
=
279 container_of(query
, typeof(*action_query
),
282 lttng_trigger_put(action_query
->trigger
);
283 lttng_action_path_destroy(action_query
->action_path
);
293 int lttng_error_query_result_counter_serialize(
294 const struct lttng_error_query_result
*result
,
295 struct lttng_payload
*payload
)
297 const struct lttng_error_query_result_counter
*counter_result
;
299 LTTNG_ASSERT(result
->type
== LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
);
300 counter_result
= container_of(result
, typeof(*counter_result
), parent
);
302 lttng_error_query_result_counter_comm comm
= {
303 .value
= counter_result
->value
,
306 return lttng_dynamic_buffer_append(&payload
->buffer
,
308 sizeof(struct lttng_error_query_result_counter_comm
));
311 int lttng_error_query_result_serialize(
312 const struct lttng_error_query_result
*result
,
313 struct lttng_payload
*payload
)
316 struct lttng_error_query_result_comm header
= {
317 .type
= (uint8_t) result
->type
,
318 .name_len
= (typeof(header
.name_len
)) strlen(result
->name
) + 1,
319 .description_len
= (typeof(header
.name_len
)) strlen(result
->description
) + 1,
323 ret
= lttng_dynamic_buffer_append(
324 &payload
->buffer
, &header
, sizeof(header
));
326 ERR("Failed to append error query result communication header to payload");
331 ret
= lttng_dynamic_buffer_append(
332 &payload
->buffer
, result
->name
, header
.name_len
);
334 ERR("Failed to append error query result name to payload");
339 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, result
->description
,
340 header
.description_len
);
342 ERR("Failed to append error query result description to payload");
346 /* Type-specific payload. */
347 switch (result
->type
) {
348 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
349 ret
= lttng_error_query_result_counter_serialize(
352 ERR("Failed to serialize counter error query result");
365 int lttng_error_query_result_init(
366 struct lttng_error_query_result
*result
,
367 enum lttng_error_query_result_type result_type
,
369 const char *description
)
374 LTTNG_ASSERT(description
);
376 result
->type
= result_type
;
378 result
->name
= strdup(name
);
380 PERROR("Failed to copy error query result name");
385 result
->description
= strdup(description
);
386 if (!result
->description
) {
387 PERROR("Failed to copy error query result description");
397 void lttng_error_query_result_destroy(struct lttng_error_query_result
*counter
)
403 switch (counter
->type
) {
404 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
405 /* Nothing to tear down. */
412 free(counter
->description
);
416 struct lttng_error_query_result
*
417 lttng_error_query_result_counter_create(
418 const char *name
, const char *description
, uint64_t value
)
421 struct lttng_error_query_result_counter
*counter
;
423 counter
= zmalloc
<lttng_error_query_result_counter
>();
425 PERROR("Failed to allocate error query counter result");
429 init_ret
= lttng_error_query_result_init(&counter
->parent
,
430 LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
, name
,
436 counter
->value
= value
;
439 lttng_error_query_result_destroy(&counter
->parent
);
441 return counter
? &counter
->parent
: NULL
;
445 void destroy_result(void *ptr
)
447 struct lttng_error_query_result
*result
= (typeof(result
)) ptr
;
449 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
<lttng_error_query_results
>();
457 PERROR("Failed to allocate an error query result set");
461 lttng_dynamic_pointer_array_init(&set
->results
, destroy_result
);
466 int lttng_error_query_results_add_result(
467 struct lttng_error_query_results
*results
,
468 struct lttng_error_query_result
*result
)
470 return lttng_dynamic_pointer_array_add_pointer(
471 &results
->results
, result
);
474 ssize_t
lttng_error_query_result_create_from_payload(
475 struct lttng_payload_view
*view
,
476 struct lttng_error_query_result
**result
)
478 ssize_t used_size
= 0;
479 struct lttng_error_query_result_comm
*header
;
480 struct lttng_payload_view header_view
=
481 lttng_payload_view_from_view(view
, 0, sizeof(*header
));
483 const char *description
;
485 if (!lttng_payload_view_is_valid(&header_view
)) {
490 header
= (typeof(header
)) header_view
.buffer
.data
;
491 used_size
+= sizeof(*header
);
494 struct lttng_payload_view name_view
=
495 lttng_payload_view_from_view(view
, used_size
,
498 if (!lttng_payload_view_is_valid(&name_view
) ||
499 !lttng_buffer_view_contains_string(
501 name_view
.buffer
.data
,
507 name
= name_view
.buffer
.data
;
508 used_size
+= header
->name_len
;
512 struct lttng_payload_view description_view
=
513 lttng_payload_view_from_view(view
, used_size
,
514 header
->description_len
);
516 if (!lttng_payload_view_is_valid(&description_view
) ||
517 !lttng_buffer_view_contains_string(
518 &description_view
.buffer
,
519 description_view
.buffer
.data
,
520 header
->description_len
)) {
525 description
= description_view
.buffer
.data
;
526 used_size
+= header
->description_len
;
529 switch (header
->type
) {
530 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
532 struct lttng_error_query_result_counter_comm
*counter
;
533 struct lttng_payload_view counter_payload_view
=
534 lttng_payload_view_from_view(view
, used_size
,
537 if (!lttng_payload_view_is_valid(&counter_payload_view
)) {
542 counter
= (typeof(counter
)) counter_payload_view
.buffer
.data
;
543 *result
= lttng_error_query_result_counter_create(
544 name
, description
, counter
->value
);
550 used_size
+= sizeof(*counter
);
562 int lttng_error_query_results_serialize(
563 const struct lttng_error_query_results
*results
,
564 struct lttng_payload
*payload
)
568 const size_t result_count
= lttng_dynamic_pointer_array_get_count(
570 const struct lttng_error_query_results_comm header
= {
571 .count
= (decltype(header
.count
)) result_count
,
575 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &header
, sizeof(header
));
577 ERR("Failed to append error query result set header to payload");
582 for (result_index
= 0; result_index
< result_count
; result_index
++) {
583 const struct lttng_error_query_result
*result
= (typeof(result
))
584 lttng_dynamic_pointer_array_get_pointer(
588 ret
= lttng_error_query_result_serialize(result
, payload
);
590 ERR("Failed to append error query result to payload");
598 ssize_t
lttng_error_query_results_create_from_payload(
599 struct lttng_payload_view
*view
,
600 struct lttng_error_query_results
**_results
)
603 ssize_t total_used_size
= 0;
604 struct lttng_error_query_results_comm
*header
;
605 struct lttng_payload_view header_view
=
606 lttng_payload_view_from_view(view
, 0, sizeof(*header
));
607 struct lttng_error_query_results
*results
= NULL
;
609 if (!lttng_payload_view_is_valid(&header_view
)) {
610 ERR("Failed to map view to error query result set header");
611 total_used_size
= -1;
615 header
= (typeof(header
)) header_view
.buffer
.data
;
616 total_used_size
+= sizeof(*header
);
617 results
= lttng_error_query_results_create();
619 total_used_size
= -1;
623 for (result_index
= 0; result_index
< header
->count
; result_index
++) {
625 struct lttng_error_query_result
*result
;
626 struct lttng_payload_view result_view
=
627 lttng_payload_view_from_view(
628 view
, total_used_size
, -1);
630 if (!lttng_payload_view_is_valid(&result_view
)) {
631 total_used_size
= -1;
635 used_size
= lttng_error_query_result_create_from_payload(
636 &result_view
, &result
);
638 total_used_size
= -1;
642 total_used_size
+= used_size
;
644 if (lttng_dynamic_pointer_array_add_pointer(
645 &results
->results
, result
)) {
646 lttng_error_query_result_destroy(result
);
647 total_used_size
= -1;
655 lttng_error_query_results_destroy(results
);
656 return total_used_size
;
660 int lttng_error_query_trigger_serialize(const struct lttng_error_query
*query
,
661 struct lttng_payload
*payload
)
664 const struct lttng_error_query_trigger
*query_trigger
=
665 container_of(query
, typeof(*query_trigger
), parent
);
667 if (!lttng_trigger_validate(query_trigger
->trigger
)) {
672 ret
= lttng_trigger_serialize(query_trigger
->trigger
, payload
);
682 int lttng_error_query_condition_serialize(const struct lttng_error_query
*query
,
683 struct lttng_payload
*payload
)
686 const struct lttng_error_query_condition
*query_trigger
=
687 container_of(query
, typeof(*query_trigger
), parent
);
689 if (!lttng_trigger_validate(query_trigger
->trigger
)) {
694 ret
= lttng_trigger_serialize(query_trigger
->trigger
, payload
);
704 int lttng_error_query_action_serialize(const struct lttng_error_query
*query
,
705 struct lttng_payload
*payload
)
708 const struct lttng_error_query_action
*query_action
=
709 container_of(query
, typeof(*query_action
), parent
);
711 if (!lttng_trigger_validate(query_action
->trigger
)) {
716 ret
= lttng_trigger_serialize(query_action
->trigger
, payload
);
721 ret
= lttng_action_path_serialize(query_action
->action_path
, payload
);
730 enum lttng_error_query_target_type
lttng_error_query_get_target_type(
731 const struct lttng_error_query
*query
)
733 return query
->target_type
;
736 const struct lttng_trigger
*lttng_error_query_trigger_borrow_target(
737 const struct lttng_error_query
*query
)
739 const struct lttng_error_query_trigger
*query_trigger
=
740 container_of(query
, typeof(*query_trigger
), parent
);
742 return query_trigger
->trigger
;
745 const struct lttng_trigger
*lttng_error_query_condition_borrow_target(
746 const struct lttng_error_query
*query
)
748 const struct lttng_error_query_condition
*query_trigger
=
749 container_of(query
, typeof(*query_trigger
), parent
);
751 return query_trigger
->trigger
;
754 const struct lttng_trigger
*lttng_error_query_action_borrow_trigger_target(
755 const struct lttng_error_query
*query
)
757 const struct lttng_error_query_action
*query_action
=
758 container_of(query
, typeof(*query_action
), parent
);
760 return query_action
->trigger
;
763 struct lttng_action
*lttng_error_query_action_borrow_action_target(
764 const struct lttng_error_query
*query
,
765 struct lttng_trigger
*trigger
)
767 const struct lttng_error_query_action
*query_action
=
768 container_of(query
, typeof(*query_action
), parent
);
770 return get_trigger_action_from_path(
771 trigger
, query_action
->action_path
);
774 int lttng_error_query_serialize(const struct lttng_error_query
*query
,
775 struct lttng_payload
*payload
)
778 const struct lttng_error_query_comm header
= {
779 .target_type
= (decltype(header
.target_type
)) query
->target_type
,
782 ret
= lttng_dynamic_buffer_append(
783 &payload
->buffer
, &header
, sizeof(header
));
785 ERR("Failed to append error query header to payload");
789 switch (query
->target_type
) {
790 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
:
791 ret
= lttng_error_query_trigger_serialize(query
, payload
);
797 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
798 ret
= lttng_error_query_condition_serialize(query
, payload
);
804 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
805 ret
= lttng_error_query_action_serialize(query
, payload
);
818 ssize_t
lttng_error_query_create_from_payload(struct lttng_payload_view
*view
,
819 struct lttng_error_query
**query
)
821 ssize_t used_size
= 0;
822 struct lttng_error_query_comm
*header
;
823 struct lttng_trigger
*trigger
= NULL
;
824 struct lttng_payload_view header_view
=
825 lttng_payload_view_from_view(view
, 0, sizeof(*header
));
827 if (!lttng_payload_view_is_valid(&header_view
)) {
828 ERR("Failed to map error query header");
833 used_size
= sizeof(*header
);
835 header
= (typeof(header
)) header_view
.buffer
.data
;
836 switch ((enum lttng_error_query_target_type
) header
->target_type
) {
837 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
:
839 ssize_t trigger_used_size
;
840 struct lttng_payload_view trigger_view
=
841 lttng_payload_view_from_view(
842 view
, used_size
, -1);
844 if (!lttng_payload_view_is_valid(&trigger_view
)) {
849 trigger_used_size
= lttng_trigger_create_from_payload(
850 &trigger_view
, &trigger
);
851 if (trigger_used_size
< 0) {
856 used_size
+= trigger_used_size
;
858 *query
= lttng_error_query_trigger_create(trigger
);
866 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
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
;
887 *query
= lttng_error_query_condition_create(trigger
);
895 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
897 struct lttng_action_path
*action_path
= NULL
;
900 ssize_t trigger_used_size
;
901 struct lttng_payload_view trigger_view
=
902 lttng_payload_view_from_view(
903 view
, used_size
, -1);
905 if (!lttng_payload_view_is_valid(&trigger_view
)) {
910 trigger_used_size
= lttng_trigger_create_from_payload(
911 &trigger_view
, &trigger
);
912 if (trigger_used_size
< 0) {
917 used_size
+= trigger_used_size
;
921 ssize_t action_path_used_size
;
922 struct lttng_payload_view action_path_view
=
923 lttng_payload_view_from_view(
924 view
, used_size
, -1);
926 if (!lttng_payload_view_is_valid(&action_path_view
)) {
931 action_path_used_size
= lttng_action_path_create_from_payload(
932 &action_path_view
, &action_path
);
933 if (action_path_used_size
< 0) {
938 used_size
+= action_path_used_size
;
941 *query
= lttng_error_query_action_create(
942 trigger
, action_path
);
943 lttng_action_path_destroy(action_path
);
957 lttng_trigger_put(trigger
);
961 enum lttng_error_query_results_status
lttng_error_query_results_get_count(
962 const struct lttng_error_query_results
*results
,
965 enum lttng_error_query_results_status status
;
967 if (!results
|| !count
) {
968 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
972 *count
= lttng_dynamic_pointer_array_get_count(&results
->results
);
973 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
;
978 enum lttng_error_query_results_status
979 lttng_error_query_results_get_result(
980 const struct lttng_error_query_results
*results
,
981 const struct lttng_error_query_result
**result
,
984 unsigned int result_count
;
985 enum lttng_error_query_results_status status
;
987 if (!results
|| !result
) {
988 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
992 status
= lttng_error_query_results_get_count(results
, &result_count
);
993 if (status
!= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
) {
997 if (index
>= result_count
) {
998 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
1002 *result
= (typeof(*result
)) lttng_dynamic_pointer_array_get_pointer(
1003 &results
->results
, index
);
1004 LTTNG_ASSERT(*result
);
1005 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
;
1010 void lttng_error_query_results_destroy(
1011 struct lttng_error_query_results
*results
)
1017 lttng_dynamic_pointer_array_reset(&results
->results
);
1021 enum lttng_error_query_result_type
1022 lttng_error_query_result_get_type(const struct lttng_error_query_result
*result
)
1024 return result
? result
->type
: LTTNG_ERROR_QUERY_RESULT_TYPE_UNKNOWN
;
1027 enum lttng_error_query_result_status
lttng_error_query_result_get_name(
1028 const struct lttng_error_query_result
*result
,
1031 enum lttng_error_query_result_status status
;
1033 if (!result
|| !name
) {
1034 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1038 *name
= result
->name
;
1039 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
1044 enum lttng_error_query_result_status
lttng_error_query_result_get_description(
1045 const struct lttng_error_query_result
*result
,
1046 const char **description
)
1048 enum lttng_error_query_result_status status
;
1050 if (!result
|| !description
) {
1051 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1055 *description
= result
->description
;
1056 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
1061 enum lttng_error_query_result_status
lttng_error_query_result_counter_get_value(
1062 const struct lttng_error_query_result
*result
,
1065 enum lttng_error_query_result_status status
;
1066 const struct lttng_error_query_result_counter
*counter_result
;
1068 if (!result
|| !value
||
1069 result
->type
!= LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
) {
1070 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1074 counter_result
= container_of(result
, typeof(*counter_result
), parent
);
1076 *value
= counter_result
->value
;
1077 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
1083 enum lttng_error_code
lttng_error_query_result_counter_mi_serialize(
1084 const struct lttng_error_query_result
*result
,
1085 struct mi_writer
*writer
)
1088 enum lttng_error_code ret_code
;
1089 enum lttng_error_query_result_status status
;
1092 LTTNG_ASSERT(result
);
1093 LTTNG_ASSERT(writer
);
1095 status
= lttng_error_query_result_counter_get_value(result
, &value
);
1096 LTTNG_ASSERT(status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1098 /* Open error query result counter element. */
1099 ret
= mi_lttng_writer_open_element(
1100 writer
, mi_lttng_element_error_query_result_counter
);
1106 ret
= mi_lttng_writer_write_element_unsigned_int(writer
,
1107 mi_lttng_element_error_query_result_counter_value
,
1113 /* Close error query result counter element. */
1114 ret
= mi_lttng_writer_close_element(writer
);
1119 ret_code
= LTTNG_OK
;
1123 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
1129 enum lttng_error_code
lttng_error_query_result_mi_serialize(
1130 const struct lttng_error_query_result
*result
,
1131 struct mi_writer
*writer
)
1134 enum lttng_error_code ret_code
;
1135 enum lttng_error_query_result_status result_status
;
1136 enum lttng_error_query_result_type type
;
1137 const char *name
= NULL
;
1138 const char *description
= NULL
;
1140 LTTNG_ASSERT(result
);
1141 LTTNG_ASSERT(writer
);
1143 type
= lttng_error_query_result_get_type(result
);
1145 result_status
= lttng_error_query_result_get_name(result
, &name
);
1146 LTTNG_ASSERT(result_status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1148 result_status
= lttng_error_query_result_get_description(
1149 result
, &description
);
1150 LTTNG_ASSERT(result_status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1152 /* Open error query result element. */
1153 ret
= mi_lttng_writer_open_element(
1154 writer
, mi_lttng_element_error_query_result
);
1160 ret
= mi_lttng_writer_write_element_string(
1161 writer
, mi_lttng_element_error_query_result_name
, name
);
1167 ret
= mi_lttng_writer_write_element_string(writer
,
1168 mi_lttng_element_error_query_result_description
,
1174 /* Serialize the result according to its sub type. */
1176 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
1177 ret_code
= lttng_error_query_result_counter_mi_serialize(
1184 if (ret_code
!= LTTNG_OK
) {
1188 /* Close error query result element. */
1189 ret
= mi_lttng_writer_close_element(writer
);
1194 ret_code
= LTTNG_OK
;
1198 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
1203 enum lttng_error_code
lttng_error_query_results_mi_serialize(
1204 const struct lttng_error_query_results
*results
,
1205 struct mi_writer
*writer
)
1208 enum lttng_error_code ret_code
;
1209 unsigned int i
, count
;
1210 enum lttng_error_query_results_status results_status
;
1212 LTTNG_ASSERT(results
);
1213 LTTNG_ASSERT(writer
);
1215 /* Open error query results element. */
1216 ret
= mi_lttng_writer_open_element(
1217 writer
, mi_lttng_element_error_query_results
);
1222 results_status
= lttng_error_query_results_get_count(results
, &count
);
1223 LTTNG_ASSERT(results_status
== LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
);
1225 for (i
= 0; i
< count
; i
++) {
1226 const struct lttng_error_query_result
*result
;
1228 results_status
= lttng_error_query_results_get_result(
1229 results
, &result
, i
);
1230 LTTNG_ASSERT(results_status
== LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
);
1232 /* A single error query result. */
1233 ret_code
= lttng_error_query_result_mi_serialize(result
, writer
);
1234 if (ret_code
!= LTTNG_OK
) {
1239 /* Close error query results. */
1240 ret
= mi_lttng_writer_close_element(writer
);
1245 ret_code
= LTTNG_OK
;
1249 ret_code
= LTTNG_ERR_MI_IO_FAIL
;