Fix: futex wait: handle spurious futex wakeups
[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 if (!query) {
252 return;
253 }
254
255 switch (query->target_type) {
256 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER:
257 {
258 struct lttng_error_query_trigger *trigger_query =
259 lttng::utils::container_of(query, &lttng_error_query_trigger::parent);
260
261 lttng_trigger_put(trigger_query->trigger);
262 free(trigger_query);
263 break;
264 }
265 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION:
266 {
267 struct lttng_error_query_condition *condition_query = lttng::utils::container_of(
268 query, &lttng_error_query_condition::parent);
269
270 lttng_trigger_put(condition_query->trigger);
271 free(condition_query);
272 break;
273 }
274 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION:
275 {
276 struct lttng_error_query_action *action_query = lttng::utils::container_of(
277 query, &lttng_error_query_action::parent);
278
279 lttng_trigger_put(action_query->trigger);
280 lttng_action_path_destroy(action_query->action_path);
281 free(action_query);
282 break;
283 }
284 default:
285 abort();
286 }
287 }
288
289 static
290 int lttng_error_query_result_counter_serialize(
291 const struct lttng_error_query_result *result,
292 struct lttng_payload *payload)
293 {
294 const struct lttng_error_query_result_counter *counter_result;
295
296 LTTNG_ASSERT(result->type == LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER);
297 counter_result = lttng::utils::container_of(
298 result, &lttng_error_query_result_counter::parent);
299
300 lttng_error_query_result_counter_comm comm = {
301 .value = counter_result->value,
302 };
303
304 return lttng_dynamic_buffer_append(&payload->buffer,
305 &comm,
306 sizeof(struct lttng_error_query_result_counter_comm));
307 }
308
309 int lttng_error_query_result_serialize(
310 const struct lttng_error_query_result *result,
311 struct lttng_payload *payload)
312 {
313 int ret;
314 struct lttng_error_query_result_comm header;
315
316 header.type = (uint8_t) result->type;
317 header.name_len = (typeof(header.name_len)) strlen(result->name) + 1;
318 header.description_len = (typeof(header.name_len)) strlen(result->description) + 1;
319
320 /* Header. */
321 ret = lttng_dynamic_buffer_append(
322 &payload->buffer, &header, sizeof(header));
323 if (ret) {
324 ERR("Failed to append error query result communication header to payload");
325 goto end;
326 }
327
328 /* Name. */
329 ret = lttng_dynamic_buffer_append(
330 &payload->buffer, result->name, header.name_len);
331 if (ret) {
332 ERR("Failed to append error query result name to payload");
333 goto end;
334 }
335
336 /* Description. */
337 ret = lttng_dynamic_buffer_append(&payload->buffer, result->description,
338 header.description_len);
339 if (ret) {
340 ERR("Failed to append error query result description to payload");
341 goto end;
342 }
343
344 /* Type-specific payload. */
345 switch (result->type) {
346 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER:
347 ret = lttng_error_query_result_counter_serialize(
348 result, payload);
349 if (ret) {
350 ERR("Failed to serialize counter error query result");
351 goto end;
352 }
353 break;
354 default:
355 abort();
356 }
357
358 end:
359 return ret;
360 }
361
362 static
363 int lttng_error_query_result_init(
364 struct lttng_error_query_result *result,
365 enum lttng_error_query_result_type result_type,
366 const char *name,
367 const char *description)
368 {
369 int ret;
370
371 LTTNG_ASSERT(name);
372 LTTNG_ASSERT(description);
373
374 result->type = result_type;
375
376 result->name = strdup(name);
377 if (!result->name) {
378 PERROR("Failed to copy error query result name");
379 ret = -1;
380 goto end;
381 }
382
383 result->description = strdup(description);
384 if (!result->description) {
385 PERROR("Failed to copy error query result description");
386 ret = -1;
387 goto end;
388 }
389
390 ret = 0;
391 end:
392 return ret;
393 }
394
395 void lttng_error_query_result_destroy(struct lttng_error_query_result *counter)
396 {
397 if (!counter) {
398 return;
399 }
400
401 switch (counter->type) {
402 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER:
403 /* Nothing to tear down. */
404 break;
405 default:
406 abort();
407 }
408
409 free(counter->name);
410 free(counter->description);
411 free(counter);
412 }
413
414 struct lttng_error_query_result *
415 lttng_error_query_result_counter_create(
416 const char *name, const char *description, uint64_t value)
417 {
418 int init_ret;
419 struct lttng_error_query_result_counter *counter;
420
421 counter = zmalloc<lttng_error_query_result_counter>();
422 if (!counter) {
423 PERROR("Failed to allocate error query counter result");
424 goto end;
425 }
426
427 init_ret = lttng_error_query_result_init(&counter->parent,
428 LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER, name,
429 description);
430 if (init_ret) {
431 goto error;
432 }
433
434 counter->value = value;
435 goto end;
436 error:
437 lttng_error_query_result_destroy(&counter->parent);
438 end:
439 return counter ? &counter->parent : NULL;
440 }
441
442 static
443 void destroy_result(void *ptr)
444 {
445 struct lttng_error_query_result *result = (typeof(result)) ptr;
446
447 lttng_error_query_result_destroy(result);
448 }
449
450 struct lttng_error_query_results *lttng_error_query_results_create(void)
451 {
452 struct lttng_error_query_results *set = zmalloc<lttng_error_query_results>();
453
454 if (!set) {
455 PERROR("Failed to allocate an error query result set");
456 goto end;
457 }
458
459 lttng_dynamic_pointer_array_init(&set->results, destroy_result);
460 end:
461 return set;
462 }
463
464 int lttng_error_query_results_add_result(
465 struct lttng_error_query_results *results,
466 struct lttng_error_query_result *result)
467 {
468 return lttng_dynamic_pointer_array_add_pointer(
469 &results->results, result);
470 }
471
472 ssize_t lttng_error_query_result_create_from_payload(
473 struct lttng_payload_view *view,
474 struct lttng_error_query_result **result)
475 {
476 ssize_t used_size = 0;
477 struct lttng_error_query_result_comm *header;
478 struct lttng_payload_view header_view =
479 lttng_payload_view_from_view(view, 0, sizeof(*header));
480 const char *name;
481 const char *description;
482
483 if (!lttng_payload_view_is_valid(&header_view)) {
484 used_size = -1;
485 goto end;
486 }
487
488 header = (typeof(header)) header_view.buffer.data;
489 used_size += sizeof(*header);
490
491 {
492 struct lttng_payload_view name_view =
493 lttng_payload_view_from_view(view, used_size,
494 header->name_len);
495
496 if (!lttng_payload_view_is_valid(&name_view) ||
497 !lttng_buffer_view_contains_string(
498 &name_view.buffer,
499 name_view.buffer.data,
500 header->name_len)) {
501 used_size = -1;
502 goto end;
503 }
504
505 name = name_view.buffer.data;
506 used_size += header->name_len;
507 }
508
509 {
510 struct lttng_payload_view description_view =
511 lttng_payload_view_from_view(view, used_size,
512 header->description_len);
513
514 if (!lttng_payload_view_is_valid(&description_view) ||
515 !lttng_buffer_view_contains_string(
516 &description_view.buffer,
517 description_view.buffer.data,
518 header->description_len)) {
519 used_size = -1;
520 goto end;
521 }
522
523 description = description_view.buffer.data;
524 used_size += header->description_len;
525 }
526
527 switch (header->type) {
528 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER:
529 {
530 struct lttng_error_query_result_counter_comm *counter;
531 struct lttng_payload_view counter_payload_view =
532 lttng_payload_view_from_view(view, used_size,
533 sizeof(*counter));
534
535 if (!lttng_payload_view_is_valid(&counter_payload_view)) {
536 used_size = -1;
537 goto end;
538 }
539
540 counter = (typeof(counter)) counter_payload_view.buffer.data;
541 *result = lttng_error_query_result_counter_create(
542 name, description, counter->value);
543 if (!*result) {
544 used_size = -1;
545 goto end;
546 }
547
548 used_size += sizeof(*counter);
549 break;
550 }
551 default:
552 used_size = -1;
553 goto end;
554 }
555
556 end:
557 return used_size;
558 }
559
560 int lttng_error_query_results_serialize(
561 const struct lttng_error_query_results *results,
562 struct lttng_payload *payload)
563 {
564 int ret;
565 size_t result_index;
566 const size_t result_count = lttng_dynamic_pointer_array_get_count(
567 &results->results);
568 struct lttng_error_query_results_comm header;
569
570 header.count = (decltype(header.count)) result_count;
571
572 /* Header. */
573 ret = lttng_dynamic_buffer_append(&payload->buffer, &header, sizeof(header));
574 if (ret) {
575 ERR("Failed to append error query result set header to payload");
576 goto end;
577 }
578
579 /* Results. */
580 for (result_index = 0; result_index < result_count; result_index++) {
581 const struct lttng_error_query_result *result = (typeof(result))
582 lttng_dynamic_pointer_array_get_pointer(
583 &results->results,
584 result_index);
585
586 ret = lttng_error_query_result_serialize(result, payload);
587 if (ret) {
588 ERR("Failed to append error query result to payload");
589 goto end;
590 }
591 }
592 end:
593 return ret;
594 }
595
596 ssize_t lttng_error_query_results_create_from_payload(
597 struct lttng_payload_view *view,
598 struct lttng_error_query_results **_results)
599 {
600 size_t result_index;
601 ssize_t total_used_size = 0;
602 struct lttng_error_query_results_comm *header;
603 struct lttng_payload_view header_view =
604 lttng_payload_view_from_view(view, 0, sizeof(*header));
605 struct lttng_error_query_results *results = NULL;
606
607 if (!lttng_payload_view_is_valid(&header_view)) {
608 ERR("Failed to map view to error query result set header");
609 total_used_size = -1;
610 goto end;
611 }
612
613 header = (typeof(header)) header_view.buffer.data;
614 total_used_size += sizeof(*header);
615 results = lttng_error_query_results_create();
616 if (!results) {
617 total_used_size = -1;
618 goto end;
619 }
620
621 for (result_index = 0; result_index < header->count; result_index++) {
622 ssize_t used_size;
623 struct lttng_error_query_result *result;
624 struct lttng_payload_view result_view =
625 lttng_payload_view_from_view(
626 view, total_used_size, -1);
627
628 if (!lttng_payload_view_is_valid(&result_view)) {
629 total_used_size = -1;
630 goto end;
631 }
632
633 used_size = lttng_error_query_result_create_from_payload(
634 &result_view, &result);
635 if (used_size < 0) {
636 total_used_size = -1;
637 goto end;
638 }
639
640 total_used_size += used_size;
641
642 if (lttng_dynamic_pointer_array_add_pointer(
643 &results->results, result)) {
644 lttng_error_query_result_destroy(result);
645 total_used_size = -1;
646 goto end;
647 }
648 }
649
650 *_results = results;
651 results = NULL;
652 end:
653 lttng_error_query_results_destroy(results);
654 return total_used_size;
655 }
656
657 static
658 int lttng_error_query_trigger_serialize(const struct lttng_error_query *query,
659 struct lttng_payload *payload)
660 {
661 int ret;
662 const struct lttng_error_query_trigger *query_trigger =
663 lttng::utils::container_of(query, &lttng_error_query_trigger::parent);
664
665 if (!lttng_trigger_validate(query_trigger->trigger)) {
666 ret = -1;
667 goto end;
668 }
669
670 ret = lttng_trigger_serialize(query_trigger->trigger, payload);
671 if (ret) {
672 goto end;
673 }
674
675 end:
676 return ret;
677 }
678
679 static
680 int lttng_error_query_condition_serialize(const struct lttng_error_query *query,
681 struct lttng_payload *payload)
682 {
683 int ret;
684 const struct lttng_error_query_condition *query_trigger =
685 lttng::utils::container_of(query, &lttng_error_query_condition::parent);
686
687 if (!lttng_trigger_validate(query_trigger->trigger)) {
688 ret = -1;
689 goto end;
690 }
691
692 ret = lttng_trigger_serialize(query_trigger->trigger, payload);
693 if (ret) {
694 goto end;
695 }
696
697 end:
698 return ret;
699 }
700
701 static
702 int lttng_error_query_action_serialize(const struct lttng_error_query *query,
703 struct lttng_payload *payload)
704 {
705 int ret;
706 const struct lttng_error_query_action *query_action =
707 lttng::utils::container_of(query, &lttng_error_query_action::parent);
708
709 if (!lttng_trigger_validate(query_action->trigger)) {
710 ret = -1;
711 goto end;
712 }
713
714 ret = lttng_trigger_serialize(query_action->trigger, payload);
715 if (ret) {
716 goto end;
717 }
718
719 ret = lttng_action_path_serialize(query_action->action_path, payload);
720 if (ret) {
721 goto end;
722 }
723
724 end:
725 return ret;
726 }
727
728 enum lttng_error_query_target_type lttng_error_query_get_target_type(
729 const struct lttng_error_query *query)
730 {
731 return query->target_type;
732 }
733
734 const struct lttng_trigger *lttng_error_query_trigger_borrow_target(
735 const struct lttng_error_query *query)
736 {
737 const struct lttng_error_query_trigger *query_trigger =
738 lttng::utils::container_of(query, &lttng_error_query_trigger::parent);
739
740 return query_trigger->trigger;
741 }
742
743 const struct lttng_trigger *lttng_error_query_condition_borrow_target(
744 const struct lttng_error_query *query)
745 {
746 const struct lttng_error_query_condition *query_trigger =
747 lttng::utils::container_of(query, &lttng_error_query_condition::parent);
748
749 return query_trigger->trigger;
750 }
751
752 const struct lttng_trigger *lttng_error_query_action_borrow_trigger_target(
753 const struct lttng_error_query *query)
754 {
755 const struct lttng_error_query_action *query_action =
756 lttng::utils::container_of(query, &lttng_error_query_action::parent);
757
758 return query_action->trigger;
759 }
760
761 struct lttng_action *lttng_error_query_action_borrow_action_target(
762 const struct lttng_error_query *query, struct lttng_trigger *trigger)
763 {
764 const struct lttng_error_query_action *query_action =
765 lttng::utils::container_of(query, &lttng_error_query_action::parent);
766
767 return get_trigger_action_from_path(
768 trigger, query_action->action_path);
769 }
770
771 int lttng_error_query_serialize(const struct lttng_error_query *query,
772 struct lttng_payload *payload)
773 {
774 int ret;
775 struct lttng_error_query_comm header;
776
777 header.target_type = (decltype(header.target_type)) query->target_type;
778
779 ret = lttng_dynamic_buffer_append(
780 &payload->buffer, &header, sizeof(header));
781 if (ret) {
782 ERR("Failed to append error query header to payload");
783 goto end;
784 }
785
786 switch (query->target_type) {
787 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER:
788 ret = lttng_error_query_trigger_serialize(query, payload);
789 if (ret) {
790 goto end;
791 }
792
793 break;
794 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION:
795 ret = lttng_error_query_condition_serialize(query, payload);
796 if (ret) {
797 goto end;
798 }
799
800 break;
801 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION:
802 ret = lttng_error_query_action_serialize(query, payload);
803 if (ret) {
804 goto end;
805 }
806
807 break;
808 default:
809 abort();
810 }
811 end:
812 return ret;
813 }
814
815 ssize_t lttng_error_query_create_from_payload(struct lttng_payload_view *view,
816 struct lttng_error_query **query)
817 {
818 ssize_t used_size = 0;
819 struct lttng_error_query_comm *header;
820 struct lttng_trigger *trigger = NULL;
821 struct lttng_payload_view header_view =
822 lttng_payload_view_from_view(view, 0, sizeof(*header));
823
824 if (!lttng_payload_view_is_valid(&header_view)) {
825 ERR("Failed to map error query header");
826 used_size = -1;
827 goto end;
828 }
829
830 used_size = sizeof(*header);
831
832 header = (typeof(header)) header_view.buffer.data;
833 switch ((enum lttng_error_query_target_type) header->target_type) {
834 case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER:
835 {
836 ssize_t trigger_used_size;
837 struct lttng_payload_view trigger_view =
838 lttng_payload_view_from_view(
839 view, used_size, -1);
840
841 if (!lttng_payload_view_is_valid(&trigger_view)) {
842 used_size = -1;
843 goto end;
844 }
845
846 trigger_used_size = lttng_trigger_create_from_payload(
847 &trigger_view, &trigger);
848 if (trigger_used_size < 0) {
849 used_size = -1;
850 goto end;
851 }
852
853 used_size += trigger_used_size;
854
855 *query = lttng_error_query_trigger_create(trigger);
856 if (!*query) {
857 used_size = -1;
858 goto end;
859 }
860
861 break;
862 }
863 case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION:
864 {
865 ssize_t trigger_used_size;
866 struct lttng_payload_view trigger_view =
867 lttng_payload_view_from_view(
868 view, used_size, -1);
869
870 if (!lttng_payload_view_is_valid(&trigger_view)) {
871 used_size = -1;
872 goto end;
873 }
874
875 trigger_used_size = lttng_trigger_create_from_payload(
876 &trigger_view, &trigger);
877 if (trigger_used_size < 0) {
878 used_size = -1;
879 goto end;
880 }
881
882 used_size += trigger_used_size;
883
884 *query = lttng_error_query_condition_create(trigger);
885 if (!*query) {
886 used_size = -1;
887 goto end;
888 }
889
890 break;
891 }
892 case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION:
893 {
894 struct lttng_action_path *action_path = NULL;
895
896 {
897 ssize_t trigger_used_size;
898 struct lttng_payload_view trigger_view =
899 lttng_payload_view_from_view(
900 view, used_size, -1);
901
902 if (!lttng_payload_view_is_valid(&trigger_view)) {
903 used_size = -1;
904 goto end;
905 }
906
907 trigger_used_size = lttng_trigger_create_from_payload(
908 &trigger_view, &trigger);
909 if (trigger_used_size < 0) {
910 used_size = -1;
911 goto end;
912 }
913
914 used_size += trigger_used_size;
915 }
916
917 {
918 ssize_t action_path_used_size;
919 struct lttng_payload_view action_path_view =
920 lttng_payload_view_from_view(
921 view, used_size, -1);
922
923 if (!lttng_payload_view_is_valid(&action_path_view)) {
924 used_size = -1;
925 goto end;
926 }
927
928 action_path_used_size = lttng_action_path_create_from_payload(
929 &action_path_view, &action_path);
930 if (action_path_used_size < 0) {
931 used_size = -1;
932 goto end;
933 }
934
935 used_size += action_path_used_size;
936 }
937
938 *query = lttng_error_query_action_create(
939 trigger, action_path);
940 lttng_action_path_destroy(action_path);
941 if (!*query) {
942 used_size = -1;
943 goto end;
944 }
945
946 break;
947 }
948 default:
949 used_size = -1;
950 goto end;
951 }
952
953 end:
954 lttng_trigger_put(trigger);
955 return used_size;
956 }
957
958 enum lttng_error_query_results_status lttng_error_query_results_get_count(
959 const struct lttng_error_query_results *results,
960 unsigned int *count)
961 {
962 enum lttng_error_query_results_status status;
963
964 if (!results || !count) {
965 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER;
966 goto end;
967 }
968
969 *count = lttng_dynamic_pointer_array_get_count(&results->results);
970 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_OK;
971 end:
972 return status;
973 }
974
975 enum lttng_error_query_results_status
976 lttng_error_query_results_get_result(
977 const struct lttng_error_query_results *results,
978 const struct lttng_error_query_result **result,
979 unsigned int index)
980 {
981 unsigned int result_count;
982 enum lttng_error_query_results_status status;
983
984 if (!results || !result) {
985 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER;
986 goto end;
987 }
988
989 status = lttng_error_query_results_get_count(results, &result_count);
990 if (status != LTTNG_ERROR_QUERY_RESULTS_STATUS_OK) {
991 goto end;
992 }
993
994 if (index >= result_count) {
995 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_INVALID_PARAMETER;
996 goto end;
997 }
998
999 *result = (typeof(*result)) lttng_dynamic_pointer_array_get_pointer(
1000 &results->results, index);
1001 LTTNG_ASSERT(*result);
1002 status = LTTNG_ERROR_QUERY_RESULTS_STATUS_OK;
1003 end:
1004 return status;
1005 }
1006
1007 void lttng_error_query_results_destroy(
1008 struct lttng_error_query_results *results)
1009 {
1010 if (!results) {
1011 return;
1012 }
1013
1014 lttng_dynamic_pointer_array_reset(&results->results);
1015 free(results);
1016 }
1017
1018 enum lttng_error_query_result_type
1019 lttng_error_query_result_get_type(const struct lttng_error_query_result *result)
1020 {
1021 return result ? result->type : LTTNG_ERROR_QUERY_RESULT_TYPE_UNKNOWN;
1022 }
1023
1024 enum lttng_error_query_result_status lttng_error_query_result_get_name(
1025 const struct lttng_error_query_result *result,
1026 const char **name)
1027 {
1028 enum lttng_error_query_result_status status;
1029
1030 if (!result || !name) {
1031 status = LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER;
1032 goto end;
1033 }
1034
1035 *name = result->name;
1036 status = LTTNG_ERROR_QUERY_RESULT_STATUS_OK;
1037 end:
1038 return status;
1039 }
1040
1041 enum lttng_error_query_result_status lttng_error_query_result_get_description(
1042 const struct lttng_error_query_result *result,
1043 const char **description)
1044 {
1045 enum lttng_error_query_result_status status;
1046
1047 if (!result || !description) {
1048 status = LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER;
1049 goto end;
1050 }
1051
1052 *description = result->description;
1053 status = LTTNG_ERROR_QUERY_RESULT_STATUS_OK;
1054 end:
1055 return status;
1056 }
1057
1058 enum lttng_error_query_result_status lttng_error_query_result_counter_get_value(
1059 const struct lttng_error_query_result *result,
1060 uint64_t *value)
1061 {
1062 enum lttng_error_query_result_status status;
1063 const struct lttng_error_query_result_counter *counter_result;
1064
1065 if (!result || !value ||
1066 result->type != LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER) {
1067 status = LTTNG_ERROR_QUERY_RESULT_STATUS_INVALID_PARAMETER;
1068 goto end;
1069 }
1070
1071 counter_result = lttng::utils::container_of(
1072 result, &lttng_error_query_result_counter::parent);
1073
1074 *value = counter_result->value;
1075 status = LTTNG_ERROR_QUERY_RESULT_STATUS_OK;
1076 end:
1077 return status;
1078 }
1079
1080 static
1081 enum lttng_error_code lttng_error_query_result_counter_mi_serialize(
1082 const struct lttng_error_query_result *result,
1083 struct mi_writer *writer)
1084 {
1085 int ret;
1086 enum lttng_error_code ret_code;
1087 enum lttng_error_query_result_status status;
1088 uint64_t value;
1089
1090 LTTNG_ASSERT(result);
1091 LTTNG_ASSERT(writer);
1092
1093 status = lttng_error_query_result_counter_get_value(result, &value);
1094 LTTNG_ASSERT(status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK);
1095
1096 /* Open error query result counter element. */
1097 ret = mi_lttng_writer_open_element(
1098 writer, mi_lttng_element_error_query_result_counter);
1099 if (ret) {
1100 goto mi_error;
1101 }
1102
1103 /* Value. */
1104 ret = mi_lttng_writer_write_element_unsigned_int(writer,
1105 mi_lttng_element_error_query_result_counter_value,
1106 value);
1107 if (ret) {
1108 goto mi_error;
1109 }
1110
1111 /* Close error query result counter element. */
1112 ret = mi_lttng_writer_close_element(writer);
1113 if (ret) {
1114 goto mi_error;
1115 }
1116
1117 ret_code = LTTNG_OK;
1118 goto end;
1119
1120 mi_error:
1121 ret_code = LTTNG_ERR_MI_IO_FAIL;
1122 end:
1123 return ret_code;
1124 }
1125
1126 static
1127 enum lttng_error_code lttng_error_query_result_mi_serialize(
1128 const struct lttng_error_query_result *result,
1129 struct mi_writer *writer)
1130 {
1131 int ret;
1132 enum lttng_error_code ret_code;
1133 enum lttng_error_query_result_status result_status;
1134 enum lttng_error_query_result_type type;
1135 const char *name = NULL;
1136 const char *description = NULL;
1137
1138 LTTNG_ASSERT(result);
1139 LTTNG_ASSERT(writer);
1140
1141 type = lttng_error_query_result_get_type(result);
1142
1143 result_status = lttng_error_query_result_get_name(result, &name);
1144 LTTNG_ASSERT(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK);
1145
1146 result_status = lttng_error_query_result_get_description(
1147 result, &description);
1148 LTTNG_ASSERT(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK);
1149
1150 /* Open error query result element. */
1151 ret = mi_lttng_writer_open_element(
1152 writer, mi_lttng_element_error_query_result);
1153 if (ret) {
1154 goto mi_error;
1155 }
1156
1157 /* Name. */
1158 ret = mi_lttng_writer_write_element_string(
1159 writer, mi_lttng_element_error_query_result_name, name);
1160 if (ret) {
1161 goto mi_error;
1162 }
1163
1164 /* Description. */
1165 ret = mi_lttng_writer_write_element_string(writer,
1166 mi_lttng_element_error_query_result_description,
1167 description);
1168 if (ret) {
1169 goto mi_error;
1170 }
1171
1172 /* Serialize the result according to its sub type. */
1173 switch (type) {
1174 case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER:
1175 ret_code = lttng_error_query_result_counter_mi_serialize(
1176 result, writer);
1177 break;
1178 default:
1179 abort();
1180 }
1181
1182 if (ret_code != LTTNG_OK) {
1183 goto end;
1184 }
1185
1186 /* Close error query result element. */
1187 ret = mi_lttng_writer_close_element(writer);
1188 if (ret) {
1189 goto mi_error;
1190 }
1191
1192 ret_code = LTTNG_OK;
1193 goto end;
1194
1195 mi_error:
1196 ret_code = LTTNG_ERR_MI_IO_FAIL;
1197 end:
1198 return ret_code;
1199 }
1200
1201 enum lttng_error_code lttng_error_query_results_mi_serialize(
1202 const struct lttng_error_query_results *results,
1203 struct mi_writer *writer)
1204 {
1205 int ret;
1206 enum lttng_error_code ret_code;
1207 unsigned int i, count;
1208 enum lttng_error_query_results_status results_status;
1209
1210 LTTNG_ASSERT(results);
1211 LTTNG_ASSERT(writer);
1212
1213 /* Open error query results element. */
1214 ret = mi_lttng_writer_open_element(
1215 writer, mi_lttng_element_error_query_results);
1216 if (ret) {
1217 goto mi_error;
1218 }
1219
1220 results_status = lttng_error_query_results_get_count(results, &count);
1221 LTTNG_ASSERT(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK);
1222
1223 for (i = 0; i < count; i++) {
1224 const struct lttng_error_query_result *result;
1225
1226 results_status = lttng_error_query_results_get_result(
1227 results, &result, i);
1228 LTTNG_ASSERT(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK);
1229
1230 /* A single error query result. */
1231 ret_code = lttng_error_query_result_mi_serialize(result, writer);
1232 if (ret_code != LTTNG_OK) {
1233 goto end;
1234 }
1235 }
1236
1237 /* Close error query results. */
1238 ret = mi_lttng_writer_close_element(writer);
1239 if (ret) {
1240 goto mi_error;
1241 }
1242
1243 ret_code = LTTNG_OK;
1244 goto end;
1245
1246 mi_error:
1247 ret_code = LTTNG_ERR_MI_IO_FAIL;
1248 end:
1249 return ret_code;
1250 }
This page took 0.09037 seconds and 4 git commands to generate.