2 * Copyright (C) 2019 EfficiOS, Inc.
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <common/error.h>
20 #include <common/macros.h>
21 #include <common/snapshot.h>
22 #include <lttng/action/action-internal.h>
23 #include <lttng/action/snapshot-session-internal.h>
24 #include <lttng/action/snapshot-session.h>
25 #include <lttng/snapshot.h>
26 #include <lttng/snapshot-internal.h>
29 struct lttng_action_snapshot_session
{
30 struct lttng_action parent
;
36 * When non-NULL, use this custom output when taking the snapshot,
37 * rather than the session's registered snapshot output.
41 struct lttng_snapshot_output
*output
;
44 struct lttng_action_snapshot_session_comm
{
45 /* All string lengths include the trailing \0. */
46 uint32_t session_name_len
;
47 uint32_t snapshot_output_len
;
50 * Variable data (all strings are null-terminated):
52 * - session name string
53 * - snapshot output object
59 static struct lttng_action_snapshot_session
*
60 action_snapshot_session_from_action(struct lttng_action
*action
)
65 action
, struct lttng_action_snapshot_session
, parent
);
68 static const struct lttng_action_snapshot_session
*
69 action_snapshot_session_from_action_const(const struct lttng_action
*action
)
74 action
, struct lttng_action_snapshot_session
, parent
);
77 static bool lttng_action_snapshot_session_validate(struct lttng_action
*action
)
80 struct lttng_action_snapshot_session
*action_snapshot_session
;
86 action_snapshot_session
= action_snapshot_session_from_action(action
);
88 /* A non-empty session name is mandatory. */
89 if (!action_snapshot_session
->session_name
||
90 strlen(action_snapshot_session
->session_name
) == 0) {
94 if (action_snapshot_session
->output
&&
95 !lttng_snapshot_output_validate(action_snapshot_session
->output
)) {
104 static bool lttng_action_snapshot_session_is_equal(const struct lttng_action
*_a
, const struct lttng_action
*_b
)
106 bool is_equal
= false;
107 const struct lttng_action_snapshot_session
*a
, *b
;
109 a
= action_snapshot_session_from_action_const(_a
);
110 b
= action_snapshot_session_from_action_const(_b
);
112 /* Action is not valid if this is not true. */
113 assert(a
->session_name
);
114 assert(b
->session_name
);
115 if (strcmp(a
->session_name
, b
->session_name
)) {
119 if (a
->output
&& b
->output
&&
120 !lttng_snapshot_output_is_equal(a
->output
, b
->output
)) {
122 } else if (!!a
->output
!= !!b
->output
) {
131 static size_t serialize_strlen(const char *s
)
143 static int lttng_action_snapshot_session_serialize(
144 struct lttng_action
*action
, struct lttng_dynamic_buffer
*buf
)
146 struct lttng_action_snapshot_session
*action_snapshot_session
;
147 struct lttng_action_snapshot_session_comm comm
;
148 struct lttng_dynamic_buffer snapshot_output_buf
= { 0 };
154 lttng_dynamic_buffer_init(&snapshot_output_buf
);
156 action_snapshot_session
= action_snapshot_session_from_action(action
);
158 assert(action_snapshot_session
->session_name
);
159 DBG("Serializing snapshot session action: session-name: %s",
160 action_snapshot_session
->session_name
);
162 /* Serialize the snapshot output object first, so we know its length. */
163 if (action_snapshot_session
->output
) {
164 ret
= lttng_snapshot_output_serialize(
165 action_snapshot_session
->output
, &snapshot_output_buf
);
171 comm
.session_name_len
=
172 serialize_strlen(action_snapshot_session
->session_name
);
173 comm
.snapshot_output_len
= snapshot_output_buf
.size
;
175 ret
= lttng_dynamic_buffer_append(buf
, &comm
, sizeof(comm
));
180 ret
= lttng_dynamic_buffer_append(buf
,
181 action_snapshot_session
->session_name
,
182 comm
.session_name_len
);
187 ret
= lttng_dynamic_buffer_append_buffer(buf
, &snapshot_output_buf
);
193 lttng_dynamic_buffer_reset(&snapshot_output_buf
);
197 static void lttng_action_snapshot_session_destroy(struct lttng_action
*action
)
199 struct lttng_action_snapshot_session
*action_snapshot_session
;
205 action_snapshot_session
= action_snapshot_session_from_action(action
);
207 free(action_snapshot_session
->session_name
);
208 lttng_snapshot_output_destroy(action_snapshot_session
->output
);
209 free(action_snapshot_session
);
215 ssize_t
lttng_action_snapshot_session_create_from_buffer(
216 const struct lttng_buffer_view
*view
,
217 struct lttng_action
**p_action
)
219 ssize_t consumed_len
;
220 struct lttng_action_snapshot_session_comm
*comm
;
221 const char *variable_data
;
222 struct lttng_action
*action
;
223 enum lttng_action_status status
;
224 struct lttng_snapshot_output
*snapshot_output
= NULL
;
226 action
= lttng_action_snapshot_session_create();
231 comm
= (struct lttng_action_snapshot_session_comm
*) view
->data
;
232 variable_data
= (const char *) &comm
->data
;
234 consumed_len
= sizeof(struct lttng_action_snapshot_session_comm
);
236 if (!lttng_buffer_view_validate_string(
237 view
, variable_data
, comm
->session_name_len
)) {
241 status
= lttng_action_snapshot_session_set_session_name(
242 action
, variable_data
);
243 if (status
!= LTTNG_ACTION_STATUS_OK
) {
247 variable_data
+= comm
->session_name_len
;
248 consumed_len
+= comm
->session_name_len
;
250 /* If there is a snapshot output object, deserialize it. */
251 if (comm
->snapshot_output_len
> 0) {
252 ssize_t snapshot_output_consumed_len
;
253 enum lttng_action_status action_status
;
254 struct lttng_buffer_view snapshot_output_buffer_view
=
255 lttng_buffer_view_from_view(view
, consumed_len
,
256 comm
->snapshot_output_len
);
257 if (!snapshot_output_buffer_view
.data
) {
258 fprintf(stderr
, "Failed to create buffer view for snapshot output.\n");
262 snapshot_output_consumed_len
=
263 lttng_snapshot_output_create_from_buffer(
264 &snapshot_output_buffer_view
, &snapshot_output
);
265 if (snapshot_output_consumed_len
!= comm
->snapshot_output_len
) {
266 fprintf(stderr
, "Failed to deserialize snapshot output object: "
267 "consumed-len: %zd, expected-len: %" PRIu32
,
268 snapshot_output_consumed_len
,
269 comm
->snapshot_output_len
);
273 action_status
= lttng_action_snapshot_session_set_output(
274 action
, snapshot_output
);
275 if (action_status
!= LTTNG_ACTION_STATUS_OK
) {
279 /* Ownership has been transferred to the action. */
280 snapshot_output
= NULL
;
283 variable_data
+= comm
->snapshot_output_len
;
284 consumed_len
+= comm
->snapshot_output_len
;
295 lttng_action_snapshot_session_destroy(action
);
296 lttng_snapshot_output_destroy(snapshot_output
);
301 struct lttng_action
*lttng_action_snapshot_session_create(void)
303 struct lttng_action
*action
;
305 action
= zmalloc(sizeof(struct lttng_action_snapshot_session
));
310 lttng_action_init(action
, LTTNG_ACTION_TYPE_SNAPSHOT_SESSION
,
311 lttng_action_snapshot_session_validate
,
312 lttng_action_snapshot_session_serialize
,
313 lttng_action_snapshot_session_is_equal
,
314 lttng_action_snapshot_session_destroy
);
320 enum lttng_action_status
lttng_action_snapshot_session_set_session_name(
321 struct lttng_action
*action
, const char *session_name
)
323 struct lttng_action_snapshot_session
*action_snapshot_session
;
324 enum lttng_action_status status
;
326 if (!action
|| !session_name
|| strlen(session_name
) == 0) {
327 status
= LTTNG_ACTION_STATUS_INVALID
;
331 action_snapshot_session
= action_snapshot_session_from_action(action
);
333 free(action_snapshot_session
->session_name
);
335 action_snapshot_session
->session_name
= strdup(session_name
);
336 if (!action_snapshot_session
->session_name
) {
337 status
= LTTNG_ACTION_STATUS_ERROR
;
341 status
= LTTNG_ACTION_STATUS_OK
;
346 enum lttng_action_status
lttng_action_snapshot_session_get_session_name(
347 const struct lttng_action
*action
, const char **session_name
)
349 const struct lttng_action_snapshot_session
*action_snapshot_session
;
350 enum lttng_action_status status
;
352 if (!action
|| !session_name
) {
353 status
= LTTNG_ACTION_STATUS_INVALID
;
357 action_snapshot_session
= action_snapshot_session_from_action_const(action
);
359 if (action_snapshot_session
->session_name
) {
360 *session_name
= action_snapshot_session
->session_name
;
361 status
= LTTNG_ACTION_STATUS_OK
;
363 status
= LTTNG_ACTION_STATUS_UNSET
;
371 enum lttng_action_status
lttng_action_snapshot_session_set_output(
372 struct lttng_action
*action
,
373 struct lttng_snapshot_output
*output
)
375 struct lttng_action_snapshot_session
*action_snapshot_session
;
376 enum lttng_action_status status
;
378 if (!action
|| !output
) {
379 status
= LTTNG_ACTION_STATUS_INVALID
;
383 action_snapshot_session
= action_snapshot_session_from_action(action
);
385 lttng_snapshot_output_destroy(action_snapshot_session
->output
);
386 action_snapshot_session
->output
= output
;
388 status
= LTTNG_ACTION_STATUS_OK
;
394 enum lttng_action_status
lttng_action_snapshot_session_get_output_const(
395 const struct lttng_action
*action
,
396 const struct lttng_snapshot_output
**output
)
398 const struct lttng_action_snapshot_session
*action_snapshot_session
;
399 enum lttng_action_status status
;
401 if (!action
|| !output
) {
402 status
= LTTNG_ACTION_STATUS_INVALID
;
406 action_snapshot_session
= action_snapshot_session_from_action_const(action
);
408 if (action_snapshot_session
->output
) {
409 *output
= action_snapshot_session
->output
;
410 status
= LTTNG_ACTION_STATUS_OK
;
412 status
= LTTNG_ACTION_STATUS_UNSET
;