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