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