SoW-2020-0002: Trace Hit Counters
[lttng-tools.git] / src / common / map-query.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 <stdint.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #include <common/error.h>
14 #include <common/macros.h>
15 #include <common/optional.h>
16 #include <common/payload.h>
17
18 #include <lttng/map/map-query-internal.h>
19
20 struct lttng_map_query *lttng_map_query_create(
21 enum lttng_map_query_config_cpu cpu,
22 enum lttng_map_query_config_buffer buffer,
23 enum lttng_map_query_config_app_bitness bitness)
24 {
25 struct lttng_map_query *query = NULL;
26
27 if ((buffer == LTTNG_MAP_QUERY_CONFIG_BUFFER_KERNEL_GLOBAL) ^
28 (bitness == LTTNG_MAP_QUERY_CONFIG_APP_BITNESS_KERNEL)) {
29 /*
30 * If any of the buffer or bitness config is set to kernel,
31 * they other has to as well.
32 */
33 goto end;
34 }
35
36 if (bitness != LTTNG_MAP_QUERY_CONFIG_APP_BITNESS_ALL &&
37 bitness != LTTNG_MAP_QUERY_CONFIG_APP_BITNESS_KERNEL) {
38 /* We currently don't support targetting a specific bitness. */
39 goto end;
40 }
41
42 query = zmalloc(sizeof(struct lttng_map_query));
43 if (!query) {
44 goto end;
45 }
46
47 query->config_cpu = cpu;
48 query->config_buffer = buffer;
49 query->config_bitness = bitness;
50
51 query->sum_by_uid = false;
52 query->sum_by_pid = false;
53 query->sum_by_cpu = false;
54 // defaults to true for now.
55 query->sum_by_app_bitness = true;
56
57 if (query->config_cpu == LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) {
58 lttng_dynamic_array_init(&query->cpu_array, sizeof(int), NULL);
59 }
60
61 switch(query->config_buffer) {
62 case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET:
63 lttng_dynamic_array_init(&query->uid_array, sizeof(uid_t), NULL);
64 break;
65 case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET:
66 lttng_dynamic_array_init(&query->pid_array, sizeof(pid_t), NULL);
67 break;
68 default:
69 break;
70 }
71 end:
72 return query;
73 }
74
75 enum lttng_map_query_status lttng_map_query_set_sum_by_cpu(
76 struct lttng_map_query *query, bool sum_by_cpu)
77 {
78 query->sum_by_cpu = sum_by_cpu;
79
80 return LTTNG_MAP_QUERY_STATUS_OK;
81 }
82
83 enum lttng_map_query_status lttng_map_query_set_sum_by_app_bitness(
84 struct lttng_map_query *query, bool sum_by_app_bitness)
85 {
86 enum lttng_map_query_status status;
87
88 if (query->config_bitness != LTTNG_MAP_QUERY_CONFIG_APP_BITNESS_ALL) {
89 status = LTTNG_MAP_QUERY_STATUS_INVALID;
90 goto end;
91 }
92
93 query->sum_by_app_bitness = sum_by_app_bitness;
94 status = LTTNG_MAP_QUERY_STATUS_OK;
95
96 end:
97 return status;
98 }
99
100 enum lttng_map_query_status lttng_map_query_set_sum_by_pid(
101 struct lttng_map_query *query, bool sum_by_pid)
102 {
103 enum lttng_map_query_status status;
104
105 switch (query->config_buffer) {
106 case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_ALL:
107 case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET:
108 break;
109 default:
110 status = LTTNG_MAP_QUERY_STATUS_INVALID;
111 goto end;
112 }
113
114 query->sum_by_pid = sum_by_pid;
115 status = LTTNG_MAP_QUERY_STATUS_OK;
116
117 end:
118 return status;
119 }
120
121 enum lttng_map_query_status lttng_map_query_set_sum_by_uid(
122 struct lttng_map_query *query, bool sum_by_uid)
123 {
124 enum lttng_map_query_status status;
125
126 switch (query->config_buffer) {
127 case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_ALL:
128 case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET:
129 break;
130 default:
131 status = LTTNG_MAP_QUERY_STATUS_INVALID;
132 goto end;
133 }
134
135 query->sum_by_uid = sum_by_uid;
136 status = LTTNG_MAP_QUERY_STATUS_OK;
137
138 end:
139 return status;
140 }
141
142 enum lttng_map_query_status lttng_map_query_add_cpu(
143 struct lttng_map_query *query, int cpu_id)
144 {
145 enum lttng_map_query_status status;
146 unsigned int cpu_count;
147 int ret;
148
149 if (query->config_cpu != LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) {
150 status = LTTNG_MAP_QUERY_STATUS_INVALID;
151 goto end;
152 }
153
154 lttng_map_query_get_cpu_count(query, &cpu_count);
155 if (cpu_count > 0) {
156 ERR("Only one CPU can be targeted in a query at the moment");
157 status = LTTNG_MAP_QUERY_STATUS_INVALID;
158 goto end;
159 }
160
161 ret = lttng_dynamic_array_add_element(&query->cpu_array, &cpu_id);
162 if (ret) {
163 status = LTTNG_MAP_QUERY_STATUS_ERROR;
164 goto end;
165 }
166
167 status = LTTNG_MAP_QUERY_STATUS_OK;
168 end:
169 return status;
170 }
171
172 enum lttng_map_query_status lttng_map_query_add_uid(
173 struct lttng_map_query *query, uid_t uid)
174 {
175 int ret;
176 unsigned int uid_count;
177 enum lttng_map_query_status status;
178
179 if (query->config_buffer != LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET) {
180 status = LTTNG_MAP_QUERY_STATUS_INVALID;
181 goto end;
182 }
183
184 lttng_map_query_get_uid_count(query, &uid_count);
185 if (uid_count > 0) {
186 ERR("Only one UID can be targeted in a query at the moment");
187 status = LTTNG_MAP_QUERY_STATUS_INVALID;
188 goto end;
189 }
190
191 ret = lttng_dynamic_array_add_element(&query->uid_array, &uid);
192 if (ret) {
193 status = LTTNG_MAP_QUERY_STATUS_ERROR;
194 goto end;
195 }
196
197 status = LTTNG_MAP_QUERY_STATUS_OK;
198 end:
199 return status;
200 }
201
202 enum lttng_map_query_status lttng_map_query_add_pid(
203 struct lttng_map_query *query, pid_t pid)
204 {
205 int ret;
206 unsigned int pid_count;
207 enum lttng_map_query_status status;
208
209 if (query->config_buffer != LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET) {
210 status = LTTNG_MAP_QUERY_STATUS_INVALID;
211 goto end;
212 }
213
214 lttng_map_query_get_pid_count(query, &pid_count);
215 if (pid_count > 0) {
216 ERR("Only one PID can be targeted in a query at the moment");
217 status = LTTNG_MAP_QUERY_STATUS_INVALID;
218 goto end;
219 }
220
221 ret = lttng_dynamic_array_add_element(&query->pid_array, &pid);
222 if (ret) {
223 status = LTTNG_MAP_QUERY_STATUS_ERROR;
224 goto end;
225 }
226
227 status = LTTNG_MAP_QUERY_STATUS_OK;
228 end:
229 return status;
230 }
231
232 enum lttng_map_query_status lttng_map_query_add_key_filter(
233 struct lttng_map_query *query, const char *key_filter)
234 {
235 enum lttng_map_query_status status;
236
237 query->key_filter = strdup(key_filter);
238 if (!query->key_filter) {
239 status = LTTNG_MAP_QUERY_STATUS_ERROR;
240 goto end;
241 }
242
243 status = LTTNG_MAP_QUERY_STATUS_OK;
244 end:
245 return status;
246 }
247
248 enum lttng_map_query_config_cpu lttng_map_query_get_config_cpu(
249 const struct lttng_map_query *query)
250 {
251 return query->config_cpu;
252 }
253
254 enum lttng_map_query_config_buffer lttng_map_query_get_config_buffer(
255 const struct lttng_map_query *query)
256 {
257 return query->config_buffer;
258 }
259
260 enum lttng_map_query_config_app_bitness lttng_map_query_get_config_app_bitness(
261 const struct lttng_map_query *query)
262 {
263 return query->config_bitness;
264 }
265
266 bool lttng_map_query_get_config_sum_by_cpu(
267 const struct lttng_map_query *query)
268 {
269 return query->sum_by_cpu;
270 }
271
272 bool lttng_map_query_get_config_sum_by_pid(
273 const struct lttng_map_query *query)
274 {
275 return query->sum_by_pid;
276 }
277
278 bool lttng_map_query_get_config_sum_by_uid(
279 const struct lttng_map_query *query)
280 {
281 return query->sum_by_uid;
282 }
283
284 bool lttng_map_query_get_config_sum_by_app_bitness(
285 const struct lttng_map_query *query)
286 {
287 return query->sum_by_app_bitness;
288 }
289
290 enum lttng_map_query_status lttng_map_query_get_cpu_count(
291 const struct lttng_map_query *query, unsigned int *count)
292 {
293 enum lttng_map_query_status status;
294
295 assert(query);
296 if (query->config_cpu != LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) {
297 status = LTTNG_MAP_QUERY_STATUS_INVALID;
298 goto end;
299 }
300
301 if (!count) {
302 status = LTTNG_MAP_QUERY_STATUS_INVALID;
303 goto end;
304 }
305
306 *count = lttng_dynamic_array_get_count(&query->cpu_array);
307 status = LTTNG_MAP_QUERY_STATUS_OK;
308
309 end:
310 return status;
311 }
312
313 enum lttng_map_query_status lttng_map_query_get_cpu_at_index(
314 const struct lttng_map_query *query, unsigned int index,
315 int *cpu)
316 {
317 enum lttng_map_query_status status;
318
319 assert(query);
320
321 if (query->config_cpu != LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) {
322 status = LTTNG_MAP_QUERY_STATUS_INVALID;
323 goto end;
324 }
325
326
327 *cpu = *(int *) lttng_dynamic_array_get_element(&query->cpu_array, index);
328 status = LTTNG_MAP_QUERY_STATUS_OK;
329 end:
330 return status;
331 }
332
333 enum lttng_map_query_status lttng_map_query_get_uid_count(
334 const struct lttng_map_query *query, unsigned int *count)
335 {
336 enum lttng_map_query_status status;
337
338 assert(query);
339 if (query->config_buffer != LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET) {
340 status = LTTNG_MAP_QUERY_STATUS_INVALID;
341 goto end;
342 }
343
344 if (!count) {
345 status = LTTNG_MAP_QUERY_STATUS_INVALID;
346 goto end;
347 }
348
349 *count = lttng_dynamic_array_get_count(&query->uid_array);
350 status = LTTNG_MAP_QUERY_STATUS_OK;
351
352 end:
353 return status;
354 }
355
356 enum lttng_map_query_status lttng_map_query_get_uid_at_index(
357 const struct lttng_map_query *query, unsigned int index,
358 uid_t *uid)
359 {
360 enum lttng_map_query_status status;
361
362 assert(query);
363
364 if (query->config_buffer != LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET) {
365 status = LTTNG_MAP_QUERY_STATUS_INVALID;
366 goto end;
367 }
368
369
370 *uid = *(uid_t *) lttng_dynamic_array_get_element(&query->uid_array, index);
371 status = LTTNG_MAP_QUERY_STATUS_OK;
372 end:
373 return status;
374 }
375
376 enum lttng_map_query_status lttng_map_query_get_pid_count(
377 const struct lttng_map_query *query, unsigned int *count)
378 {
379 enum lttng_map_query_status status;
380
381 assert(query);
382 if (query->config_buffer != LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET) {
383 status = LTTNG_MAP_QUERY_STATUS_INVALID;
384 goto end;
385 }
386
387 if (!count) {
388 status = LTTNG_MAP_QUERY_STATUS_INVALID;
389 goto end;
390 }
391
392 *count = lttng_dynamic_array_get_count(&query->pid_array);
393 status = LTTNG_MAP_QUERY_STATUS_OK;
394
395 end:
396 return status;
397 }
398
399 enum lttng_map_query_status lttng_map_query_get_pid_at_index(
400 const struct lttng_map_query *query, unsigned int index,
401 pid_t *pid)
402 {
403 enum lttng_map_query_status status;
404
405 assert(query);
406
407 if (query->config_buffer != LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET) {
408 status = LTTNG_MAP_QUERY_STATUS_INVALID;
409 goto end;
410 }
411
412
413 *pid = *(pid_t *) lttng_dynamic_array_get_element(&query->pid_array, index);
414 status = LTTNG_MAP_QUERY_STATUS_OK;
415 end:
416 return status;
417 }
418
419
420 enum lttng_map_query_status lttng_map_query_get_key_filter(
421 const struct lttng_map_query *query, const char **key_filter)
422 {
423 enum lttng_map_query_status status;
424
425 if (query->key_filter == NULL) {
426 status = LTTNG_MAP_QUERY_STATUS_NONE;
427 goto end;
428 }
429
430 *key_filter = query->key_filter;
431 status = LTTNG_MAP_QUERY_STATUS_OK;
432 end:
433 return status;
434 }
435
436 LTTNG_HIDDEN
437 ssize_t lttng_map_query_create_from_payload(struct lttng_payload_view *src_view,
438 struct lttng_map_query **query)
439 {
440 ssize_t ret, offset = 0;
441 struct lttng_map_query *local_query;
442 const struct lttng_map_query_comm *query_comm;
443
444 if (!src_view || !query) {
445 ret = -1;
446 goto end;
447 }
448
449 query_comm = (typeof(query_comm)) src_view->buffer.data;
450 offset += sizeof(*query_comm);
451
452 local_query = lttng_map_query_create(query_comm->config_cpu,
453 query_comm->config_buffer, query_comm->config_app_bitness);
454 if (!local_query) {
455 ret = -1;
456 goto end;
457 }
458
459 local_query->sum_by_cpu = query_comm->sum_by_cpu;
460 local_query->sum_by_pid = query_comm->sum_by_pid;
461 local_query->sum_by_uid = query_comm->sum_by_uid;
462 local_query->sum_by_app_bitness = query_comm->sum_by_app_bitness;
463
464 if (query_comm->key_filter_length != 0) {
465 const char *key_filter;
466 struct lttng_payload_view key_filter_view =
467 lttng_payload_view_from_view(
468 src_view, offset,
469 query_comm->key_filter_length);
470
471 key_filter = key_filter_view.buffer.data;
472 if (!lttng_buffer_view_contains_string(&key_filter_view.buffer,
473 key_filter, query_comm->key_filter_length)){
474 ret = -1;
475 goto end;
476 }
477
478 lttng_map_query_add_key_filter(local_query, key_filter);
479
480 offset += query_comm->key_filter_length;
481 }
482
483 if (local_query->config_cpu == LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) {
484 unsigned int cpu_idx;
485
486 assert(query_comm->cpu_count > 0);
487
488 for (cpu_idx = 0; cpu_idx < query_comm->cpu_count; cpu_idx++) {
489 int cpu_id;
490 struct lttng_payload_view cpu_id_view =
491 lttng_payload_view_from_view( src_view,
492 offset, sizeof(cpu_id));
493 cpu_id = *(int *) cpu_id_view.buffer.data;
494 lttng_map_query_add_cpu(local_query, cpu_id);
495 offset+=sizeof(cpu_id);
496 }
497 }
498
499 switch (local_query->config_buffer){
500 case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET:
501 {
502 unsigned int pid_idx;
503
504 assert(query_comm->pid_count > 0);
505
506 for (pid_idx = 0; pid_idx < query_comm->pid_count; pid_idx++) {
507 pid_t pid;
508 struct lttng_payload_view pid_view =
509 lttng_payload_view_from_view( src_view,
510 offset, sizeof(pid));
511 pid = *(pid_t *) pid_view.buffer.data;
512 lttng_map_query_add_pid(local_query, pid);
513 offset+=sizeof(pid);
514 }
515 break;
516 }
517 case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET:
518 {
519 unsigned int uid_idx;
520
521 assert(query_comm->uid_count > 0);
522
523 for (uid_idx = 0; uid_idx < query_comm->uid_count; uid_idx++) {
524 uid_t uid;
525 struct lttng_payload_view uid_view =
526 lttng_payload_view_from_view( src_view,
527 offset, sizeof(uid));
528 uid = *(uid_t *) uid_view.buffer.data;
529 lttng_map_query_add_uid(local_query, uid);
530 offset+=sizeof(uid);
531 }
532 }
533 default:
534 break;
535 }
536
537 ret = offset;
538 *query = local_query;
539 local_query = NULL;
540 end:
541 return ret;
542 }
543
544 LTTNG_HIDDEN
545 int lttng_map_query_serialize(const struct lttng_map_query *query,
546 struct lttng_payload *payload)
547 {
548 int ret;
549 struct lttng_map_query_comm query_comm = {};
550 enum lttng_map_query_status status;
551
552 query_comm.config_cpu = (uint8_t) query->config_cpu;
553 query_comm.config_buffer = (uint8_t) query->config_buffer;
554 query_comm.config_app_bitness = (uint8_t) query->config_bitness;
555
556 query_comm.sum_by_cpu = (uint8_t) query->sum_by_cpu;
557 query_comm.sum_by_uid = (uint8_t) query->sum_by_uid;
558 query_comm.sum_by_pid = (uint8_t) query->sum_by_pid;
559 query_comm.sum_by_app_bitness = (uint8_t) query->sum_by_app_bitness;
560
561 if (query->config_cpu == LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) {
562 unsigned int cpu_count;
563 status = lttng_map_query_get_cpu_count(query, &cpu_count);
564 if (status != LTTNG_MAP_QUERY_STATUS_OK) {
565 ret = -1;
566 goto end;
567 }
568
569 query_comm.cpu_count = cpu_count;
570 }
571
572 switch (query->config_buffer){
573 case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET:
574 {
575 unsigned int pid_count;
576 status = lttng_map_query_get_pid_count(query, &pid_count);
577 if (status != LTTNG_MAP_QUERY_STATUS_OK) {
578 ret = -1;
579 goto end;
580 }
581 query_comm.pid_count = pid_count;
582 break;
583 }
584 case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET:
585 {
586 unsigned int uid_count;
587 status = lttng_map_query_get_uid_count(query, &uid_count);
588 if (status != LTTNG_MAP_QUERY_STATUS_OK) {
589 ret = -1;
590 goto end;
591 }
592 query_comm.uid_count = uid_count;
593 }
594 default:
595 break;
596 }
597
598 if (query->key_filter) {
599 query_comm.key_filter_length = strlen(query->key_filter) + 1;
600 } else {
601 query_comm.key_filter_length = 0;
602 }
603
604 ret = lttng_dynamic_buffer_append(&payload->buffer, &query_comm,
605 sizeof(query_comm));
606 if (ret) {
607 goto end;
608 }
609
610 /* key_filter */
611 ret = lttng_dynamic_buffer_append(
612 &payload->buffer, query->key_filter,
613 query_comm.key_filter_length);
614 if (ret) {
615 goto end;
616 }
617
618 if (query->config_cpu == LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) {
619 ret = lttng_dynamic_buffer_append(&payload->buffer,
620 query->cpu_array.buffer.data,
621 query->cpu_array.buffer.size);
622 if (ret) {
623 goto end;
624 }
625 }
626
627 switch (query->config_buffer){
628 case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET:
629 {
630 ret = lttng_dynamic_buffer_append(&payload->buffer,
631 query->pid_array.buffer.data,
632 query->pid_array.buffer.size);
633 if (ret) {
634 goto end;
635 }
636 }
637 case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET:
638 {
639 ret = lttng_dynamic_buffer_append(&payload->buffer,
640 query->uid_array.buffer.data,
641 query->uid_array.buffer.size);
642 if (ret) {
643 goto end;
644 }
645 }
646 default:
647 break;
648 }
649
650 end:
651 return ret;
652 }
653
654 void lttng_map_query_destroy(struct lttng_map_query *query)
655 {
656 assert(query);
657
658 if (query->config_cpu == LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) {
659 lttng_dynamic_array_reset(&query->cpu_array);
660 }
661
662 switch(query->config_buffer) {
663 case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET:
664 lttng_dynamic_array_reset(&query->uid_array);
665 break;
666 case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET:
667 lttng_dynamic_array_reset(&query->pid_array);
668 break;
669 default:
670 break;
671 }
672 free(query->key_filter);
673 free(query);
674 }
This page took 0.043796 seconds and 5 git commands to generate.