Clean-up: format using remaining buffer len rather than total len
[lttng-tools.git] / src / bin / lttng-relayd / stream.c
CommitLineData
2a174661
DG
1/*
2 * Copyright (C) 2013 - Julien Desfossez <jdesfossez@efficios.com>
3 * David Goulet <dgoulet@efficios.com>
7591bab1 4 * 2015 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
c35f9726 5 * 2019 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
2a174661
DG
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License, version 2 only, as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 51
18 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
6c1c0768 21#define _LGPL_SOURCE
2a174661 22#include <common/common.h>
7591bab1
MD
23#include <common/utils.h>
24#include <common/defaults.h>
c35f9726 25#include <common/sessiond-comm/relayd.h>
7591bab1
MD
26#include <urcu/rculist.h>
27#include <sys/stat.h>
2a174661 28
7591bab1 29#include "lttng-relayd.h"
2a174661
DG
30#include "index.h"
31#include "stream.h"
32#include "viewer-stream.h"
33
348a81dc
JG
34#include <sys/types.h>
35#include <fcntl.h>
36
c35f9726
JG
37#define FILE_IO_STACK_BUFFER_SIZE 65536
38
7591bab1
MD
39/* Should be called with RCU read-side lock held. */
40bool stream_get(struct relay_stream *stream)
41{
ce4d4083 42 return urcu_ref_get_unless_zero(&stream->ref);
7591bab1
MD
43}
44
2a174661 45/*
7591bab1
MD
46 * Get stream from stream id from the streams hash table. Return stream
47 * if found else NULL. A stream reference is taken when a stream is
48 * returned. stream_put() must be called on that stream.
2a174661 49 */
7591bab1 50struct relay_stream *stream_get_by_id(uint64_t stream_id)
2a174661
DG
51{
52 struct lttng_ht_node_u64 *node;
53 struct lttng_ht_iter iter;
54 struct relay_stream *stream = NULL;
55
7591bab1
MD
56 rcu_read_lock();
57 lttng_ht_lookup(relay_streams_ht, &stream_id, &iter);
2a174661 58 node = lttng_ht_iter_get_node_u64(&iter);
7591bab1 59 if (!node) {
2a174661
DG
60 DBG("Relay stream %" PRIu64 " not found", stream_id);
61 goto end;
62 }
63 stream = caa_container_of(node, struct relay_stream, node);
7591bab1
MD
64 if (!stream_get(stream)) {
65 stream = NULL;
66 }
2a174661 67end:
7591bab1 68 rcu_read_unlock();
2a174661
DG
69 return stream;
70}
71
c35f9726
JG
72static void stream_complete_rotation(struct relay_stream *stream)
73{
74 DBG("Rotation completed for stream %" PRIu64, stream->stream_handle);
75 lttng_trace_chunk_put(stream->trace_chunk);
76 stream->trace_chunk = stream->ongoing_rotation.value.next_trace_chunk;
77 stream->ongoing_rotation = (typeof(stream->ongoing_rotation)) {};
78}
79
80/*
81 * If too much data has been written in a tracefile before we received the
82 * rotation command, we have to move the excess data to the new tracefile and
83 * perform the rotation. This can happen because the control and data
84 * connections are separate, the indexes as well as the commands arrive from
85 * the control connection and we have no control over the order so we could be
86 * in a situation where too much data has been received on the data connection
87 * before the rotation command on the control connection arrives.
88 */
89static int rotate_truncate_stream(struct relay_stream *stream)
90{
91 int ret, new_fd;
92 off_t lseek_ret;
93 uint64_t diff, pos = 0;
94 char buf[FILE_IO_STACK_BUFFER_SIZE];
95
96 assert(!stream->is_metadata);
97
98 assert(stream->tracefile_size_current >
99 stream->pos_after_last_complete_data_index);
100 diff = stream->tracefile_size_current -
101 stream->pos_after_last_complete_data_index;
102
103 /* Create the new tracefile. */
104 new_fd = utils_create_stream_file(stream->path_name,
105 stream->channel_name,
106 stream->tracefile_size, stream->tracefile_count,
107 /* uid */ -1, /* gid */ -1, /* suffix */ NULL);
108 if (new_fd < 0) {
109 ERR("Failed to create new stream file at path %s for channel %s",
110 stream->path_name, stream->channel_name);
111 ret = -1;
112 goto end;
113 }
114
115 /*
116 * Rewind the current tracefile to the position at which the rotation
117 * should have occurred.
118 */
119 lseek_ret = lseek(stream->stream_fd->fd,
120 stream->pos_after_last_complete_data_index, SEEK_SET);
121 if (lseek_ret < 0) {
122 PERROR("seek truncate stream");
123 ret = -1;
124 goto end;
125 }
126
127 /* Move data from the old file to the new file. */
128 while (pos < diff) {
129 uint64_t count, bytes_left;
130 ssize_t io_ret;
131
132 bytes_left = diff - pos;
133 count = bytes_left > sizeof(buf) ? sizeof(buf) : bytes_left;
134 assert(count <= SIZE_MAX);
135
136 io_ret = lttng_read(stream->stream_fd->fd, buf, count);
137 if (io_ret < (ssize_t) count) {
138 char error_string[256];
139
140 snprintf(error_string, sizeof(error_string),
141 "Failed to read %" PRIu64 " bytes from fd %i in rotate_truncate_stream(), returned %zi",
142 count, stream->stream_fd->fd, io_ret);
143 if (io_ret == -1) {
144 PERROR("%s", error_string);
145 } else {
146 ERR("%s", error_string);
147 }
148 ret = -1;
149 goto end;
150 }
151
152 io_ret = lttng_write(new_fd, buf, count);
153 if (io_ret < (ssize_t) count) {
154 char error_string[256];
155
156 snprintf(error_string, sizeof(error_string),
157 "Failed to write %" PRIu64 " bytes from fd %i in rotate_truncate_stream(), returned %zi",
158 count, new_fd, io_ret);
159 if (io_ret == -1) {
160 PERROR("%s", error_string);
161 } else {
162 ERR("%s", error_string);
163 }
164 ret = -1;
165 goto end;
166 }
167
168 pos += count;
169 }
170
171 /* Truncate the file to get rid of the excess data. */
172 ret = ftruncate(stream->stream_fd->fd,
173 stream->pos_after_last_complete_data_index);
174 if (ret) {
175 PERROR("ftruncate");
176 goto end;
177 }
178
179 ret = close(stream->stream_fd->fd);
180 if (ret < 0) {
181 PERROR("Closing tracefile");
182 goto end;
183 }
184
185 /*
186 * Update the offset and FD of all the eventual indexes created by the
187 * data connection before the rotation command arrived.
188 */
189 ret = relay_index_switch_all_files(stream);
190 if (ret < 0) {
191 ERR("Failed to rotate index file");
192 goto end;
193 }
194
195 stream->stream_fd->fd = new_fd;
196 stream->tracefile_size_current = diff;
197 stream->pos_after_last_complete_data_index = 0;
198 stream_complete_rotation(stream);
199
200 ret = 0;
201
202end:
203 return ret;
204}
205
206static int stream_create_data_output_file_from_trace_chunk(
207 struct relay_stream *stream,
208 struct lttng_trace_chunk *trace_chunk,
209 bool force_unlink,
210 struct stream_fd **out_stream_fd)
348a81dc
JG
211{
212 int ret, fd;
c35f9726 213 char stream_path[LTTNG_PATH_MAX];
348a81dc
JG
214 enum lttng_trace_chunk_status status;
215 const int flags = O_RDWR | O_CREAT | O_TRUNC;
216 const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
348a81dc
JG
217
218 ASSERT_LOCKED(stream->lock);
219 assert(stream->trace_chunk);
220
348a81dc 221 ret = utils_stream_file_path(stream->path_name, stream->channel_name,
c35f9726
JG
222 stream->tracefile_size, stream->tracefile_current_index,
223 NULL, stream_path, sizeof(stream_path));
348a81dc
JG
224 if (ret < 0) {
225 goto end;
226 }
227
c35f9726
JG
228 if (stream->tracefile_wrapped_around || force_unlink) {
229 /*
230 * The on-disk ring-buffer has wrapped around.
231 * Newly created stream files will replace existing files. Since
232 * live clients may be consuming existing files, the file about
233 * to be replaced is unlinked in order to not overwrite its
234 * content.
235 */
236 status = lttng_trace_chunk_unlink_file(trace_chunk,
237 stream_path);
238 if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
239 PERROR("Failed to unlink stream file \"%s\" during trace file rotation",
240 stream_path);
241 /*
242 * Don't abort if the file doesn't exist, it is
243 * unexpected, but should not be a fatal error.
244 */
245 if (errno != ENOENT) {
246 ret = -1;
247 goto end;
248 }
249 }
250 }
251
348a81dc 252 status = lttng_trace_chunk_open_file(
c35f9726 253 trace_chunk, stream_path, flags, mode, &fd);
348a81dc
JG
254 if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
255 ERR("Failed to open stream file \"%s\"", stream->channel_name);
256 ret = -1;
257 goto end;
258 }
259
c35f9726
JG
260 *out_stream_fd = stream_fd_create(fd);
261 if (!*out_stream_fd) {
348a81dc
JG
262 if (close(ret)) {
263 PERROR("Error closing stream file descriptor %d", ret);
264 }
265 ret = -1;
266 goto end;
267 }
268end:
269 return ret;
270}
271
c35f9726
JG
272static int stream_rotate_data_file(struct relay_stream *stream)
273{
274 int ret = 0;
275
276 DBG("Rotating stream %" PRIu64 " data file",
277 stream->stream_handle);
278
279 if (stream->stream_fd) {
280 stream_fd_put(stream->stream_fd);
281 stream->stream_fd = NULL;
282 }
283
284 stream->tracefile_wrapped_around = false;
285 stream->tracefile_current_index = 0;
286
287 if (stream->ongoing_rotation.value.next_trace_chunk) {
288 struct stream_fd *new_stream_fd = NULL;
289 enum lttng_trace_chunk_status chunk_status;
290
291 chunk_status = lttng_trace_chunk_create_subdirectory(
292 stream->ongoing_rotation.value.next_trace_chunk,
293 stream->path_name);
294 if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
295 ret = -1;
296 goto end;
297 }
298
299 /* Rotate the data file. */
300 ret = stream_create_data_output_file_from_trace_chunk(stream,
301 stream->ongoing_rotation.value.next_trace_chunk,
302 false, &new_stream_fd);
303 stream->stream_fd = new_stream_fd;
304 if (ret < 0) {
305 ERR("Failed to rotate stream data file");
306 goto end;
307 }
308 }
309 stream->tracefile_size_current = 0;
310 stream->pos_after_last_complete_data_index = 0;
311 stream->ongoing_rotation.value.data_rotated = true;
312
313 if (stream->ongoing_rotation.value.index_rotated) {
314 /* Rotation completed; reset its state. */
315 stream_complete_rotation(stream);
316 }
317end:
318 return ret;
319}
320
321/*
322 * Check if a stream's data file (as opposed to index) should be rotated
323 * (for session rotation).
324 * Must be called with the stream lock held.
325 *
326 * Return 0 on success, a negative value on error.
327 */
328static int try_rotate_stream_data(struct relay_stream *stream)
329{
330 int ret = 0;
331
332 if (caa_likely(!stream->ongoing_rotation.is_set)) {
333 /* No rotation expected. */
334 goto end;
335 }
336
337 if (stream->ongoing_rotation.value.data_rotated) {
338 /* Rotation of the data file has already occurred. */
339 goto end;
340 }
341
342 if (stream->prev_data_seq == -1ULL ||
343 stream->prev_data_seq + 1 < stream->ongoing_rotation.value.seq_num) {
344 /*
345 * The next packet that will be written is not part of the next
346 * chunk yet.
347 */
348 DBG("Stream %" PRIu64 " not yet ready for rotation (rotate_at_seq_num = %" PRIu64
349 ", prev_data_seq = %" PRIu64 ")",
350 stream->stream_handle,
351 stream->ongoing_rotation.value.seq_num,
352 stream->prev_data_seq);
353 goto end;
354 } else if (stream->prev_data_seq > stream->ongoing_rotation.value.seq_num) {
355 /*
356 * prev_data_seq is checked here since indexes and rotation
357 * commands are serialized with respect to each other.
358 */
359 DBG("Rotation after too much data has been written in tracefile "
360 "for stream %" PRIu64 ", need to truncate before "
361 "rotating", stream->stream_handle);
362 ret = rotate_truncate_stream(stream);
363 if (ret) {
364 ERR("Failed to truncate stream");
365 goto end;
366 }
367 } else {
368 ret = stream_rotate_data_file(stream);
369 }
370
371end:
372 return ret;
373}
374
375/*
376 * Close the current index file if it is open, and create a new one.
377 *
378 * Return 0 on success, -1 on error.
379 */
380static int create_index_file(struct relay_stream *stream,
381 struct lttng_trace_chunk *chunk)
382{
383 int ret;
384 uint32_t major, minor;
385 char *index_subpath = NULL;
3a735fa7 386 enum lttng_trace_chunk_status status;
c35f9726
JG
387
388 ASSERT_LOCKED(stream->lock);
389
390 /* Put ref on previous index_file. */
391 if (stream->index_file) {
392 lttng_index_file_put(stream->index_file);
393 stream->index_file = NULL;
394 }
395 major = stream->trace->session->major;
396 minor = stream->trace->session->minor;
397
398 if (!chunk) {
399 ret = 0;
400 goto end;
401 }
402 ret = asprintf(&index_subpath, "%s/%s", stream->path_name,
403 DEFAULT_INDEX_DIR);
404 if (ret < 0) {
405 goto end;
406 }
407
3a735fa7 408 status = lttng_trace_chunk_create_subdirectory(chunk,
c35f9726
JG
409 index_subpath);
410 free(index_subpath);
3a735fa7
MD
411 if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
412 ret = -1;
c35f9726
JG
413 goto end;
414 }
415 stream->index_file = lttng_index_file_create_from_trace_chunk(
416 chunk, stream->path_name,
417 stream->channel_name, stream->tracefile_size,
418 stream->tracefile_current_index,
419 lttng_to_index_major(major, minor),
420 lttng_to_index_minor(major, minor), true);
421 if (!stream->index_file) {
422 ret = -1;
423 goto end;
424 }
425
426 ret = 0;
427
428end:
429 return ret;
430}
431
432/*
433 * Check if a stream's index file should be rotated (for session rotation).
434 * Must be called with the stream lock held.
435 *
436 * Return 0 on success, a negative value on error.
437 */
438static int try_rotate_stream_index(struct relay_stream *stream)
439{
440 int ret = 0;
441
442 if (!stream->ongoing_rotation.is_set) {
443 /* No rotation expected. */
444 goto end;
445 }
446
447 if (stream->ongoing_rotation.value.index_rotated) {
448 /* Rotation of the index has already occurred. */
449 goto end;
450 }
451
452 if (stream->prev_index_seq == -1ULL ||
453 stream->prev_index_seq + 1 < stream->ongoing_rotation.value.seq_num) {
454 DBG("Stream %" PRIu64 " index not yet ready for rotation (rotate_at_seq_num = %" PRIu64 ", prev_index_seq = %" PRIu64 ")",
455 stream->stream_handle,
456 stream->ongoing_rotation.value.seq_num,
457 stream->prev_index_seq);
458 goto end;
459 } else {
460 /* The next index belongs to the new trace chunk; rotate. */
461 assert(stream->prev_index_seq + 1 ==
462 stream->ongoing_rotation.value.seq_num);
463 DBG("Rotating stream %" PRIu64 " index file",
464 stream->stream_handle);
465 ret = create_index_file(stream,
466 stream->ongoing_rotation.value.next_trace_chunk);
467 stream->ongoing_rotation.value.index_rotated = true;
468
469 if (stream->ongoing_rotation.value.data_rotated &&
470 stream->ongoing_rotation.value.index_rotated) {
471 /* Rotation completed; reset its state. */
472 DBG("Rotation completed for stream %" PRIu64,
473 stream->stream_handle);
474 stream_complete_rotation(stream);
475 }
476 }
477
478end:
479 return ret;
480}
481
348a81dc
JG
482static int stream_set_trace_chunk(struct relay_stream *stream,
483 struct lttng_trace_chunk *chunk)
484{
485 int ret = 0;
486 enum lttng_trace_chunk_status status;
487 bool acquired_reference;
c35f9726 488 struct stream_fd *new_stream_fd = NULL;
348a81dc 489
348a81dc
JG
490 status = lttng_trace_chunk_create_subdirectory(chunk,
491 stream->path_name);
492 if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
493 ret = -1;
494 goto end;
495 }
496
497 lttng_trace_chunk_put(stream->trace_chunk);
498 acquired_reference = lttng_trace_chunk_get(chunk);
499 assert(acquired_reference);
500 stream->trace_chunk = chunk;
c35f9726
JG
501
502 if (stream->stream_fd) {
503 stream_fd_put(stream->stream_fd);
504 stream->stream_fd = NULL;
505 }
506 ret = stream_create_data_output_file_from_trace_chunk(stream, chunk,
507 false, &new_stream_fd);
508 stream->stream_fd = new_stream_fd;
348a81dc 509end:
348a81dc
JG
510 return ret;
511}
512
2a174661 513/*
7591bab1 514 * We keep ownership of path_name and channel_name.
2a174661 515 */
7591bab1
MD
516struct relay_stream *stream_create(struct ctf_trace *trace,
517 uint64_t stream_handle, char *path_name,
518 char *channel_name, uint64_t tracefile_size,
348a81dc 519 uint64_t tracefile_count)
2a174661 520{
7591bab1
MD
521 int ret;
522 struct relay_stream *stream = NULL;
523 struct relay_session *session = trace->session;
348a81dc
JG
524 bool acquired_reference = false;
525 struct lttng_trace_chunk *current_trace_chunk;
2a174661 526
7591bab1
MD
527 stream = zmalloc(sizeof(struct relay_stream));
528 if (stream == NULL) {
529 PERROR("relay stream zmalloc");
7591bab1
MD
530 goto error_no_alloc;
531 }
2a174661 532
7591bab1 533 stream->stream_handle = stream_handle;
a8f9f353 534 stream->prev_data_seq = -1ULL;
7a45c7e6 535 stream->prev_index_seq = -1ULL;
bda7c7b9 536 stream->last_net_seq_num = -1ULL;
7591bab1
MD
537 stream->ctf_stream_id = -1ULL;
538 stream->tracefile_size = tracefile_size;
539 stream->tracefile_count = tracefile_count;
540 stream->path_name = path_name;
541 stream->channel_name = channel_name;
2f9c3030 542 stream->beacon_ts_end = -1ULL;
7591bab1
MD
543 lttng_ht_node_init_u64(&stream->node, stream->stream_handle);
544 pthread_mutex_init(&stream->lock, NULL);
7591bab1
MD
545 urcu_ref_init(&stream->ref);
546 ctf_trace_get(trace);
547 stream->trace = trace;
2a174661 548
348a81dc
JG
549 pthread_mutex_lock(&trace->session->lock);
550 current_trace_chunk = trace->session->current_trace_chunk;
551 if (current_trace_chunk) {
552 acquired_reference = lttng_trace_chunk_get(current_trace_chunk);
553 }
554 pthread_mutex_unlock(&trace->session->lock);
555 if (!acquired_reference) {
556 ERR("Cannot create stream for channel \"%s\" as a reference to the session's current trace chunk could not be acquired",
557 channel_name);
7591bab1
MD
558 ret = -1;
559 goto end;
2a174661
DG
560 }
561
348a81dc
JG
562 stream->indexes_ht = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
563 if (!stream->indexes_ht) {
564 ERR("Cannot created indexes_ht");
565 ret = -1;
7591bab1
MD
566 goto end;
567 }
2a174661 568
c35f9726 569 pthread_mutex_lock(&stream->lock);
348a81dc 570 ret = stream_set_trace_chunk(stream, current_trace_chunk);
c35f9726 571 pthread_mutex_unlock(&stream->lock);
348a81dc
JG
572 if (ret) {
573 ERR("Failed to set the current trace chunk of session \"%s\" on newly created stream of channel \"%s\"",
574 trace->session->session_name,
575 stream->channel_name);
7591bab1
MD
576 ret = -1;
577 goto end;
2a174661 578 }
a44ca2ca
MD
579 stream->tfa = tracefile_array_create(stream->tracefile_count);
580 if (!stream->tfa) {
581 ret = -1;
582 goto end;
583 }
7591bab1 584
348a81dc
JG
585 stream->is_metadata = !strcmp(stream->channel_name,
586 DEFAULT_METADATA_NAME);
7591bab1
MD
587 stream->in_recv_list = true;
588
589 /*
590 * Add the stream in the recv list of the session. Once the end stream
591 * message is received, all session streams are published.
592 */
593 pthread_mutex_lock(&session->recv_list_lock);
594 cds_list_add_rcu(&stream->recv_node, &session->recv_list);
595 session->stream_count++;
596 pthread_mutex_unlock(&session->recv_list_lock);
597
598 /*
599 * Both in the ctf_trace object and the global stream ht since the data
600 * side of the relayd does not have the concept of session.
601 */
602 lttng_ht_add_unique_u64(relay_streams_ht, &stream->node);
77f7bd85 603 stream->in_stream_ht = true;
2a174661 604
7591bab1
MD
605 DBG("Relay new stream added %s with ID %" PRIu64, stream->channel_name,
606 stream->stream_handle);
607 ret = 0;
608
609end:
610 if (ret) {
611 if (stream->stream_fd) {
612 stream_fd_put(stream->stream_fd);
613 stream->stream_fd = NULL;
2a174661 614 }
7591bab1
MD
615 stream_put(stream);
616 stream = NULL;
2a174661 617 }
348a81dc 618 lttng_trace_chunk_put(current_trace_chunk);
7591bab1 619 return stream;
2a174661 620
7591bab1
MD
621error_no_alloc:
622 /*
623 * path_name and channel_name need to be freed explicitly here
624 * because we cannot rely on stream_put().
625 */
626 free(path_name);
627 free(channel_name);
628 return NULL;
629}
630
631/*
632 * Called with the session lock held.
633 */
634void stream_publish(struct relay_stream *stream)
635{
636 struct relay_session *session;
637
638 pthread_mutex_lock(&stream->lock);
639 if (stream->published) {
640 goto unlock;
2a174661
DG
641 }
642
7591bab1 643 session = stream->trace->session;
2a174661 644
7591bab1
MD
645 pthread_mutex_lock(&session->recv_list_lock);
646 if (stream->in_recv_list) {
647 cds_list_del_rcu(&stream->recv_node);
648 stream->in_recv_list = false;
649 }
650 pthread_mutex_unlock(&session->recv_list_lock);
2a174661 651
7591bab1
MD
652 pthread_mutex_lock(&stream->trace->stream_list_lock);
653 cds_list_add_rcu(&stream->stream_node, &stream->trace->stream_list);
654 pthread_mutex_unlock(&stream->trace->stream_list_lock);
2a174661 655
7591bab1
MD
656 stream->published = true;
657unlock:
2a174661 658 pthread_mutex_unlock(&stream->lock);
2a174661
DG
659}
660
7591bab1 661/*
77f7bd85 662 * Stream must be protected by holding the stream lock or by virtue of being
ce4d4083 663 * called from stream_destroy.
7591bab1
MD
664 */
665static void stream_unpublish(struct relay_stream *stream)
2a174661 666{
77f7bd85
MD
667 if (stream->in_stream_ht) {
668 struct lttng_ht_iter iter;
669 int ret;
670
671 iter.iter.node = &stream->node.node;
672 ret = lttng_ht_del(relay_streams_ht, &iter);
673 assert(!ret);
674 stream->in_stream_ht = false;
675 }
676 if (stream->published) {
677 pthread_mutex_lock(&stream->trace->stream_list_lock);
678 cds_list_del_rcu(&stream->stream_node);
679 pthread_mutex_unlock(&stream->trace->stream_list_lock);
680 stream->published = false;
7591bab1 681 }
7591bab1
MD
682}
683
684static void stream_destroy(struct relay_stream *stream)
685{
686 if (stream->indexes_ht) {
49e614cb
MD
687 /*
688 * Calling lttng_ht_destroy in call_rcu worker thread so
689 * we don't hold the RCU read-side lock while calling
690 * it.
691 */
7591bab1
MD
692 lttng_ht_destroy(stream->indexes_ht);
693 }
a44ca2ca
MD
694 if (stream->tfa) {
695 tracefile_array_destroy(stream->tfa);
696 }
7591bab1
MD
697 free(stream->path_name);
698 free(stream->channel_name);
699 free(stream);
700}
701
702static void stream_destroy_rcu(struct rcu_head *rcu_head)
703{
704 struct relay_stream *stream =
705 caa_container_of(rcu_head, struct relay_stream, rcu_node);
706
707 stream_destroy(stream);
708}
709
710/*
711 * No need to take stream->lock since this is only called on the final
712 * stream_put which ensures that a single thread may act on the stream.
7591bab1
MD
713 */
714static void stream_release(struct urcu_ref *ref)
715{
716 struct relay_stream *stream =
717 caa_container_of(ref, struct relay_stream, ref);
718 struct relay_session *session;
2a174661 719
7591bab1
MD
720 session = stream->trace->session;
721
722 DBG("Releasing stream id %" PRIu64, stream->stream_handle);
723
724 pthread_mutex_lock(&session->recv_list_lock);
725 session->stream_count--;
726 if (stream->in_recv_list) {
727 cds_list_del_rcu(&stream->recv_node);
728 stream->in_recv_list = false;
729 }
730 pthread_mutex_unlock(&session->recv_list_lock);
2a174661 731
7591bab1
MD
732 stream_unpublish(stream);
733
734 if (stream->stream_fd) {
735 stream_fd_put(stream->stream_fd);
736 stream->stream_fd = NULL;
737 }
f8f3885c
MD
738 if (stream->index_file) {
739 lttng_index_file_put(stream->index_file);
740 stream->index_file = NULL;
7591bab1
MD
741 }
742 if (stream->trace) {
743 ctf_trace_put(stream->trace);
744 stream->trace = NULL;
745 }
c35f9726 746 stream_complete_rotation(stream);
348a81dc
JG
747 lttng_trace_chunk_put(stream->trace_chunk);
748 stream->trace_chunk = NULL;
7591bab1
MD
749
750 call_rcu(&stream->rcu_node, stream_destroy_rcu);
2a174661
DG
751}
752
7591bab1 753void stream_put(struct relay_stream *stream)
2a174661 754{
7591bab1 755 rcu_read_lock();
7591bab1
MD
756 assert(stream->ref.refcount != 0);
757 /*
758 * Wait until we have processed all the stream packets before
759 * actually putting our last stream reference.
760 */
7591bab1 761 urcu_ref_put(&stream->ref, stream_release);
7591bab1
MD
762 rcu_read_unlock();
763}
764
c35f9726
JG
765int stream_set_pending_rotation(struct relay_stream *stream,
766 struct lttng_trace_chunk *next_trace_chunk,
767 uint64_t rotation_sequence_number)
768{
769 int ret = 0;
770 const struct relay_stream_rotation rotation = {
771 .seq_num = rotation_sequence_number,
772 .next_trace_chunk = next_trace_chunk,
773 };
774
775 if (stream->ongoing_rotation.is_set) {
776 ERR("Attempted to set a pending rotation on a stream already being rotated (protocol error)");
777 ret = -1;
778 goto end;
779 }
780
781 if (next_trace_chunk) {
782 const bool reference_acquired =
783 lttng_trace_chunk_get(next_trace_chunk);
784
785 assert(reference_acquired);
786 }
787 LTTNG_OPTIONAL_SET(&stream->ongoing_rotation, rotation);
788
789 DBG("Setting pending rotation: stream_id = %" PRIu64 ", rotation_seq_num = %" PRIu64,
790 stream->stream_handle, rotation_sequence_number);
791 if (stream->is_metadata) {
792 /*
793 * A metadata stream has no index; consider it already rotated.
794 */
795 stream->ongoing_rotation.value.index_rotated = true;
796 ret = stream_rotate_data_file(stream);
797 } else {
798 ret = try_rotate_stream_data(stream);
799 if (ret < 0) {
800 goto end;
801 }
802
803 ret = try_rotate_stream_index(stream);
804 if (ret < 0) {
805 goto end;
806 }
807 }
808end:
809 return ret;
810}
811
bda7c7b9 812void try_stream_close(struct relay_stream *stream)
7591bab1 813{
98ba050e
JR
814 bool session_aborted;
815 struct relay_session *session = stream->trace->session;
816
bda7c7b9 817 DBG("Trying to close stream %" PRIu64, stream->stream_handle);
98ba050e
JR
818
819 pthread_mutex_lock(&session->lock);
820 session_aborted = session->aborted;
821 pthread_mutex_unlock(&session->lock);
822
7591bab1 823 pthread_mutex_lock(&stream->lock);
bda7c7b9
JG
824 /*
825 * Can be called concurently by connection close and reception of last
826 * pending data.
827 */
828 if (stream->closed) {
829 pthread_mutex_unlock(&stream->lock);
830 DBG("closing stream %" PRIu64 " aborted since it is already marked as closed", stream->stream_handle);
831 return;
832 }
833
834 stream->close_requested = true;
3d07a857
MD
835
836 if (stream->last_net_seq_num == -1ULL) {
837 /*
838 * Handle connection close without explicit stream close
839 * command.
840 *
841 * We can be clever about indexes partially received in
842 * cases where we received the data socket part, but not
843 * the control socket part: since we're currently closing
844 * the stream on behalf of the control socket, we *know*
845 * there won't be any more control information for this
846 * socket. Therefore, we can destroy all indexes for
847 * which we have received only the file descriptor (from
848 * data socket). This takes care of consumerd crashes
849 * between sending the data and control information for
850 * a packet. Since those are sent in that order, we take
851 * care of consumerd crashes.
852 */
5312a3ed 853 DBG("relay_index_close_partial_fd");
3d07a857
MD
854 relay_index_close_partial_fd(stream);
855 /*
856 * Use the highest net_seq_num we currently have pending
857 * As end of stream indicator. Leave last_net_seq_num
858 * at -1ULL if we cannot find any index.
859 */
860 stream->last_net_seq_num = relay_index_find_last(stream);
5312a3ed 861 DBG("Updating stream->last_net_seq_num to %" PRIu64, stream->last_net_seq_num);
3d07a857
MD
862 /* Fall-through into the next check. */
863 }
864
bda7c7b9 865 if (stream->last_net_seq_num != -1ULL &&
a8f9f353 866 ((int64_t) (stream->prev_data_seq - stream->last_net_seq_num)) < 0
98ba050e 867 && !session_aborted) {
3d07a857
MD
868 /*
869 * Don't close since we still have data pending. This
870 * handles cases where an explicit close command has
871 * been received for this stream, and cases where the
872 * connection has been closed, and we are awaiting for
873 * index information from the data socket. It is
874 * therefore expected that all the index fd information
875 * we need has already been received on the control
876 * socket. Matching index information from data socket
877 * should be Expected Soon(TM).
878 *
879 * TODO: We should implement a timer to garbage collect
880 * streams after a timeout to be resilient against a
881 * consumerd implementation that would not match this
882 * expected behavior.
883 */
bda7c7b9
JG
884 pthread_mutex_unlock(&stream->lock);
885 DBG("closing stream %" PRIu64 " aborted since it still has data pending", stream->stream_handle);
886 return;
887 }
3d07a857
MD
888 /*
889 * We received all the indexes we can expect.
890 */
77f7bd85 891 stream_unpublish(stream);
2229a09c 892 stream->closed = true;
bda7c7b9 893 /* Relay indexes are only used by the "consumer/sessiond" end. */
7591bab1
MD
894 relay_index_close_all(stream);
895 pthread_mutex_unlock(&stream->lock);
bda7c7b9 896 DBG("Succeeded in closing stream %" PRIu64, stream->stream_handle);
7591bab1
MD
897 stream_put(stream);
898}
899
c35f9726
JG
900int stream_init_packet(struct relay_stream *stream, size_t packet_size,
901 bool *file_rotated)
902{
903 int ret = 0;
904
905 ASSERT_LOCKED(stream->lock);
906 if (caa_likely(stream->tracefile_size == 0)) {
907 /* No size limit set; nothing to check. */
908 goto end;
909 }
910
911 /*
912 * Check if writing the new packet would exceed the maximal file size.
913 */
914 if (caa_unlikely((stream->tracefile_size_current + packet_size) >
915 stream->tracefile_size)) {
916 const uint64_t new_file_index =
917 (stream->tracefile_current_index + 1) %
918 stream->tracefile_count;
919
920 if (new_file_index < stream->tracefile_current_index) {
921 stream->tracefile_wrapped_around = true;
922 }
923 DBG("New stream packet causes stream file rotation: stream_id = %" PRIu64
924 ", current_file_size = %" PRIu64
76ee9245 925 ", packet_size = %zu, current_file_index = %" PRIu64
c35f9726
JG
926 " new_file_index = %" PRIu64,
927 stream->stream_handle,
928 stream->tracefile_size_current, packet_size,
929 stream->tracefile_current_index, new_file_index);
930 tracefile_array_file_rotate(stream->tfa);
931 stream->tracefile_current_index = new_file_index;
932
933 if (stream->stream_fd) {
934 stream_fd_put(stream->stream_fd);
935 stream->stream_fd = NULL;
936 }
937 ret = stream_create_data_output_file_from_trace_chunk(stream,
938 stream->trace_chunk, false, &stream->stream_fd);
939 if (ret) {
940 ERR("Failed to perform trace file rotation of stream %" PRIu64,
941 stream->stream_handle);
942 goto end;
943 }
944
945 /*
946 * Reset current size because we just performed a stream
947 * rotation.
948 */
949 stream->tracefile_size_current = 0;
950 *file_rotated = true;
951 } else {
952 *file_rotated = false;
953 }
954end:
955 return ret;
956}
957
958/* Note that the packet is not necessarily complete. */
959int stream_write(struct relay_stream *stream,
960 const struct lttng_buffer_view *packet, size_t padding_len)
961{
962 int ret = 0;
963 ssize_t write_ret;
964 size_t padding_to_write = padding_len;
965 char padding_buffer[FILE_IO_STACK_BUFFER_SIZE];
966
967 ASSERT_LOCKED(stream->lock);
968 memset(padding_buffer, 0,
969 min(sizeof(padding_buffer), padding_to_write));
970
971 if (packet) {
972 write_ret = lttng_write(stream->stream_fd->fd,
973 packet->data, packet->size);
974 if (write_ret != packet->size) {
975 PERROR("Failed to write to stream file of %sstream %" PRIu64,
976 stream->is_metadata ? "metadata " : "",
977 stream->stream_handle);
978 ret = -1;
979 goto end;
980 }
981 }
982
983 while (padding_to_write > 0) {
984 const size_t padding_to_write_this_pass =
985 min(padding_to_write, sizeof(padding_buffer));
986
987 write_ret = lttng_write(stream->stream_fd->fd,
988 padding_buffer, padding_to_write_this_pass);
989 if (write_ret != padding_to_write_this_pass) {
990 PERROR("Failed to write padding to file of %sstream %" PRIu64,
991 stream->is_metadata ? "metadata " : "",
992 stream->stream_handle);
993 ret = -1;
994 goto end;
995 }
996 padding_to_write -= padding_to_write_this_pass;
997 }
998
999 if (stream->is_metadata) {
1000 stream->metadata_received += packet->size + padding_len;
1001 }
1002
8c865d87 1003 DBG("Wrote to %sstream %" PRIu64 ": data_length = %zu, padding_length = %zu",
c35f9726
JG
1004 stream->is_metadata ? "metadata " : "",
1005 stream->stream_handle,
8c865d87 1006 packet ? packet->size : (size_t) 0, padding_len);
c35f9726
JG
1007end:
1008 return ret;
1009}
1010
1011/*
1012 * Update index after receiving a packet for a data stream.
1013 *
1014 * Called with the stream lock held.
1015 *
1016 * Return 0 on success else a negative value.
1017 */
1018int stream_update_index(struct relay_stream *stream, uint64_t net_seq_num,
1019 bool rotate_index, bool *flushed, uint64_t total_size)
1020{
1021 int ret = 0;
1022 uint64_t data_offset;
1023 struct relay_index *index;
1024
1025 ASSERT_LOCKED(stream->lock);
1026 /* Get data offset because we are about to update the index. */
1027 data_offset = htobe64(stream->tracefile_size_current);
1028
1029 DBG("handle_index_data: stream %" PRIu64 " net_seq_num %" PRIu64 " data offset %" PRIu64,
1030 stream->stream_handle, net_seq_num, stream->tracefile_size_current);
1031
1032 /*
1033 * Lookup for an existing index for that stream id/sequence
1034 * number. If it exists, the control thread has already received the
1035 * data for it, thus we need to write it to disk.
1036 */
1037 index = relay_index_get_by_id_or_create(stream, net_seq_num);
1038 if (!index) {
1039 ret = -1;
1040 goto end;
1041 }
1042
1043 if (rotate_index || !stream->index_file) {
1044 ret = create_index_file(stream, stream->trace_chunk);
1045 if (ret) {
1046 ERR("Failed to create index file for stream %" PRIu64,
1047 stream->stream_handle);
1048 /* Put self-ref for this index due to error. */
1049 relay_index_put(index);
1050 index = NULL;
1051 goto end;
1052 }
1053 }
1054
1055 if (relay_index_set_file(index, stream->index_file, data_offset)) {
1056 ret = -1;
1057 /* Put self-ref for this index due to error. */
1058 relay_index_put(index);
1059 index = NULL;
1060 goto end;
1061 }
1062
1063 ret = relay_index_try_flush(index);
1064 if (ret == 0) {
1065 tracefile_array_commit_seq(stream->tfa);
1066 stream->index_received_seqcount++;
1067 *flushed = true;
1068 } else if (ret > 0) {
1069 index->total_size = total_size;
1070 /* No flush. */
1071 ret = 0;
1072 } else {
1073 /*
1074 * ret < 0
1075 *
1076 * relay_index_try_flush is responsible for the self-reference
1077 * put of the index object on error.
1078 */
1079 ERR("relay_index_try_flush error %d", ret);
1080 ret = -1;
1081 }
1082end:
1083 return ret;
1084}
1085
1086int stream_complete_packet(struct relay_stream *stream, size_t packet_total_size,
1087 uint64_t sequence_number, bool index_flushed)
1088{
1089 int ret = 0;
1090
1091 ASSERT_LOCKED(stream->lock);
1092
1093 stream->tracefile_size_current += packet_total_size;
1094 if (index_flushed) {
1095 stream->pos_after_last_complete_data_index =
1096 stream->tracefile_size_current;
1097 stream->prev_index_seq = sequence_number;
1098 ret = try_rotate_stream_index(stream);
1099 if (ret < 0) {
1100 goto end;
1101 }
1102 }
1103
1104 stream->prev_data_seq = sequence_number;
1105 ret = try_rotate_stream_data(stream);
1106 if (ret < 0) {
1107 goto end;
1108 }
1109end:
1110 return ret;
1111}
1112
1113int stream_add_index(struct relay_stream *stream,
1114 const struct lttcomm_relayd_index *index_info)
1115{
1116 int ret = 0;
1117 struct relay_index *index;
1118
1119 ASSERT_LOCKED(stream->lock);
1120
1121 /* Live beacon handling */
1122 if (index_info->packet_size == 0) {
1123 DBG("Received live beacon for stream %" PRIu64,
1124 stream->stream_handle);
1125
1126 /*
1127 * Only flag a stream inactive when it has already
1128 * received data and no indexes are in flight.
1129 */
1130 if (stream->index_received_seqcount > 0
1131 && stream->indexes_in_flight == 0) {
1132 stream->beacon_ts_end = index_info->timestamp_end;
1133 }
1134 ret = 0;
1135 goto end;
1136 } else {
1137 stream->beacon_ts_end = -1ULL;
1138 }
1139
1140 if (stream->ctf_stream_id == -1ULL) {
1141 stream->ctf_stream_id = index_info->stream_id;
1142 }
1143
1144 index = relay_index_get_by_id_or_create(stream, index_info->net_seq_num);
1145 if (!index) {
1146 ret = -1;
1147 ERR("Failed to get or create index %" PRIu64,
1148 index_info->net_seq_num);
1149 goto end;
1150 }
1151 if (relay_index_set_control_data(index, index_info,
1152 stream->trace->session->minor)) {
1153 ERR("set_index_control_data error");
1154 relay_index_put(index);
1155 ret = -1;
1156 goto end;
1157 }
1158 ret = relay_index_try_flush(index);
1159 if (ret == 0) {
1160 tracefile_array_commit_seq(stream->tfa);
1161 stream->index_received_seqcount++;
1162 stream->pos_after_last_complete_data_index += index->total_size;
1163 stream->prev_index_seq = index_info->net_seq_num;
1164
1165 ret = try_rotate_stream_index(stream);
1166 if (ret < 0) {
1167 goto end;
1168 }
1169 } else if (ret > 0) {
1170 /* no flush. */
1171 ret = 0;
1172 } else {
1173 /*
1174 * ret < 0
1175 *
1176 * relay_index_try_flush is responsible for the self-reference
1177 * put of the index object on error.
1178 */
1179 ERR("relay_index_try_flush error %d", ret);
1180 ret = -1;
1181 }
1182end:
1183 return ret;
1184}
1185
da412cde
MD
1186static void print_stream_indexes(struct relay_stream *stream)
1187{
1188 struct lttng_ht_iter iter;
1189 struct relay_index *index;
1190
1191 rcu_read_lock();
1192 cds_lfht_for_each_entry(stream->indexes_ht->ht, &iter.iter, index,
1193 index_n.node) {
1194 DBG("index %p net_seq_num %" PRIu64 " refcount %ld"
1195 " stream %" PRIu64 " trace %" PRIu64
1196 " session %" PRIu64,
1197 index,
1198 index->index_n.key,
1199 stream->ref.refcount,
1200 index->stream->stream_handle,
1201 index->stream->trace->id,
1202 index->stream->trace->session->id);
1203 }
1204 rcu_read_unlock();
1205}
1206
c35f9726
JG
1207int stream_reset_file(struct relay_stream *stream)
1208{
1209 ASSERT_LOCKED(stream->lock);
1210
1211 if (stream->stream_fd) {
1212 stream_fd_put(stream->stream_fd);
1213 stream->stream_fd = NULL;
1214 }
1215
1216 stream->tracefile_size_current = 0;
1217 stream->prev_data_seq = 0;
1218 stream->prev_index_seq = 0;
1219 /* Note that this does not reset the tracefile array. */
1220 stream->tracefile_current_index = 0;
1221 stream->pos_after_last_complete_data_index = 0;
1222
1223 return stream_create_data_output_file_from_trace_chunk(stream,
1224 stream->trace_chunk, true, &stream->stream_fd);
1225}
1226
7591bab1
MD
1227void print_relay_streams(void)
1228{
1229 struct lttng_ht_iter iter;
1230 struct relay_stream *stream;
1231
ce3f3ba3
JG
1232 if (!relay_streams_ht) {
1233 return;
1234 }
1235
7591bab1
MD
1236 rcu_read_lock();
1237 cds_lfht_for_each_entry(relay_streams_ht->ht, &iter.iter, stream,
1238 node.node) {
1239 if (!stream_get(stream)) {
1240 continue;
1241 }
1242 DBG("stream %p refcount %ld stream %" PRIu64 " trace %" PRIu64
1243 " session %" PRIu64,
1244 stream,
1245 stream->ref.refcount,
1246 stream->stream_handle,
1247 stream->trace->id,
1248 stream->trace->session->id);
da412cde 1249 print_stream_indexes(stream);
7591bab1
MD
1250 stream_put(stream);
1251 }
1252 rcu_read_unlock();
2a174661 1253}
This page took 0.187211 seconds and 4 git commands to generate.