SoW-2020-0003: Trace Hit Counters
[lttng-tools.git] / src / common / map.c
1 /*
2 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <assert.h>
9 #include <string.h>
10
11 #include <common/error.h>
12 #include <common/macros.h>
13 #include <common/optional.h>
14 #include <common/payload.h>
15
16 #include <lttng/lttng.h>
17 #include <lttng/map/map-internal.h>
18
19 enum lttng_map_status lttng_map_set_name(struct lttng_map *map,
20 const char *name)
21 {
22 char *name_copy = NULL;
23 enum lttng_map_status status;
24
25 if (!map || !name || strlen(name) == 0) {
26 status = LTTNG_MAP_STATUS_INVALID;
27 goto end;
28 }
29
30 name_copy = strdup(name);
31 if (!name_copy) {
32 status = LTTNG_MAP_STATUS_ERROR;
33 goto end;
34 }
35
36 free(map->name);
37
38 map->name = name_copy;
39 name_copy = NULL;
40
41 status = LTTNG_MAP_STATUS_OK;
42 end:
43 return status;
44 }
45
46 enum lttng_map_status lttng_map_get_name(const struct lttng_map *map,
47 const char **name)
48 {
49 enum lttng_map_status status;
50
51 if (!map || !name) {
52 status = LTTNG_MAP_STATUS_INVALID;
53 goto end;
54 }
55
56 if (!map->name) {
57 status = LTTNG_MAP_STATUS_UNSET;
58 }
59
60 *name = map->name;
61 status = LTTNG_MAP_STATUS_OK;
62 end:
63 return status;
64 }
65
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,
73 bool coalesce_hits,
74 struct lttng_map **map_out)
75 {
76 enum lttng_map_status status;
77 struct lttng_map *map;
78
79 if (dimension_count != 1) {
80 status = LTTNG_MAP_STATUS_INVALID;
81 goto end;
82 }
83
84 map = zmalloc(sizeof(struct lttng_map));
85 if (!map) {
86 status = LTTNG_MAP_STATUS_ERROR;
87 goto end;
88 }
89
90 if (name) {
91 status = lttng_map_set_name(map, name);
92 if (status != LTTNG_MAP_STATUS_OK) {
93 goto free_map;
94 }
95 } else {
96 map->name = NULL;
97 }
98
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;
104 goto free_name;
105 }
106
107 memcpy(map->dimension_sizes, dimension_sizes,
108 sizeof(*map->dimension_sizes) * dimension_count);
109
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;
115
116 lttng_map_set_is_enabled(map, true);
117
118 urcu_ref_init(&map->ref);
119
120 *map_out = map;
121
122 status = LTTNG_MAP_STATUS_OK;
123
124 goto end;
125 free_name:
126 free(map->name);
127 free_map:
128 free(map);
129 end:
130 return status;
131 }
132
133 unsigned int lttng_map_get_dimension_count(
134 const struct lttng_map *map)
135 {
136 assert(map);
137
138 return map->dimension_count;
139 }
140
141 enum lttng_map_status lttng_map_get_dimension_length(
142 const struct lttng_map *map, unsigned int dimension,
143 uint64_t *dimension_length)
144 {
145 enum lttng_map_status status;
146
147 assert(map);
148
149 if (dimension >= map->dimension_count) {
150 status = LTTNG_MAP_STATUS_INVALID;
151 goto end;
152 }
153
154 *dimension_length = map->dimension_sizes[dimension];
155
156 status = LTTNG_MAP_STATUS_OK;
157 end:
158 return status;
159 }
160
161 enum lttng_map_bitness lttng_map_get_bitness(
162 const struct lttng_map *map)
163 {
164 assert(map);
165
166 return map->bitness;
167 }
168
169 enum lttng_domain_type lttng_map_get_domain(
170 const struct lttng_map *map)
171 {
172 assert(map);
173
174 return map->domain;
175 }
176
177 enum lttng_buffer_type lttng_map_get_buffer_type(
178 const struct lttng_map *map)
179 {
180 assert(map);
181
182 return map->buffer_type;
183 }
184
185 enum lttng_map_boundary_policy lttng_map_get_boundary_policy(
186 const struct lttng_map *map)
187 {
188 assert(map);
189
190 return map->boundary_policy;
191 }
192
193 bool lttng_map_get_coalesce_hits(const struct lttng_map *map)
194 {
195 assert(map);
196
197 return map->coalesce_hits;
198 }
199
200 LTTNG_HIDDEN
201 int lttng_map_serialize(const struct lttng_map *map,
202 struct lttng_payload *payload)
203 {
204 int ret;
205 size_t header_offset, size_before_payload, size_name;
206 struct lttng_map_comm map_comm = {};
207 struct lttng_map_comm *header;
208
209 if (map->name != NULL) {
210 size_name = strlen(map->name) + 1;
211 } else {
212 size_name = 0;
213 }
214
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;
223
224 header_offset = payload->buffer.size;
225
226 ret = lttng_dynamic_buffer_append(&payload->buffer, &map_comm,
227 sizeof(map_comm));
228 if (ret) {
229 goto end;
230 }
231
232 size_before_payload = payload->buffer.size;
233
234 /* map name */
235 ret = lttng_dynamic_buffer_append(
236 &payload->buffer, map->name, size_name);
237 if (ret) {
238 goto end;
239 }
240
241 ret = lttng_dynamic_buffer_append(
242 &payload->buffer, map->dimension_sizes,
243 sizeof(*map->dimension_sizes) * map->dimension_count);
244 if (ret) {
245 goto end;
246 }
247
248 /* Update payload size. */
249 header = (typeof(header)) (payload->buffer.data + header_offset);
250 header->length = payload->buffer.size - size_before_payload;
251
252 end:
253 return ret;
254 }
255
256 LTTNG_HIDDEN
257 ssize_t lttng_map_create_from_payload(
258 struct lttng_payload_view *src_view,
259 struct lttng_map **map)
260 {
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;
266 bool coalesce_hits;
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;
272
273 if (!src_view || !map) {
274 ret = -1;
275 goto end;
276 }
277
278 map_comm = (typeof(map_comm)) src_view->buffer.data;
279 offset += sizeof(*map_comm);
280
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;
287
288 if (map_comm->name_length != 0) {
289 struct lttng_payload_view name_view =
290 lttng_payload_view_from_view(
291 src_view, offset,
292 map_comm->name_length);
293
294 name = name_view.buffer.data;
295 if (!lttng_buffer_view_contains_string(&name_view.buffer,
296 name, map_comm->name_length)){
297 ret = -1;
298 goto end;
299 }
300 offset += map_comm->name_length;
301 }
302
303 size_t map_dim_sizes_len = sizeof(*(*map)->dimension_sizes) * dimension_count;
304
305 struct lttng_payload_view dimension_sizes_view =
306 lttng_payload_view_from_view(src_view, offset,
307 map_dim_sizes_len);
308
309 dimension_sizes = zmalloc(map_dim_sizes_len);
310 if (!dimension_sizes) {
311 ret = -1;
312 goto end;
313 }
314
315 memcpy(dimension_sizes, dimension_sizes_view.buffer.data,
316 map_dim_sizes_len);
317
318 offset += map_dim_sizes_len;
319
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) {
324 ret = -1;
325 goto end;
326 }
327
328 lttng_map_set_is_enabled(*map, map_comm->is_enabled);
329
330 ret = offset;
331
332 end:
333 free(dimension_sizes);
334 return ret;
335 }
336
337 LTTNG_HIDDEN
338 void lttng_map_set_is_enabled(struct lttng_map *map, bool enabled)
339 {
340 assert(map);
341
342 LTTNG_OPTIONAL_SET(&map->is_enabled, enabled);
343 }
344
345 int lttng_map_get_is_enabled(const struct lttng_map *map)
346 {
347 assert(map);
348 return (int) LTTNG_OPTIONAL_GET(map->is_enabled);
349 }
350
351 LTTNG_HIDDEN
352 void lttng_map_get(struct lttng_map *map)
353 {
354 urcu_ref_get(&map->ref);
355 }
356
357 static void map_destroy_ref(struct urcu_ref *ref)
358 {
359 struct lttng_map *map = container_of(ref, struct lttng_map, ref);
360
361 free(map->dimension_sizes);
362 free(map->name);
363 free(map);
364
365 }
366
367 LTTNG_HIDDEN
368 void lttng_map_put(struct lttng_map *map)
369 {
370 if (!map) {
371 return;
372 }
373
374 urcu_ref_put(&map->ref , map_destroy_ref);
375 }
376
377
378 void lttng_map_destroy(struct lttng_map *map)
379 {
380 lttng_map_put(map);
381 }
382
383 static void delete_map_array_element(void *ptr)
384 {
385 struct lttng_map *map = ptr;
386
387 lttng_map_put(map);
388 }
389
390 LTTNG_HIDDEN
391 struct lttng_map_list *lttng_map_list_create(void)
392 {
393 struct lttng_map_list *map_list = NULL;
394
395 map_list = zmalloc(sizeof(*map_list));
396 if (!map_list) {
397 goto end;
398 }
399
400 lttng_dynamic_pointer_array_init(&map_list->array,
401 delete_map_array_element);
402
403 end:
404 return map_list;
405 }
406
407 LTTNG_HIDDEN
408 enum lttng_map_status lttng_map_list_add(struct lttng_map_list *map_list,
409 struct lttng_map *map)
410 {
411 enum lttng_map_status status;
412 int ret;
413
414 assert(map_list);
415 assert(map);
416
417 lttng_map_get(map);
418
419 ret = lttng_dynamic_pointer_array_add_pointer(&map_list->array, map);
420 if (ret) {
421 lttng_map_put(map);
422 status = LTTNG_MAP_STATUS_ERROR;
423 goto end;
424 }
425 status = LTTNG_MAP_STATUS_OK;
426 end:
427 return status;
428
429 }
430
431 LTTNG_HIDDEN
432 ssize_t lttng_map_list_create_from_payload(struct lttng_payload_view *src_view,
433 struct lttng_map_list **map_list)
434 {
435 unsigned int i;
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;
439
440 map_list_comm = (typeof(map_list_comm)) src_view->buffer.data;
441 offset += sizeof(*map_list_comm);
442
443 local_map_list = lttng_map_list_create();
444 if (!local_map_list) {
445 ret = -1;
446 goto end;
447 }
448
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);
453 ssize_t map_size;
454
455 map_size = lttng_map_create_from_payload(&map_view, &map);
456 if (map_size < 0) {
457 ret = map_size;
458 goto end;
459 }
460
461 /* Transfer ownership of the map to the collection. */
462 ret = lttng_map_list_add(local_map_list, map);
463 lttng_map_put(map);
464 if (ret < 0) {
465 ret = -1;
466 goto end;
467 }
468
469 offset += map_size;
470 }
471
472 /* Pass ownership to caller. */
473 *map_list = local_map_list;
474 local_map_list = NULL;
475
476 ret = offset;
477 end:
478 lttng_map_list_destroy(local_map_list);
479 return ret;
480 }
481
482 LTTNG_HIDDEN
483 int lttng_map_list_serialize(const struct lttng_map_list *map_list,
484 struct lttng_payload *payload)
485 {
486 int ret;
487 unsigned int i, count;
488 enum lttng_map_status status;
489 struct lttng_map_list_comm map_list_comm = {};
490
491 status = lttng_map_list_get_count(map_list, &count);
492 if (status != LTTNG_MAP_STATUS_OK) {
493 ret = LTTNG_ERR_INVALID;
494 goto end;
495 }
496
497 map_list_comm.count = count;
498 ret = lttng_dynamic_buffer_append(&payload->buffer, &map_list_comm,
499 sizeof(map_list_comm));
500 if (ret) {
501 goto end;
502 }
503 for (i = 0; i < count; i++) {
504 const struct lttng_map *map =
505 lttng_map_list_get_at_index(map_list, i);
506
507 assert(map);
508
509 ret = lttng_map_serialize(map, payload);
510 if (ret) {
511 goto end;
512 }
513 }
514
515 end:
516 return ret;
517 }
518
519 const struct lttng_map *lttng_map_list_get_at_index(
520 const struct lttng_map_list *map_list, unsigned int index)
521 {
522 struct lttng_map *map = NULL;
523
524 assert(map_list);
525 if (index >= lttng_dynamic_pointer_array_get_count(&map_list->array)) {
526 goto end;
527 }
528
529 map = (struct lttng_map *)
530 lttng_dynamic_pointer_array_get_pointer(
531 &map_list->array, index);
532 end:
533 return map;
534 }
535
536 enum lttng_map_status lttng_map_list_get_count(
537 const struct lttng_map_list *map_list, unsigned int *count)
538 {
539 enum lttng_map_status status = LTTNG_MAP_STATUS_OK;
540
541 if (!map_list || !count) {
542 status = LTTNG_MAP_STATUS_INVALID;
543 goto end;
544 }
545
546 *count = lttng_dynamic_pointer_array_get_count(&map_list->array);
547 status = LTTNG_MAP_STATUS_OK;
548 end:
549 return status;
550 }
551
552 void lttng_map_list_destroy(struct lttng_map_list *map_list)
553 {
554 if (!map_list) {
555 return;
556 }
557
558 lttng_dynamic_pointer_array_reset(&map_list->array);
559 free(map_list);
560 }
561
562 struct lttng_map_key_value_pair *lttng_map_key_value_pair_create(const char *key,
563 int64_t value)
564 {
565 struct lttng_map_key_value_pair *key_value;
566
567 key_value = zmalloc(sizeof(struct lttng_map_key_value_pair));
568 if (!key_value) {
569 goto end;
570 }
571
572 key_value->key = strdup(key);
573 if (!key_value->key) {
574 free(key_value);
575 key_value = NULL;
576 goto end;
577 }
578 key_value->value = value;
579
580 end:
581 return key_value;
582 }
583
584 enum lttng_map_status lttng_map_key_value_pair_get_key(
585 const struct lttng_map_key_value_pair *key_value,
586 const char **key)
587 {
588 assert(key_value);
589 assert(key_value->key);
590
591 *key = key_value->key;
592 return LTTNG_MAP_STATUS_OK;
593 }
594
595 enum lttng_map_status lttng_map_key_value_pair_get_value(
596 const struct lttng_map_key_value_pair *key_value,
597 int64_t *value)
598 {
599 assert(key_value);
600 *value = key_value->value;
601 return LTTNG_MAP_STATUS_OK;
602 }
603
604 LTTNG_HIDDEN
605 void lttng_map_key_value_pair_set_has_overflowed(
606 struct lttng_map_key_value_pair *key_value)
607 {
608 assert(key_value);
609
610 key_value->has_overflowed = true;
611 }
612
613 LTTNG_HIDDEN
614 void lttng_map_key_value_pair_set_has_underflowed(
615 struct lttng_map_key_value_pair *key_value)
616 {
617 assert(key_value);
618
619 key_value->has_underflowed = true;
620 }
621
622 bool lttng_map_key_value_pair_get_has_overflowed(
623 const struct lttng_map_key_value_pair *key_value)
624 {
625 assert(key_value);
626
627 return key_value->has_overflowed;
628 }
629
630 bool lttng_map_key_value_pair_get_has_underflowed(
631 const struct lttng_map_key_value_pair *key_value)
632 {
633 assert(key_value);
634
635 return key_value->has_underflowed;
636 }
637
638 LTTNG_HIDDEN
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)
642 {
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;
646 const char *key;
647 int64_t value;
648
649 if (!src_view || !key_value) {
650 ret = -1;
651 goto end;
652 }
653
654 kv_pair_comm = (typeof(kv_pair_comm)) src_view->buffer.data;
655 offset += sizeof(*kv_pair_comm);
656
657 if (kv_pair_comm->key_length == 0) {
658 ret = -1;
659 goto end;
660 }
661
662 value = kv_pair_comm->value;
663
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)) {
670 ret = -1;
671 goto end;
672 }
673
674 offset += kv_pair_comm->key_length;
675
676 kv_pair = lttng_map_key_value_pair_create(key, value);
677 if (!kv_pair) {
678 ret = -1;
679 goto end;
680 }
681
682 kv_pair->has_overflowed = kv_pair_comm->has_overflowed;
683 kv_pair->has_underflowed = kv_pair_comm->has_underflowed;
684
685 *key_value = kv_pair;
686
687 ret = offset;
688
689 end:
690 return ret;
691 }
692
693 LTTNG_HIDDEN
694 int lttng_map_key_value_pair_serialize(
695 const struct lttng_map_key_value_pair *key_value,
696 struct lttng_payload *payload)
697 {
698 int ret;
699 size_t key_len;
700 struct lttng_map_key_value_pair_comm kv_pair_comm = {0};
701
702 assert(key_value);
703 assert(key_value->key);
704
705 key_len = strlen(key_value->key) + 1;
706
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;
711
712 ret = lttng_dynamic_buffer_append(&payload->buffer, &kv_pair_comm,
713 sizeof(kv_pair_comm));
714 if (ret) {
715 goto end;
716 }
717
718 /* Append key.*/
719 ret = lttng_dynamic_buffer_append(
720 &payload->buffer, key_value->key, key_len);
721 if (ret) {
722 goto end;
723 }
724
725 end:
726 return ret;
727 }
728
729 void lttng_map_key_value_pair_destroy(struct lttng_map_key_value_pair *key_value)
730 {
731 if (!key_value) {
732 return;
733 }
734
735 free(key_value->key);
736 free(key_value);
737 }
738
739 static void delete_map_key_value_pair_array_element(void *ptr)
740 {
741 struct lttng_map_key_value_pair *key_value = ptr;
742 lttng_map_key_value_pair_destroy(key_value);
743 }
744
745 LTTNG_HIDDEN
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)
749 {
750 struct lttng_map_key_value_pair_list *map_key_values = NULL;
751
752 map_key_values = zmalloc(sizeof(*map_key_values));
753 if (!map_key_values) {
754 goto end;
755 }
756
757 map_key_values->type = type;
758 map_key_values->summed_all_cpus = summed_all_cpus;
759
760 lttng_dynamic_pointer_array_init(&map_key_values->array,
761 delete_map_key_value_pair_array_element);
762
763 end:
764 return map_key_values;
765 }
766
767 LTTNG_HIDDEN
768 enum lttng_map_status lttng_map_key_value_pair_list_set_identifier(
769 struct lttng_map_key_value_pair_list *kv_pair_list,
770 uint64_t identifier)
771 {
772 enum lttng_map_status status;
773 assert(kv_pair_list);
774
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;
780 break;
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;
784 break;
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;
788 break;
789 default:
790 ERR("Unknown key value par list type %d", kv_pair_list->type);
791 abort();
792 }
793
794 return status;
795 }
796
797 bool lttng_map_key_value_pair_list_get_summed_all_cpu(
798 const struct lttng_map_key_value_pair_list *kv_pair_list)
799 {
800 assert(kv_pair_list);
801
802 return kv_pair_list->summed_all_cpus;
803 }
804
805 LTTNG_HIDDEN
806 enum lttng_map_status lttng_map_key_value_pair_list_set_cpu(
807 struct lttng_map_key_value_pair_list *kv_pair_list,
808 uint64_t cpu)
809 {
810 assert(kv_pair_list);
811
812 kv_pair_list->cpu = cpu;
813
814 return LTTNG_MAP_STATUS_OK;
815 }
816
817 uint64_t lttng_map_key_value_pair_list_get_cpu(
818 const struct lttng_map_key_value_pair_list *kv_pair_list)
819 {
820 assert(kv_pair_list);
821
822 return kv_pair_list->cpu;
823 }
824
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)
827 {
828 assert(kv_pair_list);
829
830 return kv_pair_list->type;
831 }
832
833 LTTNG_HIDDEN
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)
837 {
838 int ret;
839 enum lttng_map_status status;
840
841 assert(kv_pair_list);
842 assert(key_value);
843
844 ret = lttng_dynamic_pointer_array_add_pointer(&kv_pair_list->array,
845 key_value);
846 if (ret) {
847 status = LTTNG_MAP_STATUS_ERROR;
848 goto end;
849 }
850
851 status = LTTNG_MAP_STATUS_OK;
852
853 end:
854 return status;
855 }
856
857 uint64_t lttng_map_key_value_pair_list_get_identifer(
858 const struct lttng_map_key_value_pair_list *kv_pair_list)
859 {
860 assert(kv_pair_list);
861
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:
865 break;
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");
868 abort();
869 break;
870 case LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_KERNEL:
871 ERR("No identifier for kernel key value pair lists");
872 abort();
873 break;
874 default:
875 ERR("Unknown key value par list type %d", kv_pair_list->type);
876 abort();
877 }
878
879 return kv_pair_list->id;
880 }
881
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,
884 unsigned int index)
885 {
886 struct lttng_map_key_value_pair *key_value = NULL;
887
888 assert(kv_pair_list);
889 if (index >= lttng_dynamic_pointer_array_get_count(&kv_pair_list->array)) {
890 goto end;
891 }
892
893 key_value = (struct lttng_map_key_value_pair *)
894 lttng_dynamic_pointer_array_get_pointer(
895 &kv_pair_list->array, index);
896 end:
897 return key_value;
898 }
899
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,
902 unsigned int *count)
903 {
904 enum lttng_map_status status;
905
906 if (!kv_pair_list || !count) {
907 status = LTTNG_MAP_STATUS_INVALID;;
908 goto end;
909 }
910
911 *count = lttng_dynamic_pointer_array_get_count(&kv_pair_list->array);
912
913 status = LTTNG_MAP_STATUS_OK;
914 end:
915 return status;
916 }
917
918 void lttng_map_key_value_pair_list_destroy(struct lttng_map_key_value_pair_list *kv_pair_list)
919 {
920 if (!kv_pair_list) {
921 return;
922 }
923
924 lttng_dynamic_pointer_array_reset(&kv_pair_list->array);
925 free(kv_pair_list);
926 }
927
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)
931 {
932 int ret;
933 unsigned int i, count;
934 enum lttng_map_status status;
935 struct lttng_map_key_value_pair_list_comm kv_pair_list_comm = {};
936
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;
941
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;
945 goto end;
946 }
947
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));
951 if (ret) {
952 goto end;
953 }
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);
957
958 assert(kv_pair);
959
960 ret = lttng_map_key_value_pair_serialize(kv_pair, payload);
961 if (ret) {
962 goto end;
963 }
964 }
965
966 end:
967 return ret;
968 }
969
970 LTTNG_HIDDEN
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)
974 {
975 ssize_t ret, offset = 0;
976 unsigned int i;
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;
980
981 kv_pair_list_comm = (typeof(kv_pair_list_comm)) src_view->buffer.data;
982 offset += sizeof(*kv_pair_list_comm);
983
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) {
987 ret = -1;
988 goto end;
989 }
990
991 local_key_values->cpu = kv_pair_list_comm->cpu;
992
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) {
999 ret = -1;
1000 goto end;
1001 }
1002 break;
1003 default:
1004 break;
1005 }
1006
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);
1011 ssize_t kv_size;
1012
1013 kv_size = lttng_map_key_value_pair_create_from_payload(
1014 &kv_view, &kv_pair);
1015 if (kv_size < 0) {
1016 ret = kv_size;
1017 goto end;
1018 }
1019
1020 /* Transfer ownership of the key-value to the collection. */
1021 status = lttng_map_key_value_pair_list_append_key_value(local_key_values,
1022 kv_pair);
1023 if (status != LTTNG_MAP_STATUS_OK) {
1024 ret = -1;
1025 goto end;
1026 }
1027
1028 offset += kv_size;
1029 }
1030
1031 /* Pass ownership to caller. */
1032 *kv_pair_list = local_key_values;
1033 local_key_values = NULL;
1034
1035 ret = offset;
1036 end:
1037 lttng_map_key_value_pair_list_destroy(local_key_values);
1038 return ret;
1039 }
1040
1041 static void delete_map_key_value_pair_list_array_element(void *ptr)
1042 {
1043 struct lttng_map_key_value_pair_list *kv_list = ptr;
1044 lttng_map_key_value_pair_list_destroy(kv_list);
1045 }
1046
1047 LTTNG_HIDDEN
1048 struct lttng_map_content *lttng_map_content_create(
1049 enum lttng_buffer_type type)
1050 {
1051 struct lttng_map_content *map_content = NULL;
1052
1053 map_content = zmalloc(sizeof(*map_content));
1054 if (!map_content) {
1055 goto end;
1056 }
1057
1058 map_content->type = type;
1059
1060 lttng_dynamic_pointer_array_init(&map_content->array,
1061 delete_map_key_value_pair_list_array_element);
1062
1063 end:
1064 return map_content;
1065 }
1066
1067 enum lttng_map_status lttng_map_content_get_count(
1068 const struct lttng_map_content *map_content,
1069 unsigned int *count)
1070 {
1071 enum lttng_map_status status = LTTNG_MAP_STATUS_OK;
1072
1073 if (!map_content || !count) {
1074 status = LTTNG_MAP_STATUS_INVALID;
1075 goto end;
1076 }
1077
1078 *count = lttng_dynamic_pointer_array_get_count(&map_content->array);
1079 status = LTTNG_MAP_STATUS_OK;
1080 end:
1081 return status;
1082 }
1083
1084 enum lttng_buffer_type lttng_map_content_get_buffer_type(
1085 const struct lttng_map_content *map_content)
1086 {
1087 assert(map_content);
1088
1089 return map_content->type;
1090 }
1091
1092 LTTNG_HIDDEN
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)
1096 {
1097 int ret;
1098 enum lttng_map_status status;
1099
1100 assert(map_content);
1101 assert(kv_list);
1102
1103 ret = lttng_dynamic_pointer_array_add_pointer(&map_content->array,
1104 kv_list);
1105 if (ret) {
1106 status = LTTNG_MAP_STATUS_ERROR;
1107 goto end;
1108 }
1109
1110 status = LTTNG_MAP_STATUS_OK;
1111
1112 end:
1113 return status;
1114 }
1115
1116 const struct lttng_map_key_value_pair_list *lttng_map_content_get_at_index(
1117 const struct lttng_map_content *map_content,
1118 unsigned int index)
1119 {
1120 struct lttng_map_key_value_pair_list *kv_pair_list = NULL;
1121
1122 assert(map_content);
1123 if (index >= lttng_dynamic_pointer_array_get_count(&map_content->array)) {
1124 goto end;
1125 }
1126
1127 kv_pair_list = (struct lttng_map_key_value_pair_list *)
1128 lttng_dynamic_pointer_array_get_pointer(
1129 &map_content->array, index);
1130 end:
1131 return kv_pair_list;
1132 }
1133
1134 LTTNG_HIDDEN
1135 ssize_t lttng_map_content_create_from_payload(
1136 struct lttng_payload_view *src_view,
1137 struct lttng_map_content **map_content)
1138 {
1139 ssize_t ret, offset = 0;
1140 unsigned int i;
1141 struct lttng_map_content_comm *map_content_comm;
1142 struct lttng_map_content *local_map_content;
1143
1144 map_content_comm = (typeof(map_content_comm)) src_view->buffer.data;
1145 offset += sizeof(*map_content_comm);
1146
1147 local_map_content = lttng_map_content_create(map_content_comm->type);
1148 if (!local_map_content) {
1149 ret = -1;
1150 goto end;
1151 }
1152
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;
1158
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) {
1162 ret = kv_list_size;
1163 goto end;
1164 }
1165
1166 /* Transfer ownership of the key-value to the collection. */
1167 ret = lttng_map_content_append_key_value_list(local_map_content,
1168 kv_pair_list);
1169 if (ret < 0) {
1170 ret = -1;
1171 goto end;
1172 }
1173
1174 offset += kv_list_size;
1175 }
1176
1177 /* Pass ownership to caller. */
1178 *map_content = local_map_content;
1179 local_map_content = NULL;
1180
1181 ret = offset;
1182 end:
1183 lttng_map_content_destroy(local_map_content);
1184 return ret;
1185 }
1186
1187 LTTNG_HIDDEN
1188 int lttng_map_content_serialize(
1189 const struct lttng_map_content *map_content,
1190 struct lttng_payload *payload)
1191 {
1192 int ret;
1193 unsigned int i, count;
1194 enum lttng_map_status status;
1195 struct lttng_map_content_comm map_content_comm = {};
1196
1197 status = lttng_map_content_get_count(map_content, &count);
1198 if (status != LTTNG_MAP_STATUS_OK) {
1199 ret = LTTNG_ERR_INVALID;
1200 goto end;
1201 }
1202
1203 map_content_comm.count = count;
1204 map_content_comm.type = lttng_map_content_get_buffer_type(map_content);
1205
1206 ret = lttng_dynamic_buffer_append(&payload->buffer, &map_content_comm,
1207 sizeof(map_content_comm));
1208 if (ret) {
1209 goto end;
1210 }
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);
1214
1215 assert(kv_pair_list);
1216
1217 ret = lttng_map_key_value_pair_list_serialize(kv_pair_list, payload);
1218 if (ret) {
1219 goto end;
1220 }
1221 }
1222
1223 end:
1224 return ret;
1225 }
1226
1227 void lttng_map_content_destroy(struct lttng_map_content *map_content)
1228 {
1229 if (!map_content) {
1230 return;
1231 }
1232
1233 lttng_dynamic_pointer_array_reset(&map_content->array);
1234 free(map_content);
1235 }
This page took 0.081458 seconds and 5 git commands to generate.