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