2 * Copyright (C) 2019 Simon Marchi <simon.marchi@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
9 #include <common/dynamic-array.h>
10 #include <common/payload.h>
11 #include <common/payload-view.h>
12 #include <common/error.h>
13 #include <common/macros.h>
14 #include <lttng/action/action-internal.h>
15 #include <lttng/action/group-internal.h>
16 #include <lttng/action/group.h>
18 #define IS_GROUP_ACTION(action) \
19 (lttng_action_get_type_const(action) == LTTNG_ACTION_TYPE_GROUP)
21 struct lttng_action_group
{
22 struct lttng_action parent
;
24 /* The array owns the action elements. */
25 struct lttng_dynamic_pointer_array actions
;
28 struct lttng_action_group_comm
{
29 uint32_t action_count
;
32 * Variable data: each element serialized sequentially.
37 static void destroy_lttng_action_group_element(void *ptr
)
39 struct lttng_action
*element
= (struct lttng_action
*) ptr
;
41 lttng_action_destroy(element
);
44 static struct lttng_action_group
*action_group_from_action(
45 const struct lttng_action
*action
)
49 return container_of(action
, struct lttng_action_group
, parent
);
52 static const struct lttng_action_group
*action_group_from_action_const(
53 const struct lttng_action
*action
)
57 return container_of(action
, struct lttng_action_group
, parent
);
60 static bool lttng_action_group_validate(struct lttng_action
*action
)
62 unsigned int i
, count
;
63 struct lttng_action_group
*action_group
;
66 assert(IS_GROUP_ACTION(action
));
68 action_group
= action_group_from_action(action
);
70 count
= lttng_dynamic_pointer_array_get_count(&action_group
->actions
);
72 for (i
= 0; i
< count
; i
++) {
73 struct lttng_action
*child
=
74 lttng_dynamic_pointer_array_get_pointer(
75 &action_group
->actions
, i
);
79 if (!lttng_action_validate(child
)) {
91 static bool lttng_action_group_is_equal(
92 const struct lttng_action
*_a
, const struct lttng_action
*_b
)
94 bool is_equal
= false;
96 unsigned int a_count
, b_count
;
98 if (lttng_action_group_get_count(_a
, &a_count
) !=
99 LTTNG_ACTION_STATUS_OK
) {
103 if (lttng_action_group_get_count(_b
, &b_count
) !=
104 LTTNG_ACTION_STATUS_OK
) {
108 if (a_count
!= b_count
) {
112 for (i
= 0; i
< a_count
; i
++) {
113 const struct lttng_action
*child_a
=
114 lttng_action_group_get_at_index(_a
, i
);
115 const struct lttng_action
*child_b
=
116 lttng_action_group_get_at_index(_b
, i
);
121 if (!lttng_action_is_equal(child_a
, child_b
)) {
131 static int lttng_action_group_serialize(
132 struct lttng_action
*action
, struct lttng_payload
*payload
)
134 struct lttng_action_group
*action_group
;
135 struct lttng_action_group_comm comm
;
137 unsigned int i
, count
;
141 assert(IS_GROUP_ACTION(action
));
143 action_group
= action_group_from_action(action
);
145 DBG("Serializing action group");
147 count
= lttng_dynamic_pointer_array_get_count(&action_group
->actions
);
149 comm
.action_count
= count
;
151 ret
= lttng_dynamic_buffer_append(
152 &payload
->buffer
, &comm
, sizeof(comm
));
158 for (i
= 0; i
< count
; i
++) {
159 struct lttng_action
*child
=
160 lttng_dynamic_pointer_array_get_pointer(
161 &action_group
->actions
, i
);
165 ret
= lttng_action_serialize(child
, payload
);
177 static void lttng_action_group_destroy(struct lttng_action
*action
)
179 struct lttng_action_group
*action_group
;
185 action_group
= action_group_from_action(action
);
186 lttng_dynamic_pointer_array_reset(&action_group
->actions
);
193 ssize_t
lttng_action_group_create_from_payload(
194 struct lttng_payload_view
*view
,
195 struct lttng_action
**p_action
)
197 ssize_t consumed_len
;
198 const struct lttng_action_group_comm
*comm
;
199 struct lttng_action
*group
;
200 struct lttng_action
*child_action
= NULL
;
201 enum lttng_action_status status
;
204 group
= lttng_action_group_create();
210 comm
= (typeof(comm
)) view
->buffer
.data
;
212 consumed_len
= sizeof(struct lttng_action_group_comm
);
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
);
220 consumed_len_child
= lttng_action_create_from_payload(
221 &child_view
, &child_action
);
222 if (consumed_len_child
< 0) {
227 status
= lttng_action_group_add_action(group
, child_action
);
228 if (status
!= LTTNG_ACTION_STATUS_OK
) {
233 /* Transfer ownership to the action group. */
234 lttng_action_put(child_action
);
237 consumed_len
+= consumed_len_child
;
244 lttng_action_group_destroy(group
);
248 struct lttng_action
*lttng_action_group_create(void)
250 struct lttng_action_group
*action_group
;
251 struct lttng_action
*action
;
253 action_group
= zmalloc(sizeof(struct lttng_action_group
));
259 action
= &action_group
->parent
;
261 lttng_action_init(action
, LTTNG_ACTION_TYPE_GROUP
,
262 lttng_action_group_validate
,
263 lttng_action_group_serialize
,
264 lttng_action_group_is_equal
,
265 lttng_action_group_destroy
);
267 lttng_dynamic_pointer_array_init(&action_group
->actions
,
268 destroy_lttng_action_group_element
);
274 enum lttng_action_status
lttng_action_group_add_action(
275 struct lttng_action
*group
, struct lttng_action
*action
)
277 struct lttng_action_group
*action_group
;
278 enum lttng_action_status status
;
281 if (!group
|| !IS_GROUP_ACTION(action
) || !action
) {
282 status
= LTTNG_ACTION_STATUS_INVALID
;
287 * Don't allow adding groups in groups for now, since we're afraid of
290 if (IS_GROUP_ACTION(action
)) {
291 status
= LTTNG_ACTION_STATUS_INVALID
;
295 action_group
= action_group_from_action(group
);
297 ret
= lttng_dynamic_pointer_array_add_pointer(&action_group
->actions
,
300 status
= LTTNG_ACTION_STATUS_ERROR
;
304 /* Take ownership of the object. */
305 lttng_action_get(action
);
306 status
= LTTNG_ACTION_STATUS_OK
;
311 enum lttng_action_status
lttng_action_group_get_count(
312 const struct lttng_action
*group
, unsigned int *count
)
314 const struct lttng_action_group
*action_group
;
315 enum lttng_action_status status
= LTTNG_ACTION_STATUS_OK
;
317 if (!group
|| !IS_GROUP_ACTION(group
)) {
318 status
= LTTNG_ACTION_STATUS_INVALID
;
323 action_group
= action_group_from_action_const(group
);
324 *count
= lttng_dynamic_pointer_array_get_count(&action_group
->actions
);
329 const struct lttng_action
*lttng_action_group_get_at_index(
330 const struct lttng_action
*group
, unsigned int index
)
333 const struct lttng_action_group
*action_group
;
334 const struct lttng_action
* action
= NULL
;
336 if (lttng_action_group_get_count(group
, &count
) !=
337 LTTNG_ACTION_STATUS_OK
) {
341 if (index
>= count
) {
345 action_group
= action_group_from_action_const(group
);
346 action
= lttng_dynamic_pointer_array_get_pointer(&action_group
->actions
,