SoW-2020-0002: 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 LTTNG_HIDDEN
798 bool lttng_map_key_value_pair_list_get_summed_all_cpu(
799 const struct lttng_map_key_value_pair_list *kv_pair_list)
800 {
801 assert(kv_pair_list);
802
803 return kv_pair_list->summed_all_cpus;
804 }
805
806 LTTNG_HIDDEN
807 enum lttng_map_status lttng_map_key_value_pair_list_set_cpu(
808 struct lttng_map_key_value_pair_list *kv_pair_list,
809 uint64_t cpu)
810 {
811 assert(kv_pair_list);
812
813 kv_pair_list->cpu = cpu;
814
815 return LTTNG_MAP_STATUS_OK;
816 }
817
818 LTTNG_HIDDEN
819 uint64_t lttng_map_key_value_pair_list_get_cpu(
820 const struct lttng_map_key_value_pair_list *kv_pair_list)
821 {
822 assert(kv_pair_list);
823
824 return kv_pair_list->cpu;
825 }
826
827 LTTNG_HIDDEN
828 enum lttng_map_key_value_pair_list_type lttng_map_key_value_pair_list_get_type(
829 const struct lttng_map_key_value_pair_list *kv_pair_list)
830 {
831 assert(kv_pair_list);
832
833 return kv_pair_list->type;
834 }
835
836 LTTNG_HIDDEN
837 enum lttng_map_status lttng_map_key_value_pair_list_append_key_value(
838 struct lttng_map_key_value_pair_list *kv_pair_list,
839 struct lttng_map_key_value_pair *key_value)
840 {
841 int ret;
842 enum lttng_map_status status;
843
844 assert(kv_pair_list);
845 assert(key_value);
846
847 ret = lttng_dynamic_pointer_array_add_pointer(&kv_pair_list->array,
848 key_value);
849 if (ret) {
850 status = LTTNG_MAP_STATUS_ERROR;
851 goto end;
852 }
853
854 status = LTTNG_MAP_STATUS_OK;
855
856 end:
857 return status;
858 }
859
860 LTTNG_HIDDEN
861 uint64_t lttng_map_key_value_pair_list_get_identifer(
862 const struct lttng_map_key_value_pair_list *kv_pair_list)
863 {
864 assert(kv_pair_list);
865
866 switch (kv_pair_list->type) {
867 case LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_PID:
868 case LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_UID:
869 break;
870 case LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_PID_AGGREGATED:
871 ERR("No identifier for UST per-pid aggregation key value pair lists");
872 abort();
873 break;
874 case LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_KERNEL:
875 ERR("No identifier for kernel key value pair lists");
876 abort();
877 break;
878 default:
879 ERR("Unknown key value par list type %d", kv_pair_list->type);
880 abort();
881 }
882
883 return kv_pair_list->id;
884 }
885
886 const struct lttng_map_key_value_pair *lttng_map_key_value_pair_list_get_at_index(
887 const struct lttng_map_key_value_pair_list *kv_pair_list,
888 unsigned int index)
889 {
890 struct lttng_map_key_value_pair *key_value = NULL;
891
892 assert(kv_pair_list);
893 if (index >= lttng_dynamic_pointer_array_get_count(&kv_pair_list->array)) {
894 goto end;
895 }
896
897 key_value = (struct lttng_map_key_value_pair *)
898 lttng_dynamic_pointer_array_get_pointer(
899 &kv_pair_list->array, index);
900 end:
901 return key_value;
902 }
903
904 enum lttng_map_status lttng_map_key_value_pair_list_get_count(
905 const struct lttng_map_key_value_pair_list *kv_pair_list,
906 unsigned int *count)
907 {
908 enum lttng_map_status status;
909
910 if (!kv_pair_list || !count) {
911 status = LTTNG_MAP_STATUS_INVALID;;
912 goto end;
913 }
914
915 *count = lttng_dynamic_pointer_array_get_count(&kv_pair_list->array);
916
917 status = LTTNG_MAP_STATUS_OK;
918 end:
919 return status;
920 }
921
922 void lttng_map_key_value_pair_list_destroy(struct lttng_map_key_value_pair_list *kv_pair_list)
923 {
924 if (!kv_pair_list) {
925 return;
926 }
927
928 lttng_dynamic_pointer_array_reset(&kv_pair_list->array);
929 free(kv_pair_list);
930 }
931
932 int lttng_map_key_value_pair_list_serialize(
933 const struct lttng_map_key_value_pair_list *kv_pair_list,
934 struct lttng_payload *payload)
935 {
936 int ret;
937 unsigned int i, count;
938 enum lttng_map_status status;
939 struct lttng_map_key_value_pair_list_comm kv_pair_list_comm = {};
940
941 kv_pair_list_comm.id = kv_pair_list->id;
942 kv_pair_list_comm.cpu = kv_pair_list->cpu;
943 kv_pair_list_comm.type = (uint8_t) kv_pair_list->type;
944 kv_pair_list_comm.summed_all_cpus = (uint8_t) kv_pair_list->summed_all_cpus;
945
946 status = lttng_map_key_value_pair_list_get_count(kv_pair_list, &count);
947 if (status != LTTNG_MAP_STATUS_OK) {
948 ret = LTTNG_ERR_INVALID;
949 goto end;
950 }
951
952 kv_pair_list_comm.count = count;
953 ret = lttng_dynamic_buffer_append(&payload->buffer, &kv_pair_list_comm,
954 sizeof(kv_pair_list_comm));
955 if (ret) {
956 goto end;
957 }
958 for (i = 0; i < count; i++) {
959 const struct lttng_map_key_value_pair *kv_pair =
960 lttng_map_key_value_pair_list_get_at_index(kv_pair_list, i);
961
962 assert(kv_pair);
963
964 ret = lttng_map_key_value_pair_serialize(kv_pair, payload);
965 if (ret) {
966 goto end;
967 }
968 }
969
970 end:
971 return ret;
972 }
973
974 LTTNG_HIDDEN
975 ssize_t lttng_map_key_value_pair_list_create_from_payload(
976 struct lttng_payload_view *src_view,
977 struct lttng_map_key_value_pair_list **kv_pair_list)
978 {
979 ssize_t ret, offset = 0;
980 unsigned int i;
981 enum lttng_map_status status;
982 const struct lttng_map_key_value_pair_list_comm *kv_pair_list_comm;
983 struct lttng_map_key_value_pair_list *local_key_values = NULL;
984
985 kv_pair_list_comm = (typeof(kv_pair_list_comm)) src_view->buffer.data;
986 offset += sizeof(*kv_pair_list_comm);
987
988 local_key_values = lttng_map_key_value_pair_list_create(
989 kv_pair_list_comm->type, kv_pair_list_comm->summed_all_cpus);
990 if (!local_key_values) {
991 ret = -1;
992 goto end;
993 }
994
995 local_key_values->cpu = kv_pair_list_comm->cpu;
996
997 switch (lttng_map_key_value_pair_list_get_type(local_key_values)) {
998 case LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_PID:
999 case LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_UID:
1000 status = lttng_map_key_value_pair_list_set_identifier(local_key_values,
1001 kv_pair_list_comm->id);
1002 if (status != LTTNG_MAP_STATUS_OK) {
1003 ret = -1;
1004 goto end;
1005 }
1006 break;
1007 default:
1008 break;
1009 }
1010
1011 for (i = 0; i < kv_pair_list_comm->count; i++) {
1012 struct lttng_map_key_value_pair *kv_pair = NULL;
1013 struct lttng_payload_view kv_view =
1014 lttng_payload_view_from_view(src_view, offset, -1);
1015 ssize_t kv_size;
1016
1017 kv_size = lttng_map_key_value_pair_create_from_payload(
1018 &kv_view, &kv_pair);
1019 if (kv_size < 0) {
1020 ret = kv_size;
1021 goto end;
1022 }
1023
1024 /* Transfer ownership of the key-value to the collection. */
1025 status = lttng_map_key_value_pair_list_append_key_value(local_key_values,
1026 kv_pair);
1027 if (status != LTTNG_MAP_STATUS_OK) {
1028 ret = -1;
1029 goto end;
1030 }
1031
1032 offset += kv_size;
1033 }
1034
1035 /* Pass ownership to caller. */
1036 *kv_pair_list = local_key_values;
1037 local_key_values = NULL;
1038
1039 ret = offset;
1040 end:
1041 lttng_map_key_value_pair_list_destroy(local_key_values);
1042 return ret;
1043 }
1044
1045 static void delete_map_key_value_pair_list_array_element(void *ptr)
1046 {
1047 struct lttng_map_key_value_pair_list *kv_list = ptr;
1048 lttng_map_key_value_pair_list_destroy(kv_list);
1049 }
1050
1051 LTTNG_HIDDEN
1052 struct lttng_map_content *lttng_map_content_create(
1053 enum lttng_buffer_type type)
1054 {
1055 struct lttng_map_content *map_content = NULL;
1056
1057 map_content = zmalloc(sizeof(*map_content));
1058 if (!map_content) {
1059 goto end;
1060 }
1061
1062 map_content->type = type;
1063
1064 lttng_dynamic_pointer_array_init(&map_content->array,
1065 delete_map_key_value_pair_list_array_element);
1066
1067 end:
1068 return map_content;
1069 }
1070
1071 enum lttng_map_status lttng_map_content_get_count(
1072 const struct lttng_map_content *map_content,
1073 unsigned int *count)
1074 {
1075 enum lttng_map_status status = LTTNG_MAP_STATUS_OK;
1076
1077 if (!map_content || !count) {
1078 status = LTTNG_MAP_STATUS_INVALID;
1079 goto end;
1080 }
1081
1082 *count = lttng_dynamic_pointer_array_get_count(&map_content->array);
1083 status = LTTNG_MAP_STATUS_OK;
1084 end:
1085 return status;
1086 }
1087
1088 enum lttng_buffer_type lttng_map_content_get_buffer_type(
1089 const struct lttng_map_content *map_content)
1090 {
1091 assert(map_content);
1092
1093 return map_content->type;
1094 }
1095
1096 LTTNG_HIDDEN
1097 enum lttng_map_status lttng_map_content_append_key_value_list(
1098 struct lttng_map_content *map_content,
1099 struct lttng_map_key_value_pair_list *kv_list)
1100 {
1101 int ret;
1102 enum lttng_map_status status;
1103
1104 assert(map_content);
1105 assert(kv_list);
1106
1107 ret = lttng_dynamic_pointer_array_add_pointer(&map_content->array,
1108 kv_list);
1109 if (ret) {
1110 status = LTTNG_MAP_STATUS_ERROR;
1111 goto end;
1112 }
1113
1114 status = LTTNG_MAP_STATUS_OK;
1115
1116 end:
1117 return status;
1118 }
1119
1120 const struct lttng_map_key_value_pair_list *lttng_map_content_get_at_index(
1121 const struct lttng_map_content *map_content,
1122 unsigned int index)
1123 {
1124 struct lttng_map_key_value_pair_list *kv_pair_list = NULL;
1125
1126 assert(map_content);
1127 if (index >= lttng_dynamic_pointer_array_get_count(&map_content->array)) {
1128 goto end;
1129 }
1130
1131 kv_pair_list = (struct lttng_map_key_value_pair_list *)
1132 lttng_dynamic_pointer_array_get_pointer(
1133 &map_content->array, index);
1134 end:
1135 return kv_pair_list;
1136 }
1137
1138 LTTNG_HIDDEN
1139 ssize_t lttng_map_content_create_from_payload(
1140 struct lttng_payload_view *src_view,
1141 struct lttng_map_content **map_content)
1142 {
1143 ssize_t ret, offset = 0;
1144 unsigned int i;
1145 struct lttng_map_content_comm *map_content_comm;
1146 struct lttng_map_content *local_map_content;
1147
1148 map_content_comm = (typeof(map_content_comm)) src_view->buffer.data;
1149 offset += sizeof(*map_content_comm);
1150
1151 local_map_content = lttng_map_content_create(map_content_comm->type);
1152 if (!local_map_content) {
1153 ret = -1;
1154 goto end;
1155 }
1156
1157 for (i = 0; i < map_content_comm->count; i++) {
1158 struct lttng_map_key_value_pair_list *kv_pair_list = NULL;
1159 struct lttng_payload_view kv_list_view =
1160 lttng_payload_view_from_view(src_view, offset, -1);
1161 ssize_t kv_list_size;
1162
1163 kv_list_size = lttng_map_key_value_pair_list_create_from_payload(
1164 &kv_list_view, &kv_pair_list);
1165 if (kv_list_size < 0) {
1166 ret = kv_list_size;
1167 goto end;
1168 }
1169
1170 /* Transfer ownership of the key-value to the collection. */
1171 ret = lttng_map_content_append_key_value_list(local_map_content,
1172 kv_pair_list);
1173 if (ret < 0) {
1174 ret = -1;
1175 goto end;
1176 }
1177
1178 offset += kv_list_size;
1179 }
1180
1181 /* Pass ownership to caller. */
1182 *map_content = local_map_content;
1183 local_map_content = NULL;
1184
1185 ret = offset;
1186 end:
1187 lttng_map_content_destroy(local_map_content);
1188 return ret;
1189 }
1190
1191 LTTNG_HIDDEN
1192 int lttng_map_content_serialize(
1193 const struct lttng_map_content *map_content,
1194 struct lttng_payload *payload)
1195 {
1196 int ret;
1197 unsigned int i, count;
1198 enum lttng_map_status status;
1199 struct lttng_map_content_comm map_content_comm = {};
1200
1201 status = lttng_map_content_get_count(map_content, &count);
1202 if (status != LTTNG_MAP_STATUS_OK) {
1203 ret = LTTNG_ERR_INVALID;
1204 goto end;
1205 }
1206
1207 map_content_comm.count = count;
1208 map_content_comm.type = lttng_map_content_get_buffer_type(map_content);
1209
1210 ret = lttng_dynamic_buffer_append(&payload->buffer, &map_content_comm,
1211 sizeof(map_content_comm));
1212 if (ret) {
1213 goto end;
1214 }
1215 for (i = 0; i < count; i++) {
1216 const struct lttng_map_key_value_pair_list *kv_pair_list =
1217 lttng_map_content_get_at_index(map_content, i);
1218
1219 assert(kv_pair_list);
1220
1221 ret = lttng_map_key_value_pair_list_serialize(kv_pair_list, payload);
1222 if (ret) {
1223 goto end;
1224 }
1225 }
1226
1227 end:
1228 return ret;
1229 }
1230
1231 void lttng_map_content_destroy(struct lttng_map_content *map_content)
1232 {
1233 if (!map_content) {
1234 return;
1235 }
1236
1237 lttng_dynamic_pointer_array_reset(&map_content->array);
1238 free(map_content);
1239 }
This page took 0.055096 seconds and 5 git commands to generate.