2 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
11 #include <common/error.h>
12 #include <common/macros.h>
13 #include <common/optional.h>
15 #include <lttng/action/action-internal.h>
16 #include <lttng/action/incr-value-internal.h>
17 #include <lttng/action/incr-value.h>
18 #include <lttng/map-key.h>
19 #include <lttng/map-key-internal.h>
21 #define IS_INCR_VALUE_ACTION(action) \
22 (lttng_action_get_type(action) == LTTNG_ACTION_TYPE_INCREMENT_VALUE)
24 struct lttng_action_incr_value
{
25 struct lttng_action parent
;
28 struct lttng_map_key
*key
;
34 LTTNG_OPTIONAL(uint64_t) action_tracer_token
;
37 struct lttng_action_incr_value_comm
{
38 /* Includes the trailing \0. */
39 uint32_t session_name_len
;
40 /* Includes the trailing \0. */
41 uint32_t map_name_len
;
46 * - struct lttng_map_key object with variable data
47 * - session name (null terminated)
48 * - map name (null terminated)
53 static struct lttng_action_incr_value
*action_incr_value_from_action(
54 struct lttng_action
*action
)
58 return container_of(action
, struct lttng_action_incr_value
, parent
);
61 static const struct lttng_action_incr_value
*
62 action_incr_value_from_action_const(const struct lttng_action
*action
)
66 return container_of(action
, struct lttng_action_incr_value
, parent
);
69 static bool lttng_action_incr_value_validate(struct lttng_action
*action
)
72 struct lttng_action_incr_value
*action_incr_value
;
79 action_incr_value
= action_incr_value_from_action(action
);
81 /* Non null key is mandatory. */
82 if (!action_incr_value
->key
) {
87 /* A non-empty session name is mandatory. */
88 if (!action_incr_value
->session_name
||
89 strlen(action_incr_value
->session_name
) == 0) {
94 /* A non-empty map name is mandatory. */
95 if (!action_incr_value
->map_name
||
96 strlen(action_incr_value
->map_name
) == 0) {
106 static bool lttng_action_incr_value_is_equal(
107 const struct lttng_action
*_a
, const struct lttng_action
*_b
)
109 bool is_equal
= false;
110 const struct lttng_action_incr_value
*a
, *b
;
112 a
= action_incr_value_from_action_const(_a
);
113 b
= action_incr_value_from_action_const(_b
);
115 /* Action is not valid if this is not true. */
118 assert(a
->session_name
);
119 assert(b
->session_name
);
123 if (strcmp(a
->session_name
, b
->session_name
)) {
127 if (strcmp(a
->map_name
, b
->map_name
)) {
131 is_equal
= lttng_map_key_is_equal(a
->key
, b
->key
);
137 static int lttng_action_incr_value_serialize(
138 struct lttng_action
*action
, struct lttng_payload
*payload
)
140 struct lttng_action_incr_value
*action_incr_value
;
141 struct lttng_action_incr_value_comm comm
;
142 size_t session_name_len
, map_name_len
;
148 action_incr_value
= action_incr_value_from_action(action
);
150 DBG("Serializing increment value action");
152 session_name_len
= strlen(action_incr_value
->session_name
) + 1;
153 comm
.session_name_len
= session_name_len
;
155 map_name_len
= strlen(action_incr_value
->map_name
) + 1;
156 comm
.map_name_len
= map_name_len
;
158 ret
= lttng_dynamic_buffer_append(
159 &payload
->buffer
, &comm
, sizeof(comm
));
165 ret
= lttng_map_key_serialize(action_incr_value
->key
, payload
);
171 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
172 action_incr_value
->session_name
, session_name_len
);
178 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
179 action_incr_value
->map_name
, map_name_len
);
190 static void lttng_action_incr_value_destroy(struct lttng_action
*action
)
192 struct lttng_action_incr_value
*action_incr_value
;
198 action_incr_value
= action_incr_value_from_action(action
);
200 lttng_map_key_destroy(action_incr_value
->key
);
202 free(action_incr_value
->session_name
);
203 free(action_incr_value
->map_name
);
204 free(action_incr_value
);
210 ssize_t
lttng_action_incr_value_create_from_payload(
211 struct lttng_payload_view
*view
,
212 struct lttng_action
**p_action
)
214 ssize_t consumed_len
, consumed_key_len
, ret
;
215 struct lttng_map_key
*key
= NULL
;
216 const struct lttng_action_incr_value_comm
*comm
;
217 const char *session_name
, *map_name
;
218 struct lttng_action
*action
;
219 enum lttng_action_status status
;
221 action
= lttng_action_incr_value_create();
227 comm
= (typeof(comm
)) view
->buffer
.data
;
228 consumed_len
= sizeof(struct lttng_action_incr_value_comm
);
231 struct lttng_payload_view key_view
=
232 lttng_payload_view_from_view(view
, consumed_len
,
233 view
->buffer
.size
- consumed_len
);
235 if (!lttng_payload_view_is_valid(&key_view
)) {
239 ret
= lttng_map_key_create_from_payload(&key_view
, &key
);
244 consumed_key_len
= ret
;
247 consumed_len
+= consumed_key_len
;
248 session_name
= (const char *) &comm
->data
+ consumed_key_len
;
250 if (!lttng_buffer_view_contains_string(
251 &view
->buffer
, session_name
, comm
->session_name_len
)) {
256 consumed_len
+= comm
->session_name_len
;
258 map_name
= (const char *) &comm
->data
+ consumed_key_len
+ comm
->session_name_len
;
260 if (!lttng_buffer_view_contains_string(
261 &view
->buffer
, map_name
, comm
->map_name_len
)) {
266 consumed_len
+= comm
->map_name_len
;
268 status
= lttng_action_incr_value_set_key(action
, key
);
269 /* Ownership is passed to the action. */
270 lttng_map_key_put(key
);
272 if (status
!= LTTNG_ACTION_STATUS_OK
) {
277 status
= lttng_action_incr_value_set_session_name(
278 action
, session_name
);
279 if (status
!= LTTNG_ACTION_STATUS_OK
) {
284 status
= lttng_action_incr_value_set_map_name(
286 if (status
!= LTTNG_ACTION_STATUS_OK
) {
296 lttng_action_incr_value_destroy(action
);
303 struct lttng_action
*lttng_action_incr_value_create(void)
305 struct lttng_action
*action
;
307 action
= zmalloc(sizeof(struct lttng_action_incr_value
));
312 lttng_action_init(action
, LTTNG_ACTION_TYPE_INCREMENT_VALUE
,
313 lttng_action_incr_value_validate
,
314 lttng_action_incr_value_serialize
,
315 lttng_action_incr_value_is_equal
,
316 lttng_action_incr_value_destroy
);
322 enum lttng_action_status
lttng_action_incr_value_set_session_name(
323 struct lttng_action
*action
, const char *session_name
)
325 struct lttng_action_incr_value
*action_incr_value
;
326 enum lttng_action_status status
;
328 if (!action
|| !IS_INCR_VALUE_ACTION(action
) || !session_name
||
329 strlen(session_name
) == 0) {
330 status
= LTTNG_ACTION_STATUS_INVALID
;
334 action_incr_value
= action_incr_value_from_action(action
);
336 free(action_incr_value
->session_name
);
338 action_incr_value
->session_name
= strdup(session_name
);
339 if (!action_incr_value
->session_name
) {
340 status
= LTTNG_ACTION_STATUS_ERROR
;
344 status
= LTTNG_ACTION_STATUS_OK
;
349 enum lttng_action_status
lttng_action_incr_value_get_session_name(
350 const struct lttng_action
*action
, const char **session_name
)
352 const struct lttng_action_incr_value
*action_incr_value
;
353 enum lttng_action_status status
;
355 if (!action
|| !IS_INCR_VALUE_ACTION(action
) || !session_name
) {
356 status
= LTTNG_ACTION_STATUS_INVALID
;
360 action_incr_value
= action_incr_value_from_action_const(action
);
362 *session_name
= action_incr_value
->session_name
;
364 status
= LTTNG_ACTION_STATUS_OK
;
369 enum lttng_action_status
lttng_action_incr_value_set_map_name(
370 struct lttng_action
*action
, const char *map_name
)
372 struct lttng_action_incr_value
*action_incr_value
;
373 enum lttng_action_status status
;
375 if (!action
|| !IS_INCR_VALUE_ACTION(action
) || !map_name
||
376 strlen(map_name
) == 0) {
377 status
= LTTNG_ACTION_STATUS_INVALID
;
381 action_incr_value
= action_incr_value_from_action(action
);
383 free(action_incr_value
->map_name
);
385 action_incr_value
->map_name
= strdup(map_name
);
386 if (!action_incr_value
->map_name
) {
387 status
= LTTNG_ACTION_STATUS_ERROR
;
391 status
= LTTNG_ACTION_STATUS_OK
;
396 enum lttng_action_status
lttng_action_incr_value_get_map_name(
397 const struct lttng_action
*action
, const char **map_name
)
399 const struct lttng_action_incr_value
*action_incr_value
;
400 enum lttng_action_status status
;
402 if (!action
|| !IS_INCR_VALUE_ACTION(action
) || !map_name
) {
403 status
= LTTNG_ACTION_STATUS_INVALID
;
407 action_incr_value
= action_incr_value_from_action_const(action
);
409 *map_name
= action_incr_value
->map_name
;
411 status
= LTTNG_ACTION_STATUS_OK
;
417 enum lttng_action_status
lttng_action_incr_value_borrow_key_mutable(
418 const struct lttng_action
*action
, struct lttng_map_key
**key
)
420 const struct lttng_action_incr_value
*action_incr_value
;
421 enum lttng_action_status status
;
423 if (!action
|| !IS_INCR_VALUE_ACTION(action
) || !key
) {
424 status
= LTTNG_ACTION_STATUS_INVALID
;
428 action_incr_value
= action_incr_value_from_action_const(action
);
430 *key
= action_incr_value
->key
;
432 status
= LTTNG_ACTION_STATUS_OK
;
437 enum lttng_action_status
lttng_action_incr_value_get_key(
438 const struct lttng_action
*action
,
439 const struct lttng_map_key
**key
)
441 struct lttng_map_key
*mutable_key
= NULL
;
442 enum lttng_action_status status
=
443 lttng_action_incr_value_borrow_key_mutable(
444 action
, &mutable_key
);
450 enum lttng_action_status
451 lttng_action_incr_value_set_key(
452 struct lttng_action
*action
,
453 struct lttng_map_key
*key
)
455 struct lttng_action_incr_value
*action_incr_value
;
456 enum lttng_action_status status
;
458 if (!action
|| !IS_INCR_VALUE_ACTION(action
) || !key
) {
459 status
= LTTNG_ACTION_STATUS_INVALID
;
463 action_incr_value
= action_incr_value_from_action(action
);
465 /* Take a reference to the key. */
466 lttng_map_key_get(key
);
467 action_incr_value
->key
= key
;
469 status
= LTTNG_ACTION_STATUS_OK
;
475 enum lttng_action_status
lttng_action_incr_value_set_tracer_token(
476 struct lttng_action
*action
, uint64_t token
)
478 struct lttng_action_incr_value
*action_incr_value
;
479 enum lttng_action_status status
;
481 if (!action
|| !IS_INCR_VALUE_ACTION(action
)) {
482 status
= LTTNG_ACTION_STATUS_INVALID
;
486 action_incr_value
= action_incr_value_from_action(action
);
488 LTTNG_OPTIONAL_SET(&action_incr_value
->action_tracer_token
, token
);
490 status
= LTTNG_ACTION_STATUS_OK
;
496 uint64_t lttng_action_incr_value_get_tracer_token(
497 const struct lttng_action
*action
)
499 const struct lttng_action_incr_value
*action_incr_value
;
502 assert(IS_INCR_VALUE_ACTION(action
));
504 action_incr_value
= action_incr_value_from_action_const(action
);
506 return LTTNG_OPTIONAL_GET(action_incr_value
->action_tracer_token
);