In two steps I tried to improve the `main()` function. The reason for
those patches is that the current `main()` function is doing much more
than the necessary (implementing commands); this makes the code not
uniform and less clear.
Tests
Since those patches are mainly, copy & paste and re-writing how `trace-cmd`
runs command, I tested these changes by executing the help message for all
the commands. In principle, if we are able to run the commands the patches
are correct.
Most of the commands have the implementation in a dedicated file.
Those commands without a dedicated file are implemented in the
`main()` function. This patch uniform the code by moving the commands
implemented in the `main()` function to dedicated files.
Signed-off-by: Federico Vaga <[email protected]>
---
Makefile | 3 +-
trace-check-events.c | 66 ++++++
trace-cmd.c | 631 +--------------------------------------------------
trace-list.c | 486 +++++++++++++++++++++++++++++++++++++++
trace-local.h | 7 +
trace-show.c | 176 ++++++++++++++
6 files changed, 741 insertions(+), 628 deletions(-)
create mode 100644 trace-check-events.c
create mode 100644 trace-list.c
create mode 100644 trace-show.c
diff --git a/Makefile b/Makefile
index a3c6bfa..2be2754 100644
--- a/Makefile
+++ b/Makefile
@@ -341,7 +341,8 @@ TRACE_GUI_OBJS = trace-filter.o trace-compat.o trace-filter-hash.o trace-dialog.
trace-xml.o
TRACE_CMD_OBJS = trace-cmd.o trace-record.o trace-read.o trace-split.o trace-listen.o \
trace-stack.o trace-hist.o trace-mem.o trace-snapshot.o trace-stat.o \
- trace-hash.o trace-profile.o trace-stream.o trace-record.o trace-restore.o
+ trace-hash.o trace-profile.o trace-stream.o trace-record.o trace-restore.o \
+ trace-check-events.o trace-show.o trace-list.o
TRACE_VIEW_OBJS = trace-view.o trace-view-store.o
TRACE_GRAPH_OBJS = trace-graph.o trace-plot.o trace-plot-cpu.o trace-plot-task.o
TRACE_VIEW_MAIN_OBJS = trace-view-main.o $(TRACE_VIEW_OBJS) $(TRACE_GUI_OBJS)
diff --git a/trace-check-events.c b/trace-check-events.c
new file mode 100644
index 0000000..c5a0127
--- /dev/null
+++ b/trace-check-events.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <[email protected]>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdlib.h>
+#include <getopt.h>
+#include <errno.h>
+
+#include "trace-local.h"
+
+void trace_check_events(int argc, char **argv)
+{
+ const char *tracing;
+ int ret, c;
+ struct pevent *pevent = NULL;
+ struct plugin_list *list = NULL;
+
+ while ((c = getopt(argc-1, argv+1, "+hN")) >= 0) {
+ switch (c) {
+ case 'h':
+ default:
+ usage(argv);
+ break;
+ case 'N':
+ tracecmd_disable_plugins = 1;
+ break;
+ }
+ }
+ tracing = tracecmd_get_tracing_dir();
+
+ if (!tracing) {
+ printf("Can not find or mount tracing directory!\n"
+ "Either tracing is not configured for this "
+ "kernel\n"
+ "or you do not have the proper permissions to "
+ "mount the directory");
+ exit(EINVAL);
+ }
+
+ pevent = pevent_alloc();
+ if (!pevent)
+ exit(EINVAL);
+ list = tracecmd_load_plugins(pevent);
+ ret = tracecmd_fill_local_events(tracing, pevent);
+ if (ret || pevent->parsing_failures)
+ ret = EINVAL;
+ tracecmd_unload_plugins(list, pevent);
+ pevent_free(pevent);
+
+ return;
+}
diff --git a/trace-cmd.c b/trace-cmd.c
index 6a023e8..39bcc06 100644
--- a/trace-cmd.c
+++ b/trace-cmd.c
@@ -75,346 +75,9 @@ void *malloc_or_die(unsigned int size)
return data;
}
-static void dump_file_content(const char *path)
-{
- char buf[BUFSIZ];
- ssize_t n;
- FILE *fp;
-
- fp = fopen(path, "r");
- if (!fp)
- die("reading %s", path);
-
- do {
- n = fread(buf, 1, BUFSIZ, fp);
- if (n > 0)
- fwrite(buf, 1, n, stdout);
- } while (n > 0);
- fclose(fp);
-}
-
-void show_file(const char *name)
-{
- char *path;
-
- path = tracecmd_get_tracing_file(name);
- dump_file_content(path);
- tracecmd_put_tracing_file(path);
-}
-
-typedef int (*process_file_func)(char *buf, int len);
-
-static void process_file_re(process_file_func func,
- const char *name, const char *re)
-{
- regex_t reg;
- char *path;
- char *buf = NULL;
- char *str;
- FILE *fp;
- ssize_t n;
- size_t l = strlen(re);
-
- /* Just in case :-p */
- if (!re || l == 0) {
- show_file(name);
- return;
- }
-
- /* Handle the newline at end of names for the user */
- str = malloc(l + 3);
- if (!str)
- die("Failed to allocate reg ex %s", re);
- strcpy(str, re);
- if (re[l-1] == '$')
- strcpy(&str[l-1], "\n*$");
-
- if (regcomp(®, str, REG_ICASE|REG_NOSUB))
- die("invalid function regex '%s'", re);
-
- free(str);
-
- path = tracecmd_get_tracing_file(name);
- fp = fopen(path, "r");
- if (!fp)
- die("reading %s", path);
- tracecmd_put_tracing_file(path);
-
- do {
- n = getline(&buf, &l, fp);
- if (n > 0 && regexec(®, buf, 0, NULL, 0) == 0)
- func(buf, n);
- } while (n > 0);
- free(buf);
- fclose(fp);
-
- regfree(®);
-}
-
-static int show_file_write(char *buf, int len)
-{
- return fwrite(buf, 1, len, stdout);
-}
-
-static void show_file_re(const char *name, const char *re)
-{
- process_file_re(show_file_write, name, re);
-}
-
-static char *get_event_file(const char *type, char *buf, int len)
-{
- char *system;
- char *event;
- char *path;
- char *file;
-
- if (buf[len-1] == '\n')
- buf[len-1] = '\0';
-
- system = strtok(buf, ":");
- if (!system)
- die("no system found in %s", buf);
-
- event = strtok(NULL, ":");
- if (!event)
- die("no event found in %s\n", buf);
-
- path = tracecmd_get_tracing_file("events");
- file = malloc(strlen(path) + strlen(system) + strlen(event) +
- strlen(type) + strlen("///") + 1);
- if (!file)
- die("Failed to allocate event file %s %s", system, event);
- sprintf(file, "%s/%s/%s/%s", path, system, event, type);
- tracecmd_put_tracing_file(path);
-
- return file;
-}
-
-static int event_filter_write(char *buf, int len)
-{
- char *file;
-
- if (buf[len-1] == '\n')
- buf[len-1] = '\0';
-
- printf("%s\n", buf);
-
- file = get_event_file("filter", buf, len);
- dump_file_content(file);
- free(file);
- printf("\n");
-
- return 0;
-}
-
-static int event_trigger_write(char *buf, int len)
-{
- char *file;
-
- if (buf[len-1] == '\n')
- buf[len-1] = '\0';
-
- printf("%s\n", buf);
-
- file = get_event_file("trigger", buf, len);
- dump_file_content(file);
- free(file);
- printf("\n");
-
- return 0;
-}
-
-static int event_format_write(char *fbuf, int len)
-{
- char *file = get_event_file("format", fbuf, len);
- char *buf = NULL;
- size_t l;
- FILE *fp;
- int n;
-
- /* The get_event_file() crops system in fbuf */
- printf("system: %s\n", fbuf);
-
- /* Don't print the print fmt, it's ugly */
-
- fp = fopen(file, "r");
- if (!fp)
- die("reading %s", file);
-
- do {
- n = getline(&buf, &l, fp);
- if (n > 0) {
- if (strncmp(buf, "print fmt", 9) == 0)
- break;
- fwrite(buf, 1, n, stdout);
- }
- } while (n > 0);
- fclose(fp);
- free(buf);
- free(file);
-
- return 0;
-}
-
-static void show_event_filter_re(const char *re)
-{
- process_file_re(event_filter_write, "available_events", re);
-}
-
-static void show_event_trigger_re(const char *re)
-{
- process_file_re(event_trigger_write, "available_events", re);
-}
-
-static void show_event_format_re(const char *re)
-{
- process_file_re(event_format_write, "available_events", re);
-}
-
-void show_instance_file(struct buffer_instance *instance, const char *name)
-{
- char *path;
-
- path = get_instance_file(instance, name);
- dump_file_content(path);
- tracecmd_put_tracing_file(path);
-}
-
-enum {
- SHOW_EVENT_FORMAT = 1 << 0,
- SHOW_EVENT_FILTER = 1 << 1,
- SHOW_EVENT_TRIGGER = 1 << 2,
-};
-
-static void show_events(const char *eventre, int flags)
-{
- if (flags && !eventre)
- die("When specifying event files, an event must be named");
-
- if (eventre) {
- if (flags & SHOW_EVENT_FORMAT)
- show_event_format_re(eventre);
-
- else if (flags & SHOW_EVENT_FILTER)
- show_event_filter_re(eventre);
-
- else if (flags & SHOW_EVENT_TRIGGER)
- show_event_trigger_re(eventre);
- else
- show_file_re("available_events", eventre);
- } else
- show_file("available_events");
-}
-
-static void show_tracers(void)
-{
- show_file("available_tracers");
-}
-
-static void show_options(void)
-{
- show_file("trace_options");
-}
-
-static void show_clocks(void)
-{
- show_file("trace_clock");
-}
-
-static void show_functions(const char *funcre)
-{
- if (funcre)
- show_file_re("available_filter_functions", funcre);
- else
- show_file("available_filter_functions");
-}
-
-static void show_buffers(void)
-{
- struct dirent *dent;
- DIR *dir;
- char *path;
- int printed = 0;
-
- path = tracecmd_get_tracing_file("instances");
- dir = opendir(path);
- tracecmd_put_tracing_file(path);
- if (!dir)
- die("Can not read instance directory");
-
- while ((dent = readdir(dir))) {
- const char *name = dent->d_name;
-
- if (strcmp(name, ".") == 0 ||
- strcmp(name, "..") == 0)
- continue;
-
- printf("%s\n", name);
- printed = 1;
- }
- closedir(dir);
-
- if (!printed)
- printf("No buffer instances defined\n");
-}
-
-static void show_plugins(void)
-{
- struct pevent *pevent;
- struct plugin_list *list;
- struct trace_seq s;
-
- pevent = pevent_alloc();
- if (!pevent)
- die("Can not allocate pevent\n");
-
- trace_seq_init(&s);
-
- list = tracecmd_load_plugins(pevent);
- trace_util_print_plugins(&s, " ", "\n", list);
- trace_seq_do_printf(&s);
- tracecmd_unload_plugins(list, pevent);
- pevent_free(pevent);
-}
-
-static void show_plugin_options(void)
-{
- struct pevent *pevent;
- struct plugin_list *list;
- struct trace_seq s;
-
- tracecmd_ftrace_load_options();
-
- pevent = pevent_alloc();
- if (!pevent)
- die("Can not allocate pevent\n");
-
- trace_seq_init(&s);
-
- list = tracecmd_load_plugins(pevent);
- trace_util_print_plugin_options(&s);
- trace_seq_do_printf(&s);
- tracecmd_unload_plugins(list, pevent);
- pevent_free(pevent);
-}
-
-enum {
- OPT_tracing_on = 255,
- OPT_current_tracer = 254,
- OPT_buffer_size_kb = 253,
- OPT_buffer_total_size_kb = 252,
- OPT_ftrace_filter = 251,
- OPT_ftrace_notrace = 250,
- OPT_ftrace_pid = 249,
- OPT_graph_function = 248,
- OPT_graph_notrace = 247,
- OPT_cpumask = 246,
-};
int main (int argc, char **argv)
{
- int c;
-
errno = 0;
if (argc < 2)
@@ -445,44 +108,8 @@ int main (int argc, char **argv)
trace_stack(argc, argv);
exit(0);
} else if (strcmp(argv[1], "check-events") == 0) {
- const char *tracing;
- int ret;
- struct pevent *pevent = NULL;
- struct plugin_list *list = NULL;
-
- while ((c = getopt(argc-1, argv+1, "+hN")) >= 0) {
- switch (c) {
- case 'h':
- default:
- usage(argv);
- break;
- case 'N':
- tracecmd_disable_plugins = 1;
- break;
- }
- }
- tracing = tracecmd_get_tracing_dir();
-
- if (!tracing) {
- printf("Can not find or mount tracing directory!\n"
- "Either tracing is not configured for this "
- "kernel\n"
- "or you do not have the proper permissions to "
- "mount the directory");
- exit(EINVAL);
- }
-
- pevent = pevent_alloc();
- if (!pevent)
- exit(EINVAL);
- list = tracecmd_load_plugins(pevent);
- ret = tracecmd_fill_local_events(tracing, pevent);
- if (ret || pevent->parsing_failures)
- ret = EINVAL;
- tracecmd_unload_plugins(list, pevent);
- pevent_free(pevent);
- exit(ret);
-
+ trace_check_events(argc, argv);
+ exit(0);
} else if (strcmp(argv[1], "record") == 0 ||
strcmp(argv[1], "start") == 0 ||
strcmp(argv[1], "extract") == 0 ||
@@ -502,261 +129,11 @@ int main (int argc, char **argv)
show_plugin_options();
exit(0);
} else if (strcmp(argv[1], "show") == 0) {
- const char *buffer = NULL;
- const char *file = "trace";
- const char *cpu = NULL;
- struct buffer_instance *instance = &top_instance;
- char cpu_path[128];
- char *path;
- int snap = 0;
- int pipe = 0;
- int show_name = 0;
- int option_index = 0;
- int stop = 0;
- static struct option long_options[] = {
- {"tracing_on", no_argument, NULL, OPT_tracing_on},
- {"current_tracer", no_argument, NULL, OPT_current_tracer},
- {"buffer_size", no_argument, NULL, OPT_buffer_size_kb},
- {"buffer_total_size", no_argument, NULL, OPT_buffer_total_size_kb},
- {"ftrace_filter", no_argument, NULL, OPT_ftrace_filter},
- {"ftrace_notrace", no_argument, NULL, OPT_ftrace_notrace},
- {"ftrace_pid", no_argument, NULL, OPT_ftrace_pid},
- {"graph_function", no_argument, NULL, OPT_graph_function},
- {"graph_notrace", no_argument, NULL, OPT_graph_notrace},
- {"cpumask", no_argument, NULL, OPT_cpumask},
- {"help", no_argument, NULL, '?'},
- {NULL, 0, NULL, 0}
- };
-
- while ((c = getopt_long(argc-1, argv+1, "B:c:fsp",
- long_options, &option_index)) >= 0) {
- switch (c) {
- case 'h':
- usage(argv);
- break;
- case 'B':
- if (buffer)
- die("Can only show one buffer at a time");
- buffer = optarg;
- instance = create_instance(optarg);
- if (!instance)
- die("Failed to create instance");
- break;
- case 'c':
- if (cpu)
- die("Can only show one CPU at a time");
- cpu = optarg;
- break;
- case 'f':
- show_name = 1;
- break;
- case 's':
- snap = 1;
- if (pipe)
- die("Can not have -s and -p together");
- break;
- case 'p':
- pipe = 1;
- if (snap)
- die("Can not have -s and -p together");
- break;
- case OPT_tracing_on:
- show_instance_file(instance, "tracing_on");
- stop = 1;
- break;
- case OPT_current_tracer:
- show_instance_file(instance, "current_tracer");
- stop = 1;
- break;
- case OPT_buffer_size_kb:
- show_instance_file(instance, "buffer_size_kb");
- stop = 1;
- break;
- case OPT_buffer_total_size_kb:
- show_instance_file(instance, "buffer_total_size_kb");
- stop = 1;
- break;
- case OPT_ftrace_filter:
- show_instance_file(instance, "set_ftrace_filter");
- stop = 1;
- break;
- case OPT_ftrace_notrace:
- show_instance_file(instance, "set_ftrace_notrace");
- stop = 1;
- break;
- case OPT_ftrace_pid:
- show_instance_file(instance, "set_ftrace_pid");
- stop = 1;
- break;
- case OPT_graph_function:
- show_instance_file(instance, "set_graph_function");
- stop = 1;
- break;
- case OPT_graph_notrace:
- show_instance_file(instance, "set_graph_notrace");
- stop = 1;
- break;
- case OPT_cpumask:
- show_instance_file(instance, "tracing_cpumask");
- stop = 1;
- break;
- default:
- usage(argv);
- }
- }
- if (stop)
- exit(0);
- if (pipe)
- file = "trace_pipe";
- else if (snap)
- file = "snapshot";
-
- if (cpu) {
- snprintf(cpu_path, 128, "per_cpu/cpu%d/%s", atoi(cpu), file);
- file = cpu_path;
- }
-
- if (buffer) {
- path = malloc(strlen(buffer) + strlen("instances//") +
- strlen(file) + 1);
- if (!path)
- die("Failed to allocate instance path %s", file);
- sprintf(path, "instances/%s/%s", buffer, file);
- file = path;
- }
-
- if (show_name) {
- char *name;
- name = tracecmd_get_tracing_file(file);
- printf("%s\n", name);
- tracecmd_put_tracing_file(name);
- }
- show_file(file);
- if (buffer)
- free(path);
-
+ trace_show(argc, argv);
exit(0);
} else if (strcmp(argv[1], "list") == 0) {
- int events = 0;
- int tracer = 0;
- int options = 0;
- int funcs = 0;
- int buffers = 0;
- int clocks = 0;
- int plug = 0;
- int plug_op = 0;
- int flags = 0;
- int show_all = 1;
- int i;
- const char *arg;
- const char *funcre = NULL;
- const char *eventre = NULL;
-
- for (i = 2; i < argc; i++) {
- arg = NULL;
- if (argv[i][0] == '-') {
- if (i < argc - 1) {
- if (argv[i+1][0] != '-')
- arg = argv[i+1];
- }
- switch (argv[i][1]) {
- case 'h':
- usage(argv);
- break;
- case 'e':
- events = 1;
- eventre = arg;
- show_all = 0;
- break;
- case 'B':
- buffers = 1;
- show_all = 0;
- break;
- case 'C':
- clocks = 1;
- show_all = 0;
- break;
- case 'F':
- flags |= SHOW_EVENT_FORMAT;
- break;
- case 'R':
- flags |= SHOW_EVENT_TRIGGER;
- break;
- case 'l':
- flags |= SHOW_EVENT_FILTER;
- break;
- case 'p':
- case 't':
- tracer = 1;
- show_all = 0;
- break;
- case 'P':
- plug = 1;
- show_all = 0;
- break;
- case 'O':
- plug_op = 1;
- show_all = 0;
- break;
- case 'o':
- options = 1;
- show_all = 0;
- break;
- case 'f':
- funcs = 1;
- funcre = arg;
- show_all = 0;
- break;
- case '-':
- if (strcmp(argv[i], "--debug") == 0) {
- debug = true;
- break;
- }
- fprintf(stderr, "list: invalid option -- '%s'\n",
- argv[i]);
- default:
- fprintf(stderr, "list: invalid option -- '%c'\n",
- argv[i][1]);
- usage(argv);
- }
- }
- }
-
- if (events)
- show_events(eventre, flags);
-
- if (tracer)
- show_tracers();
-
- if (options)
- show_options();
-
- if (plug)
- show_plugins();
-
- if (plug_op)
- show_plugin_options();
-
- if (funcs)
- show_functions(funcre);
-
- if (buffers)
- show_buffers();
-
- if (clocks)
- show_clocks();
-
- if (show_all) {
- printf("events:\n");
- show_events(NULL, 0);
- printf("\ntracers:\n");
- show_tracers();
- printf("\noptions:\n");
- show_options();
- }
-
+ trace_list(argc, argv);
exit(0);
-
} else if (strcmp(argv[1], "-h") == 0 ||
strcmp(argv[1], "help") == 0) {
usage(argv);
diff --git a/trace-list.c b/trace-list.c
new file mode 100644
index 0000000..3fdca34
--- /dev/null
+++ b/trace-list.c
@@ -0,0 +1,486 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <[email protected]>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <stdlib.h>
+
+#include "trace-local.h"
+
+
+static void dump_file_content(const char *path)
+{
+ char buf[BUFSIZ];
+ ssize_t n;
+ FILE *fp;
+
+ fp = fopen(path, "r");
+ if (!fp)
+ die("reading %s", path);
+
+ do {
+ n = fread(buf, 1, BUFSIZ, fp);
+ if (n > 0)
+ fwrite(buf, 1, n, stdout);
+ } while (n > 0);
+ fclose(fp);
+}
+
+
+
+void show_instance_file(struct buffer_instance *instance, const char *name)
+{
+ char *path;
+
+ path = get_instance_file(instance, name);
+ dump_file_content(path);
+ tracecmd_put_tracing_file(path);
+}
+
+enum {
+ SHOW_EVENT_FORMAT = 1 << 0,
+ SHOW_EVENT_FILTER = 1 << 1,
+ SHOW_EVENT_TRIGGER = 1 << 2,
+};
+
+
+void show_file(const char *name)
+{
+ char *path;
+
+ path = tracecmd_get_tracing_file(name);
+ dump_file_content(path);
+ tracecmd_put_tracing_file(path);
+}
+
+typedef int (*process_file_func)(char *buf, int len);
+
+static void process_file_re(process_file_func func,
+ const char *name, const char *re)
+{
+ regex_t reg;
+ char *path;
+ char *buf = NULL;
+ char *str;
+ FILE *fp;
+ ssize_t n;
+ size_t l = strlen(re);
+
+ /* Just in case :-p */
+ if (!re || l == 0) {
+ show_file(name);
+ return;
+ }
+
+ /* Handle the newline at end of names for the user */
+ str = malloc(l + 3);
+ if (!str)
+ die("Failed to allocate reg ex %s", re);
+ strcpy(str, re);
+ if (re[l-1] == '$')
+ strcpy(&str[l-1], "\n*$");
+
+ if (regcomp(®, str, REG_ICASE|REG_NOSUB))
+ die("invalid function regex '%s'", re);
+
+ free(str);
+
+ path = tracecmd_get_tracing_file(name);
+ fp = fopen(path, "r");
+ if (!fp)
+ die("reading %s", path);
+ tracecmd_put_tracing_file(path);
+
+ do {
+ n = getline(&buf, &l, fp);
+ if (n > 0 && regexec(®, buf, 0, NULL, 0) == 0)
+ func(buf, n);
+ } while (n > 0);
+ free(buf);
+ fclose(fp);
+
+ regfree(®);
+}
+
+static int show_file_write(char *buf, int len)
+{
+ return fwrite(buf, 1, len, stdout);
+}
+
+static void show_file_re(const char *name, const char *re)
+{
+ process_file_re(show_file_write, name, re);
+}
+
+static char *get_event_file(const char *type, char *buf, int len)
+{
+ char *system;
+ char *event;
+ char *path;
+ char *file;
+
+ if (buf[len-1] == '\n')
+ buf[len-1] = '\0';
+
+ system = strtok(buf, ":");
+ if (!system)
+ die("no system found in %s", buf);
+
+ event = strtok(NULL, ":");
+ if (!event)
+ die("no event found in %s\n", buf);
+
+ path = tracecmd_get_tracing_file("events");
+ file = malloc(strlen(path) + strlen(system) + strlen(event) +
+ strlen(type) + strlen("///") + 1);
+ if (!file)
+ die("Failed to allocate event file %s %s", system, event);
+ sprintf(file, "%s/%s/%s/%s", path, system, event, type);
+ tracecmd_put_tracing_file(path);
+
+ return file;
+}
+
+static int event_filter_write(char *buf, int len)
+{
+ char *file;
+
+ if (buf[len-1] == '\n')
+ buf[len-1] = '\0';
+
+ printf("%s\n", buf);
+
+ file = get_event_file("filter", buf, len);
+ dump_file_content(file);
+ free(file);
+ printf("\n");
+
+ return 0;
+}
+
+static int event_trigger_write(char *buf, int len)
+{
+ char *file;
+
+ if (buf[len-1] == '\n')
+ buf[len-1] = '\0';
+
+ printf("%s\n", buf);
+
+ file = get_event_file("trigger", buf, len);
+ dump_file_content(file);
+ free(file);
+ printf("\n");
+
+ return 0;
+}
+
+static int event_format_write(char *fbuf, int len)
+{
+ char *file = get_event_file("format", fbuf, len);
+ char *buf = NULL;
+ size_t l;
+ FILE *fp;
+ int n;
+
+ /* The get_event_file() crops system in fbuf */
+ printf("system: %s\n", fbuf);
+
+ /* Don't print the print fmt, it's ugly */
+
+ fp = fopen(file, "r");
+ if (!fp)
+ die("reading %s", file);
+
+ do {
+ n = getline(&buf, &l, fp);
+ if (n > 0) {
+ if (strncmp(buf, "print fmt", 9) == 0)
+ break;
+ fwrite(buf, 1, n, stdout);
+ }
+ } while (n > 0);
+ fclose(fp);
+ free(buf);
+ free(file);
+
+ return 0;
+}
+
+
+static void show_event_filter_re(const char *re)
+{
+ process_file_re(event_filter_write, "available_events", re);
+}
+
+
+static void show_event_trigger_re(const char *re)
+{
+ process_file_re(event_trigger_write, "available_events", re);
+}
+
+
+static void show_event_format_re(const char *re)
+{
+ process_file_re(event_format_write, "available_events", re);
+}
+
+
+static void show_events(const char *eventre, int flags)
+{
+ if (flags && !eventre)
+ die("When specifying event files, an event must be named");
+
+ if (eventre) {
+ if (flags & SHOW_EVENT_FORMAT)
+ show_event_format_re(eventre);
+
+ else if (flags & SHOW_EVENT_FILTER)
+ show_event_filter_re(eventre);
+
+ else if (flags & SHOW_EVENT_TRIGGER)
+ show_event_trigger_re(eventre);
+ else
+ show_file_re("available_events", eventre);
+ } else
+ show_file("available_events");
+}
+
+
+static void show_tracers(void)
+{
+ show_file("available_tracers");
+}
+
+
+static void show_options(void)
+{
+ show_file("trace_options");
+}
+
+
+static void show_clocks(void)
+{
+ show_file("trace_clock");
+}
+
+
+static void show_functions(const char *funcre)
+{
+ if (funcre)
+ show_file_re("available_filter_functions", funcre);
+ else
+ show_file("available_filter_functions");
+}
+
+
+static void show_buffers(void)
+{
+ struct dirent *dent;
+ DIR *dir;
+ char *path;
+ int printed = 0;
+
+ path = tracecmd_get_tracing_file("instances");
+ dir = opendir(path);
+ tracecmd_put_tracing_file(path);
+ if (!dir)
+ die("Can not read instance directory");
+
+ while ((dent = readdir(dir))) {
+ const char *name = dent->d_name;
+
+ if (strcmp(name, ".") == 0 ||
+ strcmp(name, "..") == 0)
+ continue;
+
+ printf("%s\n", name);
+ printed = 1;
+ }
+ closedir(dir);
+
+ if (!printed)
+ printf("No buffer instances defined\n");
+}
+
+
+void show_plugin_options(void)
+{
+ struct pevent *pevent;
+ struct plugin_list *list;
+ struct trace_seq s;
+
+ tracecmd_ftrace_load_options();
+
+ pevent = pevent_alloc();
+ if (!pevent)
+ die("Can not allocate pevent\n");
+
+ trace_seq_init(&s);
+
+ list = tracecmd_load_plugins(pevent);
+ trace_util_print_plugin_options(&s);
+ trace_seq_do_printf(&s);
+ tracecmd_unload_plugins(list, pevent);
+ pevent_free(pevent);
+}
+
+
+static void show_plugins(void)
+{
+ struct pevent *pevent;
+ struct plugin_list *list;
+ struct trace_seq s;
+
+ pevent = pevent_alloc();
+ if (!pevent)
+ die("Can not allocate pevent\n");
+
+ trace_seq_init(&s);
+
+ list = tracecmd_load_plugins(pevent);
+ trace_util_print_plugins(&s, " ", "\n", list);
+ trace_seq_do_printf(&s);
+ tracecmd_unload_plugins(list, pevent);
+ pevent_free(pevent);
+}
+
+
+void trace_list(int argc, char **argv)
+{
+ int events = 0;
+ int tracer = 0;
+ int options = 0;
+ int funcs = 0;
+ int buffers = 0;
+ int clocks = 0;
+ int plug = 0;
+ int plug_op = 0;
+ int flags = 0;
+ int show_all = 1;
+ int i;
+ const char *arg;
+ const char *funcre = NULL;
+ const char *eventre = NULL;
+
+ for (i = 2; i < argc; i++) {
+ arg = NULL;
+ if (argv[i][0] == '-') {
+ if (i < argc - 1) {
+ if (argv[i+1][0] != '-')
+ arg = argv[i+1];
+ }
+ switch (argv[i][1]) {
+ case 'h':
+ usage(argv);
+ break;
+ case 'e':
+ events = 1;
+ eventre = arg;
+ show_all = 0;
+ break;
+ case 'B':
+ buffers = 1;
+ show_all = 0;
+ break;
+ case 'C':
+ clocks = 1;
+ show_all = 0;
+ break;
+ case 'F':
+ flags |= SHOW_EVENT_FORMAT;
+ break;
+ case 'R':
+ flags |= SHOW_EVENT_TRIGGER;
+ break;
+ case 'l':
+ flags |= SHOW_EVENT_FILTER;
+ break;
+ case 'p':
+ case 't':
+ tracer = 1;
+ show_all = 0;
+ break;
+ case 'P':
+ plug = 1;
+ show_all = 0;
+ break;
+ case 'O':
+ plug_op = 1;
+ show_all = 0;
+ break;
+ case 'o':
+ options = 1;
+ show_all = 0;
+ break;
+ case 'f':
+ funcs = 1;
+ funcre = arg;
+ show_all = 0;
+ break;
+ case '-':
+ if (strcmp(argv[i], "--debug") == 0) {
+ debug = true;
+ break;
+ }
+ fprintf(stderr, "list: invalid option -- '%s'\n",
+ argv[i]);
+ default:
+ fprintf(stderr, "list: invalid option -- '%c'\n",
+ argv[i][1]);
+ usage(argv);
+ }
+ }
+ }
+
+ if (events)
+ show_events(eventre, flags);
+
+ if (tracer)
+ show_tracers();
+
+ if (options)
+ show_options();
+
+ if (plug)
+ show_plugins();
+
+ if (plug_op)
+ show_plugin_options();
+
+ if (funcs)
+ show_functions(funcre);
+
+ if (buffers)
+ show_buffers();
+
+ if (clocks)
+ show_clocks();
+
+ if (show_all) {
+ printf("events:\n");
+ show_events(NULL, 0);
+ printf("\ntracers:\n");
+ show_tracers();
+ printf("\noptions:\n");
+ show_options();
+ }
+
+ return;
+
+}
diff --git a/trace-local.h b/trace-local.h
index 46aa979..ee518fb 100644
--- a/trace-local.h
+++ b/trace-local.h
@@ -65,6 +65,8 @@ void trace_listen(int argc, char **argv);
void trace_restore(int argc, char **argv);
+void trace_check_events(int argc, char **argv);
+
void trace_stack(int argc, char **argv);
void trace_option(int argc, char **argv);
@@ -77,6 +79,10 @@ void trace_mem(int argc, char **argv);
void trace_stat(int argc, char **argv);
+void trace_show(int argc, char **argv);
+
+void trace_list(int argc, char **argv);
+
struct hook_list;
void trace_init_profile(struct tracecmd_input *handle, struct hook_list *hooks,
@@ -183,6 +189,7 @@ char *get_instance_file(struct buffer_instance *instance, const char *file);
void update_first_instance(struct buffer_instance *instance, int topt);
void show_instance_file(struct buffer_instance *instance, const char *name);
+void show_plugin_options(void);
int count_cpus(void);
/* No longer in event-utils.h */
diff --git a/trace-show.c b/trace-show.c
new file mode 100644
index 0000000..14b786c
--- /dev/null
+++ b/trace-show.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <[email protected]>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdlib.h>
+#include <getopt.h>
+#include <errno.h>
+
+#include "trace-local.h"
+
+enum {
+ OPT_tracing_on = 255,
+ OPT_current_tracer = 254,
+ OPT_buffer_size_kb = 253,
+ OPT_buffer_total_size_kb = 252,
+ OPT_ftrace_filter = 251,
+ OPT_ftrace_notrace = 250,
+ OPT_ftrace_pid = 249,
+ OPT_graph_function = 248,
+ OPT_graph_notrace = 247,
+ OPT_cpumask = 246,
+};
+
+void trace_show(int argc, char **argv)
+{
+ const char *buffer = NULL;
+ const char *file = "trace";
+ const char *cpu = NULL;
+ struct buffer_instance *instance = &top_instance;
+ char cpu_path[128];
+ char *path;
+ int snap = 0;
+ int pipe = 0;
+ int show_name = 0;
+ int option_index = 0;
+ int stop = 0;
+ int c;
+ static struct option long_options[] = {
+ {"tracing_on", no_argument, NULL, OPT_tracing_on},
+ {"current_tracer", no_argument, NULL, OPT_current_tracer},
+ {"buffer_size", no_argument, NULL, OPT_buffer_size_kb},
+ {"buffer_total_size", no_argument, NULL, OPT_buffer_total_size_kb},
+ {"ftrace_filter", no_argument, NULL, OPT_ftrace_filter},
+ {"ftrace_notrace", no_argument, NULL, OPT_ftrace_notrace},
+ {"ftrace_pid", no_argument, NULL, OPT_ftrace_pid},
+ {"graph_function", no_argument, NULL, OPT_graph_function},
+ {"graph_notrace", no_argument, NULL, OPT_graph_notrace},
+ {"cpumask", no_argument, NULL, OPT_cpumask},
+ {"help", no_argument, NULL, '?'},
+ {NULL, 0, NULL, 0}
+ };
+
+ while ((c = getopt_long(argc-1, argv+1, "B:c:fsp",
+ long_options, &option_index)) >= 0) {
+ switch (c) {
+ case 'h':
+ usage(argv);
+ break;
+ case 'B':
+ if (buffer)
+ die("Can only show one buffer at a time");
+ buffer = optarg;
+ instance = create_instance(optarg);
+ if (!instance)
+ die("Failed to create instance");
+ break;
+ case 'c':
+ if (cpu)
+ die("Can only show one CPU at a time");
+ cpu = optarg;
+ break;
+ case 'f':
+ show_name = 1;
+ break;
+ case 's':
+ snap = 1;
+ if (pipe)
+ die("Can not have -s and -p together");
+ break;
+ case 'p':
+ pipe = 1;
+ if (snap)
+ die("Can not have -s and -p together");
+ break;
+ case OPT_tracing_on:
+ show_instance_file(instance, "tracing_on");
+ stop = 1;
+ break;
+ case OPT_current_tracer:
+ show_instance_file(instance, "current_tracer");
+ stop = 1;
+ break;
+ case OPT_buffer_size_kb:
+ show_instance_file(instance, "buffer_size_kb");
+ stop = 1;
+ break;
+ case OPT_buffer_total_size_kb:
+ show_instance_file(instance, "buffer_total_size_kb");
+ stop = 1;
+ break;
+ case OPT_ftrace_filter:
+ show_instance_file(instance, "set_ftrace_filter");
+ stop = 1;
+ break;
+ case OPT_ftrace_notrace:
+ show_instance_file(instance, "set_ftrace_notrace");
+ stop = 1;
+ break;
+ case OPT_ftrace_pid:
+ show_instance_file(instance, "set_ftrace_pid");
+ stop = 1;
+ break;
+ case OPT_graph_function:
+ show_instance_file(instance, "set_graph_function");
+ stop = 1;
+ break;
+ case OPT_graph_notrace:
+ show_instance_file(instance, "set_graph_notrace");
+ stop = 1;
+ break;
+ case OPT_cpumask:
+ show_instance_file(instance, "tracing_cpumask");
+ stop = 1;
+ break;
+ default:
+ usage(argv);
+ }
+ }
+ if (stop)
+ exit(0);
+ if (pipe)
+ file = "trace_pipe";
+ else if (snap)
+ file = "snapshot";
+
+ if (cpu) {
+ snprintf(cpu_path, 128, "per_cpu/cpu%d/%s", atoi(cpu), file);
+ file = cpu_path;
+ }
+
+ if (buffer) {
+ path = malloc(strlen(buffer) + strlen("instances//") +
+ strlen(file) + 1);
+ if (!path)
+ die("Failed to allocate instance path %s", file);
+ sprintf(path, "instances/%s/%s", buffer, file);
+ file = path;
+ }
+
+ if (show_name) {
+ char *name;
+ name = tracecmd_get_tracing_file(file);
+ printf("%s\n", name);
+ tracecmd_put_tracing_file(name);
+ }
+ show_file(file);
+ if (buffer)
+ free(path);
+
+ return;
+}
--
2.9.3
Since now there is an uniform command implementation I can reduce the
`main()` function to the minimum by using a lookup table. People can
now directly focus on a command implementation because there is
"nothing" in the `main()` function.
Signed-off-by: Federico Vaga <[email protected]>
---
trace-cmd.c | 116 ++++++++++++++++++++++++++++------------------------------
trace-list.c | 8 +++-
trace-local.h | 4 +-
trace-usage.c | 6 +++
4 files changed, 71 insertions(+), 63 deletions(-)
diff --git a/trace-cmd.c b/trace-cmd.c
index 39bcc06..0f71e12 100644
--- a/trace-cmd.c
+++ b/trace-cmd.c
@@ -76,72 +76,66 @@ void *malloc_or_die(unsigned int size)
}
+/**
+ * struct command
+ * @name command name
+ * @run function to execute on command `name`
+ */
+struct command {
+ char *name;
+ void (*run)(int argc, char **argv);
+};
+
+
+/**
+ * Lookup table that maps command names to functions
+ */
+struct command commands[] = {
+ {"report", trace_report},
+ {"snapshot", trace_snapshot},
+ {"hist", trace_hist},
+ {"mem", trace_mem},
+ {"listen", trace_listen},
+ {"split", trace_split},
+ {"restore", trace_restore},
+ {"stack", trace_stack},
+ {"check-events", trace_check_events},
+ {"record", trace_record},
+ {"start", trace_record},
+ {"extract", trace_record},
+ {"stop", trace_record},
+ {"stream", trace_record},
+ {"profile", trace_record},
+ {"restart", trace_record},
+ {"reset", trace_record},
+ {"stat", trace_stat},
+ {"options", trace_option},
+ {"show", trace_show},
+ {"list", trace_list},
+ {"help", trace_usage},
+ {"-h", trace_usage},
+};
+
+#define ARRAY_SIZE(_a) (sizeof(_a) / sizeof(_a[0]))
+
int main (int argc, char **argv)
{
+ int i;
+
errno = 0;
if (argc < 2)
- usage(argv);
-
- if (strcmp(argv[1], "report") == 0) {
- trace_report(argc, argv);
- exit(0);
- } else if (strcmp(argv[1], "snapshot") == 0) {
- trace_snapshot(argc, argv);
- exit(0);
- } else if (strcmp(argv[1], "hist") == 0) {
- trace_hist(argc, argv);
- exit(0);
- } else if (strcmp(argv[1], "mem") == 0) {
- trace_mem(argc, argv);
- exit(0);
- } else if (strcmp(argv[1], "listen") == 0) {
- trace_listen(argc, argv);
- exit(0);
- } else if (strcmp(argv[1], "split") == 0) {
- trace_split(argc, argv);
- exit(0);
- } else if (strcmp(argv[1], "restore") == 0) {
- trace_restore(argc, argv);
- exit(0);
- } else if (strcmp(argv[1], "stack") == 0) {
- trace_stack(argc, argv);
- exit(0);
- } else if (strcmp(argv[1], "check-events") == 0) {
- trace_check_events(argc, argv);
- exit(0);
- } else if (strcmp(argv[1], "record") == 0 ||
- strcmp(argv[1], "start") == 0 ||
- strcmp(argv[1], "extract") == 0 ||
- strcmp(argv[1], "stop") == 0 ||
- strcmp(argv[1], "stream") == 0 ||
- strcmp(argv[1], "profile") == 0 ||
- strcmp(argv[1], "restart") == 0 ||
- strcmp(argv[1], "reset") == 0) {
- trace_record(argc, argv);
- exit(0);
-
- } else if (strcmp(argv[1], "stat") == 0) {
- trace_stat(argc, argv);
- exit(0);
-
- } else if (strcmp(argv[1], "options") == 0) {
- show_plugin_options();
- exit(0);
- } else if (strcmp(argv[1], "show") == 0) {
- trace_show(argc, argv);
- exit(0);
- } else if (strcmp(argv[1], "list") == 0) {
- trace_list(argc, argv);
- exit(0);
- } else if (strcmp(argv[1], "-h") == 0 ||
- strcmp(argv[1], "help") == 0) {
- usage(argv);
- } else {
- fprintf(stderr, "unknown command: %s\n", argv[1]);
- usage(argv);
+ trace_usage(argc, argv);
+
+ for (i = 0; i < ARRAY_SIZE(commands); ++i) {
+ if (strcmp(argv[1], commands[i].name) == 0 ){
+ commands[i].run(argc, argv);
+ goto out;
+ }
}
- return 0;
+ /* No valid command found, show help */
+ trace_usage(argc, argv);
+out:
+ exit(0);
}
-
diff --git a/trace-list.c b/trace-list.c
index 3fdca34..293635f 100644
--- a/trace-list.c
+++ b/trace-list.c
@@ -319,7 +319,7 @@ static void show_buffers(void)
}
-void show_plugin_options(void)
+static void show_plugin_options(void)
{
struct pevent *pevent;
struct plugin_list *list;
@@ -341,6 +341,12 @@ void show_plugin_options(void)
}
+void trace_option(int argc, char **argv)
+{
+ show_plugin_options();
+}
+
+
static void show_plugins(void)
{
struct pevent *pevent;
diff --git a/trace-local.h b/trace-local.h
index ee518fb..fa987bc 100644
--- a/trace-local.h
+++ b/trace-local.h
@@ -83,6 +83,8 @@ void trace_show(int argc, char **argv);
void trace_list(int argc, char **argv);
+void trace_usage(int argc, char **argv);
+
struct hook_list;
void trace_init_profile(struct tracecmd_input *handle, struct hook_list *hooks,
@@ -189,7 +191,7 @@ char *get_instance_file(struct buffer_instance *instance, const char *file);
void update_first_instance(struct buffer_instance *instance, int topt);
void show_instance_file(struct buffer_instance *instance, const char *name);
-void show_plugin_options(void);
+
int count_cpus(void);
/* No longer in event-utils.h */
diff --git a/trace-usage.c b/trace-usage.c
index 5c1a692..9664aa6 100644
--- a/trace-usage.c
+++ b/trace-usage.c
@@ -327,3 +327,9 @@ void usage(char **argv)
printf("\n");
exit(-1);
}
+
+
+void trace_usage(int argc, char **argv)
+{
+ usage(argv);
+}
--
2.9.3