SoW-2020-0003: Trace Hit Counters
[lttng-tools.git] / src / bin / lttng / commands / add_map.c
1 /*
2 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #define _LGPL_SOURCE
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <assert.h>
13
14 #include <lttng/map/map.h>
15
16 #include "common/argpar/argpar.h"
17 #include "common/utils.h"
18
19 #include "../command.h"
20 #include "../utils.h"
21
22 #define LTTNG_MAP_DEFAULT_SIZE 4096
23
24 enum {
25 OPT_HELP,
26 OPT_SESSION,
27 OPT_USERSPACE,
28 OPT_KERNEL,
29 OPT_MAX_KEY_COUNT,
30 OPT_PER_PID,
31 OPT_PER_UID,
32 OPT_OVERFLOW,
33 OPT_BITNESS,
34 OPT_COALESCE_HITS,
35 };
36
37 static const struct argpar_opt_descr add_map_opt_descrs[] = {
38
39 { OPT_HELP, 'h', "help", false },
40 { OPT_SESSION, 's', "session", true },
41 { OPT_USERSPACE, 'u', "userspace", false },
42 { OPT_KERNEL, 'k', "kernel", false },
43 { OPT_MAX_KEY_COUNT, '\0', "max-key-count", true},
44 { OPT_PER_PID, '\0', "per-pid", false},
45 { OPT_PER_UID, '\0', "per-uid", false},
46 { OPT_OVERFLOW, '\0', "overflow", false},
47 { OPT_BITNESS, '\0', "bitness", true},
48 { OPT_COALESCE_HITS, '\0', "coalesce-hits", false},
49 ARGPAR_OPT_DESCR_SENTINEL
50 };
51
52 static
53 bool assign_string(char **dest, const char *src, const char *opt_name)
54 {
55 bool ret;
56
57 if (*dest) {
58 ERR("Duplicate %s given.", opt_name);
59 goto error;
60 }
61
62 *dest = strdup(src);
63 if (!*dest) {
64 ERR("Failed to allocate %s string.", opt_name);
65 goto error;
66 }
67
68 ret = true;
69 goto end;
70
71 error:
72 ret = false;
73
74 end:
75 return ret;
76 }
77
78 int cmd_add_map(int argc, const char **argv)
79 {
80 int ret, i;
81 enum lttng_error_code error_code_ret;
82 struct argpar_parse_ret argpar_parse_ret = { 0 };
83 bool opt_userspace = false, opt_kernel = false, opt_buffers_uid = false,
84 opt_buffers_pid = false, opt_overflow = false, opt_coalesce_hits = false;
85 char *opt_session_name = NULL, *session_name = NULL, *opt_max_key_count = NULL, *opt_bitness = NULL;
86 const char *opt_map_name = NULL;;
87 enum lttng_map_bitness bitness_type;
88 enum lttng_map_boundary_policy boundary_policy;
89 enum lttng_map_status status;
90 uint64_t dimensions_sizes[1] = {0};
91 unsigned long long bitness;
92 struct lttng_map *map;
93 struct lttng_domain dom = {0};
94 struct lttng_handle *handle = NULL;
95
96 argpar_parse_ret = argpar_parse(argc - 1, argv + 1,
97 add_map_opt_descrs, true);
98 if (!argpar_parse_ret.items) {
99 ERR("%s", argpar_parse_ret.error);
100 goto error;
101 }
102
103 for (i = 0; i < argpar_parse_ret.items->n_items; i++) {
104 struct argpar_item *item = argpar_parse_ret.items->items[i];
105
106 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
107 struct argpar_item_opt *item_opt =
108 (struct argpar_item_opt *) item;
109
110 switch (item_opt->descr->id) {
111 case OPT_HELP:
112 SHOW_HELP();
113 ret = CMD_SUCCESS;
114 goto end;
115 case OPT_SESSION:
116 if (!assign_string(&opt_session_name, item_opt->arg,
117 "-s/--session")) {
118 goto error;
119 }
120 break;
121 case OPT_USERSPACE:
122 opt_userspace = true;
123 break;
124 case OPT_KERNEL:
125 opt_kernel = true;
126 break;
127 case OPT_MAX_KEY_COUNT:
128 if (!assign_string(&opt_max_key_count, item_opt->arg,
129 "--max-key-count")) {
130 goto error;
131 }
132 break;
133 case OPT_PER_PID:
134 opt_buffers_pid = true;
135 break;
136 case OPT_PER_UID:
137 opt_buffers_uid = true;
138 break;
139 case OPT_OVERFLOW:
140 opt_overflow = true;
141 break;
142 case OPT_BITNESS:
143 if (!assign_string(&opt_bitness, item_opt->arg,
144 "--bitness")) {
145 goto error;
146 }
147 break;
148 case OPT_COALESCE_HITS:
149 opt_coalesce_hits = true;
150 break;
151 default:
152 abort();
153 }
154 } else {
155 struct argpar_item_non_opt *item_non_opt =
156 (struct argpar_item_non_opt *) item;
157
158 if (opt_map_name) {
159 ERR("Unexpected argument: %s", item_non_opt->arg);
160 goto error;
161 }
162
163 opt_map_name = item_non_opt->arg;
164 }
165 }
166
167 if (!opt_map_name) {
168 ERR("Missing map name");
169 goto error;
170 }
171
172 if (!opt_session_name) {
173 session_name = get_session_name();
174 if (session_name == NULL) {
175 goto error;
176 }
177 } else {
178 session_name = opt_session_name;
179 }
180
181 /* Check that one and only one domain option was provided. */
182 ret = print_missing_or_multiple_domains(
183 opt_kernel + opt_userspace, false);
184 if (ret) {
185 goto error;
186 }
187
188 if (opt_kernel) {
189 dom.type = LTTNG_DOMAIN_KERNEL;
190 if (opt_buffers_uid || opt_buffers_pid) {
191 ERR("Buffer type not supported for kernel domain");
192 goto error;
193 }
194 dom.buf_type = LTTNG_BUFFER_GLOBAL;
195 } else {
196 dom.type = LTTNG_DOMAIN_UST;
197
198 if (opt_buffers_uid && opt_buffers_pid) {
199 ERR("Only one domain can be specified");
200 goto error;
201 }
202 if (opt_buffers_pid) {
203 dom.buf_type = LTTNG_BUFFER_PER_PID;
204 } else {
205 /* Defaults to per UID */
206 dom.buf_type = LTTNG_BUFFER_PER_UID;
207 }
208 }
209
210 handle = lttng_create_handle(session_name, &dom);
211 if (handle == NULL) {
212 ret = -1;
213 goto error;
214 }
215
216 if (opt_max_key_count) {
217 unsigned long long max_key_count;
218 if (utils_parse_unsigned_long_long(opt_max_key_count, &max_key_count) != 0) {
219 ERR("Failed to parse `%s` as an integer.", opt_max_key_count);
220 goto error;
221 }
222
223 dimensions_sizes[0] = max_key_count;
224 } else {
225 dimensions_sizes[0] = LTTNG_MAP_DEFAULT_SIZE;
226 }
227
228 if (opt_bitness) {
229 if (utils_parse_unsigned_long_long(opt_bitness, &bitness) != 0) {
230 ERR("Failed to parse `%s` as an integer.", opt_bitness);
231 goto error;
232 }
233 switch (bitness) {
234 case 32:
235 bitness_type = LTTNG_MAP_BITNESS_32BITS;
236 break;
237 case 64:
238 bitness_type = LTTNG_MAP_BITNESS_64BITS;
239 break;
240 default:
241 ERR("Bitness %llu not supported", bitness);
242 goto error;
243 }
244
245 } else {
246 bitness_type = LTTNG_MAP_BITNESS_64BITS;
247 }
248
249
250 if (opt_overflow) {
251 boundary_policy = LTTNG_MAP_BOUNDARY_POLICY_OVERFLOW;
252 } else {
253 boundary_policy = LTTNG_MAP_BOUNDARY_POLICY_OVERFLOW;
254 }
255
256 status = lttng_map_create(opt_map_name, 1, dimensions_sizes, dom.type,
257 dom.buf_type, bitness_type, boundary_policy,
258 opt_coalesce_hits, &map);
259 if (status != LTTNG_MAP_STATUS_OK) {
260 ERR("Creating map \"%s\"", opt_map_name);
261 goto error;
262 }
263
264 error_code_ret = lttng_add_map(handle, map);
265 if (error_code_ret != LTTNG_OK) {
266 ERR("Adding map \"%s\": %s", opt_map_name,
267 lttng_strerror(error_code_ret));
268 lttng_map_destroy(map);
269 goto error;
270 }
271
272 MSG("Map %s created.", opt_map_name);
273 ret = CMD_SUCCESS;
274
275 lttng_map_destroy(map);
276
277 goto end;
278
279 error:
280 ret = CMD_ERROR;
281 end:
282 argpar_parse_ret_fini(&argpar_parse_ret);
283 free(opt_session_name);
284 free(opt_max_key_count);
285 free(opt_bitness);
286 lttng_destroy_handle(handle);
287 return ret;
288 }
This page took 0.03527 seconds and 5 git commands to generate.