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/error.h>
11 #include <common/macros.h>
12 #include <lttng/action/action-internal.h>
13 #include <lttng/action/group-internal.h>
14 #include <lttng/action/group.h>
16 struct lttng_action_group
{
17 struct lttng_action parent
;
19 /* The array own the action elements */
20 struct lttng_dynamic_pointer_array actions
;
23 struct lttng_action_group_comm
{
24 uint32_t action_count
;
27 * Variable data: each element serialized sequentially.
32 static void destroy_lttng_action_group_element(void *ptr
)
34 struct lttng_action
*element
= (struct lttng_action
*) ptr
;
35 lttng_action_destroy(element
);
38 static struct lttng_action_group
*action_group_from_action(
39 const struct lttng_action
*action
)
43 return container_of(action
, struct lttng_action_group
, parent
);
46 static const struct lttng_action_group
*action_group_from_action_const(
47 const struct lttng_action
*action
)
51 return container_of(action
, struct lttng_action_group
, parent
);
54 static bool lttng_action_group_validate(struct lttng_action
*action
)
56 unsigned int i
, count
;
57 struct lttng_action_group
*action_group
;
60 assert(lttng_action_get_type(action
) == LTTNG_ACTION_TYPE_GROUP
);
62 action_group
= action_group_from_action(action
);
64 count
= lttng_dynamic_pointer_array_get_count(&action_group
->actions
);
66 for (i
= 0; i
< count
; i
++) {
67 struct lttng_action
*child
=
68 lttng_dynamic_pointer_array_get_pointer(
69 &action_group
->actions
, i
);
73 if (!lttng_action_validate(child
)) {
85 static bool lttng_action_group_is_equal(const struct lttng_action
*_a
, const struct lttng_action
*_b
)
87 bool is_equal
= false;
89 unsigned int a_count
, b_count
;
91 if (lttng_action_group_get_count(_a
, &a_count
) != LTTNG_ACTION_STATUS_OK
) {
94 if (lttng_action_group_get_count(_b
, &b_count
) != LTTNG_ACTION_STATUS_OK
) {
99 if (a_count
!= b_count
) {
103 for (i
= 0; i
< a_count
; i
++) {
104 const struct lttng_action
*child_a
=
105 lttng_action_group_get_at_index_const(_a
, i
);
106 const struct lttng_action
*child_b
=
107 lttng_action_group_get_at_index_const(_b
, i
);
112 if (!lttng_action_is_equal(child_a
, child_b
)) {
122 static int lttng_action_group_serialize(
123 struct lttng_action
*action
, struct lttng_dynamic_buffer
*buf
)
125 struct lttng_action_group
*action_group
;
126 struct lttng_action_group_comm comm
;
128 unsigned int i
, count
;
132 assert(lttng_action_get_type(action
) == LTTNG_ACTION_TYPE_GROUP
);
134 action_group
= action_group_from_action(action
);
136 DBG("Serializing action group");
138 count
= lttng_dynamic_pointer_array_get_count(&action_group
->actions
);
140 comm
.action_count
= count
;
142 ret
= lttng_dynamic_buffer_append(buf
, &comm
, sizeof(comm
));
148 for (i
= 0; i
< count
; i
++) {
149 struct lttng_action
*child
=
150 lttng_dynamic_pointer_array_get_pointer(
151 &action_group
->actions
, i
);
154 ret
= lttng_action_serialize(child
, buf
);
166 static void lttng_action_group_destroy(struct lttng_action
*action
)
168 struct lttng_action_group
*action_group
;
174 action_group
= action_group_from_action(action
);
176 lttng_dynamic_pointer_array_reset(&action_group
->actions
);
184 ssize_t
lttng_action_group_create_from_buffer(
185 const struct lttng_buffer_view
*view
,
186 struct lttng_action
**p_action
)
188 ssize_t consumed_len
;
189 struct lttng_action_group_comm
*comm
;
190 struct lttng_action
*group
;
191 struct lttng_action
*child_action
= NULL
;
192 enum lttng_action_status status
;
195 group
= lttng_action_group_create();
201 comm
= (struct lttng_action_group_comm
*) view
->data
;
203 consumed_len
= sizeof(struct lttng_action_group_comm
);
205 for (i
= 0; i
< comm
->action_count
; i
++) {
206 ssize_t consumed_len_child
;
207 struct lttng_buffer_view child_view
;
209 child_view
= lttng_buffer_view_from_view(
210 view
, consumed_len
, view
->size
- consumed_len
);
211 consumed_len_child
= lttng_action_create_from_buffer(
212 &child_view
, &child_action
);
214 status
= lttng_action_group_add_action(group
, child_action
);
215 if (status
!= LTTNG_ACTION_STATUS_OK
) {
221 consumed_len
+= consumed_len_child
;
228 lttng_action_group_destroy(group
);
229 lttng_action_destroy(child_action
);
234 struct lttng_action
*lttng_action_group_create(void)
236 struct lttng_action_group
*action_group
;
237 struct lttng_action
*action
;
239 action_group
= zmalloc(sizeof(struct lttng_action_group
));
245 action
= &action_group
->parent
;
247 lttng_action_init(action
, LTTNG_ACTION_TYPE_GROUP
,
248 lttng_action_group_validate
,
249 lttng_action_group_serialize
,
250 lttng_action_group_is_equal
,
251 lttng_action_group_destroy
);
253 lttng_dynamic_pointer_array_init(&action_group
->actions
,
254 destroy_lttng_action_group_element
);
260 enum lttng_action_status
lttng_action_group_add_action(
261 struct lttng_action
*group
, struct lttng_action
*action
)
263 struct lttng_action_group
*action_group
;
264 enum lttng_action_status status
;
268 (lttng_action_get_type(group
) !=
269 LTTNG_ACTION_TYPE_GROUP
) ||
271 status
= LTTNG_ACTION_STATUS_INVALID
;
276 * Don't allow adding groups in groups for now, since we're afraid of
279 if (lttng_action_get_type(action
) == LTTNG_ACTION_TYPE_GROUP
) {
280 status
= LTTNG_ACTION_STATUS_INVALID
;
284 action_group
= action_group_from_action(group
);
286 ret
= lttng_dynamic_pointer_array_add_pointer(&action_group
->actions
,
289 status
= LTTNG_ACTION_STATUS_ERROR
;
293 status
= LTTNG_ACTION_STATUS_OK
;
298 enum lttng_action_status
lttng_action_group_get_count(
299 const struct lttng_action
*group
, unsigned int *count
)
301 const struct lttng_action_group
*action_group
;
302 enum lttng_action_status status
= LTTNG_ACTION_STATUS_OK
;
304 if (!group
|| (lttng_action_get_type_const(group
) !=
305 LTTNG_ACTION_TYPE_GROUP
)) {
306 status
= LTTNG_ACTION_STATUS_INVALID
;
311 action_group
= action_group_from_action_const(group
);
313 *count
= lttng_dynamic_pointer_array_get_count(&action_group
->actions
);
318 const struct lttng_action
*lttng_action_group_get_at_index_const(
319 const struct lttng_action
*group
, unsigned int index
)
322 const struct lttng_action_group
*action_group
;
323 const struct lttng_action
* action
= NULL
;
325 if (lttng_action_group_get_count(group
, &count
) !=
326 LTTNG_ACTION_STATUS_OK
) {
330 if (index
>= count
) {
334 action_group
= action_group_from_action_const(group
);
335 action
= lttng_dynamic_pointer_array_get_pointer(&action_group
->actions
,