From: Julien Desfossez Date: Thu, 28 Mar 2013 15:48:02 +0000 (-0400) Subject: Move stream file rotation functions to utils X-Git-Tag: v2.2.0-rc1~5 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=fe4477ee14abb348ce9e167f8b4c09312d67de36;p=lttng-tools.git Move stream file rotation functions to utils These functions are now in libcommon which can be used by the relayd and consumer. Signed-off-by: Julien Desfossez Signed-off-by: David Goulet --- diff --git a/src/common/consumer.c b/src/common/consumer.c index a9070b1c9..52a4ed171 100644 --- a/src/common/consumer.c +++ b/src/common/consumer.c @@ -1287,99 +1287,6 @@ end: return ret; } -/* - * Create the tracefile on disk. - * - * Return 0 on success or else a negative value. - */ -int lttng_create_output_file(struct lttng_consumer_stream *stream) -{ - int ret; - char full_path[PATH_MAX]; - char *path_name_id = NULL; - char *path; - - assert(stream); - - /* Don't create anything if this is set for streaming. */ - if (stream->net_seq_idx != (uint64_t) -1ULL) { - ret = 0; - goto end; - } - - ret = snprintf(full_path, sizeof(full_path), "%s/%s", - stream->chan->pathname, stream->name); - if (ret < 0) { - PERROR("snprintf create output file"); - goto error; - } - - /* - * If we split the trace in multiple files, we have to add the tracefile - * current count at the end of the tracefile name - */ - if (stream->chan->tracefile_size > 0) { - ret = asprintf(&path_name_id, "%s_%" PRIu64, full_path, - stream->tracefile_count_current); - if (ret < 0) { - PERROR("Allocating path name ID"); - goto error; - } - path = path_name_id; - } else { - path = full_path; - } - - ret = run_as_open(path, O_WRONLY | O_CREAT | O_TRUNC, - S_IRWXU | S_IRWXG | S_IRWXO, stream->uid, stream->gid); - if (ret < 0) { - PERROR("open stream path %s", path); - goto error_open; - } - stream->out_fd = ret; - stream->tracefile_size_current = 0; - -error_open: - free(path_name_id); -error: -end: - return ret; -} - -/* - * Change the output tracefile according to the tracefile_size and - * tracefile_count parameters. The stream lock MUST be held before calling this - * function because we are modifying the stream status. - * - * Return 0 on success or else a negative value. - */ -static int rotate_output_file(struct lttng_consumer_stream *stream) -{ - int ret; - - assert(stream); - assert(stream->tracefile_size_current); - - ret = close(stream->out_fd); - if (ret < 0) { - PERROR("Closing tracefile"); - goto end; - } - - if (stream->chan->tracefile_count > 0) { - stream->tracefile_count_current = - (stream->tracefile_count_current + 1) % - stream->chan->tracefile_count; - } else { - stream->tracefile_count_current++; - } - - return lttng_create_output_file(stream); - -end: - return ret; -} - /* * Mmap the ring buffer, read it and write the data to the tracefile. This is a * core function for writing trace buffers to either the local filesystem or @@ -1494,12 +1401,15 @@ ssize_t lttng_consumer_on_read_subbuffer_mmap( if (stream->chan->tracefile_size > 0 && (stream->tracefile_size_current + len) > stream->chan->tracefile_size) { - ret = rotate_output_file(stream); + ret = utils_rotate_stream_file(stream->chan->pathname, + stream->name, stream->chan->tracefile_size, + stream->chan->tracefile_count, stream->uid, stream->gid, + stream->out_fd, &(stream->tracefile_count_current)); if (ret < 0) { ERR("Rotating output file"); goto end; } - outfd = stream->out_fd; + outfd = stream->out_fd = ret; } stream->tracefile_size_current += len; } @@ -1671,12 +1581,15 @@ ssize_t lttng_consumer_on_read_subbuffer_splice( if (stream->chan->tracefile_size > 0 && (stream->tracefile_size_current + len) > stream->chan->tracefile_size) { - ret = rotate_output_file(stream); + ret = utils_rotate_stream_file(stream->chan->pathname, + stream->name, stream->chan->tracefile_size, + stream->chan->tracefile_count, stream->uid, stream->gid, + stream->out_fd, &(stream->tracefile_count_current)); if (ret < 0) { ERR("Rotating output file"); goto end; } - outfd = stream->out_fd; + outfd = stream->out_fd = ret; } stream->tracefile_size_current += len; } diff --git a/src/common/consumer.h b/src/common/consumer.h index 0931250b0..19a590e80 100644 --- a/src/common/consumer.h +++ b/src/common/consumer.h @@ -494,7 +494,6 @@ struct lttng_consumer_local_data *lttng_consumer_create( int (*recv_stream)(struct lttng_consumer_stream *stream), int (*update_stream)(int sessiond_key, uint32_t state)); void lttng_consumer_destroy(struct lttng_consumer_local_data *ctx); -int lttng_create_output_file(struct lttng_consumer_stream *stream); ssize_t lttng_consumer_on_read_subbuffer_mmap( struct lttng_consumer_local_data *ctx, struct lttng_consumer_stream *stream, unsigned long len, diff --git a/src/common/kernel-consumer/kernel-consumer.c b/src/common/kernel-consumer/kernel-consumer.c index 385af875a..bc3ddc930 100644 --- a/src/common/kernel-consumer/kernel-consumer.c +++ b/src/common/kernel-consumer/kernel-consumer.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "kernel-consumer.h" @@ -506,10 +507,16 @@ int lttng_kconsumer_on_recv_stream(struct lttng_consumer_stream *stream) assert(stream); - ret = lttng_create_output_file(stream); - if (ret < 0) { - ERR("Creating output file"); - goto error; + /* Don't create anything if this is set for streaming. */ + if (stream->net_seq_idx == (uint64_t) -1ULL) { + ret = utils_create_stream_file(stream->chan->pathname, stream->name, + stream->chan->tracefile_size, stream->tracefile_count_current, + stream->uid, stream->gid); + if (ret < 0) { + goto error; + } + stream->out_fd = ret; + stream->tracefile_size_current = 0; } if (stream->output == LTTNG_EVENT_MMAP) { diff --git a/src/common/ust-consumer/ust-consumer.c b/src/common/ust-consumer/ust-consumer.c index b558988dc..bc0f58538 100644 --- a/src/common/ust-consumer/ust-consumer.c +++ b/src/common/ust-consumer/ust-consumer.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "ust-consumer.h" @@ -1283,10 +1284,28 @@ end: /* * Called when a stream is created. + * + * Return 0 on success or else a negative value. */ int lttng_ustconsumer_on_recv_stream(struct lttng_consumer_stream *stream) { - return lttng_create_output_file(stream); + int ret; + + /* Don't create anything if this is set for streaming. */ + if (stream->net_seq_idx == (uint64_t) -1ULL) { + ret = utils_create_stream_file(stream->chan->pathname, stream->name, + stream->chan->tracefile_size, stream->tracefile_count_current, + stream->uid, stream->gid); + if (ret < 0) { + goto error; + } + stream->out_fd = ret; + stream->tracefile_size_current = 0; + } + ret = 0; + +error: + return ret; } /* diff --git a/src/common/utils.c b/src/common/utils.c index a18e906d7..9f3a8f942 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -25,8 +25,10 @@ #include #include #include +#include #include +#include #include "utils.h" @@ -301,3 +303,85 @@ int utils_mkdir_recursive(const char *path, mode_t mode) error: return ret; } + +/* + * Create the stream tracefile on disk. + * + * Return 0 on success or else a negative value. + */ +int utils_create_stream_file(char *path_name, char *file_name, uint64_t size, + uint64_t count, int uid, int gid) +{ + int ret, out_fd; + char full_path[PATH_MAX], *path_name_id = NULL, *path; + + assert(path_name); + assert(file_name); + + ret = snprintf(full_path, sizeof(full_path), "%s/%s", + path_name, file_name); + if (ret < 0) { + PERROR("snprintf create output file"); + goto error; + } + + /* + * If we split the trace in multiple files, we have to add the count at the + * end of the tracefile name + */ + if (size > 0) { + ret = asprintf(&path_name_id, "%s_%" PRIu64, full_path, count); + if (ret < 0) { + PERROR("Allocating path name ID"); + goto error; + } + path = path_name_id; + } else { + path = full_path; + } + + out_fd = run_as_open(path, O_WRONLY | O_CREAT | O_TRUNC, + S_IRWXU | S_IRWXG | S_IRWXO, uid, gid); + if (out_fd < 0) { + PERROR("open stream path %s", path); + goto error_open; + } + ret = out_fd; + +error_open: + free(path_name_id); +error: + return ret; +} + +/* + * Change the output tracefile according to the given size and count The + * new_count pointer is set during this operation. + * + * From the consumer, the stream lock MUST be held before calling this function + * because we are modifying the stream status. + * + * Return 0 on success or else a negative value. + */ +int utils_rotate_stream_file(char *path_name, char *file_name, uint64_t size, + uint64_t count, int uid, int gid, int out_fd, uint64_t *new_count) +{ + int ret; + + ret = close(out_fd); + if (ret < 0) { + PERROR("Closing tracefile"); + goto error; + } + + if (count > 0) { + *new_count = (*new_count + 1) % count; + } else { + (*new_count)++; + } + + return utils_create_stream_file(path_name, file_name, size, *new_count, + uid, gid); +error: + return ret; +} diff --git a/src/common/utils.h b/src/common/utils.h index f63e84e5b..2d39cefb9 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -26,5 +26,9 @@ char *utils_strdupdelim(const char *begin, const char *end); int utils_set_fd_cloexec(int fd); int utils_create_pid_file(pid_t pid, const char *filepath); int utils_mkdir_recursive(const char *path, mode_t mode); +int utils_create_stream_file(char *path_name, char *file_name, uint64_t size, + uint64_t count, int uid, int gid); +int utils_rotate_stream_file(char *path_name, char *file_name, uint64_t size, + uint64_t count, int uid, int gid, int out_fd, uint64_t *new_count); #endif /* _COMMON_UTILS_H */ diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am index 169ca2ebe..c9e1bfcf4 100644 --- a/tests/unit/Makefile.am +++ b/tests/unit/Makefile.am @@ -22,7 +22,7 @@ endif # URI unit tests test_uri_SOURCES = test_uri.c -test_uri_LDADD = $(LIBTAP) $(LIBCOMMON) +test_uri_LDADD = $(LIBTAP) $(LIBCOMMON) $(LIBHASHTABLE) # Session unit test SESSIONS=$(top_srcdir)/src/bin/lttng-sessiond/session.c \