SoW-2019-0007-2: Dynamic Snapshot: Triggers send partial event payload with notifications
[lttng-tools.git] / src / common / actions / snapshot-session.c
CommitLineData
5024c2ac
JR
1/*
2 * Copyright (C) 2019 Simon Marchi <simon.marchi@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8#include <assert.h>
9#include <common/error.h>
10#include <common/macros.h>
11#include <common/snapshot.h>
12#include <lttng/action/action-internal.h>
13#include <lttng/action/snapshot-session-internal.h>
14#include <lttng/action/snapshot-session.h>
15#include <lttng/snapshot.h>
16#include <lttng/snapshot-internal.h>
17#include <inttypes.h>
18
19struct lttng_action_snapshot_session {
20 struct lttng_action parent;
21
22 /* Owned by this. */
23 char *session_name;
24
25 /*
26 * When non-NULL, use this custom output when taking the snapshot,
27 * rather than the session's registered snapshot output.
28 *
29 * Owned by this.
30 */
31 struct lttng_snapshot_output *output;
32};
33
34struct lttng_action_snapshot_session_comm {
35 /* All string lengths include the trailing \0. */
36 uint32_t session_name_len;
37 uint32_t snapshot_output_len;
38
39 /*
40 * Variable data (all strings are null-terminated):
41 *
42 * - session name string
43 * - snapshot output object
44 *
45 */
46 char data[];
47} LTTNG_PACKED;
48
49static struct lttng_action_snapshot_session *
50action_snapshot_session_from_action(struct lttng_action *action)
51{
52 assert(action);
53
54 return container_of(
55 action, struct lttng_action_snapshot_session, parent);
56}
57
58static const struct lttng_action_snapshot_session *
59action_snapshot_session_from_action_const(const struct lttng_action *action)
60{
61 assert(action);
62
63 return container_of(
64 action, struct lttng_action_snapshot_session, parent);
65}
66
67static bool lttng_action_snapshot_session_validate(struct lttng_action *action)
68{
69 bool valid = false;
70 struct lttng_action_snapshot_session *action_snapshot_session;
71
72 if (!action) {
73 goto end;
74 }
75
76 action_snapshot_session = action_snapshot_session_from_action(action);
77
78 /* A non-empty session name is mandatory. */
79 if (!action_snapshot_session->session_name ||
80 strlen(action_snapshot_session->session_name) == 0) {
81 goto end;
82 }
83
84 if (action_snapshot_session->output &&
85 !lttng_snapshot_output_validate(action_snapshot_session->output)) {
86 goto end;
87 }
88
89 valid = true;
90end:
91 return valid;
92}
93
94static bool lttng_action_snapshot_session_is_equal(const struct lttng_action *_a, const struct lttng_action *_b)
95{
96 bool is_equal = false;
97 const struct lttng_action_snapshot_session *a, *b;
98
99 a = action_snapshot_session_from_action_const(_a);
100 b = action_snapshot_session_from_action_const(_b);
101
102 /* Action is not valid if this is not true. */
103 assert(a->session_name);
104 assert(b->session_name);
105 if (strcmp(a->session_name, b->session_name)) {
106 goto end;
107 }
108
109 if (a->output && b->output &&
110 !lttng_snapshot_output_is_equal(a->output, b->output)) {
111 goto end;
112 } else if (!!a->output != !!b->output) {
113 goto end;
114 }
115
116 is_equal = true;
117end:
118 return is_equal;
119}
120
121static size_t serialize_strlen(const char *s)
122{
123
124 size_t len = 0;
125
126 if (s) {
127 len = strlen(s) + 1;
128 }
129
130 return len;
131}
132
133static int lttng_action_snapshot_session_serialize(
134 struct lttng_action *action, struct lttng_dynamic_buffer *buf)
135{
136 struct lttng_action_snapshot_session *action_snapshot_session;
137 struct lttng_action_snapshot_session_comm comm;
138 struct lttng_dynamic_buffer snapshot_output_buf = { 0 };
139 int ret;
140
141 assert(action);
142 assert(buf);
143
144 lttng_dynamic_buffer_init(&snapshot_output_buf);
145
146 action_snapshot_session = action_snapshot_session_from_action(action);
147
148 assert(action_snapshot_session->session_name);
149 DBG("Serializing snapshot session action: session-name: %s",
150 action_snapshot_session->session_name);
151
152 /* Serialize the snapshot output object first, so we know its length. */
153 if (action_snapshot_session->output) {
154 ret = lttng_snapshot_output_serialize(
155 action_snapshot_session->output, &snapshot_output_buf);
156 if (ret) {
157 goto end;
158 }
159 }
160
161 comm.session_name_len =
162 serialize_strlen(action_snapshot_session->session_name);
163 comm.snapshot_output_len = snapshot_output_buf.size;
164
165 ret = lttng_dynamic_buffer_append(buf, &comm, sizeof(comm));
166 if (ret) {
167 goto end;
168 }
169
170 ret = lttng_dynamic_buffer_append(buf,
171 action_snapshot_session->session_name,
172 comm.session_name_len);
173 if (ret) {
174 goto end;
175 }
176
177 ret = lttng_dynamic_buffer_append_buffer(buf, &snapshot_output_buf);
178 if (ret) {
179 goto end;
180 }
181
182end:
183 lttng_dynamic_buffer_reset(&snapshot_output_buf);
184 return ret;
185}
186
187static void lttng_action_snapshot_session_destroy(struct lttng_action *action)
188{
189 struct lttng_action_snapshot_session *action_snapshot_session;
190
191 if (!action) {
192 goto end;
193 }
194
195 action_snapshot_session = action_snapshot_session_from_action(action);
196
197 free(action_snapshot_session->session_name);
198 lttng_snapshot_output_destroy(action_snapshot_session->output);
199 free(action_snapshot_session);
200
201end:
202 return;
203}
204
205ssize_t lttng_action_snapshot_session_create_from_buffer(
206 const struct lttng_buffer_view *view,
207 struct lttng_action **p_action)
208{
209 ssize_t consumed_len;
210 struct lttng_action_snapshot_session_comm *comm;
211 const char *variable_data;
212 struct lttng_action *action;
213 enum lttng_action_status status;
214 struct lttng_snapshot_output *snapshot_output = NULL;
215
216 action = lttng_action_snapshot_session_create();
217 if (!action) {
218 goto error;
219 }
220
221 comm = (struct lttng_action_snapshot_session_comm *) view->data;
222 variable_data = (const char *) &comm->data;
223
224 consumed_len = sizeof(struct lttng_action_snapshot_session_comm);
225
226 if (!lttng_buffer_view_contains_string(
227 view, variable_data, comm->session_name_len)) {
228 goto error;
229 }
230
231 status = lttng_action_snapshot_session_set_session_name(
232 action, variable_data);
233 if (status != LTTNG_ACTION_STATUS_OK) {
234 goto error;
235 }
236
237 variable_data += comm->session_name_len;
238 consumed_len += comm->session_name_len;
239
240 /* If there is a snapshot output object, deserialize it. */
241 if (comm->snapshot_output_len > 0) {
242 ssize_t snapshot_output_consumed_len;
243 enum lttng_action_status action_status;
244 struct lttng_buffer_view snapshot_output_buffer_view =
245 lttng_buffer_view_from_view(view, consumed_len,
246 comm->snapshot_output_len);
247 if (!snapshot_output_buffer_view.data) {
248 fprintf(stderr, "Failed to create buffer view for snapshot output.\n");
249 goto error;
250 }
251
252 snapshot_output_consumed_len =
253 lttng_snapshot_output_create_from_buffer(
254 &snapshot_output_buffer_view,
255 &snapshot_output);
256 if (snapshot_output_consumed_len != comm->snapshot_output_len) {
257 fprintf(stderr,
258 "Failed to deserialize snapshot output object: "
259 "consumed-len: %zd, expected-len: %" PRIu32,
260 snapshot_output_consumed_len,
261 comm->snapshot_output_len);
262 goto error;
263 }
264
265 action_status = lttng_action_snapshot_session_set_output(
266 action, snapshot_output);
267 if (action_status != LTTNG_ACTION_STATUS_OK) {
268 goto error;
269 }
270
271 /* Ownership has been transferred to the action. */
272 snapshot_output = NULL;
273 }
274
275 variable_data += comm->snapshot_output_len;
276 consumed_len += comm->snapshot_output_len;
277 *p_action = action;
278 action = NULL;
279
280 goto end;
281
282error:
283 consumed_len = -1;
284
285end:
286 lttng_action_snapshot_session_destroy(action);
287 lttng_snapshot_output_destroy(snapshot_output);
288
289 return consumed_len;
290}
291
292struct lttng_action *lttng_action_snapshot_session_create(void)
293{
294 struct lttng_action *action;
295
296 action = zmalloc(sizeof(struct lttng_action_snapshot_session));
297 if (!action) {
298 goto end;
299 }
300
301 lttng_action_init(action, LTTNG_ACTION_TYPE_SNAPSHOT_SESSION,
302 lttng_action_snapshot_session_validate,
303 lttng_action_snapshot_session_serialize,
304 lttng_action_snapshot_session_is_equal,
305 lttng_action_snapshot_session_destroy);
306
307end:
308 return action;
309}
310
311enum lttng_action_status lttng_action_snapshot_session_set_session_name(
312 struct lttng_action *action, const char *session_name)
313{
314 struct lttng_action_snapshot_session *action_snapshot_session;
315 enum lttng_action_status status;
316
317 if (!action || !session_name || strlen(session_name) == 0) {
318 status = LTTNG_ACTION_STATUS_INVALID;
319 goto end;
320 }
321
322 action_snapshot_session = action_snapshot_session_from_action(action);
323
324 free(action_snapshot_session->session_name);
325
326 action_snapshot_session->session_name = strdup(session_name);
327 if (!action_snapshot_session->session_name) {
328 status = LTTNG_ACTION_STATUS_ERROR;
329 goto end;
330 }
331
332 status = LTTNG_ACTION_STATUS_OK;
333end:
334 return status;
335}
336
337enum lttng_action_status lttng_action_snapshot_session_get_session_name(
338 const struct lttng_action *action, const char **session_name)
339{
340 const struct lttng_action_snapshot_session *action_snapshot_session;
341 enum lttng_action_status status;
342
343 if (!action || !session_name) {
344 status = LTTNG_ACTION_STATUS_INVALID;
345 goto end;
346 }
347
348 action_snapshot_session = action_snapshot_session_from_action_const(action);
349
350 if (action_snapshot_session->session_name) {
351 *session_name = action_snapshot_session->session_name;
352 status = LTTNG_ACTION_STATUS_OK;
353 } else {
354 status = LTTNG_ACTION_STATUS_UNSET;
355 }
356
357end:
358
359 return status;
360}
361
362enum lttng_action_status lttng_action_snapshot_session_set_output(
363 struct lttng_action *action,
364 struct lttng_snapshot_output *output)
365{
366 struct lttng_action_snapshot_session *action_snapshot_session;
367 enum lttng_action_status status;
368
369 if (!action || !output) {
370 status = LTTNG_ACTION_STATUS_INVALID;
371 goto end;
372 }
373
374 action_snapshot_session = action_snapshot_session_from_action(action);
375
376 lttng_snapshot_output_destroy(action_snapshot_session->output);
377 action_snapshot_session->output = output;
378
379 status = LTTNG_ACTION_STATUS_OK;
380
381end:
382 return status;
383}
384
385enum lttng_action_status lttng_action_snapshot_session_get_output_const(
386 const struct lttng_action *action,
387 const struct lttng_snapshot_output **output)
388{
389 const struct lttng_action_snapshot_session *action_snapshot_session;
390 enum lttng_action_status status;
391
392 if (!action || !output) {
393 status = LTTNG_ACTION_STATUS_INVALID;
394 goto end;
395 }
396
397 action_snapshot_session = action_snapshot_session_from_action_const(action);
398
399 if (action_snapshot_session->output) {
400 *output = action_snapshot_session->output;
401 status = LTTNG_ACTION_STATUS_OK;
402 } else {
403 status = LTTNG_ACTION_STATUS_UNSET;
404 }
405
406end:
407 return status;
408}
This page took 0.039341 seconds and 5 git commands to generate.