CLI: Add lttng_trace_format_descriptor to lttng_session_extended
[lttng-tools.git] / src / common / session.cpp
1 /*
2 * Copyright (C) 2022 Jonathan Rajotte<jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 */
6
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>
16 #include <memory>
17 #include <stdio.h>
18 #include <time.h>
19
20 struct session_list_element {
21 struct lttng_session *session;
22 };
23
24 static void session_list_destructor(void *ptr)
25 {
26 struct session_list_element *element = (struct session_list_element *) ptr;
27
28 free(element->session);
29 free(element);
30 }
31
32 int lttng_session_serialize(const struct lttng_session *session, lttng_payload *payload)
33 {
34 int ret;
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;
38
39 LTTNG_ASSERT(extended != nullptr);
40
41 name_len = lttng_strnlen(session->name, sizeof(session->name));
42 if (name_len == sizeof(session->name)) {
43 /* Session name is not NULL-terminated. */
44 ret = -1;
45 goto end;
46 }
47
48 /* Add null termination. */
49 name_len += 1;
50
51 path_len = lttng_strnlen(session->path, sizeof(session->path));
52 if (path_len == sizeof(session->path)) {
53 /* Session path is not NULL-terminated. */
54 ret = -1;
55 goto end;
56 }
57
58 /* Add null termination. */
59 path_len += 1;
60
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));
71 } else {
72 LTTNG_OPTIONAL_UNSET(&session_comm.creation_time);
73 }
74
75 /* Header */
76 ret = lttng_dynamic_buffer_append(&payload->buffer, &session_comm, sizeof(session_comm));
77 if (ret) {
78 goto end;
79 }
80
81 /* Session name */
82 ret = lttng_dynamic_buffer_append(&payload->buffer, session->name, name_len);
83 if (ret) {
84 goto end;
85 }
86
87 /* Session path */
88 ret = lttng_dynamic_buffer_append(&payload->buffer, session->path, path_len);
89 if (ret) {
90 goto end;
91 }
92
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);
97 if (ret) {
98 goto end;
99 }
100
101 end:
102 return ret;
103 }
104
105 ssize_t lttng_session_create_from_payload(
106 struct lttng_payload_view *view, struct lttng_session **out_session)
107 {
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;
112
113 LTTNG_ASSERT(out_session);
114 LTTNG_ASSERT(view);
115
116 {
117 struct lttng_payload_view comm_view =
118 lttng_payload_view_from_view(view, offset, sizeof(*session_comm));
119
120 if (!lttng_payload_view_is_valid(&comm_view)) {
121 ret = -1;
122 goto end;
123 }
124
125 /* lttng_session_comm header */
126 session_comm = (typeof(session_comm)) comm_view.buffer.data;
127 offset += sizeof(*session_comm);
128 }
129
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) {
134 ret = -1;
135 goto end;
136 }
137
138 local_extended = (struct lttng_session_extended *) ((char *) local_session +
139 sizeof(lttng_session));
140 if (local_extended == nullptr) {
141 ret = -1;
142 goto end;
143 }
144
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);
150
151 local_session->extended.ptr = local_extended;
152
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));
159 }
160
161 {
162 const char *name;
163 const struct lttng_buffer_view name_view = lttng_buffer_view_from_view(
164 &view->buffer, offset, session_comm->name_len);
165
166 if (!lttng_buffer_view_is_valid(&name_view)) {
167 ret = -1;
168 goto end;
169 }
170
171 name = (const char *) name_view.data;
172
173 if (!lttng_buffer_view_contains_string(&name_view, name, session_comm->name_len)) {
174 ret = -1;
175 goto end;
176 }
177
178 ret = lttng_strncpy(local_session->name, name, sizeof(local_session->name));
179 if (ret) {
180 ret = -1;
181 goto end;
182 }
183
184 offset += session_comm->name_len;
185 }
186
187 {
188 const char *path;
189 const struct lttng_buffer_view path_view = lttng_buffer_view_from_view(
190 &view->buffer, offset, session_comm->path_len);
191
192 if (!lttng_buffer_view_is_valid(&path_view)) {
193 ret = -1;
194 goto end;
195 }
196
197 path = (const char *) path_view.data;
198
199 if (!lttng_buffer_view_contains_string(&path_view, path, session_comm->path_len)) {
200 ret = -1;
201 goto end;
202 }
203
204 ret = lttng_strncpy(local_session->path, path, sizeof(local_session->path));
205 if (ret) {
206 ret = -1;
207 goto end;
208 }
209
210 offset += session_comm->path_len;
211 }
212 {
213 const struct lttng_buffer_view trace_format_view = lttng_buffer_view_from_view(
214 &view->buffer, offset, session_comm->trace_format_descriptor_len);
215
216 if (!lttng_buffer_view_is_valid(&trace_format_view)) {
217 ret = -1;
218 goto end;
219 }
220
221 memcpy((void *) local_extended->serialized_trace_format_descriptor.data,
222 trace_format_view.data, trace_format_view.size);
223
224 offset += session_comm->trace_format_descriptor_len;
225 }
226 /* Transfer ownership to the caller. */
227 *out_session = local_session;
228 local_session = nullptr;
229
230 ret = offset;
231 end:
232 free(local_session);
233 return ret;
234 }
235
236 static enum lttng_error_code compute_flattened_size(
237 struct lttng_dynamic_pointer_array *sessions, size_t *size)
238 {
239 enum lttng_error_code ret_code;
240 size_t storage_req, session_count, i;
241
242 assert(size);
243 assert(sessions);
244
245 session_count = lttng_dynamic_pointer_array_get_count(sessions);
246
247 /* The basic struct lttng_session */
248 storage_req = session_count * sizeof(struct lttng_session);
249
250 /* The struct lttng_session_extended */
251 storage_req += session_count * sizeof(struct lttng_session_extended);
252
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);
256
257 storage_req += ((const struct lttng_session_extended *) (element->session->extended
258 .ptr))
259 ->serialized_trace_format_descriptor.size;
260 }
261
262 *size = storage_req;
263 ret_code = LTTNG_OK;
264
265 return ret_code;
266 }
267
268 static enum lttng_error_code flatten_lttng_sessions(struct lttng_dynamic_pointer_array *sessions,
269 struct lttng_session **flattened_sessions)
270 {
271 enum lttng_error_code ret_code;
272 int ret, i;
273 size_t storage_req;
274 struct lttng_dynamic_buffer local_flattened_sessions;
275 int nb_sessions;
276
277 assert(sessions);
278 assert(flattened_sessions);
279
280 lttng_dynamic_buffer_init(&local_flattened_sessions);
281 nb_sessions = lttng_dynamic_pointer_array_get_count(sessions);
282
283 ret_code = compute_flattened_size(sessions, &storage_req);
284 if (ret_code != LTTNG_OK) {
285 goto end;
286 }
287
288 /*
289 * We must ensure that "local_flattened_sessions" is never resized so as
290 * to preserve the validity of the flattened objects.
291 */
292 ret = lttng_dynamic_buffer_set_capacity(&local_flattened_sessions, storage_req);
293 if (ret) {
294 ret_code = LTTNG_ERR_NOMEM;
295 goto end;
296 }
297
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);
302
303 if (!element) {
304 ret_code = LTTNG_ERR_FATAL;
305 goto end;
306 }
307
308 ret = lttng_dynamic_buffer_append(&local_flattened_sessions, element->session,
309 sizeof(struct lttng_session));
310 if (ret) {
311 ret_code = LTTNG_ERR_NOMEM;
312 goto end;
313 }
314 }
315
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);
325 size_t currentSize;
326
327 assert(element);
328
329 /* Insert struct lttng_session_extended. */
330 ret = lttng_dynamic_buffer_append(&local_flattened_sessions,
331 element->session->extended.ptr, sizeof(*session_extended));
332 if (ret) {
333 ret_code = LTTNG_ERR_NOMEM;
334 goto end;
335 }
336 /* Update the location of the extended protion in the base lttng_session object */
337 session->extended.ptr = session_extended;
338
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);
344 if (ret) {
345 ret_code = LTTNG_ERR_NOMEM;
346 goto end;
347 }
348
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);
354 }
355
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);
359 ret_code = LTTNG_OK;
360 end:
361 lttng_dynamic_buffer_reset(&local_flattened_sessions);
362 return ret_code;
363 }
364
365 static enum lttng_error_code session_list_create_from_payload(struct lttng_payload_view *view,
366 unsigned int count,
367 struct lttng_dynamic_pointer_array *session_list)
368 {
369 enum lttng_error_code ret_code;
370 int ret;
371 unsigned int i;
372 int offset = 0;
373
374 assert(view);
375 assert(session_list);
376
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>();
382
383 if (!element) {
384 ret_code = LTTNG_ERR_NOMEM;
385 goto end;
386 }
387
388 /*
389 * Lifetime and management of the object is now bound to the
390 * array.
391 */
392 ret = lttng_dynamic_pointer_array_add_pointer(session_list, element);
393 if (ret) {
394 session_list_destructor(element);
395 ret_code = LTTNG_ERR_NOMEM;
396 goto end;
397 }
398
399 session_size = lttng_session_create_from_payload(&session_view, &element->session);
400 if (session_size < 0) {
401 ret_code = LTTNG_ERR_INVALID;
402 goto end;
403 }
404
405 offset += session_size;
406 }
407
408 if (view->buffer.size != offset) {
409 ret_code = LTTNG_ERR_INVALID_PROTOCOL;
410 goto end;
411 }
412
413 ret_code = LTTNG_OK;
414
415 end:
416 return ret_code;
417 }
418 enum lttng_error_code lttng_sessions_create_and_flatten_from_payload(
419 struct lttng_payload_view *payload,
420 unsigned int count,
421 struct lttng_session **sessions)
422 {
423 enum lttng_error_code ret = LTTNG_OK;
424 struct lttng_dynamic_pointer_array local_sessions;
425
426 lttng_dynamic_pointer_array_init(&local_sessions, session_list_destructor);
427
428 /* Deserialize the sessions. */
429 {
430 struct lttng_payload_view sessions_view =
431 lttng_payload_view_from_view(payload, 0, -1);
432
433 ret = session_list_create_from_payload(&sessions_view, count, &local_sessions);
434 if (ret != LTTNG_OK) {
435 goto end;
436 }
437 }
438
439 ret = flatten_lttng_sessions(&local_sessions, sessions);
440 if (ret != LTTNG_OK) {
441 goto end;
442 }
443
444 end:
445 lttng_dynamic_pointer_array_reset(&local_sessions);
446 return ret;
447 }
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)
450 {
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;
456
457 if (!session || !session->extended.ptr) {
458 ret_code = LTTNG_ERR_INVALID;
459 goto error;
460 }
461
462 extended = (struct lttng_session_extended *) session->extended.ptr;
463
464 {
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 ||
471 deserialiazed !=
472 extended->serialized_trace_format_descriptor.size) {
473 ret_code = LTTNG_ERR_INVALID;
474 goto error;
475 }
476 }
477
478 local_descriptor = reinterpret_cast<struct lttng_trace_format_descriptor *>(
479 p_trace_format.release());
480
481 *p_lttng_trace_format_descriptor = local_descriptor;
482 local_descriptor = nullptr;
483 ret_code = LTTNG_OK;
484 error:
485 lttng_trace_format_descriptor_destroy(local_descriptor);
486 return ret_code;
487 }
This page took 0.041752 seconds and 5 git commands to generate.