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