2 * Copyright (C) 2021 Francis Deslauriers <francis.deslauriers@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
11 #include <common/dynamic-array.h>
12 #include <common/error.h>
13 #include <common/macros.h>
14 #include <common/payload.h>
15 #include <common/payload-view.h>
17 #include <lttng/map-key.h>
18 #include <lttng/map-key-internal.h>
20 #define TOKEN_VAR_EVENT_NAME "EVENT_NAME"
21 #define TOKEN_VAR_PROVIDER_NAME "PROVIDER_NAME"
24 void destroy_map_key_token(void *ptr
)
26 struct lttng_map_key_token
*token
= (struct lttng_map_key_token
*) ptr
;
27 switch (token
->type
) {
28 case LTTNG_MAP_KEY_TOKEN_TYPE_STRING
:
30 struct lttng_map_key_token_string
*token_string
=
31 (struct lttng_map_key_token_string
*) token
;
32 free(token_string
->string
);
35 case LTTNG_MAP_KEY_TOKEN_TYPE_VARIABLE
:
44 struct lttng_map_key
*lttng_map_key_create(void)
46 struct lttng_map_key
*key
= NULL
;
48 key
= zmalloc(sizeof(*key
));
53 urcu_ref_init(&key
->ref
);
54 lttng_dynamic_pointer_array_init(&key
->tokens
,
55 destroy_map_key_token
);
60 ssize_t
lttng_map_key_create_from_payload(struct lttng_payload_view
*src_view
,
61 struct lttng_map_key
**out_key
)
63 ssize_t ret
, consumed_len
;
65 const struct lttng_map_key_comm
*comm
;
66 struct lttng_map_key
*key
;
68 if (!src_view
|| !out_key
) {
73 key
= lttng_map_key_create();
79 comm
= (typeof(comm
)) src_view
->buffer
.data
;
80 consumed_len
= sizeof(*comm
);
82 assert(comm
->token_count
> 0);
84 for (i
= 0; i
< comm
->token_count
; i
++) {
85 enum lttng_map_key_status key_status
;
86 const struct lttng_map_key_token_comm
*token_comm
;
87 struct lttng_payload_view child_view
=
88 lttng_payload_view_from_view(src_view
, consumed_len
,
89 src_view
->buffer
.size
- consumed_len
);
90 if (!lttng_payload_view_is_valid(&child_view
)) {
95 token_comm
= (const struct lttng_map_key_token_comm
*) child_view
.buffer
.data
;
97 switch (token_comm
->type
) {
98 case LTTNG_MAP_KEY_TOKEN_TYPE_STRING
:
101 const struct lttng_map_key_token_string_comm
*comm
;
103 comm
= (typeof(comm
)) token_comm
;
104 str_val
= (const char *) &comm
->payload
;
106 if (!lttng_buffer_view_contains_string(&child_view
.buffer
,
107 str_val
, comm
->string_len
)) {
112 key_status
= lttng_map_key_append_token_string(key
, str_val
);
113 if (key_status
!= LTTNG_MAP_KEY_STATUS_OK
) {
118 consumed_len
+= sizeof(*comm
) + comm
->string_len
;
122 case LTTNG_MAP_KEY_TOKEN_TYPE_VARIABLE
:
124 const struct lttng_map_key_token_variable_comm
*comm
;
126 comm
= (typeof(comm
)) token_comm
;
127 key_status
= lttng_map_key_append_token_variable(key
,
129 if (key_status
!= LTTNG_MAP_KEY_STATUS_OK
) {
134 consumed_len
+= sizeof(*comm
);
148 int lttng_map_key_serialize(const struct lttng_map_key
*key
,
149 struct lttng_payload
*payload
)
152 uint32_t i
, nb_tokens
;
153 enum lttng_map_key_status key_status
;
154 struct lttng_map_key_comm comm
= {0};
156 DBG("Serializing map key");
158 key_status
= lttng_map_key_get_token_count(key
, &nb_tokens
);
159 if (key_status
!= LTTNG_MAP_KEY_STATUS_OK
) {
164 if (nb_tokens
== 0) {
165 ERR("Map key token number is zero");
170 DBG("Serializing map key token count: %" PRIu32
, nb_tokens
);
171 comm
.token_count
= nb_tokens
;
173 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &comm
,
179 for (i
= 0; i
< nb_tokens
; i
++) {
181 const struct lttng_map_key_token
*token
=
182 lttng_map_key_get_token_at_index(key
, i
);
183 DBG("Serializing map key token's type: %d", token
->type
);
185 token_type
= (uint8_t) token
->type
;
187 switch (token
->type
) {
188 case LTTNG_MAP_KEY_TOKEN_TYPE_STRING
:
190 struct lttng_map_key_token_string
*str_token
=
191 (struct lttng_map_key_token_string
*) token
;
192 struct lttng_map_key_token_string_comm comm
= {0};
193 uint32_t len
= strlen(str_token
->string
) + 1;
195 DBG("Serializing a string type key token");
196 comm
.parent_type
= token_type
;
197 comm
.string_len
= len
;
199 /* Serialize the length, include the null character */
200 DBG("Serializing map key token string length (include null character):"
202 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
203 &comm
, sizeof(comm
));
208 /* Serialize the string */
209 DBG("Serializing map key token string's value: \"%s\"",
211 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
212 str_token
->string
, len
);
219 case LTTNG_MAP_KEY_TOKEN_TYPE_VARIABLE
:
221 struct lttng_map_key_token_variable
*var_token
=
222 (struct lttng_map_key_token_variable
*) token
;
223 struct lttng_map_key_token_variable_comm comm
= {0};
225 DBG("Serializing a variable type key token");
227 comm
.parent_type
= token_type
;
228 comm
.var_type
= var_token
->type
;
230 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
231 &comm
, sizeof(comm
));
248 bool token_variable_type_is_valid(enum lttng_map_key_token_variable_type var_type
)
251 case LTTNG_MAP_KEY_TOKEN_VARIABLE_TYPE_EVENT_NAME
:
252 case LTTNG_MAP_KEY_TOKEN_VARIABLE_TYPE_PROVIDER_NAME
:
259 static bool lttng_map_key_token_variable_is_equal(
260 const struct lttng_map_key_token
*_a
,
261 const struct lttng_map_key_token
*_b
)
263 struct lttng_map_key_token_variable
*a
, *b
;
264 assert(_a
->type
== LTTNG_MAP_KEY_TOKEN_TYPE_VARIABLE
);
265 assert(_b
->type
== LTTNG_MAP_KEY_TOKEN_TYPE_VARIABLE
);
267 a
= container_of(_a
, struct lttng_map_key_token_variable
, parent
);
268 b
= container_of(_b
, struct lttng_map_key_token_variable
, parent
);
270 return lttng_map_key_token_variable_get_type(a
) ==
271 lttng_map_key_token_variable_get_type(b
);
274 enum lttng_map_key_status
lttng_map_key_append_token_variable(
275 struct lttng_map_key
*key
,
276 enum lttng_map_key_token_variable_type var_type
)
279 enum lttng_map_key_status status
;
280 struct lttng_map_key_token_variable
*token
= NULL
;
282 if (!token_variable_type_is_valid(var_type
)) {
283 ERR("Invalid token variable type");
284 status
= LTTNG_MAP_KEY_STATUS_INVALID
;
288 token
= zmalloc(sizeof(*token
));
290 status
= LTTNG_MAP_KEY_STATUS_ERROR
;
294 token
->parent
.type
= LTTNG_MAP_KEY_TOKEN_TYPE_VARIABLE
;
295 token
->parent
.equal
= lttng_map_key_token_variable_is_equal
;
296 token
->type
= var_type
;
298 ret
= lttng_dynamic_pointer_array_add_pointer(
299 &key
->tokens
, token
);
301 status
= LTTNG_MAP_KEY_STATUS_ERROR
;
305 status
= LTTNG_MAP_KEY_STATUS_OK
;
311 static bool lttng_map_key_token_string_is_equal(
312 const struct lttng_map_key_token
*_a
,
313 const struct lttng_map_key_token
*_b
)
315 struct lttng_map_key_token_string
*a
, *b
;
316 const char *a_string
, *b_string
;
318 assert(_a
->type
== LTTNG_MAP_KEY_TOKEN_TYPE_STRING
);
319 assert(_b
->type
== LTTNG_MAP_KEY_TOKEN_TYPE_STRING
);
321 a
= container_of(_a
, struct lttng_map_key_token_string
, parent
);
322 b
= container_of(_b
, struct lttng_map_key_token_string
, parent
);
324 a_string
= lttng_map_key_token_string_get_string(a
);
325 b_string
= lttng_map_key_token_string_get_string(b
);
327 return !strcmp(a_string
, b_string
);
330 enum lttng_map_key_status
lttng_map_key_append_token_string(
331 struct lttng_map_key
*key
, const char *string
)
334 enum lttng_map_key_status status
;
335 struct lttng_map_key_token_string
*token
= NULL
;
338 token
= zmalloc(sizeof(*token
));
340 status
= LTTNG_MAP_KEY_STATUS_ERROR
;
344 token
->parent
.type
= LTTNG_MAP_KEY_TOKEN_TYPE_STRING
;
345 token
->parent
.equal
= lttng_map_key_token_string_is_equal
;
346 token
->string
= strdup(string
);
347 if (!token
->string
) {
348 status
= LTTNG_MAP_KEY_STATUS_ERROR
;
352 ret
= lttng_dynamic_pointer_array_add_pointer(
353 &key
->tokens
, token
);
355 status
= LTTNG_MAP_KEY_STATUS_ERROR
;
359 status
= LTTNG_MAP_KEY_STATUS_OK
;
364 enum lttng_map_key_status
lttng_map_key_get_token_count(
365 const struct lttng_map_key
*key
, unsigned int *count
)
367 enum lttng_map_key_status status
;
368 if (!key
|| !count
) {
369 status
= LTTNG_MAP_KEY_STATUS_INVALID
;
374 *count
= lttng_dynamic_pointer_array_get_count(
377 status
= LTTNG_MAP_KEY_STATUS_OK
;
382 const struct lttng_map_key_token
*
383 lttng_map_key_get_token_at_index(const struct lttng_map_key
*key
,
386 const struct lttng_map_key_token
*token
= NULL
;
387 enum lttng_map_key_status status
;
394 status
= lttng_map_key_get_token_count(key
, &count
);
395 if (status
!= LTTNG_MAP_KEY_STATUS_OK
) {
399 if (index
>= count
) {
403 token
= lttng_dynamic_pointer_array_get_pointer(&key
->tokens
,
410 enum lttng_map_key_token_variable_type
lttng_map_key_token_variable_get_type(
411 const struct lttng_map_key_token_variable
*token
)
413 assert(token
->parent
.type
== LTTNG_MAP_KEY_TOKEN_TYPE_VARIABLE
);
418 const char *lttng_map_key_token_string_get_string(
419 const struct lttng_map_key_token_string
*token
)
421 assert(token
->parent
.type
== LTTNG_MAP_KEY_TOKEN_TYPE_STRING
);
423 return token
->string
;
426 void lttng_map_key_destroy(struct lttng_map_key
*key
)
428 lttng_map_key_put(key
);
432 struct lttng_map_key
*lttng_map_key_parse_from_string(const char *_key_str
)
434 struct lttng_map_key
*key
= NULL
;
435 enum lttng_map_key_status status
;
436 char *key_str
= NULL
, *curr_pos
;
438 key
= lttng_map_key_create();
443 key_str
= strdup(_key_str
);
447 curr_pos
= strtok(curr_pos
, "$}");
449 if (curr_pos
[0] == '{') {
450 if (strncmp(&curr_pos
[1], TOKEN_VAR_EVENT_NAME
, strlen(TOKEN_VAR_EVENT_NAME
)) == 0) {
451 status
= lttng_map_key_append_token_variable(key
,
452 LTTNG_MAP_KEY_TOKEN_VARIABLE_TYPE_EVENT_NAME
);
453 if (status
!= LTTNG_MAP_KEY_STATUS_OK
) {
456 } else if (strncmp(&curr_pos
[1], TOKEN_VAR_PROVIDER_NAME
, strlen(TOKEN_VAR_PROVIDER_NAME
)) == 0) {
457 status
= lttng_map_key_append_token_variable(key
,
458 LTTNG_MAP_KEY_TOKEN_VARIABLE_TYPE_PROVIDER_NAME
);
459 if (status
!= LTTNG_MAP_KEY_STATUS_OK
) {
466 status
= lttng_map_key_append_token_string(key
, curr_pos
);
467 if (status
!= LTTNG_MAP_KEY_STATUS_OK
) {
471 curr_pos
= strtok(NULL
, "$}");
476 lttng_map_key_destroy(key
);
485 bool lttng_map_key_is_equal(
486 const struct lttng_map_key
*a
, const struct lttng_map_key
*b
)
488 bool is_equal
= false;
489 enum lttng_map_key_status status
;
490 unsigned int a_count
, b_count
, i
;
496 if (a
== NULL
&& b
== NULL
) {
506 status
= lttng_map_key_get_token_count(a
, &a_count
);
507 assert(status
== LTTNG_MAP_KEY_STATUS_OK
);
508 status
= lttng_map_key_get_token_count(b
, &b_count
);
509 assert(status
== LTTNG_MAP_KEY_STATUS_OK
);
511 if (a_count
!= b_count
) {
515 for (i
= 0; i
< a_count
; i
++) {
516 const struct lttng_map_key_token
*token_a
= NULL
, *token_b
= NULL
;
518 token_a
= lttng_map_key_get_token_at_index(a
, i
);
519 token_b
= lttng_map_key_get_token_at_index(b
, i
);
521 /* JORAJ TODO: is order important for the map key token? */
522 if(token_a
->type
!= token_b
->type
) {
526 if(!token_a
->equal(token_a
, token_b
)) {
539 static void map_key_destroy_ref(struct urcu_ref
*ref
)
541 struct lttng_map_key
*key
= container_of(ref
, struct lttng_map_key
, ref
);
543 lttng_dynamic_pointer_array_reset(&key
->tokens
);
548 void lttng_map_key_get(struct lttng_map_key
*key
)
550 urcu_ref_get(&key
->ref
);
554 void lttng_map_key_put(struct lttng_map_key
*key
)
560 urcu_ref_put(&key
->ref
, map_key_destroy_ref
);