Run clang-format on the whole tree
[lttng-tools.git] / src / common / actions / snapshot-session.cpp
CommitLineData
757c48a2
SM
1/*
2 * Copyright (C) 2019 Simon Marchi <simon.marchi@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
c9e313bc
SM
8#include <common/error.hpp>
9#include <common/macros.hpp>
10#include <common/mi-lttng.hpp>
11#include <common/payload-view.hpp>
12#include <common/payload.hpp>
13#include <common/snapshot.hpp>
28ab034a 14
c9e313bc
SM
15#include <lttng/action/action-internal.hpp>
16#include <lttng/action/rate-policy-internal.hpp>
7f4d5b07 17#include <lttng/action/rate-policy.h>
c9e313bc 18#include <lttng/action/snapshot-session-internal.hpp>
757c48a2 19#include <lttng/action/snapshot-session.h>
c9e313bc 20#include <lttng/snapshot-internal.hpp>
d35c7a38 21#include <lttng/snapshot.h>
757c48a2 22
28ab034a
JG
23#include <inttypes.h>
24
757c48a2 25#define IS_SNAPSHOT_SESSION_ACTION(action) \
17182cfd 26 (lttng_action_get_type(action) == LTTNG_ACTION_TYPE_SNAPSHOT_SESSION)
757c48a2 27
f1494934 28namespace {
757c48a2
SM
29struct lttng_action_snapshot_session {
30 struct lttng_action parent;
31
32 /* Owned by this. */
33 char *session_name;
34
35 /*
36 * When non-NULL, use this custom output when taking the snapshot,
37 * rather than the session's registered snapshot output.
38 *
39 * Owned by this.
40 */
41 struct lttng_snapshot_output *output;
7f4d5b07 42 struct lttng_rate_policy *policy;
757c48a2
SM
43};
44
45struct lttng_action_snapshot_session_comm {
46 /* All string lengths include the trailing \0. */
47 uint32_t session_name_len;
48 uint32_t snapshot_output_len;
7f4d5b07 49 uint32_t rate_policy_len;
757c48a2
SM
50
51 /*
52 * Variable data (all strings are null-terminated):
53 *
54 * - session name string
55 * - snapshot output object
d35c7a38 56 * - policy object
757c48a2
SM
57 */
58 char data[];
59} LTTNG_PACKED;
f1494934 60} /* namespace */
757c48a2 61
7f4d5b07 62static const struct lttng_rate_policy *
28ab034a 63lttng_action_snapshot_session_internal_get_rate_policy(const struct lttng_action *action);
2d57482c 64
757c48a2
SM
65static struct lttng_action_snapshot_session *
66action_snapshot_session_from_action(struct lttng_action *action)
67{
a0377dfe 68 LTTNG_ASSERT(action);
757c48a2 69
28ab034a 70 return lttng::utils::container_of(action, &lttng_action_snapshot_session::parent);
757c48a2
SM
71}
72
73static const struct lttng_action_snapshot_session *
74action_snapshot_session_from_action_const(const struct lttng_action *action)
75{
a0377dfe 76 LTTNG_ASSERT(action);
757c48a2 77
28ab034a 78 return lttng::utils::container_of(action, &lttng_action_snapshot_session::parent);
757c48a2
SM
79}
80
81static bool lttng_action_snapshot_session_validate(struct lttng_action *action)
82{
83 bool valid = false;
84 struct lttng_action_snapshot_session *action_snapshot_session;
85
86 if (!action) {
87 goto end;
88 }
89
90 action_snapshot_session = action_snapshot_session_from_action(action);
91
92 /* A non-empty session name is mandatory. */
93 if (!action_snapshot_session->session_name ||
28ab034a 94 strlen(action_snapshot_session->session_name) == 0) {
757c48a2
SM
95 goto end;
96 }
97
98 if (action_snapshot_session->output &&
28ab034a 99 !lttng_snapshot_output_validate(action_snapshot_session->output)) {
757c48a2
SM
100 goto end;
101 }
102
103 valid = true;
104end:
105 return valid;
106}
107
28ab034a
JG
108static bool lttng_action_snapshot_session_is_equal(const struct lttng_action *_a,
109 const struct lttng_action *_b)
757c48a2
SM
110{
111 bool is_equal = false;
112 const struct lttng_action_snapshot_session *a, *b;
113
114 a = action_snapshot_session_from_action_const(_a);
115 b = action_snapshot_session_from_action_const(_b);
116
117 /* Action is not valid if this is not true. */
a0377dfe
FD
118 LTTNG_ASSERT(a->session_name);
119 LTTNG_ASSERT(b->session_name);
757c48a2
SM
120 if (strcmp(a->session_name, b->session_name)) {
121 goto end;
122 }
123
28ab034a 124 if (a->output && b->output && !lttng_snapshot_output_is_equal(a->output, b->output)) {
757c48a2
SM
125 goto end;
126 } else if (!!a->output != !!b->output) {
127 goto end;
128 }
129
7f4d5b07 130 is_equal = lttng_rate_policy_is_equal(a->policy, b->policy);
757c48a2
SM
131end:
132 return is_equal;
133}
134
0c51e8f3 135static size_t serialize_strlen(const char *str)
757c48a2 136{
0c51e8f3 137 return str ? strlen(str) + 1 : 0;
757c48a2
SM
138}
139
28ab034a
JG
140static int lttng_action_snapshot_session_serialize(struct lttng_action *action,
141 struct lttng_payload *payload)
757c48a2
SM
142{
143 struct lttng_action_snapshot_session *action_snapshot_session;
144 struct lttng_action_snapshot_session_comm comm = {};
145 int ret;
146 size_t size_before_comm;
147
a0377dfe
FD
148 LTTNG_ASSERT(action);
149 LTTNG_ASSERT(payload);
757c48a2
SM
150
151 size_before_comm = payload->buffer.size;
757c48a2
SM
152
153 action_snapshot_session = action_snapshot_session_from_action(action);
28ab034a 154 comm.session_name_len = serialize_strlen(action_snapshot_session->session_name);
757c48a2
SM
155
156 /* Add header. */
28ab034a 157 ret = lttng_dynamic_buffer_append(&payload->buffer, &comm, sizeof(comm));
757c48a2
SM
158 if (ret) {
159 goto end;
160 }
161
a0377dfe 162 LTTNG_ASSERT(action_snapshot_session->session_name);
757c48a2 163 DBG("Serializing snapshot session action: session-name: %s",
28ab034a 164 action_snapshot_session->session_name);
757c48a2
SM
165
166 /* Add session name. */
28ab034a
JG
167 ret = lttng_dynamic_buffer_append(
168 &payload->buffer, action_snapshot_session->session_name, comm.session_name_len);
757c48a2
SM
169 if (ret) {
170 goto end;
171 }
172
173 /* Serialize the snapshot output object, if any. */
174 if (action_snapshot_session->output) {
175 const size_t size_before_output = payload->buffer.size;
176 struct lttng_action_snapshot_session_comm *comm_in_payload;
177
28ab034a 178 ret = lttng_snapshot_output_serialize(action_snapshot_session->output, payload);
757c48a2
SM
179 if (ret) {
180 goto end;
181 }
182
28ab034a
JG
183 comm_in_payload =
184 (typeof(comm_in_payload)) (payload->buffer.data + size_before_comm);
d35c7a38 185 /* Adjust action length in header. */
28ab034a 186 comm_in_payload->snapshot_output_len = payload->buffer.size - size_before_output;
757c48a2
SM
187 }
188
7f4d5b07 189 /* Serialize the rate policy. */
d35c7a38
JR
190 {
191 const size_t size_before_output = payload->buffer.size;
192 struct lttng_action_snapshot_session_comm *comm_in_payload;
193
28ab034a 194 ret = lttng_rate_policy_serialize(action_snapshot_session->policy, payload);
d35c7a38
JR
195 if (ret) {
196 ret = -1;
197 goto end;
198 }
199
28ab034a
JG
200 comm_in_payload =
201 (typeof(comm_in_payload)) (payload->buffer.data + size_before_comm);
7f4d5b07 202 /* Adjust rate policy length in header. */
28ab034a 203 comm_in_payload->rate_policy_len = payload->buffer.size - size_before_output;
d35c7a38
JR
204 }
205
757c48a2
SM
206end:
207 return ret;
208}
209
210static void lttng_action_snapshot_session_destroy(struct lttng_action *action)
211{
212 struct lttng_action_snapshot_session *action_snapshot_session;
213
214 if (!action) {
215 goto end;
216 }
217
218 action_snapshot_session = action_snapshot_session_from_action(action);
219
220 free(action_snapshot_session->session_name);
221 lttng_snapshot_output_destroy(action_snapshot_session->output);
7f4d5b07 222 lttng_rate_policy_destroy(action_snapshot_session->policy);
757c48a2
SM
223 free(action_snapshot_session);
224
225end:
226 return;
227}
228
28ab034a
JG
229ssize_t lttng_action_snapshot_session_create_from_payload(struct lttng_payload_view *view,
230 struct lttng_action **p_action)
757c48a2
SM
231{
232 ssize_t consumed_len;
757c48a2
SM
233 const char *variable_data;
234 struct lttng_action *action;
235 enum lttng_action_status status;
236 struct lttng_snapshot_output *snapshot_output = NULL;
7f4d5b07 237 struct lttng_rate_policy *policy = NULL;
3e6e0df2
JG
238 const struct lttng_action_snapshot_session_comm *comm;
239 const struct lttng_payload_view snapshot_session_comm_view =
28ab034a 240 lttng_payload_view_from_view(view, 0, sizeof(*comm));
757c48a2
SM
241
242 action = lttng_action_snapshot_session_create();
243 if (!action) {
244 goto error;
245 }
246
3e6e0df2
JG
247 if (!lttng_payload_view_is_valid(&snapshot_session_comm_view)) {
248 /* Payload not large enough to contain the header. */
249 goto error;
250 }
251
252 comm = (typeof(comm)) snapshot_session_comm_view.buffer.data;
757c48a2
SM
253 variable_data = (const char *) &comm->data;
254
255 consumed_len = sizeof(struct lttng_action_snapshot_session_comm);
256
257 if (!lttng_buffer_view_contains_string(
28ab034a 258 &view->buffer, variable_data, comm->session_name_len)) {
757c48a2
SM
259 goto error;
260 }
261
28ab034a 262 status = lttng_action_snapshot_session_set_session_name(action, variable_data);
757c48a2
SM
263 if (status != LTTNG_ACTION_STATUS_OK) {
264 goto error;
265 }
266
267 variable_data += comm->session_name_len;
268 consumed_len += comm->session_name_len;
269
270 /* If there is a snapshot output object, deserialize it. */
271 if (comm->snapshot_output_len > 0) {
272 ssize_t snapshot_output_consumed_len;
273 enum lttng_action_status action_status;
274 struct lttng_payload_view snapshot_output_buffer_view =
28ab034a 275 lttng_payload_view_from_view(view, consumed_len, comm->snapshot_output_len);
757c48a2 276
3e6e0df2 277 if (!lttng_payload_view_is_valid(&snapshot_output_buffer_view)) {
0c51e8f3 278 ERR("Failed to create buffer view for snapshot output.");
757c48a2
SM
279 goto error;
280 }
281
28ab034a
JG
282 snapshot_output_consumed_len = lttng_snapshot_output_create_from_payload(
283 &snapshot_output_buffer_view, &snapshot_output);
757c48a2 284 if (snapshot_output_consumed_len != comm->snapshot_output_len) {
0c51e8f3 285 ERR("Failed to deserialize snapshot output object: "
28ab034a
JG
286 "consumed-len: %zd, expected-len: %" PRIu32,
287 snapshot_output_consumed_len,
288 comm->snapshot_output_len);
757c48a2
SM
289 goto error;
290 }
291
28ab034a 292 action_status = lttng_action_snapshot_session_set_output(action, snapshot_output);
757c48a2
SM
293 if (action_status != LTTNG_ACTION_STATUS_OK) {
294 goto error;
295 }
296
297 /* Ownership has been transferred to the action. */
298 snapshot_output = NULL;
299 }
300
301 variable_data += comm->snapshot_output_len;
302 consumed_len += comm->snapshot_output_len;
d35c7a38 303
7f4d5b07
JR
304 /* Rate policy. */
305 if (comm->rate_policy_len <= 0) {
306 ERR("Rate policy should be present.");
d35c7a38
JR
307 goto error;
308 }
309 {
7f4d5b07 310 ssize_t rate_policy_consumed_len;
d35c7a38 311 struct lttng_payload_view policy_view =
28ab034a 312 lttng_payload_view_from_view(view, consumed_len, comm->rate_policy_len);
d35c7a38
JR
313
314 if (!lttng_payload_view_is_valid(&policy_view)) {
7f4d5b07 315 ERR("Failed to create buffer view for rate policy.");
d35c7a38
JR
316 goto error;
317 }
318
7f4d5b07 319 rate_policy_consumed_len =
28ab034a 320 lttng_rate_policy_create_from_payload(&policy_view, &policy);
7f4d5b07 321 if (rate_policy_consumed_len < 0) {
d35c7a38
JR
322 goto error;
323 }
324
7f4d5b07
JR
325 if (rate_policy_consumed_len != comm->rate_policy_len) {
326 ERR("Failed to deserialize rate policy object: "
d35c7a38 327 "consumed-len: %zd, expected-len: %" PRIu32,
28ab034a
JG
328 rate_policy_consumed_len,
329 comm->rate_policy_len);
d35c7a38
JR
330 goto error;
331 }
332
28ab034a 333 status = lttng_action_snapshot_session_set_rate_policy(action, policy);
d35c7a38
JR
334 if (status != LTTNG_ACTION_STATUS_OK) {
335 goto error;
336 }
337 }
338
7f4d5b07
JR
339 variable_data += comm->rate_policy_len;
340 consumed_len += comm->rate_policy_len;
d35c7a38 341
757c48a2
SM
342 *p_action = action;
343 action = NULL;
344
345 goto end;
346
347error:
348 consumed_len = -1;
349
350end:
7f4d5b07 351 lttng_rate_policy_destroy(policy);
757c48a2
SM
352 lttng_action_snapshot_session_destroy(action);
353 lttng_snapshot_output_destroy(snapshot_output);
354
355 return consumed_len;
356}
357
28ab034a
JG
358static enum lttng_error_code
359lttng_action_snapshot_session_mi_serialize(const struct lttng_action *action,
360 struct mi_writer *writer)
6a751b95
JR
361{
362 int ret;
363 enum lttng_error_code ret_code;
364 enum lttng_action_status status;
365 const char *session_name = NULL;
366 const struct lttng_snapshot_output *output = NULL;
367 const struct lttng_rate_policy *policy = NULL;
368
a0377dfe
FD
369 LTTNG_ASSERT(action);
370 LTTNG_ASSERT(IS_SNAPSHOT_SESSION_ACTION(action));
6a751b95 371
28ab034a 372 status = lttng_action_snapshot_session_get_session_name(action, &session_name);
a0377dfe
FD
373 LTTNG_ASSERT(status == LTTNG_ACTION_STATUS_OK);
374 LTTNG_ASSERT(session_name != NULL);
6a751b95
JR
375
376 status = lttng_action_snapshot_session_get_rate_policy(action, &policy);
a0377dfe
FD
377 LTTNG_ASSERT(status == LTTNG_ACTION_STATUS_OK);
378 LTTNG_ASSERT(policy != NULL);
6a751b95
JR
379
380 /* Open action snapshot session element. */
28ab034a 381 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_action_snapshot_session);
6a751b95
JR
382 if (ret) {
383 goto mi_error;
384 }
385
386 /* Session name. */
387 ret = mi_lttng_writer_write_element_string(
28ab034a 388 writer, mi_lttng_element_session_name, session_name);
6a751b95
JR
389 if (ret) {
390 goto mi_error;
391 }
392
393 /* Output if any. */
394 status = lttng_action_snapshot_session_get_output(action, &output);
395 if (status == LTTNG_ACTION_STATUS_OK) {
a0377dfe 396 LTTNG_ASSERT(output != NULL);
6a751b95
JR
397 ret_code = lttng_snapshot_output_mi_serialize(output, writer);
398 if (ret_code != LTTNG_OK) {
399 goto end;
400 }
401 } else if (status != LTTNG_ACTION_STATUS_UNSET) {
402 /* This should not happen at this point. */
403 abort();
404 }
405
406 /* Rate policy. */
407 ret_code = lttng_rate_policy_mi_serialize(policy, writer);
408 if (ret_code != LTTNG_OK) {
409 goto end;
410 }
411
412 /* Close action_snapshot_session element. */
413 ret = mi_lttng_writer_close_element(writer);
414 if (ret) {
415 goto mi_error;
416 }
417
418 ret_code = LTTNG_OK;
419 goto end;
420
421mi_error:
422 ret_code = LTTNG_ERR_MI_IO_FAIL;
423end:
424 return ret_code;
425}
426
757c48a2
SM
427struct lttng_action *lttng_action_snapshot_session_create(void)
428{
64803277 429 struct lttng_action_snapshot_session *action_snapshot = NULL;
7f4d5b07 430 struct lttng_rate_policy *policy = NULL;
d35c7a38
JR
431 enum lttng_action_status status;
432
7f4d5b07
JR
433 /* Create a every N = 1 rate policy. */
434 policy = lttng_rate_policy_every_n_create(1);
d35c7a38
JR
435 if (!policy) {
436 goto end;
437 }
757c48a2 438
64803277
SM
439 action_snapshot = zmalloc<lttng_action_snapshot_session>();
440 if (!action_snapshot) {
757c48a2
SM
441 goto end;
442 }
443
64803277 444 lttng_action_init(&action_snapshot->parent,
28ab034a
JG
445 LTTNG_ACTION_TYPE_SNAPSHOT_SESSION,
446 lttng_action_snapshot_session_validate,
447 lttng_action_snapshot_session_serialize,
448 lttng_action_snapshot_session_is_equal,
449 lttng_action_snapshot_session_destroy,
450 lttng_action_snapshot_session_internal_get_rate_policy,
451 lttng_action_generic_add_error_query_results,
452 lttng_action_snapshot_session_mi_serialize);
453
454 status = lttng_action_snapshot_session_set_rate_policy(&action_snapshot->parent, policy);
d35c7a38 455 if (status != LTTNG_ACTION_STATUS_OK) {
64803277
SM
456 lttng_action_destroy(&action_snapshot->parent);
457 action_snapshot = NULL;
d35c7a38
JR
458 goto end;
459 }
460
757c48a2 461end:
7f4d5b07 462 lttng_rate_policy_destroy(policy);
64803277 463 return action_snapshot ? &action_snapshot->parent : nullptr;
757c48a2
SM
464}
465
28ab034a
JG
466enum lttng_action_status lttng_action_snapshot_session_set_session_name(struct lttng_action *action,
467 const char *session_name)
757c48a2
SM
468{
469 struct lttng_action_snapshot_session *action_snapshot_session;
470 enum lttng_action_status status;
471
472 if (!action || !IS_SNAPSHOT_SESSION_ACTION(action) || !session_name ||
28ab034a 473 strlen(session_name) == 0) {
757c48a2
SM
474 status = LTTNG_ACTION_STATUS_INVALID;
475 goto end;
476 }
477
478 action_snapshot_session = action_snapshot_session_from_action(action);
479
480 free(action_snapshot_session->session_name);
481
482 action_snapshot_session->session_name = strdup(session_name);
483 if (!action_snapshot_session->session_name) {
484 status = LTTNG_ACTION_STATUS_ERROR;
485 goto end;
486 }
487
488 status = LTTNG_ACTION_STATUS_OK;
489end:
490 return status;
491}
492
28ab034a
JG
493enum lttng_action_status
494lttng_action_snapshot_session_get_session_name(const struct lttng_action *action,
495 const char **session_name)
757c48a2
SM
496{
497 const struct lttng_action_snapshot_session *action_snapshot_session;
498 enum lttng_action_status status;
499
500 if (!action || !IS_SNAPSHOT_SESSION_ACTION(action) || !session_name) {
501 status = LTTNG_ACTION_STATUS_INVALID;
502 goto end;
503 }
504
505 action_snapshot_session = action_snapshot_session_from_action_const(action);
506
507 if (action_snapshot_session->session_name) {
508 *session_name = action_snapshot_session->session_name;
509 status = LTTNG_ACTION_STATUS_OK;
510 } else {
511 status = LTTNG_ACTION_STATUS_UNSET;
512 }
513
514end:
515
516 return status;
517}
518
28ab034a
JG
519enum lttng_action_status
520lttng_action_snapshot_session_set_output(struct lttng_action *action,
521 struct lttng_snapshot_output *output)
757c48a2
SM
522{
523 struct lttng_action_snapshot_session *action_snapshot_session;
524 enum lttng_action_status status;
525
526 if (!action || !IS_SNAPSHOT_SESSION_ACTION(action) || !output) {
527 status = LTTNG_ACTION_STATUS_INVALID;
528 goto end;
529 }
530
531 action_snapshot_session = action_snapshot_session_from_action(action);
532
533 lttng_snapshot_output_destroy(action_snapshot_session->output);
534 action_snapshot_session->output = output;
535
536 status = LTTNG_ACTION_STATUS_OK;
537
538end:
539 return status;
540}
541
28ab034a
JG
542enum lttng_action_status
543lttng_action_snapshot_session_get_output(const struct lttng_action *action,
544 const struct lttng_snapshot_output **output)
757c48a2
SM
545{
546 const struct lttng_action_snapshot_session *action_snapshot_session;
547 enum lttng_action_status status;
548
28ab034a 549 if (!action || !IS_SNAPSHOT_SESSION_ACTION(action) || !output) {
757c48a2
SM
550 status = LTTNG_ACTION_STATUS_INVALID;
551 goto end;
552 }
553
554 action_snapshot_session = action_snapshot_session_from_action_const(action);
555
556 if (action_snapshot_session->output) {
557 *output = action_snapshot_session->output;
558 status = LTTNG_ACTION_STATUS_OK;
559 } else {
560 status = LTTNG_ACTION_STATUS_UNSET;
561 }
562
563end:
564 return status;
565}
d35c7a38 566
28ab034a
JG
567enum lttng_action_status
568lttng_action_snapshot_session_set_rate_policy(struct lttng_action *action,
569 const struct lttng_rate_policy *policy)
d35c7a38
JR
570{
571 enum lttng_action_status status;
572 struct lttng_action_snapshot_session *snapshot_session_action;
7f4d5b07 573 struct lttng_rate_policy *copy = NULL;
d35c7a38
JR
574
575 if (!action || !policy || !IS_SNAPSHOT_SESSION_ACTION(action)) {
576 status = LTTNG_ACTION_STATUS_INVALID;
577 goto end;
578 }
579
7f4d5b07 580 copy = lttng_rate_policy_copy(policy);
d35c7a38
JR
581 if (!copy) {
582 status = LTTNG_ACTION_STATUS_ERROR;
583 goto end;
584 }
585
586 snapshot_session_action = action_snapshot_session_from_action(action);
587
7f4d5b07
JR
588 /* Free the previous rate policy .*/
589 lttng_rate_policy_destroy(snapshot_session_action->policy);
d35c7a38
JR
590
591 /* Assign the policy. */
592 snapshot_session_action->policy = copy;
593 status = LTTNG_ACTION_STATUS_OK;
594 copy = NULL;
595
596end:
7f4d5b07 597 lttng_rate_policy_destroy(copy);
d35c7a38
JR
598 return status;
599}
600
28ab034a
JG
601enum lttng_action_status
602lttng_action_snapshot_session_get_rate_policy(const struct lttng_action *action,
603 const struct lttng_rate_policy **policy)
d35c7a38
JR
604{
605 enum lttng_action_status status;
606 const struct lttng_action_snapshot_session *snapshot_session_action;
607
608 if (!action || !policy || !IS_SNAPSHOT_SESSION_ACTION(action)) {
609 status = LTTNG_ACTION_STATUS_INVALID;
610 goto end;
611 }
612
28ab034a 613 snapshot_session_action = action_snapshot_session_from_action_const(action);
d35c7a38
JR
614
615 *policy = snapshot_session_action->policy;
616 status = LTTNG_ACTION_STATUS_OK;
617end:
618 return status;
619}
2d57482c 620
7f4d5b07 621static const struct lttng_rate_policy *
28ab034a 622lttng_action_snapshot_session_internal_get_rate_policy(const struct lttng_action *action)
2d57482c
JR
623{
624 const struct lttng_action_snapshot_session *_action;
625 _action = action_snapshot_session_from_action_const(action);
626
627 return _action->policy;
628}
This page took 0.070503 seconds and 4 git commands to generate.