X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;ds=sidebyside;f=converter%2Fbabeltrace.c;h=43121dc43f0a6c42a63131bbbf6c14466ad233d2;hb=33bceaf8b418f6f3e63371e4ba36ed552e8fe2df;hp=2fd371c396a9f218c575eaaff704ca2571f33656;hpb=65923160260ca0d5928db5d8840e76576cb429c4;p=babeltrace.git diff --git a/converter/babeltrace.c b/converter/babeltrace.c index 2fd371c3..43121dc4 100644 --- a/converter/babeltrace.c +++ b/converter/babeltrace.c @@ -26,8 +26,6 @@ * SOFTWARE. */ -#define _GNU_SOURCE -#include #include #include #include @@ -38,7 +36,10 @@ #include #include #include +#include + #include +#include #include #include #include @@ -57,6 +58,11 @@ #define DEFAULT_FILE_ARRAY_SIZE 1 +#define NET_URL_PREFIX "net://" +#define NET4_URL_PREFIX "net4://" +#define NET6_URL_PREFIX "net6://" + +static struct bt_component_factory *component_factory; static char *opt_input_format, *opt_output_format; /* @@ -68,9 +74,17 @@ static char *opt_input_format, *opt_output_format; */ static GPtrArray *opt_input_paths; static char *opt_output_path; +static int opt_stream_intersection; +static char *opt_plugin_path; static struct bt_format *fmt_read; +void bt_dummy_hook(void); +void bt_lttng_live_hook(void); +void bt_ctf_hook(void); +void bt_ctf_text_hook(void); +void bt_ctf_metadata_hook(void); + static void strlower(char *str) { @@ -87,6 +101,7 @@ enum { OPT_OUTPUT_FORMAT, OPT_HELP, OPT_LIST, + OPT_PLUGIN_PATH, OPT_VERBOSE, OPT_DEBUG, OPT_NAMES, @@ -99,10 +114,14 @@ enum { OPT_CLOCK_DATE, OPT_CLOCK_GMT, OPT_CLOCK_FORCE_CORRELATE, + OPT_STREAM_INTERSECTION, + OPT_DEBUG_INFO_DIR, + OPT_DEBUG_INFO_FULL_PATH, + OPT_DEBUG_INFO_TARGET_PREFIX, }; /* - * We are _not_ using POPT_ARG_STRING ability to store directly into + * We are _not_ using POPT_ARG_STRING's ability to store directly into * variables, because we want to cast the return to non-const, which is * not possible without using poptGetOptArg explicitly. This helps us * controlling memory allocation correctly without making assumptions @@ -116,6 +135,7 @@ static struct poptOption long_options[] = { { "output-format", 'o', POPT_ARG_STRING, NULL, OPT_OUTPUT_FORMAT, NULL, NULL }, { "help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL }, { "list", 'l', POPT_ARG_NONE, NULL, OPT_LIST, NULL, NULL }, + { "plugin-path", 0, POPT_ARG_STRING, NULL, OPT_PLUGIN_PATH, NULL, NULL }, { "verbose", 'v', POPT_ARG_NONE, NULL, OPT_VERBOSE, NULL, NULL }, { "debug", 'd', POPT_ARG_NONE, NULL, OPT_DEBUG, NULL, NULL }, { "names", 'n', POPT_ARG_STRING, NULL, OPT_NAMES, NULL, NULL }, @@ -128,6 +148,12 @@ static struct poptOption long_options[] = { { "clock-date", 0, POPT_ARG_NONE, NULL, OPT_CLOCK_DATE, NULL, NULL }, { "clock-gmt", 0, POPT_ARG_NONE, NULL, OPT_CLOCK_GMT, NULL, NULL }, { "clock-force-correlate", 0, POPT_ARG_NONE, NULL, OPT_CLOCK_FORCE_CORRELATE, NULL, NULL }, + { "stream-intersection", 0, POPT_ARG_NONE, NULL, OPT_STREAM_INTERSECTION, NULL, NULL }, +#ifdef ENABLE_DEBUG_INFO + { "debug-info-dir", 0, POPT_ARG_STRING, NULL, OPT_DEBUG_INFO_DIR, NULL, NULL }, + { "debug-info-full-path", 0, POPT_ARG_NONE, NULL, OPT_DEBUG_INFO_FULL_PATH, NULL, NULL }, + { "debug-info-target-prefix", 0, POPT_ARG_STRING, NULL, OPT_DEBUG_INFO_TARGET_PREFIX, NULL, NULL }, +#endif { NULL, 0, 0, NULL, 0, NULL, NULL }, }; @@ -151,6 +177,7 @@ static void usage(FILE *fp) fprintf(fp, "\n"); fprintf(fp, " -h, --help This help message\n"); fprintf(fp, " -l, --list List available formats\n"); + fprintf(fp, " --plugin-path Supplementary plug-in path\n"); fprintf(fp, " -v, --verbose Verbose mode\n"); fprintf(fp, " (or set BABELTRACE_VERBOSE environment variable)\n"); fprintf(fp, " -d, --debug Debug mode\n"); @@ -173,6 +200,13 @@ static void usage(FILE *fp) fprintf(fp, " --clock-gmt Print clock in GMT time zone (default: local time zone)\n"); fprintf(fp, " --clock-force-correlate Assume that clocks are inherently correlated\n"); fprintf(fp, " across traces.\n"); + fprintf(fp, " --stream-intersection Only print events when all streams are active.\n"); +#ifdef ENABLE_DEBUG_INFO + fprintf(fp, " --debug-info-dir Directory in which to look for debugging information\n"); + fprintf(fp, " files. (default: /usr/lib/debug/)\n"); + fprintf(fp, " --debug-info-target-prefix Directory to use as a prefix for executable lookup\n"); + fprintf(fp, " --debug-info-full-path Show full debug info source and binary paths (if available)\n"); +#endif list_formats(fp); fprintf(fp, "\n"); } @@ -311,6 +345,13 @@ static int parse_options(int argc, char **argv) list_formats(stdout); ret = 1; goto end; + case OPT_PLUGIN_PATH: + opt_plugin_path = (char *) poptGetOptArg(pc); + if (!opt_plugin_path) { + ret = -EINVAL; + goto end; + } ; + break; case OPT_VERBOSE: babeltrace_verbose = 1; break; @@ -347,7 +388,7 @@ static int parse_options(int argc, char **argv) goto end; } errno = 0; - opt_clock_offset = strtoull(str, &endptr, 0); + opt_clock_offset = strtoll(str, &endptr, 0); if (*endptr != '\0' || str == endptr || errno != 0) { fprintf(stderr, "[error] Incorrect --clock-offset argument: %s\n", str); ret = -EINVAL; @@ -372,7 +413,7 @@ static int parse_options(int argc, char **argv) goto end; } errno = 0; - opt_clock_offset_ns = strtoull(str, &endptr, 0); + opt_clock_offset_ns = strtoll(str, &endptr, 0); if (*endptr != '\0' || str == endptr || errno != 0) { fprintf(stderr, "[error] Incorrect --clock-offset-ns argument: %s\n", str); ret = -EINVAL; @@ -392,7 +433,26 @@ static int parse_options(int argc, char **argv) case OPT_CLOCK_FORCE_CORRELATE: opt_clock_force_correlate = 1; break; - + case OPT_STREAM_INTERSECTION: + opt_stream_intersection = 1; + break; + case OPT_DEBUG_INFO_DIR: + opt_debug_info_dir = (char *) poptGetOptArg(pc); + if (!opt_debug_info_dir) { + ret = -EINVAL; + goto end; + } + break; + case OPT_DEBUG_INFO_FULL_PATH: + opt_debug_info_full_path = 1; + break; + case OPT_DEBUG_INFO_TARGET_PREFIX: + opt_debug_info_target_prefix = (char *) poptGetOptArg(pc); + if (!opt_debug_info_target_prefix) { + ret = -EINVAL; + goto end; + } + break; default: ret = -EINVAL; goto end; @@ -404,10 +464,6 @@ static int parse_options(int argc, char **argv) if (ipath) g_ptr_array_add(opt_input_paths, (gpointer) ipath); } while (ipath); - if (opt_input_paths->len == 0) { - ret = -EINVAL; - goto end; - } end: if (pc) { @@ -451,15 +507,20 @@ static int traverse_trace_dir(const char *fpath, const struct stat *sb, /* No meta data, just return */ return 0; } else { + int err_close = 0; + closeret = close(metafd); if (closeret < 0) { perror("close"); - return -1; /* failure */ + err_close = 1; } closeret = close(dirfd); if (closeret < 0) { perror("close"); - return -1; /* failure */ + err_close = 1; + } + if (err_close) { + return -1; } /* Add path to the global list */ @@ -490,15 +551,22 @@ int bt_context_add_traces_recursive(struct bt_context *ctx, const char *path, void (*packet_seek)(struct bt_stream_pos *pos, size_t offset, int whence)) { + int ret = 0, trace_ids = 0; - GArray *trace_ids; - int ret = 0; - + if ((strncmp(path, NET4_URL_PREFIX, sizeof(NET4_URL_PREFIX) - 1)) == 0 || + (strncmp(path, NET6_URL_PREFIX, sizeof(NET6_URL_PREFIX) - 1)) == 0 || + (strncmp(path, NET_URL_PREFIX, sizeof(NET_URL_PREFIX) - 1)) == 0) { + ret = bt_context_add_trace(ctx, + path, format_str, packet_seek, NULL, NULL); + if (ret < 0) { + fprintf(stderr, "[warning] [Context] cannot open trace \"%s\" " + "for reading.\n", path); + } + return ret; + } /* Should lock traversed_paths mutex here if used in multithread */ traversed_paths = g_ptr_array_new(); - trace_ids = g_array_new(FALSE, TRUE, sizeof(int)); - ret = nftw(path, traverse_trace_dir, 10, 0); /* Process the array if ntfw did not return a fatal error */ @@ -520,7 +588,7 @@ int bt_context_add_traces_recursive(struct bt_context *ctx, const char *path, /* Allow to skip erroneous traces. */ ret = 1; /* partial error */ } else { - g_array_append_val(trace_ids, trace_id); + trace_ids++; } g_string_free(trace_path, TRUE); } @@ -534,11 +602,10 @@ int bt_context_add_traces_recursive(struct bt_context *ctx, const char *path, /* * Return an error if no trace can be opened. */ - if (trace_ids->len == 0) { + if (trace_ids == 0) { fprintf(stderr, "[error] Cannot open any trace for reading.\n\n"); ret = -ENOENT; /* failure */ } - g_array_free(trace_ids, TRUE); return ret; } @@ -608,18 +675,24 @@ int convert_trace(struct bt_trace_descriptor *td_write, { struct bt_ctf_iter *iter; struct ctf_text_stream_pos *sout; - struct bt_iter_pos begin_pos; + struct bt_iter_pos *begin_pos = NULL, *end_pos = NULL; struct bt_ctf_event *ctf_event; int ret; sout = container_of(td_write, struct ctf_text_stream_pos, trace_descriptor); - if (!sout->parent.event_cb) + if (!sout->parent.event_cb) { return 0; + } - begin_pos.type = BT_SEEK_BEGIN; - iter = bt_ctf_iter_create(ctx, &begin_pos, NULL); + if (opt_stream_intersection) { + iter = bt_ctf_iter_create_intersect(ctx, &begin_pos, &end_pos); + } else { + begin_pos = bt_iter_create_time_pos(NULL, 0); + begin_pos->type = BT_SEEK_BEGIN; + iter = bt_ctf_iter_create(ctx, begin_pos, NULL); + } if (!iter) { ret = -1; goto error_iter; @@ -631,17 +704,29 @@ int convert_trace(struct bt_trace_descriptor *td_write, goto end; } ret = bt_iter_next(bt_ctf_get_iter(iter)); - if (ret < 0) + if (ret < 0) { goto end; + } } ret = 0; end: bt_ctf_iter_destroy(iter); error_iter: + bt_iter_free_pos(begin_pos); + bt_iter_free_pos(end_pos); return ret; } +void call_plugins_hooks(void) +{ + bt_dummy_hook(); + bt_lttng_live_hook(); + bt_ctf_hook(); + bt_ctf_text_hook(); + bt_ctf_metadata_hook(); +} + int main(int argc, char **argv) { int ret, partial_error = 0, open_success = 0; @@ -650,6 +735,8 @@ int main(int argc, char **argv) struct bt_context *ctx; int i; + call_plugins_hooks(); + opt_input_paths = g_ptr_array_new(); ret = parse_options(argc, argv); @@ -665,6 +752,31 @@ int main(int argc, char **argv) printf_verbose("Verbose mode active.\n"); printf_debug("Debug mode active.\n"); + if (!opt_plugin_path) { + fprintf(stderr, "No plugin path specified, aborting...\n"); + ret = -1; + goto end; + } + printf_verbose("Looking-up plugins at %s", + opt_plugin_path ? opt_plugin_path : "Invalid"); + component_factory = bt_component_factory_create(); + if (!component_factory) { + fprintf(stderr, "Failed to create component factory.\n"); + ret = -1; + goto end; + } + + ret = bt_component_factory_load(component_factory, opt_plugin_path); + if (ret) { + fprintf(stderr, "Failed to load plugins.\n"); + goto end; + } + + if (opt_input_paths->len == 0) { + ret = -1; + goto end; + } + if (opt_input_format) strlower(opt_input_format); if (opt_output_format) @@ -697,7 +809,7 @@ int main(int argc, char **argv) } } fmt_read = bt_lookup_format(g_quark_from_static_string(opt_input_format)); - if (!fmt_read || fmt_read->name != g_quark_from_static_string("ctf")) { + if (!fmt_read) { fprintf(stderr, "[error] Format \"%s\" is not supported.\n\n", opt_input_format); partial_error = 1; @@ -757,10 +869,13 @@ int main(int argc, char **argv) goto error_copy_trace; } - ret = convert_trace(td_write, ctx); - if (ret) { - fprintf(stderr, "Error printing trace.\n\n"); - goto error_copy_trace; + /* For now, we support only CTF iterators */ + if (fmt_read->name == g_quark_from_static_string("ctf")) { + ret = convert_trace(td_write, ctx); + if (ret) { + fprintf(stderr, "Error printing trace.\n\n"); + goto error_copy_trace; + } } ret = trace_post_handler(td_write, ctx); @@ -789,6 +904,8 @@ end: free(opt_input_format); free(opt_output_format); free(opt_output_path); + free(opt_debug_info_dir); + free(opt_debug_info_target_prefix); g_ptr_array_free(opt_input_paths, TRUE); if (partial_error) exit(EXIT_FAILURE);