SoW-2020-0003: Trace Hit Counters
[lttng-tools.git] / src / common / actions / incr-value.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 <inttypes.h>
10
11 #include <common/error.h>
12 #include <common/macros.h>
13 #include <common/optional.h>
14
15 #include <lttng/action/action-internal.h>
16 #include <lttng/action/incr-value-internal.h>
17 #include <lttng/action/incr-value.h>
18 #include <lttng/map-key.h>
19 #include <lttng/map-key-internal.h>
20
21 #define IS_INCR_VALUE_ACTION(action) \
22 (lttng_action_get_type(action) == LTTNG_ACTION_TYPE_INCREMENT_VALUE)
23
24 struct lttng_action_incr_value {
25 struct lttng_action parent;
26
27 /* Owned by this. */
28 struct lttng_map_key *key;
29 /* Owned by this. */
30 char *session_name;
31 /* Owned by this. */
32 char *map_name;
33
34 LTTNG_OPTIONAL(uint64_t) action_tracer_token;
35 };
36
37 struct lttng_action_incr_value_comm {
38 /* Includes the trailing \0. */
39 uint32_t session_name_len;
40 /* Includes the trailing \0. */
41 uint32_t map_name_len;
42
43 /*
44 * Variable data:
45 *
46 * - struct lttng_map_key object with variable data
47 * - session name (null terminated)
48 * - map name (null terminated)
49 */
50 char data[];
51 } LTTNG_PACKED;
52
53 static struct lttng_action_incr_value *action_incr_value_from_action(
54 struct lttng_action *action)
55 {
56 assert(action);
57
58 return container_of(action, struct lttng_action_incr_value, parent);
59 }
60
61 static const struct lttng_action_incr_value *
62 action_incr_value_from_action_const(const struct lttng_action *action)
63 {
64 assert(action);
65
66 return container_of(action, struct lttng_action_incr_value, parent);
67 }
68
69 static bool lttng_action_incr_value_validate(struct lttng_action *action)
70 {
71 bool valid;
72 struct lttng_action_incr_value *action_incr_value;
73
74 if (!action) {
75 valid = false;
76 goto end;
77 }
78
79 action_incr_value = action_incr_value_from_action(action);
80
81 /* Non null key is mandatory. */
82 if (!action_incr_value->key) {
83 valid = false;
84 goto end;
85 }
86
87 /* A non-empty session name is mandatory. */
88 if (!action_incr_value->session_name ||
89 strlen(action_incr_value->session_name) == 0) {
90 valid = false;
91 goto end;
92 }
93
94 /* A non-empty map name is mandatory. */
95 if (!action_incr_value->map_name ||
96 strlen(action_incr_value->map_name) == 0) {
97 valid = false;
98 goto end;
99 }
100
101 valid = true;
102 end:
103 return valid;
104 }
105
106 static bool lttng_action_incr_value_is_equal(
107 const struct lttng_action *_a, const struct lttng_action *_b)
108 {
109 bool is_equal = false;
110 const struct lttng_action_incr_value *a, *b;
111
112 a = action_incr_value_from_action_const(_a);
113 b = action_incr_value_from_action_const(_b);
114
115 /* Action is not valid if this is not true. */
116 assert(a->key);
117 assert(b->key);
118 assert(a->session_name);
119 assert(b->session_name);
120 assert(a->map_name);
121 assert(b->map_name);
122
123 if (strcmp(a->session_name, b->session_name)) {
124 goto end;
125 }
126
127 if (strcmp(a->map_name, b->map_name)) {
128 goto end;
129 }
130
131 is_equal = lttng_map_key_is_equal(a->key, b->key);
132
133 end:
134 return is_equal;
135 }
136
137 static int lttng_action_incr_value_serialize(
138 struct lttng_action *action, struct lttng_payload *payload)
139 {
140 struct lttng_action_incr_value *action_incr_value;
141 struct lttng_action_incr_value_comm comm;
142 size_t session_name_len, map_name_len;
143 int ret;
144
145 assert(action);
146 assert(payload);
147
148 action_incr_value = action_incr_value_from_action(action);
149
150 DBG("Serializing increment value action");
151
152 session_name_len = strlen(action_incr_value->session_name) + 1;
153 comm.session_name_len = session_name_len;
154
155 map_name_len = strlen(action_incr_value->map_name) + 1;
156 comm.map_name_len = map_name_len;
157
158 ret = lttng_dynamic_buffer_append(
159 &payload->buffer, &comm, sizeof(comm));
160 if (ret) {
161 ret = -1;
162 goto end;
163 }
164
165 ret = lttng_map_key_serialize(action_incr_value->key, payload);
166 if (ret) {
167 ret = -1;
168 goto end;
169 }
170
171 ret = lttng_dynamic_buffer_append(&payload->buffer,
172 action_incr_value->session_name, session_name_len);
173 if (ret) {
174 ret = -1;
175 goto end;
176 }
177
178 ret = lttng_dynamic_buffer_append(&payload->buffer,
179 action_incr_value->map_name, map_name_len);
180 if (ret) {
181 ret = -1;
182 goto end;
183 }
184
185 ret = 0;
186 end:
187 return ret;
188 }
189
190 static void lttng_action_incr_value_destroy(struct lttng_action *action)
191 {
192 struct lttng_action_incr_value *action_incr_value;
193
194 if (!action) {
195 goto end;
196 }
197
198 action_incr_value = action_incr_value_from_action(action);
199
200 lttng_map_key_destroy(action_incr_value->key);
201
202 free(action_incr_value->session_name);
203 free(action_incr_value->map_name);
204 free(action_incr_value);
205
206 end:
207 return;
208 }
209
210 ssize_t lttng_action_incr_value_create_from_payload(
211 struct lttng_payload_view *view,
212 struct lttng_action **p_action)
213 {
214 ssize_t consumed_len, consumed_key_len, ret;
215 struct lttng_map_key *key = NULL;
216 const struct lttng_action_incr_value_comm *comm;
217 const char *session_name, *map_name;
218 struct lttng_action *action;
219 enum lttng_action_status status;
220
221 action = lttng_action_incr_value_create();
222 if (!action) {
223 consumed_len = -1;
224 goto error;
225 }
226
227 comm = (typeof(comm)) view->buffer.data;
228 consumed_len = sizeof(struct lttng_action_incr_value_comm);
229
230 {
231 struct lttng_payload_view key_view =
232 lttng_payload_view_from_view(view, consumed_len,
233 view->buffer.size - consumed_len);
234
235 if (!lttng_payload_view_is_valid(&key_view)) {
236 consumed_len = -1;
237 goto end;
238 }
239 ret = lttng_map_key_create_from_payload(&key_view, &key);
240 if (ret <= 0) {
241 consumed_len = -1;
242 goto error;
243 }
244 consumed_key_len = ret;
245 }
246
247 consumed_len += consumed_key_len;
248 session_name = (const char *) &comm->data + consumed_key_len;
249
250 if (!lttng_buffer_view_contains_string(
251 &view->buffer, session_name, comm->session_name_len)) {
252 consumed_len = -1;
253 goto error;
254 }
255
256 consumed_len += comm->session_name_len;
257
258 map_name = (const char *) &comm->data + consumed_key_len + comm->session_name_len;
259
260 if (!lttng_buffer_view_contains_string(
261 &view->buffer, map_name, comm->map_name_len)) {
262 consumed_len = -1;
263 goto error;
264 }
265
266 consumed_len += comm->map_name_len;
267
268 status = lttng_action_incr_value_set_key(action, key);
269 /* Ownership is passed to the action. */
270 lttng_map_key_put(key);
271
272 if (status != LTTNG_ACTION_STATUS_OK) {
273 consumed_len = -1;
274 goto error;
275 }
276
277 status = lttng_action_incr_value_set_session_name(
278 action, session_name);
279 if (status != LTTNG_ACTION_STATUS_OK) {
280 consumed_len = -1;
281 goto error;
282 }
283
284 status = lttng_action_incr_value_set_map_name(
285 action, map_name);
286 if (status != LTTNG_ACTION_STATUS_OK) {
287 consumed_len = -1;
288 goto error;
289 }
290
291 *p_action = action;
292 action = NULL;
293 goto end;
294
295 error:
296 lttng_action_incr_value_destroy(action);
297 consumed_len = -1;
298
299 end:
300 return consumed_len;
301 }
302
303 struct lttng_action *lttng_action_incr_value_create(void)
304 {
305 struct lttng_action *action;
306
307 action = zmalloc(sizeof(struct lttng_action_incr_value));
308 if (!action) {
309 goto end;
310 }
311
312 lttng_action_init(action, LTTNG_ACTION_TYPE_INCREMENT_VALUE,
313 lttng_action_incr_value_validate,
314 lttng_action_incr_value_serialize,
315 lttng_action_incr_value_is_equal,
316 lttng_action_incr_value_destroy);
317
318 end:
319 return action;
320 }
321
322 enum lttng_action_status lttng_action_incr_value_set_session_name(
323 struct lttng_action *action, const char *session_name)
324 {
325 struct lttng_action_incr_value *action_incr_value;
326 enum lttng_action_status status;
327
328 if (!action || !IS_INCR_VALUE_ACTION(action) || !session_name ||
329 strlen(session_name) == 0) {
330 status = LTTNG_ACTION_STATUS_INVALID;
331 goto end;
332 }
333
334 action_incr_value = action_incr_value_from_action(action);
335
336 free(action_incr_value->session_name);
337
338 action_incr_value->session_name = strdup(session_name);
339 if (!action_incr_value->session_name) {
340 status = LTTNG_ACTION_STATUS_ERROR;
341 goto end;
342 }
343
344 status = LTTNG_ACTION_STATUS_OK;
345 end:
346 return status;
347 }
348
349 enum lttng_action_status lttng_action_incr_value_get_session_name(
350 const struct lttng_action *action, const char **session_name)
351 {
352 const struct lttng_action_incr_value *action_incr_value;
353 enum lttng_action_status status;
354
355 if (!action || !IS_INCR_VALUE_ACTION(action) || !session_name) {
356 status = LTTNG_ACTION_STATUS_INVALID;
357 goto end;
358 }
359
360 action_incr_value = action_incr_value_from_action_const(action);
361
362 *session_name = action_incr_value->session_name;
363
364 status = LTTNG_ACTION_STATUS_OK;
365 end:
366 return status;
367 }
368
369 enum lttng_action_status lttng_action_incr_value_set_map_name(
370 struct lttng_action *action, const char *map_name)
371 {
372 struct lttng_action_incr_value *action_incr_value;
373 enum lttng_action_status status;
374
375 if (!action || !IS_INCR_VALUE_ACTION(action) || !map_name ||
376 strlen(map_name) == 0) {
377 status = LTTNG_ACTION_STATUS_INVALID;
378 goto end;
379 }
380
381 action_incr_value = action_incr_value_from_action(action);
382
383 free(action_incr_value->map_name);
384
385 action_incr_value->map_name = strdup(map_name);
386 if (!action_incr_value->map_name) {
387 status = LTTNG_ACTION_STATUS_ERROR;
388 goto end;
389 }
390
391 status = LTTNG_ACTION_STATUS_OK;
392 end:
393 return status;
394 }
395
396 enum lttng_action_status lttng_action_incr_value_get_map_name(
397 const struct lttng_action *action, const char **map_name)
398 {
399 const struct lttng_action_incr_value *action_incr_value;
400 enum lttng_action_status status;
401
402 if (!action || !IS_INCR_VALUE_ACTION(action) || !map_name) {
403 status = LTTNG_ACTION_STATUS_INVALID;
404 goto end;
405 }
406
407 action_incr_value = action_incr_value_from_action_const(action);
408
409 *map_name = action_incr_value->map_name;
410
411 status = LTTNG_ACTION_STATUS_OK;
412 end:
413 return status;
414 }
415
416 LTTNG_HIDDEN
417 enum lttng_action_status lttng_action_incr_value_borrow_key_mutable(
418 const struct lttng_action *action, struct lttng_map_key **key)
419 {
420 const struct lttng_action_incr_value *action_incr_value;
421 enum lttng_action_status status;
422
423 if (!action || !IS_INCR_VALUE_ACTION(action) || !key) {
424 status = LTTNG_ACTION_STATUS_INVALID;
425 goto end;
426 }
427
428 action_incr_value = action_incr_value_from_action_const(action);
429
430 *key = action_incr_value->key;
431
432 status = LTTNG_ACTION_STATUS_OK;
433 end:
434 return status;
435 }
436
437 enum lttng_action_status lttng_action_incr_value_get_key(
438 const struct lttng_action *action,
439 const struct lttng_map_key **key)
440 {
441 struct lttng_map_key *mutable_key = NULL;
442 enum lttng_action_status status =
443 lttng_action_incr_value_borrow_key_mutable(
444 action, &mutable_key);
445
446 *key = mutable_key;
447 return status;
448 }
449
450 enum lttng_action_status
451 lttng_action_incr_value_set_key(
452 struct lttng_action *action,
453 struct lttng_map_key *key)
454 {
455 struct lttng_action_incr_value *action_incr_value;
456 enum lttng_action_status status;
457
458 if (!action || !IS_INCR_VALUE_ACTION(action) || !key) {
459 status = LTTNG_ACTION_STATUS_INVALID;
460 goto end;
461 }
462
463 action_incr_value = action_incr_value_from_action(action);
464
465 /* Take a reference to the key. */
466 lttng_map_key_get(key);
467 action_incr_value->key = key;
468
469 status = LTTNG_ACTION_STATUS_OK;
470 end:
471 return status;
472 }
473
474 LTTNG_HIDDEN
475 enum lttng_action_status lttng_action_incr_value_set_tracer_token(
476 struct lttng_action *action, uint64_t token)
477 {
478 struct lttng_action_incr_value *action_incr_value;
479 enum lttng_action_status status;
480
481 if (!action || !IS_INCR_VALUE_ACTION(action)) {
482 status = LTTNG_ACTION_STATUS_INVALID;
483 goto end;
484 }
485
486 action_incr_value = action_incr_value_from_action(action);
487
488 LTTNG_OPTIONAL_SET(&action_incr_value->action_tracer_token, token);
489
490 status = LTTNG_ACTION_STATUS_OK;
491 end:
492 return status;
493 }
494
495 LTTNG_HIDDEN
496 uint64_t lttng_action_incr_value_get_tracer_token(
497 const struct lttng_action *action)
498 {
499 const struct lttng_action_incr_value *action_incr_value;
500
501 assert(action);
502 assert(IS_INCR_VALUE_ACTION(action));
503
504 action_incr_value = action_incr_value_from_action_const(action);
505
506 return LTTNG_OPTIONAL_GET(action_incr_value->action_tracer_token);
507 }
508
This page took 0.040603 seconds and 5 git commands to generate.