diff options
author | Lluís Vilanova <vilanova@ac.upc.edu> | 2013-03-05 14:47:38 +0100 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2013-03-28 14:19:57 +0100 |
commit | b1bae816c4c0743e37ee9e797a503610c34e3073 (patch) | |
tree | 4b10c9a3a0bfa301d8ecd728db20e61867eeb4ac /trace/control.c | |
parent | 45be2f5d0dcdd314cd0c70a11220e5e09a44d654 (diff) |
trace: Provide a detailed event control interface
This interface decouples event obtaining from interaction.
Events can be obtained through three different methods:
* identifier
* name
* simple wildcard pattern
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'trace/control.c')
-rw-r--r-- | trace/control.c | 106 |
1 files changed, 93 insertions, 13 deletions
diff --git a/trace/control.c b/trace/control.c index be05efb99b..49f61e137b 100644 --- a/trace/control.c +++ b/trace/control.c @@ -1,19 +1,86 @@ /* * Interface for configuring and controlling the state of tracing events. * - * Copyright (C) 2011 Lluís Vilanova <vilanova@ac.upc.edu> + * Copyright (C) 2011-2012 Lluís Vilanova <vilanova@ac.upc.edu> * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. */ #include "trace/control.h" -void trace_backend_init_events(const char *fname) +TraceEvent *trace_event_name(const char *name) +{ + assert(name != NULL); + + TraceEventID i; + for (i = 0; i < trace_event_count(); i++) { + TraceEvent *ev = trace_event_id(i); + if (strcmp(trace_event_get_name(ev), name) == 0) { + return ev; + } + } + return NULL; +} + +static bool pattern_glob(const char *pat, const char *ev) +{ + while (*pat != '\0' && *ev != '\0') { + if (*pat == *ev) { + pat++; + ev++; + } + else if (*pat == '*') { + if (pattern_glob(pat, ev+1)) { + return true; + } else if (pattern_glob(pat+1, ev)) { + return true; + } else { + return false; + } + } else { + return false; + } + } + + while (*pat == '*') { + pat++; + } + + if (*pat == '\0' && *ev == '\0') { + return true; + } else { + return false; + } +} + +TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev) { - int ret; + assert(pat != NULL); + TraceEventID i; + + if (ev == NULL) { + i = -1; + } else { + i = trace_event_get_id(ev); + } + i++; + + while (i < trace_event_count()) { + TraceEvent *res = trace_event_id(i); + if (pattern_glob(pat, trace_event_get_name(res))) { + return res; + } + i++; + } + + return NULL; +} + +void trace_backend_init_events(const char *fname) +{ if (fname == NULL) { return; } @@ -32,15 +99,28 @@ void trace_backend_init_events(const char *fname) if ('#' == line_buf[0]) { /* skip commented lines */ continue; } - if ('-' == line_buf[0]) { - ret = trace_event_set_state(line_buf+1, false); + const bool enable = ('-' != line_buf[0]); + char *line_ptr = enable ? line_buf : line_buf + 1; + if (trace_event_is_pattern(line_ptr)) { + TraceEvent *ev = NULL; + while ((ev = trace_event_pattern(line_ptr, ev)) != NULL) { + if (trace_event_get_state_static(ev)) { + trace_event_set_state_dynamic(ev, enable); + } + } } else { - ret = trace_event_set_state(line_buf, true); - } - if (!ret) { - fprintf(stderr, - "error: trace event '%s' does not exist\n", line_buf); - exit(1); + TraceEvent *ev = trace_event_name(line_ptr); + if (ev == NULL) { + fprintf(stderr, + "error: trace event '%s' does not exist\n", line_ptr); + exit(1); + } + if (!trace_event_get_state_static(ev)) { + fprintf(stderr, + "error: trace event '%s' is not traceable\n", line_ptr); + exit(1); + } + trace_event_set_state_dynamic(ev, enable); } } } |