2 * Copyright (C) 2019 EfficiOS, Inc.
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <common/error.h>
20 #include <common/macros.h>
21 #include <lttng/action/action-internal.h>
22 #include <lttng/action/group-internal.h>
23 #include <lttng/action/group.h>
25 struct lttng_action_group
{
26 struct lttng_action parent
;
29 struct lttng_action
**elements
;
31 size_t n_elements_allocated
;
34 struct lttng_action_group_comm
{
38 * Variable data: each element serialized sequentially.
43 static struct lttng_action_group
*action_group_from_action(
44 const struct lttng_action
*action
)
48 return container_of(action
, struct lttng_action_group
, parent
);
51 static bool lttng_action_group_validate(struct lttng_action
*action
)
54 struct lttng_action_group
*action_group
;
57 assert(lttng_action_get_type(action
) == LTTNG_ACTION_TYPE_GROUP
);
59 action_group
= action_group_from_action(action
);
61 for (i
= 0; i
< action_group
->n_elements
; i
++) {
62 struct lttng_action
*child
= action_group
->elements
[i
];
66 if (!lttng_action_validate(child
)) {
78 static bool lttng_action_group_is_equal(const struct lttng_action
*_a
, const struct lttng_action
*_b
)
80 bool is_equal
= false;
81 struct lttng_action_group
*a
, *b
;
84 assert(lttng_action_get_type_const(_a
) == LTTNG_ACTION_TYPE_GROUP
);
85 assert(lttng_action_get_type_const(_b
) == LTTNG_ACTION_TYPE_GROUP
);
87 a
= action_group_from_action(_a
);
88 b
= action_group_from_action(_b
);
90 if (a
->n_elements
!= b
->n_elements
) {
94 for (i
= 0; i
< a
->n_elements
; i
++) {
95 struct lttng_action
*child_a
= a
->elements
[i
];
96 struct lttng_action
*child_b
= b
->elements
[i
];
101 if (!lttng_action_is_equal(child_a
, child_b
)) {
111 static int lttng_action_group_serialize(
112 struct lttng_action
*action
, struct lttng_dynamic_buffer
*buf
)
114 struct lttng_action_group
*action_group
;
115 struct lttng_action_group_comm comm
;
121 assert(lttng_action_get_type(action
) == LTTNG_ACTION_TYPE_GROUP
);
123 action_group
= action_group_from_action(action
);
125 DBG("Serializing action group");
127 comm
.n_elements
= action_group
->n_elements
;
129 ret
= lttng_dynamic_buffer_append(buf
, &comm
, sizeof(comm
));
135 for (i
= 0; i
< action_group
->n_elements
; i
++) {
136 struct lttng_action
*child
= action_group
->elements
[i
];
140 ret
= lttng_action_serialize(child
, buf
);
152 static void lttng_action_group_destroy(struct lttng_action
*action
)
154 struct lttng_action_group
*action_group
;
161 action_group
= action_group_from_action(action
);
163 for (i
= 0; i
< action_group
->n_elements
; i
++) {
164 struct lttng_action
*child
= action_group
->elements
[i
];
168 lttng_action_destroy(child
);
171 free(action_group
->elements
);
178 ssize_t
lttng_action_group_create_from_buffer(
179 const struct lttng_buffer_view
*view
,
180 struct lttng_action
**p_action
)
182 ssize_t consumed_len
;
183 struct lttng_action_group_comm
*comm
;
184 struct lttng_action
*group
;
185 struct lttng_action
*child_action
= NULL
;
186 enum lttng_action_status status
;
189 group
= lttng_action_group_create();
195 comm
= (struct lttng_action_group_comm
*) view
->data
;
197 consumed_len
= sizeof(struct lttng_action_group_comm
);
199 for (i
= 0; i
< comm
->n_elements
; i
++) {
200 ssize_t consumed_len_child
;
201 struct lttng_buffer_view child_view
;
203 child_view
= lttng_buffer_view_from_view(
204 view
, consumed_len
, view
->size
- consumed_len
);
205 consumed_len_child
= lttng_action_create_from_buffer(
206 &child_view
, &child_action
);
208 status
= lttng_action_group_add_action(group
, child_action
);
209 if (status
!= LTTNG_ACTION_STATUS_OK
) {
215 consumed_len
+= consumed_len_child
;
222 lttng_action_group_destroy(group
);
223 lttng_action_destroy(child_action
);
228 struct lttng_action
*lttng_action_group_create(void)
230 struct lttng_action_group
*action_group
;
231 struct lttng_action
*action
;
233 action_group
= zmalloc(sizeof(struct lttng_action_group
));
239 action
= &action_group
->parent
;
241 lttng_action_init(action
, LTTNG_ACTION_TYPE_GROUP
,
242 lttng_action_group_validate
,
243 lttng_action_group_serialize
,
244 lttng_action_group_is_equal
,
245 lttng_action_group_destroy
);
247 action_group
->n_elements
= 0;
248 action_group
->n_elements_allocated
= 10;
249 action_group
->elements
= zmalloc(10 * sizeof(struct lttng_action
*));
250 if (!action_group
->elements
) {
257 lttng_action_group_destroy(action
);
264 enum lttng_action_status
lttng_action_group_add_action(
265 struct lttng_action
*group
, struct lttng_action
*action
)
267 struct lttng_action_group
*action_group
;
268 enum lttng_action_status status
;
271 (lttng_action_get_type(group
) !=
272 LTTNG_ACTION_TYPE_GROUP
) ||
274 status
= LTTNG_ACTION_STATUS_INVALID
;
279 * Don't allow adding groups in groups for now, since we're afraid of
282 if (lttng_action_get_type(action
) == LTTNG_ACTION_TYPE_GROUP
) {
283 status
= LTTNG_ACTION_STATUS_INVALID
;
287 action_group
= action_group_from_action(group
);
289 if (action_group
->n_elements
== action_group
->n_elements_allocated
) {
290 // TODO: handle resize.
291 status
= LTTNG_ACTION_STATUS_ERROR
;
295 action_group
->elements
[action_group
->n_elements
] = action
;
296 action_group
->n_elements
++;
298 status
= LTTNG_ACTION_STATUS_OK
;
303 enum lttng_action_status
lttng_action_group_get_count(
304 const struct lttng_action
*group
, unsigned int *count
)
306 struct lttng_action_group
*action_group
;
307 enum lttng_action_status status
= LTTNG_ACTION_STATUS_OK
;
309 if (!group
|| (lttng_action_get_type_const(group
) !=
310 LTTNG_ACTION_TYPE_GROUP
)) {
311 status
= LTTNG_ACTION_STATUS_INVALID
;
316 action_group
= action_group_from_action(group
);
319 *count
= action_group
->n_elements
;
324 const struct lttng_action
*lttng_action_group_get_at_index_const(
325 const struct lttng_action
*group
,
328 struct lttng_action_group
*action_group
;
329 const struct lttng_action
*action
= NULL
;
331 if (!group
|| (lttng_action_get_type_const(group
) !=
332 LTTNG_ACTION_TYPE_GROUP
)) {
336 action_group
= action_group_from_action(group
);
338 if (index
>= action_group
->n_elements
) {
342 action
= action_group
->elements
[index
];