126f0ca34bb2246ad29d4cf400c2e4bb547d959e
[lttng-tools.git] / src / lib / lttng-ctl / event-expr.c
1 /*
2 * event-expr.c
3 *
4 * Linux Trace Toolkit Control Library
5 *
6 * Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
7 *
8 * SPDX-License-Identifier: LGPL-2.1-only
9 *
10 */
11
12 #define _LGPL_SOURCE
13 #include <assert.h>
14 #include <stddef.h>
15
16 #include <common/error.h>
17 #include <common/macros.h>
18 #include <lttng/event-expr-internal.h>
19
20 enum lttng_event_expr_type lttng_event_expr_get_type(
21 const struct lttng_event_expr *expr)
22 {
23 enum lttng_event_expr_type type;
24
25 if (!expr) {
26 type = LTTNG_EVENT_EXPR_TYPE_INVALID;
27 goto end;
28 }
29
30 type = expr->type;
31
32 end:
33 return type;
34 }
35
36 static
37 struct lttng_event_expr *create_empty_expr(enum lttng_event_expr_type type,
38 size_t size)
39 {
40 struct lttng_event_expr *expr;
41
42 expr = zmalloc(size);
43 if (!expr) {
44 goto end;
45 }
46
47 expr->type = type;
48
49 end:
50 return expr;
51 }
52
53 static
54 struct lttng_event_expr_field *create_field_event_expr(
55 enum lttng_event_expr_type type,
56 const char *name)
57 {
58 struct lttng_event_expr_field *expr =
59 container_of(
60 create_empty_expr(type, sizeof(*expr)),
61 struct lttng_event_expr_field, parent);
62
63 if (!expr) {
64 goto error;
65 }
66
67 assert(name);
68 expr->name = strdup(name);
69 if (!expr->name) {
70 goto error;
71 }
72
73 goto end;
74
75 error:
76 if (expr) {
77 lttng_event_expr_destroy(&expr->parent);
78 }
79 expr = NULL;
80
81 end:
82 return expr;
83 }
84
85 struct lttng_event_expr *lttng_event_expr_event_payload_field_create(
86 const char *field_name)
87 {
88 struct lttng_event_expr *expr = NULL;
89
90 if (!field_name) {
91 goto end;
92 }
93
94 expr = &create_field_event_expr(
95 LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD,
96 field_name)->parent;
97
98 end:
99 return expr;
100 }
101
102 struct lttng_event_expr *lttng_event_expr_channel_context_field_create(
103 const char *field_name)
104 {
105 struct lttng_event_expr *expr = NULL;
106
107 if (!field_name) {
108 goto end;
109 }
110
111 expr = &create_field_event_expr(
112 LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD,
113 field_name)->parent;
114
115 end:
116 return expr;
117 }
118
119 struct lttng_event_expr *lttng_event_expr_app_specific_context_field_create(
120 const char *provider_name, const char *type_name)
121 {
122 struct lttng_event_expr_app_specific_context_field *expr = NULL;
123 struct lttng_event_expr *ret_parent_expr;
124
125 if (!type_name || !provider_name) {
126 goto error;
127 }
128
129 expr = container_of(create_empty_expr(
130 LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD,
131 sizeof(*expr)),
132 struct lttng_event_expr_app_specific_context_field,
133 parent);
134 if (!expr) {
135 goto error;
136 }
137
138 expr->provider_name = strdup(provider_name);
139 if (!expr->provider_name) {
140 goto error;
141 }
142
143 expr->type_name = strdup(type_name);
144 if (!expr->type_name) {
145 goto error;
146 }
147
148 ret_parent_expr = &expr->parent;
149 goto end;
150
151 error:
152 if (expr) {
153 lttng_event_expr_destroy(&expr->parent);
154 }
155 ret_parent_expr = NULL;
156
157 end:
158 return ret_parent_expr;
159 }
160
161 struct lttng_event_expr *lttng_event_expr_array_field_element_create(
162 struct lttng_event_expr *array_field_expr,
163 unsigned int index)
164 {
165 struct lttng_event_expr_array_field_element *expr = NULL;
166 struct lttng_event_expr *ret_parent_expr;
167
168 /* The parent array field expression must be an l-value */
169 if (!array_field_expr ||
170 !lttng_event_expr_is_lvalue(array_field_expr)) {
171 goto error;
172 }
173
174 expr = container_of(create_empty_expr(
175 LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT,
176 sizeof(*expr)),
177 struct lttng_event_expr_array_field_element,
178 parent);
179 if (!expr) {
180 goto error;
181 }
182
183 expr->array_field_expr = array_field_expr;
184 expr->index = index;
185 ret_parent_expr = &expr->parent;
186 goto end;
187
188 error:
189 if (expr) {
190 lttng_event_expr_destroy(&expr->parent);
191 }
192 ret_parent_expr = NULL;
193
194 end:
195 return ret_parent_expr;
196 }
197
198 const char *lttng_event_expr_event_payload_field_get_name(
199 const struct lttng_event_expr *expr)
200 {
201 const char *ret = NULL;
202
203 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD) {
204 goto end;
205 }
206
207 ret = container_of(expr,
208 const struct lttng_event_expr_field, parent)->name;
209
210 end:
211 return ret;
212 }
213
214 const char *lttng_event_expr_channel_context_field_get_name(
215 const struct lttng_event_expr *expr)
216 {
217 const char *ret = NULL;
218
219 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD) {
220 goto end;
221 }
222
223 ret = container_of(expr,
224 const struct lttng_event_expr_field, parent)->name;
225
226 end:
227 return ret;
228 }
229
230 const char *lttng_event_expr_app_specific_context_field_get_provider_name(
231 const struct lttng_event_expr *expr)
232 {
233 const char *ret = NULL;
234
235 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD) {
236 goto end;
237 }
238
239 ret = container_of(expr,
240 const struct lttng_event_expr_app_specific_context_field,
241 parent)->provider_name;
242
243 end:
244 return ret;
245 }
246
247 const char *lttng_event_expr_app_specific_context_field_get_type_name(
248 const struct lttng_event_expr *expr)
249 {
250 const char *ret = NULL;
251
252 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD) {
253 goto end;
254 }
255
256 ret = container_of(expr,
257 const struct lttng_event_expr_app_specific_context_field,
258 parent)->type_name;
259
260 end:
261 return ret;
262 }
263
264 const struct lttng_event_expr *
265 lttng_event_expr_array_field_element_get_parent_expr(
266 const struct lttng_event_expr *expr)
267 {
268 const struct lttng_event_expr *ret = NULL;
269
270 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT) {
271 goto end;
272 }
273
274 ret = container_of(expr,
275 const struct lttng_event_expr_array_field_element,
276 parent)->array_field_expr;
277
278 end:
279 return ret;
280 }
281
282 enum lttng_event_expr_status lttng_event_expr_array_field_element_get_index(
283 const struct lttng_event_expr *expr, unsigned int *index)
284 {
285 enum lttng_event_expr_status ret = LTTNG_EVENT_EXPR_STATUS_OK;
286
287 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT ||
288 !index) {
289 ret = LTTNG_EVENT_EXPR_STATUS_INVALID;
290 goto end;
291 }
292
293 *index = container_of(expr,
294 const struct lttng_event_expr_array_field_element,
295 parent)->index;
296
297 end:
298 return ret;
299 }
300
301 bool lttng_event_expr_is_equal(const struct lttng_event_expr *expr_a,
302 const struct lttng_event_expr *expr_b)
303 {
304 bool is_equal = true;
305
306 if (!expr_a && !expr_b) {
307 /* Both `NULL`: equal */
308 goto end;
309 }
310
311 if (!expr_a || !expr_b) {
312 /* Only one `NULL`: not equal */
313 goto not_equal;
314 }
315
316 if (expr_a->type != expr_b->type) {
317 /* Different types: not equal */
318 goto not_equal;
319 }
320
321 switch (expr_a->type) {
322 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
323 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
324 {
325 const struct lttng_event_expr_field *field_expr_a =
326 container_of(expr_a,
327 const struct lttng_event_expr_field,
328 parent);
329 const struct lttng_event_expr_field *field_expr_b =
330 container_of(expr_b,
331 const struct lttng_event_expr_field,
332 parent);
333
334 if (strcmp(field_expr_a->name, field_expr_b->name) != 0) {
335 goto not_equal;
336 }
337
338 break;
339 }
340 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
341 {
342 const struct lttng_event_expr_app_specific_context_field *field_expr_a =
343 container_of(expr_a,
344 const struct lttng_event_expr_app_specific_context_field,
345 parent);
346 const struct lttng_event_expr_app_specific_context_field *field_expr_b =
347 container_of(expr_b,
348 const struct lttng_event_expr_app_specific_context_field,
349 parent);
350
351 if (strcmp(field_expr_a->provider_name,
352 field_expr_b->provider_name) != 0) {
353 goto not_equal;
354 }
355
356 if (strcmp(field_expr_a->type_name,
357 field_expr_b->type_name) != 0) {
358 goto not_equal;
359 }
360
361 break;
362 }
363 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
364 {
365 const struct lttng_event_expr_array_field_element *elem_expr_a =
366 container_of(expr_a,
367 const struct lttng_event_expr_array_field_element,
368 parent);
369 const struct lttng_event_expr_array_field_element *elem_expr_b =
370 container_of(expr_b,
371 const struct lttng_event_expr_array_field_element,
372 parent);
373
374 if (!lttng_event_expr_is_equal(elem_expr_a->array_field_expr,
375 elem_expr_b->array_field_expr)) {
376 goto not_equal;
377 }
378
379 if (elem_expr_a->index != elem_expr_b->index) {
380 goto not_equal;
381 }
382
383 break;
384 }
385 default:
386 break;
387 }
388
389 goto end;
390
391 not_equal:
392 is_equal = false;
393
394 end:
395 return is_equal;
396 }
397
398 void lttng_event_expr_destroy(struct lttng_event_expr *expr)
399 {
400 if (!expr) {
401 goto end;
402 }
403
404 switch (expr->type) {
405 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
406 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
407 {
408 struct lttng_event_expr_field *field_expr =
409 container_of(expr,
410 struct lttng_event_expr_field, parent);
411
412 free(field_expr->name);
413 break;
414 }
415 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
416 {
417 struct lttng_event_expr_app_specific_context_field *field_expr =
418 container_of(expr,
419 struct lttng_event_expr_app_specific_context_field,
420 parent);
421
422 free(field_expr->provider_name);
423 free(field_expr->type_name);
424 break;
425 }
426 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
427 {
428 struct lttng_event_expr_array_field_element *elem_expr =
429 container_of(expr,
430 struct lttng_event_expr_array_field_element,
431 parent);
432
433 lttng_event_expr_destroy(elem_expr->array_field_expr);
434 break;
435 }
436 default:
437 break;
438 }
439
440 free(expr);
441
442 end:
443 return;
444 }
This page took 0.038898 seconds and 4 git commands to generate.