2 * Copyright (C) 2018 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 #include "index-file.h"
19 #include "lttng-relayd.h"
21 #include <common/defaults.h>
22 #include <common/error.h>
23 #include <common/utils.h>
24 #include <common/readwrite.h>
25 #include <common/fd-tracker/fd-tracker.h>
26 #include <common/fd-tracker/utils.h>
27 #include <lttng/constant.h>
35 struct relay_index_file
{
39 struct fs_handle
*handle
;
50 * Create the index file associated with a trace file.
52 * Return allocated struct lttng_index_file, NULL on error.
54 struct relay_index_file
*relay_index_file_create(const char *path_name
,
55 const char *stream_name
, uint64_t size
, uint64_t count
,
56 uint32_t idx_major
, uint32_t idx_minor
)
58 struct relay_index_file
*index_file
;
59 struct fs_handle
*fs_handle
= NULL
;
62 struct ctf_packet_index_file_hdr hdr
;
63 char idx_dir_path
[LTTNG_PATH_MAX
];
64 char idx_file_path
[LTTNG_PATH_MAX
];
66 * With the session rotation feature on the relay, we might need to seek
67 * and truncate a tracefile, so we need read and write access.
69 int flags
= O_RDWR
| O_CREAT
| O_TRUNC
;
70 /* Open with 660 mode */
71 mode_t mode
= S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
;
73 index_file
= zmalloc(sizeof(*index_file
));
75 PERROR("allocating relay_index_file");
80 * The receiving end of the relay daemon is not expected to try
81 * to append to an index file. It is thus safe to create it as
84 index_file
->suspendable
= true;
86 ret
= snprintf(idx_dir_path
, sizeof(idx_dir_path
), "%s/" DEFAULT_INDEX_DIR
,
89 PERROR("snprintf index path");
93 /* Create index directory if necessary. */
94 ret
= utils_mkdir(idx_dir_path
, S_IRWXU
| S_IRWXG
, -1, -1);
96 if (errno
!= EEXIST
) {
97 PERROR("Index trace directory creation error");
102 ret
= utils_stream_file_name(idx_file_path
, idx_dir_path
, stream_name
,
103 size
, count
, DEFAULT_INDEX_FILE_SUFFIX
);
105 ERR("Could not build path of index file");
110 * For tracefile rotation. We need to unlink the old
111 * file if present to synchronize with the tail of the
112 * live viewer which could be working on this same file.
113 * By doing so, any reference to the old index file
114 * stays valid even if we re-create a new file with the
115 * same name afterwards.
117 unlink(idx_file_path
);
118 if (ret
< 0 && errno
!= ENOENT
) {
119 PERROR("Failed to unlink index file");
123 fs_handle
= fd_tracker_open_fs_handle(the_fd_tracker
, idx_file_path
,
128 index_file
->u
.handle
= fs_handle
;
130 fd
= fs_handle_get_fd(fs_handle
);
135 ctf_packet_index_file_hdr_init(&hdr
, idx_major
, idx_minor
);
136 size_ret
= lttng_write(fd
, &hdr
, sizeof(hdr
));
137 if (size_ret
< sizeof(hdr
)) {
138 PERROR("write index header");
142 index_file
->major
= idx_major
;
143 index_file
->minor
= idx_minor
;
144 index_file
->element_len
= ctf_packet_index_len(idx_major
, idx_minor
);
145 urcu_ref_init(&index_file
->ref
);
147 fs_handle_put_fd(fs_handle
);
153 fs_handle_put_fd(fs_handle
);
158 close_ret
= fs_handle_close(fs_handle
);
160 PERROR("Failed to close index filesystem handle");
168 int open_file(void *data
, int *out_fd
)
171 const char *path
= data
;
173 ret
= open(path
, O_RDONLY
);
183 struct relay_index_file
*relay_index_file_open(const char *path_name
,
184 const char *channel_name
, uint64_t tracefile_count
,
185 uint64_t tracefile_count_current
)
187 struct relay_index_file
*index_file
;
190 char fullpath
[PATH_MAX
];
191 char *path_param
= fullpath
;
192 struct ctf_packet_index_file_hdr hdr
;
193 uint32_t major
, minor
, element_len
;
196 assert(channel_name
);
198 index_file
= zmalloc(sizeof(*index_file
));
200 PERROR("Failed to allocate relay_index_file");
204 index_file
->suspendable
= false;
206 if (tracefile_count
> 0) {
207 ret
= snprintf(fullpath
, sizeof(fullpath
), "%s/" DEFAULT_INDEX_DIR
"/%s_%"
208 PRIu64 DEFAULT_INDEX_FILE_SUFFIX
, path_name
,
209 channel_name
, tracefile_count_current
);
211 ret
= snprintf(fullpath
, sizeof(fullpath
), "%s/" DEFAULT_INDEX_DIR
"/%s"
212 DEFAULT_INDEX_FILE_SUFFIX
, path_name
, channel_name
);
215 PERROR("Failed to build index path");
219 DBG("Index opening file %s in read only", fullpath
);
220 ret
= fd_tracker_open_unsuspendable_fd(the_fd_tracker
, &fd
,
221 (const char **) &path_param
, 1,
222 open_file
, (void *) fullpath
);
224 PERROR("Failed to open index file at %s", fullpath
);
228 read_len
= lttng_read(fd
, &hdr
, sizeof(hdr
));
230 PERROR("Failed to read index header");
234 if (be32toh(hdr
.magic
) != CTF_INDEX_MAGIC
) {
235 ERR("Invalid header magic %#010x, expected %#010x",
236 be32toh(hdr
.magic
), CTF_INDEX_MAGIC
);
239 major
= be32toh(hdr
.index_major
);
240 minor
= be32toh(hdr
.index_minor
);
241 element_len
= be32toh(hdr
.packet_index_len
);
243 if (major
!= CTF_INDEX_MAJOR
) {
244 ERR("Invalid header version, major = %" PRIu32
", expected %i",
245 major
, CTF_INDEX_MAJOR
);
248 if (element_len
> sizeof(struct ctf_packet_index
)) {
249 ERR("Index element length too long (%" PRIu32
" bytes)",
254 index_file
->u
.fd
= fd
;
255 index_file
->major
= major
;
256 index_file
->minor
= minor
;
257 index_file
->element_len
= element_len
;
258 urcu_ref_init(&index_file
->ref
);
263 ret
= fd_tracker_close_unsuspendable_fd(the_fd_tracker
, &fd
,
264 1, fd_tracker_util_close_fd
, NULL
);
266 PERROR("Failed to close index fd %d", fd
);
274 int relay_index_file_write(const struct relay_index_file
*index_file
,
275 const struct ctf_packet_index
*element
)
283 fd
= index_file
->suspendable
?
284 fs_handle_get_fd(index_file
->u
.handle
) :
291 write_ret
= lttng_write(fd
, element
, index_file
->element_len
);
292 if (write_ret
< index_file
->element_len
) {
293 PERROR("Failed to write packet index to index file");
298 if (index_file
->suspendable
) {
299 fs_handle_put_fd(index_file
->u
.handle
);
305 int relay_index_file_read(const struct relay_index_file
*index_file
,
306 struct ctf_packet_index
*element
)
314 fd
= index_file
->suspendable
?
315 fs_handle_get_fd(index_file
->u
.handle
) :
322 read_ret
= lttng_read(fd
, element
, index_file
->element_len
);
323 if (read_ret
< index_file
->element_len
) {
324 PERROR("Failed to read packet index from file");
329 if (index_file
->suspendable
) {
330 fs_handle_put_fd(index_file
->u
.handle
);
336 int relay_index_file_seek_end(struct relay_index_file
*index_file
)
341 fd
= index_file
->suspendable
?
342 fs_handle_get_fd(index_file
->u
.handle
) :
349 lseek_ret
= lseek(fd
, 0, SEEK_END
);
354 if (index_file
->suspendable
) {
355 fs_handle_put_fd(index_file
->u
.handle
);
361 void relay_index_file_get(struct relay_index_file
*index_file
)
363 urcu_ref_get(&index_file
->ref
);
367 void relay_index_file_release(struct urcu_ref
*ref
)
370 struct relay_index_file
*index_file
= caa_container_of(ref
,
371 struct relay_index_file
, ref
);
373 if (index_file
->suspendable
) {
374 ret
= fs_handle_close(index_file
->u
.handle
);
376 ret
= fd_tracker_close_unsuspendable_fd(the_fd_tracker
, &index_file
->u
.fd
,
377 1, fd_tracker_util_close_fd
, NULL
);
380 PERROR("Failed to close index file");
385 void relay_index_file_put(struct relay_index_file
*index_file
)
387 urcu_ref_put(&index_file
->ref
, relay_index_file_release
);