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