Commit | Line | Data |
---|---|---|
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 | ||
25 | struct lttng_error_query { | |
26 | enum lttng_error_query_target_type target_type; | |
27 | }; | |
28 | ||
f1494934 JG |
29 | struct lttng_error_query_result { |
30 | enum lttng_error_query_result_type type; | |
31 | char *name; | |
32 | char *description; | |
33 | }; | |
34 | ||
35 | struct lttng_error_query_results { | |
36 | struct lttng_dynamic_pointer_array results; | |
37 | }; | |
38 | ||
39 | namespace { | |
b99a0cb3 JG |
40 | struct 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 | ||
47 | struct 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 |
53 | struct 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 |
59 | struct 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 |
66 | struct 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 | ||
77 | struct lttng_error_query_result_counter_comm { | |
78 | uint64_t value; | |
79 | } LTTNG_PACKED; | |
80 | ||
81 | struct lttng_error_query_result_counter { | |
82 | struct lttng_error_query_result parent; | |
83 | uint64_t value; | |
84 | }; | |
85 | ||
86 | struct 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 |
93 | static enum lttng_error_code |
94 | lttng_error_query_result_mi_serialize(const struct lttng_error_query_result *result, | |
95 | struct mi_writer *writer); | |
6a751b95 | 96 | |
28ab034a JG |
97 | static enum lttng_error_code |
98 | lttng_error_query_result_counter_mi_serialize(const struct lttng_error_query_result *result, | |
99 | struct mi_writer *writer); | |
b99a0cb3 | 100 | |
28ab034a | 101 | struct 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 | |
125 | error: | |
126 | lttng_trigger_put(trigger_copy); | |
b99a0cb3 | 127 | end: |
cd9adb8b | 128 | return query ? &query->parent : nullptr; |
b99a0cb3 JG |
129 | } |
130 | ||
28ab034a | 131 | struct 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 | |
155 | error: | |
156 | lttng_trigger_put(trigger_copy); | |
157 | end: | |
cd9adb8b | 158 | return query ? &query->parent : nullptr; |
63dd3d7b JG |
159 | } |
160 | ||
28ab034a JG |
161 | static struct lttng_action * |
162 | get_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 |
187 | end: |
188 | return current_action; | |
189 | } | |
190 | ||
28ab034a JG |
191 | static 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 |
201 | struct lttng_error_query * |
202 | lttng_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 |
234 | error: |
235 | lttng_trigger_put(trigger_copy); | |
cd9adb8b | 236 | lttng_error_query_destroy(query ? &query->parent : nullptr); |
b99a0cb3 | 237 | end: |
cd9adb8b | 238 | return query ? &query->parent : nullptr; |
b99a0cb3 JG |
239 | } |
240 | ||
241 | void 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, <tng_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, <tng_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, <tng_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 |
281 | static 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, <tng_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 |
298 | int 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 | ||
343 | end: | |
344 | return ret; | |
345 | } | |
346 | ||
28ab034a JG |
347 | static 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; | |
374 | end: | |
375 | return ret; | |
376 | } | |
377 | ||
b99a0cb3 JG |
378 | void 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 | 397 | struct lttng_error_query_result * |
28ab034a | 398 | lttng_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; |
417 | error: | |
418 | lttng_error_query_result_destroy(&counter->parent); | |
419 | end: | |
cd9adb8b | 420 | return counter ? &counter->parent : nullptr; |
b99a0cb3 JG |
421 | } |
422 | ||
28ab034a | 423 | static 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 | 430 | struct 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); | |
440 | end: | |
441 | return set; | |
442 | } | |
443 | ||
28ab034a JG |
444 | int 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 |
450 | ssize_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 | ||
527 | end: | |
528 | return used_size; | |
529 | } | |
530 | ||
28ab034a JG |
531 | int 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 | } | |
560 | end: | |
561 | return ret; | |
562 | } | |
563 | ||
28ab034a JG |
564 | ssize_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 |
616 | end: |
617 | lttng_error_query_results_destroy(results); | |
618 | return total_used_size; | |
619 | } | |
620 | ||
28ab034a JG |
621 | static 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, <tng_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 | ||
638 | end: | |
639 | return ret; | |
640 | } | |
641 | ||
28ab034a JG |
642 | static 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, <tng_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 | ||
659 | end: | |
660 | return ret; | |
661 | } | |
662 | ||
28ab034a JG |
663 | static 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, <tng_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 |
685 | end: |
686 | return ret; | |
687 | } | |
688 | ||
28ab034a JG |
689 | enum lttng_error_query_target_type |
690 | lttng_error_query_get_target_type(const struct lttng_error_query *query) | |
b99a0cb3 JG |
691 | { |
692 | return query->target_type; | |
693 | } | |
694 | ||
28ab034a JG |
695 | const struct lttng_trigger * |
696 | lttng_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, <tng_error_query_trigger::parent); |
b99a0cb3 JG |
700 | |
701 | return query_trigger->trigger; | |
702 | } | |
703 | ||
28ab034a JG |
704 | const struct lttng_trigger * |
705 | lttng_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, <tng_error_query_condition::parent); |
63dd3d7b JG |
709 | |
710 | return query_trigger->trigger; | |
711 | } | |
712 | ||
28ab034a JG |
713 | const struct lttng_trigger * |
714 | lttng_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, <tng_error_query_action::parent); |
b99a0cb3 JG |
718 | |
719 | return query_action->trigger; | |
720 | } | |
721 | ||
28ab034a JG |
722 | struct lttng_action * |
723 | lttng_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, <tng_error_query_action::parent); |
b99a0cb3 | 728 | |
28ab034a | 729 | return get_trigger_action_from_path(trigger, query_action->action_path); |
b99a0cb3 JG |
730 | } |
731 | ||
b99a0cb3 | 732 | int 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 | } | |
771 | end: | |
772 | return ret; | |
773 | } | |
774 | ||
b99a0cb3 | 775 | ssize_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 | ||
906 | end: | |
9de6375f | 907 | lttng_trigger_put(trigger); |
b99a0cb3 JG |
908 | return used_size; |
909 | } | |
910 | ||
28ab034a JG |
911 | enum lttng_error_query_results_status |
912 | lttng_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; | |
924 | end: | |
925 | return status; | |
926 | } | |
927 | ||
928 | enum lttng_error_query_results_status | |
28ab034a JG |
929 | lttng_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; |
955 | end: | |
956 | return status; | |
957 | } | |
958 | ||
28ab034a | 959 | void 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 | ||
969 | enum lttng_error_query_result_type | |
970 | lttng_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 |
975 | enum lttng_error_query_result_status |
976 | lttng_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; | |
987 | end: | |
988 | return status; | |
989 | } | |
990 | ||
28ab034a JG |
991 | enum lttng_error_query_result_status |
992 | lttng_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; | |
1004 | end: | |
1005 | return status; | |
1006 | } | |
1007 | ||
28ab034a JG |
1008 | enum lttng_error_query_result_status |
1009 | lttng_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, <tng_error_query_result_counter::parent); | |
b99a0cb3 JG |
1022 | |
1023 | *value = counter_result->value; | |
1024 | status = LTTNG_ERROR_QUERY_RESULT_STATUS_OK; | |
1025 | end: | |
1026 | return status; | |
1027 | } | |
6a751b95 | 1028 | |
28ab034a JG |
1029 | static enum lttng_error_code |
1030 | lttng_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 | ||
1066 | mi_error: | |
1067 | ret_code = LTTNG_ERR_MI_IO_FAIL; | |
1068 | end: | |
1069 | return ret_code; | |
1070 | } | |
1071 | ||
28ab034a JG |
1072 | static enum lttng_error_code |
1073 | lttng_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 | ||
1136 | mi_error: | |
1137 | ret_code = LTTNG_ERR_MI_IO_FAIL; | |
1138 | end: | |
1139 | return ret_code; | |
1140 | } | |
1141 | ||
28ab034a JG |
1142 | enum lttng_error_code |
1143 | lttng_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 | ||
1185 | mi_error: | |
1186 | ret_code = LTTNG_ERR_MI_IO_FAIL; | |
1187 | end: | |
1188 | return ret_code; | |
1189 | } |