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