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