sessiond: implement EXECUTE_ERROR_QUERY command
[lttng-tools.git] / src / common / error-query.c
CommitLineData
b99a0cb3
JG
1/*
2 * error-query.c
3 *
4 * Copyright (C) 2021 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 *
6 * SPDX-License-Identifier: GPL-2.1-only
7 *
8 */
9
10#include <common/dynamic-array.h>
11#include <common/error.h>
12#include <common/macros.h>
13#include <common/sessiond-comm/sessiond-comm.h>
14#include <lttng/action/action-internal.h>
15#include <lttng/action/group-internal.h>
16#include <lttng/error-query-internal.h>
17#include <lttng/error-query.h>
18#include <lttng/trigger/trigger-internal.h>
19#include <stddef.h>
20
21struct lttng_error_query {
22 enum lttng_error_query_target_type target_type;
23};
24
25struct lttng_error_query_comm {
26 /* enum lttng_error_query_target_type */
27 int8_t target_type;
28 /* Target-specific payload. */
29 char payload[];
30};
31
32struct lttng_error_query_trigger {
33 struct lttng_error_query parent;
34 /* Mutable only because of the reference count. */
35 struct lttng_trigger *trigger;
36};
37
38struct lttng_error_query_action_comm {
39 LTTNG_OPTIONAL_COMM(uint32_t) action_index;
40 /* Trigger payload. */
41 char payload[];
42};
43
44struct lttng_error_query_action {
45 struct lttng_error_query parent;
46 /* Mutable only because of the reference count. */
47 struct lttng_trigger *trigger;
48 /*
49 * Index of the target action. Since action lists can't be nested,
50 * the targetted action is the top-level group if the action_index is
51 * unset. Otherwise, the index refers to the index within the top-level
52 * group.
53 */
54 LTTNG_OPTIONAL(unsigned int) action_index;
55};
56
57struct lttng_error_query_result {
58 enum lttng_error_query_result_type type;
59 char *name;
60 char *description;
61};
62
63struct lttng_error_query_result_comm {
64 /* enum lttng_error_query_result_type */
65 uint8_t type;
66 /* Length of name (including null-terminator). */
67 uint32_t name_len;
68 /* Length of description (including null-terminator). */
69 uint32_t description_len;
70 /* Name, description, and type-specific payload follow. */
71 char payload[];
72} LTTNG_PACKED;
73
74struct lttng_error_query_result_counter_comm {
75 uint64_t value;
76} LTTNG_PACKED;
77
78struct lttng_error_query_result_counter {
79 struct lttng_error_query_result parent;
80 uint64_t value;
81};
82
83struct lttng_error_query_results_comm {
84 uint32_t count;
85 /* `count` instances of `struct lttng_error_query_result` follow. */
86 char payload[];
87} LTTNG_PACKED;
88
89struct lttng_error_query_results {
90 struct lttng_dynamic_pointer_array results;
91};
92
93
94struct lttng_error_query *lttng_error_query_trigger_create(
95 const struct lttng_trigger *trigger)
96{
97 struct lttng_error_query_trigger *query = NULL;
98 struct lttng_trigger *trigger_copy;
99
100 trigger_copy = lttng_trigger_copy(trigger);
101 if (!trigger_copy) {
102 goto end;
103 }
104
105 if (!trigger) {
106 goto end;
107 }
108
109 query = zmalloc(sizeof(*query));
110 if (!query) {
111 PERROR("Failed to allocate trigger error query");
112 goto end;
113 }
114
115 query->parent.target_type = LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER;
116 query->trigger = trigger_copy;
117end:
118 return query ? &query->parent : NULL;
119}
120
121extern struct lttng_error_query *lttng_error_query_action_create(
122 const struct lttng_trigger *trigger,
123 const struct lttng_action *action)
124{
125 struct lttng_error_query_action *query = NULL;
126 typeof(query->action_index) action_index;
127 struct lttng_trigger *trigger_copy;
128
129 if (!trigger || !action) {
130 goto end;
131 }
132
133 trigger_copy = lttng_trigger_copy(trigger);
134 if (!trigger_copy) {
135 goto end;
136 }
137
138 /*
139 * If an action is not the top-level action of the trigger, our only
140 * hope of finding its position is if the top-level action is an
141 * action list.
142 *
143 * Note that action comparisons are performed by pointer since multiple
144 * otherwise identical actions can be found in an action group (two
145 * notify actions, for example).
146 */
147 if (action != trigger->action &&
148 lttng_action_get_type(trigger->action) ==
149 LTTNG_ACTION_TYPE_GROUP) {
150 unsigned int i, action_group_count;
151 enum lttng_action_status action_status;
152
153 action_status = lttng_action_group_get_count(
154 trigger->action, &action_group_count);
155 if (action_status != LTTNG_ACTION_STATUS_OK) {
156 goto end;
157 }
158
159 for (i = 0; i < action_group_count; i++) {
160 const struct lttng_action *candidate_action =
161 lttng_action_group_get_at_index(
162 trigger->action, i);
163
164 assert(candidate_action);
165 if (candidate_action == action) {
166 LTTNG_OPTIONAL_SET(&action_index, i);
167 break;
168 }
169 }
170
171 if (!action_index.is_set) {
172 /* Not found; invalid action. */
173 goto end;
174 }
175 } else {
176 /*
177 * Trigger action is not a group and not equal to the target
178 * action; invalid action provided.
179 */
180 goto end;
181 }
182
183 query = zmalloc(sizeof(*query));
184 if (!query) {
185 PERROR("Failed to allocate action error query");
186 goto end;
187 }
188
189 query->parent.target_type = LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION;
190 query->trigger = trigger_copy;
191 query->action_index = action_index;
192end:
193 return query ? &query->parent : NULL;
194}
195
196void lttng_error_query_destroy(struct lttng_error_query *query)
197{
198 struct lttng_error_query_trigger *trigger_query;
199
200 if (!query) {
201 return;
202 }
203
204 trigger_query = container_of(query, typeof(*trigger_query), parent);
205 lttng_trigger_put(trigger_query->trigger);
206 free(trigger_query);
207}
208
209static
210int lttng_error_query_result_counter_serialize(
211 const struct lttng_error_query_result *result,
212 struct lttng_payload *payload)
213{
214 const struct lttng_error_query_result_counter *counter_result;
215
216 assert(result->type == LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER);
217 counter_result = container_of(result, typeof(*counter_result), parent);
218
219 return lttng_dynamic_buffer_append(&payload->buffer,
220 &(struct lttng_error_query_result_counter_comm) {
221 .value = counter_result->value
222 },
223 sizeof(struct lttng_error_query_result_counter_comm));
224}
225
226LTTNG_HIDDEN
227int lttng_error_query_result_serialize(
228 const struct lttng_error_query_result *result,
229 struct lttng_payload *payload)
230{
231 int ret;
232 struct lttng_error_query_result_comm header = {
233 .type = (uint8_t) result->type,
234 .name_len = (typeof(header.name_len)) strlen(result->name) + 1,
235 .description_len = (typeof(header.name_len)) strlen(result->description) + 1,
236 };
237
238 /* Header. */
239 ret = lttng_dynamic_buffer_append(
240 &payload->buffer, &header, sizeof(header));
241 if (ret) {
242 ERR("Failed to append error query result communication header to payload");
243 goto end;
244 }
245
246 /* Name. */
247 ret = lttng_dynamic_buffer_append(
248 &payload->buffer, result->name, header.name_len);
249 if (ret) {
250 ERR("Failed to append error query result name to payload");
251 goto end;
252 }
253
254 /* Description. */
255 ret = lttng_dynamic_buffer_append(&payload->buffer, result->description,
256 header.description_len);
257 if (ret) {
258 ERR("Failed to append error query result description to payload");
259 goto end;
260 }
261
262 /* Type-specific payload. */
263 switch (result->type) {
264 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER:
265 ret = lttng_error_query_result_counter_serialize(
266 result, payload);
267 if (ret) {
268 ERR("Failed to serialize counter error query result");
269 goto end;
270 }
271 break;
272 default:
273 abort();
274 }
275
276end:
277 return ret;
278}
279
280static
281int lttng_error_query_result_init(
282 struct lttng_error_query_result *result,
283 enum lttng_error_query_result_type result_type,
284 const char *name,
285 const char *description)
286{
287 int ret;
288
289 assert(name);
290 assert(description);
291
292 result->type = result_type;
293
294 result->name = strdup(name);
295 if (!result->name) {
296 PERROR("Failed to copy error query result name");
297 ret = -1;
298 goto end;
299 }
300
301 result->description = strdup(description);
302 if (!result->description) {
303 PERROR("Failed to copy error query result description");
304 ret = -1;
305 goto end;
306 }
307
308 ret = 0;
309end:
310 return ret;
311}
312
313LTTNG_HIDDEN
314void lttng_error_query_result_destroy(struct lttng_error_query_result *counter)
315{
316 if (!counter) {
317 return;
318 }
319
320 switch (counter->type) {
321 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER:
322 /* Nothing to tear down. */
323 break;
324 default:
325 abort();
326 }
327
328 free(counter->name);
329 free(counter->description);
330 free(counter);
331}
332
333LTTNG_HIDDEN
334struct lttng_error_query_result *
335lttng_error_query_result_counter_create(
336 const char *name, const char *description, uint64_t value)
337{
338 int init_ret;
339 struct lttng_error_query_result_counter *counter;
340
341 counter = zmalloc(sizeof(*counter));
342 if (!counter) {
343 PERROR("Failed to allocate error query counter result");
344 goto end;
345 }
346
347 init_ret = lttng_error_query_result_init(&counter->parent,
348 LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER, name,
349 description);
350 if (init_ret) {
351 goto error;
352 }
353
588c4b0d 354 counter->value = value;
b99a0cb3
JG
355 goto end;
356error:
357 lttng_error_query_result_destroy(&counter->parent);
358end:
359 return counter ? &counter->parent : NULL;
360}
361
362static
363void destroy_result(void *ptr)
364{
365 struct lttng_error_query_result *result = (typeof(result)) ptr;
366
367 lttng_error_query_result_destroy(result);
368}
369
370LTTNG_HIDDEN
371struct lttng_error_query_results *lttng_error_query_results_create(void)
372{
373 struct lttng_error_query_results *set = zmalloc(sizeof(*set));
374
375 if (!set) {
376 PERROR("Failed to allocate an error query result set");
377 goto end;
378 }
379
380 lttng_dynamic_pointer_array_init(&set->results, destroy_result);
381end:
382 return set;
383}
384
385LTTNG_HIDDEN
386int lttng_error_query_results_add_result(
387 struct lttng_error_query_results *results,
388 struct lttng_error_query_result *result)
389{
390 return lttng_dynamic_pointer_array_add_pointer(
391 &results->results, result);
392}
393
394LTTNG_HIDDEN
395ssize_t lttng_error_query_result_create_from_payload(
396 struct lttng_payload_view *view,
397 struct lttng_error_query_result **result)
398{
399 ssize_t used_size = 0;
400 struct lttng_error_query_result_comm *header;
401 struct lttng_payload_view header_view =
402 lttng_payload_view_from_view(view, 0, sizeof(*header));
403 const char *name;
404 const char *description;
405
406 if (!lttng_payload_view_is_valid(&header_view)) {
407 used_size = -1;
408 goto end;
409 }
410
411 header = (typeof(header)) header_view.buffer.data;
412 used_size += sizeof(*header);
413
414 {
415 struct lttng_payload_view name_view =
416 lttng_payload_view_from_view(view, used_size,
417 header->name_len);
418
419 if (!lttng_payload_view_is_valid(&name_view) ||
420 !lttng_buffer_view_contains_string(
421 &name_view.buffer,
422 name_view.buffer.data,
423 header->name_len)) {
424 used_size = -1;
425 goto end;
426 }
427
428 name = name_view.buffer.data;
429 used_size += header->name_len;
430 }
431
432 {
433 struct lttng_payload_view description_view =
434 lttng_payload_view_from_view(view, used_size,
435 header->description_len);
436
437 if (!lttng_payload_view_is_valid(&description_view) ||
438 !lttng_buffer_view_contains_string(
439 &description_view.buffer,
440 description_view.buffer.data,
441 header->description_len)) {
442 used_size = -1;
443 goto end;
444 }
445
446 description = description_view.buffer.data;
447 used_size += header->description_len;
448 }
449
450 switch (header->type) {
451 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER:
452 {
453 struct lttng_error_query_result_counter_comm *counter;
454 struct lttng_payload_view counter_payload_view =
455 lttng_payload_view_from_view(view, used_size,
456 sizeof(*counter));
457
458 if (!lttng_payload_view_is_valid(&counter_payload_view)) {
459 used_size = -1;
460 goto end;
461 }
462
463 counter = (typeof(counter)) counter_payload_view.buffer.data;
464 *result = lttng_error_query_result_counter_create(
465 name, description, counter->value);
466 if (!*result) {
467 used_size = -1;
468 goto end;
469 }
470
471 used_size += sizeof(*counter);
472 break;
473 }
474 default:
475 used_size = -1;
476 goto end;
477 }
478
479end:
480 return used_size;
481}
482
483LTTNG_HIDDEN
484int lttng_error_query_results_serialize(
485 const struct lttng_error_query_results *results,
486 struct lttng_payload *payload)
487{
488 int ret;
489 size_t result_index;
490 const size_t result_count = lttng_dynamic_pointer_array_get_count(
491 &results->results);
492 const struct lttng_error_query_results_comm header = {
493 .count = (typeof(header.count)) result_count,
494 };
495
496 /* Header. */
497 ret = lttng_dynamic_buffer_append(&payload->buffer, &header, sizeof(header));
498 if (ret) {
499 ERR("Failed to append error query result set header to payload");
500 goto end;
501 }
502
503 /* Results. */
504 for (result_index = 0; result_index < result_count; result_index++) {
505 const struct lttng_error_query_result *result = (typeof(result))
506 lttng_dynamic_pointer_array_get_pointer(
507 &results->results,
508 result_index);
509
510 ret = lttng_error_query_result_serialize(result, payload);
511 if (ret) {
512 ERR("Failed to append error query result to payload");
513 goto end;
514 }
515 }
516end:
517 return ret;
518}
519
520LTTNG_HIDDEN
521ssize_t lttng_error_query_results_create_from_payload(
522 struct lttng_payload_view *view,
523 struct lttng_error_query_results **_results)
524{
525 size_t result_index;
526 ssize_t total_used_size = 0;
527 struct lttng_error_query_results_comm *header;
528 struct lttng_payload_view header_view =
529 lttng_payload_view_from_view(view, 0, sizeof(*header));
530 struct lttng_error_query_results *results = NULL;
531
532 if (!lttng_payload_view_is_valid(&header_view)) {
533 ERR("Failed to map view to error query result set header");
534 total_used_size = -1;
535 goto end;
536 }
537
538 header = (typeof(header)) header_view.buffer.data;
539 total_used_size += sizeof(*header);
540 results = lttng_error_query_results_create();
541 if (!results) {
542 total_used_size = -1;
543 goto end;
544 }
545
546 for (result_index = 0; result_index < header->count; result_index++) {
547 ssize_t used_size;
548 struct lttng_error_query_result *result;
549 struct lttng_payload_view result_view =
550 lttng_payload_view_from_view(
551 view, total_used_size, -1);
552
553 if (!lttng_payload_view_is_valid(&result_view)) {
554 total_used_size = -1;
555 goto end;
556 }
557
558 used_size = lttng_error_query_result_create_from_payload(
559 &result_view, &result);
560 if (used_size < 0) {
561 total_used_size = -1;
562 goto end;
563 }
564
565 total_used_size += used_size;
566
567 if (lttng_dynamic_pointer_array_add_pointer(
568 &results->results, result)) {
569 lttng_error_query_result_destroy(result);
570 total_used_size = -1;
571 goto end;
572 }
573 }
574
575 *_results = results;
576 results = NULL;
577end:
578 lttng_error_query_results_destroy(results);
579 return total_used_size;
580}
581
582static
583int lttng_error_query_trigger_serialize(const struct lttng_error_query *query,
584 struct lttng_payload *payload)
585{
586 int ret;
587 const struct lttng_error_query_trigger *query_trigger =
588 container_of(query, typeof(*query_trigger), parent);
589
590 if (!lttng_trigger_validate(query_trigger->trigger)) {
591 ret = -1;
592 goto end;
593 }
594
595 ret = lttng_trigger_serialize(query_trigger->trigger, payload);
596 if (ret) {
597 goto end;
598 }
599
600end:
601 return ret;
602}
603
604static
605int lttng_error_query_action_serialize(const struct lttng_error_query *query,
606 struct lttng_payload *payload)
607{
608 int ret;
609 const struct lttng_error_query_action *query_action =
610 container_of(query, typeof(*query_action), parent);
611 struct lttng_error_query_action_comm header = {
612 .action_index.is_set = query_action->action_index.is_set,
613 .action_index.value = query_action->action_index.value,
614 };
615
616 if (!lttng_trigger_validate(query_action->trigger)) {
617 ret = -1;
618 goto end;
619 }
620
621 ret = lttng_dynamic_buffer_append(
622 &payload->buffer, &header, sizeof(header));
623 if (ret) {
624 goto end;
625 }
626
627 ret = lttng_trigger_serialize(query_action->trigger, payload);
628 if (ret) {
629 goto end;
630 }
631end:
632 return ret;
633}
634
635LTTNG_HIDDEN
636enum lttng_error_query_target_type lttng_error_query_get_target_type(
637 const struct lttng_error_query *query)
638{
639 return query->target_type;
640}
641
642LTTNG_HIDDEN
643const struct lttng_trigger *lttng_error_query_trigger_borrow_target(
644 const struct lttng_error_query *query)
645{
646 const struct lttng_error_query_trigger *query_trigger =
647 container_of(query, typeof(*query_trigger), parent);
648
649 return query_trigger->trigger;
650}
651
652LTTNG_HIDDEN
653const struct lttng_trigger *lttng_error_query_action_borrow_trigger_target(
654 const struct lttng_error_query *query)
655{
656 const struct lttng_error_query_action *query_action =
657 container_of(query, typeof(*query_action), parent);
658
659 return query_action->trigger;
660}
661
662LTTNG_HIDDEN
588c4b0d 663struct lttng_action *lttng_error_query_action_borrow_action_target(
b99a0cb3 664 const struct lttng_error_query *query,
588c4b0d 665 struct lttng_trigger *trigger)
b99a0cb3 666{
588c4b0d 667 struct lttng_action *target_action = NULL;
b99a0cb3
JG
668 const struct lttng_error_query_action *query_action =
669 container_of(query, typeof(*query_action), parent);
588c4b0d
JG
670 struct lttng_action *trigger_action =
671 lttng_trigger_get_action(trigger);
b99a0cb3
JG
672
673 if (!query_action->action_index.is_set) {
674 target_action = trigger_action;
675 } else {
676 if (lttng_action_get_type(trigger_action) !=
677 LTTNG_ACTION_TYPE_GROUP) {
678 ERR("Invalid action error query target index: trigger action is not a group");
679 goto end;
680 }
681
588c4b0d
JG
682 target_action = lttng_action_group_borrow_mutable_at_index(
683 trigger_action,
b99a0cb3
JG
684 LTTNG_OPTIONAL_GET(query_action->action_index));
685 }
686
687end:
688 return target_action;
689}
690
691LTTNG_HIDDEN
692int lttng_error_query_serialize(const struct lttng_error_query *query,
693 struct lttng_payload *payload)
694{
695 int ret;
696 struct lttng_error_query_comm header = {
697 .target_type = (typeof(header.target_type)) query->target_type,
698 };
699
700 ret = lttng_dynamic_buffer_append(
701 &payload->buffer, &header, sizeof(header));
702 if (ret) {
703 ERR("Failed to append error query header to payload");
704 goto end;
705 }
706
707 switch (query->target_type) {
708 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER:
709 ret = lttng_error_query_trigger_serialize(query, payload);
710 if (ret) {
711 goto end;
712 }
713
714 break;
715 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION:
716 ret = lttng_error_query_action_serialize(query, payload);
717 if (ret) {
718 goto end;
719 }
720
721 break;
722 default:
723 abort();
724 }
725end:
726 return ret;
727}
728
729LTTNG_HIDDEN
730ssize_t lttng_error_query_create_from_payload(struct lttng_payload_view *view,
731 struct lttng_error_query **query)
732{
733 ssize_t used_size = 0;
734 struct lttng_error_query_comm *header;
735 struct lttng_payload_view header_view =
736 lttng_payload_view_from_view(view, 0, sizeof(*header));
737
738 if (!lttng_payload_view_is_valid(&header_view)) {
739 ERR("Failed to map error query header");
740 used_size = -1;
741 goto end;
742 }
743
744 used_size = sizeof(*header);
745
746 header = (typeof(header)) header_view.buffer.data;
747 switch ((enum lttng_error_query_target_type) header->target_type) {
748 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER:
749 {
750 struct lttng_trigger *trigger;
751 ssize_t trigger_used_size;
752 struct lttng_payload_view trigger_view =
753 lttng_payload_view_from_view(
754 view, used_size, -1);
755
756 if (!lttng_payload_view_is_valid(&trigger_view)) {
757 used_size = -1;
758 goto end;
759 }
760
761 trigger_used_size = lttng_trigger_create_from_payload(
762 &trigger_view, &trigger);
763 if (trigger_used_size < 0) {
764 used_size = -1;
765 goto end;
766 }
767
768 used_size += trigger_used_size;
769
770 *query = lttng_error_query_trigger_create(trigger);
771 lttng_trigger_put(trigger);
772 if (!*query) {
773 used_size = -1;
774 goto end;
775 }
776
777 break;
778 }
779 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION:
780 {
781 struct lttng_trigger *trigger;
782 const struct lttng_action *target_action;
783 ssize_t trigger_used_size;
784 struct lttng_error_query_action_comm *action_header;
785
786 {
787 struct lttng_payload_view action_header_view =
788 lttng_payload_view_from_view(view,
789 used_size,
790 sizeof(*action_header));
791
792 if (!lttng_payload_view_is_valid(&action_header_view)) {
793 used_size = -1;
794 goto end;
795 }
796
797 action_header = (typeof(action_header)) action_header_view.buffer.data;
798 used_size += sizeof(*action_header);
799 }
800
801 {
802 struct lttng_payload_view trigger_view =
803 lttng_payload_view_from_view(
804 view, used_size, -1);
805
806 if (!lttng_payload_view_is_valid(&trigger_view)) {
807 used_size = -1;
808 goto end;
809 }
810
811 trigger_used_size = lttng_trigger_create_from_payload(
812 &trigger_view, &trigger);
813 if (trigger_used_size < 0) {
814 used_size = -1;
815 goto end;
816 }
817
818 used_size += trigger_used_size;
819 }
820
821 if (!action_header->action_index.is_set) {
822 target_action = trigger->action;
823 } else {
824 if (lttng_action_get_type(trigger->action) !=
825 LTTNG_ACTION_TYPE_GROUP) {
826 used_size = -1;
827 goto end;
828 }
829
830 target_action = lttng_action_group_get_at_index(
831 trigger->action,
832 action_header->action_index.value);
833 }
834
835 *query = lttng_error_query_action_create(
836 trigger, target_action);
837 lttng_trigger_put(trigger);
838 if (!*query) {
839 used_size = -1;
840 goto end;
841 }
842
843 break;
844 }
845 default:
846 used_size = -1;
847 goto end;
848 }
849
850end:
851 return used_size;
852}
853
854enum lttng_error_query_results_status lttng_error_query_results_get_count(
855 const struct lttng_error_query_results *results,
856 unsigned int *count)
857{
858 enum lttng_error_query_results_status status;
859
860 if (!results || !count) {
861 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER;
862 goto end;
863 }
864
865 *count = lttng_dynamic_pointer_array_get_count(&results->results);
866 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_OK;
867end:
868 return status;
869}
870
871enum lttng_error_query_results_status
872lttng_error_query_results_get_result(
873 const struct lttng_error_query_results *results,
874 const struct lttng_error_query_result **result,
875 unsigned int index)
876{
877 unsigned int result_count;
878 enum lttng_error_query_results_status status;
879
880 if (!results || !result) {
881 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER;
882 goto end;
883 }
884
885 status = lttng_error_query_results_get_count(results, &result_count);
886 if (status != LTTNG_ERROR_QUERY_RESULTS_STATUS_OK) {
887 goto end;
888 }
889
890 if (index >= result_count) {
891 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER;
892 goto end;
893 }
894
895 *result = (typeof(*result)) lttng_dynamic_pointer_array_get_pointer(
896 &results->results, index);
897 assert(*result);
898 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_OK;
899end:
900 return status;
901}
902
903void lttng_error_query_results_destroy(
904 struct lttng_error_query_results *results)
905{
906 if (!results) {
907 return;
908 }
909
910 lttng_dynamic_pointer_array_reset(&results->results);
911 free(results);
912}
913
914enum lttng_error_query_result_type
915lttng_error_query_result_get_type(const struct lttng_error_query_result *result)
916{
917 return result ? result->type : LTTNG_ERROR_QUERY_RESULT_TYPE_UNKNOWN;
918}
919
920enum lttng_error_query_result_status lttng_error_query_result_get_name(
921 const struct lttng_error_query_result *result,
922 const char **name)
923{
924 enum lttng_error_query_result_status status;
925
926 if (!result || !name) {
927 status = LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER;
928 goto end;
929 }
930
931 *name = result->name;
932 status = LTTNG_ERROR_QUERY_RESULT_STATUS_OK;
933end:
934 return status;
935}
936
937enum lttng_error_query_result_status lttng_error_query_result_get_description(
938 const struct lttng_error_query_result *result,
939 const char **description)
940{
941 enum lttng_error_query_result_status status;
942
943 if (!result || !description) {
944 status = LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER;
945 goto end;
946 }
947
948 *description = result->description;
949 status = LTTNG_ERROR_QUERY_RESULT_STATUS_OK;
950end:
951 return status;
952}
953
954enum lttng_error_query_result_status lttng_error_query_result_counter_get_value(
955 const struct lttng_error_query_result *result,
956 uint64_t *value)
957{
958 enum lttng_error_query_result_status status;
959 const struct lttng_error_query_result_counter *counter_result;
960
961 if (!result || !value ||
962 result->type != LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER) {
963 status = LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER;
964 goto end;
965 }
966
967 counter_result = container_of(result, typeof(*counter_result), parent);
968
969 *value = counter_result->value;
970 status = LTTNG_ERROR_QUERY_RESULT_STATUS_OK;
971end:
972 return status;
973}
This page took 0.057253 seconds and 4 git commands to generate.