Tests: Add test to check shared-memory FD leaks after relayd dies
[lttng-tools.git] / src / common / location.c
1 /*
2 * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <lttng/location-internal.h>
9 #include <common/macros.h>
10 #include <stdlib.h>
11 #include <common/error.h>
12
13 static
14 struct lttng_trace_archive_location *lttng_trace_archive_location_create(
15 enum lttng_trace_archive_location_type type)
16 {
17 struct lttng_trace_archive_location *location;
18
19 location = zmalloc(sizeof(*location));
20 if (!location) {
21 goto end;
22 }
23
24 urcu_ref_init(&location->ref);
25 location->type = type;
26 end:
27 return location;
28 }
29
30 static
31 void trace_archive_location_destroy_ref(struct urcu_ref *ref)
32 {
33 struct lttng_trace_archive_location *location =
34 container_of(ref, struct lttng_trace_archive_location, ref);
35
36 switch (location->type) {
37 case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL:
38 free(location->types.local.absolute_path);
39 break;
40 case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY:
41 free(location->types.relay.host);
42 free(location->types.relay.relative_path);
43 break;
44 default:
45 abort();
46 }
47
48 free(location);
49 }
50
51 void lttng_trace_archive_location_get(struct lttng_trace_archive_location *location)
52 {
53 urcu_ref_get(&location->ref);
54 }
55
56 void lttng_trace_archive_location_put(struct lttng_trace_archive_location *location)
57 {
58 if (!location) {
59 return;
60 }
61
62 urcu_ref_put(&location->ref, trace_archive_location_destroy_ref);
63 }
64
65 struct lttng_trace_archive_location *lttng_trace_archive_location_local_create(
66 const char *absolute_path)
67 {
68 struct lttng_trace_archive_location *location = NULL;
69
70 if (!absolute_path) {
71 goto end;
72 }
73
74 location = lttng_trace_archive_location_create(
75 LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL);
76 if (!location) {
77 goto end;
78 }
79
80 location->types.local.absolute_path = strdup(absolute_path);
81 if (!location->types.local.absolute_path) {
82 goto error;
83 }
84
85 end:
86 return location;
87 error:
88 lttng_trace_archive_location_put(location);
89 return NULL;
90 }
91
92 struct lttng_trace_archive_location *lttng_trace_archive_location_relay_create(
93 const char *host,
94 enum lttng_trace_archive_location_relay_protocol_type protocol,
95 uint16_t control_port, uint16_t data_port,
96 const char *relative_path)
97 {
98 struct lttng_trace_archive_location *location = NULL;
99
100 if (!host || !relative_path) {
101 goto end;
102 }
103
104 location = lttng_trace_archive_location_create(
105 LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY);
106 if (!location) {
107 goto end;
108 }
109
110 location->types.relay.host = strdup(host);
111 if (!location->types.relay.host) {
112 goto error;
113 }
114 location->types.relay.relative_path = strdup(relative_path);
115 if (!location->types.relay.relative_path) {
116 goto error;
117 }
118
119 location->types.relay.protocol = protocol;
120 location->types.relay.ports.control = control_port;
121 location->types.relay.ports.data = data_port;
122 end:
123 return location;
124 error:
125 lttng_trace_archive_location_put(location);
126 return NULL;
127 }
128
129 ssize_t lttng_trace_archive_location_create_from_buffer(
130 const struct lttng_buffer_view *view,
131 struct lttng_trace_archive_location **location)
132 {
133 size_t offset = 0;
134 const struct lttng_trace_archive_location_comm *location_comm;
135 struct lttng_buffer_view location_comm_view;
136
137 location_comm_view = lttng_buffer_view_from_view(view, 0,
138 sizeof(*location_comm));
139 if (!lttng_buffer_view_is_valid(&location_comm_view)) {
140 goto error;
141 }
142
143 offset += location_comm_view.size;
144 location_comm = (const struct lttng_trace_archive_location_comm *) location_comm_view.data;
145
146 switch ((enum lttng_trace_archive_location_type) location_comm->type) {
147 case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL:
148 {
149 const struct lttng_buffer_view absolute_path_view =
150 lttng_buffer_view_from_view(view, offset,
151 location_comm->types.local.absolute_path_len);
152
153 if (!lttng_buffer_view_is_valid(&absolute_path_view)) {
154 goto error;
155 }
156
157 if (absolute_path_view.data[absolute_path_view.size - 1] != '\0') {
158 goto error;
159 }
160 offset += absolute_path_view.size;
161
162 *location = lttng_trace_archive_location_local_create(
163 absolute_path_view.data);
164 if (!*location) {
165 goto error;
166 }
167 break;
168 }
169 case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY:
170 {
171 const struct lttng_buffer_view hostname_view =
172 lttng_buffer_view_from_view(view, offset,
173 location_comm->types.relay.hostname_len);
174 const struct lttng_buffer_view relative_path_view =
175 lttng_buffer_view_from_view(view,
176 offset + hostname_view.size,
177 location_comm->types.relay.relative_path_len);
178
179 if (!lttng_buffer_view_is_valid(&hostname_view) ||
180 !lttng_buffer_view_is_valid(
181 &relative_path_view)) {
182 goto error;
183 }
184
185 if (hostname_view.data[hostname_view.size - 1] != '\0') {
186 goto error;
187 }
188 if (relative_path_view.data[relative_path_view.size - 1] != '\0') {
189 goto error;
190 }
191 offset += hostname_view.size + relative_path_view.size;
192
193 *location = lttng_trace_archive_location_relay_create(
194 hostname_view.data,
195 (enum lttng_trace_archive_location_relay_protocol_type) location_comm->types.relay.protocol,
196 location_comm->types.relay.ports.control,
197 location_comm->types.relay.ports.data,
198 relative_path_view.data);
199 if (!*location) {
200 goto error;
201 }
202 break;
203 }
204 default:
205 goto error;
206 }
207
208 return offset;
209 error:
210 return -1;
211 }
212
213 ssize_t lttng_trace_archive_location_serialize(
214 const struct lttng_trace_archive_location *location,
215 struct lttng_dynamic_buffer *buffer)
216 {
217 int ret;
218 struct lttng_trace_archive_location_comm location_comm;
219
220 location_comm.type = (int8_t) location->type;
221
222 switch (location->type) {
223 case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL:
224 location_comm.types.local.absolute_path_len =
225 strlen(location->types.local.absolute_path) + 1;
226 break;
227 case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY:
228 location_comm.types.relay.hostname_len =
229 strlen(location->types.relay.host) + 1;
230 location_comm.types.relay.protocol =
231 (int8_t) location->types.relay.protocol;
232 location_comm.types.relay.ports.control =
233 location->types.relay.ports.control;
234 location_comm.types.relay.ports.data =
235 location->types.relay.ports.data;
236 location_comm.types.relay.relative_path_len =
237 strlen(location->types.relay.relative_path) + 1;
238 break;
239 default:
240 abort();
241 }
242
243 ret = lttng_dynamic_buffer_append(buffer, &location_comm,
244 sizeof(location_comm));
245 if (ret) {
246 goto error;
247 }
248
249 switch (location->type) {
250 case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL:
251 ret = lttng_dynamic_buffer_append(buffer,
252 location->types.local.absolute_path,
253 location_comm.types.local.absolute_path_len);
254 if (ret) {
255 goto error;
256 }
257 break;
258 case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY:
259 ret = lttng_dynamic_buffer_append(buffer,
260 location->types.relay.host,
261 location_comm.types.relay.hostname_len);
262 if (ret) {
263 goto error;
264 }
265 ret = lttng_dynamic_buffer_append(buffer,
266 location->types.relay.relative_path,
267 location_comm.types.relay.relative_path_len);
268 if (ret) {
269 goto error;
270 }
271 break;
272 default:
273 abort();
274 }
275
276 return 0;
277 error:
278 return -1;
279 }
280
281 enum lttng_trace_archive_location_type lttng_trace_archive_location_get_type(
282 const struct lttng_trace_archive_location *location)
283 {
284 enum lttng_trace_archive_location_type type;
285
286 if (!location) {
287 type = LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_UNKNOWN;
288 goto end;
289 }
290
291 type = location->type;
292 end:
293 return type;
294 }
295
296 enum lttng_trace_archive_location_status
297 lttng_trace_archive_location_local_get_absolute_path(
298 const struct lttng_trace_archive_location *location,
299 const char **absolute_path)
300 {
301 enum lttng_trace_archive_location_status status =
302 LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK;
303
304 if (!location || !absolute_path ||
305 location->type != LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL) {
306 status = LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_INVALID;
307 goto end;
308 }
309
310 *absolute_path = location->types.local.absolute_path;
311 end:
312 return status;
313 }
314
315 enum lttng_trace_archive_location_status
316 lttng_trace_archive_location_relay_get_host(
317 const struct lttng_trace_archive_location *location,
318 const char **relay_host)
319 {
320 enum lttng_trace_archive_location_status status =
321 LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK;
322
323 if (!location || !relay_host ||
324 location->type != LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY) {
325 status = LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_INVALID;
326 goto end;
327 }
328
329 *relay_host = location->types.relay.host;
330 end:
331 return status;
332 }
333
334 enum lttng_trace_archive_location_status
335 lttng_trace_archive_location_relay_get_relative_path(
336 const struct lttng_trace_archive_location *location,
337 const char **relative_path)
338 {
339 enum lttng_trace_archive_location_status status =
340 LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK;
341
342 if (!location || !relative_path ||
343 location->type != LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY) {
344 status = LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_INVALID;
345 goto end;
346 }
347
348 *relative_path = location->types.relay.relative_path;
349 end:
350 return status;
351 }
352
353 enum lttng_trace_archive_location_status
354 lttng_trace_archive_location_relay_get_control_port(
355 const struct lttng_trace_archive_location *location,
356 uint16_t *control_port)
357 {
358 enum lttng_trace_archive_location_status status =
359 LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK;
360
361 if (!location || !control_port ||
362 location->type != LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY) {
363 status = LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_INVALID;
364 goto end;
365 }
366
367 *control_port = location->types.relay.ports.control;
368 end:
369 return status;
370 }
371
372 enum lttng_trace_archive_location_status
373 lttng_trace_archive_location_relay_get_data_port(
374 const struct lttng_trace_archive_location *location,
375 uint16_t *data_port)
376 {
377 enum lttng_trace_archive_location_status status =
378 LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK;
379
380 if (!location || !data_port ||
381 location->type != LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY) {
382 status = LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_INVALID;
383 goto end;
384 }
385
386 *data_port = location->types.relay.ports.data;
387 end:
388 return status;
389 }
390
391 enum lttng_trace_archive_location_status
392 lttng_trace_archive_location_relay_get_protocol_type(
393 const struct lttng_trace_archive_location *location,
394 enum lttng_trace_archive_location_relay_protocol_type *protocol)
395 {
396 enum lttng_trace_archive_location_status status =
397 LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK;
398
399 if (!location || !protocol ||
400 location->type != LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY) {
401 status = LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_INVALID;
402 goto end;
403 }
404
405 *protocol = location->types.relay.protocol;
406 end:
407 return status;
408 }
This page took 0.03686 seconds and 4 git commands to generate.