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