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