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