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