Press '/' key to input filter string like main hist browser does.

Requested-by: Jiri Olsa <jo...@redhat.com>
Signed-off-by: Namhyung Kim <namhy...@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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to