SoW-2019-0007-2: Dynamic Snapshot: Triggers send partial event payload with notifications
[lttng-tools.git] / src / common / actions / group.c
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>
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>
15
16 struct lttng_action_group {
17 struct lttng_action parent;
18
19 /* The array own the action elements */
20 struct lttng_dynamic_pointer_array actions;
21 };
22
23 struct lttng_action_group_comm {
24 uint32_t action_count;
25
26 /*
27 * Variable data: each element serialized sequentially.
28 */
29 char data[];
30 } LTTNG_PACKED;
31
32 static void destroy_lttng_action_group_element(void *ptr)
33 {
34 struct lttng_action *element = (struct lttng_action *) ptr;
35 lttng_action_destroy(element);
36 }
37
38 static struct lttng_action_group *action_group_from_action(
39 const struct lttng_action *action)
40 {
41 assert(action);
42
43 return container_of(action, struct lttng_action_group, parent);
44 }
45
46 static const struct lttng_action_group *action_group_from_action_const(
47 const struct lttng_action *action)
48 {
49 assert(action);
50
51 return container_of(action, struct lttng_action_group, parent);
52 }
53
54 static bool lttng_action_group_validate(struct lttng_action *action)
55 {
56 unsigned int i, count;
57 struct lttng_action_group *action_group;
58 bool valid;
59
60 assert(lttng_action_get_type(action) == LTTNG_ACTION_TYPE_GROUP);
61
62 action_group = action_group_from_action(action);
63
64 count = lttng_dynamic_pointer_array_get_count(&action_group->actions);
65
66 for (i = 0; i < count; i++) {
67 struct lttng_action *child =
68 lttng_dynamic_pointer_array_get_pointer(
69 &action_group->actions, i);
70
71 assert(child);
72
73 if (!lttng_action_validate(child)) {
74 valid = false;
75 goto end;
76 }
77 }
78
79 valid = true;
80
81 end:
82 return valid;
83 }
84
85 static bool lttng_action_group_is_equal(const struct lttng_action *_a, const struct lttng_action *_b)
86 {
87 bool is_equal = false;
88 unsigned int i;
89 unsigned int a_count, b_count;
90
91 if (lttng_action_group_get_count(_a, &a_count) != LTTNG_ACTION_STATUS_OK) {
92 goto end;
93 }
94 if (lttng_action_group_get_count(_b, &b_count) != LTTNG_ACTION_STATUS_OK) {
95 goto end;
96 }
97
98
99 if (a_count != b_count) {
100 goto end;
101 }
102
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);
108
109 assert(child_a);
110 assert(child_b);
111
112 if (!lttng_action_is_equal(child_a, child_b)) {
113 goto end;
114 }
115 }
116
117 is_equal = true;
118 end:
119 return is_equal;
120 }
121
122 static int lttng_action_group_serialize(
123 struct lttng_action *action, struct lttng_dynamic_buffer *buf)
124 {
125 struct lttng_action_group *action_group;
126 struct lttng_action_group_comm comm;
127 int ret;
128 unsigned int i, count;
129
130 assert(action);
131 assert(buf);
132 assert(lttng_action_get_type(action) == LTTNG_ACTION_TYPE_GROUP);
133
134 action_group = action_group_from_action(action);
135
136 DBG("Serializing action group");
137
138 count = lttng_dynamic_pointer_array_get_count(&action_group->actions);
139
140 comm.action_count = count;
141
142 ret = lttng_dynamic_buffer_append(buf, &comm, sizeof(comm));
143 if (ret) {
144 ret = -1;
145 goto end;
146 }
147
148 for (i = 0; i < count; i++) {
149 struct lttng_action *child =
150 lttng_dynamic_pointer_array_get_pointer(
151 &action_group->actions, i);
152 assert(child);
153
154 ret = lttng_action_serialize(child, buf);
155 if (ret) {
156 goto end;
157 }
158 }
159
160 ret = 0;
161
162 end:
163 return ret;
164 }
165
166 static void lttng_action_group_destroy(struct lttng_action *action)
167 {
168 struct lttng_action_group *action_group;
169
170 if (!action) {
171 goto end;
172 }
173
174 action_group = action_group_from_action(action);
175
176 lttng_dynamic_pointer_array_reset(&action_group->actions);
177
178 free(action_group);
179
180 end:
181 return;
182 }
183
184 ssize_t lttng_action_group_create_from_buffer(
185 const struct lttng_buffer_view *view,
186 struct lttng_action **p_action)
187 {
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;
193 size_t i;
194
195 group = lttng_action_group_create();
196 if (!group) {
197 consumed_len = -1;
198 goto end;
199 }
200
201 comm = (struct lttng_action_group_comm *) view->data;
202
203 consumed_len = sizeof(struct lttng_action_group_comm);
204
205 for (i = 0; i < comm->action_count; i++) {
206 ssize_t consumed_len_child;
207 struct lttng_buffer_view child_view;
208
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);
213
214 status = lttng_action_group_add_action(group, child_action);
215 if (status != LTTNG_ACTION_STATUS_OK) {
216 consumed_len = -1;
217 goto end;
218 }
219 child_action = NULL;
220
221 consumed_len += consumed_len_child;
222 }
223
224 *p_action = group;
225 group = NULL;
226
227 end:
228 lttng_action_group_destroy(group);
229 lttng_action_destroy(child_action);
230
231 return consumed_len;
232 }
233
234 struct lttng_action *lttng_action_group_create(void)
235 {
236 struct lttng_action_group *action_group;
237 struct lttng_action *action;
238
239 action_group = zmalloc(sizeof(struct lttng_action_group));
240 if (!action_group) {
241 action = NULL;
242 goto end;
243 }
244
245 action = &action_group->parent;
246
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);
252
253 lttng_dynamic_pointer_array_init(&action_group->actions,
254 destroy_lttng_action_group_element);
255
256 end:
257 return action;
258 }
259
260 enum lttng_action_status lttng_action_group_add_action(
261 struct lttng_action *group, struct lttng_action *action)
262 {
263 struct lttng_action_group *action_group;
264 enum lttng_action_status status;
265 int ret;
266
267 if (!group ||
268 (lttng_action_get_type(group) !=
269 LTTNG_ACTION_TYPE_GROUP) ||
270 !action) {
271 status = LTTNG_ACTION_STATUS_INVALID;
272 goto end;
273 }
274
275 /*
276 * Don't allow adding groups in groups for now, since we're afraid of
277 * cycles.
278 */
279 if (lttng_action_get_type(action) == LTTNG_ACTION_TYPE_GROUP) {
280 status = LTTNG_ACTION_STATUS_INVALID;
281 goto end;
282 }
283
284 action_group = action_group_from_action(group);
285
286 ret = lttng_dynamic_pointer_array_add_pointer(&action_group->actions,
287 action);
288 if (ret < 0) {
289 status = LTTNG_ACTION_STATUS_ERROR;
290 goto end;
291 }
292
293 status = LTTNG_ACTION_STATUS_OK;
294 end:
295 return status;
296 }
297
298 enum lttng_action_status lttng_action_group_get_count(
299 const struct lttng_action *group, unsigned int *count)
300 {
301 const struct lttng_action_group *action_group;
302 enum lttng_action_status status = LTTNG_ACTION_STATUS_OK;
303
304 if (!group || (lttng_action_get_type_const(group) !=
305 LTTNG_ACTION_TYPE_GROUP)) {
306 status = LTTNG_ACTION_STATUS_INVALID;
307 *count = 0;
308 goto end;
309 }
310
311 action_group = action_group_from_action_const(group);
312
313 *count = lttng_dynamic_pointer_array_get_count(&action_group->actions);
314 end:
315 return status;
316 }
317
318 const struct lttng_action *lttng_action_group_get_at_index_const(
319 const struct lttng_action *group, unsigned int index)
320 {
321 unsigned int count;
322 const struct lttng_action_group *action_group;
323 const struct lttng_action * action = NULL;
324
325 if (lttng_action_group_get_count(group, &count) !=
326 LTTNG_ACTION_STATUS_OK) {
327 goto end;
328 }
329
330 if (index >= count) {
331 goto end;
332 }
333
334 action_group = action_group_from_action_const(group);
335 action = lttng_dynamic_pointer_array_get_pointer(&action_group->actions,
336 index);
337 end:
338 return action;
339 }
This page took 0.03831 seconds and 5 git commands to generate.