Rename group action files to list files
[lttng-tools.git] / src / common / actions / list.c
CommitLineData
0c51e8f3
SM
1/*
2 * Copyright (C) 2019 Simon Marchi <simon.marchi@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8#include <assert.h>
9#include <common/dynamic-array.h>
9e620ea7
JG
10#include <common/payload.h>
11#include <common/payload-view.h>
0c51e8f3
SM
12#include <common/error.h>
13#include <common/macros.h>
14#include <lttng/action/action-internal.h>
ad63a966
JR
15#include <lttng/action/list-internal.h>
16#include <lttng/action/list.h>
0c51e8f3
SM
17
18#define IS_GROUP_ACTION(action) \
17182cfd 19 (lttng_action_get_type(action) == LTTNG_ACTION_TYPE_GROUP)
0c51e8f3 20
702f26c8 21struct lttng_action_list {
0c51e8f3
SM
22 struct lttng_action parent;
23
24 /* The array owns the action elements. */
25 struct lttng_dynamic_pointer_array actions;
26};
27
702f26c8 28struct lttng_action_list_comm {
0c51e8f3
SM
29 uint32_t action_count;
30
31 /*
32 * Variable data: each element serialized sequentially.
33 */
34 char data[];
35} LTTNG_PACKED;
36
702f26c8 37static void destroy_lttng_action_list_element(void *ptr)
0c51e8f3
SM
38{
39 struct lttng_action *element = (struct lttng_action *) ptr;
40
41 lttng_action_destroy(element);
42}
43
702f26c8 44static struct lttng_action_list *action_list_from_action(
0c51e8f3
SM
45 const struct lttng_action *action)
46{
47 assert(action);
48
702f26c8 49 return container_of(action, struct lttng_action_list, parent);
0c51e8f3
SM
50}
51
702f26c8 52static const struct lttng_action_list *action_list_from_action_const(
0c51e8f3
SM
53 const struct lttng_action *action)
54{
55 assert(action);
56
702f26c8 57 return container_of(action, struct lttng_action_list, parent);
0c51e8f3
SM
58}
59
702f26c8 60static bool lttng_action_list_validate(struct lttng_action *action)
0c51e8f3
SM
61{
62 unsigned int i, count;
702f26c8 63 struct lttng_action_list *action_list;
0c51e8f3
SM
64 bool valid;
65
66 assert(IS_GROUP_ACTION(action));
67
702f26c8 68 action_list = action_list_from_action(action);
0c51e8f3 69
702f26c8 70 count = lttng_dynamic_pointer_array_get_count(&action_list->actions);
0c51e8f3
SM
71
72 for (i = 0; i < count; i++) {
73 struct lttng_action *child =
74 lttng_dynamic_pointer_array_get_pointer(
702f26c8 75 &action_list->actions, i);
0c51e8f3
SM
76
77 assert(child);
78
79 if (!lttng_action_validate(child)) {
80 valid = false;
81 goto end;
82 }
83 }
84
85 valid = true;
86
87end:
88 return valid;
89}
90
702f26c8 91static bool lttng_action_list_is_equal(
0c51e8f3
SM
92 const struct lttng_action *_a, const struct lttng_action *_b)
93{
94 bool is_equal = false;
95 unsigned int i;
96 unsigned int a_count, b_count;
97
702f26c8 98 if (lttng_action_list_get_count(_a, &a_count) !=
0c51e8f3
SM
99 LTTNG_ACTION_STATUS_OK) {
100 goto end;
101 }
102
702f26c8 103 if (lttng_action_list_get_count(_b, &b_count) !=
0c51e8f3
SM
104 LTTNG_ACTION_STATUS_OK) {
105 goto end;
106 }
107
108 if (a_count != b_count) {
109 goto end;
110 }
111
112 for (i = 0; i < a_count; i++) {
113 const struct lttng_action *child_a =
702f26c8 114 lttng_action_list_get_at_index(_a, i);
0c51e8f3 115 const struct lttng_action *child_b =
702f26c8 116 lttng_action_list_get_at_index(_b, i);
0c51e8f3
SM
117
118 assert(child_a);
119 assert(child_b);
120
121 if (!lttng_action_is_equal(child_a, child_b)) {
122 goto end;
123 }
124 }
125
126 is_equal = true;
127end:
128 return is_equal;
129}
130
702f26c8 131static int lttng_action_list_serialize(
0c51e8f3
SM
132 struct lttng_action *action, struct lttng_payload *payload)
133{
702f26c8
JR
134 struct lttng_action_list *action_list;
135 struct lttng_action_list_comm comm;
0c51e8f3
SM
136 int ret;
137 unsigned int i, count;
138
139 assert(action);
140 assert(payload);
141 assert(IS_GROUP_ACTION(action));
142
702f26c8 143 action_list = action_list_from_action(action);
0c51e8f3 144
702f26c8 145 DBG("Serializing action list");
0c51e8f3 146
702f26c8 147 count = lttng_dynamic_pointer_array_get_count(&action_list->actions);
0c51e8f3
SM
148
149 comm.action_count = count;
150
151 ret = lttng_dynamic_buffer_append(
152 &payload->buffer, &comm, sizeof(comm));
153 if (ret) {
154 ret = -1;
155 goto end;
156 }
157
158 for (i = 0; i < count; i++) {
159 struct lttng_action *child =
160 lttng_dynamic_pointer_array_get_pointer(
702f26c8 161 &action_list->actions, i);
0c51e8f3
SM
162
163 assert(child);
164
165 ret = lttng_action_serialize(child, payload);
166 if (ret) {
167 goto end;
168 }
169 }
170
171 ret = 0;
172
173end:
174 return ret;
175}
176
702f26c8 177static void lttng_action_list_destroy(struct lttng_action *action)
0c51e8f3 178{
702f26c8 179 struct lttng_action_list *action_list;
0c51e8f3
SM
180
181 if (!action) {
182 goto end;
183 }
184
702f26c8
JR
185 action_list = action_list_from_action(action);
186 lttng_dynamic_pointer_array_reset(&action_list->actions);
187 free(action_list);
0c51e8f3
SM
188
189end:
190 return;
191}
192
702f26c8 193ssize_t lttng_action_list_create_from_payload(
0c51e8f3
SM
194 struct lttng_payload_view *view,
195 struct lttng_action **p_action)
196{
197 ssize_t consumed_len;
702f26c8 198 const struct lttng_action_list_comm *comm;
0c51e8f3
SM
199 struct lttng_action *group;
200 struct lttng_action *child_action = NULL;
201 enum lttng_action_status status;
202 size_t i;
203
702f26c8 204 group = lttng_action_list_create();
0c51e8f3
SM
205 if (!group) {
206 consumed_len = -1;
207 goto end;
208 }
209
210 comm = (typeof(comm)) view->buffer.data;
211
702f26c8 212 consumed_len = sizeof(struct lttng_action_list_comm);
0c51e8f3
SM
213
214 for (i = 0; i < comm->action_count; i++) {
215 ssize_t consumed_len_child;
216 struct lttng_payload_view child_view =
217 lttng_payload_view_from_view(view, consumed_len,
218 view->buffer.size - consumed_len);
219
3e6e0df2
JG
220 if (!lttng_payload_view_is_valid(&child_view)) {
221 consumed_len = -1;
222 goto end;
223 }
224
0c51e8f3
SM
225 consumed_len_child = lttng_action_create_from_payload(
226 &child_view, &child_action);
227 if (consumed_len_child < 0) {
228 consumed_len = -1;
229 goto end;
230 }
231
702f26c8 232 status = lttng_action_list_add_action(group, child_action);
0c51e8f3
SM
233 if (status != LTTNG_ACTION_STATUS_OK) {
234 consumed_len = -1;
235 goto end;
236 }
237
702f26c8 238 /* Transfer ownership to the action list. */
0c51e8f3
SM
239 lttng_action_put(child_action);
240 child_action = NULL;
241
242 consumed_len += consumed_len_child;
243 }
244
245 *p_action = group;
246 group = NULL;
247
248end:
702f26c8 249 lttng_action_list_destroy(group);
0c51e8f3
SM
250 return consumed_len;
251}
252
702f26c8 253static enum lttng_action_status lttng_action_list_add_error_query_results(
588c4b0d
JG
254 const struct lttng_action *action,
255 struct lttng_error_query_results *results)
256{
257 unsigned int i, count;
258 enum lttng_action_status action_status;
702f26c8 259 const struct lttng_action_list *group =
588c4b0d
JG
260 container_of(action, typeof(*group), parent);
261
702f26c8 262 action_status = lttng_action_list_get_count(action, &count);
588c4b0d
JG
263 if (action_status != LTTNG_ACTION_STATUS_OK) {
264 goto end;
265 }
266
267 for (i = 0; i < count; i++) {
268 struct lttng_action *inner_action =
702f26c8 269 lttng_action_list_borrow_mutable_at_index(action, i);
588c4b0d
JG
270
271 action_status = lttng_action_add_error_query_results(
272 inner_action, results);
273 if (action_status != LTTNG_ACTION_STATUS_OK) {
274 goto end;
275 }
276 }
277end:
278 return action_status;
279}
280
702f26c8 281struct lttng_action *lttng_action_list_create(void)
0c51e8f3 282{
702f26c8 283 struct lttng_action_list *action_list;
0c51e8f3
SM
284 struct lttng_action *action;
285
702f26c8
JR
286 action_list = zmalloc(sizeof(struct lttng_action_list));
287 if (!action_list) {
0c51e8f3
SM
288 action = NULL;
289 goto end;
290 }
291
702f26c8 292 action = &action_list->parent;
0c51e8f3
SM
293
294 lttng_action_init(action, LTTNG_ACTION_TYPE_GROUP,
702f26c8
JR
295 lttng_action_list_validate,
296 lttng_action_list_serialize,
297 lttng_action_list_is_equal, lttng_action_list_destroy,
588c4b0d 298 NULL,
702f26c8 299 lttng_action_list_add_error_query_results);
0c51e8f3 300
702f26c8
JR
301 lttng_dynamic_pointer_array_init(&action_list->actions,
302 destroy_lttng_action_list_element);
0c51e8f3
SM
303
304end:
305 return action;
306}
307
702f26c8 308enum lttng_action_status lttng_action_list_add_action(
0c51e8f3
SM
309 struct lttng_action *group, struct lttng_action *action)
310{
702f26c8 311 struct lttng_action_list *action_list;
0c51e8f3
SM
312 enum lttng_action_status status;
313 int ret;
314
f3a9cc34 315 if (!group || !IS_GROUP_ACTION(group) || !action) {
0c51e8f3
SM
316 status = LTTNG_ACTION_STATUS_INVALID;
317 goto end;
318 }
319
320 /*
321 * Don't allow adding groups in groups for now, since we're afraid of
322 * cycles.
323 */
324 if (IS_GROUP_ACTION(action)) {
325 status = LTTNG_ACTION_STATUS_INVALID;
326 goto end;
327 }
328
702f26c8 329 action_list = action_list_from_action(group);
0c51e8f3 330
702f26c8 331 ret = lttng_dynamic_pointer_array_add_pointer(&action_list->actions,
0c51e8f3
SM
332 action);
333 if (ret < 0) {
334 status = LTTNG_ACTION_STATUS_ERROR;
335 goto end;
336 }
337
338 /* Take ownership of the object. */
339 lttng_action_get(action);
340 status = LTTNG_ACTION_STATUS_OK;
341end:
342 return status;
343}
344
702f26c8 345enum lttng_action_status lttng_action_list_get_count(
0c51e8f3
SM
346 const struct lttng_action *group, unsigned int *count)
347{
702f26c8 348 const struct lttng_action_list *action_list;
0c51e8f3
SM
349 enum lttng_action_status status = LTTNG_ACTION_STATUS_OK;
350
351 if (!group || !IS_GROUP_ACTION(group)) {
352 status = LTTNG_ACTION_STATUS_INVALID;
353 *count = 0;
354 goto end;
355 }
356
702f26c8
JR
357 action_list = action_list_from_action_const(group);
358 *count = lttng_dynamic_pointer_array_get_count(&action_list->actions);
0c51e8f3
SM
359end:
360 return status;
361}
362
702f26c8 363const struct lttng_action *lttng_action_list_get_at_index(
0c51e8f3 364 const struct lttng_action *group, unsigned int index)
2d57482c 365{
702f26c8 366 return lttng_action_list_borrow_mutable_at_index(group, index);
2d57482c
JR
367}
368
369LTTNG_HIDDEN
702f26c8 370struct lttng_action *lttng_action_list_borrow_mutable_at_index(
2d57482c 371 const struct lttng_action *group, unsigned int index)
0c51e8f3
SM
372{
373 unsigned int count;
702f26c8 374 const struct lttng_action_list *action_list;
2d57482c 375 struct lttng_action *action = NULL;
0c51e8f3 376
702f26c8 377 if (lttng_action_list_get_count(group, &count) !=
0c51e8f3
SM
378 LTTNG_ACTION_STATUS_OK) {
379 goto end;
380 }
381
382 if (index >= count) {
383 goto end;
384 }
385
702f26c8
JR
386 action_list = action_list_from_action_const(group);
387 action = lttng_dynamic_pointer_array_get_pointer(&action_list->actions,
0c51e8f3
SM
388 index);
389end:
390 return action;
391}
This page took 0.076181 seconds and 4 git commands to generate.