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>
14 #include <common/payload.h>
16 #include <lttng/lttng.h>
17 #include <lttng/map/map-internal.h>
19 enum lttng_map_status
lttng_map_set_name(struct lttng_map
*map
,
22 char *name_copy
= NULL
;
23 enum lttng_map_status status
;
25 if (!map
|| !name
|| strlen(name
) == 0) {
26 status
= LTTNG_MAP_STATUS_INVALID
;
30 name_copy
= strdup(name
);
32 status
= LTTNG_MAP_STATUS_ERROR
;
38 map
->name
= name_copy
;
41 status
= LTTNG_MAP_STATUS_OK
;
46 enum lttng_map_status
lttng_map_get_name(const struct lttng_map
*map
,
49 enum lttng_map_status status
;
52 status
= LTTNG_MAP_STATUS_INVALID
;
57 status
= LTTNG_MAP_STATUS_UNSET
;
61 status
= LTTNG_MAP_STATUS_OK
;
66 enum lttng_map_status
lttng_map_create(const char *name
,
67 unsigned int dimension_count
,
68 uint64_t *dimension_sizes
,
69 enum lttng_domain_type domain
,
70 enum lttng_buffer_type buffer_type
,
71 enum lttng_map_bitness bitness
,
72 enum lttng_map_boundary_policy boundary_policy
,
74 struct lttng_map
**map_out
)
76 enum lttng_map_status status
;
77 struct lttng_map
*map
;
79 if (dimension_count
!= 1) {
80 status
= LTTNG_MAP_STATUS_INVALID
;
84 map
= zmalloc(sizeof(struct lttng_map
));
86 status
= LTTNG_MAP_STATUS_ERROR
;
91 status
= lttng_map_set_name(map
, name
);
92 if (status
!= LTTNG_MAP_STATUS_OK
) {
99 map
->dimension_count
= dimension_count
;
100 map
->dimension_sizes
= zmalloc(
101 sizeof(*map
->dimension_sizes
) * dimension_count
);
102 if (!map
->dimension_sizes
) {
103 status
= LTTNG_MAP_STATUS_ERROR
;
107 memcpy(map
->dimension_sizes
, dimension_sizes
,
108 sizeof(*map
->dimension_sizes
) * dimension_count
);
110 map
->domain
= domain
;
111 map
->buffer_type
= buffer_type
;
112 map
->bitness
= bitness
;
113 map
->boundary_policy
= boundary_policy
;
114 map
->coalesce_hits
= coalesce_hits
;
116 lttng_map_set_is_enabled(map
, true);
118 urcu_ref_init(&map
->ref
);
122 status
= LTTNG_MAP_STATUS_OK
;
133 unsigned int lttng_map_get_dimension_count(
134 const struct lttng_map
*map
)
138 return map
->dimension_count
;
141 enum lttng_map_status
lttng_map_get_dimension_length(
142 const struct lttng_map
*map
, unsigned int dimension
,
143 uint64_t *dimension_length
)
145 enum lttng_map_status status
;
149 if (dimension
>= map
->dimension_count
) {
150 status
= LTTNG_MAP_STATUS_INVALID
;
154 *dimension_length
= map
->dimension_sizes
[dimension
];
156 status
= LTTNG_MAP_STATUS_OK
;
161 enum lttng_map_bitness
lttng_map_get_bitness(
162 const struct lttng_map
*map
)
169 enum lttng_domain_type
lttng_map_get_domain(
170 const struct lttng_map
*map
)
177 enum lttng_buffer_type
lttng_map_get_buffer_type(
178 const struct lttng_map
*map
)
182 return map
->buffer_type
;
185 enum lttng_map_boundary_policy
lttng_map_get_boundary_policy(
186 const struct lttng_map
*map
)
190 return map
->boundary_policy
;
193 bool lttng_map_get_coalesce_hits(const struct lttng_map
*map
)
197 return map
->coalesce_hits
;
201 int lttng_map_serialize(const struct lttng_map
*map
,
202 struct lttng_payload
*payload
)
205 size_t header_offset
, size_before_payload
, size_name
;
206 struct lttng_map_comm map_comm
= {};
207 struct lttng_map_comm
*header
;
209 if (map
->name
!= NULL
) {
210 size_name
= strlen(map
->name
) + 1;
215 map_comm
.name_length
= size_name
;
216 map_comm
.is_enabled
= LTTNG_OPTIONAL_GET(map
->is_enabled
);
217 map_comm
.bitness
= map
->bitness
;
218 map_comm
.domain
= map
->domain
;
219 map_comm
.buffer_type
= map
->buffer_type
;
220 map_comm
.boundary_policy
= map
->boundary_policy
;
221 map_comm
.dimension_count
= map
->dimension_count
;
222 map_comm
.coalesce_hits
= map
->coalesce_hits
;
224 header_offset
= payload
->buffer
.size
;
226 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &map_comm
,
232 size_before_payload
= payload
->buffer
.size
;
235 ret
= lttng_dynamic_buffer_append(
236 &payload
->buffer
, map
->name
, size_name
);
241 ret
= lttng_dynamic_buffer_append(
242 &payload
->buffer
, map
->dimension_sizes
,
243 sizeof(*map
->dimension_sizes
) * map
->dimension_count
);
248 /* Update payload size. */
249 header
= (typeof(header
)) (payload
->buffer
.data
+ header_offset
);
250 header
->length
= payload
->buffer
.size
- size_before_payload
;
257 ssize_t
lttng_map_create_from_payload(
258 struct lttng_payload_view
*src_view
,
259 struct lttng_map
**map
)
261 ssize_t ret
, offset
= 0;
262 const struct lttng_map_comm
*map_comm
;
263 enum lttng_map_status status
;
264 unsigned int dimension_count
;
265 uint64_t *dimension_sizes
= NULL
;
267 const char *name
= NULL
;
268 enum lttng_domain_type domain
;
269 enum lttng_buffer_type buffer_type
;
270 enum lttng_map_bitness bitness
;
271 enum lttng_map_boundary_policy boundary_policy
;
273 if (!src_view
|| !map
) {
278 map_comm
= (typeof(map_comm
)) src_view
->buffer
.data
;
279 offset
+= sizeof(*map_comm
);
281 domain
= map_comm
->domain
;
282 buffer_type
= map_comm
->buffer_type
;
283 bitness
= map_comm
->bitness
;
284 boundary_policy
= map_comm
->boundary_policy
;
285 dimension_count
= map_comm
->dimension_count
;
286 coalesce_hits
= map_comm
->coalesce_hits
;
288 if (map_comm
->name_length
!= 0) {
289 struct lttng_payload_view name_view
=
290 lttng_payload_view_from_view(
292 map_comm
->name_length
);
294 name
= name_view
.buffer
.data
;
295 if (!lttng_buffer_view_contains_string(&name_view
.buffer
,
296 name
, map_comm
->name_length
)){
300 offset
+= map_comm
->name_length
;
303 size_t map_dim_sizes_len
= sizeof(*(*map
)->dimension_sizes
) * dimension_count
;
305 struct lttng_payload_view dimension_sizes_view
=
306 lttng_payload_view_from_view(src_view
, offset
,
309 dimension_sizes
= zmalloc(map_dim_sizes_len
);
310 if (!dimension_sizes
) {
315 memcpy(dimension_sizes
, dimension_sizes_view
.buffer
.data
,
318 offset
+= map_dim_sizes_len
;
320 status
= lttng_map_create(name
, dimension_count
,
321 dimension_sizes
, domain
, buffer_type
, bitness
,
322 boundary_policy
, coalesce_hits
, map
);
323 if (status
!= LTTNG_MAP_STATUS_OK
) {
328 lttng_map_set_is_enabled(*map
, map_comm
->is_enabled
);
333 free(dimension_sizes
);
338 void lttng_map_set_is_enabled(struct lttng_map
*map
, bool enabled
)
342 LTTNG_OPTIONAL_SET(&map
->is_enabled
, enabled
);
345 int lttng_map_get_is_enabled(const struct lttng_map
*map
)
348 return (int) LTTNG_OPTIONAL_GET(map
->is_enabled
);
352 void lttng_map_get(struct lttng_map
*map
)
354 urcu_ref_get(&map
->ref
);
357 static void map_destroy_ref(struct urcu_ref
*ref
)
359 struct lttng_map
*map
= container_of(ref
, struct lttng_map
, ref
);
361 free(map
->dimension_sizes
);
368 void lttng_map_put(struct lttng_map
*map
)
374 urcu_ref_put(&map
->ref
, map_destroy_ref
);
378 void lttng_map_destroy(struct lttng_map
*map
)
383 static void delete_map_array_element(void *ptr
)
385 struct lttng_map
*map
= ptr
;
391 struct lttng_map_list
*lttng_map_list_create(void)
393 struct lttng_map_list
*map_list
= NULL
;
395 map_list
= zmalloc(sizeof(*map_list
));
400 lttng_dynamic_pointer_array_init(&map_list
->array
,
401 delete_map_array_element
);
408 enum lttng_map_status
lttng_map_list_add(struct lttng_map_list
*map_list
,
409 struct lttng_map
*map
)
411 enum lttng_map_status status
;
419 ret
= lttng_dynamic_pointer_array_add_pointer(&map_list
->array
, map
);
422 status
= LTTNG_MAP_STATUS_ERROR
;
425 status
= LTTNG_MAP_STATUS_OK
;
432 ssize_t
lttng_map_list_create_from_payload(struct lttng_payload_view
*src_view
,
433 struct lttng_map_list
**map_list
)
436 ssize_t ret
, offset
= 0;
437 const struct lttng_map_list_comm
*map_list_comm
;
438 struct lttng_map_list
*local_map_list
= NULL
;
440 map_list_comm
= (typeof(map_list_comm
)) src_view
->buffer
.data
;
441 offset
+= sizeof(*map_list_comm
);
443 local_map_list
= lttng_map_list_create();
444 if (!local_map_list
) {
449 for (i
= 0; i
< map_list_comm
->count
; i
++) {
450 struct lttng_map
*map
= NULL
;
451 struct lttng_payload_view map_view
=
452 lttng_payload_view_from_view(src_view
, offset
, -1);
455 map_size
= lttng_map_create_from_payload(&map_view
, &map
);
461 /* Transfer ownership of the map to the collection. */
462 ret
= lttng_map_list_add(local_map_list
, map
);
472 /* Pass ownership to caller. */
473 *map_list
= local_map_list
;
474 local_map_list
= NULL
;
478 lttng_map_list_destroy(local_map_list
);
483 int lttng_map_list_serialize(const struct lttng_map_list
*map_list
,
484 struct lttng_payload
*payload
)
487 unsigned int i
, count
;
488 enum lttng_map_status status
;
489 struct lttng_map_list_comm map_list_comm
= {};
491 status
= lttng_map_list_get_count(map_list
, &count
);
492 if (status
!= LTTNG_MAP_STATUS_OK
) {
493 ret
= LTTNG_ERR_INVALID
;
497 map_list_comm
.count
= count
;
498 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &map_list_comm
,
499 sizeof(map_list_comm
));
503 for (i
= 0; i
< count
; i
++) {
504 const struct lttng_map
*map
=
505 lttng_map_list_get_at_index(map_list
, i
);
509 ret
= lttng_map_serialize(map
, payload
);
519 const struct lttng_map
*lttng_map_list_get_at_index(
520 const struct lttng_map_list
*map_list
, unsigned int index
)
522 struct lttng_map
*map
= NULL
;
525 if (index
>= lttng_dynamic_pointer_array_get_count(&map_list
->array
)) {
529 map
= (struct lttng_map
*)
530 lttng_dynamic_pointer_array_get_pointer(
531 &map_list
->array
, index
);
536 enum lttng_map_status
lttng_map_list_get_count(
537 const struct lttng_map_list
*map_list
, unsigned int *count
)
539 enum lttng_map_status status
= LTTNG_MAP_STATUS_OK
;
541 if (!map_list
|| !count
) {
542 status
= LTTNG_MAP_STATUS_INVALID
;
546 *count
= lttng_dynamic_pointer_array_get_count(&map_list
->array
);
547 status
= LTTNG_MAP_STATUS_OK
;
552 void lttng_map_list_destroy(struct lttng_map_list
*map_list
)
558 lttng_dynamic_pointer_array_reset(&map_list
->array
);
562 struct lttng_map_key_value_pair
*lttng_map_key_value_pair_create(const char *key
,
565 struct lttng_map_key_value_pair
*key_value
;
567 key_value
= zmalloc(sizeof(struct lttng_map_key_value_pair
));
572 key_value
->key
= strdup(key
);
573 if (!key_value
->key
) {
578 key_value
->value
= value
;
584 enum lttng_map_status
lttng_map_key_value_pair_get_key(
585 const struct lttng_map_key_value_pair
*key_value
,
589 assert(key_value
->key
);
591 *key
= key_value
->key
;
592 return LTTNG_MAP_STATUS_OK
;
595 enum lttng_map_status
lttng_map_key_value_pair_get_value(
596 const struct lttng_map_key_value_pair
*key_value
,
600 *value
= key_value
->value
;
601 return LTTNG_MAP_STATUS_OK
;
605 void lttng_map_key_value_pair_set_has_overflowed(
606 struct lttng_map_key_value_pair
*key_value
)
610 key_value
->has_overflowed
= true;
614 void lttng_map_key_value_pair_set_has_underflowed(
615 struct lttng_map_key_value_pair
*key_value
)
619 key_value
->has_underflowed
= true;
622 bool lttng_map_key_value_pair_get_has_overflowed(
623 const struct lttng_map_key_value_pair
*key_value
)
627 return key_value
->has_overflowed
;
630 bool lttng_map_key_value_pair_get_has_underflowed(
631 const struct lttng_map_key_value_pair
*key_value
)
635 return key_value
->has_underflowed
;
639 ssize_t
lttng_map_key_value_pair_create_from_payload(
640 struct lttng_payload_view
*src_view
,
641 struct lttng_map_key_value_pair
**key_value
)
643 const struct lttng_map_key_value_pair_comm
*kv_pair_comm
;
644 struct lttng_map_key_value_pair
*kv_pair
;
645 ssize_t ret
, offset
= 0;
649 if (!src_view
|| !key_value
) {
654 kv_pair_comm
= (typeof(kv_pair_comm
)) src_view
->buffer
.data
;
655 offset
+= sizeof(*kv_pair_comm
);
657 if (kv_pair_comm
->key_length
== 0) {
662 value
= kv_pair_comm
->value
;
664 struct lttng_payload_view key_view
=
665 lttng_payload_view_from_view(src_view
, offset
,
666 kv_pair_comm
->key_length
);
667 key
= key_view
.buffer
.data
;
668 if (!lttng_buffer_view_contains_string(&key_view
.buffer
,
669 key
, kv_pair_comm
->key_length
)) {
674 offset
+= kv_pair_comm
->key_length
;
676 kv_pair
= lttng_map_key_value_pair_create(key
, value
);
682 kv_pair
->has_overflowed
= kv_pair_comm
->has_overflowed
;
683 kv_pair
->has_underflowed
= kv_pair_comm
->has_underflowed
;
685 *key_value
= kv_pair
;
694 int lttng_map_key_value_pair_serialize(
695 const struct lttng_map_key_value_pair
*key_value
,
696 struct lttng_payload
*payload
)
700 struct lttng_map_key_value_pair_comm kv_pair_comm
= {0};
703 assert(key_value
->key
);
705 key_len
= strlen(key_value
->key
) + 1;
707 kv_pair_comm
.key_length
= key_len
;
708 kv_pair_comm
.value
= key_value
->value
;
709 kv_pair_comm
.has_overflowed
= key_value
->has_overflowed
;
710 kv_pair_comm
.has_underflowed
= key_value
->has_underflowed
;
712 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &kv_pair_comm
,
713 sizeof(kv_pair_comm
));
719 ret
= lttng_dynamic_buffer_append(
720 &payload
->buffer
, key_value
->key
, key_len
);
729 void lttng_map_key_value_pair_destroy(struct lttng_map_key_value_pair
*key_value
)
735 free(key_value
->key
);
739 static void delete_map_key_value_pair_array_element(void *ptr
)
741 struct lttng_map_key_value_pair
*key_value
= ptr
;
742 lttng_map_key_value_pair_destroy(key_value
);
746 struct lttng_map_key_value_pair_list
*lttng_map_key_value_pair_list_create(
747 enum lttng_map_key_value_pair_list_type type
,
748 bool summed_all_cpus
)
750 struct lttng_map_key_value_pair_list
*map_key_values
= NULL
;
752 map_key_values
= zmalloc(sizeof(*map_key_values
));
753 if (!map_key_values
) {
757 map_key_values
->type
= type
;
758 map_key_values
->summed_all_cpus
= summed_all_cpus
;
760 lttng_dynamic_pointer_array_init(&map_key_values
->array
,
761 delete_map_key_value_pair_array_element
);
764 return map_key_values
;
768 enum lttng_map_status
lttng_map_key_value_pair_list_set_identifier(
769 struct lttng_map_key_value_pair_list
*kv_pair_list
,
772 enum lttng_map_status status
;
773 assert(kv_pair_list
);
775 switch (kv_pair_list
->type
) {
776 case LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_PID
:
777 case LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_UID
:
778 kv_pair_list
->id
= identifier
;
779 status
= LTTNG_MAP_STATUS_OK
;
781 case LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_PID_AGGREGATED
:
782 ERR("Cannot set an identifier for an UST per-pid aggregation key value pair list");
783 status
= LTTNG_MAP_STATUS_INVALID
;
785 case LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_KERNEL
:
786 ERR("Cannot set an identifier for a kernel key value pair list");
787 status
= LTTNG_MAP_STATUS_INVALID
;
790 ERR("Unknown key value par list type %d", kv_pair_list
->type
);
797 bool lttng_map_key_value_pair_list_get_summed_all_cpu(
798 const struct lttng_map_key_value_pair_list
*kv_pair_list
)
800 assert(kv_pair_list
);
802 return kv_pair_list
->summed_all_cpus
;
806 enum lttng_map_status
lttng_map_key_value_pair_list_set_cpu(
807 struct lttng_map_key_value_pair_list
*kv_pair_list
,
810 assert(kv_pair_list
);
812 kv_pair_list
->cpu
= cpu
;
814 return LTTNG_MAP_STATUS_OK
;
817 uint64_t lttng_map_key_value_pair_list_get_cpu(
818 const struct lttng_map_key_value_pair_list
*kv_pair_list
)
820 assert(kv_pair_list
);
822 return kv_pair_list
->cpu
;
825 enum lttng_map_key_value_pair_list_type
lttng_map_key_value_pair_list_get_type(
826 const struct lttng_map_key_value_pair_list
*kv_pair_list
)
828 assert(kv_pair_list
);
830 return kv_pair_list
->type
;
834 enum lttng_map_status
lttng_map_key_value_pair_list_append_key_value(
835 struct lttng_map_key_value_pair_list
*kv_pair_list
,
836 struct lttng_map_key_value_pair
*key_value
)
839 enum lttng_map_status status
;
841 assert(kv_pair_list
);
844 ret
= lttng_dynamic_pointer_array_add_pointer(&kv_pair_list
->array
,
847 status
= LTTNG_MAP_STATUS_ERROR
;
851 status
= LTTNG_MAP_STATUS_OK
;
857 uint64_t lttng_map_key_value_pair_list_get_identifer(
858 const struct lttng_map_key_value_pair_list
*kv_pair_list
)
860 assert(kv_pair_list
);
862 switch (kv_pair_list
->type
) {
863 case LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_PID
:
864 case LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_UID
:
866 case LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_PID_AGGREGATED
:
867 ERR("No identifier for UST per-pid aggregation key value pair lists");
870 case LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_KERNEL
:
871 ERR("No identifier for kernel key value pair lists");
875 ERR("Unknown key value par list type %d", kv_pair_list
->type
);
879 return kv_pair_list
->id
;
882 const struct lttng_map_key_value_pair
*lttng_map_key_value_pair_list_get_at_index(
883 const struct lttng_map_key_value_pair_list
*kv_pair_list
,
886 struct lttng_map_key_value_pair
*key_value
= NULL
;
888 assert(kv_pair_list
);
889 if (index
>= lttng_dynamic_pointer_array_get_count(&kv_pair_list
->array
)) {
893 key_value
= (struct lttng_map_key_value_pair
*)
894 lttng_dynamic_pointer_array_get_pointer(
895 &kv_pair_list
->array
, index
);
900 enum lttng_map_status
lttng_map_key_value_pair_list_get_count(
901 const struct lttng_map_key_value_pair_list
*kv_pair_list
,
904 enum lttng_map_status status
;
906 if (!kv_pair_list
|| !count
) {
907 status
= LTTNG_MAP_STATUS_INVALID
;;
911 *count
= lttng_dynamic_pointer_array_get_count(&kv_pair_list
->array
);
913 status
= LTTNG_MAP_STATUS_OK
;
918 void lttng_map_key_value_pair_list_destroy(struct lttng_map_key_value_pair_list
*kv_pair_list
)
924 lttng_dynamic_pointer_array_reset(&kv_pair_list
->array
);
928 int lttng_map_key_value_pair_list_serialize(
929 const struct lttng_map_key_value_pair_list
*kv_pair_list
,
930 struct lttng_payload
*payload
)
933 unsigned int i
, count
;
934 enum lttng_map_status status
;
935 struct lttng_map_key_value_pair_list_comm kv_pair_list_comm
= {};
937 kv_pair_list_comm
.id
= kv_pair_list
->id
;
938 kv_pair_list_comm
.cpu
= kv_pair_list
->cpu
;
939 kv_pair_list_comm
.type
= (uint8_t) kv_pair_list
->type
;
940 kv_pair_list_comm
.summed_all_cpus
= (uint8_t) kv_pair_list
->summed_all_cpus
;
942 status
= lttng_map_key_value_pair_list_get_count(kv_pair_list
, &count
);
943 if (status
!= LTTNG_MAP_STATUS_OK
) {
944 ret
= LTTNG_ERR_INVALID
;
948 kv_pair_list_comm
.count
= count
;
949 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &kv_pair_list_comm
,
950 sizeof(kv_pair_list_comm
));
954 for (i
= 0; i
< count
; i
++) {
955 const struct lttng_map_key_value_pair
*kv_pair
=
956 lttng_map_key_value_pair_list_get_at_index(kv_pair_list
, i
);
960 ret
= lttng_map_key_value_pair_serialize(kv_pair
, payload
);
971 ssize_t
lttng_map_key_value_pair_list_create_from_payload(
972 struct lttng_payload_view
*src_view
,
973 struct lttng_map_key_value_pair_list
**kv_pair_list
)
975 ssize_t ret
, offset
= 0;
977 enum lttng_map_status status
;
978 const struct lttng_map_key_value_pair_list_comm
*kv_pair_list_comm
;
979 struct lttng_map_key_value_pair_list
*local_key_values
= NULL
;
981 kv_pair_list_comm
= (typeof(kv_pair_list_comm
)) src_view
->buffer
.data
;
982 offset
+= sizeof(*kv_pair_list_comm
);
984 local_key_values
= lttng_map_key_value_pair_list_create(
985 kv_pair_list_comm
->type
, kv_pair_list_comm
->summed_all_cpus
);
986 if (!local_key_values
) {
991 local_key_values
->cpu
= kv_pair_list_comm
->cpu
;
993 switch (lttng_map_key_value_pair_list_get_type(local_key_values
)) {
994 case LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_PID
:
995 case LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_UID
:
996 status
= lttng_map_key_value_pair_list_set_identifier(local_key_values
,
997 kv_pair_list_comm
->id
);
998 if (status
!= LTTNG_MAP_STATUS_OK
) {
1007 for (i
= 0; i
< kv_pair_list_comm
->count
; i
++) {
1008 struct lttng_map_key_value_pair
*kv_pair
= NULL
;
1009 struct lttng_payload_view kv_view
=
1010 lttng_payload_view_from_view(src_view
, offset
, -1);
1013 kv_size
= lttng_map_key_value_pair_create_from_payload(
1014 &kv_view
, &kv_pair
);
1020 /* Transfer ownership of the key-value to the collection. */
1021 status
= lttng_map_key_value_pair_list_append_key_value(local_key_values
,
1023 if (status
!= LTTNG_MAP_STATUS_OK
) {
1031 /* Pass ownership to caller. */
1032 *kv_pair_list
= local_key_values
;
1033 local_key_values
= NULL
;
1037 lttng_map_key_value_pair_list_destroy(local_key_values
);
1041 static void delete_map_key_value_pair_list_array_element(void *ptr
)
1043 struct lttng_map_key_value_pair_list
*kv_list
= ptr
;
1044 lttng_map_key_value_pair_list_destroy(kv_list
);
1048 struct lttng_map_content
*lttng_map_content_create(
1049 enum lttng_buffer_type type
)
1051 struct lttng_map_content
*map_content
= NULL
;
1053 map_content
= zmalloc(sizeof(*map_content
));
1058 map_content
->type
= type
;
1060 lttng_dynamic_pointer_array_init(&map_content
->array
,
1061 delete_map_key_value_pair_list_array_element
);
1067 enum lttng_map_status
lttng_map_content_get_count(
1068 const struct lttng_map_content
*map_content
,
1069 unsigned int *count
)
1071 enum lttng_map_status status
= LTTNG_MAP_STATUS_OK
;
1073 if (!map_content
|| !count
) {
1074 status
= LTTNG_MAP_STATUS_INVALID
;
1078 *count
= lttng_dynamic_pointer_array_get_count(&map_content
->array
);
1079 status
= LTTNG_MAP_STATUS_OK
;
1084 enum lttng_buffer_type
lttng_map_content_get_buffer_type(
1085 const struct lttng_map_content
*map_content
)
1087 assert(map_content
);
1089 return map_content
->type
;
1093 enum lttng_map_status
lttng_map_content_append_key_value_list(
1094 struct lttng_map_content
*map_content
,
1095 struct lttng_map_key_value_pair_list
*kv_list
)
1098 enum lttng_map_status status
;
1100 assert(map_content
);
1103 ret
= lttng_dynamic_pointer_array_add_pointer(&map_content
->array
,
1106 status
= LTTNG_MAP_STATUS_ERROR
;
1110 status
= LTTNG_MAP_STATUS_OK
;
1116 const struct lttng_map_key_value_pair_list
*lttng_map_content_get_at_index(
1117 const struct lttng_map_content
*map_content
,
1120 struct lttng_map_key_value_pair_list
*kv_pair_list
= NULL
;
1122 assert(map_content
);
1123 if (index
>= lttng_dynamic_pointer_array_get_count(&map_content
->array
)) {
1127 kv_pair_list
= (struct lttng_map_key_value_pair_list
*)
1128 lttng_dynamic_pointer_array_get_pointer(
1129 &map_content
->array
, index
);
1131 return kv_pair_list
;
1135 ssize_t
lttng_map_content_create_from_payload(
1136 struct lttng_payload_view
*src_view
,
1137 struct lttng_map_content
**map_content
)
1139 ssize_t ret
, offset
= 0;
1141 struct lttng_map_content_comm
*map_content_comm
;
1142 struct lttng_map_content
*local_map_content
;
1144 map_content_comm
= (typeof(map_content_comm
)) src_view
->buffer
.data
;
1145 offset
+= sizeof(*map_content_comm
);
1147 local_map_content
= lttng_map_content_create(map_content_comm
->type
);
1148 if (!local_map_content
) {
1153 for (i
= 0; i
< map_content_comm
->count
; i
++) {
1154 struct lttng_map_key_value_pair_list
*kv_pair_list
= NULL
;
1155 struct lttng_payload_view kv_list_view
=
1156 lttng_payload_view_from_view(src_view
, offset
, -1);
1157 ssize_t kv_list_size
;
1159 kv_list_size
= lttng_map_key_value_pair_list_create_from_payload(
1160 &kv_list_view
, &kv_pair_list
);
1161 if (kv_list_size
< 0) {
1166 /* Transfer ownership of the key-value to the collection. */
1167 ret
= lttng_map_content_append_key_value_list(local_map_content
,
1174 offset
+= kv_list_size
;
1177 /* Pass ownership to caller. */
1178 *map_content
= local_map_content
;
1179 local_map_content
= NULL
;
1183 lttng_map_content_destroy(local_map_content
);
1188 int lttng_map_content_serialize(
1189 const struct lttng_map_content
*map_content
,
1190 struct lttng_payload
*payload
)
1193 unsigned int i
, count
;
1194 enum lttng_map_status status
;
1195 struct lttng_map_content_comm map_content_comm
= {};
1197 status
= lttng_map_content_get_count(map_content
, &count
);
1198 if (status
!= LTTNG_MAP_STATUS_OK
) {
1199 ret
= LTTNG_ERR_INVALID
;
1203 map_content_comm
.count
= count
;
1204 map_content_comm
.type
= lttng_map_content_get_buffer_type(map_content
);
1206 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &map_content_comm
,
1207 sizeof(map_content_comm
));
1211 for (i
= 0; i
< count
; i
++) {
1212 const struct lttng_map_key_value_pair_list
*kv_pair_list
=
1213 lttng_map_content_get_at_index(map_content
, i
);
1215 assert(kv_pair_list
);
1217 ret
= lttng_map_key_value_pair_list_serialize(kv_pair_list
, payload
);
1227 void lttng_map_content_destroy(struct lttng_map_content
*map_content
)
1233 lttng_dynamic_pointer_array_reset(&map_content
->array
);