Run clang-format on the whole tree
[lttng-tools.git] / src / common / channel.cpp
CommitLineData
999af9c1
JR
1/*
2 * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
c9e313bc
SM
8#include <common/buffer-view.hpp>
9#include <common/dynamic-array.hpp>
10#include <common/dynamic-buffer.hpp>
11#include <common/error.hpp>
12#include <common/macros.hpp>
13#include <common/sessiond-comm/sessiond-comm.hpp>
28ab034a 14
c9e313bc 15#include <lttng/channel-internal.hpp>
999af9c1
JR
16#include <lttng/channel.h>
17#include <lttng/constant.h>
c9e313bc 18#include <lttng/userspace-probe-internal.hpp>
999af9c1 19
28ab034a
JG
20static enum lttng_error_code flatten_lttng_channels(struct lttng_dynamic_pointer_array *channels,
21 struct lttng_channel **flattened_channels);
999af9c1 22
28ab034a
JG
23static enum lttng_error_code
24channel_list_create_from_buffer(const struct lttng_buffer_view *buffer,
25 uint32_t count,
26 struct lttng_dynamic_pointer_array *channel_list);
999af9c1
JR
27
28static void channel_list_destructor(void *ptr)
29{
30 struct lttng_channel *element = (struct lttng_channel *) ptr;
31
32 lttng_channel_destroy(element);
33}
34
35struct lttng_channel *lttng_channel_copy(const struct lttng_channel *src)
36{
37 struct lttng_channel_extended *extended = nullptr;
38 struct lttng_channel *channel = nullptr, *ret = nullptr;
39
64803277 40 channel = zmalloc<lttng_channel>();
999af9c1
JR
41 if (!channel) {
42 goto end;
43 }
44
45 *channel = *src;
46
47 if (src->attr.extended.ptr) {
64803277 48 extended = zmalloc<lttng_channel_extended>();
999af9c1
JR
49 if (!extended) {
50 goto end;
51 }
52 memcpy(extended, src->attr.extended.ptr, sizeof(*extended));
53 channel->attr.extended.ptr = extended;
54 extended = nullptr;
55 }
56
57 ret = channel;
58 channel = nullptr;
59end:
60 free(channel);
61 free(extended);
62 return ret;
63}
64
65/*
66 * The channel object is NOT populated.
67 */
68struct lttng_channel *lttng_channel_create_internal(void)
69{
70 struct lttng_channel *local_channel = nullptr, *ret = nullptr;
71 struct lttng_channel_extended *extended = nullptr;
72
64803277 73 local_channel = zmalloc<lttng_channel>();
999af9c1
JR
74 if (!local_channel) {
75 goto end;
76 }
77
78 /* Extended struct */
64803277 79 extended = zmalloc<lttng_channel_extended>();
999af9c1
JR
80 if (!extended) {
81 goto end;
82 }
83
84 local_channel->attr.extended.ptr = extended;
85 extended = nullptr;
86
87 ret = local_channel;
88 local_channel = nullptr;
89end:
90 free(extended);
91 free(local_channel);
92 return ret;
93}
94
95ssize_t lttng_channel_create_from_buffer(const struct lttng_buffer_view *view,
28ab034a 96 struct lttng_channel **channel)
999af9c1
JR
97{
98 ssize_t ret, offset = 0;
99 struct lttng_channel *local_channel = nullptr;
100 const struct lttng_channel_comm *channel_comm;
101 struct lttng_channel_extended *extended = nullptr;
102
103 assert(channel);
104
105 if (!view || !channel) {
106 ret = -1;
107 goto end;
108 }
109
110 /*
111 * Create an 'internal' channel since `lttng_create_channel` requires a
112 * domain and we cannot infer the domain from the payload.
113 */
114 local_channel = lttng_channel_create_internal();
115 if (!local_channel) {
116 ret = -1;
117 goto end;
118 }
119
120 extended = (typeof(extended)) local_channel->attr.extended.ptr;
121
122 /* lttng_trigger_comm header */
123 {
124 const struct lttng_buffer_view comm_view =
28ab034a 125 lttng_buffer_view_from_view(view, offset, sizeof(*channel_comm));
999af9c1
JR
126
127 if (!lttng_buffer_view_is_valid(&comm_view)) {
128 ret = -1;
129 goto end;
130 }
131
28ab034a 132 channel_comm = (const struct lttng_channel_comm *) comm_view.data;
999af9c1
JR
133 offset += sizeof(*channel_comm);
134 }
135
136 {
137 const char *name;
138 const struct lttng_buffer_view name_view =
28ab034a 139 lttng_buffer_view_from_view(view, offset, channel_comm->name_len);
999af9c1 140
999af9c1 141 name = name_view.data;
28ab034a 142 if (!lttng_buffer_view_contains_string(&name_view, name, channel_comm->name_len)) {
999af9c1
JR
143 ret = -1;
144 goto end;
145 }
146
28ab034a 147 ret = lttng_strncpy(local_channel->name, name, sizeof(local_channel->name));
2d6df81a
JG
148 if (ret) {
149 goto end;
150 }
151
999af9c1
JR
152 offset += channel_comm->name_len;
153 }
154
155 /* Populate the channel */
156 local_channel->enabled = channel_comm->enabled;
157
158 /* attr */
159 local_channel->attr.overwrite = channel_comm->overwrite;
160 local_channel->attr.subbuf_size = channel_comm->subbuf_size;
161 local_channel->attr.num_subbuf = channel_comm->num_subbuf;
28ab034a
JG
162 local_channel->attr.switch_timer_interval = channel_comm->switch_timer_interval;
163 local_channel->attr.read_timer_interval = channel_comm->read_timer_interval;
999af9c1
JR
164 local_channel->attr.output = (enum lttng_event_output) channel_comm->output;
165 local_channel->attr.tracefile_size = channel_comm->tracefile_size;
166 local_channel->attr.tracefile_count = channel_comm->tracefile_count;
28ab034a 167 local_channel->attr.live_timer_interval = channel_comm->live_timer_interval;
999af9c1
JR
168
169 extended->discarded_events = channel_comm->discarded_events;
170 extended->lost_packets = channel_comm->lost_packets;
171 extended->monitor_timer_interval = channel_comm->monitor_timer_interval;
172 extended->blocking_timeout = channel_comm->blocking_timeout;
173
174 *channel = local_channel;
175 local_channel = nullptr;
176
177 ret = offset;
178end:
179 lttng_channel_destroy(local_channel);
180 return ret;
181}
182
28ab034a 183int lttng_channel_serialize(struct lttng_channel *channel, struct lttng_dynamic_buffer *buf)
999af9c1
JR
184{
185 int ret;
186 size_t name_len;
1c9a0b0e 187 struct lttng_channel_comm channel_comm = {};
999af9c1
JR
188 struct lttng_channel_extended *extended;
189
190 assert(channel);
191 assert(buf);
192
193 extended = (struct lttng_channel_extended *) channel->attr.extended.ptr;
194
195 name_len = lttng_strnlen(channel->name, LTTNG_SYMBOL_NAME_LEN);
196 if (name_len == LTTNG_SYMBOL_NAME_LEN) {
197 /* channel name is not nullptr-terminated. */
198 ret = -1;
199 goto end;
200 }
201
202 /* Include string termination. */
203 name_len += 1;
204
205 /* Base field */
206 channel_comm.name_len = (uint32_t) name_len;
207 channel_comm.enabled = channel->enabled;
208
209 /* attr */
210 channel_comm.overwrite = channel->attr.overwrite;
211 channel_comm.subbuf_size = channel->attr.subbuf_size;
212 channel_comm.num_subbuf = channel->attr.num_subbuf;
28ab034a 213 channel_comm.switch_timer_interval = channel->attr.switch_timer_interval;
999af9c1
JR
214 channel_comm.read_timer_interval = channel->attr.read_timer_interval;
215 channel_comm.output = channel->attr.output;
216 channel_comm.tracefile_size = channel->attr.tracefile_size;
217 channel_comm.tracefile_count = channel->attr.tracefile_count;
218 channel_comm.live_timer_interval = channel->attr.live_timer_interval;
219
220 /* Extended struct */
221 channel_comm.discarded_events = extended->discarded_events;
222 channel_comm.lost_packets = extended->lost_packets;
223 channel_comm.monitor_timer_interval = extended->monitor_timer_interval;
224 channel_comm.blocking_timeout = extended->blocking_timeout;
225
226 /* Header */
28ab034a 227 ret = lttng_dynamic_buffer_append(buf, &channel_comm, sizeof(channel_comm));
999af9c1
JR
228 if (ret) {
229 goto end;
230 }
231
232 /* channel name */
233 ret = lttng_dynamic_buffer_append(buf, channel->name, name_len);
234 if (ret) {
235 goto end;
236 }
237end:
238 return ret;
239}
240
241void lttng_channel_set_default_extended_attr(struct lttng_domain *domain,
28ab034a 242 struct lttng_channel_extended *extended_attr)
999af9c1
JR
243{
244 assert(domain);
245 assert(extended_attr);
246
247 memset(extended_attr, 0, sizeof(*extended_attr));
248
249 switch (domain->type) {
250 case LTTNG_DOMAIN_KERNEL:
28ab034a
JG
251 extended_attr->monitor_timer_interval = DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER;
252 extended_attr->blocking_timeout = DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT;
999af9c1
JR
253 break;
254 case LTTNG_DOMAIN_UST:
255 switch (domain->buf_type) {
256 case LTTNG_BUFFER_PER_UID:
257 extended_attr->monitor_timer_interval =
28ab034a
JG
258 DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER;
259 extended_attr->blocking_timeout = DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT;
999af9c1
JR
260 break;
261 case LTTNG_BUFFER_PER_PID:
262 default:
263 if (extended_attr) {
264 extended_attr->monitor_timer_interval =
28ab034a 265 DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER;
999af9c1 266 extended_attr->blocking_timeout =
28ab034a 267 DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT;
999af9c1
JR
268 }
269 break;
270 }
271 default:
272 /* Default behavior: leave set to 0. */
273 break;
274 }
275}
276
28ab034a
JG
277static enum lttng_error_code
278channel_list_create_from_buffer(const struct lttng_buffer_view *view,
279 unsigned int count,
280 struct lttng_dynamic_pointer_array *channel_list)
999af9c1
JR
281{
282 enum lttng_error_code ret_code;
283 int ret, i;
284 int offset = 0;
285
286 assert(view);
287 assert(channel_list);
288
289 for (i = 0; i < count; i++) {
290 ssize_t channel_size;
291 struct lttng_channel *channel = nullptr;
292 const struct lttng_buffer_view channel_view =
28ab034a 293 lttng_buffer_view_from_view(view, offset, -1);
999af9c1 294
28ab034a 295 channel_size = lttng_channel_create_from_buffer(&channel_view, &channel);
999af9c1
JR
296 if (channel_size < 0) {
297 ret_code = LTTNG_ERR_INVALID;
298 goto end;
299 }
300
301 /* Lifetime and management of the object is now bound to the array. */
302 ret = lttng_dynamic_pointer_array_add_pointer(channel_list, channel);
303 if (ret) {
304 lttng_channel_destroy(channel);
305 ret_code = LTTNG_ERR_NOMEM;
306 goto end;
307 }
308 offset += channel_size;
309 }
310
311 if (view->size != offset) {
312 ret_code = LTTNG_ERR_INVALID;
313 goto end;
314 }
315
316 ret_code = LTTNG_OK;
317
318end:
319 return ret_code;
320}
321
322static enum lttng_error_code flatten_lttng_channels(struct lttng_dynamic_pointer_array *channels,
28ab034a 323 struct lttng_channel **flattened_channels)
999af9c1
JR
324{
325 enum lttng_error_code ret_code;
326 int ret, i;
327 size_t storage_req = 0;
328 struct lttng_dynamic_buffer local_flattened_channels;
329 int nb_channels;
330
331 assert(channels);
332 assert(flattened_channels);
333
334 lttng_dynamic_buffer_init(&local_flattened_channels);
335 nb_channels = lttng_dynamic_pointer_array_get_count(channels);
336
337 storage_req += sizeof(struct lttng_channel) * nb_channels;
338 storage_req += sizeof(struct lttng_channel_extended) * nb_channels;
339
340 /*
341 * We must ensure that "local_flattened_channels" is never resized so as
342 * to preserve the validity of the flattened objects.
343 */
28ab034a 344 ret = lttng_dynamic_buffer_set_capacity(&local_flattened_channels, storage_req);
999af9c1
JR
345 if (ret) {
346 ret_code = LTTNG_ERR_NOMEM;
347 goto end;
348 }
349
350 /* Start by laying the struct lttng_channel */
351 for (i = 0; i < nb_channels; i++) {
28ab034a
JG
352 const auto *element =
353 (const struct lttng_channel *) lttng_dynamic_pointer_array_get_pointer(
354 channels, i);
999af9c1
JR
355
356 if (!element) {
357 ret_code = LTTNG_ERR_FATAL;
358 goto end;
359 }
360
28ab034a
JG
361 ret = lttng_dynamic_buffer_append(
362 &local_flattened_channels, element, sizeof(struct lttng_channel));
999af9c1
JR
363 if (ret) {
364 ret_code = LTTNG_ERR_NOMEM;
365 goto end;
366 }
367 }
368
369 /* Flatten the extended data */
370 for (i = 0; i < nb_channels; i++) {
28ab034a
JG
371 const auto *element =
372 (const struct lttng_channel *) lttng_dynamic_pointer_array_get_pointer(
373 channels, i);
999af9c1
JR
374 /*
375 * Sample the location of the flattened channel we are about
376 * to modify.
377 */
28ab034a
JG
378 auto *channel = (struct lttng_channel *) (local_flattened_channels.data +
379 (sizeof(struct lttng_channel) * i));
999af9c1
JR
380 /*
381 * Sample the location of the extended attributes we are about
382 * to add.
383 */
28ab034a
JG
384 const auto *channel_extended =
385 (struct lttng_channel_extended *) (local_flattened_channels.data +
386 local_flattened_channels.size);
999af9c1
JR
387
388 if (!element) {
389 ret_code = LTTNG_ERR_FATAL;
390 goto end;
391 }
392
393 ret = lttng_dynamic_buffer_append(&local_flattened_channels,
28ab034a
JG
394 element->attr.extended.ptr,
395 sizeof(struct lttng_channel_extended));
999af9c1
JR
396 if (ret) {
397 ret_code = LTTNG_ERR_NOMEM;
398 goto end;
399 }
400
401 /*
402 * Update the flattened lttng_channel object with its flattened
403 * extended object location.
404 */
405 channel->attr.extended.ptr = (void *) channel_extended;
406 }
407
408 /* Don't reset local_flattened_channels buffer as we return its content. */
409 *flattened_channels = (struct lttng_channel *) local_flattened_channels.data;
410 lttng_dynamic_buffer_init(&local_flattened_channels);
411 ret_code = LTTNG_OK;
412end:
413 lttng_dynamic_buffer_reset(&local_flattened_channels);
414 return ret_code;
415}
416
417enum lttng_error_code lttng_channels_create_and_flatten_from_buffer(
28ab034a 418 const struct lttng_buffer_view *view, uint32_t count, struct lttng_channel **channels)
999af9c1
JR
419{
420 enum lttng_error_code ret_code;
421 struct lttng_dynamic_pointer_array local_channels;
422
423 lttng_dynamic_pointer_array_init(&local_channels, channel_list_destructor);
424
425 /* Deserialize the channels */
426 {
427 const struct lttng_buffer_view channels_view =
28ab034a 428 lttng_buffer_view_from_view(view, 0, -1);
999af9c1 429
28ab034a 430 ret_code = channel_list_create_from_buffer(&channels_view, count, &local_channels);
999af9c1
JR
431 if (ret_code != LTTNG_OK) {
432 goto end;
433 }
434 }
435
436 ret_code = flatten_lttng_channels(&local_channels, channels);
437
438end:
439 lttng_dynamic_pointer_array_reset(&local_channels);
440 return ret_code;
441}
This page took 0.048462 seconds and 4 git commands to generate.