4 * Copyright (C) 2021 Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 * SPDX-License-Identifier: LGPL-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>
16 #include <lttng/action/action-internal.hpp>
17 #include <lttng/action/list-internal.hpp>
18 #include <lttng/action/path-internal.hpp>
19 #include <lttng/error-query-internal.hpp>
20 #include <lttng/error-query.h>
21 #include <lttng/trigger/trigger-internal.hpp>
25 struct lttng_error_query
{
26 enum lttng_error_query_target_type target_type
;
29 struct lttng_error_query_result
{
30 enum lttng_error_query_result_type type
;
35 struct lttng_error_query_results
{
36 struct lttng_dynamic_pointer_array results
;
40 struct lttng_error_query_comm
{
41 /* enum lttng_error_query_target_type */
43 /* Target-specific payload. */
47 struct lttng_error_query_trigger
{
48 struct lttng_error_query parent
;
49 /* Mutable only because of the reference count. */
50 struct lttng_trigger
*trigger
;
53 struct lttng_error_query_condition
{
54 struct lttng_error_query parent
;
55 /* Mutable only because of the reference count. */
56 struct lttng_trigger
*trigger
;
59 struct lttng_error_query_action
{
60 struct lttng_error_query parent
;
61 /* Mutable only because of the reference count. */
62 struct lttng_trigger
*trigger
;
63 struct lttng_action_path
*action_path
;
66 struct lttng_error_query_result_comm
{
67 /* enum lttng_error_query_result_type */
69 /* Length of name (including null-terminator). */
71 /* Length of description (including null-terminator). */
72 uint32_t description_len
;
73 /* Name, description, and type-specific payload follow. */
77 struct lttng_error_query_result_counter_comm
{
81 struct lttng_error_query_result_counter
{
82 struct lttng_error_query_result parent
;
86 struct lttng_error_query_results_comm
{
88 /* `count` instances of `struct lttng_error_query_result` follow. */
93 static enum lttng_error_code
94 lttng_error_query_result_mi_serialize(const struct lttng_error_query_result
*result
,
95 struct mi_writer
*writer
);
97 static enum lttng_error_code
98 lttng_error_query_result_counter_mi_serialize(const struct lttng_error_query_result
*result
,
99 struct mi_writer
*writer
);
101 struct lttng_error_query
*lttng_error_query_trigger_create(const struct lttng_trigger
*trigger
)
103 struct lttng_error_query_trigger
*query
= nullptr;
104 struct lttng_trigger
*trigger_copy
= nullptr;
110 trigger_copy
= lttng_trigger_copy(trigger
);
115 query
= zmalloc
<lttng_error_query_trigger
>();
117 PERROR("Failed to allocate trigger error query");
121 query
->parent
.target_type
= LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
;
122 query
->trigger
= trigger_copy
;
123 trigger_copy
= nullptr;
126 lttng_trigger_put(trigger_copy
);
128 return query
? &query
->parent
: nullptr;
131 struct lttng_error_query
*lttng_error_query_condition_create(const struct lttng_trigger
*trigger
)
133 struct lttng_error_query_condition
*query
= nullptr;
134 struct lttng_trigger
*trigger_copy
= nullptr;
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
;
153 trigger_copy
= nullptr;
156 lttng_trigger_put(trigger_copy
);
158 return query
? &query
->parent
: nullptr;
161 static struct lttng_action
*
162 get_trigger_action_from_path(struct lttng_trigger
*trigger
,
163 const struct lttng_action_path
*action_path
)
165 size_t index_count
, i
;
166 enum lttng_action_path_status path_status
;
167 struct lttng_action
*current_action
= nullptr;
169 path_status
= lttng_action_path_get_index_count(action_path
, &index_count
);
170 if (path_status
!= LTTNG_ACTION_PATH_STATUS_OK
) {
174 current_action
= lttng_trigger_get_action(trigger
);
175 for (i
= 0; i
< index_count
; i
++) {
178 path_status
= lttng_action_path_get_index_at_index(action_path
, i
, &path_index
);
180 lttng_action_list_borrow_mutable_at_index(current_action
, path_index
);
181 if (!current_action
) {
182 /* Invalid action path. */
188 return current_action
;
191 static bool is_valid_action_path(const struct lttng_trigger
*trigger
,
192 const struct lttng_action_path
*action_path
)
195 * While 'trigger's constness is casted-away, the trigger and resulting
196 * action are not modified; we merely check for the action's existence.
198 return !!get_trigger_action_from_path((struct lttng_trigger
*) trigger
, action_path
);
201 struct lttng_error_query
*
202 lttng_error_query_action_create(const struct lttng_trigger
*trigger
,
203 const struct lttng_action_path
*action_path
)
205 struct lttng_error_query_action
*query
= nullptr;
206 struct lttng_trigger
*trigger_copy
= nullptr;
209 if (!trigger
|| !action_path
|| !is_valid_action_path(trigger
, action_path
)) {
213 trigger_copy
= lttng_trigger_copy(trigger
);
218 query
= zmalloc
<lttng_error_query_action
>();
220 PERROR("Failed to allocate action error query");
224 ret_copy
= lttng_action_path_copy(action_path
, &query
->action_path
);
229 query
->parent
.target_type
= LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
;
230 query
->trigger
= trigger_copy
;
231 trigger_copy
= nullptr;
235 lttng_trigger_put(trigger_copy
);
236 lttng_error_query_destroy(query
? &query
->parent
: nullptr);
238 return query
? &query
->parent
: nullptr;
241 void lttng_error_query_destroy(struct lttng_error_query
*query
)
247 switch (query
->target_type
) {
248 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
:
250 struct lttng_error_query_trigger
*trigger_query
=
251 lttng::utils::container_of(query
, <tng_error_query_trigger::parent
);
253 lttng_trigger_put(trigger_query
->trigger
);
257 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
259 struct lttng_error_query_condition
*condition_query
=
260 lttng::utils::container_of(query
, <tng_error_query_condition::parent
);
262 lttng_trigger_put(condition_query
->trigger
);
263 free(condition_query
);
266 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
268 struct lttng_error_query_action
*action_query
=
269 lttng::utils::container_of(query
, <tng_error_query_action::parent
);
271 lttng_trigger_put(action_query
->trigger
);
272 lttng_action_path_destroy(action_query
->action_path
);
281 static int lttng_error_query_result_counter_serialize(const struct lttng_error_query_result
*result
,
282 struct lttng_payload
*payload
)
284 const struct lttng_error_query_result_counter
*counter_result
;
286 LTTNG_ASSERT(result
->type
== LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
);
288 lttng::utils::container_of(result
, <tng_error_query_result_counter::parent
);
290 lttng_error_query_result_counter_comm comm
= {
291 .value
= counter_result
->value
,
294 return lttng_dynamic_buffer_append(
295 &payload
->buffer
, &comm
, sizeof(struct lttng_error_query_result_counter_comm
));
298 int lttng_error_query_result_serialize(const struct lttng_error_query_result
*result
,
299 struct lttng_payload
*payload
)
302 struct lttng_error_query_result_comm header
;
304 header
.type
= (uint8_t) result
->type
;
305 header
.name_len
= (typeof(header
.name_len
)) strlen(result
->name
) + 1;
306 header
.description_len
= (typeof(header
.name_len
)) strlen(result
->description
) + 1;
309 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &header
, sizeof(header
));
311 ERR("Failed to append error query result communication header to payload");
316 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, result
->name
, header
.name_len
);
318 ERR("Failed to append error query result name to payload");
323 ret
= lttng_dynamic_buffer_append(
324 &payload
->buffer
, result
->description
, header
.description_len
);
326 ERR("Failed to append error query result description to payload");
330 /* Type-specific payload. */
331 switch (result
->type
) {
332 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
333 ret
= lttng_error_query_result_counter_serialize(result
, payload
);
335 ERR("Failed to serialize counter error query result");
347 static int lttng_error_query_result_init(struct lttng_error_query_result
*result
,
348 enum lttng_error_query_result_type result_type
,
350 const char *description
)
355 LTTNG_ASSERT(description
);
357 result
->type
= result_type
;
359 result
->name
= strdup(name
);
361 PERROR("Failed to copy error query result name");
366 result
->description
= strdup(description
);
367 if (!result
->description
) {
368 PERROR("Failed to copy error query result description");
378 void lttng_error_query_result_destroy(struct lttng_error_query_result
*counter
)
384 switch (counter
->type
) {
385 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
386 /* Nothing to tear down. */
393 free(counter
->description
);
397 struct lttng_error_query_result
*
398 lttng_error_query_result_counter_create(const char *name
, const char *description
, uint64_t value
)
401 struct lttng_error_query_result_counter
*counter
;
403 counter
= zmalloc
<lttng_error_query_result_counter
>();
405 PERROR("Failed to allocate error query counter result");
409 init_ret
= lttng_error_query_result_init(
410 &counter
->parent
, LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
, name
, description
);
415 counter
->value
= value
;
418 lttng_error_query_result_destroy(&counter
->parent
);
420 return counter
? &counter
->parent
: nullptr;
423 static void destroy_result(void *ptr
)
425 struct lttng_error_query_result
*result
= (typeof(result
)) ptr
;
427 lttng_error_query_result_destroy(result
);
430 struct lttng_error_query_results
*lttng_error_query_results_create()
432 struct lttng_error_query_results
*set
= zmalloc
<lttng_error_query_results
>();
435 PERROR("Failed to allocate an error query result set");
439 lttng_dynamic_pointer_array_init(&set
->results
, destroy_result
);
444 int lttng_error_query_results_add_result(struct lttng_error_query_results
*results
,
445 struct lttng_error_query_result
*result
)
447 return lttng_dynamic_pointer_array_add_pointer(&results
->results
, result
);
450 ssize_t
lttng_error_query_result_create_from_payload(struct lttng_payload_view
*view
,
451 struct lttng_error_query_result
**result
)
453 ssize_t used_size
= 0;
454 struct lttng_error_query_result_comm
*header
;
455 struct lttng_payload_view header_view
=
456 lttng_payload_view_from_view(view
, 0, sizeof(*header
));
458 const char *description
;
460 if (!lttng_payload_view_is_valid(&header_view
)) {
465 header
= (typeof(header
)) header_view
.buffer
.data
;
466 used_size
+= sizeof(*header
);
469 struct lttng_payload_view name_view
=
470 lttng_payload_view_from_view(view
, used_size
, header
->name_len
);
472 if (!lttng_payload_view_is_valid(&name_view
) ||
473 !lttng_buffer_view_contains_string(
474 &name_view
.buffer
, name_view
.buffer
.data
, header
->name_len
)) {
479 name
= name_view
.buffer
.data
;
480 used_size
+= header
->name_len
;
484 struct lttng_payload_view description_view
=
485 lttng_payload_view_from_view(view
, used_size
, header
->description_len
);
487 if (!lttng_payload_view_is_valid(&description_view
) ||
488 !lttng_buffer_view_contains_string(&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
, sizeof(*counter
));
506 if (!lttng_payload_view_is_valid(&counter_payload_view
)) {
511 counter
= (typeof(counter
)) counter_payload_view
.buffer
.data
;
513 lttng_error_query_result_counter_create(name
, description
, counter
->value
);
519 used_size
+= sizeof(*counter
);
531 int lttng_error_query_results_serialize(const struct lttng_error_query_results
*results
,
532 struct lttng_payload
*payload
)
536 const size_t result_count
= lttng_dynamic_pointer_array_get_count(&results
->results
);
537 struct lttng_error_query_results_comm header
;
539 header
.count
= (decltype(header
.count
)) result_count
;
542 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &header
, sizeof(header
));
544 ERR("Failed to append error query result set header to payload");
549 for (result_index
= 0; result_index
< result_count
; result_index
++) {
550 const struct lttng_error_query_result
*result
=
551 (typeof(result
)) lttng_dynamic_pointer_array_get_pointer(&results
->results
,
554 ret
= lttng_error_query_result_serialize(result
, payload
);
556 ERR("Failed to append error query result to payload");
564 ssize_t
lttng_error_query_results_create_from_payload(struct lttng_payload_view
*view
,
565 struct lttng_error_query_results
**_results
)
568 ssize_t total_used_size
= 0;
569 struct lttng_error_query_results_comm
*header
;
570 struct lttng_payload_view header_view
=
571 lttng_payload_view_from_view(view
, 0, sizeof(*header
));
572 struct lttng_error_query_results
*results
= nullptr;
574 if (!lttng_payload_view_is_valid(&header_view
)) {
575 ERR("Failed to map view to error query result set header");
576 total_used_size
= -1;
580 header
= (typeof(header
)) header_view
.buffer
.data
;
581 total_used_size
+= sizeof(*header
);
582 results
= lttng_error_query_results_create();
584 total_used_size
= -1;
588 for (result_index
= 0; result_index
< header
->count
; result_index
++) {
590 struct lttng_error_query_result
*result
;
591 struct lttng_payload_view result_view
=
592 lttng_payload_view_from_view(view
, total_used_size
, -1);
594 if (!lttng_payload_view_is_valid(&result_view
)) {
595 total_used_size
= -1;
599 used_size
= lttng_error_query_result_create_from_payload(&result_view
, &result
);
601 total_used_size
= -1;
605 total_used_size
+= used_size
;
607 if (lttng_dynamic_pointer_array_add_pointer(&results
->results
, result
)) {
608 lttng_error_query_result_destroy(result
);
609 total_used_size
= -1;
617 lttng_error_query_results_destroy(results
);
618 return total_used_size
;
621 static int lttng_error_query_trigger_serialize(const struct lttng_error_query
*query
,
622 struct lttng_payload
*payload
)
625 const struct lttng_error_query_trigger
*query_trigger
=
626 lttng::utils::container_of(query
, <tng_error_query_trigger::parent
);
628 if (!lttng_trigger_validate(query_trigger
->trigger
)) {
633 ret
= lttng_trigger_serialize(query_trigger
->trigger
, payload
);
642 static int lttng_error_query_condition_serialize(const struct lttng_error_query
*query
,
643 struct lttng_payload
*payload
)
646 const struct lttng_error_query_condition
*query_trigger
=
647 lttng::utils::container_of(query
, <tng_error_query_condition::parent
);
649 if (!lttng_trigger_validate(query_trigger
->trigger
)) {
654 ret
= lttng_trigger_serialize(query_trigger
->trigger
, payload
);
663 static int lttng_error_query_action_serialize(const struct lttng_error_query
*query
,
664 struct lttng_payload
*payload
)
667 const struct lttng_error_query_action
*query_action
=
668 lttng::utils::container_of(query
, <tng_error_query_action::parent
);
670 if (!lttng_trigger_validate(query_action
->trigger
)) {
675 ret
= lttng_trigger_serialize(query_action
->trigger
, payload
);
680 ret
= lttng_action_path_serialize(query_action
->action_path
, payload
);
689 enum lttng_error_query_target_type
690 lttng_error_query_get_target_type(const struct lttng_error_query
*query
)
692 return query
->target_type
;
695 const struct lttng_trigger
*
696 lttng_error_query_trigger_borrow_target(const struct lttng_error_query
*query
)
698 const struct lttng_error_query_trigger
*query_trigger
=
699 lttng::utils::container_of(query
, <tng_error_query_trigger::parent
);
701 return query_trigger
->trigger
;
704 const struct lttng_trigger
*
705 lttng_error_query_condition_borrow_target(const struct lttng_error_query
*query
)
707 const struct lttng_error_query_condition
*query_trigger
=
708 lttng::utils::container_of(query
, <tng_error_query_condition::parent
);
710 return query_trigger
->trigger
;
713 const struct lttng_trigger
*
714 lttng_error_query_action_borrow_trigger_target(const struct lttng_error_query
*query
)
716 const struct lttng_error_query_action
*query_action
=
717 lttng::utils::container_of(query
, <tng_error_query_action::parent
);
719 return query_action
->trigger
;
722 struct lttng_action
*
723 lttng_error_query_action_borrow_action_target(const struct lttng_error_query
*query
,
724 struct lttng_trigger
*trigger
)
726 const struct lttng_error_query_action
*query_action
=
727 lttng::utils::container_of(query
, <tng_error_query_action::parent
);
729 return get_trigger_action_from_path(trigger
, query_action
->action_path
);
732 int lttng_error_query_serialize(const struct lttng_error_query
*query
,
733 struct lttng_payload
*payload
)
736 struct lttng_error_query_comm header
;
738 header
.target_type
= (decltype(header
.target_type
)) query
->target_type
;
740 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &header
, sizeof(header
));
742 ERR("Failed to append error query header to payload");
746 switch (query
->target_type
) {
747 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
:
748 ret
= lttng_error_query_trigger_serialize(query
, payload
);
754 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
755 ret
= lttng_error_query_condition_serialize(query
, payload
);
761 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
762 ret
= lttng_error_query_action_serialize(query
, payload
);
775 ssize_t
lttng_error_query_create_from_payload(struct lttng_payload_view
*view
,
776 struct lttng_error_query
**query
)
778 ssize_t used_size
= 0;
779 struct lttng_error_query_comm
*header
;
780 struct lttng_trigger
*trigger
= nullptr;
781 struct lttng_payload_view header_view
=
782 lttng_payload_view_from_view(view
, 0, sizeof(*header
));
784 if (!lttng_payload_view_is_valid(&header_view
)) {
785 ERR("Failed to map error query header");
790 used_size
= sizeof(*header
);
792 header
= (typeof(header
)) header_view
.buffer
.data
;
793 switch ((enum lttng_error_query_target_type
) header
->target_type
) {
794 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER
:
796 ssize_t trigger_used_size
;
797 struct lttng_payload_view trigger_view
=
798 lttng_payload_view_from_view(view
, used_size
, -1);
800 if (!lttng_payload_view_is_valid(&trigger_view
)) {
805 trigger_used_size
= lttng_trigger_create_from_payload(&trigger_view
, &trigger
);
806 if (trigger_used_size
< 0) {
811 used_size
+= trigger_used_size
;
813 *query
= lttng_error_query_trigger_create(trigger
);
821 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION
:
823 ssize_t trigger_used_size
;
824 struct lttng_payload_view trigger_view
=
825 lttng_payload_view_from_view(view
, used_size
, -1);
827 if (!lttng_payload_view_is_valid(&trigger_view
)) {
832 trigger_used_size
= lttng_trigger_create_from_payload(&trigger_view
, &trigger
);
833 if (trigger_used_size
< 0) {
838 used_size
+= trigger_used_size
;
840 *query
= lttng_error_query_condition_create(trigger
);
848 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION
:
850 struct lttng_action_path
*action_path
= nullptr;
853 ssize_t trigger_used_size
;
854 struct lttng_payload_view trigger_view
=
855 lttng_payload_view_from_view(view
, used_size
, -1);
857 if (!lttng_payload_view_is_valid(&trigger_view
)) {
863 lttng_trigger_create_from_payload(&trigger_view
, &trigger
);
864 if (trigger_used_size
< 0) {
869 used_size
+= trigger_used_size
;
873 ssize_t action_path_used_size
;
874 struct lttng_payload_view action_path_view
=
875 lttng_payload_view_from_view(view
, used_size
, -1);
877 if (!lttng_payload_view_is_valid(&action_path_view
)) {
882 action_path_used_size
= lttng_action_path_create_from_payload(
883 &action_path_view
, &action_path
);
884 if (action_path_used_size
< 0) {
889 used_size
+= action_path_used_size
;
892 *query
= lttng_error_query_action_create(trigger
, action_path
);
893 lttng_action_path_destroy(action_path
);
907 lttng_trigger_put(trigger
);
911 enum lttng_error_query_results_status
912 lttng_error_query_results_get_count(const struct lttng_error_query_results
*results
,
915 enum lttng_error_query_results_status status
;
917 if (!results
|| !count
) {
918 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
922 *count
= lttng_dynamic_pointer_array_get_count(&results
->results
);
923 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
;
928 enum lttng_error_query_results_status
929 lttng_error_query_results_get_result(const struct lttng_error_query_results
*results
,
930 const struct lttng_error_query_result
**result
,
933 unsigned int result_count
;
934 enum lttng_error_query_results_status status
;
936 if (!results
|| !result
) {
937 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
941 status
= lttng_error_query_results_get_count(results
, &result_count
);
942 if (status
!= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
) {
946 if (index
>= result_count
) {
947 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER
;
952 (typeof(*result
)) lttng_dynamic_pointer_array_get_pointer(&results
->results
, index
);
953 LTTNG_ASSERT(*result
);
954 status
= LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
;
959 void lttng_error_query_results_destroy(struct lttng_error_query_results
*results
)
965 lttng_dynamic_pointer_array_reset(&results
->results
);
969 enum lttng_error_query_result_type
970 lttng_error_query_result_get_type(const struct lttng_error_query_result
*result
)
972 return result
? result
->type
: LTTNG_ERROR_QUERY_RESULT_TYPE_UNKNOWN
;
975 enum lttng_error_query_result_status
976 lttng_error_query_result_get_name(const struct lttng_error_query_result
*result
, const char **name
)
978 enum lttng_error_query_result_status status
;
980 if (!result
|| !name
) {
981 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
985 *name
= result
->name
;
986 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
991 enum lttng_error_query_result_status
992 lttng_error_query_result_get_description(const struct lttng_error_query_result
*result
,
993 const char **description
)
995 enum lttng_error_query_result_status status
;
997 if (!result
|| !description
) {
998 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1002 *description
= result
->description
;
1003 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
1008 enum lttng_error_query_result_status
1009 lttng_error_query_result_counter_get_value(const struct lttng_error_query_result
*result
,
1012 enum lttng_error_query_result_status status
;
1013 const struct lttng_error_query_result_counter
*counter_result
;
1015 if (!result
|| !value
|| result
->type
!= LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
) {
1016 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER
;
1021 lttng::utils::container_of(result
, <tng_error_query_result_counter::parent
);
1023 *value
= counter_result
->value
;
1024 status
= LTTNG_ERROR_QUERY_RESULT_STATUS_OK
;
1029 static enum lttng_error_code
1030 lttng_error_query_result_counter_mi_serialize(const struct lttng_error_query_result
*result
,
1031 struct mi_writer
*writer
)
1034 enum lttng_error_code ret_code
;
1035 enum lttng_error_query_result_status status
;
1038 LTTNG_ASSERT(result
);
1039 LTTNG_ASSERT(writer
);
1041 status
= lttng_error_query_result_counter_get_value(result
, &value
);
1042 LTTNG_ASSERT(status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1044 /* Open error query result counter element. */
1045 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_error_query_result_counter
);
1051 ret
= mi_lttng_writer_write_element_unsigned_int(
1052 writer
, mi_lttng_element_error_query_result_counter_value
, value
);
1057 /* Close error query result counter element. */
1058 ret
= mi_lttng_writer_close_element(writer
);
1063 ret_code
= LTTNG_OK
;
1067 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
1072 static enum lttng_error_code
1073 lttng_error_query_result_mi_serialize(const struct lttng_error_query_result
*result
,
1074 struct mi_writer
*writer
)
1077 enum lttng_error_code ret_code
;
1078 enum lttng_error_query_result_status result_status
;
1079 enum lttng_error_query_result_type type
;
1080 const char *name
= nullptr;
1081 const char *description
= nullptr;
1083 LTTNG_ASSERT(result
);
1084 LTTNG_ASSERT(writer
);
1086 type
= lttng_error_query_result_get_type(result
);
1088 result_status
= lttng_error_query_result_get_name(result
, &name
);
1089 LTTNG_ASSERT(result_status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1091 result_status
= lttng_error_query_result_get_description(result
, &description
);
1092 LTTNG_ASSERT(result_status
== LTTNG_ERROR_QUERY_RESULT_STATUS_OK
);
1094 /* Open error query result element. */
1095 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_error_query_result
);
1101 ret
= mi_lttng_writer_write_element_string(
1102 writer
, mi_lttng_element_error_query_result_name
, name
);
1108 ret
= mi_lttng_writer_write_element_string(
1109 writer
, mi_lttng_element_error_query_result_description
, description
);
1114 /* Serialize the result according to its sub type. */
1116 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER
:
1117 ret_code
= lttng_error_query_result_counter_mi_serialize(result
, writer
);
1123 if (ret_code
!= LTTNG_OK
) {
1127 /* Close error query result element. */
1128 ret
= mi_lttng_writer_close_element(writer
);
1133 ret_code
= LTTNG_OK
;
1137 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
1142 enum lttng_error_code
1143 lttng_error_query_results_mi_serialize(const struct lttng_error_query_results
*results
,
1144 struct mi_writer
*writer
)
1147 enum lttng_error_code ret_code
;
1148 unsigned int i
, count
;
1149 enum lttng_error_query_results_status results_status
;
1151 LTTNG_ASSERT(results
);
1152 LTTNG_ASSERT(writer
);
1154 /* Open error query results element. */
1155 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_error_query_results
);
1160 results_status
= lttng_error_query_results_get_count(results
, &count
);
1161 LTTNG_ASSERT(results_status
== LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
);
1163 for (i
= 0; i
< count
; i
++) {
1164 const struct lttng_error_query_result
*result
;
1166 results_status
= lttng_error_query_results_get_result(results
, &result
, i
);
1167 LTTNG_ASSERT(results_status
== LTTNG_ERROR_QUERY_RESULTS_STATUS_OK
);
1169 /* A single error query result. */
1170 ret_code
= lttng_error_query_result_mi_serialize(result
, writer
);
1171 if (ret_code
!= LTTNG_OK
) {
1176 /* Close error query results. */
1177 ret
= mi_lttng_writer_close_element(writer
);
1182 ret_code
= LTTNG_OK
;
1186 ret_code
= LTTNG_ERR_MI_IO_FAIL
;