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