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 lttng::utils::container_of(query
, <tng_error_query_trigger::parent
);
261 lttng_trigger_put(trigger_query
->trigger
);
265 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
267 struct lttng_error_query_condition
*condition_query
= lttng::utils::container_of(
268 query
, <tng_error_query_condition::parent
);
270 lttng_trigger_put(condition_query
->trigger
);
271 free(condition_query
);
274 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
276 struct lttng_error_query_action
*action_query
= lttng::utils::container_of(
277 query
, <tng_error_query_action::parent
);
279 lttng_trigger_put(action_query
->trigger
);
280 lttng_action_path_destroy(action_query
->action_path
);
290 int lttng_error_query_result_counter_serialize(
291 const struct lttng_error_query_result
*result
,
292 struct lttng_payload
*payload
)
294 const struct lttng_error_query_result_counter
*counter_result
;
296 LTTNG_ASSERT(result
->type
== LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
);
297 counter_result
= lttng::utils::container_of(
298 result
, <tng_error_query_result_counter::parent
);
300 lttng_error_query_result_counter_comm comm
= {
301 .value
= counter_result
->value
,
304 return lttng_dynamic_buffer_append(&payload
->buffer
,
306 sizeof(struct lttng_error_query_result_counter_comm
));
309 int lttng_error_query_result_serialize(
310 const struct lttng_error_query_result
*result
,
311 struct lttng_payload
*payload
)
314 struct lttng_error_query_result_comm header
;
316 header
.type
= (uint8_t) result
->type
;
317 header
.name_len
= (typeof(header
.name_len
)) strlen(result
->name
) + 1;
318 header
.description_len
= (typeof(header
.name_len
)) strlen(result
->description
) + 1;
321 ret
= lttng_dynamic_buffer_append(
322 &payload
->buffer
, &header
, sizeof(header
));
324 ERR("Failed to append error query result communication header to payload");
329 ret
= lttng_dynamic_buffer_append(
330 &payload
->buffer
, result
->name
, header
.name_len
);
332 ERR("Failed to append error query result name to payload");
337 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, result
->description
,
338 header
.description_len
);
340 ERR("Failed to append error query result description to payload");
344 /* Type-specific payload. */
345 switch (result
->type
) {
346 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
347 ret
= lttng_error_query_result_counter_serialize(
350 ERR("Failed to serialize counter error query result");
363 int lttng_error_query_result_init(
364 struct lttng_error_query_result
*result
,
365 enum lttng_error_query_result_type result_type
,
367 const char *description
)
372 LTTNG_ASSERT(description
);
374 result
->type
= result_type
;
376 result
->name
= strdup(name
);
378 PERROR("Failed to copy error query result name");
383 result
->description
= strdup(description
);
384 if (!result
->description
) {
385 PERROR("Failed to copy error query result description");
395 void lttng_error_query_result_destroy(struct lttng_error_query_result
*counter
)
401 switch (counter
->type
) {
402 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
403 /* Nothing to tear down. */
410 free(counter
->description
);
414 struct lttng_error_query_result
*
415 lttng_error_query_result_counter_create(
416 const char *name
, const char *description
, uint64_t value
)
419 struct lttng_error_query_result_counter
*counter
;
421 counter
= zmalloc
<lttng_error_query_result_counter
>();
423 PERROR("Failed to allocate error query counter result");
427 init_ret
= lttng_error_query_result_init(&counter
->parent
,
428 LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
, name
,
434 counter
->value
= value
;
437 lttng_error_query_result_destroy(&counter
->parent
);
439 return counter
? &counter
->parent
: NULL
;
443 void destroy_result(void *ptr
)
445 struct lttng_error_query_result
*result
= (typeof(result
)) ptr
;
447 lttng_error_query_result_destroy(result
);
450 struct lttng_error_query_results
*lttng_error_query_results_create(void)
452 struct lttng_error_query_results
*set
= zmalloc
<lttng_error_query_results
>();
455 PERROR("Failed to allocate an error query result set");
459 lttng_dynamic_pointer_array_init(&set
->results
, destroy_result
);
464 int lttng_error_query_results_add_result(
465 struct lttng_error_query_results
*results
,
466 struct lttng_error_query_result
*result
)
468 return lttng_dynamic_pointer_array_add_pointer(
469 &results
->results
, result
);
472 ssize_t
lttng_error_query_result_create_from_payload(
473 struct lttng_payload_view
*view
,
474 struct lttng_error_query_result
**result
)
476 ssize_t used_size
= 0;
477 struct lttng_error_query_result_comm
*header
;
478 struct lttng_payload_view header_view
=
479 lttng_payload_view_from_view(view
, 0, sizeof(*header
));
481 const char *description
;
483 if (!lttng_payload_view_is_valid(&header_view
)) {
488 header
= (typeof(header
)) header_view
.buffer
.data
;
489 used_size
+= sizeof(*header
);
492 struct lttng_payload_view name_view
=
493 lttng_payload_view_from_view(view
, used_size
,
496 if (!lttng_payload_view_is_valid(&name_view
) ||
497 !lttng_buffer_view_contains_string(
499 name_view
.buffer
.data
,
505 name
= name_view
.buffer
.data
;
506 used_size
+= header
->name_len
;
510 struct lttng_payload_view description_view
=
511 lttng_payload_view_from_view(view
, used_size
,
512 header
->description_len
);
514 if (!lttng_payload_view_is_valid(&description_view
) ||
515 !lttng_buffer_view_contains_string(
516 &description_view
.buffer
,
517 description_view
.buffer
.data
,
518 header
->description_len
)) {
523 description
= description_view
.buffer
.data
;
524 used_size
+= header
->description_len
;
527 switch (header
->type
) {
528 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
530 struct lttng_error_query_result_counter_comm
*counter
;
531 struct lttng_payload_view counter_payload_view
=
532 lttng_payload_view_from_view(view
, used_size
,
535 if (!lttng_payload_view_is_valid(&counter_payload_view
)) {
540 counter
= (typeof(counter
)) counter_payload_view
.buffer
.data
;
541 *result
= lttng_error_query_result_counter_create(
542 name
, description
, counter
->value
);
548 used_size
+= sizeof(*counter
);
560 int lttng_error_query_results_serialize(
561 const struct lttng_error_query_results
*results
,
562 struct lttng_payload
*payload
)
566 const size_t result_count
= lttng_dynamic_pointer_array_get_count(
568 struct lttng_error_query_results_comm header
;
570 header
.count
= (decltype(header
.count
)) result_count
;
573 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &header
, sizeof(header
));
575 ERR("Failed to append error query result set header to payload");
580 for (result_index
= 0; result_index
< result_count
; result_index
++) {
581 const struct lttng_error_query_result
*result
= (typeof(result
))
582 lttng_dynamic_pointer_array_get_pointer(
586 ret
= lttng_error_query_result_serialize(result
, payload
);
588 ERR("Failed to append error query result to payload");
596 ssize_t
lttng_error_query_results_create_from_payload(
597 struct lttng_payload_view
*view
,
598 struct lttng_error_query_results
**_results
)
601 ssize_t total_used_size
= 0;
602 struct lttng_error_query_results_comm
*header
;
603 struct lttng_payload_view header_view
=
604 lttng_payload_view_from_view(view
, 0, sizeof(*header
));
605 struct lttng_error_query_results
*results
= NULL
;
607 if (!lttng_payload_view_is_valid(&header_view
)) {
608 ERR("Failed to map view to error query result set header");
609 total_used_size
= -1;
613 header
= (typeof(header
)) header_view
.buffer
.data
;
614 total_used_size
+= sizeof(*header
);
615 results
= lttng_error_query_results_create();
617 total_used_size
= -1;
621 for (result_index
= 0; result_index
< header
->count
; result_index
++) {
623 struct lttng_error_query_result
*result
;
624 struct lttng_payload_view result_view
=
625 lttng_payload_view_from_view(
626 view
, total_used_size
, -1);
628 if (!lttng_payload_view_is_valid(&result_view
)) {
629 total_used_size
= -1;
633 used_size
= lttng_error_query_result_create_from_payload(
634 &result_view
, &result
);
636 total_used_size
= -1;
640 total_used_size
+= used_size
;
642 if (lttng_dynamic_pointer_array_add_pointer(
643 &results
->results
, result
)) {
644 lttng_error_query_result_destroy(result
);
645 total_used_size
= -1;
653 lttng_error_query_results_destroy(results
);
654 return total_used_size
;
658 int lttng_error_query_trigger_serialize(const struct lttng_error_query
*query
,
659 struct lttng_payload
*payload
)
662 const struct lttng_error_query_trigger
*query_trigger
=
663 lttng::utils::container_of(query
, <tng_error_query_trigger::parent
);
665 if (!lttng_trigger_validate(query_trigger
->trigger
)) {
670 ret
= lttng_trigger_serialize(query_trigger
->trigger
, payload
);
680 int lttng_error_query_condition_serialize(const struct lttng_error_query
*query
,
681 struct lttng_payload
*payload
)
684 const struct lttng_error_query_condition
*query_trigger
=
685 lttng::utils::container_of(query
, <tng_error_query_condition::parent
);
687 if (!lttng_trigger_validate(query_trigger
->trigger
)) {
692 ret
= lttng_trigger_serialize(query_trigger
->trigger
, payload
);
702 int lttng_error_query_action_serialize(const struct lttng_error_query
*query
,
703 struct lttng_payload
*payload
)
706 const struct lttng_error_query_action
*query_action
=
707 lttng::utils::container_of(query
, <tng_error_query_action::parent
);
709 if (!lttng_trigger_validate(query_action
->trigger
)) {
714 ret
= lttng_trigger_serialize(query_action
->trigger
, payload
);
719 ret
= lttng_action_path_serialize(query_action
->action_path
, payload
);
728 enum lttng_error_query_target_type
lttng_error_query_get_target_type(
729 const struct lttng_error_query
*query
)
731 return query
->target_type
;
734 const struct lttng_trigger
*lttng_error_query_trigger_borrow_target(
735 const struct lttng_error_query
*query
)
737 const struct lttng_error_query_trigger
*query_trigger
=
738 lttng::utils::container_of(query
, <tng_error_query_trigger::parent
);
740 return query_trigger
->trigger
;
743 const struct lttng_trigger
*lttng_error_query_condition_borrow_target(
744 const struct lttng_error_query
*query
)
746 const struct lttng_error_query_condition
*query_trigger
=
747 lttng::utils::container_of(query
, <tng_error_query_condition::parent
);
749 return query_trigger
->trigger
;
752 const struct lttng_trigger
*lttng_error_query_action_borrow_trigger_target(
753 const struct lttng_error_query
*query
)
755 const struct lttng_error_query_action
*query_action
=
756 lttng::utils::container_of(query
, <tng_error_query_action::parent
);
758 return query_action
->trigger
;
761 struct lttng_action
*lttng_error_query_action_borrow_action_target(
762 const struct lttng_error_query
*query
, struct lttng_trigger
*trigger
)
764 const struct lttng_error_query_action
*query_action
=
765 lttng::utils::container_of(query
, <tng_error_query_action::parent
);
767 return get_trigger_action_from_path(
768 trigger
, query_action
->action_path
);
771 int lttng_error_query_serialize(const struct lttng_error_query
*query
,
772 struct lttng_payload
*payload
)
775 struct lttng_error_query_comm header
;
777 header
.target_type
= (decltype(header
.target_type
)) query
->target_type
;
779 ret
= lttng_dynamic_buffer_append(
780 &payload
->buffer
, &header
, sizeof(header
));
782 ERR("Failed to append error query header to payload");
786 switch (query
->target_type
) {
787 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
:
788 ret
= lttng_error_query_trigger_serialize(query
, payload
);
794 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
795 ret
= lttng_error_query_condition_serialize(query
, payload
);
801 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
802 ret
= lttng_error_query_action_serialize(query
, payload
);
815 ssize_t
lttng_error_query_create_from_payload(struct lttng_payload_view
*view
,
816 struct lttng_error_query
**query
)
818 ssize_t used_size
= 0;
819 struct lttng_error_query_comm
*header
;
820 struct lttng_trigger
*trigger
= NULL
;
821 struct lttng_payload_view header_view
=
822 lttng_payload_view_from_view(view
, 0, sizeof(*header
));
824 if (!lttng_payload_view_is_valid(&header_view
)) {
825 ERR("Failed to map error query header");
830 used_size
= sizeof(*header
);
832 header
= (typeof(header
)) header_view
.buffer
.data
;
833 switch ((enum lttng_error_query_target_type
) header
->target_type
) {
834 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
:
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_trigger_create(trigger
);
863 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
865 ssize_t trigger_used_size
;
866 struct lttng_payload_view trigger_view
=
867 lttng_payload_view_from_view(
868 view
, used_size
, -1);
870 if (!lttng_payload_view_is_valid(&trigger_view
)) {
875 trigger_used_size
= lttng_trigger_create_from_payload(
876 &trigger_view
, &trigger
);
877 if (trigger_used_size
< 0) {
882 used_size
+= trigger_used_size
;
884 *query
= lttng_error_query_condition_create(trigger
);
892 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
894 struct lttng_action_path
*action_path
= NULL
;
897 ssize_t trigger_used_size
;
898 struct lttng_payload_view trigger_view
=
899 lttng_payload_view_from_view(
900 view
, used_size
, -1);
902 if (!lttng_payload_view_is_valid(&trigger_view
)) {
907 trigger_used_size
= lttng_trigger_create_from_payload(
908 &trigger_view
, &trigger
);
909 if (trigger_used_size
< 0) {
914 used_size
+= trigger_used_size
;
918 ssize_t action_path_used_size
;
919 struct lttng_payload_view action_path_view
=
920 lttng_payload_view_from_view(
921 view
, used_size
, -1);
923 if (!lttng_payload_view_is_valid(&action_path_view
)) {
928 action_path_used_size
= lttng_action_path_create_from_payload(
929 &action_path_view
, &action_path
);
930 if (action_path_used_size
< 0) {
935 used_size
+= action_path_used_size
;
938 *query
= lttng_error_query_action_create(
939 trigger
, action_path
);
940 lttng_action_path_destroy(action_path
);
954 lttng_trigger_put(trigger
);
958 enum lttng_error_query_results_status
lttng_error_query_results_get_count(
959 const struct lttng_error_query_results
*results
,
962 enum lttng_error_query_results_status status
;
964 if (!results
|| !count
) {
965 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
969 *count
= lttng_dynamic_pointer_array_get_count(&results
->results
);
970 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
;
975 enum lttng_error_query_results_status
976 lttng_error_query_results_get_result(
977 const struct lttng_error_query_results
*results
,
978 const struct lttng_error_query_result
**result
,
981 unsigned int result_count
;
982 enum lttng_error_query_results_status status
;
984 if (!results
|| !result
) {
985 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
989 status
= lttng_error_query_results_get_count(results
, &result_count
);
990 if (status
!= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
) {
994 if (index
>= result_count
) {
995 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
999 *result
= (typeof(*result
)) lttng_dynamic_pointer_array_get_pointer(
1000 &results
->results
, index
);
1001 LTTNG_ASSERT(*result
);
1002 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
;
1007 void lttng_error_query_results_destroy(
1008 struct lttng_error_query_results
*results
)
1014 lttng_dynamic_pointer_array_reset(&results
->results
);
1018 enum lttng_error_query_result_type
1019 lttng_error_query_result_get_type(const struct lttng_error_query_result
*result
)
1021 return result
? result
->type
: LTTNG_ERROR_QUERY_RESULT_TYPE_UNKNOWN
;
1024 enum lttng_error_query_result_status
lttng_error_query_result_get_name(
1025 const struct lttng_error_query_result
*result
,
1028 enum lttng_error_query_result_status status
;
1030 if (!result
|| !name
) {
1031 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1035 *name
= result
->name
;
1036 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
1041 enum lttng_error_query_result_status
lttng_error_query_result_get_description(
1042 const struct lttng_error_query_result
*result
,
1043 const char **description
)
1045 enum lttng_error_query_result_status status
;
1047 if (!result
|| !description
) {
1048 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1052 *description
= result
->description
;
1053 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
1058 enum lttng_error_query_result_status
lttng_error_query_result_counter_get_value(
1059 const struct lttng_error_query_result
*result
,
1062 enum lttng_error_query_result_status status
;
1063 const struct lttng_error_query_result_counter
*counter_result
;
1065 if (!result
|| !value
||
1066 result
->type
!= LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
) {
1067 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1071 counter_result
= lttng::utils::container_of(
1072 result
, <tng_error_query_result_counter::parent
);
1074 *value
= counter_result
->value
;
1075 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
1081 enum lttng_error_code
lttng_error_query_result_counter_mi_serialize(
1082 const struct lttng_error_query_result
*result
,
1083 struct mi_writer
*writer
)
1086 enum lttng_error_code ret_code
;
1087 enum lttng_error_query_result_status status
;
1090 LTTNG_ASSERT(result
);
1091 LTTNG_ASSERT(writer
);
1093 status
= lttng_error_query_result_counter_get_value(result
, &value
);
1094 LTTNG_ASSERT(status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1096 /* Open error query result counter element. */
1097 ret
= mi_lttng_writer_open_element(
1098 writer
, mi_lttng_element_error_query_result_counter
);
1104 ret
= mi_lttng_writer_write_element_unsigned_int(writer
,
1105 mi_lttng_element_error_query_result_counter_value
,
1111 /* Close error query result counter element. */
1112 ret
= mi_lttng_writer_close_element(writer
);
1117 ret_code
= LTTNG_OK
;
1121 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
1127 enum lttng_error_code
lttng_error_query_result_mi_serialize(
1128 const struct lttng_error_query_result
*result
,
1129 struct mi_writer
*writer
)
1132 enum lttng_error_code ret_code
;
1133 enum lttng_error_query_result_status result_status
;
1134 enum lttng_error_query_result_type type
;
1135 const char *name
= NULL
;
1136 const char *description
= NULL
;
1138 LTTNG_ASSERT(result
);
1139 LTTNG_ASSERT(writer
);
1141 type
= lttng_error_query_result_get_type(result
);
1143 result_status
= lttng_error_query_result_get_name(result
, &name
);
1144 LTTNG_ASSERT(result_status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1146 result_status
= lttng_error_query_result_get_description(
1147 result
, &description
);
1148 LTTNG_ASSERT(result_status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1150 /* Open error query result element. */
1151 ret
= mi_lttng_writer_open_element(
1152 writer
, mi_lttng_element_error_query_result
);
1158 ret
= mi_lttng_writer_write_element_string(
1159 writer
, mi_lttng_element_error_query_result_name
, name
);
1165 ret
= mi_lttng_writer_write_element_string(writer
,
1166 mi_lttng_element_error_query_result_description
,
1172 /* Serialize the result according to its sub type. */
1174 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
1175 ret_code
= lttng_error_query_result_counter_mi_serialize(
1182 if (ret_code
!= LTTNG_OK
) {
1186 /* Close error query result element. */
1187 ret
= mi_lttng_writer_close_element(writer
);
1192 ret_code
= LTTNG_OK
;
1196 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
1201 enum lttng_error_code
lttng_error_query_results_mi_serialize(
1202 const struct lttng_error_query_results
*results
,
1203 struct mi_writer
*writer
)
1206 enum lttng_error_code ret_code
;
1207 unsigned int i
, count
;
1208 enum lttng_error_query_results_status results_status
;
1210 LTTNG_ASSERT(results
);
1211 LTTNG_ASSERT(writer
);
1213 /* Open error query results element. */
1214 ret
= mi_lttng_writer_open_element(
1215 writer
, mi_lttng_element_error_query_results
);
1220 results_status
= lttng_error_query_results_get_count(results
, &count
);
1221 LTTNG_ASSERT(results_status
== LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
);
1223 for (i
= 0; i
< count
; i
++) {
1224 const struct lttng_error_query_result
*result
;
1226 results_status
= lttng_error_query_results_get_result(
1227 results
, &result
, i
);
1228 LTTNG_ASSERT(results_status
== LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
);
1230 /* A single error query result. */
1231 ret_code
= lttng_error_query_result_mi_serialize(result
, writer
);
1232 if (ret_code
!= LTTNG_OK
) {
1237 /* Close error query results. */
1238 ret
= mi_lttng_writer_close_element(writer
);
1243 ret_code
= LTTNG_OK
;
1247 ret_code
= LTTNG_ERR_MI_IO_FAIL
;