From: Amer Alhalabi Date: Fri, 5 Aug 2011 18:42:35 +0000 (-0400) Subject: Multiple Directory Conversion X-Git-Tag: v0.4~1 X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=afb48eae796fc5e35b7cb5e1363750091ad124aa Multiple Directory Conversion Code added/modified to merge and convert many CTF binary files located in different directories into one ASCII file. Edit by Mathieu Desnoyers: - Introduce struct trace_collection, because this will eventually be seen as an API to the outside world, so I want to hide the internal dependency on glib types. - Added #define _XOPEN_SOURCE 700 needed for openat and nftw at the top of babeltrace.c. Signed-off-by: Amer Alhalabi Signed-off-by: Mathieu Desnoyers --- diff --git a/converter/babeltrace-lib.c b/converter/babeltrace-lib.c index 6cc2b7b8..3f9369b4 100644 --- a/converter/babeltrace-lib.c +++ b/converter/babeltrace-lib.c @@ -57,37 +57,55 @@ int stream_compare(void *a, void *b) } int convert_trace(struct trace_descriptor *td_write, - struct trace_descriptor *td_read) + struct trace_collection *trace_collection_read) { - struct ctf_trace *tin = container_of(td_read, struct ctf_trace, parent); - struct ctf_text_stream_pos *sout = - container_of(td_write, struct ctf_text_stream_pos, trace_descriptor); - int stream_id; + struct ptr_heap *stream_heap; + struct ctf_text_stream_pos *sout; + int i, stream_id; int ret = 0; - tin->stream_heap = g_new(struct ptr_heap, 1); - heap_init(tin->stream_heap, 0, stream_compare); + stream_heap = g_new(struct ptr_heap, 1); + heap_init(stream_heap, 0, stream_compare); + sout = container_of(td_write, struct ctf_text_stream_pos, + trace_descriptor); - /* Populate heap with each stream */ - for (stream_id = 0; stream_id < tin->streams->len; stream_id++) { - struct ctf_stream_class *stream = g_ptr_array_index(tin->streams, stream_id); - int filenr; + for (i = 0; i < trace_collection_read->array->len; i++) { + struct ctf_trace *tin; + struct trace_descriptor *td_read; - if (!stream) - continue; - for (filenr = 0; filenr < stream->streams->len; filenr++) { - struct ctf_file_stream *file_stream = g_ptr_array_index(stream->streams, filenr); - ret = read_event(file_stream); - if (ret == EOF) { - ret = 0; + td_read = g_ptr_array_index(trace_collection_read->array, i); + tin = container_of(td_read, struct ctf_trace, parent); + + /* Populate heap with each stream */ + for (stream_id = 0; stream_id < tin->streams->len; + stream_id++) { + struct ctf_stream_class *stream; + int filenr; + + stream = g_ptr_array_index(tin->streams, stream_id); + if (!stream) continue; - } else if (ret) - goto end; - /* Add to heap */ - ret = heap_insert(tin->stream_heap, file_stream); - if (ret) { - fprintf(stdout, "[error] Out of memory.\n"); - goto end; + for (filenr = 0; filenr < stream->streams->len; + filenr++) { + struct ctf_file_stream *file_stream; + + file_stream = g_ptr_array_index(stream->streams, + filenr); + + ret = read_event(file_stream); + if (ret == EOF) { + ret = 0; + continue; + } else if (ret) { + goto end; + } + /* Add to heap */ + ret = heap_insert(stream_heap, file_stream); + if (ret) { + fprintf(stdout, + "[error] Out of memory.\n"); + goto end; + } } } } @@ -96,7 +114,7 @@ int convert_trace(struct trace_descriptor *td_write, for (;;) { struct ctf_file_stream *file_stream, *removed; - file_stream = heap_maximum(tin->stream_heap); + file_stream = heap_maximum(stream_heap); if (!file_stream) { /* end of file for all streams */ ret = 0; @@ -109,19 +127,19 @@ int convert_trace(struct trace_descriptor *td_write, } ret = read_event(file_stream); if (ret == EOF) { - removed = heap_remove(tin->stream_heap); + removed = heap_remove(stream_heap); assert(removed == file_stream); ret = 0; continue; } else if (ret) goto end; /* Reinsert the file stream into the heap, and rebalance. */ - removed = heap_replace_max(tin->stream_heap, file_stream); + removed = heap_replace_max(stream_heap, file_stream); assert(removed == file_stream); } end: - heap_free(tin->stream_heap); - g_free(tin->stream_heap); + heap_free(stream_heap); + g_free(stream_heap); return ret; } diff --git a/converter/babeltrace.c b/converter/babeltrace.c index dd335edb..9d79c39d 100644 --- a/converter/babeltrace.c +++ b/converter/babeltrace.c @@ -18,6 +18,7 @@ * all copies or substantial portions of the Software. */ +#define _XOPEN_SOURCE 700 #include #include #include @@ -27,7 +28,11 @@ #include #include #include +#include +#include +#include +#define DEFAULT_FILE_ARRAY_SIZE 1 static char *opt_input_format; static char *opt_output_format; @@ -37,6 +42,9 @@ static const char *opt_output_path; int babeltrace_verbose, babeltrace_debug; int opt_field_names; +static struct trace_collection trace_collection_read; +static struct format *fmt_read; + void strlower(char *str) { while (*str) { @@ -149,11 +157,78 @@ end: return ret; } +static void init_trace_collection(struct trace_collection *tc) +{ + tc->array = g_ptr_array_sized_new(DEFAULT_FILE_ARRAY_SIZE); +} + +/* + * finalize_trace_collection() closes the opened traces for read + * and free the memory allocated for trace collection + */ +static void finalize_trace_collection(struct trace_collection *tc) +{ + int i; + + for (i = 0; i < tc->array->len; i++) { + struct trace_descriptor *temp = + g_ptr_array_index(tc->array, i); + fmt_read->close_trace(temp); + } + g_ptr_array_free(tc->array, TRUE); +} + +static void trace_collection_add(struct trace_collection *tc, + struct trace_descriptor *td) +{ + g_ptr_array_add(tc->array, td); +} + +/* + * traverse_dir() is the callback functiion for File Tree Walk (nftw). + * it receives the path of the current entry (file, dir, link..etc) with + * a flag to indicate the type of the entry. + * if the entry being visited is a directory and contains a metadata file, + * then open it for reading and save a trace_descriptor to that directory + * in the read trace collection. + */ +static int traverse_dir(const char *fpath, const struct stat *sb, + int tflag, struct FTW *ftwbuf) +{ + int dirfd; + int fd; + struct trace_descriptor *td_read; + + if (tflag != FTW_D) + return 0; + dirfd = open(fpath, 0); + if (dirfd < 0) { + fprintf(stdout, "[error] unable to open trace " + "directory file descriptor.\n"); + return -1; + } + fd = openat(dirfd, "metadata", O_RDONLY); + if (fd < 0) { + close(dirfd); + } else { + close(fd); + close(dirfd); + td_read = fmt_read->open_trace(fpath, O_RDONLY); + if (!td_read) { + fprintf(stdout, "Error opening trace \"%s\" " + "for reading.\n\n", fpath); + return -1; /* error */ + } + trace_collection_add(&trace_collection_read, td_read); + } + return 0; /* success */ +} + int main(int argc, char **argv) { int ret; - struct format *fmt_read, *fmt_write; - struct trace_descriptor *td_read, *td_write; + struct format *fmt_write; + struct trace_descriptor *td_write; ret = parse_options(argc, argv); if (ret < 0) { @@ -171,10 +246,10 @@ int main(int argc, char **argv) if (opt_output_format) strlower(opt_output_format); - printf_verbose("Converting from file: %s\n", opt_input_path); + printf_verbose("Converting from directory: %s\n", opt_input_path); printf_verbose("Converting from format: %s\n", opt_input_format ? : "ctf "); - printf_verbose("Converting to file: %s\n", + printf_verbose("Converting to directory: %s\n", opt_output_path ? : ""); printf_verbose("Converting to format: %s\n", opt_output_format ? : "text "); @@ -196,12 +271,25 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } - td_read = fmt_read->open_trace(opt_input_path, O_RDONLY); - if (!td_read) { + /* + * pass the input path to nftw() . + * specify traverse_dir() as the callback function. + * depth = 10 which is the max number of file descriptors + * that nftw() can open at a given time. + * flags = 0 check nftw documentation for more info . + */ + init_trace_collection(&trace_collection_read); + ret = nftw(opt_input_path, traverse_dir, 10, 0); + if (ret != 0) { fprintf(stdout, "[error] opening trace \"%s\" for reading.\n\n", opt_input_path); goto error_td_read; } + if (trace_collection_read.array->len == 0) { + fprintf(stdout, "[warning] no metadata file was found." + " no output was generated\n"); + return 0; + } td_write = fmt_write->open_trace(opt_output_path, O_RDWR); if (!td_write) { @@ -210,21 +298,23 @@ int main(int argc, char **argv) goto error_td_write; } - ret = convert_trace(td_write, td_read); + ret = convert_trace(td_write, &trace_collection_read); if (ret) { fprintf(stdout, "Error printing trace.\n\n"); goto error_copy_trace; } fmt_write->close_trace(td_write); - fmt_read->close_trace(td_read); + finalize_trace_collection(&trace_collection_read); + printf_verbose("finished converting. Output written to:\n%s\n", + opt_output_path ? : ""); exit(EXIT_SUCCESS); /* Error handling */ error_copy_trace: fmt_write->close_trace(td_write); error_td_write: - fmt_read->close_trace(td_read); + finalize_trace_collection(&trace_collection_read); error_td_read: exit(EXIT_FAILURE); } diff --git a/include/babeltrace/babeltrace.h b/include/babeltrace/babeltrace.h index b7646a1d..cb28eb79 100644 --- a/include/babeltrace/babeltrace.h +++ b/include/babeltrace/babeltrace.h @@ -2,6 +2,7 @@ #define _BABELTRACE_H #include +#include #define BABELTRACE_VERSION_MAJOR 0 #define BABELTRACE_VERSION_MINOR 1 @@ -21,9 +22,12 @@ extern int babeltrace_verbose, babeltrace_debug; } while (0) struct trace_descriptor; +struct trace_collection { + GPtrArray *array; +}; int convert_trace(struct trace_descriptor *td_write, - struct trace_descriptor *td_read); + struct trace_collection *trace_collection_read); extern int opt_field_names;