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