* [PATCHSET 0/5] perf tools: Add support log window on TUI (v4)
@ 2014-01-13 8:00 Namhyung Kim
2014-01-13 8:00 ` [PATCH 1/5] perf tools: Introduce struct perf_log Namhyung Kim
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Namhyung Kim @ 2014-01-13 8:00 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
Jiri Olsa, David Ahern
Hello,
This is a new attempt to add a log window support on TUI browser. The
header window support was already merged to acme/perf/core.
* changes in v3)
- use tmpfile(3) instead of mkstemp (David)
- check NULL fp before use (David)
- rename functions to follow the 'class__method' convention (Arnaldo)
- restore original position when write failed (David)
You can get it from the 'perf/tui-v4' branch in my tree:
git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git
Any comments are welcome, thanks
Namhyung
Namhyung Kim (5):
perf tools: Introduce struct perf_log
perf tools: Save message when pr_*() was called
perf ui/tui: Implement log window
perf ui/tui: Filter messages in log window
perf ui/tui: Remember last log line for filtering
tools/perf/Makefile.perf | 2 +
tools/perf/perf.c | 5 +
tools/perf/ui/browser.h | 1 +
tools/perf/ui/browsers/hists.c | 5 +
tools/perf/ui/browsers/log.c | 235 +++++++++++++++++++++++++++++++++++++++++
tools/perf/util/debug.c | 6 ++
tools/perf/util/debug.h | 16 +++
tools/perf/util/log.c | 117 ++++++++++++++++++++
8 files changed, 387 insertions(+)
create mode 100644 tools/perf/ui/browsers/log.c
create mode 100644 tools/perf/util/log.c
--
1.7.11.7
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/5] perf tools: Introduce struct perf_log
2014-01-13 8:00 [PATCHSET 0/5] perf tools: Add support log window on TUI (v4) Namhyung Kim
@ 2014-01-13 8:00 ` Namhyung Kim
2014-01-13 8:00 ` [PATCH 2/5] perf tools: Save message when pr_*() was called Namhyung Kim
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Namhyung Kim @ 2014-01-13 8:00 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
Jiri Olsa, David Ahern
Add new functions to save error messages in a temp file. It'll be
used by some UI front-ends to see the messages.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/Makefile.perf | 1 +
tools/perf/perf.c | 5 +++
tools/perf/util/debug.h | 15 +++++++
tools/perf/util/log.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 136 insertions(+)
create mode 100644 tools/perf/util/log.c
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 87d7726cee2d..2b5252f09c04 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -372,6 +372,7 @@ LIB_OBJS += $(OUTPUT)util/stat.o
LIB_OBJS += $(OUTPUT)util/record.o
LIB_OBJS += $(OUTPUT)util/srcline.o
LIB_OBJS += $(OUTPUT)util/data.o
+LIB_OBJS += $(OUTPUT)util/log.o
LIB_OBJS += $(OUTPUT)ui/setup.o
LIB_OBJS += $(OUTPUT)ui/helpline.o
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 431798a4110d..f7c806d264a2 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -10,6 +10,7 @@
#include "util/exec_cmd.h"
#include "util/cache.h"
+#include "util/debug.h"
#include "util/quote.h"
#include "util/run-command.h"
#include "util/parse-events.h"
@@ -524,6 +525,9 @@ int main(int argc, const char **argv)
*/
pthread__block_sigwinch();
+ if (perf_log__init() < 0)
+ fprintf(stderr, "Failed to init temporary log file.. ignoring\n");
+
while (1) {
static int done_help;
int was_alias = run_argv(&argc, &argv);
@@ -547,5 +551,6 @@ int main(int argc, const char **argv)
fprintf(stderr, "Failed to run command '%s': %s\n",
cmd, strerror(errno));
out:
+ perf_log__exit();
return 1;
}
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 443694c36b03..2d69e9fa6499 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -19,4 +19,19 @@ int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
void pr_stat(const char *fmt, ...);
+struct perf_log {
+ FILE *fp;
+ off_t *linemap;
+ u32 lines;
+ u32 nr_alloc;
+ bool seen_newline;
+};
+
+extern struct perf_log perf_log;
+
+int perf_log__init(void);
+int perf_log__exit(void);
+void perf_log__add(const char *msg);
+void perf_log__addv(const char *fmt, va_list ap);
+
#endif /* __PERF_DEBUG_H */
diff --git a/tools/perf/util/log.c b/tools/perf/util/log.c
new file mode 100644
index 000000000000..cb94417da435
--- /dev/null
+++ b/tools/perf/util/log.c
@@ -0,0 +1,115 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "util/debug.h"
+
+#define LINEMAP_GROW 128
+
+struct perf_log perf_log = {
+ .seen_newline = true,
+};
+
+int perf_log__init(void)
+{
+ FILE *fp = tmpfile();
+ if (fp == NULL)
+ return -1;
+
+ perf_log.fp = fp;
+
+ return 0;
+}
+
+int perf_log__exit(void)
+{
+ FILE *fp = perf_log.fp;
+ if (fp)
+ fclose(fp);
+
+ free(perf_log.linemap);
+
+ perf_log.fp = NULL;
+ perf_log.linemap = NULL;
+ return 0;
+}
+
+static int grow_linemap(struct perf_log *log)
+{
+ off_t *newmap;
+ int newsize = log->nr_alloc + LINEMAP_GROW;
+
+ newmap = realloc(log->linemap, newsize * sizeof(*log->linemap));
+ if (newmap == NULL)
+ return -1;
+
+ log->nr_alloc = newsize;
+ log->linemap = newmap;
+ return 0;
+}
+
+static int __add_to_linemap(struct perf_log *log, off_t idx)
+{
+ if (log->lines == log->nr_alloc)
+ if (grow_linemap(log) < 0)
+ return -1;
+
+ log->linemap[log->lines++] = idx;
+ return 0;
+}
+
+static void add_to_linemap(struct perf_log *log, const char *msg, off_t base)
+{
+ const char *pos;
+
+ if (strlen(msg) == 0)
+ return;
+
+ if (log->seen_newline) {
+ if (__add_to_linemap(log, base) < 0)
+ return;
+ }
+
+ if ((pos = strchr(msg, '\n')) != NULL) {
+ log->seen_newline = true;
+ pos++;
+ add_to_linemap(log, pos, base + (pos - msg));
+ } else {
+ log->seen_newline = false;
+ }
+}
+
+void perf_log__add(const char *msg)
+{
+ FILE *fp = perf_log.fp;
+ off_t offset;
+ u32 saved_lines;
+ size_t msglen;
+
+ if (fp == NULL)
+ return;
+
+ pthread_mutex_lock(&ui__lock);
+
+ offset = ftello(fp);
+ saved_lines = perf_log.lines;
+ msglen = strlen(msg);
+
+ add_to_linemap(&perf_log, msg, offset);
+
+ if (fwrite(msg, 1, msglen, fp) != msglen) {
+ /* restore original offset */
+ fseeko(fp, offset, SEEK_SET);
+ perf_log.lines = saved_lines;
+ }
+ pthread_mutex_unlock(&ui__lock);
+}
+
+void perf_log__addv(const char *fmt, va_list ap)
+{
+ char buf[4096];
+
+ if (perf_log.fp == NULL)
+ return;
+
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ perf_log__add(buf);
+}
--
1.7.11.7
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/5] perf tools: Save message when pr_*() was called
2014-01-13 8:00 [PATCHSET 0/5] perf tools: Add support log window on TUI (v4) Namhyung Kim
2014-01-13 8:00 ` [PATCH 1/5] perf tools: Introduce struct perf_log Namhyung Kim
@ 2014-01-13 8:00 ` Namhyung Kim
2014-01-13 8:00 ` [PATCH 3/5] perf ui/tui: Implement log window Namhyung Kim
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Namhyung Kim @ 2014-01-13 8:00 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
Jiri Olsa, David Ahern
The message will be saved in a temp file so that it can be shown at a
UI dialog at any time.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/util/debug.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 299b55586502..801cdf205d3e 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -19,12 +19,18 @@ bool dump_trace = false, quiet = false;
static int _eprintf(int level, const char *fmt, va_list args)
{
int ret = 0;
+ va_list ap;
if (verbose >= level) {
+ va_copy(ap, args);
+
if (use_browser >= 1)
ui_helpline__vshow(fmt, args);
else
ret = vfprintf(stderr, fmt, args);
+
+ perf_log__addv(fmt, ap);
+ va_end(ap);
}
return ret;
--
1.7.11.7
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 3/5] perf ui/tui: Implement log window
2014-01-13 8:00 [PATCHSET 0/5] perf tools: Add support log window on TUI (v4) Namhyung Kim
2014-01-13 8:00 ` [PATCH 1/5] perf tools: Introduce struct perf_log Namhyung Kim
2014-01-13 8:00 ` [PATCH 2/5] perf tools: Save message when pr_*() was called Namhyung Kim
@ 2014-01-13 8:00 ` Namhyung Kim
2014-01-13 8:00 ` [PATCH 4/5] perf ui/tui: Filter messages in " Namhyung Kim
2014-01-13 8:00 ` [PATCH 5/5] perf ui/tui: Remember last log line for filtering Namhyung Kim
4 siblings, 0 replies; 6+ messages in thread
From: Namhyung Kim @ 2014-01-13 8:00 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
Jiri Olsa, David Ahern
Implement a simple, full-screen log window which shows error messages
saved so far. Press 'l' (lower-case 'L') key to display the log
window. It'll be used usually with -v option.
Protect updating log by ui__lock to prevent the linemap reallocation
during log window refresh (it led to a segfault) and add
linemap_changed member to perf_log in order to detect the change.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/Makefile.perf | 1 +
tools/perf/ui/browser.h | 1 +
tools/perf/ui/browsers/hists.c | 5 ++
tools/perf/ui/browsers/log.c | 132 +++++++++++++++++++++++++++++++++++++++++
tools/perf/util/debug.h | 1 +
tools/perf/util/log.c | 2 +
6 files changed, 142 insertions(+)
create mode 100644 tools/perf/ui/browsers/log.c
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 2b5252f09c04..51d87a25d17d 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -491,6 +491,7 @@ ifndef NO_SLANG
LIB_OBJS += $(OUTPUT)ui/browsers/map.o
LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
LIB_OBJS += $(OUTPUT)ui/browsers/header.o
+ LIB_OBJS += $(OUTPUT)ui/browsers/log.o
LIB_OBJS += $(OUTPUT)ui/tui/setup.o
LIB_OBJS += $(OUTPUT)ui/tui/util.o
LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index 118cca29dd26..1f676c8ec4f3 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -61,6 +61,7 @@ int ui_browser__input_window(const char *title, const char *text, char *input,
const char *exit_msg, int delay_sec);
struct perf_session_env;
int tui__header_window(struct perf_session_env *env);
+int tui__log_window(void);
void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence);
unsigned int ui_browser__argv_refresh(struct ui_browser *browser);
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index b720b92eba6e..e0ab399d431d 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1416,6 +1416,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
/* help messages are sorted by lexical order of the hotkey */
const char report_help[] = HIST_BROWSER_HELP_COMMON
"i Show header information\n"
+ "l Show log messages\n"
"P Print histograms to perf.hist.N\n"
"r Run available scripts\n"
"s Switch to another data file in PWD\n"
@@ -1423,6 +1424,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
"V Verbose (DSO names in callchains, etc)\n"
"/ Filter symbol by name";
const char top_help[] = HIST_BROWSER_HELP_COMMON
+ "l Show log messages\n"
"P Print histograms to perf.hist.N\n"
"t Zoom into current Thread\n"
"V Verbose (DSO names in callchains, etc)\n"
@@ -1517,6 +1519,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (env->arch)
tui__header_window(env);
continue;
+ case 'l':
+ tui__log_window();
+ continue;
case K_F1:
case 'h':
case '?':
diff --git a/tools/perf/ui/browsers/log.c b/tools/perf/ui/browsers/log.c
new file mode 100644
index 000000000000..c64aeb8f9aac
--- /dev/null
+++ b/tools/perf/ui/browsers/log.c
@@ -0,0 +1,132 @@
+#include <stdio.h>
+
+#include "perf.h"
+#include "util/util.h"
+#include "util/cache.h"
+#include "util/debug.h"
+#include "ui/ui.h"
+#include "ui/util.h"
+#include "ui/browser.h"
+#include "ui/libslang.h"
+#include "ui/keysyms.h"
+
+static void ui_browser__file_seek(struct ui_browser *browser __maybe_unused,
+ off_t offset __maybe_unused,
+ int whence __maybe_unused)
+{
+ /* do nothing */
+}
+
+static void ui_browser__file_write(struct ui_browser *browser,
+ void *entry, int row)
+{
+ char buf[1024];
+ char empty[] = " ";
+ FILE *fp = perf_log.fp;
+ bool current_entry = ui_browser__is_current_entry(browser, row);
+ off_t *linemap = perf_log.linemap;
+ unsigned int idx = *(unsigned int *)entry;
+ unsigned long offset = (unsigned long)browser->priv;
+
+ fseek(fp, linemap[idx], SEEK_SET);
+ if (fgets(buf, sizeof(buf), fp) == NULL)
+ return;
+
+ ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
+ HE_COLORSET_NORMAL);
+
+ if (offset < strlen(buf))
+ slsmg_write_nstring(&buf[offset], browser->width);
+ else
+ slsmg_write_nstring(empty, browser->width);
+}
+
+static unsigned int ui_browser__file_refresh(struct ui_browser *browser)
+{
+ unsigned int row = 0;
+ unsigned int idx = browser->top_idx;
+ fpos_t pos;
+
+ fgetpos(perf_log.fp, &pos);
+
+ if (perf_log.linemap_changed) {
+ /* update log window with new linemap */
+ browser->entries = perf_log.linemap;
+ browser->nr_entries = perf_log.lines;
+ perf_log.linemap_changed = false;
+ }
+
+ while (idx < browser->nr_entries) {
+ ui_browser__gotorc(browser, row, 0);
+ browser->write(browser, &idx, row);
+ if (++row == browser->height)
+ break;
+
+ ++idx;
+ }
+
+ fsetpos(perf_log.fp, &pos);
+ return row;
+}
+
+static int log_menu__run(struct ui_browser *menu)
+{
+ int key;
+ unsigned long offset;
+ const char help[] =
+ "h/?/F1 Show this window\n"
+ "UP/DOWN/PGUP\n"
+ "PGDN/SPACE\n"
+ "LEFT/RIGHT Navigate\n"
+ "q/ESC/CTRL+C Exit browser";
+
+ if (ui_browser__show(menu, "Log messages", "Press 'q' to exit") < 0)
+ return -1;
+
+ while (1) {
+ key = ui_browser__run(menu, 0);
+
+ switch (key) {
+ case K_RIGHT:
+ offset = (unsigned long)menu->priv;
+ offset += 10;
+ menu->priv = (void *)offset;
+ continue;
+ case K_LEFT:
+ offset = (unsigned long)menu->priv;
+ if (offset >= 10)
+ offset -= 10;
+ menu->priv = (void *)offset;
+ continue;
+ case K_F1:
+ case 'h':
+ case '?':
+ ui_browser__help_window(menu, help);
+ continue;
+ case K_ESC:
+ case 'q':
+ case CTRL('c'):
+ key = -1;
+ break;
+ default:
+ continue;
+ }
+
+ break;
+ }
+
+ ui_browser__hide(menu);
+ return key;
+}
+
+int tui__log_window(void)
+{
+ struct ui_browser log_menu = {
+ .refresh = ui_browser__file_refresh,
+ .seek = ui_browser__file_seek,
+ .write = ui_browser__file_write,
+ .nr_entries = perf_log.lines,
+ };
+
+ return log_menu__run(&log_menu);
+}
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 2d69e9fa6499..469abfcdc7c0 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -25,6 +25,7 @@ struct perf_log {
u32 lines;
u32 nr_alloc;
bool seen_newline;
+ bool linemap_changed;
};
extern struct perf_log perf_log;
diff --git a/tools/perf/util/log.c b/tools/perf/util/log.c
index cb94417da435..4b05345c35c7 100644
--- a/tools/perf/util/log.c
+++ b/tools/perf/util/log.c
@@ -99,6 +99,8 @@ void perf_log__add(const char *msg)
/* restore original offset */
fseeko(fp, offset, SEEK_SET);
perf_log.lines = saved_lines;
+ } else {
+ perf_log.linemap_changed = true;
}
pthread_mutex_unlock(&ui__lock);
}
--
1.7.11.7
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 4/5] perf ui/tui: Filter messages in log window
2014-01-13 8:00 [PATCHSET 0/5] perf tools: Add support log window on TUI (v4) Namhyung Kim
` (2 preceding siblings ...)
2014-01-13 8:00 ` [PATCH 3/5] perf ui/tui: Implement log window Namhyung Kim
@ 2014-01-13 8:00 ` Namhyung Kim
2014-01-13 8:00 ` [PATCH 5/5] perf ui/tui: Remember last log line for filtering Namhyung Kim
4 siblings, 0 replies; 6+ messages in thread
From: Namhyung Kim @ 2014-01-13 8:00 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
Jiri Olsa, David Ahern
Press '/' key to input filter string like main hist browser does.
Requested-by: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/ui/browsers/log.c | 117 +++++++++++++++++++++++++++++++++++++------
1 file changed, 103 insertions(+), 14 deletions(-)
diff --git a/tools/perf/ui/browsers/log.c b/tools/perf/ui/browsers/log.c
index c64aeb8f9aac..62343e0578bb 100644
--- a/tools/perf/ui/browsers/log.c
+++ b/tools/perf/ui/browsers/log.c
@@ -10,6 +10,14 @@
#include "ui/libslang.h"
#include "ui/keysyms.h"
+struct log_browser_data {
+ unsigned long offset;
+ u32 alloc;
+ char filter[64];
+};
+
+static void __log_menu__filter(struct ui_browser *menu, char *filter);
+
static void ui_browser__file_seek(struct ui_browser *browser __maybe_unused,
off_t offset __maybe_unused,
int whence __maybe_unused)
@@ -23,10 +31,11 @@ static void ui_browser__file_write(struct ui_browser *browser,
char buf[1024];
char empty[] = " ";
FILE *fp = perf_log.fp;
+ struct log_browser_data *lbd = browser->priv;
bool current_entry = ui_browser__is_current_entry(browser, row);
- off_t *linemap = perf_log.linemap;
+ off_t *linemap = browser->entries;
unsigned int idx = *(unsigned int *)entry;
- unsigned long offset = (unsigned long)browser->priv;
+ unsigned long offset = lbd->offset;
fseek(fp, linemap[idx], SEEK_SET);
if (fgets(buf, sizeof(buf), fp) == NULL)
@@ -45,14 +54,14 @@ static unsigned int ui_browser__file_refresh(struct ui_browser *browser)
{
unsigned int row = 0;
unsigned int idx = browser->top_idx;
+ struct log_browser_data *lbd = browser->priv;
fpos_t pos;
fgetpos(perf_log.fp, &pos);
if (perf_log.linemap_changed) {
/* update log window with new linemap */
- browser->entries = perf_log.linemap;
- browser->nr_entries = perf_log.lines;
+ __log_menu__filter(browser, lbd->filter);
perf_log.linemap_changed = false;
}
@@ -69,16 +78,81 @@ static unsigned int ui_browser__file_refresh(struct ui_browser *browser)
return row;
}
+static void __log_menu__filter(struct ui_browser *menu, char *filter)
+{
+ char buf[1024];
+ struct log_browser_data *lbd = menu->priv;
+ off_t *linemap = NULL;
+ u32 lines = 0;
+ u32 alloc = 0;
+ u32 i;
+
+ if (*filter == '\0') {
+ linemap = perf_log.linemap;
+ lines = perf_log.lines;
+ goto out;
+ }
+
+ for (i = 0; i < perf_log.lines; i++) {
+ fseek(perf_log.fp, perf_log.linemap[i], SEEK_SET);
+ if (fgets(buf, sizeof(buf), perf_log.fp) == NULL)
+ goto error;
+
+ if (strstr(buf, filter) == NULL)
+ continue;
+
+ if (lines == alloc) {
+ off_t *map;
+
+ map = realloc(linemap, (alloc + 128) * sizeof(*map));
+ if (map == NULL)
+ goto error;
+
+ linemap = map;
+ alloc += 128;
+ }
+
+ linemap[lines++] = perf_log.linemap[i];
+ }
+
+out:
+ if (lbd->alloc) {
+ BUG_ON(menu->entries == perf_log.linemap);
+ free(menu->entries);
+ }
+ lbd->alloc = alloc;
+
+ menu->entries = linemap;
+ ui_browser__update_nr_entries(menu, lines);
+ return;
+
+error:
+ free(linemap);
+}
+
+static void log_menu__filter(struct ui_browser *menu, char *filter)
+{
+ fpos_t pos;
+
+ pthread_mutex_lock(&ui__lock);
+ fgetpos(perf_log.fp, &pos);
+ __log_menu__filter(menu, filter);
+ fsetpos(perf_log.fp, &pos);
+ perf_log.linemap_changed = false;
+ pthread_mutex_unlock(&ui__lock);
+}
+
static int log_menu__run(struct ui_browser *menu)
{
int key;
- unsigned long offset;
+ struct log_browser_data *lbd = menu->priv;
const char help[] =
"h/?/F1 Show this window\n"
"UP/DOWN/PGUP\n"
"PGDN/SPACE\n"
"LEFT/RIGHT Navigate\n"
- "q/ESC/CTRL+C Exit browser";
+ "q/ESC/CTRL+C Exit browser\n\n"
+ "/ Filter log message";
if (ui_browser__show(menu, "Log messages", "Press 'q' to exit") < 0)
return -1;
@@ -88,21 +162,25 @@ static int log_menu__run(struct ui_browser *menu)
switch (key) {
case K_RIGHT:
- offset = (unsigned long)menu->priv;
- offset += 10;
- menu->priv = (void *)offset;
+ lbd->offset += 10;
continue;
case K_LEFT:
- offset = (unsigned long)menu->priv;
- if (offset >= 10)
- offset -= 10;
- menu->priv = (void *)offset;
+ if (lbd->offset >= 10)
+ lbd->offset -= 10;
continue;
case K_F1:
case 'h':
case '?':
ui_browser__help_window(menu, help);
continue;
+ case '/':
+ if (ui_browser__input_window("Symbol to filter",
+ "Please enter the name of symbol you want to see",
+ lbd->filter, "ENTER: OK, ESC: Cancel",
+ 0) == K_ENTER) {
+ log_menu__filter(menu, lbd->filter);
+ }
+ continue;
case K_ESC:
case 'q':
case CTRL('c'):
@@ -121,12 +199,23 @@ static int log_menu__run(struct ui_browser *menu)
int tui__log_window(void)
{
+ struct log_browser_data lbd = {
+ .filter = "",
+ };
struct ui_browser log_menu = {
.refresh = ui_browser__file_refresh,
.seek = ui_browser__file_seek,
.write = ui_browser__file_write,
+ .entries = perf_log.linemap,
.nr_entries = perf_log.lines,
+ .priv = &lbd,
};
+ int key;
+
+ key = log_menu__run(&log_menu);
- return log_menu__run(&log_menu);
+ if (lbd.alloc)
+ free(log_menu.entries);
+
+ return key;
}
--
1.7.11.7
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 5/5] perf ui/tui: Remember last log line for filtering
2014-01-13 8:00 [PATCHSET 0/5] perf tools: Add support log window on TUI (v4) Namhyung Kim
` (3 preceding siblings ...)
2014-01-13 8:00 ` [PATCH 4/5] perf ui/tui: Filter messages in " Namhyung Kim
@ 2014-01-13 8:00 ` Namhyung Kim
4 siblings, 0 replies; 6+ messages in thread
From: Namhyung Kim @ 2014-01-13 8:00 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
Jiri Olsa, David Ahern
When updating log window with filter string, no need to search all
logs everytime. Just save the last offset and update from there.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/ui/browsers/log.c | 28 +++++++++++++++++++++-------
1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/tools/perf/ui/browsers/log.c b/tools/perf/ui/browsers/log.c
index 62343e0578bb..828b98522a48 100644
--- a/tools/perf/ui/browsers/log.c
+++ b/tools/perf/ui/browsers/log.c
@@ -13,10 +13,11 @@
struct log_browser_data {
unsigned long offset;
u32 alloc;
+ u32 last_log_line;
char filter[64];
};
-static void __log_menu__filter(struct ui_browser *menu, char *filter);
+static void __log_menu__filter(struct ui_browser *menu, char *filter, bool update);
static void ui_browser__file_seek(struct ui_browser *browser __maybe_unused,
off_t offset __maybe_unused,
@@ -61,7 +62,7 @@ static unsigned int ui_browser__file_refresh(struct ui_browser *browser)
if (perf_log.linemap_changed) {
/* update log window with new linemap */
- __log_menu__filter(browser, lbd->filter);
+ __log_menu__filter(browser, lbd->filter, true);
perf_log.linemap_changed = false;
}
@@ -78,14 +79,15 @@ static unsigned int ui_browser__file_refresh(struct ui_browser *browser)
return row;
}
-static void __log_menu__filter(struct ui_browser *menu, char *filter)
+static void __log_menu__filter(struct ui_browser *menu, char *filter, bool update)
{
char buf[1024];
struct log_browser_data *lbd = menu->priv;
off_t *linemap = NULL;
u32 lines = 0;
u32 alloc = 0;
- u32 i;
+ u32 last = 0;
+ u32 i = 0;
if (*filter == '\0') {
linemap = perf_log.linemap;
@@ -93,7 +95,14 @@ static void __log_menu__filter(struct ui_browser *menu, char *filter)
goto out;
}
- for (i = 0; i < perf_log.lines; i++) {
+ if (update) {
+ linemap = menu->entries;
+ lines = menu->nr_entries;
+ alloc = lbd->alloc;
+ last = lbd->last_log_line;
+ }
+
+ for (i = last; i < perf_log.lines; i++) {
fseek(perf_log.fp, perf_log.linemap[i], SEEK_SET);
if (fgets(buf, sizeof(buf), perf_log.fp) == NULL)
goto error;
@@ -116,11 +125,16 @@ static void __log_menu__filter(struct ui_browser *menu, char *filter)
}
out:
- if (lbd->alloc) {
+ if (!update && lbd->alloc) {
BUG_ON(menu->entries == perf_log.linemap);
free(menu->entries);
}
+
lbd->alloc = alloc;
+ lbd->last_log_line = i;
+
+ if (!update)
+ ui_browser__reset_index(menu);
menu->entries = linemap;
ui_browser__update_nr_entries(menu, lines);
@@ -136,7 +150,7 @@ static void log_menu__filter(struct ui_browser *menu, char *filter)
pthread_mutex_lock(&ui__lock);
fgetpos(perf_log.fp, &pos);
- __log_menu__filter(menu, filter);
+ __log_menu__filter(menu, filter, false);
fsetpos(perf_log.fp, &pos);
perf_log.linemap_changed = false;
pthread_mutex_unlock(&ui__lock);
--
1.7.11.7
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2014-01-13 8:02 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-01-13 8:00 [PATCHSET 0/5] perf tools: Add support log window on TUI (v4) Namhyung Kim
2014-01-13 8:00 ` [PATCH 1/5] perf tools: Introduce struct perf_log Namhyung Kim
2014-01-13 8:00 ` [PATCH 2/5] perf tools: Save message when pr_*() was called Namhyung Kim
2014-01-13 8:00 ` [PATCH 3/5] perf ui/tui: Implement log window Namhyung Kim
2014-01-13 8:00 ` [PATCH 4/5] perf ui/tui: Filter messages in " Namhyung Kim
2014-01-13 8:00 ` [PATCH 5/5] perf ui/tui: Remember last log line for filtering Namhyung Kim
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®