lttng-ctl: add event expression API
[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 lttng_event_expr_destroy(&expr->parent);
77
78 end:
79 return expr;
80 }
81
82 struct lttng_event_expr *lttng_event_expr_event_payload_field_create(
83 const char *field_name)
84 {
85 struct lttng_event_expr *expr = NULL;
86
87 if (!field_name) {
88 goto end;
89 }
90
91 expr = &create_field_event_expr(
92 LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD,
93 field_name)->parent;
94
95 end:
96 return expr;
97 }
98
99 struct lttng_event_expr *lttng_event_expr_channel_context_field_create(
100 const char *field_name)
101 {
102 struct lttng_event_expr *expr = NULL;
103
104 if (!field_name) {
105 goto end;
106 }
107
108 expr = &create_field_event_expr(
109 LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD,
110 field_name)->parent;
111
112 end:
113 return expr;
114 }
115
116 struct lttng_event_expr *lttng_event_expr_app_specific_context_field_create(
117 const char *provider_name, const char *type_name)
118 {
119 struct lttng_event_expr_app_specific_context_field *expr = NULL;
120
121 if (!type_name || !provider_name) {
122 goto error;
123 }
124
125 expr = container_of(create_empty_expr(
126 LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD,
127 sizeof(*expr)),
128 struct lttng_event_expr_app_specific_context_field,
129 parent);
130 if (!expr) {
131 goto error;
132 }
133
134 expr->provider_name = strdup(provider_name);
135 if (!expr->provider_name) {
136 goto error;
137 }
138
139 expr->type_name = strdup(type_name);
140 if (!expr->type_name) {
141 goto error;
142 }
143
144 goto end;
145
146 error:
147 lttng_event_expr_destroy(&expr->parent);
148
149 end:
150 return &expr->parent;
151 }
152
153 struct lttng_event_expr *lttng_event_expr_array_field_element_create(
154 struct lttng_event_expr *array_field_expr,
155 unsigned int index)
156 {
157 struct lttng_event_expr_array_field_element *expr = NULL;
158
159 /* The parent array field expression must be an l-value */
160 if (!array_field_expr ||
161 !lttng_event_expr_is_lvalue(array_field_expr)) {
162 goto error;
163 }
164
165 expr = container_of(create_empty_expr(
166 LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT,
167 sizeof(*expr)),
168 struct lttng_event_expr_array_field_element,
169 parent);
170 if (!expr) {
171 goto error;
172 }
173
174 expr->array_field_expr = array_field_expr;
175 expr->index = index;
176 goto end;
177
178 error:
179 lttng_event_expr_destroy(&expr->parent);
180
181 end:
182 return &expr->parent;
183 }
184
185 const char *lttng_event_expr_event_payload_field_get_name(
186 const struct lttng_event_expr *expr)
187 {
188 const char *ret = NULL;
189
190 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD) {
191 goto end;
192 }
193
194 ret = container_of(expr,
195 const struct lttng_event_expr_field, parent)->name;
196
197 end:
198 return ret;
199 }
200
201 const char *lttng_event_expr_channel_context_field_get_name(
202 const struct lttng_event_expr *expr)
203 {
204 const char *ret = NULL;
205
206 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD) {
207 goto end;
208 }
209
210 ret = container_of(expr,
211 const struct lttng_event_expr_field, parent)->name;
212
213 end:
214 return ret;
215 }
216
217 const char *lttng_event_expr_app_specific_context_field_get_provider_name(
218 const struct lttng_event_expr *expr)
219 {
220 const char *ret = NULL;
221
222 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD) {
223 goto end;
224 }
225
226 ret = container_of(expr,
227 const struct lttng_event_expr_app_specific_context_field,
228 parent)->provider_name;
229
230 end:
231 return ret;
232 }
233
234 const char *lttng_event_expr_app_specific_context_field_get_type_name(
235 const struct lttng_event_expr *expr)
236 {
237 const char *ret = NULL;
238
239 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD) {
240 goto end;
241 }
242
243 ret = container_of(expr,
244 const struct lttng_event_expr_app_specific_context_field,
245 parent)->type_name;
246
247 end:
248 return ret;
249 }
250
251 const struct lttng_event_expr *
252 lttng_event_expr_array_field_element_get_parent_expr(
253 const struct lttng_event_expr *expr)
254 {
255 const struct lttng_event_expr *ret = NULL;
256
257 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT) {
258 goto end;
259 }
260
261 ret = container_of(expr,
262 const struct lttng_event_expr_array_field_element,
263 parent)->array_field_expr;
264
265 end:
266 return ret;
267 }
268
269 enum lttng_event_expr_status lttng_event_expr_array_field_element_get_index(
270 const struct lttng_event_expr *expr, unsigned int *index)
271 {
272 enum lttng_event_expr_status ret = LTTNG_EVENT_EXPR_STATUS_OK;
273
274 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT ||
275 !index) {
276 ret = LTTNG_EVENT_EXPR_STATUS_INVALID;
277 goto end;
278 }
279
280 *index = container_of(expr,
281 const struct lttng_event_expr_array_field_element,
282 parent)->index;
283
284 end:
285 return ret;
286 }
287
288 bool lttng_event_expr_is_equal(const struct lttng_event_expr *expr_a,
289 const struct lttng_event_expr *expr_b)
290 {
291 bool is_equal = true;
292
293 if (!expr_a && !expr_b) {
294 /* Both `NULL`: equal */
295 goto end;
296 }
297
298 if (!expr_a || !expr_b) {
299 /* Only one `NULL`: not equal */
300 goto not_equal;
301 }
302
303 if (expr_a->type != expr_b->type) {
304 /* Different types: not equal */
305 goto not_equal;
306 }
307
308 switch (expr_a->type) {
309 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
310 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
311 {
312 const struct lttng_event_expr_field *field_expr_a =
313 container_of(expr_a,
314 const struct lttng_event_expr_field,
315 parent);
316 const struct lttng_event_expr_field *field_expr_b =
317 container_of(expr_b,
318 const struct lttng_event_expr_field,
319 parent);
320
321 if (strcmp(field_expr_a->name, field_expr_b->name) != 0) {
322 goto not_equal;
323 }
324
325 break;
326 }
327 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
328 {
329 const struct lttng_event_expr_app_specific_context_field *field_expr_a =
330 container_of(expr_a,
331 const struct lttng_event_expr_app_specific_context_field,
332 parent);
333 const struct lttng_event_expr_app_specific_context_field *field_expr_b =
334 container_of(expr_b,
335 const struct lttng_event_expr_app_specific_context_field,
336 parent);
337
338 if (strcmp(field_expr_a->provider_name,
339 field_expr_b->provider_name) != 0) {
340 goto not_equal;
341 }
342
343 if (strcmp(field_expr_a->type_name,
344 field_expr_b->type_name) != 0) {
345 goto not_equal;
346 }
347
348 break;
349 }
350 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
351 {
352 const struct lttng_event_expr_array_field_element *elem_expr_a =
353 container_of(expr_a,
354 const struct lttng_event_expr_array_field_element,
355 parent);
356 const struct lttng_event_expr_array_field_element *elem_expr_b =
357 container_of(expr_b,
358 const struct lttng_event_expr_array_field_element,
359 parent);
360
361 if (!lttng_event_expr_is_equal(elem_expr_a->array_field_expr,
362 elem_expr_b->array_field_expr)) {
363 goto not_equal;
364 }
365
366 if (elem_expr_a->index != elem_expr_b->index) {
367 goto not_equal;
368 }
369
370 break;
371 }
372 default:
373 break;
374 }
375
376 goto end;
377
378 not_equal:
379 is_equal = false;
380
381 end:
382 return is_equal;
383 }
384
385 void lttng_event_expr_destroy(struct lttng_event_expr *expr)
386 {
387 if (!expr) {
388 goto end;
389 }
390
391 switch (expr->type) {
392 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
393 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
394 {
395 struct lttng_event_expr_field *field_expr =
396 container_of(expr,
397 struct lttng_event_expr_field, parent);
398
399 free(field_expr->name);
400 break;
401 }
402 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
403 {
404 struct lttng_event_expr_app_specific_context_field *field_expr =
405 container_of(expr,
406 struct lttng_event_expr_app_specific_context_field,
407 parent);
408
409 free(field_expr->provider_name);
410 free(field_expr->type_name);
411 break;
412 }
413 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
414 {
415 struct lttng_event_expr_array_field_element *elem_expr =
416 container_of(expr,
417 struct lttng_event_expr_array_field_element,
418 parent);
419
420 lttng_event_expr_destroy(elem_expr->array_field_expr);
421 break;
422 }
423 default:
424 break;
425 }
426
427 free(expr);
428
429 end:
430 return;
431 }
This page took 0.037318 seconds and 4 git commands to generate.