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