X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Findex%2Findex.c;h=b481badb1d6556e2f6f1807264d33e81e6be41b2;hp=54689677ee4a2f3dd3c56a6f06236115f659ead6;hb=a3461e94de72e04fd6040c0fad5fb6d3615a2de4;hpb=2f8f53af90479595d530f8f02e71dd0b9fb810ee diff --git a/src/common/index/index.c b/src/common/index/index.c index 54689677e..b481badb1 100644 --- a/src/common/index/index.c +++ b/src/common/index/index.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 - Julien Desfossez * David Goulet + * 2016 - Mathieu Desnoyers * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License, version 2 only, as @@ -16,7 +17,7 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#define _GNU_SOURCE +#define _LGPL_SOURCE #include #include #include @@ -24,6 +25,7 @@ #include #include +#include #include #include "index.h" @@ -31,15 +33,24 @@ /* * Create the index file associated with a trace file. * - * Return fd on success, a negative value on error. + * Return allocated struct lttng_index_file, NULL on error. */ -int index_create_file(char *path_name, char *stream_name, int uid, int gid, - uint64_t size, uint64_t count) +struct lttng_index_file *lttng_index_file_create(char *path_name, + char *stream_name, int uid, int gid, + uint64_t size, uint64_t count, uint32_t major, uint32_t minor) { + struct lttng_index_file *index_file; int ret, fd = -1; ssize_t size_ret; struct ctf_packet_index_file_hdr hdr; char fullpath[PATH_MAX]; + uint32_t element_len = ctf_packet_index_len(major, minor); + + index_file = zmalloc(sizeof(*index_file)); + if (!index_file) { + PERROR("allocating lttng_index_file"); + goto error; + } ret = snprintf(fullpath, sizeof(fullpath), "%s/" DEFAULT_INDEX_DIR, path_name); @@ -49,14 +60,27 @@ int index_create_file(char *path_name, char *stream_name, int uid, int gid, } /* Create index directory if necessary. */ - ret = run_as_mkdir(fullpath, S_IRWXU | S_IRWXG, uid, gid); + ret = utils_mkdir(fullpath, S_IRWXU | S_IRWXG, uid, gid); if (ret < 0) { - if (ret != -EEXIST) { - ERR("Index trace directory creation error"); + if (errno != EEXIST) { + PERROR("Index trace directory creation error"); goto error; } } + /* + * For tracefile rotation. We need to unlink the old + * file if present to synchronize with the tail of the + * live viewer which could be working on this same file. + * By doing so, any reference to the old index file + * stays valid even if we re-create a new file with the + * same name afterwards. + */ + ret = utils_unlink_stream_file(fullpath, stream_name, size, count, uid, + gid, DEFAULT_INDEX_FILE_SUFFIX); + if (ret < 0 && errno != ENOENT) { + goto error; + } ret = utils_create_stream_file(fullpath, stream_name, size, count, uid, gid, DEFAULT_INDEX_FILE_SUFFIX); if (ret < 0) { @@ -65,9 +89,9 @@ int index_create_file(char *path_name, char *stream_name, int uid, int gid, fd = ret; hdr.magic = htobe32(CTF_INDEX_MAGIC); - hdr.index_major = htobe32(CTF_INDEX_MAJOR); - hdr.index_minor = htobe32(CTF_INDEX_MINOR); - hdr.packet_index_len = sizeof(struct ctf_packet_index); + hdr.index_major = htobe32(major); + hdr.index_minor = htobe32(minor); + hdr.packet_index_len = htobe32(element_len); size_ret = lttng_write(fd, &hdr, sizeof(hdr)); if (size_ret < sizeof(hdr)) { @@ -75,8 +99,13 @@ int index_create_file(char *path_name, char *stream_name, int uid, int gid, ret = -1; goto error; } + index_file->fd = fd; + index_file->major = major; + index_file->minor = minor; + index_file->element_len = element_len; + urcu_ref_init(&index_file->ref); - return fd; + return index_file; error: if (fd >= 0) { @@ -87,46 +116,93 @@ error: PERROR("close index fd"); } } - return ret; + free(index_file); + return NULL; } /* - * Write index values to the given fd of size len. + * Write index values to the given index file. * - * Return "len" on success or else < len on error. errno contains error - * details. + * Return 0 on success, -1 on error. */ -ssize_t index_write(int fd, struct ctf_packet_index *index, size_t len) +int lttng_index_file_write(const struct lttng_index_file *index_file, + const struct ctf_packet_index *element) { ssize_t ret; + int fd = index_file->fd; + size_t len = index_file->element_len; - assert(fd >= 0); - assert(index); + assert(element); - ret = lttng_write(fd, index, len); + if (fd < 0) { + goto error; + } + + ret = lttng_write(fd, element, len); if (ret < len) { PERROR("writing index file"); + goto error; + } + return 0; + +error: + return -1; +} + +/* + * Read index values from the given index file. + * + * Return 0 on success, -1 on error. + */ +int lttng_index_file_read(const struct lttng_index_file *index_file, + struct ctf_packet_index *element) +{ + ssize_t ret; + int fd = index_file->fd; + size_t len = index_file->element_len; + + assert(element); + + if (fd < 0) { + goto error; } - return ret; + ret = lttng_read(fd, element, len); + if (ret < len) { + PERROR("read index file"); + goto error; + } + return 0; + +error: + return -1; } /* * Open index file using a given path, channel name and tracefile count. * - * Return read only FD on success or else a negative value. + * Return allocated struct lttng_index_file, NULL on error. */ -int index_open(const char *path_name, const char *channel_name, - uint64_t tracefile_count, uint64_t tracefile_count_current) +struct lttng_index_file *lttng_index_file_open(const char *path_name, + const char *channel_name, uint64_t tracefile_count, + uint64_t tracefile_count_current) { + struct lttng_index_file *index_file; int ret, read_fd; ssize_t read_len; char fullpath[PATH_MAX]; struct ctf_packet_index_file_hdr hdr; + uint32_t major, minor, element_len; assert(path_name); assert(channel_name); + index_file = zmalloc(sizeof(*index_file)); + if (!index_file) { + PERROR("allocating lttng_index_file"); + goto error; + } + if (tracefile_count > 0) { ret = snprintf(fullpath, sizeof(fullpath), "%s/" DEFAULT_INDEX_DIR "/%s_%" PRIu64 DEFAULT_INDEX_FILE_SUFFIX, path_name, @@ -161,13 +237,26 @@ int index_open(const char *path_name, const char *channel_name, ERR("Invalid header magic"); goto error_close; } - if (be32toh(hdr.index_major) != CTF_INDEX_MAJOR || - be32toh(hdr.index_minor) != CTF_INDEX_MINOR) { + major = be32toh(hdr.index_major); + minor = be32toh(hdr.index_minor); + element_len = be32toh(hdr.packet_index_len); + + if (major != CTF_INDEX_MAJOR) { ERR("Invalid header version"); goto error_close; } + if (element_len > sizeof(struct ctf_packet_index)) { + ERR("Index element length too long"); + goto error_close; + } + + index_file->fd = read_fd; + index_file->major = major; + index_file->minor = minor; + index_file->element_len = element_len; + urcu_ref_init(&index_file->ref); - return read_fd; + return index_file; error_close: if (read_fd >= 0) { @@ -181,5 +270,27 @@ error_close: ret = -1; error: - return ret; + free(index_file); + return NULL; +} + +void lttng_index_file_get(struct lttng_index_file *index_file) +{ + urcu_ref_get(&index_file->ref); +} + +static void lttng_index_file_release(struct urcu_ref *ref) +{ + struct lttng_index_file *index_file = caa_container_of(ref, + struct lttng_index_file, ref); + + if (close(index_file->fd)) { + PERROR("close index fd"); + } + free(index_file); +} + +void lttng_index_file_put(struct lttng_index_file *index_file) +{ + urcu_ref_put(&index_file->ref, lttng_index_file_release); }