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