2 * Copyright (C) 2022 Jonathan Rajotte<jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
7 #include <common/defaults.hpp>
8 #include <common/error.hpp>
9 #include <common/macros.hpp>
10 #include <common/optional.hpp>
11 #include <common/payload-view.hpp>
12 #include <common/payload.hpp>
13 #include <common/uri.hpp>
14 #include <lttng/session-internal.hpp>
15 #include <lttng/session.h>
20 struct session_list_element
{
21 struct lttng_session
*session
;
24 static void session_list_destructor(void *ptr
)
26 struct session_list_element
*element
= (struct session_list_element
*) ptr
;
28 free(element
->session
);
32 int lttng_session_serialize(const struct lttng_session
*session
, lttng_payload
*payload
)
35 size_t name_len
, path_len
;
36 struct lttng_session_comm session_comm
= {};
37 struct lttng_session_extended
*extended
= (typeof(extended
)) session
->extended
.ptr
;
39 LTTNG_ASSERT(extended
!= nullptr);
41 name_len
= lttng_strnlen(session
->name
, sizeof(session
->name
));
42 if (name_len
== sizeof(session
->name
)) {
43 /* Session name is not NULL-terminated. */
48 /* Add null termination. */
51 path_len
= lttng_strnlen(session
->path
, sizeof(session
->path
));
52 if (path_len
== sizeof(session
->path
)) {
53 /* Session path is not NULL-terminated. */
58 /* Add null termination. */
61 session_comm
.name_len
= (uint32_t) name_len
;
62 session_comm
.path_len
= (uint32_t) path_len
;
63 session_comm
.enabled
= (uint8_t) session
->enabled
;
64 session_comm
.snapshot_mode
= session
->snapshot_mode
;
65 session_comm
.live_timer_interval
= session
->live_timer_interval
;
66 session_comm
.trace_format_descriptor_len
=
67 extended
->serialized_trace_format_descriptor
.size
;
68 if (extended
->creation_time
.is_set
) {
69 LTTNG_OPTIONAL_SET(&session_comm
.creation_time
,
70 LTTNG_OPTIONAL_GET(extended
->creation_time
));
72 LTTNG_OPTIONAL_UNSET(&session_comm
.creation_time
);
76 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &session_comm
, sizeof(session_comm
));
82 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, session
->name
, name_len
);
88 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, session
->path
, path_len
);
93 /* Serialized trace_format_descriptor */
94 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
95 extended
->serialized_trace_format_descriptor
.data
,
96 extended
->serialized_trace_format_descriptor
.size
);
105 ssize_t
lttng_session_create_from_payload(
106 struct lttng_payload_view
*view
, struct lttng_session
**out_session
)
108 ssize_t ret
, offset
= 0;
109 struct lttng_session
*local_session
= nullptr;
110 struct lttng_session_extended
*local_extended
= nullptr;
111 const struct lttng_session_comm
*session_comm
;
113 LTTNG_ASSERT(out_session
);
117 struct lttng_payload_view comm_view
=
118 lttng_payload_view_from_view(view
, offset
, sizeof(*session_comm
));
120 if (!lttng_payload_view_is_valid(&comm_view
)) {
125 /* lttng_session_comm header */
126 session_comm
= (typeof(session_comm
)) comm_view
.buffer
.data
;
127 offset
+= sizeof(*session_comm
);
130 local_session
= zmalloc
<struct lttng_session
>(sizeof(struct lttng_session
) +
131 sizeof(struct lttng_session_extended
) +
132 (size_t) session_comm
->trace_format_descriptor_len
);
133 if (local_session
== nullptr) {
138 local_extended
= (struct lttng_session_extended
*) ((char *) local_session
+
139 sizeof(lttng_session
));
140 if (local_extended
== nullptr) {
145 /* Set the view for serialized_trace_format_descriptor */
146 local_extended
->serialized_trace_format_descriptor
=
147 lttng_buffer_view_init(reinterpret_cast<const char *>(local_extended
),
148 sizeof(struct lttng_session_extended
),
149 (size_t) session_comm
->trace_format_descriptor_len
);
151 local_session
->extended
.ptr
= local_extended
;
153 local_session
->enabled
= session_comm
->enabled
;
154 local_session
->live_timer_interval
= session_comm
->live_timer_interval
;
155 local_session
->snapshot_mode
= session_comm
->snapshot_mode
;
156 if (session_comm
->creation_time
.is_set
) {
157 LTTNG_OPTIONAL_SET(&local_extended
->creation_time
,
158 LTTNG_OPTIONAL_GET(session_comm
->creation_time
));
163 const struct lttng_buffer_view name_view
= lttng_buffer_view_from_view(
164 &view
->buffer
, offset
, session_comm
->name_len
);
166 if (!lttng_buffer_view_is_valid(&name_view
)) {
171 name
= (const char *) name_view
.data
;
173 if (!lttng_buffer_view_contains_string(&name_view
, name
, session_comm
->name_len
)) {
178 ret
= lttng_strncpy(local_session
->name
, name
, sizeof(local_session
->name
));
184 offset
+= session_comm
->name_len
;
189 const struct lttng_buffer_view path_view
= lttng_buffer_view_from_view(
190 &view
->buffer
, offset
, session_comm
->path_len
);
192 if (!lttng_buffer_view_is_valid(&path_view
)) {
197 path
= (const char *) path_view
.data
;
199 if (!lttng_buffer_view_contains_string(&path_view
, path
, session_comm
->path_len
)) {
204 ret
= lttng_strncpy(local_session
->path
, path
, sizeof(local_session
->path
));
210 offset
+= session_comm
->path_len
;
213 const struct lttng_buffer_view trace_format_view
= lttng_buffer_view_from_view(
214 &view
->buffer
, offset
, session_comm
->trace_format_descriptor_len
);
216 if (!lttng_buffer_view_is_valid(&trace_format_view
)) {
221 memcpy((void *) local_extended
->serialized_trace_format_descriptor
.data
,
222 trace_format_view
.data
, trace_format_view
.size
);
224 offset
+= session_comm
->trace_format_descriptor_len
;
226 /* Transfer ownership to the caller. */
227 *out_session
= local_session
;
228 local_session
= nullptr;
236 static enum lttng_error_code
compute_flattened_size(
237 struct lttng_dynamic_pointer_array
*sessions
, size_t *size
)
239 enum lttng_error_code ret_code
;
240 size_t storage_req
, session_count
, i
;
245 session_count
= lttng_dynamic_pointer_array_get_count(sessions
);
247 /* The basic struct lttng_session */
248 storage_req
= session_count
* sizeof(struct lttng_session
);
250 /* The struct lttng_session_extended */
251 storage_req
+= session_count
* sizeof(struct lttng_session_extended
);
253 for (i
= 0; i
< session_count
; i
++) {
254 const struct session_list_element
*element
= (const struct session_list_element
*)
255 lttng_dynamic_pointer_array_get_pointer(sessions
, i
);
257 storage_req
+= ((const struct lttng_session_extended
*) (element
->session
->extended
259 ->serialized_trace_format_descriptor
.size
;
268 static enum lttng_error_code
flatten_lttng_sessions(struct lttng_dynamic_pointer_array
*sessions
,
269 struct lttng_session
**flattened_sessions
)
271 enum lttng_error_code ret_code
;
274 struct lttng_dynamic_buffer local_flattened_sessions
;
278 assert(flattened_sessions
);
280 lttng_dynamic_buffer_init(&local_flattened_sessions
);
281 nb_sessions
= lttng_dynamic_pointer_array_get_count(sessions
);
283 ret_code
= compute_flattened_size(sessions
, &storage_req
);
284 if (ret_code
!= LTTNG_OK
) {
289 * We must ensure that "local_flattened_sessions" is never resized so as
290 * to preserve the validity of the flattened objects.
292 ret
= lttng_dynamic_buffer_set_capacity(&local_flattened_sessions
, storage_req
);
294 ret_code
= LTTNG_ERR_NOMEM
;
298 /* Start by laying the struct lttng_session */
299 for (i
= 0; i
< nb_sessions
; i
++) {
300 const struct session_list_element
*element
= (const struct session_list_element
*)
301 lttng_dynamic_pointer_array_get_pointer(sessions
, i
);
304 ret_code
= LTTNG_ERR_FATAL
;
308 ret
= lttng_dynamic_buffer_append(&local_flattened_sessions
, element
->session
,
309 sizeof(struct lttng_session
));
311 ret_code
= LTTNG_ERR_NOMEM
;
316 for (i
= 0; i
< nb_sessions
; i
++) {
317 const struct session_list_element
*element
= (const struct session_list_element
*)
318 lttng_dynamic_pointer_array_get_pointer(sessions
, i
);
319 struct lttng_session
*session
=
320 (struct lttng_session
*) (local_flattened_sessions
.data
+
321 (sizeof(struct lttng_session
) * i
));
322 struct lttng_session_extended
*session_extended
=
323 (struct lttng_session_extended
*) (local_flattened_sessions
.data
+
324 local_flattened_sessions
.size
);
329 /* Insert struct lttng_session_extended. */
330 ret
= lttng_dynamic_buffer_append(&local_flattened_sessions
,
331 element
->session
->extended
.ptr
, sizeof(*session_extended
));
333 ret_code
= LTTNG_ERR_NOMEM
;
336 /* Update the location of the extended protion in the base lttng_session object */
337 session
->extended
.ptr
= session_extended
;
339 /* Insert serialize_trace_format_descriptor */
340 currentSize
= local_flattened_sessions
.size
;
341 ret
= lttng_dynamic_buffer_append(&local_flattened_sessions
,
342 session_extended
->serialized_trace_format_descriptor
.data
,
343 session_extended
->serialized_trace_format_descriptor
.size
);
345 ret_code
= LTTNG_ERR_NOMEM
;
349 /* Update the view to point at the flattened memory location for
350 * trace_format_descriptor */
351 session_extended
->serialized_trace_format_descriptor
= lttng_buffer_view_init(
352 local_flattened_sessions
.data
, currentSize
,
353 session_extended
->serialized_trace_format_descriptor
.size
);
356 /* Don't reset local_flattened_sessions buffer as we return its content. */
357 *flattened_sessions
= (struct lttng_session
*) local_flattened_sessions
.data
;
358 lttng_dynamic_buffer_init(&local_flattened_sessions
);
361 lttng_dynamic_buffer_reset(&local_flattened_sessions
);
365 static enum lttng_error_code
session_list_create_from_payload(struct lttng_payload_view
*view
,
367 struct lttng_dynamic_pointer_array
*session_list
)
369 enum lttng_error_code ret_code
;
375 assert(session_list
);
377 for (i
= 0; i
< count
; i
++) {
378 ssize_t session_size
;
379 struct lttng_payload_view session_view
=
380 lttng_payload_view_from_view(view
, offset
, -1);
381 struct session_list_element
*element
= zmalloc
<session_list_element
>();
384 ret_code
= LTTNG_ERR_NOMEM
;
389 * Lifetime and management of the object is now bound to the
392 ret
= lttng_dynamic_pointer_array_add_pointer(session_list
, element
);
394 session_list_destructor(element
);
395 ret_code
= LTTNG_ERR_NOMEM
;
399 session_size
= lttng_session_create_from_payload(&session_view
, &element
->session
);
400 if (session_size
< 0) {
401 ret_code
= LTTNG_ERR_INVALID
;
405 offset
+= session_size
;
408 if (view
->buffer
.size
!= offset
) {
409 ret_code
= LTTNG_ERR_INVALID_PROTOCOL
;
418 enum lttng_error_code
lttng_sessions_create_and_flatten_from_payload(
419 struct lttng_payload_view
*payload
,
421 struct lttng_session
**sessions
)
423 enum lttng_error_code ret
= LTTNG_OK
;
424 struct lttng_dynamic_pointer_array local_sessions
;
426 lttng_dynamic_pointer_array_init(&local_sessions
, session_list_destructor
);
428 /* Deserialize the sessions. */
430 struct lttng_payload_view sessions_view
=
431 lttng_payload_view_from_view(payload
, 0, -1);
433 ret
= session_list_create_from_payload(&sessions_view
, count
, &local_sessions
);
434 if (ret
!= LTTNG_OK
) {
439 ret
= flatten_lttng_sessions(&local_sessions
, sessions
);
440 if (ret
!= LTTNG_OK
) {
445 lttng_dynamic_pointer_array_reset(&local_sessions
);
448 enum lttng_error_code
lttng_session_get_trace_format_descriptor(const struct lttng_session
*session
,
449 struct lttng_trace_format_descriptor
**p_lttng_trace_format_descriptor
)
451 lttng_error_code ret_code
;
452 const struct lttng_session_extended
*extended
= nullptr;
453 struct lttng_trace_format_descriptor
*local_descriptor
= nullptr;
454 ssize_t deserialiazed
= 0;
455 lttng::trace_format_descriptor::uptr p_trace_format
;
457 if (!session
|| !session
->extended
.ptr
) {
458 ret_code
= LTTNG_ERR_INVALID
;
462 extended
= (struct lttng_session_extended
*) session
->extended
.ptr
;
465 struct lttng_payload_view view
= lttng_payload_view_from_buffer_view(
466 &extended
->serialized_trace_format_descriptor
, 0,
467 extended
->serialized_trace_format_descriptor
.size
);
468 deserialiazed
= lttng::trace_format_descriptor::create_from_payload(
469 &view
, p_trace_format
);
470 if (deserialiazed
< 0 ||
472 extended
->serialized_trace_format_descriptor
.size
) {
473 ret_code
= LTTNG_ERR_INVALID
;
478 local_descriptor
= reinterpret_cast<struct lttng_trace_format_descriptor
*>(
479 p_trace_format
.release());
481 *p_lttng_trace_format_descriptor
= local_descriptor
;
482 local_descriptor
= nullptr;
485 lttng_trace_format_descriptor_destroy(local_descriptor
);