From 7f5dd7b6e1aa1ea12b8d4d802b8aadd501876ba5 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Tue, 30 Mar 2010 14:43:09 -0400
Subject: kernelshark: Add dialog helper
Add trace-dialog.c to include a trace_show_help() and trace_dialog()
helpers.
Signed-off-by: Steven Rostedt
---
Makefile | 13 +++++-----
trace-compat.c | 9 +++++++
trace-compat.h | 2 ++
trace-dialog.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
trace-gui.h | 38 ++++++++++++++++++++++++++++
5 files changed, 134 insertions(+), 7 deletions(-)
create mode 100644 trace-dialog.c
create mode 100644 trace-gui.h
diff --git a/Makefile b/Makefile
index d13edec..7402ae1 100644
--- a/Makefile
+++ b/Makefile
@@ -213,14 +213,13 @@ $(obj)/%.o: $(src)/%.c
%.o: $(src)/%.c
$(Q)$(call check_gui)
+TRACE_GUI_OBJS = trace-filter.o trace-compat.o trace-hash.o trace-dialog.o
TRACE_CMD_OBJS = trace-cmd.o trace-usage.o trace-read.o trace-split.o trace-listen.o
-TRACE_VIEW_OBJS = trace-view.o trace-view-store.o trace-filter.o trace-compat.o \
- trace-hash.o
-TRACE_GRAPH_OBJS = trace-graph.o trace-compat.o trace-hash.o trace-filter.o \
- trace-plot.o trace-plot-cpu.o trace-plot-task.o
-TRACE_VIEW_MAIN_OBJS = trace-view-main.o $(TRACE_VIEW_OBJS)
-TRACE_GRAPH_MAIN_OBJS = trace-graph-main.o $(TRACE_GRAPH_OBJS)
-KERNEL_SHARK_OBJS = $(TRACE_VIEW_OBJS) $(TRACE_GRAPH_OBJS) kernel-shark.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)
+TRACE_GRAPH_MAIN_OBJS = trace-graph-main.o $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS)
+KERNEL_SHARK_OBJS = $(TRACE_VIEW_OBJS) $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS) kernel-shark.o
PEVENT_LIB_OBJS = parse-events.o trace-seq.o parse-filter.o
TCMD_LIB_OBJS = $(PEVENT_LIB_OBJS) trace-util.o trace-input.o trace-ftrace.o \
diff --git a/trace-compat.c b/trace-compat.c
index 5082757..a1f2113 100644
--- a/trace-compat.c
+++ b/trace-compat.c
@@ -22,6 +22,9 @@
* Linux Kernel that were written by Frederic Weisbecker.
*/
#include "trace-compat.h"
+#include "trace-gui.h"
+
+#include
#if GTK_VERSION < CALC_GTK_VERSION(2,18,0)
@@ -70,6 +73,12 @@ gdouble gtk_adjustment_get_lower(GtkAdjustment *adj)
return adj->lower;
}
+gboolean gtk_show_uri(GdkScreen *screen, const gchar *uri,
+ guint32 timestamp, GError **error)
+{
+ return FALSE;
+}
+
#endif /* version < 2.14.0 */
#if GTK_VERSION < CALC_GTK_VERSION(2,12,0)
diff --git a/trace-compat.h b/trace-compat.h
index 1c9126d..2eed192 100644
--- a/trace-compat.h
+++ b/trace-compat.h
@@ -43,6 +43,8 @@ void gtk_menu_item_set_label(GtkMenuItem *menu_item, const gchar *label);
gdouble gtk_adjustment_get_page_size(GtkAdjustment *adj);
gdouble gtk_adjustment_get_upper(GtkAdjustment *adj);
gdouble gtk_adjustment_get_lower(GtkAdjustment *adj);
+gboolean gtk_show_uri(GdkScreen *screen, const gchar *uri,
+ guint32 timestamp, GError **error);
#endif /* version < 2.14.0 */
diff --git a/trace-dialog.c b/trace-dialog.c
new file mode 100644
index 0000000..65d184d
--- /dev/null
+++ b/trace-dialog.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include
+#include
+#include
+#include
+#include
+
+#include "trace-compat.h"
+#include "trace-gui.h"
+
+#define DIALOG_WIDTH 400
+#define DIALOG_HEIGHT 600
+
+void trace_show_help(GtkWidget *window, const gchar *link, GError **error)
+{
+#if GTK_VERSION < CALC_GTK_VERSION(2,14,0)
+ trace_dialog(GTK_WINDOW(window), TRACE_GUI_WARNING,
+ "This version of GTK+ does not implement gtk_show_uri.\n"
+ "Please upgrade your GTK and recompile");
+#else
+ gtk_show_uri(gtk_widget_get_screen(GTK_WIDGET(window)),
+ link,
+ GDK_CURRENT_TIME,
+ error);
+#endif
+}
+
+void trace_dialog(GtkWindow *parent, enum trace_dialog_type type,
+ gchar *message, ...)
+{
+ GtkWidget *dialog;
+ GtkMessageType mtype;
+ gchar *str;
+ va_list ap;
+
+ switch (type) {
+ case TRACE_GUI_INFO:
+ mtype = GTK_MESSAGE_INFO;
+ break;
+ case TRACE_GUI_WARNING:
+ mtype = GTK_MESSAGE_WARNING;
+ break;
+ case TRACE_GUI_ERROR:
+ mtype = GTK_MESSAGE_ERROR;
+ break;
+ }
+
+ va_start(ap, message);
+ str = g_strdup_vprintf(message, ap);
+ va_end(ap);
+
+ dialog = gtk_message_dialog_new(parent,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ mtype,
+ GTK_BUTTONS_CLOSE,
+ "%s", str);
+ g_free(str);
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+}
diff --git a/trace-gui.h b/trace-gui.h
new file mode 100644
index 0000000..97b8e41
--- /dev/null
+++ b/trace-gui.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#ifndef _TRACE_GUI
+#define _TRACE_GUI
+
+#include
+
+enum trace_dialog_type {
+ TRACE_GUI_INFO,
+ TRACE_GUI_WARNING,
+ TRACE_GUI_ERROR,
+};
+
+void trace_show_help(GtkWidget *window, const gchar *link, GError **error);
+
+void trace_dialog(GtkWindow *parent, enum trace_dialog_type type,
+ gchar *message, ...);
+
+
+#endif /* _TRACE_GUI */
--
cgit v1.2.2
From 395ef10599bb35b100ecf3a87bad9a22d010b178 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Tue, 30 Mar 2010 15:18:49 -0400
Subject: kernelshark: Add "Help" menu options
Add help content and about to menu options. Still need to write
the help content, right now it just points to google.
Signed-off-by: Steven Rostedt
---
kernel-shark.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/kernel-shark.c b/kernel-shark.c
index fcb0f54..58aa860 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -31,6 +31,7 @@
#include "trace-compat.h"
#include "trace-cmd.h"
+#include "trace-gui.h"
#include "kernel-shark.h"
#include "version.h"
@@ -362,6 +363,34 @@ plot_tasks_clicked (gpointer data)
free(selected);
}
+/* Callback for the clicked signal of the help contents button */
+static void
+help_content_clicked (gpointer data)
+{
+ struct shark_info *info = data;
+ GError *error = NULL;
+ gchar *link;
+
+ link = "http://www.google.com";
+
+ trace_show_help(info->window, link, &error);
+}
+
+
+/* Callback for the clicked signal of the help about button */
+static void
+help_about_clicked (gpointer data)
+{
+ struct shark_info *info = data;
+
+ trace_dialog(GTK_WINDOW(info->window), TRACE_GUI_INFO,
+ "KernelShark\n\n"
+ "version %s\n\n"
+ "Copyright (C) 2009, 2010 Red Hat Inc\n\n"
+ " Author: Steven Rostedt ",
+ VERSION_STRING);
+}
+
static void graph_follows_tree(struct shark_info *info,
GtkTreeView *treeview,
GtkTreePath *path)
@@ -939,6 +968,53 @@ void kernel_shark(int argc, char **argv)
gtk_menu_item_set_submenu(GTK_MENU_ITEM (menu_item), menu);
+
+ /* --- Help Option --- */
+
+ menu_item = gtk_menu_item_new_with_label("Help");
+ gtk_widget_show(menu_item);
+
+ gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), menu_item);
+
+ menu = gtk_menu_new(); /* Don't need to show menus */
+
+
+ /* --- Help - Contents Option --- */
+
+ sub_item = gtk_menu_item_new_with_label("Contents");
+
+ /* Add them to the menu */
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
+
+ /* We can attach the Quit menu item to our exit function */
+ g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
+ G_CALLBACK (help_content_clicked),
+ (gpointer) info);
+
+ /* We do need to show menu items */
+ gtk_widget_show(sub_item);
+
+
+ /* --- Help - About Option --- */
+
+ sub_item = gtk_menu_item_new_with_label("About");
+
+ /* Add them to the menu */
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
+
+ /* We can attach the Quit menu item to our exit function */
+ g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
+ G_CALLBACK (help_about_clicked),
+ (gpointer) info);
+
+ /* We do need to show menu items */
+ gtk_widget_show(sub_item);
+
+
+ /* --- End Help Options --- */
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM (menu_item), menu);
+
+
/* --- Top Level Vpaned --- */
vpaned = gtk_vpaned_new();
--
cgit v1.2.2
From 810abc5b84f2855cc328cb709e75046a646be463 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Tue, 30 Mar 2010 16:45:31 -0400
Subject: kernelshark: Created trace_get_file_dialog() to ask for filename
Added shortcut trace_get_file_dialog() to simplify the asking for
a file name.
Signed-off-by: Steven Rostedt
---
kernel-shark.c | 34 +++++++++++++---------------------
trace-dialog.c | 19 +++++++++++++++++++
trace-graph-main.c | 28 +++++++++++-----------------
trace-gui.h | 2 ++
trace-view-main.c | 28 +++++++++++-----------------
5 files changed, 56 insertions(+), 55 deletions(-)
diff --git a/kernel-shark.c b/kernel-shark.c
index 58aa860..d913ae0 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -141,28 +141,21 @@ load_clicked (gpointer data)
{
struct shark_info *info = data;
struct tracecmd_input *handle;
- GtkWidget *dialog;
gchar *filename;
- dialog = gtk_file_chooser_dialog_new("Load File",
- NULL,
- GTK_FILE_CHOOSER_ACTION_OPEN,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
- NULL);
- if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
- filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
- handle = tracecmd_open(filename);
- if (handle) {
- tracecmd_close(info->handle);
- info->handle = handle;
- trace_graph_load_handle(info->ginfo, handle);
- trace_view_reload(info->treeview, handle, info->spin);
- update_title(info->window, filename);
- }
- g_free(filename);
+ filename = trace_get_file_dialog("Load File");
+ if (!filename)
+ return;
+
+ handle = tracecmd_open(filename);
+ if (handle) {
+ tracecmd_close(info->handle);
+ info->handle = handle;
+ trace_graph_load_handle(info->ginfo, handle);
+ trace_view_reload(info->treeview, handle, info->spin);
+ update_title(info->window, filename);
}
- gtk_widget_destroy(dialog);
+ g_free(filename);
}
/* Callback for the clicked signal of the Exit button */
@@ -763,12 +756,11 @@ void kernel_shark(int argc, char **argv)
/* --- File - Load Option --- */
- sub_item = gtk_menu_item_new_with_label("Load info");
+ sub_item = gtk_menu_item_new_with_label("Load data");
/* Add them to the menu */
gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
- /* We can attach the Quit menu item to our exit function */
g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
G_CALLBACK (load_clicked),
(gpointer) info);
diff --git a/trace-dialog.c b/trace-dialog.c
index 65d184d..e27245d 100644
--- a/trace-dialog.c
+++ b/trace-dialog.c
@@ -77,3 +77,22 @@ void trace_dialog(GtkWindow *parent, enum trace_dialog_type type,
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
+
+gchar *trace_get_file_dialog(const gchar *title)
+{
+ GtkWidget *dialog;
+ gchar *filename = NULL;
+
+ dialog = gtk_file_chooser_dialog_new(title,
+ NULL,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+ NULL);
+ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
+ filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+
+ gtk_widget_destroy(dialog);
+
+ return filename;
+}
diff --git a/trace-graph-main.c b/trace-graph-main.c
index b373dd2..303f342 100644
--- a/trace-graph-main.c
+++ b/trace-graph-main.c
@@ -29,6 +29,7 @@
#include "trace-cmd.h"
#include "trace-graph.h"
#include "trace-filter.h"
+#include "trace-gui.h"
#define version "0.1.1"
@@ -52,26 +53,19 @@ load_clicked (gpointer data)
{
struct graph_info *ginfo = data;
struct tracecmd_input *handle;
- GtkWidget *dialog;
gchar *filename;
- dialog = gtk_file_chooser_dialog_new("Load File",
- NULL,
- GTK_FILE_CHOOSER_ACTION_OPEN,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
- NULL);
- if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
- filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
- handle = tracecmd_open(filename);
- if (handle) {
- trace_graph_load_handle(ginfo, handle);
- /* Free handle when freeing graph */
- tracecmd_close(handle);
- }
- g_free(filename);
+ filename = trace_get_file_dialog("Load File");
+ if (!filename)
+ return;
+
+ handle = tracecmd_open(filename);
+ if (handle) {
+ trace_graph_load_handle(ginfo, handle);
+ /* Free handle when freeing graph */
+ tracecmd_close(handle);
}
- gtk_widget_destroy(dialog);
+ g_free(filename);
}
/* Callback for the clicked signal of the Exit button */
diff --git a/trace-gui.h b/trace-gui.h
index 97b8e41..55778bf 100644
--- a/trace-gui.h
+++ b/trace-gui.h
@@ -34,5 +34,7 @@ void trace_show_help(GtkWidget *window, const gchar *link, GError **error);
void trace_dialog(GtkWindow *parent, enum trace_dialog_type type,
gchar *message, ...);
+gchar *trace_get_file_dialog(const gchar *title);
+
#endif /* _TRACE_GUI */
diff --git a/trace-view-main.c b/trace-view-main.c
index 52678ce..7f1461b 100644
--- a/trace-view-main.c
+++ b/trace-view-main.c
@@ -28,6 +28,7 @@
#include "trace-cmd.h"
#include "trace-view.h"
+#include "trace-gui.h"
#define version "0.1.1"
@@ -55,26 +56,19 @@ load_clicked (gpointer data)
{
struct trace_tree_info *info = data;
struct tracecmd_input *handle;
- GtkWidget *dialog;
gchar *filename;
- dialog = gtk_file_chooser_dialog_new("Load File",
- NULL,
- GTK_FILE_CHOOSER_ACTION_OPEN,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
- NULL);
- if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
- filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
- handle = tracecmd_open(filename);
- if (handle) {
- trace_view_reload(info->trace_tree, handle, info->spin);
- /* Free handle when freeing the trace tree */
- tracecmd_close(handle);
- }
- g_free(filename);
+ filename = trace_get_file_dialog("Load File");
+ if (!filename)
+ return;
+
+ handle = tracecmd_open(filename);
+ if (handle) {
+ trace_view_reload(info->trace_tree, handle, info->spin);
+ /* Free handle when freeing the trace tree */
+ tracecmd_close(handle);
}
- gtk_widget_destroy(dialog);
+ g_free(filename);
}
/* Callback for the clicked signal of the Exit button */
--
cgit v1.2.2
From 3f1e092ed414ab2a9f73eafe87f35e868030463c Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Wed, 31 Mar 2010 05:32:43 -0400
Subject: trace-view: Added saving of filters
Add "Save filters" to "File" menu, where it will allow the user to save
the filters to a file in XML format.
Signed-off-by: Steven Rostedt
---
Makefile | 8 ++--
trace-filter.c | 51 ++++++++++++++++++++++
trace-filter.h | 7 +++
trace-view-main.c | 42 +++++++++++++++++-
trace-view.c | 48 +++++++++++++++++++++
trace-view.h | 4 ++
trace-xml.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
trace-xml.h | 41 ++++++++++++++++++
8 files changed, 323 insertions(+), 5 deletions(-)
create mode 100644 trace-xml.c
create mode 100644 trace-xml.h
diff --git a/Makefile b/Makefile
index 7402ae1..cd4db4a 100644
--- a/Makefile
+++ b/Makefile
@@ -96,7 +96,7 @@ plugin_dir_SQ = $(subst ','\'',$(plugin_dir))
LIBS = -L. -ltracecmd -ldl
LIB_FILE = libtracecmd.a
-PACKAGES= gtk+-2.0
+PACKAGES= gtk+-2.0 libxml-2.0
ifndef BUILDGUI
BUILDGUI = 0
@@ -213,13 +213,15 @@ $(obj)/%.o: $(src)/%.c
%.o: $(src)/%.c
$(Q)$(call check_gui)
-TRACE_GUI_OBJS = trace-filter.o trace-compat.o trace-hash.o trace-dialog.o
+TRACE_GUI_OBJS = trace-filter.o trace-compat.o trace-hash.o trace-dialog.o \
+ trace-xml.o
TRACE_CMD_OBJS = trace-cmd.o trace-usage.o trace-read.o trace-split.o trace-listen.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)
TRACE_GRAPH_MAIN_OBJS = trace-graph-main.o $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS)
-KERNEL_SHARK_OBJS = $(TRACE_VIEW_OBJS) $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS) kernel-shark.o
+KERNEL_SHARK_OBJS = $(TRACE_VIEW_OBJS) $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS) \
+ kernel-shark.o
PEVENT_LIB_OBJS = parse-events.o trace-seq.o parse-filter.o
TCMD_LIB_OBJS = $(PEVENT_LIB_OBJS) trace-util.o trace-input.o trace-ftrace.o \
diff --git a/trace-filter.c b/trace-filter.c
index 15d59c0..904c9cb 100644
--- a/trace-filter.c
+++ b/trace-filter.c
@@ -2158,3 +2158,54 @@ void trace_filter_convert_char_to_filter(struct event_filter *filter,
pevent_filter_free(copy);
}
+
+int trace_filter_save_events(struct tracecmd_xml_handle *handle,
+ struct event_filter *filter)
+{
+ struct event_format *event;
+ char **systems;
+ gint *event_ids;
+ char *str;
+ int i;
+
+ trace_filter_convert_filter_to_names(filter, &systems,
+ &event_ids);
+
+ for (i = 0; systems && systems[i]; i++)
+ tracecmd_xml_write_element(handle, "System", systems[i]);
+
+ for (i = 0; event_ids && event_ids[i] > 0; i++) {
+ str = pevent_filter_make_string(filter, event_ids[i]);
+ if (!str)
+ continue;
+
+ event = pevent_find_event(filter->pevent, event_ids[i]);
+ if (event) {
+
+ /* skip not filtered items */
+ if (strcmp(str, "FALSE") == 0) {
+ free(str);
+ continue;
+ }
+
+ tracecmd_xml_start_sub_system(handle, "Event");
+ tracecmd_xml_write_element(handle, "System", event->system);
+ tracecmd_xml_write_element(handle, "Name", event->name);
+ /* If this is has an advanced filter, include that too */
+ if (strcmp(str, "TRUE") != 0) {
+ tracecmd_xml_write_element(handle, "Advanced",
+ str);
+ }
+ tracecmd_xml_end_sub_system(handle);
+ }
+ free(str);
+ }
+
+ return 0;
+}
+
+int trace_filter_save_tasks(struct tracecmd_xml_handle *handle,
+ struct filter_task *filter)
+{
+ return 0;
+}
diff --git a/trace-filter.h b/trace-filter.h
index c68e8f0..7575244 100644
--- a/trace-filter.h
+++ b/trace-filter.h
@@ -23,6 +23,8 @@
#include
+#include "trace-xml.h"
+
struct event_filter_list {
struct event_filter_list *next;
struct event *event;
@@ -140,4 +142,9 @@ int id_cmp(const void *a, const void *b);
void trace_array_add(gint **array, gint *count, gint val);
+int trace_filter_save_events(struct tracecmd_xml_handle *handle,
+ struct event_filter *filter);
+int trace_filter_save_tasks(struct tracecmd_xml_handle *handle,
+ struct filter_task *filter);
+
#endif /* _TRACE_FILTER_H */
diff --git a/trace-view-main.c b/trace-view-main.c
index 7f1461b..52fb4f8 100644
--- a/trace-view-main.c
+++ b/trace-view-main.c
@@ -28,6 +28,7 @@
#include "trace-cmd.h"
#include "trace-view.h"
+#include "trace-xml.h"
#include "trace-gui.h"
#define version "0.1.1"
@@ -71,6 +72,29 @@ load_clicked (gpointer data)
g_free(filename);
}
+/* Callback for the clicked signal of the Save State button */
+static void
+save_filters_clicked (gpointer data)
+{
+ struct trace_tree_info *info = data;
+ GtkTreeView *trace_tree = GTK_TREE_VIEW(info->trace_tree);
+ struct tracecmd_xml_handle *handle;
+ gchar *filename;
+
+ filename = trace_get_file_dialog("Save State");
+ if (!filename)
+ return;
+
+ handle = tracecmd_xml_create(filename);
+ if (!handle)
+ warning("Could not create save state %s", filename);
+ g_free(filename);
+
+ trace_view_save_filters(handle, trace_tree);
+
+ tracecmd_xml_close(handle);
+}
+
/* Callback for the clicked signal of the Exit button */
static void
exit_clicked (GtkWidget *widget, gpointer data)
@@ -249,12 +273,11 @@ void trace_view(int argc, char **argv)
/* --- File - Load Option --- */
- sub_item = gtk_menu_item_new_with_label("Load info");
+ sub_item = gtk_menu_item_new_with_label("Load data");
/* Add them to the menu */
gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
- /* We can attach the Quit menu item to our exit function */
g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
G_CALLBACK (load_clicked),
(gpointer) &tree_info);
@@ -263,6 +286,21 @@ void trace_view(int argc, char **argv)
gtk_widget_show(sub_item);
+ /* --- File - Save State Option --- */
+
+ sub_item = gtk_menu_item_new_with_label("Save filters");
+
+ /* Add them to the menu */
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
+
+ g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
+ G_CALLBACK (save_filters_clicked),
+ (gpointer) &tree_info);
+
+ /* We do need to show menu items */
+ gtk_widget_show(sub_item);
+
+
/* --- File - Quit Option --- */
sub_item = gtk_menu_item_new_with_label("Quit");
diff --git a/trace-view.c b/trace-view.c
index 59e7e1a..c183b19 100644
--- a/trace-view.c
+++ b/trace-view.c
@@ -29,6 +29,7 @@
#include "trace-local.h"
#include "trace-view.h"
#include "trace-compat.h"
+#include "version.h"
#include "cpu.h"
#include "util.h"
@@ -870,3 +871,50 @@ void trace_view_search_setup(GtkBox *box, GtkTreeView *treeview)
G_CALLBACK (search_tree),
(gpointer) info);
}
+
+int trace_view_save_filters(struct tracecmd_xml_handle *handle,
+ GtkTreeView *trace_tree)
+{
+ struct event_filter *event_filter;
+ GtkTreeModel *model;
+ TraceViewStore *store;
+ gboolean all_events;
+
+ model = gtk_tree_view_get_model(trace_tree);
+ if (!model)
+ return -1;
+
+ store = TRACE_VIEW_STORE(model);
+
+ tracecmd_xml_start_system(handle, "TraceView", VERSION_STRING);
+
+ all_events = trace_view_store_get_all_events_enabled(store);
+ event_filter = trace_view_store_get_event_filter(store);
+
+ tracecmd_xml_start_sub_system(handle, "EventFilter");
+
+ if (all_events || !event_filter)
+ tracecmd_xml_write_element(handle, "FilterType", "all events");
+ else {
+ tracecmd_xml_write_element(handle, "FilterType", "filter");
+ trace_filter_save_events(handle, event_filter);
+ }
+
+ tracecmd_xml_end_sub_system(handle);
+
+ if (store->task_filter) {
+ tracecmd_xml_start_sub_system(handle, "TaskFilter");
+ trace_filter_save_tasks(handle, store->task_filter);
+ tracecmd_xml_end_sub_system(handle);
+ }
+
+ if (store->hide_tasks) {
+ tracecmd_xml_start_sub_system(handle, "HideTasks");
+ trace_filter_save_tasks(handle, store->hide_tasks);
+ tracecmd_xml_end_sub_system(handle);
+ }
+
+ tracecmd_xml_end_system(handle);
+
+ return 0;
+}
diff --git a/trace-view.h b/trace-view.h
index 182b285..5ad33bf 100644
--- a/trace-view.h
+++ b/trace-view.h
@@ -23,6 +23,7 @@
#include "trace-view-store.h"
#include "trace-filter.h"
+#include "trace-xml.h"
void
trace_view_load(GtkWidget *view, struct tracecmd_input *handle,
@@ -65,4 +66,7 @@ void trace_view_search_setup(GtkBox *box, GtkTreeView *treeview);
gint trace_view_get_selected_row(GtkWidget *treeview);
+int trace_view_save_filters(struct tracecmd_xml_handle *handle,
+ GtkTreeView *treeview);
+
#endif /* _TRACE_VIEW_H */
diff --git a/trace-xml.c b/trace-xml.c
new file mode 100644
index 0000000..0bc130c
--- /dev/null
+++ b/trace-xml.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "trace-cmd.h"
+#include "trace-xml.h"
+
+struct tracecmd_xml_handle {
+ xmlTextWriterPtr writer;
+};
+
+#define TRACE_ENCODING "UTF-8"
+
+int tracecmd_xml_write_element(struct tracecmd_xml_handle *handle,
+ const char *obj,
+ const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = xmlTextWriterWriteVFormatElement(handle->writer,
+ BAD_CAST obj, fmt, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+struct tracecmd_xml_handle *tracecmd_xml_create(const char *name)
+{
+ struct tracecmd_xml_handle *handle;
+ int ret;
+
+ handle = malloc_or_die(sizeof(*handle));
+ memset(handle, 0, sizeof(*handle));
+
+ handle->writer = xmlNewTextWriterFilename(name, 0);
+ if (!handle->writer)
+ goto fail_free;
+
+ ret = xmlTextWriterStartDocument(handle->writer, NULL,
+ TRACE_ENCODING, NULL);
+ if (ret < 0)
+ goto fail_close;
+
+ return handle;
+
+ fail_close:
+ xmlFreeTextWriter(handle->writer);
+ fail_free:
+ free(handle);
+ return NULL;
+}
+
+int tracecmd_xml_start_system(struct tracecmd_xml_handle *handle,
+ const char *system, const char *version)
+{
+ int ret;
+
+ ret = xmlTextWriterStartElement(handle->writer,
+ BAD_CAST system);
+
+ if (ret < 0)
+ return ret;
+
+ ret = tracecmd_xml_write_element(handle, "Version", "%s", version);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int tracecmd_xml_start_sub_system(struct tracecmd_xml_handle *handle,
+ const char *subsystem)
+{
+ int ret;
+
+ ret = xmlTextWriterStartElement(handle->writer,
+ BAD_CAST subsystem);
+
+ return ret;
+}
+
+void tracecmd_xml_end_system(struct tracecmd_xml_handle *handle)
+{
+ xmlTextWriterEndElement(handle->writer);
+}
+
+void tracecmd_xml_end_sub_system(struct tracecmd_xml_handle *handle)
+{
+ xmlTextWriterEndElement(handle->writer);
+}
+
+void tracecmd_xml_close(struct tracecmd_xml_handle *handle)
+{
+ if (handle->writer) {
+ xmlTextWriterEndDocument(handle->writer);
+ xmlFreeTextWriter(handle->writer);
+ }
+
+ free(handle);
+}
diff --git a/trace-xml.h b/trace-xml.h
new file mode 100644
index 0000000..41f6193
--- /dev/null
+++ b/trace-xml.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#ifndef __TRACE_XML_H
+#define __TRACE_XML_H
+
+struct tracecmd_xml_handle;
+
+struct tracecmd_xml_handle *tracecmd_xml_create(const char *name);
+void tracecmd_xml_close(struct tracecmd_xml_handle *handle);
+
+int tracecmd_xml_start_system(struct tracecmd_xml_handle *handle,
+ const char *system, const char *version);
+void tracecmd_xml_end_system(struct tracecmd_xml_handle *handle);
+
+int tracecmd_xml_start_sub_system(struct tracecmd_xml_handle *handle,
+ const char *subsystem);
+void tracecmd_xml_end_sub_system(struct tracecmd_xml_handle *handle);
+
+int tracecmd_xml_write_element(struct tracecmd_xml_handle *handle,
+ const char *obj,
+ const char *fmt, ...);
+
+#endif /* __TRACE_XML_H */
--
cgit v1.2.2
From b2a9cd2f38f6c3c30e9ef4c47eb004b41b50fe5e Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Mon, 5 Apr 2010 12:40:51 -0400
Subject: trace-view: Add loading of saved event filters
Add "Load filters" to trace-view that loads the event filters
saved with a "Save filters".
Signed-off-by: Steven Rostedt
---
trace-filter.c | 75 +++++++++++++++++++++++++++++++++++
trace-filter.h | 14 ++++---
trace-view-main.c | 46 ++++++++++++++++++++--
trace-view.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
trace-view.h | 2 +
trace-xml.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++-
trace-xml.h | 19 +++++++++
7 files changed, 366 insertions(+), 10 deletions(-)
diff --git a/trace-filter.c b/trace-filter.c
index 904c9cb..efdb5fa 100644
--- a/trace-filter.c
+++ b/trace-filter.c
@@ -2209,3 +2209,78 @@ int trace_filter_save_tasks(struct tracecmd_xml_handle *handle,
{
return 0;
}
+
+int trace_filter_load_events(struct event_filter *event_filter,
+ struct tracecmd_xml_handle *handle,
+ struct tracecmd_xml_system_node *node)
+{
+ struct tracecmd_xml_system_node *child;
+ const char *name;
+ const char *system;
+ const char *event;
+ const char *value;
+ char *buffer;
+
+ while (node) {
+ name = tracecmd_xml_node_type(node);
+
+ if (strcmp(name, "System") == 0) {
+ system = tracecmd_xml_node_value(handle, node);
+ pevent_filter_add_filter_str(event_filter,
+ system, NULL);
+ } else if (strcmp(name, "Event") == 0) {
+ system = NULL;
+ event = NULL;
+ value = NULL;
+ child = tracecmd_xml_node_child(node);
+ if (!child)
+ return -1;
+ do {
+ name = tracecmd_xml_node_type(child);
+ if (strcmp(name, "System") == 0)
+ system = tracecmd_xml_node_value(handle, child);
+ else if (strcmp(name, "Name") == 0)
+ event = tracecmd_xml_node_value(handle, child);
+ else if (strcmp(name, "Advanced") == 0)
+ value = tracecmd_xml_node_value(handle, child);
+ child = tracecmd_xml_node_next(child);
+ } while (child);
+
+ if (event || system) {
+ if (event && system) {
+ if (value) {
+ buffer = malloc_or_die(strlen(event) +
+ strlen(system) +
+ strlen(value) + 3);
+ sprintf(buffer, "%s/%s:%s",
+ system, event, value);
+ } else {
+ buffer = malloc_or_die(strlen(event) +
+ strlen(system) + 2);
+ sprintf(buffer, "%s/%s",
+ system, event);
+ }
+ } else {
+ if (!event)
+ event = system;
+ if (value) {
+ buffer = malloc_or_die(strlen(event) +
+ strlen(value) + 2);
+ sprintf(buffer, "%s:%s",
+ event, value);
+ } else {
+ buffer = malloc_or_die(strlen(event) + 1);
+ sprintf(buffer, "%s", event);
+ }
+ }
+ pevent_filter_add_filter_str(event_filter,
+ buffer, NULL);
+ free(buffer);
+ }
+ }
+
+ node = tracecmd_xml_node_next(node);
+ }
+
+ return 0;
+}
diff --git a/trace-filter.h b/trace-filter.h
index 7575244..915b174 100644
--- a/trace-filter.h
+++ b/trace-filter.h
@@ -135,16 +135,20 @@ typedef void (*trace_filter_cpu_cb_func)(gboolean accept,
void trace_filter_cpu_dialog(gboolean all_cpus, guint64 *cpu_mask_selected, gint cpus,
trace_filter_cpu_cb_func func, gpointer data);
-/* put here because there's no other place */
-
-int str_cmp(const void *a, const void *b);
-int id_cmp(const void *a, const void *b);
-
void trace_array_add(gint **array, gint *count, gint val);
+/* save and load filters */
int trace_filter_save_events(struct tracecmd_xml_handle *handle,
struct event_filter *filter);
int trace_filter_save_tasks(struct tracecmd_xml_handle *handle,
struct filter_task *filter);
+int trace_filter_load_events(struct event_filter *event_filter,
+ struct tracecmd_xml_handle *handle,
+ struct tracecmd_xml_system_node *node);
+
+/* put here because there's no other place */
+
+int str_cmp(const void *a, const void *b);
+int id_cmp(const void *a, const void *b);
#endif /* _TRACE_FILTER_H */
diff --git a/trace-view-main.c b/trace-view-main.c
index 52fb4f8..22b9e32 100644
--- a/trace-view-main.c
+++ b/trace-view-main.c
@@ -72,7 +72,30 @@ load_clicked (gpointer data)
g_free(filename);
}
-/* Callback for the clicked signal of the Save State button */
+/* Callback for the clicked signal of the Load Filters button */
+static void
+load_filters_clicked (gpointer data)
+{
+ struct trace_tree_info *info = data;
+ GtkTreeView *trace_tree = GTK_TREE_VIEW(info->trace_tree);
+ struct tracecmd_xml_handle *handle;
+ gchar *filename;
+
+ filename = trace_get_file_dialog("Load Filters");
+ if (!filename)
+ return;
+
+ handle = tracecmd_xml_open(filename);
+ if (!handle)
+ warning("Could not open %s", filename);
+ g_free(filename);
+
+ trace_view_load_filters(handle, trace_tree);
+
+ tracecmd_xml_close(handle);
+}
+
+/* Callback for the clicked signal of the Save Filters button */
static void
save_filters_clicked (gpointer data)
{
@@ -81,13 +104,13 @@ save_filters_clicked (gpointer data)
struct tracecmd_xml_handle *handle;
gchar *filename;
- filename = trace_get_file_dialog("Save State");
+ filename = trace_get_file_dialog("Save Filters");
if (!filename)
return;
handle = tracecmd_xml_create(filename);
if (!handle)
- warning("Could not create save state %s", filename);
+ warning("Could not create %s", filename);
g_free(filename);
trace_view_save_filters(handle, trace_tree);
@@ -286,7 +309,22 @@ void trace_view(int argc, char **argv)
gtk_widget_show(sub_item);
- /* --- File - Save State Option --- */
+ /* --- File - Load Filter Option --- */
+
+ sub_item = gtk_menu_item_new_with_label("Load filters");
+
+ /* Add them to the menu */
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
+
+ g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
+ G_CALLBACK (load_filters_clicked),
+ (gpointer) &tree_info);
+
+ /* We do need to show menu items */
+ gtk_widget_show(sub_item);
+
+
+ /* --- File - Save Filter Option --- */
sub_item = gtk_menu_item_new_with_label("Save filters");
diff --git a/trace-view.c b/trace-view.c
index c183b19..094f226 100644
--- a/trace-view.c
+++ b/trace-view.c
@@ -918,3 +918,119 @@ int trace_view_save_filters(struct tracecmd_xml_handle *handle,
return 0;
}
+
+static int load_event_filter(TraceViewStore *store,
+ struct tracecmd_xml_handle *handle,
+ struct tracecmd_xml_system_node *node)
+{
+ struct tracecmd_xml_system_node *child;
+ struct event_filter *event_filter;
+ const char *name;
+ const char *value;
+
+ event_filter = trace_view_store_get_event_filter(store);
+
+ child = tracecmd_xml_node_child(node);
+ name = tracecmd_xml_node_type(child);
+ if (strcmp(name, "FilterType") != 0)
+ return -1;
+
+ value = tracecmd_xml_node_value(handle, child);
+ /* Do nothing with all events enabled */
+ if (strcmp(value, "all events") == 0)
+ return 0;
+
+ node = tracecmd_xml_node_next(child);
+ if (!node)
+ return -1;
+
+ trace_view_store_clear_all_events_enabled(store);
+
+ trace_filter_load_events(event_filter, handle, node);
+
+ return 0;
+}
+
+static int load_task_filter(TraceViewStore *store,
+ struct tracecmd_xml_handle *handle,
+ struct tracecmd_xml_system_node *node)
+{
+ struct tracecmd_xml_system_node *child;
+ const char *name;
+ const char *value;
+
+ child = tracecmd_xml_node_child(node);
+ name = tracecmd_xml_node_type(child);
+ if (strcmp(name, "FilterType") == 0) {
+ value = tracecmd_xml_node_value(handle, child);
+ printf("value = %s\n", value);
+ }
+
+ return 0;
+}
+
+static int load_hide_tasks(TraceViewStore *store,
+ struct tracecmd_xml_handle *handle,
+ struct tracecmd_xml_system_node *node)
+{
+ struct tracecmd_xml_system_node *child;
+ const char *name;
+ const char *value;
+
+ child = tracecmd_xml_node_child(node);
+ name = tracecmd_xml_node_type(child);
+ if (strcmp(name, "FilterType") == 0) {
+ value = tracecmd_xml_node_value(handle, child);
+ printf("value = %s\n", value);
+ }
+
+ return 0;
+}
+
+int trace_view_load_filters(struct tracecmd_xml_handle *handle,
+ GtkTreeView *trace_tree)
+{
+ struct tracecmd_xml_system *system;
+ struct tracecmd_xml_system_node *syschild;
+ GtkTreeModel *model;
+ TraceViewStore *store;
+ const char *name;
+
+ model = gtk_tree_view_get_model(trace_tree);
+ if (!model)
+ return -1;
+
+ store = TRACE_VIEW_STORE(model);
+
+ system = tracecmd_xml_find_system(handle, "TraceView");
+ if (!system)
+ return -1;
+
+ syschild = tracecmd_xml_system_node(system);
+ if (!syschild)
+ goto out_free_sys;
+
+ do {
+ name = tracecmd_xml_node_type(syschild);
+
+ if (strcmp(name, "EventFilter") == 0)
+ load_event_filter(store, handle, syschild);
+
+ else if (strcmp(name, "TaskFilter") == 0)
+ load_task_filter(store, handle, syschild);
+
+ else if (strcmp(name, "HideTasks") == 0)
+ load_hide_tasks(store, handle, syschild);
+
+ syschild = tracecmd_xml_node_next(syschild);
+ } while (syschild);
+
+ tracecmd_xml_free_system(system);
+
+ update_rows(trace_tree, store);
+ return 0;
+
+ out_free_sys:
+ tracecmd_xml_free_system(system);
+ return -1;
+}
diff --git a/trace-view.h b/trace-view.h
index 5ad33bf..81dac6f 100644
--- a/trace-view.h
+++ b/trace-view.h
@@ -68,5 +68,7 @@ gint trace_view_get_selected_row(GtkWidget *treeview);
int trace_view_save_filters(struct tracecmd_xml_handle *handle,
GtkTreeView *treeview);
+int trace_view_load_filters(struct tracecmd_xml_handle *handle,
+ GtkTreeView *treeview);
#endif /* _TRACE_VIEW_H */
diff --git a/trace-xml.c b/trace-xml.c
index 0bc130c..47cb3c9 100644
--- a/trace-xml.c
+++ b/trace-xml.c
@@ -25,13 +25,20 @@
#include
#include
-#include
+#include
#include "trace-cmd.h"
#include "trace-xml.h"
struct tracecmd_xml_handle {
xmlTextWriterPtr writer;
+ xmlDocPtr doc;
+};
+
+struct tracecmd_xml_system {
+ struct tracecmd_xml_handle *handle;
+ xmlXPathObjectPtr result;
+ xmlNodePtr cur;
};
#define TRACE_ENCODING "UTF-8"
@@ -122,6 +129,101 @@ void tracecmd_xml_close(struct tracecmd_xml_handle *handle)
xmlTextWriterEndDocument(handle->writer);
xmlFreeTextWriter(handle->writer);
}
+ if (handle->doc) {
+ xmlFreeDoc(handle->doc);
+ }
+ free(handle);
+}
+
+/***********************************************************/
+/*** Reading XML files ***/
+/***********************************************************/
+
+
+struct tracecmd_xml_handle *tracecmd_xml_open(const char *file)
+{
+ struct tracecmd_xml_handle *handle;
+ handle = malloc_or_die(sizeof(*handle));
+ memset(handle, 0, sizeof(*handle));
+
+ handle->doc = xmlParseFile(file);
+ if (!handle->doc)
+ goto fail_free;
+
+ return handle;
+
+ fail_free:
free(handle);
+ return NULL;
+}
+
+struct tracecmd_xml_system *
+tracecmd_xml_find_system(struct tracecmd_xml_handle *handle,
+ const char *system)
+{
+ struct tracecmd_xml_system *sys;
+ xmlXPathContextPtr context;
+ xmlXPathObjectPtr result;
+ xmlChar *xpath;
+ char *path;
+
+ path = malloc_or_die(strlen(system) + 3);
+ sprintf(path, "//%s", system);
+ xpath = BAD_CAST path;
+
+ context = xmlXPathNewContext(handle->doc);
+ result = xmlXPathEvalExpression(xpath, context);
+ free(path);
+
+ if (xmlXPathNodeSetIsEmpty(result->nodesetval)) {
+ xmlXPathFreeObject(result);
+ return NULL;
+ }
+
+ sys = malloc_or_die(sizeof(*sys));
+ sys->handle = handle;
+ sys->result = result;
+ sys->cur = result->nodesetval->nodeTab[0]->xmlChildrenNode;
+
+ return sys;
+}
+
+struct tracecmd_xml_system_node *
+tracecmd_xml_system_node(struct tracecmd_xml_system *system)
+{
+ return (struct tracecmd_xml_system_node *)system->cur;
+}
+
+const char *tracecmd_xml_node_type(struct tracecmd_xml_system_node *tnode)
+{
+ xmlNodePtr node = (xmlNodePtr)tnode;
+ return (const char *)node->name;
+}
+
+struct tracecmd_xml_system_node *
+tracecmd_xml_node_child(struct tracecmd_xml_system_node *tnode)
+{
+ xmlNodePtr node = (xmlNodePtr)tnode;
+ return (struct tracecmd_xml_system_node *)node->xmlChildrenNode;
+}
+
+struct tracecmd_xml_system_node *
+tracecmd_xml_node_next(struct tracecmd_xml_system_node *tnode)
+{
+ xmlNodePtr node = (xmlNodePtr)tnode;
+ return (struct tracecmd_xml_system_node *)node->next;
+}
+
+const char *tracecmd_xml_node_value(struct tracecmd_xml_handle *handle,
+ struct tracecmd_xml_system_node *tnode)
+{
+ xmlNodePtr node = (xmlNodePtr)tnode;
+ return (const char *)xmlNodeListGetString(handle->doc, node->xmlChildrenNode, 1);
+}
+
+void tracecmd_xml_free_system(struct tracecmd_xml_system *system)
+{
+ xmlXPathFreeObject(system->result);
+ free(system);
}
diff --git a/trace-xml.h b/trace-xml.h
index 41f6193..4006538 100644
--- a/trace-xml.h
+++ b/trace-xml.h
@@ -22,8 +22,11 @@
#define __TRACE_XML_H
struct tracecmd_xml_handle;
+struct tacecmd_xml_system;
+struct tacecmd_xml_system_node;
struct tracecmd_xml_handle *tracecmd_xml_create(const char *name);
+struct tracecmd_xml_handle *tracecmd_xml_open(const char *name);
void tracecmd_xml_close(struct tracecmd_xml_handle *handle);
int tracecmd_xml_start_system(struct tracecmd_xml_handle *handle,
@@ -38,4 +41,20 @@ int tracecmd_xml_write_element(struct tracecmd_xml_handle *handle,
const char *obj,
const char *fmt, ...);
+struct tracecmd_xml_handle *tracecmd_xml_open(const char *file);
+
+struct tracecmd_xml_system *
+tracecmd_xml_find_system(struct tracecmd_xml_handle *handle,
+ const char *system);
+void tracecmd_xml_free_system(struct tracecmd_xml_system *system);
+struct tracecmd_xml_system_node *
+tracecmd_xml_system_node(struct tracecmd_xml_system *system);
+const char *tracecmd_xml_node_type(struct tracecmd_xml_system_node *tnode);
+struct tracecmd_xml_system_node *
+tracecmd_xml_node_child(struct tracecmd_xml_system_node *tnode);
+struct tracecmd_xml_system_node *
+tracecmd_xml_node_next(struct tracecmd_xml_system_node *tnode);
+const char *tracecmd_xml_node_value(struct tracecmd_xml_handle *handle,
+ struct tracecmd_xml_system_node *tnode);
+
#endif /* __TRACE_XML_H */
--
cgit v1.2.2
From 81b404df1d425f146527dc3da253365071e68bea Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Mon, 5 Apr 2010 17:28:12 -0400
Subject: trace-view: Add pop-up task menu for filtering tasks
Add pop-up menu over the rows that will allow to filter on tasks
in trace-view.
Signed-off-by: Steven Rostedt
---
trace-view-main.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 214 insertions(+), 13 deletions(-)
diff --git a/trace-view-main.c b/trace-view-main.c
index 22b9e32..74922fb 100644
--- a/trace-view-main.c
+++ b/trace-view-main.c
@@ -30,6 +30,7 @@
#include "trace-view.h"
#include "trace-xml.h"
#include "trace-gui.h"
+#include "trace-compat.h"
#define version "0.1.1"
@@ -40,8 +41,13 @@
static char *input_file;
struct trace_tree_info {
- GtkWidget *trace_tree;
- GtkWidget *spin;
+ struct tracecmd_input *handle;
+ GtkWidget *trace_tree;
+ GtkWidget *spin;
+ gint filter_enabled;
+ gint filter_task_selected;
+ struct filter_task *task_filter;
+ struct filter_task *hide_tasks;
};
void usage(char *prog)
@@ -68,6 +74,7 @@ load_clicked (gpointer data)
trace_view_reload(info->trace_tree, handle, info->spin);
/* Free handle when freeing the trace tree */
tracecmd_close(handle);
+ info->handle = handle;
}
g_free(filename);
}
@@ -203,24 +210,209 @@ cpus_clicked (gpointer data)
trace_view_cpu_filter_callback, trace_tree);
}
-#if 0
-static GtkTreeModel *
-create_combo_box_model(void)
+static void
+filter_list_clicked (gpointer data)
+{
+ struct trace_tree_info *info = data;
+
+ if (!filter_task_count(info->task_filter) &&
+ !filter_task_count(info->hide_tasks))
+ return;
+
+ info->filter_enabled ^= 1;
+
+ if (info->filter_enabled)
+ trace_view_update_filters(info->trace_tree,
+ info->task_filter,
+ info->hide_tasks);
+ else
+ trace_view_update_filters(info->trace_tree, NULL, NULL);
+}
+
+static void update_task_filter(struct trace_tree_info *info,
+ struct filter_task *filter)
+{
+ struct filter_task_item *task;
+ gint pid = info->filter_task_selected;
+
+ task = filter_task_find_pid(filter, pid);
+
+ if (task)
+ filter_task_remove_pid(filter, pid);
+ else
+ filter_task_add_pid(filter, pid);
+
+ if (info->filter_enabled)
+ trace_view_update_filters(info->trace_tree,
+ info->task_filter,
+ info->hide_tasks);
+}
+
+static void filter_add_task_clicked(gpointer data)
+{
+ struct trace_tree_info *info = data;
+
+ update_task_filter(info, info->task_filter);
+}
+
+static void filter_hide_task_clicked(gpointer data)
{
- GtkListStore *store;
- GtkTreeIter iter;
+ struct trace_tree_info *info = data;
- store = gtk_list_store_new(1, G_TYPE_STRING);
- gtk_list_store_append(store, &iter);
- gtk_list_store_set(store, &iter, 0, "1", -1);
+ update_task_filter(info, info->hide_tasks);
+}
+
+static void
+filter_clear_tasks_clicked (gpointer data)
+{
+ struct trace_tree_info *info = data;
- return GTK_TREE_MODEL(store);
+ trace_view_update_filters(info->trace_tree, NULL, NULL);
+ info->filter_enabled = 0;
+}
+
+static gboolean
+do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+ struct trace_tree_info *info = data;
+ static GtkWidget *menu;
+ static GtkWidget *menu_filter_enable;
+ static GtkWidget *menu_filter_add_task;
+ static GtkWidget *menu_filter_hide_task;
+ static GtkWidget *menu_filter_clear_tasks;
+ struct pevent *pevent;
+ struct record *record;
+ TraceViewRecord *vrec;
+ GtkTreeModel *model;
+ const char *comm;
+ gchar *text;
+ gint pid;
+ gint len;
+ guint64 offset;
+ gint row;
+ gint cpu;
+
+ if (!menu) {
+ menu = gtk_menu_new();
+
+ menu_filter_enable = gtk_menu_item_new_with_label("Enable Filter");
+ gtk_widget_show(menu_filter_enable);
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_enable);
+
+ g_signal_connect_swapped (G_OBJECT (menu_filter_enable), "activate",
+ G_CALLBACK (filter_list_clicked),
+ data);
+
+ menu_filter_add_task = gtk_menu_item_new_with_label("Add Task");
+ gtk_widget_show(menu_filter_add_task);
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_add_task);
+
+ g_signal_connect_swapped (G_OBJECT (menu_filter_add_task), "activate",
+ G_CALLBACK (filter_add_task_clicked),
+ data);
+
+ menu_filter_hide_task = gtk_menu_item_new_with_label("Hide Task");
+ gtk_widget_show(menu_filter_hide_task);
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_hide_task);
+
+ g_signal_connect_swapped (G_OBJECT (menu_filter_hide_task), "activate",
+ G_CALLBACK (filter_hide_task_clicked),
+ data);
+
+ menu_filter_clear_tasks = gtk_menu_item_new_with_label("Clear Task Filter");
+ gtk_widget_show(menu_filter_clear_tasks);
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_clear_tasks);
+
+ g_signal_connect_swapped (G_OBJECT (menu_filter_clear_tasks), "activate",
+ G_CALLBACK (filter_clear_tasks_clicked),
+ data);
+
+ }
+
+ row = trace_view_get_selected_row(GTK_WIDGET(info->trace_tree));
+ if (row >= 0) {
+
+ model = gtk_tree_view_get_model(GTK_TREE_VIEW(info->trace_tree));
+ vrec = trace_view_store_get_row(TRACE_VIEW_STORE(model), row);
+ offset = vrec->offset;
+
+ record = tracecmd_read_at(info->handle, offset, &cpu);
+
+ if (record) {
+ pevent = tracecmd_get_pevent(info->handle);
+ pid = pevent_data_pid(pevent, record);
+ comm = pevent_data_comm_from_pid(pevent, pid);
+
+ len = strlen(comm) + 50;
+
+ text = g_malloc(len);
+ g_assert(text);
+
+ if (filter_task_find_pid(info->task_filter, pid))
+ snprintf(text, len, "Remove %s-%d to filter", comm, pid);
+ else
+ snprintf(text, len, "Add %s-%d to filter", comm, pid);
+
+ info->filter_task_selected = pid;
+
+ gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_add_task),
+ text);
+
+ if (filter_task_find_pid(info->hide_tasks, pid))
+ snprintf(text, len, "Show %s-%d", comm, pid);
+ else
+ snprintf(text, len, "Hide %s-%d", comm, pid);
+
+ gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_hide_task),
+ text);
+
+ g_free(text);
+
+ info->filter_task_selected = pid;
+
+ gtk_widget_show(menu_filter_add_task);
+ gtk_widget_show(menu_filter_hide_task);
+ free_record(record);
+ }
+ } else {
+ gtk_widget_hide(menu_filter_add_task);
+ gtk_widget_hide(menu_filter_hide_task);
+ }
+
+ if (info->filter_enabled)
+ gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_enable),
+ "Disable List Filter");
+ else
+ gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_enable),
+ "Enable List Filter");
+
+ if (filter_task_count(info->task_filter) ||
+ filter_task_count(info->hide_tasks)) {
+ gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE);
+ gtk_widget_set_sensitive(menu_filter_enable, TRUE);
+ } else {
+ gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE);
+ gtk_widget_set_sensitive(menu_filter_enable, FALSE);
+ }
+
+ gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3,
+ gtk_get_current_event_time());
+
+ return TRUE;
+}
+
+static gboolean
+button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+ if (event->button == 3)
+ return do_tree_popup(widget, event, data);
+
+ return FALSE;
}
-#endif
void trace_view(int argc, char **argv)
{
- static struct tracecmd_input *handle;
+ static struct tracecmd_input *handle = NULL;
struct trace_tree_info tree_info;
struct stat st;
GtkWidget *trace_tree;
@@ -268,6 +460,11 @@ void trace_view(int argc, char **argv)
if (input_file)
handle = tracecmd_open(input_file);
+ memset(&tree_info, 0, sizeof(tree_info));
+ tree_info.handle = handle;
+ tree_info.task_filter = filter_task_hash_alloc();
+ tree_info.hide_tasks = filter_task_hash_alloc();
+
/* --- Main window --- */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
@@ -455,6 +652,10 @@ void trace_view(int argc, char **argv)
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
gtk_widget_show(label);
+ gtk_signal_connect(GTK_OBJECT(trace_tree), "button_press_event",
+ (GtkSignalFunc) button_press_event,
+ (gpointer) &tree_info);
+
trace_view_search_setup(GTK_BOX(hbox), GTK_TREE_VIEW(trace_tree));
/* --- Top Level Hbox --- */
--
cgit v1.2.2
From 64be78aa61dfda0c5fdf5c7ccfc2d9a93ba52aa5 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Mon, 5 Apr 2010 20:56:05 -0400
Subject: trace-view: Add save and load of task filters
Include saving of the task filters to the filter file as well as
the ability to load them.
Signed-off-by: Steven Rostedt
---
trace-filter.c | 43 ++++++++++++++++++++++++++++++++++++++++++
trace-filter.h | 3 +++
trace-hash.c | 27 +++++++++++++++++++++++++++
trace-hash.h | 1 +
trace-view-main.c | 6 ++++--
trace-view.c | 56 ++++++++++++-------------------------------------------
trace-view.h | 8 ++++++--
7 files changed, 96 insertions(+), 48 deletions(-)
diff --git a/trace-filter.c b/trace-filter.c
index efdb5fa..b6035ad 100644
--- a/trace-filter.c
+++ b/trace-filter.c
@@ -2207,6 +2207,21 @@ int trace_filter_save_events(struct tracecmd_xml_handle *handle,
int trace_filter_save_tasks(struct tracecmd_xml_handle *handle,
struct filter_task *filter)
{
+ char buffer[100];
+ int *pids;
+ int i;
+
+ pids = filter_task_pids(filter);
+ if (!pids)
+ return -1;
+
+ for (i = 0; pids[i] >= 0; i++) {
+ snprintf(buffer, 100, "%d", pids[i]);
+ tracecmd_xml_write_element(handle, "Task", buffer);
+ }
+
+ free(pids);
+
return 0;
}
@@ -2284,3 +2299,31 @@ int trace_filter_load_events(struct event_filter *event_filter,
return 0;
}
+
+int trace_filter_load_task_filter(struct filter_task *filter,
+ struct tracecmd_xml_handle *handle,
+ struct tracecmd_xml_system_node *node)
+{
+ const char *name;
+ const char *task;
+ int pid;
+
+ if (!filter)
+ return 0;
+
+ node = tracecmd_xml_node_child(node);
+
+ while (node) {
+ name = tracecmd_xml_node_type(node);
+
+ if (strcmp(name, "Task") == 0) {
+ task = tracecmd_xml_node_value(handle, node);
+ pid = atoi(task);
+ if (!filter_task_find_pid(filter, pid))
+ filter_task_add_pid(filter, pid);
+ }
+ node = tracecmd_xml_node_next(node);
+ }
+
+ return 0;
+}
diff --git a/trace-filter.h b/trace-filter.h
index 915b174..fd60bce 100644
--- a/trace-filter.h
+++ b/trace-filter.h
@@ -145,6 +145,9 @@ int trace_filter_save_tasks(struct tracecmd_xml_handle *handle,
int trace_filter_load_events(struct event_filter *event_filter,
struct tracecmd_xml_handle *handle,
struct tracecmd_xml_system_node *node);
+int trace_filter_load_task_filter(struct filter_task *filter,
+ struct tracecmd_xml_handle *handle,
+ struct tracecmd_xml_system_node *node);
/* put here because there's no other place */
diff --git a/trace-hash.c b/trace-hash.c
index 1197913..3349715 100644
--- a/trace-hash.c
+++ b/trace-hash.c
@@ -19,6 +19,7 @@
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#include
+#include
#include
#include
@@ -155,3 +156,29 @@ struct filter_task *filter_task_hash_copy(struct filter_task *hash)
return new_hash;
}
+
+int *filter_task_pids(struct filter_task *hash)
+{
+ struct filter_task_item *task;
+ int *pids;
+ int count = 0;
+ int i;
+
+ if (!hash->count)
+ return NULL;
+
+ pids = malloc(sizeof(*pids) * (hash->count + 1));
+ if (!pids)
+ return NULL;
+
+ for (i = 0; i < FILTER_TASK_HASH_SIZE; i++) {
+ task = hash->hash[i];
+ while (task) {
+ pids[count++] = task->pid;
+ task = task->next;
+ }
+ }
+ pids[count] = -1;
+
+ return pids;
+}
diff --git a/trace-hash.h b/trace-hash.h
index 1aaa828..29088e7 100644
--- a/trace-hash.h
+++ b/trace-hash.h
@@ -42,6 +42,7 @@ void filter_task_clear(struct filter_task *hash);
struct filter_task *filter_task_hash_alloc(void);
void filter_task_hash_free(struct filter_task *hash);
struct filter_task *filter_task_hash_copy(struct filter_task *hash);
+int *filter_task_pids(struct filter_task *hash);
static inline gint filter_task_count(struct filter_task *hash)
{
diff --git a/trace-view-main.c b/trace-view-main.c
index 74922fb..af9dc5d 100644
--- a/trace-view-main.c
+++ b/trace-view-main.c
@@ -97,7 +97,8 @@ load_filters_clicked (gpointer data)
warning("Could not open %s", filename);
g_free(filename);
- trace_view_load_filters(handle, trace_tree);
+ trace_view_load_filters(handle, trace_tree, info->task_filter,
+ info->hide_tasks);
tracecmd_xml_close(handle);
}
@@ -120,7 +121,8 @@ save_filters_clicked (gpointer data)
warning("Could not create %s", filename);
g_free(filename);
- trace_view_save_filters(handle, trace_tree);
+ trace_view_save_filters(handle, trace_tree,
+ info->task_filter, info->hide_tasks);
tracecmd_xml_close(handle);
}
diff --git a/trace-view.c b/trace-view.c
index 094f226..c1ce4ff 100644
--- a/trace-view.c
+++ b/trace-view.c
@@ -873,7 +873,9 @@ void trace_view_search_setup(GtkBox *box, GtkTreeView *treeview)
}
int trace_view_save_filters(struct tracecmd_xml_handle *handle,
- GtkTreeView *trace_tree)
+ GtkTreeView *trace_tree,
+ struct filter_task *task_filter,
+ struct filter_task *hide_tasks)
{
struct event_filter *event_filter;
GtkTreeModel *model;
@@ -902,15 +904,15 @@ int trace_view_save_filters(struct tracecmd_xml_handle *handle,
tracecmd_xml_end_sub_system(handle);
- if (store->task_filter) {
+ if (task_filter && filter_task_count(task_filter)) {
tracecmd_xml_start_sub_system(handle, "TaskFilter");
- trace_filter_save_tasks(handle, store->task_filter);
+ trace_filter_save_tasks(handle, task_filter);
tracecmd_xml_end_sub_system(handle);
}
- if (store->hide_tasks) {
+ if (hide_tasks && filter_task_count(hide_tasks)) {
tracecmd_xml_start_sub_system(handle, "HideTasks");
- trace_filter_save_tasks(handle, store->hide_tasks);
+ trace_filter_save_tasks(handle, hide_tasks);
tracecmd_xml_end_sub_system(handle);
}
@@ -951,44 +953,10 @@ static int load_event_filter(TraceViewStore *store,
return 0;
}
-static int load_task_filter(TraceViewStore *store,
- struct tracecmd_xml_handle *handle,
- struct tracecmd_xml_system_node *node)
-{
- struct tracecmd_xml_system_node *child;
- const char *name;
- const char *value;
-
- child = tracecmd_xml_node_child(node);
- name = tracecmd_xml_node_type(child);
- if (strcmp(name, "FilterType") == 0) {
- value = tracecmd_xml_node_value(handle, child);
- printf("value = %s\n", value);
- }
-
- return 0;
-}
-
-static int load_hide_tasks(TraceViewStore *store,
- struct tracecmd_xml_handle *handle,
- struct tracecmd_xml_system_node *node)
-{
- struct tracecmd_xml_system_node *child;
- const char *name;
- const char *value;
-
- child = tracecmd_xml_node_child(node);
- name = tracecmd_xml_node_type(child);
- if (strcmp(name, "FilterType") == 0) {
- value = tracecmd_xml_node_value(handle, child);
- printf("value = %s\n", value);
- }
-
- return 0;
-}
-
int trace_view_load_filters(struct tracecmd_xml_handle *handle,
- GtkTreeView *trace_tree)
+ GtkTreeView *trace_tree,
+ struct filter_task *task_filter,
+ struct filter_task *hide_tasks)
{
struct tracecmd_xml_system *system;
struct tracecmd_xml_system_node *syschild;
@@ -1017,10 +985,10 @@ int trace_view_load_filters(struct tracecmd_xml_handle *handle,
load_event_filter(store, handle, syschild);
else if (strcmp(name, "TaskFilter") == 0)
- load_task_filter(store, handle, syschild);
+ trace_filter_load_task_filter(task_filter, handle, syschild);
else if (strcmp(name, "HideTasks") == 0)
- load_hide_tasks(store, handle, syschild);
+ trace_filter_load_task_filter(hide_tasks, handle, syschild);
syschild = tracecmd_xml_node_next(syschild);
} while (syschild);
diff --git a/trace-view.h b/trace-view.h
index 81dac6f..b0ba7ed 100644
--- a/trace-view.h
+++ b/trace-view.h
@@ -67,8 +67,12 @@ void trace_view_search_setup(GtkBox *box, GtkTreeView *treeview);
gint trace_view_get_selected_row(GtkWidget *treeview);
int trace_view_save_filters(struct tracecmd_xml_handle *handle,
- GtkTreeView *treeview);
+ GtkTreeView *treeview,
+ struct filter_task *task_filter,
+ struct filter_task *hide_tasks);
int trace_view_load_filters(struct tracecmd_xml_handle *handle,
- GtkTreeView *treeview);
+ GtkTreeView *treeview,
+ struct filter_task *task_filter,
+ struct filter_task *hide_tasks);
#endif /* _TRACE_VIEW_H */
--
cgit v1.2.2
From 38b92d6b993327de864ef7182cebe530abc5f5c7 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Mon, 5 Apr 2010 21:30:53 -0400
Subject: trace-graph: Add loading and saving of task and event filters
Add the filter loading and saving to trace-graph. Most of the work
was done already to get trace-view working. This just hooks into
that framework.
Signed-off-by: Steven Rostedt
---
trace-graph-main.c | 73 ++++++++++++++++++++++++++++++++
trace-graph.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++
trace-graph.h | 6 +++
3 files changed, 198 insertions(+)
diff --git a/trace-graph-main.c b/trace-graph-main.c
index 303f342..4a9fed1 100644
--- a/trace-graph-main.c
+++ b/trace-graph-main.c
@@ -152,6 +152,50 @@ plot_tasks_clicked (gpointer data)
free(selected);
}
+/* Callback for the clicked signal of the Load Filters button */
+static void
+load_filters_clicked (gpointer data)
+{
+ struct graph_info *ginfo = data;
+ struct tracecmd_xml_handle *handle;
+ gchar *filename;
+
+ filename = trace_get_file_dialog("Load Filters");
+ if (!filename)
+ return;
+
+ handle = tracecmd_xml_open(filename);
+ if (!handle)
+ warning("Could not open %s", filename);
+ g_free(filename);
+
+ trace_graph_load_filters(ginfo, handle);
+
+ tracecmd_xml_close(handle);
+}
+
+/* Callback for the clicked signal of the Save Filters button */
+static void
+save_filters_clicked (gpointer data)
+{
+ struct graph_info *ginfo = data;
+ struct tracecmd_xml_handle *handle;
+ gchar *filename;
+
+ filename = trace_get_file_dialog("Save Filters");
+ if (!filename)
+ return;
+
+ handle = tracecmd_xml_create(filename);
+ if (!handle)
+ warning("Could not create %s", filename);
+ g_free(filename);
+
+ trace_graph_save_filters(ginfo, handle);
+
+ tracecmd_xml_close(handle);
+}
+
void trace_graph(int argc, char **argv)
{
struct tracecmd_input *handle = NULL;
@@ -247,6 +291,35 @@ void trace_graph(int argc, char **argv)
gtk_widget_show(sub_item);
+ /* --- File - Load Filter Option --- */
+
+ sub_item = gtk_menu_item_new_with_label("Load filters");
+
+ /* Add them to the menu */
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
+
+ g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
+ G_CALLBACK (load_filters_clicked),
+ (gpointer) ginfo);
+
+ /* We do need to show menu items */
+ gtk_widget_show(sub_item);
+
+
+ /* --- File - Save Filter Option --- */
+
+ sub_item = gtk_menu_item_new_with_label("Save filters");
+
+ /* Add them to the menu */
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
+
+ g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
+ G_CALLBACK (save_filters_clicked),
+ (gpointer) ginfo);
+
+ /* We do need to show menu items */
+ gtk_widget_show(sub_item);
+
/* --- File - Quit Option --- */
sub_item = gtk_menu_item_new_with_label("Quit");
diff --git a/trace-graph.c b/trace-graph.c
index 6ed7851..9ec3924 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -32,6 +32,8 @@
#include "trace-hash.h"
#include "trace-filter.h"
+#include "version.h"
+
#include "util.h"
#define DEBUG_LEVEL 0
@@ -2395,6 +2397,123 @@ int trace_graph_load_handle(struct graph_info *ginfo,
return 0;
}
+static int load_event_filter(struct graph_info *ginfo,
+ struct tracecmd_xml_handle *handle,
+ struct tracecmd_xml_system_node *node)
+{
+ struct tracecmd_xml_system_node *child;
+ struct event_filter *event_filter;
+ const char *name;
+ const char *value;
+
+ event_filter = ginfo->event_filter;
+
+ child = tracecmd_xml_node_child(node);
+ name = tracecmd_xml_node_type(child);
+ if (strcmp(name, "FilterType") != 0)
+ return -1;
+
+ value = tracecmd_xml_node_value(handle, child);
+ /* Do nothing with all events enabled */
+ if (strcmp(value, "all events") == 0)
+ return 0;
+
+ node = tracecmd_xml_node_next(child);
+ if (!node)
+ return -1;
+
+ pevent_filter_clear_trivial(event_filter, FILTER_TRIVIAL_BOTH);
+ ginfo->all_events = FALSE;
+
+ trace_filter_load_events(event_filter, handle, node);
+
+ return 0;
+}
+
+int trace_graph_load_filters(struct graph_info *ginfo,
+ struct tracecmd_xml_handle *handle)
+{
+ struct tracecmd_xml_system *system;
+ struct tracecmd_xml_system_node *syschild;
+ const char *name;
+
+ system = tracecmd_xml_find_system(handle, "TraceGraph");
+ if (!system)
+ return -1;
+
+ syschild = tracecmd_xml_system_node(system);
+ if (!syschild)
+ goto out_free_sys;
+
+ do {
+ name = tracecmd_xml_node_type(syschild);
+
+ if (strcmp(name, "EventFilter") == 0)
+ load_event_filter(ginfo, handle, syschild);
+
+ else if (strcmp(name, "TaskFilter") == 0)
+ trace_filter_load_task_filter(ginfo->task_filter, handle, syschild);
+
+ else if (strcmp(name, "HideTasks") == 0)
+ trace_filter_load_task_filter(ginfo->hide_tasks, handle, syschild);
+
+ syschild = tracecmd_xml_node_next(syschild);
+ } while (syschild);
+
+ if (filter_task_count(ginfo->task_filter) ||
+ filter_task_count(ginfo->hide_tasks))
+ ginfo->filter_available = 1;
+ else
+ ginfo->filter_available = 0;
+
+ tracecmd_xml_free_system(system);
+
+ trace_graph_refresh(ginfo);
+
+ return 0;
+
+ out_free_sys:
+ tracecmd_xml_free_system(system);
+ return -1;
+}
+
+int trace_graph_save_filters(struct graph_info *ginfo,
+ struct tracecmd_xml_handle *handle)
+{
+ struct event_filter *event_filter;
+
+ tracecmd_xml_start_system(handle, "TraceGraph", VERSION_STRING);
+
+ event_filter = ginfo->event_filter;
+
+ tracecmd_xml_start_sub_system(handle, "EventFilter");
+
+ if (ginfo->all_events || !event_filter)
+ tracecmd_xml_write_element(handle, "FilterType", "all events");
+ else {
+ tracecmd_xml_write_element(handle, "FilterType", "filter");
+ trace_filter_save_events(handle, event_filter);
+ }
+
+ tracecmd_xml_end_sub_system(handle);
+
+ if (ginfo->task_filter && filter_task_count(ginfo->task_filter)) {
+ tracecmd_xml_start_sub_system(handle, "TaskFilter");
+ trace_filter_save_tasks(handle, ginfo->task_filter);
+ tracecmd_xml_end_sub_system(handle);
+ }
+
+ if (ginfo->hide_tasks && filter_task_count(ginfo->hide_tasks)) {
+ tracecmd_xml_start_sub_system(handle, "HideTasks");
+ trace_filter_save_tasks(handle, ginfo->hide_tasks);
+ tracecmd_xml_end_sub_system(handle);
+ }
+
+ tracecmd_xml_end_system(handle);
+
+ return 0;
+}
+
struct graph_info *
trace_graph_create_with_callbacks(struct tracecmd_input *handle,
struct graph_callbacks *cbs)
diff --git a/trace-graph.h b/trace-graph.h
index 91ae161..916ad50 100644
--- a/trace-graph.h
+++ b/trace-graph.h
@@ -24,6 +24,7 @@
#include
#include "trace-cmd.h"
#include "trace-hash.h"
+#include "trace-xml.h"
struct graph_info;
@@ -306,6 +307,11 @@ void trace_graph_copy_filter(struct graph_info *ginfo,
struct event_filter *event_filter);
gint *trace_graph_task_list(struct graph_info *ginfo);
+int trace_graph_load_filters(struct graph_info *ginfo,
+ struct tracecmd_xml_handle *handle);
+int trace_graph_save_filters(struct graph_info *ginfo,
+ struct tracecmd_xml_handle *handle);
+
/* plots */
void trace_graph_plot_free(struct graph_info *ginfo);
void trace_graph_plot_init(struct graph_info *ginfo);
--
cgit v1.2.2
From 338a694c0002d70349de3f0e7e47322467f72765 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Mon, 5 Apr 2010 21:43:43 -0400
Subject: kernelshark: Add loading and saving of filters
Hooked to the trace-view and trace-graph code to load and save
event and task filters.
Signed-off-by: Steven Rostedt
---
kernel-shark.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 89 insertions(+)
diff --git a/kernel-shark.c b/kernel-shark.c
index d913ae0..7bc80fe 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -158,6 +158,66 @@ load_clicked (gpointer data)
g_free(filename);
}
+/* Callback for the clicked signal of the Load Filters button */
+static void
+load_filters_clicked (gpointer data)
+{
+ struct shark_info *info = data;
+ struct graph_info *ginfo = info->ginfo;
+ GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview);
+ struct tracecmd_xml_handle *handle;
+ gchar *filename;
+
+ filename = trace_get_file_dialog("Load Filters");
+ if (!filename)
+ return;
+
+ handle = tracecmd_xml_open(filename);
+ if (!handle)
+ warning("Could not open %s", filename);
+ g_free(filename);
+
+ /*
+ * Just in case we are loading only a tree view filter,
+ * we will load the task filters for the tree view first.
+ * Then we load the graph next, and if the graph has
+ * trace filters, than those will override them.
+ */
+ trace_view_load_filters(handle, trace_tree,
+ ginfo->task_filter,
+ ginfo->hide_tasks);
+ trace_graph_load_filters(ginfo, handle);
+
+ tracecmd_xml_close(handle);
+}
+
+/* Callback for the clicked signal of the Save Filters button */
+static void
+save_filters_clicked (gpointer data)
+{
+ struct shark_info *info = data;
+ struct graph_info *ginfo = info->ginfo;
+ struct tracecmd_xml_handle *handle;
+ GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview);
+ gchar *filename;
+
+ filename = trace_get_file_dialog("Save Filters");
+ if (!filename)
+ return;
+
+ handle = tracecmd_xml_create(filename);
+ if (!handle)
+ warning("Could not create %s", filename);
+ g_free(filename);
+
+ trace_view_save_filters(handle, trace_tree,
+ ginfo->task_filter, ginfo->hide_tasks);
+
+ trace_graph_save_filters(ginfo, handle);
+
+ tracecmd_xml_close(handle);
+}
+
/* Callback for the clicked signal of the Exit button */
static void
exit_clicked (gpointer data)
@@ -769,6 +829,35 @@ void kernel_shark(int argc, char **argv)
gtk_widget_show(sub_item);
+ /* --- File - Load Filter Option --- */
+
+ sub_item = gtk_menu_item_new_with_label("Load filters");
+
+ /* Add them to the menu */
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
+
+ g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
+ G_CALLBACK (load_filters_clicked),
+ (gpointer) info);
+
+ /* We do need to show menu items */
+ gtk_widget_show(sub_item);
+
+
+ /* --- File - Save Filter Option --- */
+
+ sub_item = gtk_menu_item_new_with_label("Save filters");
+
+ /* Add them to the menu */
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
+
+ g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
+ G_CALLBACK (save_filters_clicked),
+ (gpointer) info);
+
+ /* We do need to show menu items */
+ gtk_widget_show(sub_item);
+
/* --- File - Quit Option --- */
sub_item = gtk_menu_item_new_with_label("Quit");
--
cgit v1.2.2
From 20359fdc358744dee36b8e59c234e965fc7d2a69 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Mon, 5 Apr 2010 22:40:54 -0400
Subject: kernelshark: Make all saved filters under KernelShark
Make the xml doc under ... for trace-view
and trace-graph. Also pull out the task filters since the view
and graph in kernelshark share the same filters.
Signed-off-by: Steven Rostedt
---
kernel-shark.c | 21 ++++++++----------
trace-filter.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
trace-filter.h | 6 ++++++
trace-graph-main.c | 10 ++++++++-
trace-graph.c | 31 +++++++++------------------
trace-view-main.c | 19 +++++++++++------
trace-view.c | 29 +++----------------------
trace-view.h | 8 ++-----
trace-xml.c | 15 +++++++------
trace-xml.h | 4 ++--
10 files changed, 125 insertions(+), 80 deletions(-)
diff --git a/kernel-shark.c b/kernel-shark.c
index 7bc80fe..b0f1ecb 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -177,15 +177,10 @@ load_filters_clicked (gpointer data)
warning("Could not open %s", filename);
g_free(filename);
- /*
- * Just in case we are loading only a tree view filter,
- * we will load the task filters for the tree view first.
- * Then we load the graph next, and if the graph has
- * trace filters, than those will override them.
- */
- trace_view_load_filters(handle, trace_tree,
- ginfo->task_filter,
- ginfo->hide_tasks);
+ trace_filter_load_filters(handle, ginfo->task_filter,
+ ginfo->hide_tasks);
+
+ trace_view_load_filters(handle, trace_tree);
trace_graph_load_filters(ginfo, handle);
tracecmd_xml_close(handle);
@@ -205,16 +200,18 @@ save_filters_clicked (gpointer data)
if (!filename)
return;
- handle = tracecmd_xml_create(filename);
+ handle = tracecmd_xml_create(filename, VERSION_STRING);
if (!handle)
warning("Could not create %s", filename);
g_free(filename);
- trace_view_save_filters(handle, trace_tree,
- ginfo->task_filter, ginfo->hide_tasks);
+ trace_view_save_filters(handle, trace_tree);
trace_graph_save_filters(ginfo, handle);
+ trace_filter_save_filters(handle, ginfo->task_filter,
+ ginfo->hide_tasks);
+
tracecmd_xml_close(handle);
}
diff --git a/trace-filter.c b/trace-filter.c
index b6035ad..3f78637 100644
--- a/trace-filter.c
+++ b/trace-filter.c
@@ -2327,3 +2327,65 @@ int trace_filter_load_task_filter(struct filter_task *filter,
return 0;
}
+
+int trace_filter_load_filters(struct tracecmd_xml_handle *handle,
+ struct filter_task *task_filter,
+ struct filter_task *hide_tasks)
+{
+ struct tracecmd_xml_system *system;
+ struct tracecmd_xml_system_node *syschild;
+ const char *name;
+
+ system = tracecmd_xml_find_system(handle, "TraceFilter");
+ if (!system)
+ return -1;
+
+
+ syschild = tracecmd_xml_system_node(system);
+ if (!syschild)
+ goto out_free_sys;
+
+ do {
+ name = tracecmd_xml_node_type(syschild);
+
+ if (strcmp(name, "TaskFilter") == 0)
+ trace_filter_load_task_filter(task_filter, handle, syschild);
+
+ else if (strcmp(name, "HideTasks") == 0)
+ trace_filter_load_task_filter(hide_tasks, handle, syschild);
+
+ syschild = tracecmd_xml_node_next(syschild);
+ } while (syschild);
+
+ tracecmd_xml_free_system(system);
+
+ return 0;
+
+ out_free_sys:
+ tracecmd_xml_free_system(system);
+ return -1;
+}
+
+int trace_filter_save_filters(struct tracecmd_xml_handle *handle,
+ struct filter_task *task_filter,
+ struct filter_task *hide_tasks)
+{
+
+ tracecmd_xml_start_system(handle, "TraceFilter");
+
+ if (task_filter && filter_task_count(task_filter)) {
+ tracecmd_xml_start_sub_system(handle, "TaskFilter");
+ trace_filter_save_tasks(handle, task_filter);
+ tracecmd_xml_end_sub_system(handle);
+ }
+
+ if (hide_tasks && filter_task_count(hide_tasks)) {
+ tracecmd_xml_start_sub_system(handle, "HideTasks");
+ trace_filter_save_tasks(handle, hide_tasks);
+ tracecmd_xml_end_sub_system(handle);
+ }
+
+ tracecmd_xml_end_system(handle);
+
+ return 0;
+}
diff --git a/trace-filter.h b/trace-filter.h
index fd60bce..e0f9f4a 100644
--- a/trace-filter.h
+++ b/trace-filter.h
@@ -148,6 +148,12 @@ int trace_filter_load_events(struct event_filter *event_filter,
int trace_filter_load_task_filter(struct filter_task *filter,
struct tracecmd_xml_handle *handle,
struct tracecmd_xml_system_node *node);
+int trace_filter_load_filters(struct tracecmd_xml_handle *handle,
+ struct filter_task *task_filter,
+ struct filter_task *hide_tasks);
+int trace_filter_save_filters(struct tracecmd_xml_handle *handle,
+ struct filter_task *task_filter,
+ struct filter_task *hide_tasks);
/* put here because there's no other place */
diff --git a/trace-graph-main.c b/trace-graph-main.c
index 4a9fed1..0490a86 100644
--- a/trace-graph-main.c
+++ b/trace-graph-main.c
@@ -31,6 +31,8 @@
#include "trace-filter.h"
#include "trace-gui.h"
+#include "version.h"
+
#define version "0.1.1"
#define TRACE_WIDTH 800
@@ -169,6 +171,9 @@ load_filters_clicked (gpointer data)
warning("Could not open %s", filename);
g_free(filename);
+ trace_filter_load_filters(handle, ginfo->task_filter,
+ ginfo->hide_tasks);
+
trace_graph_load_filters(ginfo, handle);
tracecmd_xml_close(handle);
@@ -186,11 +191,14 @@ save_filters_clicked (gpointer data)
if (!filename)
return;
- handle = tracecmd_xml_create(filename);
+ handle = tracecmd_xml_create(filename, VERSION_STRING);
if (!handle)
warning("Could not create %s", filename);
g_free(filename);
+ trace_filter_save_filters(handle, ginfo->task_filter,
+ ginfo->hide_tasks);
+
trace_graph_save_filters(ginfo, handle);
tracecmd_xml_close(handle);
diff --git a/trace-graph.c b/trace-graph.c
index 9ec3924..e21ee33 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -32,8 +32,6 @@
#include "trace-hash.h"
#include "trace-filter.h"
-#include "version.h"
-
#include "util.h"
#define DEBUG_LEVEL 0
@@ -2437,6 +2435,12 @@ int trace_graph_load_filters(struct graph_info *ginfo,
struct tracecmd_xml_system_node *syschild;
const char *name;
+ if (filter_task_count(ginfo->task_filter) ||
+ filter_task_count(ginfo->hide_tasks))
+ ginfo->filter_available = 1;
+ else
+ ginfo->filter_available = 0;
+
system = tracecmd_xml_find_system(handle, "TraceGraph");
if (!system)
return -1;
@@ -2451,12 +2455,6 @@ int trace_graph_load_filters(struct graph_info *ginfo,
if (strcmp(name, "EventFilter") == 0)
load_event_filter(ginfo, handle, syschild);
- else if (strcmp(name, "TaskFilter") == 0)
- trace_filter_load_task_filter(ginfo->task_filter, handle, syschild);
-
- else if (strcmp(name, "HideTasks") == 0)
- trace_filter_load_task_filter(ginfo->hide_tasks, handle, syschild);
-
syschild = tracecmd_xml_node_next(syschild);
} while (syschild);
@@ -2474,6 +2472,9 @@ int trace_graph_load_filters(struct graph_info *ginfo,
out_free_sys:
tracecmd_xml_free_system(system);
+ if (ginfo->filter_enabled)
+ trace_graph_refresh(ginfo);
+
return -1;
}
@@ -2482,7 +2483,7 @@ int trace_graph_save_filters(struct graph_info *ginfo,
{
struct event_filter *event_filter;
- tracecmd_xml_start_system(handle, "TraceGraph", VERSION_STRING);
+ tracecmd_xml_start_system(handle, "TraceGraph");
event_filter = ginfo->event_filter;
@@ -2497,18 +2498,6 @@ int trace_graph_save_filters(struct graph_info *ginfo,
tracecmd_xml_end_sub_system(handle);
- if (ginfo->task_filter && filter_task_count(ginfo->task_filter)) {
- tracecmd_xml_start_sub_system(handle, "TaskFilter");
- trace_filter_save_tasks(handle, ginfo->task_filter);
- tracecmd_xml_end_sub_system(handle);
- }
-
- if (ginfo->hide_tasks && filter_task_count(ginfo->hide_tasks)) {
- tracecmd_xml_start_sub_system(handle, "HideTasks");
- trace_filter_save_tasks(handle, ginfo->hide_tasks);
- tracecmd_xml_end_sub_system(handle);
- }
-
tracecmd_xml_end_system(handle);
return 0;
diff --git a/trace-view-main.c b/trace-view-main.c
index af9dc5d..e6c0361 100644
--- a/trace-view-main.c
+++ b/trace-view-main.c
@@ -29,9 +29,12 @@
#include "trace-cmd.h"
#include "trace-view.h"
#include "trace-xml.h"
+#include "trace-filter.h"
#include "trace-gui.h"
#include "trace-compat.h"
+#include "version.h"
+
#define version "0.1.1"
#define TRACE_WIDTH 800
@@ -93,12 +96,16 @@ load_filters_clicked (gpointer data)
return;
handle = tracecmd_xml_open(filename);
- if (!handle)
+ if (!handle) {
warning("Could not open %s", filename);
+ return;
+ }
g_free(filename);
- trace_view_load_filters(handle, trace_tree, info->task_filter,
- info->hide_tasks);
+ trace_filter_load_filters(handle, info->task_filter,
+ info->hide_tasks);
+
+ trace_view_load_filters(handle, trace_tree);
tracecmd_xml_close(handle);
}
@@ -116,13 +123,13 @@ save_filters_clicked (gpointer data)
if (!filename)
return;
- handle = tracecmd_xml_create(filename);
+ handle = tracecmd_xml_create(filename, VERSION_STRING);
if (!handle)
warning("Could not create %s", filename);
g_free(filename);
- trace_view_save_filters(handle, trace_tree,
- info->task_filter, info->hide_tasks);
+ trace_filter_save_filters(handle, info->task_filter, info->hide_tasks);
+ trace_view_save_filters(handle, trace_tree);
tracecmd_xml_close(handle);
}
diff --git a/trace-view.c b/trace-view.c
index c1ce4ff..8d121d1 100644
--- a/trace-view.c
+++ b/trace-view.c
@@ -29,7 +29,6 @@
#include "trace-local.h"
#include "trace-view.h"
#include "trace-compat.h"
-#include "version.h"
#include "cpu.h"
#include "util.h"
@@ -873,9 +872,7 @@ void trace_view_search_setup(GtkBox *box, GtkTreeView *treeview)
}
int trace_view_save_filters(struct tracecmd_xml_handle *handle,
- GtkTreeView *trace_tree,
- struct filter_task *task_filter,
- struct filter_task *hide_tasks)
+ GtkTreeView *trace_tree)
{
struct event_filter *event_filter;
GtkTreeModel *model;
@@ -888,7 +885,7 @@ int trace_view_save_filters(struct tracecmd_xml_handle *handle,
store = TRACE_VIEW_STORE(model);
- tracecmd_xml_start_system(handle, "TraceView", VERSION_STRING);
+ tracecmd_xml_start_system(handle, "TraceView");
all_events = trace_view_store_get_all_events_enabled(store);
event_filter = trace_view_store_get_event_filter(store);
@@ -904,18 +901,6 @@ int trace_view_save_filters(struct tracecmd_xml_handle *handle,
tracecmd_xml_end_sub_system(handle);
- if (task_filter && filter_task_count(task_filter)) {
- tracecmd_xml_start_sub_system(handle, "TaskFilter");
- trace_filter_save_tasks(handle, task_filter);
- tracecmd_xml_end_sub_system(handle);
- }
-
- if (hide_tasks && filter_task_count(hide_tasks)) {
- tracecmd_xml_start_sub_system(handle, "HideTasks");
- trace_filter_save_tasks(handle, hide_tasks);
- tracecmd_xml_end_sub_system(handle);
- }
-
tracecmd_xml_end_system(handle);
return 0;
@@ -954,9 +939,7 @@ static int load_event_filter(TraceViewStore *store,
}
int trace_view_load_filters(struct tracecmd_xml_handle *handle,
- GtkTreeView *trace_tree,
- struct filter_task *task_filter,
- struct filter_task *hide_tasks)
+ GtkTreeView *trace_tree)
{
struct tracecmd_xml_system *system;
struct tracecmd_xml_system_node *syschild;
@@ -984,12 +967,6 @@ int trace_view_load_filters(struct tracecmd_xml_handle *handle,
if (strcmp(name, "EventFilter") == 0)
load_event_filter(store, handle, syschild);
- else if (strcmp(name, "TaskFilter") == 0)
- trace_filter_load_task_filter(task_filter, handle, syschild);
-
- else if (strcmp(name, "HideTasks") == 0)
- trace_filter_load_task_filter(hide_tasks, handle, syschild);
-
syschild = tracecmd_xml_node_next(syschild);
} while (syschild);
diff --git a/trace-view.h b/trace-view.h
index b0ba7ed..81dac6f 100644
--- a/trace-view.h
+++ b/trace-view.h
@@ -67,12 +67,8 @@ void trace_view_search_setup(GtkBox *box, GtkTreeView *treeview);
gint trace_view_get_selected_row(GtkWidget *treeview);
int trace_view_save_filters(struct tracecmd_xml_handle *handle,
- GtkTreeView *treeview,
- struct filter_task *task_filter,
- struct filter_task *hide_tasks);
+ GtkTreeView *treeview);
int trace_view_load_filters(struct tracecmd_xml_handle *handle,
- GtkTreeView *treeview,
- struct filter_task *task_filter,
- struct filter_task *hide_tasks);
+ GtkTreeView *treeview);
#endif /* _TRACE_VIEW_H */
diff --git a/trace-xml.c b/trace-xml.c
index 47cb3c9..62473fb 100644
--- a/trace-xml.c
+++ b/trace-xml.c
@@ -58,7 +58,8 @@ int tracecmd_xml_write_element(struct tracecmd_xml_handle *handle,
return ret;
}
-struct tracecmd_xml_handle *tracecmd_xml_create(const char *name)
+struct tracecmd_xml_handle *tracecmd_xml_create(const char *name,
+ const char *version)
{
struct tracecmd_xml_handle *handle;
int ret;
@@ -75,6 +76,11 @@ struct tracecmd_xml_handle *tracecmd_xml_create(const char *name)
if (ret < 0)
goto fail_close;
+ ret = xmlTextWriterStartElement(handle->writer,
+ BAD_CAST "KernelShark");
+ if (ret < 0)
+ goto fail_close;
+
return handle;
fail_close:
@@ -85,7 +91,7 @@ struct tracecmd_xml_handle *tracecmd_xml_create(const char *name)
}
int tracecmd_xml_start_system(struct tracecmd_xml_handle *handle,
- const char *system, const char *version)
+ const char *system)
{
int ret;
@@ -95,10 +101,6 @@ int tracecmd_xml_start_system(struct tracecmd_xml_handle *handle,
if (ret < 0)
return ret;
- ret = tracecmd_xml_write_element(handle, "Version", "%s", version);
- if (ret < 0)
- return ret;
-
return 0;
}
@@ -126,6 +128,7 @@ void tracecmd_xml_end_sub_system(struct tracecmd_xml_handle *handle)
void tracecmd_xml_close(struct tracecmd_xml_handle *handle)
{
if (handle->writer) {
+ xmlTextWriterEndElement(handle->writer);
xmlTextWriterEndDocument(handle->writer);
xmlFreeTextWriter(handle->writer);
}
diff --git a/trace-xml.h b/trace-xml.h
index 4006538..f84907d 100644
--- a/trace-xml.h
+++ b/trace-xml.h
@@ -25,12 +25,12 @@ struct tracecmd_xml_handle;
struct tacecmd_xml_system;
struct tacecmd_xml_system_node;
-struct tracecmd_xml_handle *tracecmd_xml_create(const char *name);
+struct tracecmd_xml_handle *tracecmd_xml_create(const char *name, const char *version);
struct tracecmd_xml_handle *tracecmd_xml_open(const char *name);
void tracecmd_xml_close(struct tracecmd_xml_handle *handle);
int tracecmd_xml_start_system(struct tracecmd_xml_handle *handle,
- const char *system, const char *version);
+ const char *system);
void tracecmd_xml_end_system(struct tracecmd_xml_handle *handle);
int tracecmd_xml_start_sub_system(struct tracecmd_xml_handle *handle,
--
cgit v1.2.2
From 935a801c7f3eab7bad5c183a702a506540d32700 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Mon, 5 Apr 2010 22:48:07 -0400
Subject: kernelshark: Fixed grammar on popup menu remove task
The popup menu for removing a task said:
Remove task to filter
when it should be saying:
Remove task from filter
Signed-off-by: Steven Rostedt
---
kernel-shark.c | 2 +-
trace-graph.c | 2 +-
trace-view-main.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/kernel-shark.c b/kernel-shark.c
index b0f1ecb..9ae90bc 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -642,7 +642,7 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
g_assert(text);
if (trace_graph_filter_task_find_pid(ginfo, pid))
- snprintf(text, len, "Remove %s-%d to filter", comm, pid);
+ snprintf(text, len, "Remove %s-%d from filter", comm, pid);
else
snprintf(text, len, "Add %s-%d to filter", comm, pid);
diff --git a/trace-graph.c b/trace-graph.c
index e21ee33..afd29e3 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -718,7 +718,7 @@ do_pop_up(GtkWidget *widget, GdkEventButton *event, gpointer data)
g_assert(text);
if (trace_graph_filter_task_find_pid(ginfo, pid))
- snprintf(text, len, "Remove %s-%d to filter", comm, pid);
+ snprintf(text, len, "Remove %s-%d from filter", comm, pid);
else
snprintf(text, len, "Add %s-%d to filter", comm, pid);
diff --git a/trace-view-main.c b/trace-view-main.c
index e6c0361..8f1b180 100644
--- a/trace-view-main.c
+++ b/trace-view-main.c
@@ -358,7 +358,7 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
g_assert(text);
if (filter_task_find_pid(info->task_filter, pid))
- snprintf(text, len, "Remove %s-%d to filter", comm, pid);
+ snprintf(text, len, "Remove %s-%d from filter", comm, pid);
else
snprintf(text, len, "Add %s-%d to filter", comm, pid);
--
cgit v1.2.2
From 99982a54732ed10ceb1da31240e8fcbbcd430010 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Tue, 6 Apr 2010 12:24:52 -0400
Subject: kernelshark: Add status bar and status dialog
Add a status bar at the bottom of the window and show an info icon
when status exists.
Left mouse button will produce a popup to let the user display
the status information.
Signed-off-by: Steven Rostedt
---
kernel-shark.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
trace-compat.c | 13 ++++++
trace-compat.h | 3 ++
3 files changed, 150 insertions(+)
diff --git a/kernel-shark.c b/kernel-shark.c
index 9ae90bc..7ae562c 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -27,6 +27,7 @@
#include
#include
#include
+#include
#include
#include "trace-compat.h"
@@ -49,9 +50,16 @@
#define TRACE_WIDTH 800
#define TRACE_HEIGHT 600
+#define DIALOG_WIDTH 500
+#define DIALOG_HEIGHT 550
+
#define default_input_file "trace.dat"
static char *input_file;
+static GtkWidget *statusbar;
+static GtkWidget *statuspix;
+static GString *statusstr;
+
void usage(char *prog)
{
printf("Usage: %s\n", prog);
@@ -60,6 +68,34 @@ void usage(char *prog)
printf(" -i input_file, default is %s\n", default_input_file);
}
+void pr_stat(char *fmt, ...)
+{
+ GString *str;
+ va_list ap;
+
+ if (!statusstr) {
+ statusstr = g_string_new("");
+ if (!statusstr)
+ die("Allocating status string");
+ }
+
+ str = g_string_new("");
+
+ va_start(ap, fmt);
+ g_string_vprintf(str, fmt, ap);
+ va_end(ap);
+
+ g_string_append_printf(statusstr, "%s\n", str->str);
+
+ if (statusbar) {
+ gtk_statusbar_push(GTK_STATUSBAR(statusbar), 1, str->str);
+ gtk_widget_show(statuspix);
+ }
+
+ g_string_free(str, TRUE);
+}
+
+
/* graph callbacks */
/* convert_nano() and print_time() are copied from trace-graph.c for debugging
@@ -715,6 +751,81 @@ button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
return FALSE;
}
+static void
+status_display_clicked (gpointer data)
+{
+ GtkWidget *dialog;
+ GtkWidget *scrollwin;
+ GtkWidget *viewport;
+ GtkWidget *textview;
+ GtkTextBuffer *buffer;
+
+ dialog = gtk_dialog_new_with_buttons("Status",
+ NULL,
+ GTK_DIALOG_MODAL,
+ "OK",
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ scrollwin = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrollwin, TRUE, TRUE, 0);
+ gtk_widget_show(scrollwin);
+
+ viewport = gtk_viewport_new(NULL, NULL);
+ gtk_widget_show(viewport);
+
+ gtk_container_add(GTK_CONTAINER(scrollwin), viewport);
+
+ textview = gtk_text_view_new();
+ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
+ gtk_text_buffer_set_text(buffer, statusstr->str, -1);
+
+ gtk_container_add(GTK_CONTAINER(viewport), textview);
+ gtk_widget_show(textview);
+
+ gtk_widget_set_size_request(GTK_WIDGET(dialog),
+ DIALOG_WIDTH, DIALOG_HEIGHT);
+
+ gtk_dialog_run(GTK_DIALOG(dialog));
+
+ gtk_widget_destroy(dialog);
+}
+
+static gboolean
+do_status_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+ static GtkWidget *menu;
+ static GtkWidget *menu_status_display;
+
+ if (!menu) {
+ menu = gtk_menu_new();
+ menu_status_display = gtk_menu_item_new_with_label("Display Status");
+ gtk_widget_show(menu_status_display);
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_status_display);
+
+ g_signal_connect_swapped (G_OBJECT (menu_status_display), "activate",
+ G_CALLBACK (status_display_clicked),
+ data);
+ }
+
+ gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3,
+ gtk_get_current_event_time());
+
+ return TRUE;
+}
+
+static gboolean
+button_press_status(GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+ if (event->button == 1)
+ return do_status_popup(widget, event, data);
+
+ return FALSE;
+}
+
void kernel_shark(int argc, char **argv)
{
struct tracecmd_input *handle;
@@ -734,6 +845,7 @@ void kernel_shark(int argc, char **argv)
GtkWidget *label;
GtkWidget *spin;
GtkWidget *check;
+ GtkWidget *eventbox;
int ret;
int c;
@@ -1187,6 +1299,28 @@ void kernel_shark(int argc, char **argv)
gtk_widget_show(info->treeview);
+ /* --- Set up Status Bar --- */
+
+ statusbar = gtk_statusbar_new();
+
+ gtk_box_pack_start(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0);
+ gtk_widget_show(statusbar);
+
+ statuspix = gtk_image_new_from_stock(GTK_STOCK_INFO,
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
+
+ eventbox = gtk_event_box_new();
+ gtk_container_add(GTK_CONTAINER(eventbox), statuspix);
+ gtk_widget_show(eventbox);
+
+ gtk_box_pack_end(GTK_BOX(statusbar), eventbox, FALSE, FALSE, 0);
+
+ if (statusstr)
+ gtk_widget_show(statuspix);
+
+ gtk_signal_connect(GTK_OBJECT(eventbox), "button_press_event",
+ (GtkSignalFunc) button_press_status, info);
+
/**********************************************
* Main Window
diff --git a/trace-compat.c b/trace-compat.c
index a1f2113..b23cf06 100644
--- a/trace-compat.c
+++ b/trace-compat.c
@@ -23,6 +23,7 @@
*/
#include "trace-compat.h"
#include "trace-gui.h"
+#include "trace-cmd.h"
#include
@@ -79,6 +80,18 @@ gboolean gtk_show_uri(GdkScreen *screen, const gchar *uri,
return FALSE;
}
+void g_string_vprintf(GString *string, const gchar *format, va_list args)
+{
+ char buf[1024];
+ gint len;
+
+ len = vsnprintf(buf, 1024, format, args);
+ if (len >= 1024)
+ die("compat g_string_vprintf can not process length of %d\n", len);
+
+ g_string_printf(string, "%s", buf);
+}
+
#endif /* version < 2.14.0 */
#if GTK_VERSION < CALC_GTK_VERSION(2,12,0)
diff --git a/trace-compat.h b/trace-compat.h
index 2eed192..fa11a35 100644
--- a/trace-compat.h
+++ b/trace-compat.h
@@ -22,6 +22,7 @@
#define _TRACE_COMPAT_H
#include
+#include
#define CALC_GTK_VERSION(maj, min, ext) ((maj << 16) + (min << 8) + ext)
@@ -46,6 +47,8 @@ gdouble gtk_adjustment_get_lower(GtkAdjustment *adj);
gboolean gtk_show_uri(GdkScreen *screen, const gchar *uri,
guint32 timestamp, GError **error);
+void g_string_vprintf(GString *string, const gchar *format, va_list args);
+
#endif /* version < 2.14.0 */
#if GTK_VERSION < CALC_GTK_VERSION(2,12,0)
--
cgit v1.2.2
From b75d856e313af97226686e3ada78b633874ded29 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Tue, 6 Apr 2010 12:33:46 -0400
Subject: kernelshark: Move status bar to general code for trace-view and
trace-graph
Move the code for the status bar to trace-dialog.c and have
trace-view and trace-graph have access to it too.
Signed-off-by: Steven Rostedt
---
kernel-shark.c | 130 +--------------------------------------------------
trace-dialog.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
trace-graph-main.c | 9 ++++
trace-gui.h | 2 +
trace-view-main.c | 8 ++++
5 files changed, 154 insertions(+), 130 deletions(-)
diff --git a/kernel-shark.c b/kernel-shark.c
index 7ae562c..a9e5137 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -50,16 +50,9 @@
#define TRACE_WIDTH 800
#define TRACE_HEIGHT 600
-#define DIALOG_WIDTH 500
-#define DIALOG_HEIGHT 550
-
#define default_input_file "trace.dat"
static char *input_file;
-static GtkWidget *statusbar;
-static GtkWidget *statuspix;
-static GString *statusstr;
-
void usage(char *prog)
{
printf("Usage: %s\n", prog);
@@ -68,34 +61,6 @@ void usage(char *prog)
printf(" -i input_file, default is %s\n", default_input_file);
}
-void pr_stat(char *fmt, ...)
-{
- GString *str;
- va_list ap;
-
- if (!statusstr) {
- statusstr = g_string_new("");
- if (!statusstr)
- die("Allocating status string");
- }
-
- str = g_string_new("");
-
- va_start(ap, fmt);
- g_string_vprintf(str, fmt, ap);
- va_end(ap);
-
- g_string_append_printf(statusstr, "%s\n", str->str);
-
- if (statusbar) {
- gtk_statusbar_push(GTK_STATUSBAR(statusbar), 1, str->str);
- gtk_widget_show(statuspix);
- }
-
- g_string_free(str, TRUE);
-}
-
-
/* graph callbacks */
/* convert_nano() and print_time() are copied from trace-graph.c for debugging
@@ -751,81 +716,6 @@ button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
return FALSE;
}
-static void
-status_display_clicked (gpointer data)
-{
- GtkWidget *dialog;
- GtkWidget *scrollwin;
- GtkWidget *viewport;
- GtkWidget *textview;
- GtkTextBuffer *buffer;
-
- dialog = gtk_dialog_new_with_buttons("Status",
- NULL,
- GTK_DIALOG_MODAL,
- "OK",
- GTK_RESPONSE_ACCEPT,
- NULL);
-
- scrollwin = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
- GTK_POLICY_AUTOMATIC,
- GTK_POLICY_AUTOMATIC);
- gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrollwin, TRUE, TRUE, 0);
- gtk_widget_show(scrollwin);
-
- viewport = gtk_viewport_new(NULL, NULL);
- gtk_widget_show(viewport);
-
- gtk_container_add(GTK_CONTAINER(scrollwin), viewport);
-
- textview = gtk_text_view_new();
- buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
- gtk_text_buffer_set_text(buffer, statusstr->str, -1);
-
- gtk_container_add(GTK_CONTAINER(viewport), textview);
- gtk_widget_show(textview);
-
- gtk_widget_set_size_request(GTK_WIDGET(dialog),
- DIALOG_WIDTH, DIALOG_HEIGHT);
-
- gtk_dialog_run(GTK_DIALOG(dialog));
-
- gtk_widget_destroy(dialog);
-}
-
-static gboolean
-do_status_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
-{
- static GtkWidget *menu;
- static GtkWidget *menu_status_display;
-
- if (!menu) {
- menu = gtk_menu_new();
- menu_status_display = gtk_menu_item_new_with_label("Display Status");
- gtk_widget_show(menu_status_display);
- gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_status_display);
-
- g_signal_connect_swapped (G_OBJECT (menu_status_display), "activate",
- G_CALLBACK (status_display_clicked),
- data);
- }
-
- gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3,
- gtk_get_current_event_time());
-
- return TRUE;
-}
-
-static gboolean
-button_press_status(GtkWidget *widget, GdkEventButton *event, gpointer data)
-{
- if (event->button == 1)
- return do_status_popup(widget, event, data);
-
- return FALSE;
-}
-
void kernel_shark(int argc, char **argv)
{
struct tracecmd_input *handle;
@@ -845,7 +735,7 @@ void kernel_shark(int argc, char **argv)
GtkWidget *label;
GtkWidget *spin;
GtkWidget *check;
- GtkWidget *eventbox;
+ GtkWidget *statusbar;
int ret;
int c;
@@ -1301,27 +1191,11 @@ void kernel_shark(int argc, char **argv)
/* --- Set up Status Bar --- */
- statusbar = gtk_statusbar_new();
+ statusbar = trace_status_bar_new();
gtk_box_pack_start(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0);
gtk_widget_show(statusbar);
- statuspix = gtk_image_new_from_stock(GTK_STOCK_INFO,
- GTK_ICON_SIZE_SMALL_TOOLBAR);
-
- eventbox = gtk_event_box_new();
- gtk_container_add(GTK_CONTAINER(eventbox), statuspix);
- gtk_widget_show(eventbox);
-
- gtk_box_pack_end(GTK_BOX(statusbar), eventbox, FALSE, FALSE, 0);
-
- if (statusstr)
- gtk_widget_show(statuspix);
-
- gtk_signal_connect(GTK_OBJECT(eventbox), "button_press_event",
- (GtkSignalFunc) button_press_status, info);
-
-
/**********************************************
* Main Window
**********************************************/
diff --git a/trace-dialog.c b/trace-dialog.c
index e27245d..4ed5b7b 100644
--- a/trace-dialog.c
+++ b/trace-dialog.c
@@ -25,10 +25,141 @@
#include
#include "trace-compat.h"
+#include "trace-cmd.h"
#include "trace-gui.h"
-#define DIALOG_WIDTH 400
-#define DIALOG_HEIGHT 600
+#define DIALOG_WIDTH 500
+#define DIALOG_HEIGHT 550
+
+static GtkWidget *statusbar;
+static GtkWidget *statuspix;
+static GString *statusstr;
+
+void pr_stat(char *fmt, ...)
+{
+ GString *str;
+ va_list ap;
+
+ if (!statusstr) {
+ statusstr = g_string_new("");
+ if (!statusstr)
+ die("Allocating status string");
+ }
+
+ str = g_string_new("");
+
+ va_start(ap, fmt);
+ g_string_vprintf(str, fmt, ap);
+ va_end(ap);
+
+ g_string_append_printf(statusstr, "%s\n", str->str);
+
+ if (statusbar) {
+ gtk_statusbar_push(GTK_STATUSBAR(statusbar), 1, str->str);
+ gtk_widget_show(statuspix);
+ }
+
+ g_string_free(str, TRUE);
+}
+
+static void
+status_display_clicked (gpointer data)
+{
+ GtkWidget *dialog;
+ GtkWidget *scrollwin;
+ GtkWidget *viewport;
+ GtkWidget *textview;
+ GtkTextBuffer *buffer;
+
+ dialog = gtk_dialog_new_with_buttons("Status",
+ NULL,
+ GTK_DIALOG_MODAL,
+ "OK",
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ scrollwin = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrollwin, TRUE, TRUE, 0);
+ gtk_widget_show(scrollwin);
+
+ viewport = gtk_viewport_new(NULL, NULL);
+ gtk_widget_show(viewport);
+
+ gtk_container_add(GTK_CONTAINER(scrollwin), viewport);
+
+ textview = gtk_text_view_new();
+ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
+ gtk_text_buffer_set_text(buffer, statusstr->str, -1);
+
+ gtk_container_add(GTK_CONTAINER(viewport), textview);
+ gtk_widget_show(textview);
+
+ gtk_widget_set_size_request(GTK_WIDGET(dialog),
+ DIALOG_WIDTH, DIALOG_HEIGHT);
+
+ gtk_dialog_run(GTK_DIALOG(dialog));
+
+ gtk_widget_destroy(dialog);
+}
+
+static gboolean
+do_status_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+ static GtkWidget *menu;
+ static GtkWidget *menu_status_display;
+
+ if (!menu) {
+ menu = gtk_menu_new();
+ menu_status_display = gtk_menu_item_new_with_label("Display Status");
+ gtk_widget_show(menu_status_display);
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_status_display);
+
+ g_signal_connect_swapped (G_OBJECT (menu_status_display), "activate",
+ G_CALLBACK (status_display_clicked),
+ data);
+ }
+
+ gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3,
+ gtk_get_current_event_time());
+
+ return TRUE;
+}
+
+static gboolean
+button_press_status(GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+ if (event->button == 1)
+ return do_status_popup(widget, event, data);
+
+ return FALSE;
+}
+
+GtkWidget *trace_status_bar_new(void)
+{
+ GtkWidget *eventbox;
+
+ statusbar = gtk_statusbar_new();
+
+ statuspix = gtk_image_new_from_stock(GTK_STOCK_INFO,
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
+
+ eventbox = gtk_event_box_new();
+ gtk_container_add(GTK_CONTAINER(eventbox), statuspix);
+ gtk_widget_show(eventbox);
+
+ gtk_box_pack_end(GTK_BOX(statusbar), eventbox, FALSE, FALSE, 0);
+
+ if (statusstr)
+ gtk_widget_show(statuspix);
+
+ gtk_signal_connect(GTK_OBJECT(eventbox), "button_press_event",
+ (GtkSignalFunc) button_press_status, NULL);
+
+ return statusbar;
+}
void trace_show_help(GtkWidget *window, const gchar *link, GError **error)
{
diff --git a/trace-graph-main.c b/trace-graph-main.c
index 0490a86..286e417 100644
--- a/trace-graph-main.c
+++ b/trace-graph-main.c
@@ -216,6 +216,7 @@ void trace_graph(int argc, char **argv)
GtkWidget *menu_item;
GtkWidget *sub_item;
GtkWidget *widget;
+ GtkWidget *statusbar;
int c;
int ret;
@@ -455,6 +456,14 @@ void trace_graph(int argc, char **argv)
gtk_widget_show(widget);
+ /* --- Set up Status Bar --- */
+
+ statusbar = trace_status_bar_new();
+
+ gtk_box_pack_start(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0);
+ gtk_widget_show(statusbar);
+
+
/**********************************************
* Main Window
**********************************************/
diff --git a/trace-gui.h b/trace-gui.h
index 55778bf..59784c6 100644
--- a/trace-gui.h
+++ b/trace-gui.h
@@ -29,6 +29,8 @@ enum trace_dialog_type {
TRACE_GUI_ERROR,
};
+GtkWidget *trace_status_bar_new(void);
+
void trace_show_help(GtkWidget *window, const gchar *link, GError **error);
void trace_dialog(GtkWindow *parent, enum trace_dialog_type type,
diff --git a/trace-view-main.c b/trace-view-main.c
index 8f1b180..bc7e4ee 100644
--- a/trace-view-main.c
+++ b/trace-view-main.c
@@ -435,6 +435,7 @@ void trace_view(int argc, char **argv)
GtkWidget *scrollwin;
GtkWidget *label;
GtkWidget *spin;
+ GtkWidget *statusbar;
int ret;
int c;
@@ -687,6 +688,13 @@ void trace_view(int argc, char **argv)
gtk_widget_show(trace_tree);
+ /* --- Set up Status Bar --- */
+
+ statusbar = trace_status_bar_new();
+
+ gtk_box_pack_start(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0);
+ gtk_widget_show(statusbar);
+
/**********************************************
* Main Window
**********************************************/
--
cgit v1.2.2
From 25d1c51565706f7d9e2a8cec31a80dd32c2c889b Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Tue, 6 Apr 2010 14:39:06 -0400
Subject: parse-events: Move parse-event utils to separate file
Move the util functions used by parse-events into a separate file
and compile it with the libparsevents library. Also add "__die()"
equivalent functions that are always available.
Signed-off-by: Steven Rostedt
---
Makefile | 2 +-
parse-events.h | 10 ++++++
parse-utils.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
trace-util.c | 67 ------------------------------------
4 files changed, 116 insertions(+), 68 deletions(-)
create mode 100644 parse-utils.c
diff --git a/Makefile b/Makefile
index cd4db4a..7dde5cf 100644
--- a/Makefile
+++ b/Makefile
@@ -223,7 +223,7 @@ TRACE_GRAPH_MAIN_OBJS = trace-graph-main.o $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS)
KERNEL_SHARK_OBJS = $(TRACE_VIEW_OBJS) $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS) \
kernel-shark.o
-PEVENT_LIB_OBJS = parse-events.o trace-seq.o parse-filter.o
+PEVENT_LIB_OBJS = parse-events.o trace-seq.o parse-filter.o parse-utils.o
TCMD_LIB_OBJS = $(PEVENT_LIB_OBJS) trace-util.o trace-input.o trace-ftrace.o \
trace-output.o trace-record.o
diff --git a/parse-events.h b/parse-events.h
index 0c6a330..5afbd1a 100644
--- a/parse-events.h
+++ b/parse-events.h
@@ -342,11 +342,21 @@ struct pevent {
struct event_format *last_event;
};
+/* Can be overridden */
void die(char *fmt, ...);
void *malloc_or_die(unsigned int size);
void warning(char *fmt, ...);
void pr_stat(char *fmt, ...);
+/* Always available */
+void __die(char *fmt, ...);
+void __warning(char *fmt, ...);
+void __pr_stat(char *fmt, ...);
+
+void __vdie(char *fmt, ...);
+void __vwarning(char *fmt, ...);
+void __vpr_stat(char *fmt, ...);
+
static inline unsigned short
__data2host2(struct pevent *pevent, unsigned short data)
{
diff --git a/parse-utils.c b/parse-utils.c
new file mode 100644
index 0000000..103bbd8
--- /dev/null
+++ b/parse-utils.c
@@ -0,0 +1,105 @@
+#include
+#include
+#include
+#include
+#include
+
+#define __weak __attribute__((weak))
+
+void __vdie(char *fmt, va_list ap)
+{
+ int ret = errno;
+
+ if (errno)
+ perror("trace-cmd");
+ else
+ ret = -1;
+
+ fprintf(stderr, " ");
+ vfprintf(stderr, fmt, ap);
+
+ fprintf(stderr, "\n");
+ exit(ret);
+}
+
+void __die(char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vdie(fmt, ap);
+ va_end(ap);
+}
+
+void __weak die(char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vdie(fmt, ap);
+ va_end(ap);
+}
+
+void __vwarning(char *fmt, va_list ap)
+{
+ if (errno)
+ perror("trace-cmd");
+ errno = 0;
+
+ fprintf(stderr, " ");
+ vfprintf(stderr, fmt, ap);
+
+ fprintf(stderr, "\n");
+}
+
+void __warning(char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vwarning(fmt, ap);
+ va_end(ap);
+}
+
+void __weak warning(char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vwarning(fmt, ap);
+ va_end(ap);
+}
+
+void __vpr_stat(char *fmt, va_list ap)
+{
+ vprintf(fmt, ap);
+ printf("\n");
+}
+
+void __pr_stat(char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vpr_stat(fmt, ap);
+ va_end(ap);
+}
+
+void __weak pr_stat(char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vpr_stat(fmt, ap);
+ va_end(ap);
+}
+
+void __weak *malloc_or_die(unsigned int size)
+{
+ void *data;
+
+ data = malloc(size);
+ if (!data)
+ die("malloc");
+ return data;
+}
diff --git a/trace-util.c b/trace-util.c
index 7f6f0bb..0397732 100644
--- a/trace-util.c
+++ b/trace-util.c
@@ -38,8 +38,6 @@
int tracecmd_disable_sys_plugins;
int tracecmd_disable_plugins;
-#define __weak __attribute__((weak))
-
#define _STR(x) #x
#define STR(x) _STR(x)
@@ -53,71 +51,6 @@ struct plugin_list {
void *handle;
};
-void __weak die(char *fmt, ...)
-{
- va_list ap;
- int ret = errno;
-
- if (errno)
- perror("trace-cmd");
- else
- ret = -1;
-
- va_start(ap, fmt);
- fprintf(stderr, " ");
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-
- fprintf(stderr, "\n");
- exit(ret);
-}
-
-void __weak warning(char *fmt, ...)
-{
- va_list ap;
-
- if (errno)
- perror("trace-cmd");
- errno = 0;
-
- va_start(ap, fmt);
- fprintf(stderr, " ");
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-
- fprintf(stderr, "\n");
-}
-
-void __weak pr_stat(char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
-
- printf("\n");
-}
-
-void __weak *malloc_or_die(unsigned int size)
-{
- void *data;
-
- data = malloc(size);
- if (!data)
- die("malloc");
- return data;
-}
-
-int __weak bigendian(void)
-{
- unsigned char str[] = { 0x1, 0x2, 0x3, 0x4 };
- unsigned int *ptr;
-
- ptr = (unsigned int *)str;
- return *ptr == 0x01020304;
-}
-
void parse_cmdlines(struct pevent *pevent,
char *file, int size __unused)
{
--
cgit v1.2.2
From 0af521a7ba132afbc83aff1216ce3457f97cc09c Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Tue, 6 Apr 2010 14:48:18 -0400
Subject: kernelshark: Add warning dialogs
When a warning happens, show it with a dialog instead of printing
to the console.
Signed-off-by: Steven Rostedt
---
kernel-shark.c | 2 ++
trace-dialog.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
trace-graph-main.c | 2 ++
trace-gui.h | 2 ++
trace-view-main.c | 2 ++
5 files changed, 56 insertions(+)
diff --git a/kernel-shark.c b/kernel-shark.c
index a9e5137..ee47ff5 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -788,6 +788,8 @@ void kernel_shark(int argc, char **argv)
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
info->window = window;
+ trace_dialog_register_window(window);
+
if (input_file)
update_title(window, input_file);
diff --git a/trace-dialog.c b/trace-dialog.c
index 4ed5b7b..c220a52 100644
--- a/trace-dialog.c
+++ b/trace-dialog.c
@@ -22,6 +22,7 @@
#include
#include
#include
+#include
#include
#include "trace-compat.h"
@@ -35,6 +36,8 @@ static GtkWidget *statusbar;
static GtkWidget *statuspix;
static GString *statusstr;
+static GtkWidget *parent_window;
+
void pr_stat(char *fmt, ...)
{
GString *str;
@@ -62,6 +65,51 @@ void pr_stat(char *fmt, ...)
g_string_free(str, TRUE);
}
+/**
+ * trace_dialog_register_window - register window for warning dialogs
+ * @window: parent window to use for other dialogs
+ *
+ * The warning messages do not have a way to pass the window to
+ * the function, since these functions are also used by the command
+ * line interface. This allows an application to give the warning
+ * messages a window to use.
+ */
+void trace_dialog_register_window(GtkWidget *window)
+{
+ parent_window = window;
+}
+
+void warning(char *fmt, ...)
+{
+ GString *str;
+ va_list ap;
+
+ if (!parent_window) {
+ va_start(ap, fmt);
+ __vwarning(fmt, ap);
+ va_end(ap);
+ return;
+ }
+
+ str = g_string_new("");
+
+ va_start(ap, fmt);
+ g_string_vprintf(str, fmt, ap);
+ va_end(ap);
+
+ g_string_append(str, "\n");
+
+ if (errno)
+ g_string_prepend(str, strerror(errno));
+
+ errno = 0;
+
+ trace_dialog(GTK_WINDOW(parent_window), TRACE_GUI_WARNING,
+ str->str);
+
+ g_string_free(str, TRUE);
+}
+
static void
status_display_clicked (gpointer data)
{
diff --git a/trace-graph-main.c b/trace-graph-main.c
index 286e417..2ba9447 100644
--- a/trace-graph-main.c
+++ b/trace-graph-main.c
@@ -262,6 +262,8 @@ void trace_graph(int argc, char **argv)
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ trace_dialog_register_window(window);
+
/* --- Top Level Vbox --- */
vbox = gtk_vbox_new(FALSE, 0);
diff --git a/trace-gui.h b/trace-gui.h
index 59784c6..a2d261f 100644
--- a/trace-gui.h
+++ b/trace-gui.h
@@ -31,6 +31,8 @@ enum trace_dialog_type {
GtkWidget *trace_status_bar_new(void);
+void trace_dialog_register_window(GtkWidget *window);
+
void trace_show_help(GtkWidget *window, const gchar *link, GError **error);
void trace_dialog(GtkWindow *parent, enum trace_dialog_type type,
diff --git a/trace-view-main.c b/trace-view-main.c
index bc7e4ee..8fa9aa6 100644
--- a/trace-view-main.c
+++ b/trace-view-main.c
@@ -479,6 +479,8 @@ void trace_view(int argc, char **argv)
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ trace_dialog_register_window(window);
+
/* --- Top Level Vbox --- */
vbox = gtk_vbox_new(FALSE, 0);
--
cgit v1.2.2
From 2286bfd576724d9ed44cdeb20eca20adaa953aa5 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Tue, 6 Apr 2010 14:53:40 -0400
Subject: kernelshark: Remove debug statements in trace-filter.c
Remove the printf statements that was used for debugging in
trace-filter.c.
Signed-off-by: Steven Rostedt
---
trace-filter.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/trace-filter.c b/trace-filter.c
index 3f78637..7494ccc 100644
--- a/trace-filter.c
+++ b/trace-filter.c
@@ -1651,11 +1651,9 @@ event_dialog_response (gpointer data, gint response_id)
switch (response_id) {
case GTK_RESPONSE_ACCEPT:
- printf("accept!\n");
accept_events(event_helper);
break;
case GTK_RESPONSE_REJECT:
- printf("reject!\n");
event_helper->func(FALSE, FALSE, NULL, NULL,
event_helper->data);
break;
--
cgit v1.2.2
From 608ee7934adf2ade0c1504ee030ab6f6a35be9e0 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Tue, 6 Apr 2010 16:39:31 -0400
Subject: trace-graph: Add tooltips to graph markers
Add tooltips to give some information on the markers.
Signed-off-by: Steven Rostedt
---
trace-graph.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/trace-graph.c b/trace-graph.c
index afd29e3..cab3647 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -2503,6 +2503,24 @@ int trace_graph_save_filters(struct graph_info *ginfo,
return 0;
}
+static void set_label_a(GtkWidget *widget)
+{
+ gtk_widget_set_tooltip_text(widget, "Click left mouse on graph\n"
+ "to set Marker A");
+}
+
+static void set_label_b(GtkWidget *widget)
+{
+ gtk_widget_set_tooltip_text(widget, "Shift and click left mouse on graph\n"
+ "to set Marker B");
+}
+
+static void set_label_cursor(GtkWidget *widget)
+{
+ gtk_widget_set_tooltip_text(widget, "Double click Left mouse on graph\n"
+ "to set Cursor");
+}
+
struct graph_info *
trace_graph_create_with_callbacks(struct tracecmd_input *handle,
struct graph_callbacks *cbs)
@@ -2562,10 +2580,12 @@ trace_graph_create_with_callbacks(struct tracecmd_input *handle,
/* --- Cursor --- */
label = gtk_label_new("Cursor:");
+ set_label_cursor(label);
gtk_table_attach(GTK_TABLE(table), label, 4, 5, 0, 1, GTK_EXPAND, GTK_EXPAND, 3, 3);
gtk_widget_show(label);
ginfo->cursor_label = gtk_label_new("0.0");
+ set_label_cursor(ginfo->cursor_label);
eventbox = gtk_event_box_new();
gtk_widget_show(eventbox);
gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL, &color);
@@ -2581,10 +2601,13 @@ trace_graph_create_with_callbacks(struct tracecmd_input *handle,
gtk_widget_show(hbox);
label = gtk_label_new("Marker");
+ set_label_a(label);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
gtk_widget_show(label);
+
label = gtk_label_new("A:");
+ set_label_a(label);
colorAB.red = 0;
colorAB.green = (0xff) *(65535/255);
@@ -2601,6 +2624,7 @@ trace_graph_create_with_callbacks(struct tracecmd_input *handle,
gtk_table_attach(GTK_TABLE(table), hbox, 9, 10, 0, 1, GTK_EXPAND, GTK_EXPAND, 3, 3);
ginfo->marka_label = gtk_label_new("0.0");
+ set_label_a(ginfo->marka_label);
eventbox = gtk_event_box_new();
gtk_widget_show(eventbox);
gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL, &color);
@@ -2616,10 +2640,12 @@ trace_graph_create_with_callbacks(struct tracecmd_input *handle,
gtk_widget_show(hbox);
label = gtk_label_new("Marker");
+ set_label_b(label);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
gtk_widget_show(label);
label = gtk_label_new("B:");
+ set_label_b(label);
colorAB.red = (0xff) *(65535/255);
colorAB.green = 0;
@@ -2637,6 +2663,7 @@ trace_graph_create_with_callbacks(struct tracecmd_input *handle,
gtk_widget_show(label);
ginfo->markb_label = gtk_label_new("0.0");
+ set_label_b(ginfo->markb_label);
eventbox = gtk_event_box_new();
gtk_widget_show(eventbox);
gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL, &color);
--
cgit v1.2.2
From 76654897a4e4c222871dda9ff487be0e72be6a9b Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Tue, 6 Apr 2010 17:23:42 -0400
Subject: trace-graph: Add tool tip about zooming
Show tip window to explain how to zoom in and out on the graph.
Signed-off-by: Steven Rostedt
---
trace-graph.c | 34 +++++++++++++++++++++++++++++-----
1 file changed, 29 insertions(+), 5 deletions(-)
diff --git a/trace-graph.c b/trace-graph.c
index cab3647..27c139d 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -766,7 +766,25 @@ do_pop_up(GtkWidget *widget, GdkEventButton *event, gpointer data)
return TRUE;
}
-static void button_press(struct graph_info *ginfo, gint x, guint state)
+static void draw_info_box(struct graph_info *ginfo, const gchar *buffer,
+ gint x, gint y);
+
+static void stop_zoom_tip(struct graph_info *ginfo)
+{
+ clear_info_box(ginfo);
+}
+
+static void show_zoom_tip(struct graph_info *ginfo, gint x, gint y)
+{
+ clear_info_box(ginfo);
+
+ draw_info_box(ginfo,
+ "Click and hold left mouse and drag right to zoom in\n"
+ "Click and hold left mouse and drag left to zoom out",
+ x, y);
+}
+
+static void button_press(struct graph_info *ginfo, gint x, gint y, guint state)
{
ginfo->press_x = x;
ginfo->last_x = 0;
@@ -785,8 +803,10 @@ static void button_press(struct graph_info *ginfo, gint x, guint state)
clear_line(ginfo, convert_time_to_x(ginfo, ginfo->marka_time));
update_marka(ginfo, x);
}
- } else
+ } else {
ginfo->zoom = TRUE;
+ show_zoom_tip(ginfo, x, y);
+ }
return;
}
@@ -826,7 +846,7 @@ button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
return TRUE;
}
- button_press(ginfo, event->x, event->state);
+ button_press(ginfo, event->x, event->y, event->state);
return TRUE;
}
@@ -839,6 +859,9 @@ static void motion_plot(struct graph_info *ginfo, gint x, gint y)
{
struct graph_plot *plot;
+ if (ginfo->zoom)
+ stop_zoom_tip(ginfo);
+
if (!ginfo->curr_pixmap)
return;
@@ -876,7 +899,7 @@ info_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
if (event->type == GDK_2BUTTON_PRESS)
return FALSE;
- button_press(ginfo, gtk_adjustment_get_value(ginfo->hadj), event->state);
+ button_press(ginfo, gtk_adjustment_get_value(ginfo->hadj), event->y, event->state);
return FALSE;
}
@@ -1500,7 +1523,8 @@ static void button_release(struct graph_info *ginfo, gint x)
ginfo->show_marka = TRUE;
ginfo->show_markb = TRUE;
update_markb(ginfo, x);
- }
+ } else
+ stop_zoom_tip(ginfo);
clear_line(ginfo, ginfo->last_x);
clear_line(ginfo, ginfo->press_x);
--
cgit v1.2.2
From c26682a8efa2b8f90e0562ab730f6283b8d70090 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Tue, 6 Apr 2010 18:44:52 -0400
Subject: kernelshark: Add compat for gtk_widget_set_tooltip_text()
Add a function to handle old gtk libs that do not implement
gtk_widget_set_tooltip_text(). But this compat function only works
with widgets with windows, so there's not much we can do.
Signed-off-by: Steven Rostedt
---
trace-compat.c | 16 ++++++++++++++++
trace-compat.h | 1 +
trace-graph.c | 10 +++++-----
3 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/trace-compat.c b/trace-compat.c
index b23cf06..e1652e0 100644
--- a/trace-compat.c
+++ b/trace-compat.c
@@ -101,4 +101,20 @@ GtkWidget *gtk_tree_view_column_get_tree_view(GtkTreeViewColumn *col)
return col->tree_view;
}
+void gtk_widget_set_tooltip_text(GtkWidget *widget, const gchar *text)
+{
+ static GtkTooltips *tooltips;
+
+ /* Only works for widgets with windows, sorry */
+ if (GTK_WIDGET_NO_WINDOW(widget))
+ return;
+
+ if (!tooltips) {
+ tooltips = gtk_tooltips_new();
+ gtk_tooltips_enable(tooltips);
+ }
+
+ gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), widget, text, text);
+}
+
#endif /* version < 2.12.0 */
diff --git a/trace-compat.h b/trace-compat.h
index fa11a35..ce7759d 100644
--- a/trace-compat.h
+++ b/trace-compat.h
@@ -54,6 +54,7 @@ void g_string_vprintf(GString *string, const gchar *format, va_list args);
#if GTK_VERSION < CALC_GTK_VERSION(2,12,0)
GtkWidget *gtk_tree_view_column_get_tree_view(GtkTreeViewColumn *col);
+void gtk_widget_set_tooltip_text(GtkWidget *widget, const gchar *text);
#endif /* version < 2.12.0 */
diff --git a/trace-graph.c b/trace-graph.c
index 27c139d..0eaa45a 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -2609,8 +2609,8 @@ trace_graph_create_with_callbacks(struct tracecmd_input *handle,
gtk_widget_show(label);
ginfo->cursor_label = gtk_label_new("0.0");
- set_label_cursor(ginfo->cursor_label);
eventbox = gtk_event_box_new();
+ set_label_cursor(eventbox);
gtk_widget_show(eventbox);
gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL, &color);
gtk_container_add(GTK_CONTAINER(eventbox), ginfo->cursor_label);
@@ -2631,13 +2631,13 @@ trace_graph_create_with_callbacks(struct tracecmd_input *handle,
label = gtk_label_new("A:");
- set_label_a(label);
colorAB.red = 0;
colorAB.green = (0xff) *(65535/255);
colorAB.blue = 0;
eventbox = gtk_event_box_new();
+ set_label_a(eventbox);
gtk_widget_show(eventbox);
gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL, &colorAB);
gtk_container_add(GTK_CONTAINER(eventbox), label);
@@ -2648,8 +2648,8 @@ trace_graph_create_with_callbacks(struct tracecmd_input *handle,
gtk_table_attach(GTK_TABLE(table), hbox, 9, 10, 0, 1, GTK_EXPAND, GTK_EXPAND, 3, 3);
ginfo->marka_label = gtk_label_new("0.0");
- set_label_a(ginfo->marka_label);
eventbox = gtk_event_box_new();
+ set_label_a(eventbox);
gtk_widget_show(eventbox);
gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL, &color);
gtk_container_add(GTK_CONTAINER(eventbox), ginfo->marka_label);
@@ -2669,13 +2669,13 @@ trace_graph_create_with_callbacks(struct tracecmd_input *handle,
gtk_widget_show(label);
label = gtk_label_new("B:");
- set_label_b(label);
colorAB.red = (0xff) *(65535/255);
colorAB.green = 0;
colorAB.blue = 0;
eventbox = gtk_event_box_new();
+ set_label_b(eventbox);
gtk_widget_show(eventbox);
gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL, &colorAB);
gtk_container_add(GTK_CONTAINER(eventbox), label);
@@ -2687,8 +2687,8 @@ trace_graph_create_with_callbacks(struct tracecmd_input *handle,
gtk_widget_show(label);
ginfo->markb_label = gtk_label_new("0.0");
- set_label_b(ginfo->markb_label);
eventbox = gtk_event_box_new();
+ set_label_b(eventbox);
gtk_widget_show(eventbox);
gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL, &color);
gtk_container_add(GTK_CONTAINER(eventbox), ginfo->markb_label);
--
cgit v1.2.2
From cf3a11c410f0f5453c2140c8737295f70bb33e3b Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Thu, 8 Apr 2010 12:54:23 -0400
Subject: trace-graph: Clear zoom tip on double click
When selecting a cursor with the double click, the zoom tip does
not go away. Clear it on double click.
Signed-off-by: Steven Rostedt
---
trace-graph.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/trace-graph.c b/trace-graph.c
index 0eaa45a..8050226 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -827,6 +827,7 @@ button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
/* check for double click */
if (event->type == GDK_2BUTTON_PRESS) {
+ stop_zoom_tip(ginfo);
if (ginfo->line_active) {
ginfo->line_active = FALSE;
clear_line(ginfo, ginfo->last_x);
--
cgit v1.2.2
From 933e3d54c021be56213b1475e5ac4fbebc7b48f1 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Fri, 9 Apr 2010 11:57:28 -0400
Subject: kerselshark/doc: Add html documentation on how to use kernelshark
Add documentation on how to use kernelshark.
Signed-off-by: Steven Rostedt
---
Documentation/HTML/images/kshark-cursor-1.png | Bin 0 -> 61110 bytes
.../HTML/images/kshark-filter-advance-1.png | Bin 0 -> 21625 bytes
.../HTML/images/kshark-filter-del-adv.png | Bin 0 -> 21730 bytes
.../HTML/images/kshark-filter-event-adv-list.png | Bin 0 -> 20674 bytes
.../HTML/images/kshark-filter-events-sched.png | Bin 0 -> 19572 bytes
Documentation/HTML/images/kshark-filter-events.png | Bin 0 -> 20090 bytes
.../HTML/images/kshark-filter-list-adv-irq.png | Bin 0 -> 20789 bytes
.../HTML/images/kshark-filter-sync-graph-1.png | Bin 0 -> 71003 bytes
.../HTML/images/kshark-filter-task-menu.png | Bin 0 -> 83758 bytes
Documentation/HTML/images/kshark-filter.png | Bin 0 -> 64849 bytes
.../HTML/images/kshark-graph-info-line.png | Bin 0 -> 2476 bytes
.../HTML/images/kshark-graph-plot-area.png | Bin 0 -> 5210 bytes
.../HTML/images/kshark-graph-plot-title.png | Bin 0 -> 1144 bytes
Documentation/HTML/images/kshark-list-adjust.png | Bin 0 -> 80113 bytes
.../HTML/images/kshark-list-enable-filter-1.png | Bin 0 -> 83642 bytes
.../HTML/images/kshark-list-graph-follow-1.png | Bin 0 -> 82268 bytes
.../HTML/images/kshark-list-graph-follow-2.png | Bin 0 -> 81639 bytes
.../HTML/images/kshark-list-info-area.png | Bin 0 -> 5083 bytes
Documentation/HTML/images/kshark-open.png | Bin 0 -> 58572 bytes
Documentation/HTML/images/kshark-plot-cpu-1.png | Bin 0 -> 8385 bytes
Documentation/HTML/images/kshark-plot-cpu-2.png | Bin 0 -> 8453 bytes
.../HTML/images/kshark-plot-cpu-result.png | Bin 0 -> 59326 bytes
Documentation/HTML/images/kshark-plot-menu.png | Bin 0 -> 61670 bytes
.../images/kshark-plot-task-measure-preempt.png | Bin 0 -> 65759 bytes
.../HTML/images/kshark-plot-task-measure.png | Bin 0 -> 65673 bytes
.../HTML/images/kshark-plot-task-result.png | Bin 0 -> 65607 bytes
.../HTML/images/kshark-plot-task-select.png | Bin 0 -> 26263 bytes
.../HTML/images/kshark-plot-task-zoom-1.png | Bin 0 -> 66467 bytes
Documentation/HTML/images/kshark-select-a-1.png | Bin 0 -> 59254 bytes
Documentation/HTML/images/kshark-select-b-1.png | Bin 0 -> 59400 bytes
Documentation/HTML/images/kshark-zoom-in-2.png | Bin 0 -> 63059 bytes
Documentation/HTML/images/kshark-zoom-in-3.png | Bin 0 -> 59020 bytes
.../HTML/images/kshark-zoom-in-select.png | Bin 0 -> 60206 bytes
.../HTML/images/kshark-zoom-out-select.png | Bin 0 -> 62821 bytes
Documentation/HTML/index.html | 631 +++++++++++++++++++++
35 files changed, 631 insertions(+)
create mode 100644 Documentation/HTML/images/kshark-cursor-1.png
create mode 100644 Documentation/HTML/images/kshark-filter-advance-1.png
create mode 100644 Documentation/HTML/images/kshark-filter-del-adv.png
create mode 100644 Documentation/HTML/images/kshark-filter-event-adv-list.png
create mode 100644 Documentation/HTML/images/kshark-filter-events-sched.png
create mode 100644 Documentation/HTML/images/kshark-filter-events.png
create mode 100644 Documentation/HTML/images/kshark-filter-list-adv-irq.png
create mode 100644 Documentation/HTML/images/kshark-filter-sync-graph-1.png
create mode 100644 Documentation/HTML/images/kshark-filter-task-menu.png
create mode 100644 Documentation/HTML/images/kshark-filter.png
create mode 100644 Documentation/HTML/images/kshark-graph-info-line.png
create mode 100644 Documentation/HTML/images/kshark-graph-plot-area.png
create mode 100644 Documentation/HTML/images/kshark-graph-plot-title.png
create mode 100644 Documentation/HTML/images/kshark-list-adjust.png
create mode 100644 Documentation/HTML/images/kshark-list-enable-filter-1.png
create mode 100644 Documentation/HTML/images/kshark-list-graph-follow-1.png
create mode 100644 Documentation/HTML/images/kshark-list-graph-follow-2.png
create mode 100644 Documentation/HTML/images/kshark-list-info-area.png
create mode 100644 Documentation/HTML/images/kshark-open.png
create mode 100644 Documentation/HTML/images/kshark-plot-cpu-1.png
create mode 100644 Documentation/HTML/images/kshark-plot-cpu-2.png
create mode 100644 Documentation/HTML/images/kshark-plot-cpu-result.png
create mode 100644 Documentation/HTML/images/kshark-plot-menu.png
create mode 100644 Documentation/HTML/images/kshark-plot-task-measure-preempt.png
create mode 100644 Documentation/HTML/images/kshark-plot-task-measure.png
create mode 100644 Documentation/HTML/images/kshark-plot-task-result.png
create mode 100644 Documentation/HTML/images/kshark-plot-task-select.png
create mode 100644 Documentation/HTML/images/kshark-plot-task-zoom-1.png
create mode 100644 Documentation/HTML/images/kshark-select-a-1.png
create mode 100644 Documentation/HTML/images/kshark-select-b-1.png
create mode 100644 Documentation/HTML/images/kshark-zoom-in-2.png
create mode 100644 Documentation/HTML/images/kshark-zoom-in-3.png
create mode 100644 Documentation/HTML/images/kshark-zoom-in-select.png
create mode 100644 Documentation/HTML/images/kshark-zoom-out-select.png
create mode 100644 Documentation/HTML/index.html
diff --git a/Documentation/HTML/images/kshark-cursor-1.png b/Documentation/HTML/images/kshark-cursor-1.png
new file mode 100644
index 0000000..64d19be
Binary files /dev/null and b/Documentation/HTML/images/kshark-cursor-1.png differ
diff --git a/Documentation/HTML/images/kshark-filter-advance-1.png b/Documentation/HTML/images/kshark-filter-advance-1.png
new file mode 100644
index 0000000..23f6584
Binary files /dev/null and b/Documentation/HTML/images/kshark-filter-advance-1.png differ
diff --git a/Documentation/HTML/images/kshark-filter-del-adv.png b/Documentation/HTML/images/kshark-filter-del-adv.png
new file mode 100644
index 0000000..88e2376
Binary files /dev/null and b/Documentation/HTML/images/kshark-filter-del-adv.png differ
diff --git a/Documentation/HTML/images/kshark-filter-event-adv-list.png b/Documentation/HTML/images/kshark-filter-event-adv-list.png
new file mode 100644
index 0000000..c2f2d52
Binary files /dev/null and b/Documentation/HTML/images/kshark-filter-event-adv-list.png differ
diff --git a/Documentation/HTML/images/kshark-filter-events-sched.png b/Documentation/HTML/images/kshark-filter-events-sched.png
new file mode 100644
index 0000000..0941317
Binary files /dev/null and b/Documentation/HTML/images/kshark-filter-events-sched.png differ
diff --git a/Documentation/HTML/images/kshark-filter-events.png b/Documentation/HTML/images/kshark-filter-events.png
new file mode 100644
index 0000000..4732f8a
Binary files /dev/null and b/Documentation/HTML/images/kshark-filter-events.png differ
diff --git a/Documentation/HTML/images/kshark-filter-list-adv-irq.png b/Documentation/HTML/images/kshark-filter-list-adv-irq.png
new file mode 100644
index 0000000..0b04031
Binary files /dev/null and b/Documentation/HTML/images/kshark-filter-list-adv-irq.png differ
diff --git a/Documentation/HTML/images/kshark-filter-sync-graph-1.png b/Documentation/HTML/images/kshark-filter-sync-graph-1.png
new file mode 100644
index 0000000..82e5849
Binary files /dev/null and b/Documentation/HTML/images/kshark-filter-sync-graph-1.png differ
diff --git a/Documentation/HTML/images/kshark-filter-task-menu.png b/Documentation/HTML/images/kshark-filter-task-menu.png
new file mode 100644
index 0000000..77fb98a
Binary files /dev/null and b/Documentation/HTML/images/kshark-filter-task-menu.png differ
diff --git a/Documentation/HTML/images/kshark-filter.png b/Documentation/HTML/images/kshark-filter.png
new file mode 100644
index 0000000..0e9a380
Binary files /dev/null and b/Documentation/HTML/images/kshark-filter.png differ
diff --git a/Documentation/HTML/images/kshark-graph-info-line.png b/Documentation/HTML/images/kshark-graph-info-line.png
new file mode 100644
index 0000000..4f6be47
Binary files /dev/null and b/Documentation/HTML/images/kshark-graph-info-line.png differ
diff --git a/Documentation/HTML/images/kshark-graph-plot-area.png b/Documentation/HTML/images/kshark-graph-plot-area.png
new file mode 100644
index 0000000..84ed90e
Binary files /dev/null and b/Documentation/HTML/images/kshark-graph-plot-area.png differ
diff --git a/Documentation/HTML/images/kshark-graph-plot-title.png b/Documentation/HTML/images/kshark-graph-plot-title.png
new file mode 100644
index 0000000..cbb8d2d
Binary files /dev/null and b/Documentation/HTML/images/kshark-graph-plot-title.png differ
diff --git a/Documentation/HTML/images/kshark-list-adjust.png b/Documentation/HTML/images/kshark-list-adjust.png
new file mode 100644
index 0000000..aff15c1
Binary files /dev/null and b/Documentation/HTML/images/kshark-list-adjust.png differ
diff --git a/Documentation/HTML/images/kshark-list-enable-filter-1.png b/Documentation/HTML/images/kshark-list-enable-filter-1.png
new file mode 100644
index 0000000..8321c92
Binary files /dev/null and b/Documentation/HTML/images/kshark-list-enable-filter-1.png differ
diff --git a/Documentation/HTML/images/kshark-list-graph-follow-1.png b/Documentation/HTML/images/kshark-list-graph-follow-1.png
new file mode 100644
index 0000000..c4f8702
Binary files /dev/null and b/Documentation/HTML/images/kshark-list-graph-follow-1.png differ
diff --git a/Documentation/HTML/images/kshark-list-graph-follow-2.png b/Documentation/HTML/images/kshark-list-graph-follow-2.png
new file mode 100644
index 0000000..451de10
Binary files /dev/null and b/Documentation/HTML/images/kshark-list-graph-follow-2.png differ
diff --git a/Documentation/HTML/images/kshark-list-info-area.png b/Documentation/HTML/images/kshark-list-info-area.png
new file mode 100644
index 0000000..394dfdd
Binary files /dev/null and b/Documentation/HTML/images/kshark-list-info-area.png differ
diff --git a/Documentation/HTML/images/kshark-open.png b/Documentation/HTML/images/kshark-open.png
new file mode 100644
index 0000000..1b201ce
Binary files /dev/null and b/Documentation/HTML/images/kshark-open.png differ
diff --git a/Documentation/HTML/images/kshark-plot-cpu-1.png b/Documentation/HTML/images/kshark-plot-cpu-1.png
new file mode 100644
index 0000000..f49de93
Binary files /dev/null and b/Documentation/HTML/images/kshark-plot-cpu-1.png differ
diff --git a/Documentation/HTML/images/kshark-plot-cpu-2.png b/Documentation/HTML/images/kshark-plot-cpu-2.png
new file mode 100644
index 0000000..c1ea7d1
Binary files /dev/null and b/Documentation/HTML/images/kshark-plot-cpu-2.png differ
diff --git a/Documentation/HTML/images/kshark-plot-cpu-result.png b/Documentation/HTML/images/kshark-plot-cpu-result.png
new file mode 100644
index 0000000..635ddda
Binary files /dev/null and b/Documentation/HTML/images/kshark-plot-cpu-result.png differ
diff --git a/Documentation/HTML/images/kshark-plot-menu.png b/Documentation/HTML/images/kshark-plot-menu.png
new file mode 100644
index 0000000..a26f052
Binary files /dev/null and b/Documentation/HTML/images/kshark-plot-menu.png differ
diff --git a/Documentation/HTML/images/kshark-plot-task-measure-preempt.png b/Documentation/HTML/images/kshark-plot-task-measure-preempt.png
new file mode 100644
index 0000000..243aef1
Binary files /dev/null and b/Documentation/HTML/images/kshark-plot-task-measure-preempt.png differ
diff --git a/Documentation/HTML/images/kshark-plot-task-measure.png b/Documentation/HTML/images/kshark-plot-task-measure.png
new file mode 100644
index 0000000..d4b7149
Binary files /dev/null and b/Documentation/HTML/images/kshark-plot-task-measure.png differ
diff --git a/Documentation/HTML/images/kshark-plot-task-result.png b/Documentation/HTML/images/kshark-plot-task-result.png
new file mode 100644
index 0000000..12bbf8b
Binary files /dev/null and b/Documentation/HTML/images/kshark-plot-task-result.png differ
diff --git a/Documentation/HTML/images/kshark-plot-task-select.png b/Documentation/HTML/images/kshark-plot-task-select.png
new file mode 100644
index 0000000..be7f365
Binary files /dev/null and b/Documentation/HTML/images/kshark-plot-task-select.png differ
diff --git a/Documentation/HTML/images/kshark-plot-task-zoom-1.png b/Documentation/HTML/images/kshark-plot-task-zoom-1.png
new file mode 100644
index 0000000..716b5c6
Binary files /dev/null and b/Documentation/HTML/images/kshark-plot-task-zoom-1.png differ
diff --git a/Documentation/HTML/images/kshark-select-a-1.png b/Documentation/HTML/images/kshark-select-a-1.png
new file mode 100644
index 0000000..40a6cfa
Binary files /dev/null and b/Documentation/HTML/images/kshark-select-a-1.png differ
diff --git a/Documentation/HTML/images/kshark-select-b-1.png b/Documentation/HTML/images/kshark-select-b-1.png
new file mode 100644
index 0000000..df4df41
Binary files /dev/null and b/Documentation/HTML/images/kshark-select-b-1.png differ
diff --git a/Documentation/HTML/images/kshark-zoom-in-2.png b/Documentation/HTML/images/kshark-zoom-in-2.png
new file mode 100644
index 0000000..25235e5
Binary files /dev/null and b/Documentation/HTML/images/kshark-zoom-in-2.png differ
diff --git a/Documentation/HTML/images/kshark-zoom-in-3.png b/Documentation/HTML/images/kshark-zoom-in-3.png
new file mode 100644
index 0000000..2c55319
Binary files /dev/null and b/Documentation/HTML/images/kshark-zoom-in-3.png differ
diff --git a/Documentation/HTML/images/kshark-zoom-in-select.png b/Documentation/HTML/images/kshark-zoom-in-select.png
new file mode 100644
index 0000000..12c2be7
Binary files /dev/null and b/Documentation/HTML/images/kshark-zoom-in-select.png differ
diff --git a/Documentation/HTML/images/kshark-zoom-out-select.png b/Documentation/HTML/images/kshark-zoom-out-select.png
new file mode 100644
index 0000000..25c7cfe
Binary files /dev/null and b/Documentation/HTML/images/kshark-zoom-out-select.png differ
diff --git a/Documentation/HTML/index.html b/Documentation/HTML/index.html
new file mode 100644
index 0000000..9ab45a1
--- /dev/null
+++ b/Documentation/HTML/index.html
@@ -0,0 +1,631 @@
+
+
+KernelShark
+
+
+
+KernelShark
+
+
+Introduction
+
The Graph View
+
+The List View
+
+Selecting an event
+Graph follows toggle
+
+Filters
+
+Task Filter (filtering processes)
+Event Filter
+
+Advance Event Filter
+
+
+
+
+
+
+
+KernelShark is a front end reader of trace-cmd(1) output. "trace-cmd record"
+and "trace-cmd extract" create a trace.dat (trace-cmd.dat(5)) file.
+kernelshark can read this file and produce a graph and list view of its data.
+
+
+
+
+
+The application has two main viewing areas split by a paned divider. The top half
+is a graphical display of the data and the bottom half is a list view of each
+event. Underneath the menu bar is the graph information area:
+
+
+
+
+
+
+
+The graph information line displays the timestamp of various locations.
+The Pointer: shows the timestamp of where the mouse pointer is. The Cursor: is
+the timestamp of the cursor location. To select a cursor location, double click
+on the graph. Marker A is set with a left mouse click and Marker B is set
+with a with a left mouse click while holding down the shift key.
+
+
+
+The graph is broken into two parts, the plot title section:
+
+
+
+
+
+
+
+and the plot area:
+
+
+
+
+
+The plot area contains the data of the given plot, where plots can be per CPU or
+per process. The top of the plot area shows a time line. The numbers in the time
+line are seconds. The time in the time line is taken from the timestamps within
+the trace.dat file which are architecture dependent. The time usually is the timestamp
+from when the system started.
+
+
+
+Below the graph is the list area.
+
+
+
+
+
+
+
+The list area contains the Page of the list. The list can hold a maximum of
+1 million entries per page. If the trace data contains more than a million
+entries, then the list will have more than one page.
+
+
+
+The list area also contains a search field to search for elements in the
+list.
+
+
+
+
+
+The graph view of kernelshark shows graphical plots of the data stored in
+the trace.dat file. The data plots are per CPU or per process.
+When there are too many events within the resolution of the graph,
+the plots will appear as a rainbow colored bar. To make more sense out of
+the graphs, you need to zoom into a given location to see the details of
+that time frame more clearly.
+
+
+
+
+
+To zoom in, left mouse click and hold and then drag the mouse right, release
+to zoom. When you click the left mouse button a line will appear and stay
+at that location. When you move the mouse to the right, another line appears
+and will follow the mouse. When you release the mouse button, the area
+between the two lines become the new width of the screen. That is, the graph
+zooms in until the lines match the width of the screen. This allows you to
+zoom into a specific location.
+
+
+
+
+
+The area that you selected will now become the new width of the viewable area.
+The smaller the selection, the deeper the zoom. Note, that you must select 10
+pixels to zoom in. Less than 10 pixels will cancel the zoom. You can continue zooming
+in until you get mor details.
+
+
+
+
+
+If a plot contains no events within the zoomed in raidus, then the line will be empty,
+as CPU 1 is in the above image. CPU 0 shows two tasks that were running. One task
+is given a pink/red color and the other a green color. The colored box represents
+a task other than idle was running. The small lines that jet out of the box are
+where events occur.
+
+
+
+If you zoom in enough such that a single event has enough room between itself
+and other events, the type of event and the name and PID of the task that was running will appear
+over the event.
+
+
+
+
+
+To zoom back out, left mouse click and hold and then drag the mouse left.
+This time the width between the two lines will become a single pixel.
+The farther apart the lines are, the farther the zoom out will be.
+Zoom out will stop at the width of the full trace.
+
+
+
+
+
+When the mouse is over an event, a tool tip will appear showing the event name,
+the latency data, the event info, the timestamp and the process
+name and process ID.
+
+
+
+
+
+
+
+There are two markers that can be placed on the graph as well as a cursor.
+Marker A is set by a left mouse click. When a marker is set, the
+ graph info area will be updated.
+Marker A is represented by a green line:
+
+
+
+
+
+To set Marker B, press and hold the shift key and click the left mouse button.
+Marker B will show up in red.
+
+
+
+
+
+When both the A and B markers are set, the graph info area
+will show the timestamp of where the A and B markers are, as well as the difference
+between the two. All timestamps are in seconds, with a resolution of microseconds.
+
+
+
+
+
+Double clicking on the graph will set the cursor. The cursor is a blue line, and when
+it is set, it will also select the event in the list view that is the closest event at the
+timeline of where the cursor was selected at.
+
+
+
+
+
+The above shows that list item 217448 (sys_exit) was the closest event to where
+the cursor was selected.
+
+
+
+Note that setting the cursor with double click will also set Marker A.
+
+
+
+
+
+The graph data is represented by plots. The data on the plots is either CPU specific or
+process specific. If it is CPU specific, then the data is the time line of events that
+happened on a given CPU (which CPU is shown in the plot title area).
+If the plot is process specific, then the time line of events is for the given
+process regardless of what CPU it was on at the time. The process name is also shown
+in the plot title area.
+
+
+
+By default, all the CPUs within the loaded trace.dat file are plotted.
+There's two ways to plot a process. One way is to right mouse click over a
+displayed process in the graph and select the plot option. This will add the
+process plot directly underneath the CPU plot that the process was on where
+the right mouse click took place. The other way is to use the plot menu.
+
+
+
+
+
+
+
+Selecting the "Task" menu will bring up a dialog with all the processes (also referred
+to as tasks) that was found in the trace data.
+
+
+
+
+
+Selecting a process in this dialog will add the task plot to the bottom of the graph
+area. Unselecting a process in this dialog will remove the plot.
+
+
+
+
+
+The colors in the process plots are different depending on what CPU the process
+was on at the time. The CPU plots change colors as different processes run
+on the CPU, and the process plots change color depending on what CPU the process
+is running on at a time. This makes it easy to see how much a process
+bounces around the CPUs. Zooming in on a process plot also shows some more
+characteristics of the process.
+
+
+
+
+
+The hollow green box that is shown in front of some events in the process
+plot represents when the task was woken up from a sleeping state to
+when it actually ran. The hollow red box between some events shows that
+the process was preempted by another process even though that process
+was still runnable.
+
+
+
+Since the hollow green box shows the wake up latency of the task, the
+A,B markers can be used to measure that time.
+
+
+
+
+
+The above shows that the epiphany-browser with PID 28072 had a 479 microsecond wake up
+latency. The same can be done with the preemption latency.
+
+
+
+
+
+Selecting the CPU plot menu pops up a dialog that shows the available CPUs that
+can be plotted.
+
+
+
+
+
+Removing a selected CPU and hitting "Apply" will remove that CPU plot.
+
+
+
+
+
+
+
+
+
+
+
+The list view is in the bottom half paned window and can be expanded or shortened
+with the paned handle.
+
+
+
+
+
+The top of the list view contains the list area which has the list page, list
+search, and graph follow toggle button. If more than a million events are stored in the
+list, then each set of million will be on a different page.
+
+
+
+The columns of the list are:
+
+
+
+- # - the index into the list.
+
- CPU - the CPU that the event occurred on.
+
- Time Stamp - The time stamp of the event. This is in seconds with microsecond
+resolution.
+
- PID - The process ID of the task that was running when the event occurred.
+
- Latency - The latency is broken into 5 fields:
+
+ - Interrupts disabled - 'd' if interrupts are enabled, otherwise '.'
+
- Need reschedule - 'N' if the kernel was notified that a schedule is needed, otherwise '.'
+
- In IRQ - 'h' if in a hard IRQ (hardware triggerred), 's' if in a soft IRQ
+ (context where the kernel initiated a the irq handler) or if soft IRQs
+ are disabled, 'H' if in a hard IRQ and soft IRQs are disabled or the hard IRQ
+ triggerred while processing a soft IRQ, otherwise '.'
+
- Preemption counter - The index of the preemption counter. If it is other
+ than zero, then the kernel will not preempt the running processes, even
+ if a schedule has been requested by some event. If the counter is zero,
+ then '.' is shown.
+
- Lock depth - The depth of the big kernel lock being held. The big kernel
+ lock is recusive (same task may acquire it multiple times). On the first
+ acquisition, the depth is zero. This field will be zero or greater, or
+ '.' if the big kernel lock is not held. When the big kernel lock is
+ finally removed from the kernel, this field will go away as well.
+
+ - Event - The name of the event.
+
- Info - The data output of a particular event.
+
+
+
+The list search can find an event based on the contents in a row. Select a column, a
+match criteria and the content to match will find the next row that matches the
+search. The match criteria is one of the following:
+
+
+
+- contains - the row cell of the selected column contains the match data. This works with numbers
+as well.
+
- full match - the row cell of the selected column matches exactly the match data.
+
- does not have - the row cell of the selected column does not contain the match data.
+
+
+
+The search will find the next event that has the matching data within the column.
+
+
+
+
+A single click on a row will select the row, but a double click on a row will select
+that row as well as set the graph cursor to the location of that event. If the plot
+that the event is on is not visible then the graph will adjust it vertical view area
+to show the plot with the selected event. This has no effect on
+graph markers.
+
+
+
+
+
+When the "graph follows" toggle is set, then even a single click on a row
+will move the graph cursor. With the mouse focus on the list, using the keyboard
+up and down arrow keys will move the selection of the list as well as the graph
+cursor.
+
+
+
+
+
+
+
+
+
+The amount of data that can be stored in a trace.dat file can be enourmous.
+To make any sense out of some traces, it may be required to only display various
+events. The same can be true about processes.
+Kernelshark has filters for tasks as well as for events. The task filter
+affects both the graph and the list, but the graph and list each have a separate
+event filter.
+
+
+
+
+
+The task (process) filter is currently set by a right mouse click over
+an event on either the graph or the list view, and by selecting the option to add or remove the
+task to/from the task filter. The tasks within the task filter are the same for
+both the graph and list, but each can be enabled separately.
+
+
+
+There are two types of task filters:
+
+
+
+- Task Filter - only show tasks that are in this filter
+
- Hide Tasks - do not display the tasks within this filter
+
+
+
+If there are any tasks within the Task Filter then only those tasks will be displayed
+when the filter is enabled. Any task within the Hide Tasks filter will not be
+displayed, even if that same task is in the Task Filter.
+
+
+
+
+
+When either filter contains a task, the filter can be enabled.
+
+
+
+
+The scheduling events
+
+
+The events "sched_switch", "sched_wakeup", and "sched_wakeup_new" are treated
+differently by the task filter. Because these events deal with two tasks
+(previous and next, waker and wakee), if either of the tasks should be visible
+then that event is visible regardless if the other task should be hidden.
+This may seem confusing when an event that is hidden shows up in the Task column.
+
+
+
+
+
+The graph and list view each have their own event filter. The event filters
+are enabled through the Filter menu on the top menu-bar.
+
+
+
+
+
+Selecting either the "list events" or "graph events" will bring up the event
+dialog with the events that are visible selected.
+
+
+
+Note: these do not mean that the events exist in the trace.dat file. They are
+selected if the events are not to be hidden. Events that do not exist in the trace
+and will not be displayed regardless of whether or not they are filtered.
+
+
+
+
+
+By clicking on "All" or any of the systems will either deselect all events underneath
+or select all events underneath depending on the previous state of the box being
+selected. By deselecting all events, it makes it easier to enable just a few individual events.
+
+
+
+
+
+If it is desired that the graph and list view have the same events filtered, then just
+set up the desired filtering in one and then synchronize the other through
+the filter menu.
+
+
+
+
+
+- sync graph events with list - will set the graph event filter to be the same
+as what is in the list filter.
+
- sync list events with graph - will set the list event filter to be the same
+as what is in the graph filter.
+
+
+
+
+
+Filtering on events may not be enough. The ability to filter on the content
+of individual events may be needed. In order to accomplish this, the advanced event
+filtering is used. Selecting the "list advanced event" or "graph advanced event"
+from the filter menu will pop up the advanced event filtering dialog.
+The graph and list view each have their own advanced event filter.
+
+
+
+
+
+The "Filter:" entry at the bottom of the dialog is where the advanced filter is
+written. Above that is helper buttons to pick events, operations and event fields.
+The syntax of the filter is:
+
+
+
+ FILTER := EVENTS | EVENTS ':' EXPRESSION
+ EVENTS := EVENTS ',' EVENTS | SYSTEM '/' EVENT | SYSTEM | EVENT
+ SYSTEM := any system name
+ EVENT := any event name
+ EXPRESSION := EXPRESSION BOOL EXPRESSION | '(' EXPRESSION ')' | OPERATION
+ BOOL := '&&' | '||'
+ OPERATION := '!' EXPRESSION | LVALUE CMP RVALUE | LVALUE STRCMP STRVALUE
+ CMP := '>' | '<' | '==' | '>=' | '<=' | '!='
+ STRCMP := '==' | '!=' | '=~' | '!~'
+ RVALUE := integer | FIELD
+ STRVALUE := string (double quoted value) | FIELD
+ LVALUE := FIELD | EXPR
+ EXPR := FIELD OP RVALUE | '(' EXPR ')' | EXPR OP EXPR
+ FIELD := a field name of an event
+ OP := '+' | '-' | '*' | '/' | '<<' | '>>' | '&' | '!'
+
+
+
+Spaces are ignored. The example used in the dialog figure:
+
+
+
+ sched/sched_switch : next_prio < 100 && (prev_prio > 100 && prev_pid != 0)
+
+
+
+The sched/ is not necessary because without it, the filter will process all events
+named sched_switch, and since there is only one event
+that has that name, including the sched/ is redundant.
+
+
+
+The next_prio, prev_prio and prev_pid are all
+event fields of the sched_swich event.
+
+
+
+If just sched was used and the /sched_switch was omitted, it would
+still be a valid filter, but it would behave differently. By just specifying
+a system, the filter will run on all events within that system. When a field
+is encountered that does not belong to an event, then that compare will be set to false.
+
+
+
+ sched : prev_pid != 0
+ sched : !(prev_pid == 0)
+
+
+
+The above two filters are not equivalent. They are for the sched_switch event,
+but not for the other events. The first filter will return false for all events
+that do not contain the prev_pid field, but the second filter would return
+true for all events that do not contain that field. Again, if the event does
+not contain a field, just that compare will be evaluated to false, not the entire
+expression. This means for events that do not have the prev_pid field,
+the above filters would be equivalent to:
+
+
+
+ sched : FALSE
+ sched : !(FALSE)
+
+
+
+By letting the filters contain fields that do not belong to an event be valid,
+allows for various tricks where two events can share the same
+filter.
+
+
+
+ sched_switch, sched_wake.* : next_pid == 1 || pid == 1
+
+
+
+The schedule events that have next_pid and not pid as a field
+will just compare the first part of the || and those events with
+pid but without next_pid will be compared against the second
+part of the ||
+
+
+
+Notice: that event names in the filter can be regular expressions.
+
+
+
+String fields can have regular expressions used in their comparing if
+=~ or !~ are used.
+
+
+
+ sched_switch : next_comm =~ "^events/[23]$"
+
+
+
+Note: When adding an advanced filter, all non advanced filters
+(added by the event filter dialog box) will be removed, and only the advanced
+filters will stay. But non advanced filters may be added after advanced
+filters have been. The events that have advanced filters will be shadowed
+in the event filter dialog:
+
+
+
+
+
+Just do not click on the adavanced filter box and hit "Apply" unless you want to remove
+the adavanced filter. Non advanced filters can now be selected without affecting
+the advanced filters.
+
+
+
+
+
+When adavanced filters already exist when the advanced filter dialog box pops up,
+they will be listed in the area at the top of the dialog. Although
+one filter may have been written, the list will be per event. A check box
+is to the left of the filter, when checked, the filter will be deleted if
+the "Apply" button is selected.
+
+
+
+
+
+
--
cgit v1.2.2
From 9a6f8264525228eab1baee09f567a5d72c05b0ac Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Fri, 9 Apr 2010 12:29:57 -0400
Subject: kernelshark/build: Install HTML doc and reference it
Install the HTML document on "make install_doc" and have the
kernelshark executable be able to reference that location.
Signed-off-by: Steven Rostedt
---
Documentation/Makefile | 20 +++++++++++++++++++-
Makefile | 11 ++++++++++-
kernel-shark.c | 5 ++++-
3 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 7ed8877..8e53773 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -85,7 +85,25 @@ $(MAN1_INSTALL): %.1.install : %.1 force
$(MAN5_INSTALL): %.5.install : %.5 force
$(Q)$(call do_install, $<, '$(man_dir_SQ)/man5')
-install: $(MAN1_INSTALL) $(MAN5_INSTALL)
+html_dir = $(src)/HTML
+image_dir = $(html_dir)/images
+
+HTML = $(wildcard $(html_dir)/*.html)
+IMGS = $(wildcard $(image_dir)/*.png)
+
+HTML_INSTALL = $(subst .html,.html.install,$(HTML))
+IMGS_INSTALL = $(subst .png,.png.install,$(IMGS))
+
+$(HTML_INSTALL): %.html.install : %.html force
+ $(Q)$(call do_install, $<, '$(html_install_SQ)')
+
+$(IMGS_INSTALL): %.png.install : %.png force
+ $(Q)$(call do_install, $<, '$(img_install_SQ)')
+
+
+GUI_INSTALL = $(HTML_INSTALL) $(IMGS_INSTALL)
+
+install: $(MAN1_INSTALL) $(MAN5_INSTALL) $(GUI_INSTALL)
clean:
(cd $(obj); \
diff --git a/Makefile b/Makefile
index 7dde5cf..cded750 100644
--- a/Makefile
+++ b/Makefile
@@ -23,8 +23,13 @@ bindir_relative = bin
bindir = $(prefix)/$(bindir_relative)
man_dir = $(prefix)/share/man
man_dir_SQ = '$(subst ','\'',$(man_dir))'
+html_install = $(prefix)/share/kernelshark/html
+html_install_SQ = '$(subst ','\'',$(html_install))'
+img_install = $(prefix)/share/kernelshark/html/images
+img_install_SQ = '$(subst ','\'',$(img_install))'
-export man_dir man_dir_SQ INSTALL
+export man_dir man_dir_SQ html_install html_install_SQ INSTALL
+export img_install img_install_SQ
ifeq ($(prefix),$(HOME))
plugin_dir = $(HOME)/.trace-cmd/plugins
@@ -34,6 +39,9 @@ PLUGIN_DIR = -DPLUGIN_DIR=$(plugin_dir)
PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))'
endif
+HELP_DIR = -DHELP_DIR=$(html_install)
+HELP_DIR_SQ = '$(subst ','\'',$(HELP_DIR))'
+
# copy a bit from Linux kbuild
ifeq ("$(origin V)", "command line")
@@ -124,6 +132,7 @@ REBUILD_GUI = /bin/true
G =
N = @/bin/true ||
+CONFIG_FLAGS += $(HELP_DIR_SQ)
else
CONFIG_INCLUDES =
diff --git a/kernel-shark.c b/kernel-shark.c
index ee47ff5..b056420 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -36,6 +36,9 @@
#include "kernel-shark.h"
#include "version.h"
+#define ___stringify(X) #X
+#define __stringify(X) ___stringify(X)
+
#define DEBUG_LEVEL 0
#if DEBUG_LEVEL > 0
# define dprintf(l, x...) \
@@ -422,7 +425,7 @@ help_content_clicked (gpointer data)
GError *error = NULL;
gchar *link;
- link = "http://www.google.com";
+ link = "file://" __stringify(HELP_DIR) "/index.html";
trace_show_help(info->window, link, &error);
}
--
cgit v1.2.2
From d2c42a8b5238abd33f33e6fe9ae8b48b8670f981 Mon Sep 17 00:00:00 2001
From: Randy Dunlap
Date: Fri, 9 Apr 2010 13:24:54 -0400
Subject: doc: Fix typos and grammar in kernelshark help
Signed-off-by: Randy Dunlap
Signed-off-by: Steven Rostedt
---
Documentation/HTML/index.html | 58 +++++++++++++++++++++----------------------
1 file changed, 29 insertions(+), 29 deletions(-)
diff --git a/Documentation/HTML/index.html b/Documentation/HTML/index.html
index 9ab45a1..8b3062d 100644
--- a/Documentation/HTML/index.html
+++ b/Documentation/HTML/index.html
@@ -133,13 +133,13 @@ zoom into a specific location.
The area that you selected will now become the new width of the viewable area.
The smaller the selection, the deeper the zoom. Note, that you must select 10
pixels to zoom in. Less than 10 pixels will cancel the zoom. You can continue zooming
-in until you get mor details.
+in until you get more details.
-If a plot contains no events within the zoomed in raidus, then the line will be empty,
+If a plot contains no events within the zoomed in radius, then the line will be empty,
as CPU 1 is in the above image. CPU 0 shows two tasks that were running. One task
is given a pink/red color and the other a green color. The colored box represents
a task other than idle was running. The small lines that jet out of the box are
@@ -200,7 +200,7 @@ between the two. All timestamps are in seconds, with a resolution of microsecond
Double clicking on the graph will set the cursor. The cursor is a blue line, and when
it is set, it will also select the event in the list view that is the closest event at the
-timeline of where the cursor was selected at.
+timeline of where the cursor was selected.
@@ -227,10 +227,10 @@ in the plot title area.
By default, all the CPUs within the loaded trace.dat file are plotted.
-There's two ways to plot a process. One way is to right mouse click over a
+There are two ways to plot a process. One way is to right mouse click over a
displayed process in the graph and select the plot option. This will add the
process plot directly underneath the CPU plot that the process was on where
-the right mouse click took place. The other way is to use the plot menu.
+the right mouse click took place. The other way is to use the Plots menu.
@@ -238,8 +238,8 @@ the right mouse click took place. The other way is to use the plot menu.
-Selecting the "Task" menu will bring up a dialog with all the processes (also referred
-to as tasks) that was found in the trace data.
+Selecting the "Tasks" menu item will bring up a dialog with all the processes (also referred
+to as tasks) that were found in the trace data.
@@ -287,7 +287,7 @@ latency. The same can be done with the preemption latency.
-Selecting the CPU plot menu pops up a dialog that shows the available CPUs that
+Selecting the "CPUs" plot menu item pops up a dialog that shows the available CPUs that
can be plotted.
@@ -314,7 +314,7 @@ with the paned handle.
The top of the list view contains the list area which has the list page, list
-search, and graph follow toggle button. If more than a million events are stored in the
+search, and "graph follows" toggle button. If more than a million events are stored in the
list, then each set of million will be on a different page.
@@ -330,10 +330,10 @@ resolution.
PID - The process ID of the task that was running when the event occurred.
Latency - The latency is broken into 5 fields:
- - Interrupts disabled - 'd' if interrupts are enabled, otherwise '.'
+
- Interrupts disabled - 'd' if interrupts are disabled, otherwise '.'
- Need reschedule - 'N' if the kernel was notified that a schedule is needed, otherwise '.'
- In IRQ - 'h' if in a hard IRQ (hardware triggerred), 's' if in a soft IRQ
- (context where the kernel initiated a the irq handler) or if soft IRQs
+ (context where the kernel initiated a the IRQ handler) or if soft IRQs
are disabled, 'H' if in a hard IRQ and soft IRQs are disabled or the hard IRQ
triggerred while processing a soft IRQ, otherwise '.'
- Preemption counter - The index of the preemption counter. If it is other
@@ -341,7 +341,7 @@ resolution.
if a schedule has been requested by some event. If the counter is zero,
then '.' is shown.
- Lock depth - The depth of the big kernel lock being held. The big kernel
- lock is recusive (same task may acquire it multiple times). On the first
+ lock is recursive (same task may acquire it multiple times). On the first
acquisition, the depth is zero. This field will be zero or greater, or
'.' if the big kernel lock is not held. When the big kernel lock is
finally removed from the kernel, this field will go away as well.
@@ -352,8 +352,8 @@ resolution.
The list search can find an event based on the contents in a row. Select a column, a
-match criteria and the content to match will find the next row that matches the
-search. The match criteria is one of the following:
+match criteria and the content to match to find the next row that matches the
+search. The match criterion is one of the following:
@@ -371,7 +371,7 @@ The search will find the next event that has the matching data within the column
A single click on a row will select the row, but a double click on a row will select
that row as well as set the graph cursor to the location of that event. If the plot
-that the event is on is not visible then the graph will adjust it vertical view area
+that the event is on is not visible then the graph will adjust its vertical view area
to show the plot with the selected event. This has no effect on
graph markers.
@@ -392,7 +392,7 @@ cursor.
-The amount of data that can be stored in a trace.dat file can be enourmous.
+The amount of data that can be stored in a trace.dat file can be enormous.
To make any sense out of some traces, it may be required to only display various
events. The same can be true about processes.
Kernelshark has filters for tasks as well as for events. The task filter
@@ -459,13 +459,13 @@ dialog with the events that are visible selected.
Note: these do not mean that the events exist in the trace.dat file. They are
selected if the events are not to be hidden. Events that do not exist in the trace
-and will not be displayed regardless of whether or not they are filtered.
+will not be displayed regardless of whether or not they are filtered.
-By clicking on "All" or any of the systems will either deselect all events underneath
+Clicking on "All" or any of the systems will either deselect all events underneath
or select all events underneath depending on the previous state of the box being
selected. By deselecting all events, it makes it easier to enable just a few individual events.
@@ -487,13 +487,13 @@ as what is in the list filter.
as what is in the graph filter.
-
+
Filtering on events may not be enough. The ability to filter on the content
of individual events may be needed. In order to accomplish this, the advanced event
filtering is used. Selecting the "list advanced event" or "graph advanced event"
-from the filter menu will pop up the advanced event filtering dialog.
+from the Filter menu will pop up the advanced event filtering dialog.
The graph and list view each have their own advanced event filter.
@@ -570,7 +570,7 @@ the above filters would be equivalent to:
-By letting the filters contain fields that do not belong to an event be valid,
+Letting filters contain fields that do not belong to an event be valid
allows for various tricks where two events can share the same
filter.
@@ -587,7 +587,7 @@ part of the ||
-Notice: that event names in the filter can be regular expressions.
+Notice that event names in the filter can be regular expressions.
@@ -600,28 +600,28 @@ String fields can have regular expressions used in their comparing if
-Note: When adding an advanced filter, all non advanced filters
+Note: When adding an advanced filter, all non-advanced filters
(added by the event filter dialog box) will be removed, and only the advanced
-filters will stay. But non advanced filters may be added after advanced
-filters have been. The events that have advanced filters will be shadowed
+filters will stay. But non-advanced filters may be added after advanced
+filters have been. The events that have advanced filters will be shaded
in the event filter dialog:
-Just do not click on the adavanced filter box and hit "Apply" unless you want to remove
-the adavanced filter. Non advanced filters can now be selected without affecting
+Just do not click on the advanced filter box and hit "Apply" unless you want to remove
+the advanced filter. Non-advanced filters can now be selected without affecting
the advanced filters.
-When adavanced filters already exist when the advanced filter dialog box pops up,
+When advanced filters already exist when the advanced filter dialog box pops up,
they will be listed in the area at the top of the dialog. Although
one filter may have been written, the list will be per event. A check box
-is to the left of the filter, when checked, the filter will be deleted if
+is to the left of the filter. When checked, the filter will be deleted if
the "Apply" button is selected.
--
cgit v1.2.2
From 04b2e439a93677bc6ef5035729bf05e7427ac13e Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Fri, 9 Apr 2010 14:40:25 -0400
Subject: doc: Fixed more types and cleared up some explanations
Reported-by: Darren Hart
Signed-off-by: Steven Rostedt
---
Documentation/HTML/index.html | 100 ++++++++++++++++++++++++++----------------
1 file changed, 61 insertions(+), 39 deletions(-)
diff --git a/Documentation/HTML/index.html b/Documentation/HTML/index.html
index 8b3062d..331baf4 100644
--- a/Documentation/HTML/index.html
+++ b/Documentation/HTML/index.html
@@ -16,7 +16,7 @@
- Graph Cursor
- Graph Plots
-
- Process Plots
+
- Task Plots
- CPU Plots
@@ -27,7 +27,7 @@
Filters
-- Task Filter (filtering processes)
+
- Task Filter
- Event Filter
- Advance Event Filter
@@ -79,7 +79,7 @@ and the plot area:
The plot area contains the data of the given plot, where plots can be per CPU or
-per process. The top of the plot area shows a time line. The numbers in the time
+per task. The top of the plot area shows a time line. The numbers in the time
line are seconds. The time in the time line is taken from the timestamps within
the trace.dat file which are architecture dependent. The time usually is the timestamp
from when the system started.
@@ -108,7 +108,7 @@ list.
The graph view of kernelshark shows graphical plots of the data stored in
-the trace.dat file. The data plots are per CPU or per process.
+the trace.dat file. The data plots are per CPU or per task.
When there are too many events within the resolution of the graph,
the plots will appear as a rainbow colored bar. To make more sense out of
the graphs, you need to zoom into a given location to see the details of
@@ -139,11 +139,17 @@ in until you get more details.
-If a plot contains no events within the zoomed in radius, then the line will be empty,
-as CPU 1 is in the above image. CPU 0 shows two tasks that were running. One task
-is given a pink/red color and the other a green color. The colored box represents
-a task other than idle was running. The small lines that jet out of the box are
-where events occur.
+To save on resources, when zooming in, the beginning
+and end of the full trace may not be reachable with the horizontal scroll bar.
+If a plot contains no events within the reachable area, then the line will be empty,
+as CPU 1 is in the above image.
+
+
+
+CPU 0 shows two tasks that were running. One task
+is given a pink/red color and the other a green color. The think colored
+horizontal bar represents a task other than idle was running. The small
+lines that jet out of the bar are where events occur.
@@ -165,8 +171,8 @@ Zoom out will stop at the width of the full trace.
When the mouse is over an event, a tool tip will appear showing the event name,
-the latency data, the event info, the timestamp and the process
-name and process ID.
+the latency data, the event info, the timestamp and the task
+name and task process ID.
@@ -218,60 +224,60 @@ Note that setting the cursor with double click will also set Marker A.
The graph data is represented by plots. The data on the plots is either CPU specific or
-process specific. If it is CPU specific, then the data is the time line of events that
+task specific. If it is CPU specific, then the data is the time line of events that
happened on a given CPU (which CPU is shown in the plot title area).
-If the plot is process specific, then the time line of events is for the given
-process regardless of what CPU it was on at the time. The process name is also shown
+If the plot is task specific, then the time line of events is for the given
+task regardless of what CPU it was on at the time. The task name is also shown
in the plot title area.
By default, all the CPUs within the loaded trace.dat file are plotted.
-There are two ways to plot a process. One way is to right mouse click over a
-displayed process in the graph and select the plot option. This will add the
-process plot directly underneath the CPU plot that the process was on where
+There are two ways to plot a task. One way is to right mouse click over a
+displayed task in the graph and select the plot option. This will add the
+task plot directly underneath the CPU plot that the task was on where
the right mouse click took place. The other way is to use the Plots menu.
-
+
-Selecting the "Tasks" menu item will bring up a dialog with all the processes (also referred
-to as tasks) that were found in the trace data.
+Selecting the "Tasks" menu item will bring up a dialog with all the tasks
+that were found in the trace data.
-Selecting a process in this dialog will add the task plot to the bottom of the graph
-area. Unselecting a process in this dialog will remove the plot.
+Selecting a task in this dialog will add the task plot to the bottom of the graph
+area. Unselecting a task in this dialog will remove the plot.
-The colors in the process plots are different depending on what CPU the process
-was on at the time. The CPU plots change colors as different processes run
-on the CPU, and the process plots change color depending on what CPU the process
-is running on at a time. This makes it easy to see how much a process
-bounces around the CPUs. Zooming in on a process plot also shows some more
-characteristics of the process.
+The colors in the task plots are different depending on which CPU the task
+was on at the time. The CPU plots change colors as different tasks run
+on the CPU, and the task plots change color depending on what CPU the task
+is running on. This makes it easy to see how much a task
+bounces around the CPUs. Zooming in on a task plot also shows some more
+characteristics of the task.
-The hollow green box that is shown in front of some events in the process
+The hollow green bar that is shown in front of some events in the task
plot represents when the task was woken up from a sleeping state to
-when it actually ran. The hollow red box between some events shows that
-the process was preempted by another process even though that process
+when it actually ran. The hollow red bar between some events shows that
+the task was preempted by another task even though that task
was still runnable.
-Since the hollow green box shows the wake up latency of the task, the
+Since the hollow green bar shows the wake up latency of the task, the
A,B markers can be used to measure that time.
@@ -284,7 +290,7 @@ latency. The same can be done with the preemption latency.
-
Selecting the "CPUs" plot menu item pops up a dialog that shows the available CPUs that
@@ -332,12 +338,12 @@ resolution.
- Interrupts disabled - 'd' if interrupts are disabled, otherwise '.'
- Need reschedule - 'N' if the kernel was notified that a schedule is needed, otherwise '.'
-
- In IRQ - 'h' if in a hard IRQ (hardware triggerred), 's' if in a soft IRQ
+
- In IRQ - 'h' if in a hard IRQ (hardware triggered), 's' if in a soft IRQ
(context where the kernel initiated a the IRQ handler) or if soft IRQs
are disabled, 'H' if in a hard IRQ and soft IRQs are disabled or the hard IRQ
- triggerred while processing a soft IRQ, otherwise '.'
+ triggered while processing a soft IRQ, otherwise '.'
- Preemption counter - The index of the preemption counter. If it is other
- than zero, then the kernel will not preempt the running processes, even
+ than zero, then the kernel will not preempt the running tasks, even
if a schedule has been requested by some event. If the counter is zero,
then '.' is shown.
- Lock depth - The depth of the big kernel lock being held. The big kernel
@@ -394,16 +400,16 @@ cursor.
The amount of data that can be stored in a trace.dat file can be enormous.
To make any sense out of some traces, it may be required to only display various
-events. The same can be true about processes.
+events. The same can be true about tasks.
Kernelshark has filters for tasks as well as for events. The task filter
affects both the graph and the list, but the graph and list each have a separate
event filter.
-
Task Filter (filtering processes)
+Task Filter
-The task (process) filter is currently set by a right mouse click over
+The task filter is currently set by a right mouse click over
an event on either the graph or the list view, and by selecting the option to add or remove the
task to/from the task filter. The tasks within the task filter are the same for
both the graph and list, but each can be enabled separately.
@@ -432,6 +438,18 @@ When either filter contains a task, the filter can be enabled.
+
+When a task is not in the "Task Filter", the pop up will show the
+menu item "Add task". When a task is in the "Task Filter" the
+pop up will show "Remove task".
+
+
+
+When a task is not in the "Hide Tasks", the pop up will show the
+menu item "Hide task". When a task is in the "Hide Tasks", the
+pop up will show "Show task".
+
+
The scheduling events
@@ -599,6 +617,10 @@ String fields can have regular expressions used in their comparing if
sched_switch : next_comm =~ "^events/[23]$"
+
+The available regular expressions are described in regex(7).
+
+
Note: When adding an advanced filter, all non-advanced filters
(added by the event filter dialog box) will be removed, and only the advanced
--
cgit v1.2.2
From 7f16dcb25f80f09978c762e23aca70882397ab05 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Fri, 9 Apr 2010 16:33:55 -0400
Subject: doc: Use timestamp and timeline instead of time stamp and time line
The document is inconsistent with its use of time stamp and timestamp
as well as time line and timeline. This patch changes them all to
be single words, except when referencing the GUI labels which have
the space.
Reported-by: Randy Dunlap
Signed-off-by: Steven Rostedt
---
Documentation/HTML/index.html | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/Documentation/HTML/index.html b/Documentation/HTML/index.html
index 331baf4..12c9957 100644
--- a/Documentation/HTML/index.html
+++ b/Documentation/HTML/index.html
@@ -79,8 +79,8 @@ and the plot area:
The plot area contains the data of the given plot, where plots can be per CPU or
-per task. The top of the plot area shows a time line. The numbers in the time
-line are seconds. The time in the time line is taken from the timestamps within
+per task. The top of the plot area shows a timeline. The numbers in the timeline
+are seconds. The time in the timeline is taken from the timestamps within
the trace.dat file which are architecture dependent. The time usually is the timestamp
from when the system started.
@@ -224,9 +224,9 @@ Note that setting the cursor with double click will also set Marker A.
The graph data is represented by plots. The data on the plots is either CPU specific or
-task specific. If it is CPU specific, then the data is the time line of events that
+task specific. If it is CPU specific, then the data is the timeline of events that
happened on a given CPU (which CPU is shown in the plot title area).
-If the plot is task specific, then the time line of events is for the given
+If the plot is task specific, then the timeline of events is for the given
task regardless of what CPU it was on at the time. The task name is also shown
in the plot title area.
@@ -331,7 +331,7 @@ The columns of the list are:
- # - the index into the list.
- CPU - the CPU that the event occurred on.
-
- Time Stamp - The time stamp of the event. This is in seconds with microsecond
+
- Time Stamp - The timestamp of the event. This is in seconds with microsecond
resolution.
- PID - The process ID of the task that was running when the event occurred.
- Latency - The latency is broken into 5 fields:
--
cgit v1.2.2
From 26a64b58674a53e1299c5af9b090bbce0eb2f1f8 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Tue, 18 May 2010 11:04:30 -0400
Subject: trace-cmd: Fix reading of print strings
The code that cleaned up parsing the printk_format file never registered
the formats to the pevent code. Any trace_printk() that used bprint()
was not able to be parsed.
Signed-off-by: Steven Rostedt
---
trace-cmd.h | 2 +-
trace-input.c | 2 +-
trace-util.c | 4 +++-
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/trace-cmd.h b/trace-cmd.h
index cc11cdf..643d394 100644
--- a/trace-cmd.h
+++ b/trace-cmd.h
@@ -26,7 +26,7 @@
void parse_cmdlines(struct pevent *pevent, char *file, int size);
void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size);
-void parse_ftrace_printk(char *file, unsigned int size);
+void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size);
extern int tracecmd_disable_sys_plugins;
extern int tracecmd_disable_plugins;
diff --git a/trace-input.c b/trace-input.c
index 9b0e509..c39004a 100644
--- a/trace-input.c
+++ b/trace-input.c
@@ -440,7 +440,7 @@ static int read_ftrace_printk(struct tracecmd_input *handle)
return -1;
}
- parse_ftrace_printk(buf, size);
+ parse_ftrace_printk(handle->pevent, buf, size);
free(buf);
diff --git a/trace-util.c b/trace-util.c
index 0397732..de2cb28 100644
--- a/trace-util.c
+++ b/trace-util.c
@@ -104,7 +104,8 @@ void parse_proc_kallsyms(struct pevent *pevent,
}
}
-void parse_ftrace_printk(char *file, unsigned int size __unused)
+void parse_ftrace_printk(struct pevent *pevent,
+ char *file, unsigned int size __unused)
{
unsigned long long addr;
char *printk;
@@ -124,6 +125,7 @@ void parse_ftrace_printk(char *file, unsigned int size __unused)
/* fmt still has a space, skip it */
printk = strdup(fmt+1);
line = strtok_r(NULL, "\n", &next);
+ pevent_register_print_string(pevent, printk, addr);
}
}
--
cgit v1.2.2
From 7327b8f423f55873d30d523e882bb8fd9338e1ac Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Thu, 27 May 2010 18:14:36 -0400
Subject: trace-graph: Fix pop up for hide task
The pop up said "Hide task to filter" which does not make any sense.
Change it to just "Hide task".
Signed-off-by: Steven Rostedt
---
trace-graph.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/trace-graph.c b/trace-graph.c
index 8050226..9e5cd19 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -728,9 +728,9 @@ do_pop_up(GtkWidget *widget, GdkEventButton *event, gpointer data)
text);
if (trace_graph_hide_task_find_pid(ginfo, pid))
- snprintf(text, len, "Show %s-%d to filter", comm, pid);
+ snprintf(text, len, "Show %s-%d", comm, pid);
else
- snprintf(text, len, "Hide %s-%d to filter", comm, pid);
+ snprintf(text, len, "Hide %s-%d", comm, pid);
gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_hide_task),
text);
@@ -752,7 +752,7 @@ do_pop_up(GtkWidget *widget, GdkEventButton *event, gpointer data)
gtk_widget_set_sensitive(menu_filter_add_task, FALSE);
gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_hide_task),
- "Hide task to filter");
+ "Hide task");
gtk_widget_set_sensitive(menu_filter_hide_task, FALSE);
gtk_widget_hide(menu_plot_task);
--
cgit v1.2.2
From 19c146cbf37c95cf77319569d1beff35fd8d544b Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Tue, 1 Jun 2010 11:09:01 -0400
Subject: kernelshark: Allow for separate list and graph task filters
To make the task filters more like the event filters, allow the
list and graph to have their own filtering.
Signed-off-by: Steven Rostedt
---
kernel-shark.c | 448 +++++++++++++++++++++++++++++++++++++++++++++++------
kernel-shark.h | 5 +
trace-graph.c | 14 ++
trace-graph.h | 3 +
trace-view-store.c | 1 -
5 files changed, 424 insertions(+), 47 deletions(-)
diff --git a/kernel-shark.c b/kernel-shark.c
index b056420..e591657 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -64,6 +64,68 @@ void usage(char *prog)
printf(" -i input_file, default is %s\n", default_input_file);
}
+/*
+ * trace_sync_select_menu - helper function to the syncing of list and graph filters
+ *
+ * Creates a pop up dialog with the selections given. The selections will be
+ * radio buttons to the user. The keep is a value that will be set to the check
+ * box (default on) if the user wants to keep the selection persistant.
+ */
+static int trace_sync_select_menu(const gchar *title,
+ gchar **selections, gboolean *keep)
+{
+ GtkWidget *dialog;
+ GtkWidget *radio;
+ GtkWidget *check;
+ GSList *group;
+ int result;
+ int i;
+
+ dialog = gtk_dialog_new_with_buttons(title,
+ NULL,
+ GTK_DIALOG_MODAL,
+ "OK", GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ NULL);
+
+ radio = gtk_radio_button_new_with_label(NULL, selections[0]);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), radio, TRUE, TRUE, 0);
+ gtk_widget_show(radio);
+
+ group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio));
+
+ for (i = 1; selections[i]; i++) {
+ radio = gtk_radio_button_new_with_label(group, selections[i]);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), radio, TRUE, TRUE, 0);
+ gtk_widget_show(radio);
+ }
+
+ check = gtk_check_button_new_with_label("Keep the filters in sync?");
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), check, TRUE, TRUE, 0);
+ gtk_widget_show(check);
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
+
+ result = gtk_dialog_run(GTK_DIALOG(dialog));
+ switch (result) {
+ case GTK_RESPONSE_ACCEPT:
+ i = 0;
+ for (i = 0; group; i++, group = g_slist_next(group)) {
+ radio = group->data;
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio)))
+ break;
+ }
+ result = i;
+ *keep = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check));
+ break;
+ default:
+ result = -1;
+ }
+
+ gtk_widget_destroy(dialog);
+ return result;
+}
+
/* graph callbacks */
/* convert_nano() and print_time() are copied from trace-graph.c for debugging
@@ -113,15 +175,30 @@ static void ks_graph_filter(struct graph_info *ginfo,
cbs = trace_graph_get_callbacks(ginfo);
info = container_of(cbs, struct shark_info, graph_cbs);
+ if (!info->sync_task_filters)
+ return;
+
if (info->list_filter_enabled)
trace_view_update_filters(info->treeview,
task_filter, hide_tasks);
+
+ if (filter_task_count(task_filter) ||
+ filter_task_count(hide_tasks))
+ info->list_filter_available = 1;
+ else {
+ info->list_filter_enabled = 0;
+ info->list_filter_available = 0;
+ }
}
static void free_info(struct shark_info *info)
{
tracecmd_close(info->handle);
trace_graph_free_info(info->ginfo);
+
+ filter_task_hash_free(info->list_task_filter);
+ filter_task_hash_free(info->list_hide_tasks);
+
free(info->ginfo);
free(info);
}
@@ -242,6 +319,99 @@ delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
return TRUE;
}
+/* Callback for the clicked signal of the Events filter button */
+static void
+sync_task_filter_clicked (GtkWidget *subitem, gpointer data)
+{
+ struct shark_info *info = data;
+ struct filter_task *task_filter;
+ struct filter_task *hide_tasks;
+ GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview);
+ GtkTreeModel *model;
+ TraceViewStore *store;
+ gboolean keep;
+ gchar *selections[] = { "Sync List Filter with Graph Filter",
+ "Sync Graph Filter with List Filter",
+ NULL };
+ int result;
+
+ if (info->sync_task_filters) {
+ /* Separate the List and Graph filters */
+
+ info->sync_task_filters = 0;
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->task_sync_menu),
+ "Sync Graph and List Task Filters");
+
+ /* The list now uses its own hash */
+ info->list_task_filter = filter_task_hash_copy(info->ginfo->task_filter);
+ info->list_hide_tasks = filter_task_hash_copy(info->ginfo->hide_tasks);
+ return;
+ }
+
+ model = gtk_tree_view_get_model(trace_tree);
+ if (!model)
+ return;
+
+ store = TRACE_VIEW_STORE(model);
+
+ /* Ask user which way to sync */
+ result = trace_sync_select_menu("Sync Task Filters",
+ selections, &keep);
+
+ switch (result) {
+ case 0:
+ /* Sync List Filter with Graph Filter */
+ filter_task_hash_free(info->list_task_filter);
+ filter_task_hash_free(info->list_hide_tasks);
+
+ info->list_task_filter = NULL;
+ info->list_hide_tasks = NULL;
+
+ task_filter = info->ginfo->task_filter;
+ hide_tasks = info->ginfo->hide_tasks;
+
+ if (!keep) {
+ info->list_task_filter = filter_task_hash_copy(task_filter);
+ info->list_hide_tasks = filter_task_hash_copy(hide_tasks);
+ }
+
+ if (info->list_filter_enabled)
+ trace_view_update_filters(info->treeview,
+ task_filter, hide_tasks);
+
+ if (!filter_task_count(task_filter) &&
+ !filter_task_count(hide_tasks)) {
+ info->list_filter_enabled = 0;
+ info->list_filter_available = 0;
+ } else
+ info->list_filter_available = 1;
+
+ break;
+ case 1:
+ /* Sync Graph Filter with List Filter */
+ trace_graph_update_filters(info->ginfo,
+ info->list_task_filter,
+ info->list_hide_tasks);
+
+ if (keep) {
+ filter_task_hash_free(info->list_task_filter);
+ filter_task_hash_free(info->list_hide_tasks);
+
+ info->list_task_filter = NULL;
+ info->list_hide_tasks = NULL;
+ }
+ break;
+ default:
+ keep = 0;
+ }
+
+ if (keep) {
+ info->sync_task_filters = 1;
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->task_sync_menu),
+ "Unsync Graph and List Task Filters");
+ }
+}
+
/* Callback for the clicked signal of the Events filter button */
static void
list_events_clicked (gpointer data)
@@ -510,26 +680,70 @@ static void
filter_list_enable_clicked (gpointer data)
{
struct shark_info *info = data;
+ struct filter_task *task_filter;
+ struct filter_task *hide_tasks;
info->list_filter_enabled ^= 1;
+ if (info->sync_task_filters) {
+ task_filter = info->ginfo->task_filter;
+ hide_tasks = info->ginfo->hide_tasks;
+ } else {
+ task_filter = info->list_task_filter;
+ hide_tasks = info->list_hide_tasks;
+ }
+
if (info->list_filter_enabled)
trace_view_update_filters(info->treeview,
- info->ginfo->task_filter,
- info->ginfo->hide_tasks);
+ task_filter, hide_tasks);
else
trace_view_update_filters(info->treeview, NULL, NULL);
}
+static void
+filter_update_list_filter(struct shark_info *info,
+ struct filter_task *filter,
+ struct filter_task *other_filter)
+{
+ struct filter_task_item *task;
+ int pid = info->selected_task;
+
+ task = filter_task_find_pid(filter, pid);
+ if (task) {
+ filter_task_remove_pid(filter, pid);
+ if (!filter_task_count(filter) &&
+ !filter_task_count(other_filter)) {
+ info->list_filter_enabled = 0;
+ info->list_filter_available = 0;
+ }
+ } else {
+ filter_task_add_pid(filter, pid);
+ info->list_filter_available = 1;
+ }
+}
+
static void
filter_add_task_clicked (gpointer data)
{
struct shark_info *info = data;
+ int pid = info->selected_task;
- trace_graph_filter_add_remove_task(info->ginfo, info->selected_task);
+ if (info->sync_task_filters) {
+ trace_graph_filter_add_remove_task(info->ginfo, pid);
+ return;
+ }
- if (!filter_task_count(info->ginfo->task_filter))
- info->list_filter_enabled = 0;
+ filter_update_list_filter(info, info->list_task_filter, info->list_hide_tasks);
+ trace_view_update_filters(info->treeview,
+ info->list_task_filter, info->list_hide_tasks);
+}
+
+static void
+filter_graph_add_task_clicked (gpointer data)
+{
+ struct shark_info *info = data;
+
+ trace_graph_filter_add_remove_task(info->ginfo, info->selected_task);
}
static void
@@ -537,11 +751,22 @@ filter_hide_task_clicked (gpointer data)
{
struct shark_info *info = data;
- trace_graph_filter_hide_show_task(info->ginfo, info->selected_task);
+ if (info->sync_task_filters) {
+ trace_graph_filter_hide_show_task(info->ginfo, info->selected_task);
+ return;
+ }
- if (!filter_task_count(info->ginfo->task_filter) &&
- !filter_task_count(info->ginfo->hide_tasks))
- info->list_filter_enabled = 0;
+ filter_update_list_filter(info, info->list_hide_tasks, info->list_task_filter);
+ trace_view_update_filters(info->treeview,
+ info->list_task_filter, info->list_hide_tasks);
+}
+
+static void
+filter_graph_hide_task_clicked (gpointer data)
+{
+ struct shark_info *info = data;
+
+ trace_graph_filter_hide_show_task(info->ginfo, info->selected_task);
}
static void
@@ -549,11 +774,27 @@ filter_clear_tasks_clicked (gpointer data)
{
struct shark_info *info = data;
- trace_graph_clear_tasks(info->ginfo);
+ if (info->sync_task_filters) {
+ trace_graph_clear_tasks(info->ginfo);
+ return;
+ }
+ filter_task_clear(info->list_task_filter);
+ filter_task_clear(info->list_hide_tasks);
+ trace_view_update_filters(info->treeview, NULL, NULL);
+
+ info->list_filter_available = 0;
info->list_filter_enabled = 0;
}
+static void
+filter_graph_clear_tasks_clicked (gpointer data)
+{
+ struct shark_info *info = data;
+
+ trace_graph_clear_tasks(info->ginfo);
+}
+
static void graph_check_toggle(gpointer data, GtkWidget *widget)
{
struct shark_info *info = data;
@@ -561,6 +802,17 @@ static void graph_check_toggle(gpointer data, GtkWidget *widget)
info->graph_follows = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
}
+static void set_menu_label(GtkWidget *menu, const char *comm, int pid,
+ const char *fmt)
+{
+ int len = strlen(comm) + strlen(fmt) + 50;
+ char text[len];
+
+ snprintf(text, len, fmt, comm, pid);
+
+ gtk_menu_item_set_label(GTK_MENU_ITEM(menu), text);
+}
+
static gboolean
do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
@@ -572,11 +824,13 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
static GtkWidget *menu_filter_add_task;
static GtkWidget *menu_filter_hide_task;
static GtkWidget *menu_filter_clear_tasks;
+ static GtkWidget *menu_filter_graph_add_task;
+ static GtkWidget *menu_filter_graph_hide_task;
+ static GtkWidget *menu_filter_graph_clear_tasks;
struct record *record;
TraceViewRecord *vrec;
GtkTreeModel *model;
const char *comm;
- gchar *text;
gint pid;
gint len;
guint64 offset;
@@ -585,7 +839,7 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
if (!menu) {
menu = gtk_menu_new();
- menu_filter_graph_enable = gtk_menu_item_new_with_label("Enable Graph Filter");
+ menu_filter_graph_enable = gtk_menu_item_new_with_label("Enable Graph Task Filter");
gtk_widget_show(menu_filter_graph_enable);
gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_enable);
@@ -593,7 +847,7 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
G_CALLBACK (filter_graph_enable_clicked),
data);
- menu_filter_list_enable = gtk_menu_item_new_with_label("Enable List Filter");
+ menu_filter_list_enable = gtk_menu_item_new_with_label("Enable List Task Filter");
gtk_widget_show(menu_filter_list_enable);
gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_list_enable);
@@ -609,6 +863,14 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
G_CALLBACK (filter_add_task_clicked),
data);
+ menu_filter_graph_add_task = gtk_menu_item_new_with_label("Add Task to Graph");
+ gtk_widget_show(menu_filter_graph_add_task);
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_add_task);
+
+ g_signal_connect_swapped (G_OBJECT (menu_filter_graph_add_task), "activate",
+ G_CALLBACK (filter_graph_add_task_clicked),
+ data);
+
menu_filter_hide_task = gtk_menu_item_new_with_label("Hide Task");
gtk_widget_show(menu_filter_hide_task);
gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_hide_task);
@@ -617,6 +879,14 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
G_CALLBACK (filter_hide_task_clicked),
data);
+ menu_filter_graph_hide_task = gtk_menu_item_new_with_label("Hide Task from Graph");
+ gtk_widget_show(menu_filter_graph_hide_task);
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_hide_task);
+
+ g_signal_connect_swapped (G_OBJECT (menu_filter_graph_hide_task), "activate",
+ G_CALLBACK (filter_graph_hide_task_clicked),
+ data);
+
menu_filter_clear_tasks = gtk_menu_item_new_with_label("Clear Task Filter");
gtk_widget_show(menu_filter_clear_tasks);
gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_clear_tasks);
@@ -625,6 +895,15 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
G_CALLBACK (filter_clear_tasks_clicked),
data);
+ menu_filter_graph_clear_tasks =
+ gtk_menu_item_new_with_label("Clear Graph Task Filter");
+ gtk_widget_show(menu_filter_graph_clear_tasks);
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_clear_tasks);
+
+ g_signal_connect_swapped (G_OBJECT (menu_filter_graph_clear_tasks), "activate",
+ G_CALLBACK (filter_graph_clear_tasks_clicked),
+ data);
+
}
row = trace_view_get_selected_row(GTK_WIDGET(info->treeview));
@@ -642,29 +921,59 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
len = strlen(comm) + 50;
- text = g_malloc(len);
- g_assert(text);
-
- if (trace_graph_filter_task_find_pid(ginfo, pid))
- snprintf(text, len, "Remove %s-%d from filter", comm, pid);
- else
- snprintf(text, len, "Add %s-%d to filter", comm, pid);
+ if (info->sync_task_filters) {
+ if (trace_graph_filter_task_find_pid(ginfo, pid))
+ set_menu_label(menu_filter_add_task, comm, pid,
+ "Remove %s-%d from filters");
+ else
+ set_menu_label(menu_filter_add_task, comm, pid,
+ "Add %s-%d to filters");
+
+ if (trace_graph_hide_task_find_pid(ginfo, pid))
+ set_menu_label(menu_filter_hide_task, comm, pid,
+ "Show %s-%d");
+ else
+ set_menu_label(menu_filter_hide_task, comm, pid,
+ "Hide %s-%d");
+
+ gtk_widget_hide(menu_filter_graph_add_task);
+ gtk_widget_hide(menu_filter_graph_hide_task);
+
+ } else {
+ if (filter_task_find_pid(info->list_task_filter, pid))
+ set_menu_label(menu_filter_add_task, comm, pid,
+ "Remove %s-%d from List filter");
+ else
+ set_menu_label(menu_filter_add_task, comm, pid,
+ "Add %s-%d to List filter");
+
+ if (filter_task_find_pid(info->list_hide_tasks, pid))
+ set_menu_label(menu_filter_hide_task, comm, pid,
+ "Show %s-%d in List");
+ else
+ set_menu_label(menu_filter_hide_task, comm, pid,
+ "Hide %s-%d from List");
+
+ if (trace_graph_filter_task_find_pid(ginfo, pid))
+ set_menu_label(menu_filter_graph_add_task, comm, pid,
+ "Remove %s-%d from Graph filter");
+ else
+ set_menu_label(menu_filter_graph_add_task, comm, pid,
+ "Add %s-%d to Graph filter");
+
+ if (trace_graph_hide_task_find_pid(ginfo, pid))
+ set_menu_label(menu_filter_graph_hide_task, comm, pid,
+ "Show %s-%d in Graph");
+ else
+ set_menu_label(menu_filter_graph_hide_task, comm, pid,
+ "Hide %s-%d from Graph");
+
+ gtk_widget_show(menu_filter_graph_add_task);
+ gtk_widget_show(menu_filter_graph_hide_task);
+ }
ginfo->filter_task_selected = pid;
- gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_add_task),
- text);
-
- if (trace_graph_hide_task_find_pid(ginfo, pid))
- snprintf(text, len, "Show %s-%d", comm, pid);
- else
- snprintf(text, len, "Hide %s-%d", comm, pid);
-
- gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_hide_task),
- text);
-
- g_free(text);
-
info->selected_task = pid;
gtk_widget_show(menu_filter_add_task);
@@ -674,35 +983,62 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
} else {
gtk_widget_hide(menu_filter_add_task);
gtk_widget_hide(menu_filter_hide_task);
+ gtk_widget_hide(menu_filter_graph_add_task);
+ gtk_widget_hide(menu_filter_graph_hide_task);
}
if (ginfo->filter_enabled)
gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_graph_enable),
- "Disable Graph Filter");
+ "Disable Graph Task Filter");
else
gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_graph_enable),
- "Enable Graph Filter");
+ "Enable Graph Task Filter");
if (info->list_filter_enabled)
gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_list_enable),
- "Disable List Filter");
+ "Disable List Task Filter");
else
gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_list_enable),
- "Enable List Filter");
+ "Enable List Task Filter");
- if (ginfo->filter_available) {
+ if (ginfo->filter_available)
gtk_widget_set_sensitive(menu_filter_graph_enable, TRUE);
- gtk_widget_set_sensitive(menu_filter_list_enable, TRUE);
- } else {
+ else
gtk_widget_set_sensitive(menu_filter_graph_enable, FALSE);
- gtk_widget_set_sensitive(menu_filter_list_enable, FALSE);
- }
- if (filter_task_count(ginfo->task_filter) ||
- filter_task_count(ginfo->hide_tasks))
- gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE);
+ if ((info->sync_task_filters && ginfo->filter_available) ||
+ (!info->sync_task_filters && info->list_filter_available))
+ gtk_widget_set_sensitive(menu_filter_list_enable, TRUE);
else
- gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE);
+ gtk_widget_set_sensitive(menu_filter_list_enable, FALSE);
+
+ if (info->sync_task_filters) {
+ if (filter_task_count(ginfo->task_filter) ||
+ filter_task_count(ginfo->hide_tasks))
+ gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE);
+ else
+ gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE);
+
+ set_menu_label(menu_filter_clear_tasks, comm, pid,
+ "Clear Task Filter");
+ gtk_widget_hide(menu_filter_graph_clear_tasks);
+ } else {
+ if (filter_task_count(ginfo->task_filter) ||
+ filter_task_count(ginfo->hide_tasks))
+ gtk_widget_set_sensitive(menu_filter_graph_clear_tasks, TRUE);
+ else
+ gtk_widget_set_sensitive(menu_filter_graph_clear_tasks, FALSE);
+
+ if (filter_task_count(info->list_task_filter) ||
+ filter_task_count(info->list_hide_tasks))
+ gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE);
+ else
+ gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE);
+
+ set_menu_label(menu_filter_clear_tasks, comm, pid,
+ "Clear List Task Filter");
+ gtk_widget_show(menu_filter_graph_clear_tasks);
+ }
gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3,
gtk_get_current_event_time());
@@ -785,6 +1121,7 @@ void kernel_shark(int argc, char **argv)
handle = NULL;
info->handle = handle;
+ info->sync_task_filters = TRUE;
/* --- Main window --- */
@@ -891,6 +1228,25 @@ void kernel_shark(int argc, char **argv)
menu = gtk_menu_new(); /* Don't need to show menus */
+
+ /* --- Filter - Sync task Option --- */
+
+ sub_item = gtk_menu_item_new_with_label("Unsync Graph and List Task Filters");
+
+ info->task_sync_menu = sub_item;
+
+ /* Add them to the menu */
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
+
+ /* We can attach the Quit menu item to our exit function */
+ g_signal_connect (G_OBJECT (sub_item), "activate",
+ G_CALLBACK (sync_task_filter_clicked),
+ (gpointer) info);
+
+ /* We do need to show menu items */
+ gtk_widget_show(sub_item);
+
+
/* --- Filter - List Events Option --- */
sub_item = gtk_menu_item_new_with_label("list events");
diff --git a/kernel-shark.h b/kernel-shark.h
index edb3787..f931406 100644
--- a/kernel-shark.h
+++ b/kernel-shark.h
@@ -30,10 +30,15 @@ struct shark_info {
struct tracecmd_input *handle;
GtkWidget *treeview;
GtkWidget *spin;
+ GtkWidget *task_sync_menu;
struct graph_callbacks graph_cbs;
gint selected_task;
gboolean list_filter_enabled;
+ gboolean list_filter_available;
gboolean graph_follows;
+ gboolean sync_task_filters;
+ struct filter_task *list_task_filter;
+ struct filter_task *list_hide_tasks;
};
#define offset_of(type, field) (long)(&((type *)0)->field)
diff --git a/trace-graph.c b/trace-graph.c
index 9e5cd19..2bbe73f 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -548,6 +548,20 @@ void trace_graph_clear_tasks(struct graph_info *ginfo)
redraw_graph(ginfo);
}
+void trace_graph_update_filters(struct graph_info *ginfo,
+ struct filter_task *task_filter,
+ struct filter_task *hide_tasks)
+{
+ filter_task_hash_free(ginfo->task_filter);
+ filter_task_hash_free(ginfo->hide_tasks);
+
+ ginfo->task_filter = filter_task_hash_copy(task_filter);
+ ginfo->hide_tasks = filter_task_hash_copy(hide_tasks);
+
+ if (ginfo->filter_enabled)
+ redraw_graph(ginfo);
+}
+
static void
filter_clear_tasks_clicked (gpointer data)
{
diff --git a/trace-graph.h b/trace-graph.h
index 916ad50..91194c1 100644
--- a/trace-graph.h
+++ b/trace-graph.h
@@ -311,6 +311,9 @@ int trace_graph_load_filters(struct graph_info *ginfo,
struct tracecmd_xml_handle *handle);
int trace_graph_save_filters(struct graph_info *ginfo,
struct tracecmd_xml_handle *handle);
+void trace_graph_update_filters(struct graph_info *ginfo,
+ struct filter_task *task_filter,
+ struct filter_task *hide_tasks);
/* plots */
void trace_graph_plot_free(struct graph_info *ginfo);
diff --git a/trace-view-store.c b/trace-view-store.c
index ba40aad..6f70ca5 100644
--- a/trace-view-store.c
+++ b/trace-view-store.c
@@ -1330,7 +1330,6 @@ void trace_view_store_assign_filters(TraceViewStore *store,
if (store->task_filter != task_filter)
store->task_filter = filter_task_hash_copy(task_filter);
-
}
--
cgit v1.2.2
From ddc46835affecefd9460f4f55ea14dac5dbdf8df Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Wed, 9 Jun 2010 16:05:23 -0400
Subject: kernelshark: Clean up advance filter dialog code
Use gtk_dialog_run() and examine the results instead of having
to create a helper structure that is allocated and passed back to
signals.
Signed-off-by: Steven Rostedt
---
trace-filter.c | 89 +++++++++++++++++-----------------------------------------
1 file changed, 26 insertions(+), 63 deletions(-)
diff --git a/trace-filter.c b/trace-filter.c
index 7494ccc..2c6022d 100644
--- a/trace-filter.c
+++ b/trace-filter.c
@@ -97,14 +97,7 @@ struct event_combo_info {
GtkWidget *event_combo;
GtkWidget *op_combo;
GtkWidget *field_combo;
-};
-
-struct adv_event_filter_helper {
- trace_adv_filter_cb_func func;
- GtkTreeView *view;
- GtkWidget *entry;
- struct event_combo_info combo_info;
- gpointer data;
+ GtkWidget *entry;
};
static GtkTreeModel *create_event_combo_model(struct pevent *pevent)
@@ -319,7 +312,6 @@ static void event_combo_changed(GtkComboBox *combo, gpointer data)
static void insert_combo_text(struct event_combo_info *info,
GtkComboBox *combo)
{
- struct adv_event_filter_helper *event_helper;
GtkTreeModel *model;
GtkTreeIter iter;
GtkWidget *entry;
@@ -337,8 +329,7 @@ static void insert_combo_text(struct event_combo_info *info,
0, &text,
-1);
- event_helper = container_of(info, typeof(*event_helper), combo_info);
- entry = event_helper->entry;
+ entry = info->entry;
pos = gtk_editable_get_position(GTK_EDITABLE(entry));
gtk_editable_insert_text(GTK_EDITABLE(entry), text, strlen(text), &pos);
@@ -506,35 +497,6 @@ static gint *get_event_ids(GtkTreeView *treeview)
return ids;
}
-/* Callback for the clicked signal of the advanced filter button */
-static void
-adv_filter_dialog_response (gpointer data, gint response_id)
-{
- struct dialog_helper *helper = data;
- struct adv_event_filter_helper *event_helper = helper->data;
- const gchar *text;
- gint *event_ids;
-
- switch (response_id) {
- case GTK_RESPONSE_ACCEPT:
- text = gtk_entry_get_text(GTK_ENTRY(event_helper->entry));
- event_ids = get_event_ids(event_helper->view);
- event_helper->func(TRUE, text, event_ids, event_helper->data);
- free(event_ids);
- break;
- case GTK_RESPONSE_REJECT:
- event_helper->func(FALSE, NULL, NULL, event_helper->data);
- break;
- default:
- break;
- };
-
- gtk_widget_destroy(GTK_WIDGET(helper->dialog));
-
- g_free(event_helper);
- g_free(helper);
-}
-
static GtkTreeModel *
create_tree_filter_model(struct tracecmd_input *handle,
struct event_filter *event_filter)
@@ -706,9 +668,8 @@ void trace_adv_filter_dialog(struct tracecmd_input *handle,
trace_adv_filter_cb_func func,
gpointer data)
{
+ struct event_combo_info combo_info;
struct pevent *pevent;
- struct dialog_helper *helper;
- struct adv_event_filter_helper *event_helper;
GtkWidget *dialog;
GtkWidget *hbox;
GtkWidget *label;
@@ -716,13 +677,13 @@ void trace_adv_filter_dialog(struct tracecmd_input *handle,
GtkWidget *scrollwin;
GtkWidget *view;
GtkWidget *event_box;
+ const gchar *text;
+ gint *event_ids;
+ int result;
if (!handle)
return;
- helper = g_malloc(sizeof(*helper));
- g_assert(helper);
-
/* --- Make dialog window --- */
dialog = gtk_dialog_new_with_buttons("Advanced Filters",
@@ -734,26 +695,11 @@ void trace_adv_filter_dialog(struct tracecmd_input *handle,
GTK_RESPONSE_REJECT,
NULL);
- event_helper = g_new0(typeof(*event_helper), 1);
- g_assert(event_helper);
-
- helper->dialog = dialog;
- helper->data = event_helper;
-
- event_helper->func = func;
- event_helper->data = data;
-
- /* We can attach the Quit menu item to our exit function */
- g_signal_connect_swapped (dialog, "response",
- G_CALLBACK (adv_filter_dialog_response),
- (gpointer) helper);
-
scrollwin = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
view = create_adv_filter_view(handle, event_filter);
- event_helper->view = GTK_TREE_VIEW(view);
gtk_container_add(GTK_CONTAINER(scrollwin), view);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrollwin, TRUE, TRUE, 0);
@@ -769,9 +715,9 @@ void trace_adv_filter_dialog(struct tracecmd_input *handle,
pevent = tracecmd_get_pevent(handle);
- event_helper->combo_info.pevent = pevent;
+ combo_info.pevent = pevent;
- event_box = event_info_box(&event_helper->combo_info);
+ event_box = event_info_box(&combo_info);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), event_box, FALSE, FALSE, 0);
gtk_widget_show(event_box);
@@ -787,12 +733,29 @@ void trace_adv_filter_dialog(struct tracecmd_input *handle,
gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
gtk_widget_show(entry);
- event_helper->entry = entry;
+ combo_info.entry = entry;
gtk_widget_set_size_request(GTK_WIDGET(dialog),
TEXT_DIALOG_WIDTH, TEXT_DIALOG_HEIGHT);
gtk_widget_show_all(dialog);
+
+ result = gtk_dialog_run(GTK_DIALOG(dialog));
+ switch (result) {
+ case GTK_RESPONSE_ACCEPT:
+ text = gtk_entry_get_text(GTK_ENTRY(entry));
+ event_ids = get_event_ids(GTK_TREE_VIEW(view));
+ func(TRUE, text, event_ids, data);
+ free(event_ids);
+ break;
+ case GTK_RESPONSE_REJECT:
+ func(FALSE, NULL, NULL, data);
+ break;
+ default:
+ break;
+ };
+
+ gtk_widget_destroy(dialog);
}
/* --- task list dialog --- */
--
cgit v1.2.2
From 0418165357886dfa71a273b47ba1ae44323a0f9c Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Wed, 9 Jun 2010 16:15:08 -0400
Subject: kernelshark: Clean up task plot dialog code
Use gtk_dialog_run() and examine the results instead of having
to create a helper structure that is allocated and passed back to
signals.
Signed-off-by: Steven Rostedt
---
trace-filter.c | 91 ++++++++++++++++++----------------------------------------
1 file changed, 28 insertions(+), 63 deletions(-)
diff --git a/trace-filter.c b/trace-filter.c
index 2c6022d..009d92d 100644
--- a/trace-filter.c
+++ b/trace-filter.c
@@ -760,13 +760,6 @@ void trace_adv_filter_dialog(struct tracecmd_input *handle,
/* --- task list dialog --- */
-struct task_helper {
- trace_task_cb_func func;
- GtkTreeView *view;
- gboolean start;
- gpointer data;
-};
-
enum {
TASK_COL_SELECT,
TASK_COL_PID,
@@ -813,35 +806,6 @@ static void get_tasks(GtkTreeView *treeview,
*non_selected = non_pids;
}
-/* Callback for the clicked signal of the task filter button */
-static void
-task_dialog_response (gpointer data, gint response_id)
-{
- struct dialog_helper *helper = data;
- struct task_helper *event_helper = helper->data;
- gint *selected;
- gint *non_select;
-
- switch (response_id) {
- case GTK_RESPONSE_ACCEPT:
- get_tasks(event_helper->view, &selected, &non_select);
- event_helper->func(TRUE, selected, non_select, event_helper->data);
- free(selected);
- free(non_select);
- break;
- case GTK_RESPONSE_REJECT:
- event_helper->func(FALSE, NULL, NULL, event_helper->data);
- break;
- default:
- break;
- };
-
- gtk_widget_destroy(GTK_WIDGET(helper->dialog));
-
- g_free(event_helper);
- g_free(helper);
-}
-
static GtkTreeModel *
create_task_model(struct tracecmd_input *handle,
gint *tasks,
@@ -923,14 +887,14 @@ create_task_model(struct tracecmd_input *handle,
static void task_cursor_changed(gpointer data, GtkTreeView *treeview)
{
- struct task_helper *event_helper = data;
+ gboolean *start = data;
GtkTreeModel *model;
GtkTreePath *path;
GtkTreeIter iter;
gboolean active;
- if (!event_helper->start) {
- event_helper->start = TRUE;
+ if (!*start) {
+ *start = TRUE;
return;
}
@@ -962,7 +926,7 @@ static void task_cursor_changed(gpointer data, GtkTreeView *treeview)
static GtkWidget *
create_task_view(struct tracecmd_input *handle,
gint *tasks, gint *selected,
- struct task_helper *event_helper)
+ gboolean *start)
{
GtkTreeViewColumn *col;
GtkCellRenderer *renderer;
@@ -1024,7 +988,7 @@ create_task_view(struct tracecmd_input *handle,
g_signal_connect_swapped (view, "cursor-changed",
G_CALLBACK (task_cursor_changed),
- (gpointer) event_helper);
+ (gpointer)start);
return view;
}
@@ -1043,14 +1007,12 @@ void trace_task_dialog(struct tracecmd_input *handle,
trace_task_cb_func func,
gpointer data)
{
- struct dialog_helper *helper;
- struct task_helper *event_helper;
GtkWidget *dialog;
GtkWidget *scrollwin;
GtkWidget *view;
-
- helper = g_malloc(sizeof(*helper));
- g_assert(helper);
+ gboolean start = FALSE;
+ gint *non_select;
+ int result;
/* --- Make dialog window --- */
@@ -1063,27 +1025,11 @@ void trace_task_dialog(struct tracecmd_input *handle,
GTK_RESPONSE_REJECT,
NULL);
- event_helper = g_new0(typeof(*event_helper), 1);
- g_assert(event_helper);
-
- helper->dialog = dialog;
- helper->data = event_helper;
-
- event_helper->func = func;
- event_helper->data = data;
- event_helper->start = FALSE;
-
- /* We can attach the Quit menu item to our exit function */
- g_signal_connect_swapped (dialog, "response",
- G_CALLBACK (task_dialog_response),
- (gpointer) helper);
-
scrollwin = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
- view = create_task_view(handle, tasks, selected, event_helper);
- event_helper->view = GTK_TREE_VIEW(view);
+ view = create_task_view(handle, tasks, selected, &start);
gtk_container_add(GTK_CONTAINER(scrollwin), view);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrollwin, TRUE, TRUE, 0);
@@ -1091,6 +1037,25 @@ void trace_task_dialog(struct tracecmd_input *handle,
DIALOG_WIDTH, DIALOG_HEIGHT);
gtk_widget_show_all(dialog);
+
+ selected = NULL;
+
+ result = gtk_dialog_run(GTK_DIALOG(dialog));
+ switch (result) {
+ case GTK_RESPONSE_ACCEPT:
+ get_tasks(GTK_TREE_VIEW(view), &selected, &non_select);
+ func(TRUE, selected, non_select, data);
+ free(selected);
+ free(non_select);
+ break;
+ case GTK_RESPONSE_REJECT:
+ func(FALSE, NULL, NULL, data);
+ break;
+ default:
+ break;
+ };
+
+ gtk_widget_destroy(dialog);
}
enum {
--
cgit v1.2.2
From bfcfe4834608b06ffecab2dc185e44669e48f50d Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Wed, 9 Jun 2010 16:53:40 -0400
Subject: kernelshark: Clean up event dialog code
Use gtk_dialog_run() and examine the results instead of having
to create a helper structure that is allocated and passed back to
signals.
Signed-off-by: Steven Rostedt
---
trace-filter.c | 66 ++++++++++++++++------------------------------------------
1 file changed, 18 insertions(+), 48 deletions(-)
diff --git a/trace-filter.c b/trace-filter.c
index 009d92d..b7ca5c3 100644
--- a/trace-filter.c
+++ b/trace-filter.c
@@ -1530,9 +1530,9 @@ static gint update_system_events(GtkTreeModel *model,
return size;
}
-static void accept_events(struct event_filter_helper *event_helper)
+static void accept_events(GtkTreeView *view,
+ trace_filter_event_cb_func func, gpointer data)
{
- GtkTreeView *view = event_helper->view;
GtkTreeModel *model;
GtkTreeIter iter;
gboolean active;
@@ -1558,8 +1558,7 @@ static void accept_events(struct event_filter_helper *event_helper)
&systems, systems_size,
&events, &events_size);
- event_helper->func(TRUE, active, systems, events,
- event_helper->data);
+ func(TRUE, active, systems, events, data);
if (systems) {
for (i = 0; systems[i]; i++)
@@ -1570,31 +1569,6 @@ static void accept_events(struct event_filter_helper *event_helper)
g_free(events);
}
-/* Callback for the clicked signal of the Events filter button */
-static void
-event_dialog_response (gpointer data, gint response_id)
-{
- struct dialog_helper *helper = data;
- struct event_filter_helper *event_helper = helper->data;
-
- switch (response_id) {
- case GTK_RESPONSE_ACCEPT:
- accept_events(event_helper);
- break;
- case GTK_RESPONSE_REJECT:
- event_helper->func(FALSE, FALSE, NULL, NULL,
- event_helper->data);
- break;
- default:
- break;
- };
-
- gtk_widget_destroy(GTK_WIDGET(helper->dialog));
-
- g_free(event_helper);
- g_free(helper);
-}
-
static void filter_event_dialog(struct tracecmd_input *handle,
struct event_filter *filter,
gboolean all_events,
@@ -1602,13 +1576,10 @@ static void filter_event_dialog(struct tracecmd_input *handle,
trace_filter_event_cb_func func,
gpointer data)
{
- struct dialog_helper *helper;
- struct event_filter_helper *event_helper;
GtkWidget *dialog;
GtkWidget *scrollwin;
GtkWidget *view;
-
- helper = g_malloc(sizeof(*helper));
+ int result;
/* --- Make dialog window --- */
@@ -1621,26 +1592,11 @@ static void filter_event_dialog(struct tracecmd_input *handle,
GTK_RESPONSE_REJECT,
NULL);
- event_helper = g_new0(typeof(*event_helper), 1);
- g_assert(event_helper);
-
- helper->dialog = dialog;
- helper->data = event_helper;
-
- event_helper->func = func;
- event_helper->data = data;
-
- /* We can attach the Quit menu item to our exit function */
- g_signal_connect_swapped (dialog, "response",
- G_CALLBACK (event_dialog_response),
- (gpointer) helper);
-
scrollwin = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
view = create_event_list_view(handle, filter, all_events, systems, events);
- event_helper->view = GTK_TREE_VIEW(view);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrollwin, TRUE, TRUE, 0);
gtk_container_add(GTK_CONTAINER(scrollwin), view);
@@ -1649,6 +1605,20 @@ static void filter_event_dialog(struct tracecmd_input *handle,
DIALOG_WIDTH, DIALOG_HEIGHT);
gtk_widget_show_all(dialog);
+
+ result = gtk_dialog_run(GTK_DIALOG(dialog));
+ switch (result) {
+ case GTK_RESPONSE_ACCEPT:
+ accept_events(GTK_TREE_VIEW(view), func, data);
+ break;
+ case GTK_RESPONSE_REJECT:
+ func(FALSE, FALSE, NULL, NULL, data);
+ break;
+ default:
+ break;
+ };
+
+ gtk_widget_destroy(dialog);
}
/**
--
cgit v1.2.2
From 84db8a11ec76e2e01fe299514e18b0558cb6416d Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Wed, 9 Jun 2010 17:00:12 -0400
Subject: kernelshark: Clean up CPU dialog code
Use gtk_dialog_run() and examine the results instead of having
to create a helper structure that is allocated and passed back to
signals.
Signed-off-by: Steven Rostedt
---
trace-filter.c | 83 +++++++++++++++++++---------------------------------------
1 file changed, 27 insertions(+), 56 deletions(-)
diff --git a/trace-filter.c b/trace-filter.c
index b7ca5c3..2cc0629 100644
--- a/trace-filter.c
+++ b/trace-filter.c
@@ -58,11 +58,6 @@ int id_cmp(const void *a, const void *b)
return 0;
}
-struct dialog_helper {
- GtkWidget *dialog;
- gpointer data;
-};
-
/**
* trace_array_add - allocate and add an int to an array.
* @array: address of array to allocate
@@ -1675,8 +1670,6 @@ struct cpu_filter_helper {
guint64 *cpu_mask;
GtkWidget **buttons;
int cpus;
- trace_filter_cpu_cb_func func;
- gpointer data;
};
static void destroy_cpu_helper(struct cpu_filter_helper *cpu_helper)
@@ -1686,40 +1679,6 @@ static void destroy_cpu_helper(struct cpu_filter_helper *cpu_helper)
g_free(cpu_helper);
}
-/* Callback for the clicked signal of the CPUS filter button */
-static void
-cpu_dialog_response (gpointer data, gint response_id)
-{
- struct dialog_helper *helper = data;
- struct cpu_filter_helper *cpu_helper = helper->data;
- guint64 *cpu_mask = NULL;
-
- switch (response_id) {
- case GTK_RESPONSE_ACCEPT:
-
- if (!cpu_helper->allcpus) {
- cpu_mask = cpu_helper->cpu_mask;
- cpu_helper->cpu_mask = NULL;
- }
-
- cpu_helper->func(TRUE, cpu_helper->allcpus, cpu_mask, cpu_helper->data);
- break;
-
- case GTK_RESPONSE_REJECT:
- cpu_helper->func(FALSE, FALSE, NULL, cpu_helper->data);
- break;
- default:
- break;
- };
-
- g_free(cpu_mask);
-
- gtk_widget_destroy(GTK_WIDGET(helper->dialog));
-
- destroy_cpu_helper(helper->data);
- g_free(helper);
-}
-
#define CPU_ALL_CPUS_STR "All CPUs"
void cpu_toggle(gpointer data, GtkWidget *widget)
@@ -1771,8 +1730,8 @@ void cpu_toggle(gpointer data, GtkWidget *widget)
void trace_filter_cpu_dialog(gboolean all_cpus, guint64 *cpus_selected, gint cpus,
trace_filter_cpu_cb_func func, gpointer data)
{
- struct dialog_helper *helper;
struct cpu_filter_helper *cpu_helper;
+ guint64 *cpu_mask = NULL;
GtkWidget *dialog;
GtkWidget *scrollwin;
GtkWidget *viewport;
@@ -1784,15 +1743,11 @@ void trace_filter_cpu_dialog(gboolean all_cpus, guint64 *cpus_selected, gint cpu
gint width, height;
gint allset;
gint cpu;
-
- helper = g_malloc(sizeof(*helper));
- g_assert(helper != NULL);
+ int result;
cpu_helper = g_new0(typeof(*cpu_helper), 1);
g_assert(cpu_helper != NULL);
- helper->data = cpu_helper;
-
/* --- Make dialog window --- */
dialog = gtk_dialog_new_with_buttons("Filter CPUS",
@@ -1804,19 +1759,10 @@ void trace_filter_cpu_dialog(gboolean all_cpus, guint64 *cpus_selected, gint cpu
GTK_RESPONSE_REJECT,
NULL);
- helper->dialog = dialog;
-
cpu_helper->cpus = cpus;
cpu_helper->buttons = g_new0(GtkWidget *, cpus + 1);
g_assert(cpu_helper->buttons);
- cpu_helper->func = func;
- cpu_helper->data = data;
-
- g_signal_connect_swapped (dialog, "response",
- G_CALLBACK (cpu_dialog_response),
- (gpointer) helper);
-
scrollwin = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
GTK_POLICY_AUTOMATIC,
@@ -1908,6 +1854,31 @@ void trace_filter_cpu_dialog(gboolean all_cpus, guint64 *cpus_selected, gint cpu
width, height);
gtk_widget_show_all(dialog);
+
+ result = gtk_dialog_run(GTK_DIALOG(dialog));
+ switch (result) {
+ case GTK_RESPONSE_ACCEPT:
+
+ if (!cpu_helper->allcpus) {
+ cpu_mask = cpu_helper->cpu_mask;
+ cpu_helper->cpu_mask = NULL;
+ }
+
+ func(TRUE, cpu_helper->allcpus, cpu_mask, data);
+ break;
+
+ case GTK_RESPONSE_REJECT:
+ func(FALSE, FALSE, NULL, data);
+ break;
+ default:
+ break;
+ };
+
+ g_free(cpu_mask);
+
+ gtk_widget_destroy(dialog);
+
+ destroy_cpu_helper(cpu_helper);
}
static void add_system_str(gchar ***systems, char *system, int count)
--
cgit v1.2.2
From 2db91eb153dfdc59ad42e13fefb59f180609b1bd Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Wed, 9 Jun 2010 21:33:57 -0400
Subject: trace-graph: Allow update of task filters with same filter
Allow trace_graph_update_filters have the ginfo filters passed to
it. This will give a way to let external users to refresh the graph
filters.
Signed-off-by: Steven Rostedt
---
trace-graph.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/trace-graph.c b/trace-graph.c
index 2bbe73f..73e69d3 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -552,11 +552,16 @@ void trace_graph_update_filters(struct graph_info *ginfo,
struct filter_task *task_filter,
struct filter_task *hide_tasks)
{
- filter_task_hash_free(ginfo->task_filter);
- filter_task_hash_free(ginfo->hide_tasks);
+ /* Make sure the filter passed in is not the filter we use */
+ if (task_filter != ginfo->task_filter) {
+ filter_task_hash_free(ginfo->task_filter);
+ ginfo->task_filter = filter_task_hash_copy(task_filter);
+ }
- ginfo->task_filter = filter_task_hash_copy(task_filter);
- ginfo->hide_tasks = filter_task_hash_copy(hide_tasks);
+ if (hide_tasks != ginfo->hide_tasks) {
+ filter_task_hash_free(ginfo->hide_tasks);
+ ginfo->hide_tasks = filter_task_hash_copy(hide_tasks);
+ }
if (ginfo->filter_enabled)
redraw_graph(ginfo);
--
cgit v1.2.2
From 4e0828797e2226539e5389ec864ee259a718bd01 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Wed, 9 Jun 2010 21:35:35 -0400
Subject: trace-graph: Add trace_graph_refresh_filters()
Add the function trace_graph_refresh_filters that redraws the graph
after the filters are updated.
Signed-off-by: Steven Rostedt
---
trace-graph.c | 6 ++++++
trace-graph.h | 1 +
2 files changed, 7 insertions(+)
diff --git a/trace-graph.c b/trace-graph.c
index 73e69d3..5638ce6 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -567,6 +567,12 @@ void trace_graph_update_filters(struct graph_info *ginfo,
redraw_graph(ginfo);
}
+void trace_graph_refresh_filters(struct graph_info *ginfo)
+{
+ trace_graph_update_filters(ginfo, ginfo->task_filter,
+ ginfo->hide_tasks);
+}
+
static void
filter_clear_tasks_clicked (gpointer data)
{
diff --git a/trace-graph.h b/trace-graph.h
index 91194c1..15ad4b2 100644
--- a/trace-graph.h
+++ b/trace-graph.h
@@ -314,6 +314,7 @@ int trace_graph_save_filters(struct graph_info *ginfo,
void trace_graph_update_filters(struct graph_info *ginfo,
struct filter_task *task_filter,
struct filter_task *hide_tasks);
+void trace_graph_refresh_filters(struct graph_info *ginfo);
/* plots */
void trace_graph_plot_free(struct graph_info *ginfo);
--
cgit v1.2.2
From 77441ff111de0fb54e4d00df57532333915be2e9 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Wed, 9 Jun 2010 21:43:00 -0400
Subject: trace-graph: Call filter callback on update task filters
When the task filters are updated, call the registered callback.
Signed-off-by: Steven Rostedt
---
trace-graph.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/trace-graph.c b/trace-graph.c
index 5638ce6..319b159 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -563,6 +563,10 @@ void trace_graph_update_filters(struct graph_info *ginfo,
ginfo->hide_tasks = filter_task_hash_copy(hide_tasks);
}
+ if (ginfo->callbacks && ginfo->callbacks->filter)
+ ginfo->callbacks->filter(ginfo, ginfo->task_filter,
+ ginfo->hide_tasks);
+
if (ginfo->filter_enabled)
redraw_graph(ginfo);
}
--
cgit v1.2.2
From 200cb94dd4a1f1f47c86a82c1dc665a67f426214 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Thu, 10 Jun 2010 10:15:15 -0400
Subject: kernelshark: Add list and graph task filter menu
Add a list and graph task filter menu to the menu bar.
The tasks added to this filter are enabled by default.
This also adds a nice feature that you can pick and choose
tasks to filter from a dialog box.
Signed-off-by: Steven Rostedt
---
kernel-shark.c | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++------
kernel-shark.h | 2 +
trace-graph.c | 9 +++
3 files changed, 198 insertions(+), 21 deletions(-)
diff --git a/kernel-shark.c b/kernel-shark.c
index e591657..7b13bdc 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -126,6 +126,23 @@ static int trace_sync_select_menu(const gchar *title,
return result;
}
+static void update_tree_view_filters(struct shark_info *info,
+ struct filter_task *task_filter,
+ struct filter_task *hide_tasks)
+{
+ if (info->list_filter_enabled)
+ trace_view_update_filters(info->treeview,
+ task_filter, hide_tasks);
+
+ if (filter_task_count(task_filter) ||
+ filter_task_count(hide_tasks))
+ info->list_filter_available = 1;
+ else {
+ info->list_filter_enabled = 0;
+ info->list_filter_available = 0;
+ }
+}
+
/* graph callbacks */
/* convert_nano() and print_time() are copied from trace-graph.c for debugging
@@ -178,17 +195,7 @@ static void ks_graph_filter(struct graph_info *ginfo,
if (!info->sync_task_filters)
return;
- if (info->list_filter_enabled)
- trace_view_update_filters(info->treeview,
- task_filter, hide_tasks);
-
- if (filter_task_count(task_filter) ||
- filter_task_count(hide_tasks))
- info->list_filter_available = 1;
- else {
- info->list_filter_enabled = 0;
- info->list_filter_available = 0;
- }
+ update_tree_view_filters(info, task_filter, hide_tasks);
}
static void free_info(struct shark_info *info)
@@ -342,6 +349,10 @@ sync_task_filter_clicked (GtkWidget *subitem, gpointer data)
gtk_menu_item_set_label(GTK_MENU_ITEM(info->task_sync_menu),
"Sync Graph and List Task Filters");
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_task_menu),
+ "graph task filter");
+ gtk_widget_show(info->list_task_menu);
+
/* The list now uses its own hash */
info->list_task_filter = filter_task_hash_copy(info->ginfo->task_filter);
info->list_hide_tasks = filter_task_hash_copy(info->ginfo->hide_tasks);
@@ -375,16 +386,7 @@ sync_task_filter_clicked (GtkWidget *subitem, gpointer data)
info->list_hide_tasks = filter_task_hash_copy(hide_tasks);
}
- if (info->list_filter_enabled)
- trace_view_update_filters(info->treeview,
- task_filter, hide_tasks);
-
- if (!filter_task_count(task_filter) &&
- !filter_task_count(hide_tasks)) {
- info->list_filter_enabled = 0;
- info->list_filter_available = 0;
- } else
- info->list_filter_available = 1;
+ update_tree_view_filters(info, task_filter, hide_tasks);
break;
case 1:
@@ -409,7 +411,136 @@ sync_task_filter_clicked (GtkWidget *subitem, gpointer data)
info->sync_task_filters = 1;
gtk_menu_item_set_label(GTK_MENU_ITEM(info->task_sync_menu),
"Unsync Graph and List Task Filters");
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_task_menu),
+ "task filter");
+ gtk_widget_hide(info->list_task_menu);
+ }
+}
+
+static void filter_list_enable_clicked (gpointer data);
+
+static void
+update_list_task_filter_callback(gboolean accept,
+ gint *selected,
+ gint *non_select,
+ gpointer data)
+{
+ struct shark_info *info = data;
+ GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview);
+ GtkTreeModel *model;
+ TraceViewStore *store;
+ int i;
+
+ if (!accept)
+ return;
+
+ model = gtk_tree_view_get_model(trace_tree);
+ if (!model)
+ return;
+
+ store = TRACE_VIEW_STORE(model);
+
+ filter_task_clear(info->list_task_filter);
+
+ if (selected) {
+ for (i = 0; selected[i] >= 0; i++)
+ filter_task_add_pid(info->list_task_filter, selected[i]);
}
+
+ update_tree_view_filters(info, info->list_task_filter, info->list_hide_tasks);
+
+ /*
+ * The menu filters always enable the filters.
+ */
+ if (info->list_filter_available && !info->list_filter_enabled)
+ filter_list_enable_clicked(info);
+}
+
+/* Callback for the clicked signal of the List Tasks filter button */
+static void
+list_tasks_clicked (gpointer data)
+{
+ struct shark_info *info = data;
+ GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview);
+ struct graph_info *ginfo = info->ginfo;
+ GtkTreeModel *model;
+ TraceViewStore *store;
+ gint *selected;
+ gint *tasks;
+
+ if (!ginfo->handle)
+ return;
+
+ model = gtk_tree_view_get_model(trace_tree);
+ if (!model)
+ return;
+
+ store = TRACE_VIEW_STORE(model);
+
+ tasks = trace_graph_task_list(ginfo);
+ selected = filter_task_pids(info->list_task_filter);
+
+ trace_task_dialog(info->handle, tasks, selected,
+ update_list_task_filter_callback, info);
+
+ free(tasks);
+ free(selected);
+}
+
+static void
+update_graph_task_filter_callback(gboolean accept,
+ gint *selected,
+ gint *non_select,
+ gpointer data)
+{
+ struct shark_info *info = data;
+ struct graph_info *ginfo = info->ginfo;
+ int i;
+
+ if (!accept)
+ return;
+
+ filter_task_clear(ginfo->task_filter);
+
+ if (selected) {
+ for (i = 0; selected[i] >= 0; i++)
+ filter_task_add_pid(ginfo->task_filter, selected[i]);
+ }
+
+ trace_graph_refresh_filters(ginfo);
+
+ /*
+ * The menu filters always enable the filters.
+ */
+ if (ginfo->filter_available) {
+ if (!ginfo->filter_enabled)
+ trace_graph_filter_toggle(info->ginfo);
+
+ if (info->sync_task_filters && !info->list_filter_enabled)
+ filter_list_enable_clicked(info);
+ }
+}
+
+/* Callback for the clicked signal of the Tasks filter button */
+static void
+graph_tasks_clicked (gpointer data)
+{
+ struct shark_info *info = data;
+ struct graph_info *ginfo = info->ginfo;
+ gint *selected;
+ gint *tasks;
+
+ if (!ginfo->handle)
+ return;
+
+ tasks = trace_graph_task_list(ginfo);
+ selected = filter_task_pids(ginfo->task_filter);
+
+ trace_task_dialog(ginfo->handle, tasks, selected,
+ update_graph_task_filter_callback, info);
+
+ free(tasks);
+ free(selected);
}
/* Callback for the clicked signal of the Events filter button */
@@ -1247,6 +1378,41 @@ void kernel_shark(int argc, char **argv)
gtk_widget_show(sub_item);
+ /* --- Filter - List Tasks Option --- */
+
+ sub_item = gtk_menu_item_new_with_label("list task filter");
+
+ /* Add them to the menu */
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
+
+ /* We can attach the Quit menu item to our exit function */
+ g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
+ G_CALLBACK (list_tasks_clicked),
+ (gpointer) info);
+
+ info->list_task_menu = sub_item;
+
+ /* Only show this item when list and graph tasks are not synced */
+
+
+ /* --- Filter - Graph Tasks Option --- */
+
+ sub_item = gtk_menu_item_new_with_label("task filter");
+
+ /* Add them to the menu */
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
+
+ /* We can attach the Quit menu item to our exit function */
+ g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
+ G_CALLBACK (graph_tasks_clicked),
+ (gpointer) info);
+
+ info->graph_task_menu = sub_item;
+
+ /* We do need to show menu items */
+ gtk_widget_show(sub_item);
+
+
/* --- Filter - List Events Option --- */
sub_item = gtk_menu_item_new_with_label("list events");
diff --git a/kernel-shark.h b/kernel-shark.h
index f931406..d537332 100644
--- a/kernel-shark.h
+++ b/kernel-shark.h
@@ -31,6 +31,8 @@ struct shark_info {
GtkWidget *treeview;
GtkWidget *spin;
GtkWidget *task_sync_menu;
+ GtkWidget *list_task_menu;
+ GtkWidget *graph_task_menu;
struct graph_callbacks graph_cbs;
gint selected_task;
gboolean list_filter_enabled;
diff --git a/trace-graph.c b/trace-graph.c
index 319b159..04e2439 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -569,6 +569,15 @@ void trace_graph_update_filters(struct graph_info *ginfo,
if (ginfo->filter_enabled)
redraw_graph(ginfo);
+
+ if (filter_task_count(ginfo->task_filter) ||
+ filter_task_count(ginfo->hide_tasks))
+ ginfo->filter_available = 1;
+ else {
+ ginfo->filter_enabled = 0;
+ ginfo->filter_available = 0;
+ }
+
}
void trace_graph_refresh_filters(struct graph_info *ginfo)
--
cgit v1.2.2
From eea14e07e1ff9d3fb7c0215f4589f8a061bf7107 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Thu, 10 Jun 2010 10:35:20 -0400
Subject: kernelshark: Add hide tasks filter to menu bar
Now the menu bar has hide tasks that popups a task dialog to
let the user choose what tasks to hide. Selecting tasks via
the menu bar will enable the filter automatically.
Signed-off-by: Steven Rostedt
---
kernel-shark.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++---------
kernel-shark.h | 2 +
2 files changed, 156 insertions(+), 27 deletions(-)
diff --git a/kernel-shark.c b/kernel-shark.c
index 7b13bdc..d16448c 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -350,8 +350,11 @@ sync_task_filter_clicked (GtkWidget *subitem, gpointer data)
"Sync Graph and List Task Filters");
gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_task_menu),
- "graph task filter");
+ "graph tasks");
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_hide_task_menu),
+ "graph hide tasks");
gtk_widget_show(info->list_task_menu);
+ gtk_widget_show(info->list_hide_task_menu);
/* The list now uses its own hash */
info->list_task_filter = filter_task_hash_copy(info->ginfo->task_filter);
@@ -412,20 +415,22 @@ sync_task_filter_clicked (GtkWidget *subitem, gpointer data)
gtk_menu_item_set_label(GTK_MENU_ITEM(info->task_sync_menu),
"Unsync Graph and List Task Filters");
gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_task_menu),
- "task filter");
+ "tasks");
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_hide_task_menu),
+ "hide tasks");
gtk_widget_hide(info->list_task_menu);
+ gtk_widget_hide(info->list_hide_task_menu);
}
}
static void filter_list_enable_clicked (gpointer data);
static void
-update_list_task_filter_callback(gboolean accept,
- gint *selected,
- gint *non_select,
- gpointer data)
+__update_list_task_filter_callback(struct shark_info *info,
+ gboolean accept,
+ gint *selected,
+ struct filter_task *task_filter)
{
- struct shark_info *info = data;
GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview);
GtkTreeModel *model;
TraceViewStore *store;
@@ -440,11 +445,11 @@ update_list_task_filter_callback(gboolean accept,
store = TRACE_VIEW_STORE(model);
- filter_task_clear(info->list_task_filter);
+ filter_task_clear(task_filter);
if (selected) {
for (i = 0; selected[i] >= 0; i++)
- filter_task_add_pid(info->list_task_filter, selected[i]);
+ filter_task_add_pid(task_filter, selected[i]);
}
update_tree_view_filters(info, info->list_task_filter, info->list_hide_tasks);
@@ -456,11 +461,36 @@ update_list_task_filter_callback(gboolean accept,
filter_list_enable_clicked(info);
}
-/* Callback for the clicked signal of the List Tasks filter button */
static void
-list_tasks_clicked (gpointer data)
+update_list_task_filter_callback(gboolean accept,
+ gint *selected,
+ gint *non_select,
+ gpointer data)
+{
+ struct shark_info *info = data;
+
+ __update_list_task_filter_callback(info, accept, selected,
+ info->list_task_filter);
+}
+
+static void
+update_list_hide_task_filter_callback(gboolean accept,
+ gint *selected,
+ gint *non_select,
+ gpointer data)
{
struct shark_info *info = data;
+
+ __update_list_task_filter_callback(info, accept, selected,
+ info->list_hide_tasks);
+}
+
+/* Callback for the clicked signal of the List Tasks filter button */
+static void
+__list_tasks_clicked (struct shark_info *info,
+ struct filter_task *task_filter,
+ trace_task_cb_func func)
+{
GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview);
struct graph_info *ginfo = info->ginfo;
GtkTreeModel *model;
@@ -478,33 +508,49 @@ list_tasks_clicked (gpointer data)
store = TRACE_VIEW_STORE(model);
tasks = trace_graph_task_list(ginfo);
- selected = filter_task_pids(info->list_task_filter);
+ selected = filter_task_pids(task_filter);
- trace_task_dialog(info->handle, tasks, selected,
- update_list_task_filter_callback, info);
+ trace_task_dialog(info->handle, tasks, selected, func, info);
free(tasks);
free(selected);
}
static void
-update_graph_task_filter_callback(gboolean accept,
- gint *selected,
- gint *non_select,
- gpointer data)
+list_tasks_clicked (gpointer data)
+{
+ struct shark_info *info = data;
+
+ __list_tasks_clicked(info, info->list_task_filter,
+ update_list_task_filter_callback);
+}
+
+static void
+list_hide_tasks_clicked (gpointer data)
{
struct shark_info *info = data;
+
+ __list_tasks_clicked(info, info->list_hide_tasks,
+ update_list_hide_task_filter_callback);
+}
+
+static void
+__update_graph_task_filter_callback(struct shark_info *info,
+ gboolean accept,
+ gint *selected,
+ struct filter_task *task_filter)
+{
struct graph_info *ginfo = info->ginfo;
int i;
if (!accept)
return;
- filter_task_clear(ginfo->task_filter);
+ filter_task_clear(task_filter);
if (selected) {
for (i = 0; selected[i] >= 0; i++)
- filter_task_add_pid(ginfo->task_filter, selected[i]);
+ filter_task_add_pid(task_filter, selected[i]);
}
trace_graph_refresh_filters(ginfo);
@@ -521,12 +567,39 @@ update_graph_task_filter_callback(gboolean accept,
}
}
-/* Callback for the clicked signal of the Tasks filter button */
static void
-graph_tasks_clicked (gpointer data)
+update_graph_task_filter_callback(gboolean accept,
+ gint *selected,
+ gint *non_select,
+ gpointer data)
+{
+ struct shark_info *info = data;
+ struct graph_info *ginfo = info->ginfo;
+
+ __update_graph_task_filter_callback(info, accept, selected,
+ ginfo->task_filter);
+}
+
+static void
+update_graph_hide_task_filter_callback(gboolean accept,
+ gint *selected,
+ gint *non_select,
+ gpointer data)
{
struct shark_info *info = data;
struct graph_info *ginfo = info->ginfo;
+
+ __update_graph_task_filter_callback(info, accept, selected,
+ ginfo->hide_tasks);
+}
+
+/* Callback for the clicked signal of the Tasks filter button */
+static void
+__graph_tasks_clicked (struct shark_info *info,
+ struct filter_task *task_filter,
+ trace_task_cb_func func)
+{
+ struct graph_info *ginfo = info->ginfo;
gint *selected;
gint *tasks;
@@ -534,15 +607,34 @@ graph_tasks_clicked (gpointer data)
return;
tasks = trace_graph_task_list(ginfo);
- selected = filter_task_pids(ginfo->task_filter);
+ selected = filter_task_pids(task_filter);
- trace_task_dialog(ginfo->handle, tasks, selected,
- update_graph_task_filter_callback, info);
+ trace_task_dialog(ginfo->handle, tasks, selected, func, info);
free(tasks);
free(selected);
}
+static void
+graph_tasks_clicked (gpointer data)
+{
+ struct shark_info *info = data;
+ struct graph_info *ginfo = info->ginfo;
+
+ __graph_tasks_clicked(info, ginfo->task_filter,
+ update_graph_task_filter_callback);
+}
+
+static void
+graph_hide_tasks_clicked (gpointer data)
+{
+ struct shark_info *info = data;
+ struct graph_info *ginfo = info->ginfo;
+
+ __graph_tasks_clicked(info, ginfo->hide_tasks,
+ update_graph_hide_task_filter_callback);
+}
+
/* Callback for the clicked signal of the Events filter button */
static void
list_events_clicked (gpointer data)
@@ -1380,7 +1472,7 @@ void kernel_shark(int argc, char **argv)
/* --- Filter - List Tasks Option --- */
- sub_item = gtk_menu_item_new_with_label("list task filter");
+ sub_item = gtk_menu_item_new_with_label("list tasks");
/* Add them to the menu */
gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
@@ -1397,7 +1489,7 @@ void kernel_shark(int argc, char **argv)
/* --- Filter - Graph Tasks Option --- */
- sub_item = gtk_menu_item_new_with_label("task filter");
+ sub_item = gtk_menu_item_new_with_label("tasks");
/* Add them to the menu */
gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
@@ -1413,6 +1505,41 @@ void kernel_shark(int argc, char **argv)
gtk_widget_show(sub_item);
+ /* --- Filter - List Hide Tasks Option --- */
+
+ sub_item = gtk_menu_item_new_with_label("list hide tasks");
+
+ /* Add them to the menu */
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
+
+ /* We can attach the Quit menu item to our exit function */
+ g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
+ G_CALLBACK (list_hide_tasks_clicked),
+ (gpointer) info);
+
+ info->list_hide_task_menu = sub_item;
+
+ /* Only show this item when list and graph tasks are not synced */
+
+
+ /* --- Filter - Graph Hide Tasks Option --- */
+
+ sub_item = gtk_menu_item_new_with_label("hide tasks");
+
+ /* Add them to the menu */
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
+
+ /* We can attach the Quit menu item to our exit function */
+ g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
+ G_CALLBACK (graph_hide_tasks_clicked),
+ (gpointer) info);
+
+ info->graph_hide_task_menu = sub_item;
+
+ /* We do need to show menu items */
+ gtk_widget_show(sub_item);
+
+
/* --- Filter - List Events Option --- */
sub_item = gtk_menu_item_new_with_label("list events");
diff --git a/kernel-shark.h b/kernel-shark.h
index d537332..34d2cfd 100644
--- a/kernel-shark.h
+++ b/kernel-shark.h
@@ -33,6 +33,8 @@ struct shark_info {
GtkWidget *task_sync_menu;
GtkWidget *list_task_menu;
GtkWidget *graph_task_menu;
+ GtkWidget *list_hide_task_menu;
+ GtkWidget *graph_hide_task_menu;
struct graph_callbacks graph_cbs;
gint selected_task;
gboolean list_filter_enabled;
--
cgit v1.2.2
From 66256925536b9757da1f0cb2bc2230b6478dbeaf Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Thu, 10 Jun 2010 11:33:36 -0400
Subject: kerenlshark: Allow for list and graph event filters to by in sync
Update the event filters to be like the task filters where the
list and graph event filters are in sync. The user can unsync them
so that the list and graph event filters will be independent.
Signed-off-by: Steven Rostedt
---
kernel-shark.c | 222 ++++++++++++++++++++++++++++++++++++++-------------------
kernel-shark.h | 6 ++
2 files changed, 155 insertions(+), 73 deletions(-)
diff --git a/kernel-shark.c b/kernel-shark.c
index d16448c..e0ab1ed 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -326,7 +326,7 @@ delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
return TRUE;
}
-/* Callback for the clicked signal of the Events filter button */
+/* Callback for the clicked signal of the tasks sync filter button */
static void
sync_task_filter_clicked (GtkWidget *subitem, gpointer data)
{
@@ -423,6 +423,83 @@ sync_task_filter_clicked (GtkWidget *subitem, gpointer data)
}
}
+/* Callback for the clicked signal of the events sync filter button */
+static void
+sync_events_filter_clicked (GtkWidget *subitem, gpointer data)
+{
+ struct shark_info *info = data;
+ struct graph_info *ginfo = info->ginfo;
+ struct event_filter *event_filter;
+ GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview);
+ GtkTreeModel *model;
+ TraceViewStore *store;
+ gboolean keep;
+ gboolean all_events;
+ gchar *selections[] = { "Sync List Filter with Graph Filter",
+ "Sync Graph Filter with List Filter",
+ NULL };
+ int result;
+
+ if (info->sync_event_filters) {
+ /* Separate the List and Graph filters */
+
+ info->sync_event_filters = 0;
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->events_sync_menu),
+ "Sync Graph and List Event Filters");
+
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_events_menu),
+ "graph events");
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_adv_events_menu),
+ "graph advanced events");
+ gtk_widget_show(info->list_events_menu);
+ gtk_widget_show(info->list_adv_events_menu);
+
+ return;
+ }
+
+ model = gtk_tree_view_get_model(trace_tree);
+ if (!model)
+ return;
+
+ store = TRACE_VIEW_STORE(model);
+
+ /* Ask user which way to sync */
+ result = trace_sync_select_menu("Sync Event Filters",
+ selections, &keep);
+
+ switch (result) {
+ case 0:
+ /* Sync List Filter with Graph Filter */
+ all_events = ginfo->all_events;
+
+ trace_view_copy_filter(info->treeview, all_events,
+ ginfo->event_filter);
+ break;
+ case 1:
+ /* Sync Graph Filter with List Filter */
+ all_events = trace_view_store_get_all_events_enabled(store);
+ event_filter = trace_view_store_get_event_filter(store);
+
+ trace_graph_copy_filter(info->ginfo, all_events,
+ event_filter);
+ break;
+ default:
+ keep = 0;
+ }
+
+ if (keep) {
+ info->sync_event_filters = 1;
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->events_sync_menu),
+ "Unsync Graph and List Event Filters");
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_events_menu),
+ "events");
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_adv_events_menu),
+ "advanced events");
+ gtk_widget_hide(info->list_events_menu);
+ gtk_widget_hide(info->list_adv_events_menu);
+ }
+}
+
static void filter_list_enable_clicked (gpointer data);
static void
@@ -655,12 +732,34 @@ list_events_clicked (gpointer data)
all_events = trace_view_store_get_all_events_enabled(store);
event_filter = trace_view_store_get_event_filter(store);
+ /*
+ * This menu is not available when in sync, so we
+ * can call the treeview callback directly.
+ */
trace_filter_event_filter_dialog(store->handle, event_filter,
all_events,
trace_view_event_filter_callback,
info->treeview);
}
+static void
+graph_event_filter_callback(gboolean accept,
+ gboolean all_events,
+ gchar **systems,
+ gint *events,
+ gpointer data)
+{
+ struct shark_info *info = data;
+
+ trace_graph_event_filter_callback(accept, all_events,
+ systems, events,
+ info->ginfo);
+
+ if (info->sync_event_filters)
+ trace_view_event_filter_callback(accept, all_events, systems,
+ events, info->treeview);
+}
+
static void
graph_events_clicked (gpointer data)
{
@@ -673,8 +772,8 @@ graph_events_clicked (gpointer data)
trace_filter_event_filter_dialog(info->handle,
ginfo->event_filter,
all_events,
- trace_graph_event_filter_callback,
- ginfo);
+ graph_event_filter_callback,
+ info);
}
/* Callback for the clicked signal of the List advanced filter button */
@@ -695,56 +794,39 @@ adv_list_filter_clicked (gpointer data)
event_filter = trace_view_store_get_event_filter(store);
+ /*
+ * This menu is not available when in sync, so we
+ * can call the treeview callback directly.
+ */
trace_adv_filter_dialog(store->handle, event_filter,
trace_view_adv_filter_callback, trace_tree);
}
-/* Callback for the clicked signal of the Graph advanced filter button */
static void
-adv_graph_filter_clicked (gpointer data)
+graph_adv_filter_callback(gboolean accept,
+ const gchar *text,
+ gint *event_ids,
+ gpointer data)
{
struct shark_info *info = data;
struct graph_info *ginfo = info->ginfo;
- trace_adv_filter_dialog(ginfo->handle, ginfo->event_filter,
- trace_graph_adv_filter_callback, ginfo);
-}
-
-static void
-sync_graph_events_to_list_clicked (gpointer data)
-{
- struct shark_info *info = data;
- struct event_filter *event_filter;
- GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview);
- GtkTreeModel *model;
- TraceViewStore *store;
- gboolean all_events;
-
- model = gtk_tree_view_get_model(trace_tree);
- if (!model)
- return;
+ trace_graph_adv_filter_callback(accept, text, event_ids, ginfo);
- store = TRACE_VIEW_STORE(model);
-
- all_events = trace_view_store_get_all_events_enabled(store);
- event_filter = trace_view_store_get_event_filter(store);
-
- trace_graph_copy_filter(info->ginfo, all_events,
- event_filter);
+ if (info->sync_event_filters)
+ trace_view_adv_filter_callback(accept, text, event_ids,
+ info->treeview);
}
-
+/* Callback for the clicked signal of the Graph advanced filter button */
static void
-sync_list_events_to_graph_clicked (gpointer data)
+adv_graph_filter_clicked (gpointer data)
{
struct shark_info *info = data;
struct graph_info *ginfo = info->ginfo;
- gboolean all_events;
-
- all_events = ginfo->all_events;
- trace_view_copy_filter(info->treeview, all_events,
- ginfo->event_filter);
+ trace_adv_filter_dialog(ginfo->handle, ginfo->event_filter,
+ graph_adv_filter_callback, info);
}
/* Callback for the clicked signal of the CPUs filter button */
@@ -1345,6 +1427,7 @@ void kernel_shark(int argc, char **argv)
info->handle = handle;
info->sync_task_filters = TRUE;
+ info->sync_event_filters = TRUE;
/* --- Main window --- */
@@ -1470,6 +1553,24 @@ void kernel_shark(int argc, char **argv)
gtk_widget_show(sub_item);
+ /* --- Filter - Sync events Option --- */
+
+ sub_item = gtk_menu_item_new_with_label("Unsync Graph and List Event Filters");
+
+ info->events_sync_menu = sub_item;
+
+ /* Add them to the menu */
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
+
+ /* We can attach the Quit menu item to our exit function */
+ g_signal_connect (G_OBJECT (sub_item), "activate",
+ G_CALLBACK (sync_events_filter_clicked),
+ (gpointer) info);
+
+ /* We do need to show menu items */
+ gtk_widget_show(sub_item);
+
+
/* --- Filter - List Tasks Option --- */
sub_item = gtk_menu_item_new_with_label("list tasks");
@@ -1552,53 +1653,25 @@ void kernel_shark(int argc, char **argv)
G_CALLBACK (list_events_clicked),
(gpointer) info);
- /* We do need to show menu items */
- gtk_widget_show(sub_item);
+ info->list_events_menu = sub_item;
-
- /* --- Filter - Events Option --- */
-
- sub_item = gtk_menu_item_new_with_label("graph events");
-
- /* Add them to the menu */
- gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
-
- /* We can attach the Quit menu item to our exit function */
- g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
- G_CALLBACK (graph_events_clicked),
- (gpointer) info);
-
- /* We do need to show menu items */
- gtk_widget_show(sub_item);
+ /* We do not show this menu (yet) */
/* --- Filter - Events Option --- */
- sub_item = gtk_menu_item_new_with_label("sync graph events with list");
+ /* The list and graph events start off insync */
+ sub_item = gtk_menu_item_new_with_label("events");
/* Add them to the menu */
gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
/* We can attach the Quit menu item to our exit function */
g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
- G_CALLBACK (sync_graph_events_to_list_clicked),
+ G_CALLBACK (graph_events_clicked),
(gpointer) info);
- /* We do need to show menu items */
- gtk_widget_show(sub_item);
-
-
- /* --- Filter - Events Option --- */
-
- sub_item = gtk_menu_item_new_with_label("sync list events with graph");
-
- /* Add them to the menu */
- gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
-
- /* We can attach the Quit menu item to our exit function */
- g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
- G_CALLBACK (sync_list_events_to_graph_clicked),
- (gpointer) info);
+ info->graph_events_menu = sub_item;
/* We do need to show menu items */
gtk_widget_show(sub_item);
@@ -1616,13 +1689,14 @@ void kernel_shark(int argc, char **argv)
G_CALLBACK (adv_list_filter_clicked),
(gpointer) info);
- /* We do need to show menu items */
- gtk_widget_show(sub_item);
+ info->list_adv_events_menu = sub_item;
+ /* We do not show this menu (yet) */
/* --- Filter - Graph Advanced Events Option --- */
- sub_item = gtk_menu_item_new_with_label("graph advanced event");
+ /* The list and graph events start off in sync */
+ sub_item = gtk_menu_item_new_with_label("advanced events");
/* Add them to the menu */
gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
@@ -1632,6 +1706,8 @@ void kernel_shark(int argc, char **argv)
G_CALLBACK (adv_graph_filter_clicked),
(gpointer) info);
+ info->graph_adv_events_menu = sub_item;
+
/* We do need to show menu items */
gtk_widget_show(sub_item);
diff --git a/kernel-shark.h b/kernel-shark.h
index 34d2cfd..a808108 100644
--- a/kernel-shark.h
+++ b/kernel-shark.h
@@ -31,16 +31,22 @@ struct shark_info {
GtkWidget *treeview;
GtkWidget *spin;
GtkWidget *task_sync_menu;
+ GtkWidget *events_sync_menu;
GtkWidget *list_task_menu;
GtkWidget *graph_task_menu;
GtkWidget *list_hide_task_menu;
GtkWidget *graph_hide_task_menu;
+ GtkWidget *list_events_menu;
+ GtkWidget *graph_events_menu;
+ GtkWidget *list_adv_events_menu;
+ GtkWidget *graph_adv_events_menu;
struct graph_callbacks graph_cbs;
gint selected_task;
gboolean list_filter_enabled;
gboolean list_filter_available;
gboolean graph_follows;
gboolean sync_task_filters;
+ gboolean sync_event_filters;
struct filter_task *list_task_filter;
struct filter_task *list_hide_tasks;
};
--
cgit v1.2.2
From ce6dcdc247fc6194566360e74fcb986fa656043a Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Thu, 10 Jun 2010 16:15:19 -0400
Subject: kernelshark: Fix the xml save/load to handle separate task filters
Update the save/load of the filters to handle the change to make the
List and Graph have separate task filters.
Signed-off-by: Steven Rostedt
---
kernel-shark.c | 129 +++++++++++++++++++++++++++++++++++++++--------------
trace-filter.c | 6 ++-
trace-filter.h | 2 +
trace-graph-main.c | 8 +++-
trace-view-main.c | 8 +++-
trace-xml.c | 16 +++++++
trace-xml.h | 2 +
7 files changed, 132 insertions(+), 39 deletions(-)
diff --git a/kernel-shark.c b/kernel-shark.c
index e0ab1ed..91ecf82 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -223,6 +223,38 @@ static void update_title(GtkWidget *window, const gchar *file)
g_free(str);
}
+static void unsync_task_filters(struct shark_info *info)
+{
+ info->sync_task_filters = 0;
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->task_sync_menu),
+ "Sync Graph and List Task Filters");
+
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_task_menu),
+ "graph tasks");
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_hide_task_menu),
+ "graph hide tasks");
+ gtk_widget_show(info->list_task_menu);
+ gtk_widget_show(info->list_hide_task_menu);
+
+ /* The list now uses its own hash */
+ info->list_task_filter = filter_task_hash_copy(info->ginfo->task_filter);
+ info->list_hide_tasks = filter_task_hash_copy(info->ginfo->hide_tasks);
+}
+
+static void unsync_event_filters(struct shark_info *info)
+{
+ info->sync_event_filters = 0;
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->events_sync_menu),
+ "Sync Graph and List Event Filters");
+
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_events_menu),
+ "graph events");
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_adv_events_menu),
+ "graph advanced events");
+ gtk_widget_show(info->list_events_menu);
+ gtk_widget_show(info->list_adv_events_menu);
+}
+
static void
/* Callback for the clicked signal of the Load button */
load_clicked (gpointer data)
@@ -254,24 +286,64 @@ load_filters_clicked (gpointer data)
struct graph_info *ginfo = info->ginfo;
GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview);
struct tracecmd_xml_handle *handle;
+ struct filter_task *task_filter;
+ struct filter_task *hide_tasks;
gchar *filename;
+ int ret;
filename = trace_get_file_dialog("Load Filters");
if (!filename)
return;
handle = tracecmd_xml_open(filename);
- if (!handle)
+ if (!handle) {
warning("Could not open %s", filename);
- g_free(filename);
+ goto out;
+ }
- trace_filter_load_filters(handle, ginfo->task_filter,
- ginfo->hide_tasks);
+ /* Unsync the list and graph filters */
+ if (info->sync_task_filters)
+ unsync_task_filters(info);
+ if (info->sync_event_filters)
+ unsync_event_filters(info);
+
+ ret = tracecmd_xml_system_exists(handle,
+ "GraphTaskFilter");
+ if (ret) {
+ filter_task_clear(ginfo->task_filter);
+ filter_task_clear(ginfo->hide_tasks);
+
+ trace_filter_load_filters(handle,
+ "GraphTaskFilter",
+ ginfo->task_filter,
+ ginfo->hide_tasks);
+ trace_graph_refresh_filters(ginfo);
+ }
+
+ ret = tracecmd_xml_system_exists(handle,
+ "ListTaskFilter");
+ if (ret) {
+
+ task_filter = info->list_task_filter;
+ hide_tasks = info->list_hide_tasks;
+ filter_task_clear(task_filter);
+ filter_task_clear(hide_tasks);
+
+ trace_filter_load_filters(handle,
+ "ListTaskFilter",
+ task_filter,
+ hide_tasks);
+ update_tree_view_filters(info, task_filter, hide_tasks);
+ }
- trace_view_load_filters(handle, trace_tree);
trace_graph_load_filters(ginfo, handle);
+ ret = trace_view_load_filters(handle, trace_tree);
tracecmd_xml_close(handle);
+
+ out:
+ g_free(filename);
+
}
/* Callback for the clicked signal of the Save Filters button */
@@ -282,6 +354,8 @@ save_filters_clicked (gpointer data)
struct graph_info *ginfo = info->ginfo;
struct tracecmd_xml_handle *handle;
GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview);
+ struct filter_task *task_filter;
+ struct filter_task *hide_tasks;
gchar *filename;
filename = trace_get_file_dialog("Save Filters");
@@ -294,12 +368,25 @@ save_filters_clicked (gpointer data)
g_free(filename);
trace_view_save_filters(handle, trace_tree);
-
trace_graph_save_filters(ginfo, handle);
- trace_filter_save_filters(handle, ginfo->task_filter,
+ trace_filter_save_filters(handle,
+ "GraphTaskFilter",
+ ginfo->task_filter,
ginfo->hide_tasks);
+ if (info->sync_task_filters) {
+ task_filter = ginfo->task_filter;
+ hide_tasks = ginfo->hide_tasks;
+ } else {
+ task_filter = info->list_task_filter;
+ hide_tasks = info->list_hide_tasks;
+ }
+
+ trace_filter_save_filters(handle,
+ "ListTaskFilter",
+ task_filter, hide_tasks);
+
tracecmd_xml_close(handle);
}
@@ -345,20 +432,7 @@ sync_task_filter_clicked (GtkWidget *subitem, gpointer data)
if (info->sync_task_filters) {
/* Separate the List and Graph filters */
- info->sync_task_filters = 0;
- gtk_menu_item_set_label(GTK_MENU_ITEM(info->task_sync_menu),
- "Sync Graph and List Task Filters");
-
- gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_task_menu),
- "graph tasks");
- gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_hide_task_menu),
- "graph hide tasks");
- gtk_widget_show(info->list_task_menu);
- gtk_widget_show(info->list_hide_task_menu);
-
- /* The list now uses its own hash */
- info->list_task_filter = filter_task_hash_copy(info->ginfo->task_filter);
- info->list_hide_tasks = filter_task_hash_copy(info->ginfo->hide_tasks);
+ unsync_task_filters(info);
return;
}
@@ -442,18 +516,7 @@ sync_events_filter_clicked (GtkWidget *subitem, gpointer data)
if (info->sync_event_filters) {
/* Separate the List and Graph filters */
-
- info->sync_event_filters = 0;
- gtk_menu_item_set_label(GTK_MENU_ITEM(info->events_sync_menu),
- "Sync Graph and List Event Filters");
-
- gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_events_menu),
- "graph events");
- gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_adv_events_menu),
- "graph advanced events");
- gtk_widget_show(info->list_events_menu);
- gtk_widget_show(info->list_adv_events_menu);
-
+ unsync_event_filters(info);
return;
}
diff --git a/trace-filter.c b/trace-filter.c
index 2cc0629..b8fc76f 100644
--- a/trace-filter.c
+++ b/trace-filter.c
@@ -2196,6 +2196,7 @@ int trace_filter_load_task_filter(struct filter_task *filter,
}
int trace_filter_load_filters(struct tracecmd_xml_handle *handle,
+ const char *system_name,
struct filter_task *task_filter,
struct filter_task *hide_tasks)
{
@@ -2203,7 +2204,7 @@ int trace_filter_load_filters(struct tracecmd_xml_handle *handle,
struct tracecmd_xml_system_node *syschild;
const char *name;
- system = tracecmd_xml_find_system(handle, "TraceFilter");
+ system = tracecmd_xml_find_system(handle, system_name);
if (!system)
return -1;
@@ -2234,11 +2235,12 @@ int trace_filter_load_filters(struct tracecmd_xml_handle *handle,
}
int trace_filter_save_filters(struct tracecmd_xml_handle *handle,
+ const char *system_name,
struct filter_task *task_filter,
struct filter_task *hide_tasks)
{
- tracecmd_xml_start_system(handle, "TraceFilter");
+ tracecmd_xml_start_system(handle, system_name);
if (task_filter && filter_task_count(task_filter)) {
tracecmd_xml_start_sub_system(handle, "TaskFilter");
diff --git a/trace-filter.h b/trace-filter.h
index e0f9f4a..1800471 100644
--- a/trace-filter.h
+++ b/trace-filter.h
@@ -149,9 +149,11 @@ int trace_filter_load_task_filter(struct filter_task *filter,
struct tracecmd_xml_handle *handle,
struct tracecmd_xml_system_node *node);
int trace_filter_load_filters(struct tracecmd_xml_handle *handle,
+ const char *system_name,
struct filter_task *task_filter,
struct filter_task *hide_tasks);
int trace_filter_save_filters(struct tracecmd_xml_handle *handle,
+ const char *system_name,
struct filter_task *task_filter,
struct filter_task *hide_tasks);
diff --git a/trace-graph-main.c b/trace-graph-main.c
index 2ba9447..b4f05fb 100644
--- a/trace-graph-main.c
+++ b/trace-graph-main.c
@@ -171,7 +171,9 @@ load_filters_clicked (gpointer data)
warning("Could not open %s", filename);
g_free(filename);
- trace_filter_load_filters(handle, ginfo->task_filter,
+ trace_filter_load_filters(handle,
+ "GraphTaskFilter",
+ ginfo->task_filter,
ginfo->hide_tasks);
trace_graph_load_filters(ginfo, handle);
@@ -196,7 +198,9 @@ save_filters_clicked (gpointer data)
warning("Could not create %s", filename);
g_free(filename);
- trace_filter_save_filters(handle, ginfo->task_filter,
+ trace_filter_save_filters(handle,
+ "GraphTaskFilter",
+ ginfo->task_filter,
ginfo->hide_tasks);
trace_graph_save_filters(ginfo, handle);
diff --git a/trace-view-main.c b/trace-view-main.c
index 8fa9aa6..59d6838 100644
--- a/trace-view-main.c
+++ b/trace-view-main.c
@@ -102,7 +102,9 @@ load_filters_clicked (gpointer data)
}
g_free(filename);
- trace_filter_load_filters(handle, info->task_filter,
+ trace_filter_load_filters(handle,
+ "ListTaskFilter",
+ info->task_filter,
info->hide_tasks);
trace_view_load_filters(handle, trace_tree);
@@ -128,7 +130,9 @@ save_filters_clicked (gpointer data)
warning("Could not create %s", filename);
g_free(filename);
- trace_filter_save_filters(handle, info->task_filter, info->hide_tasks);
+ trace_filter_save_filters(handle,
+ "ListTaskFilter",
+ info->task_filter, info->hide_tasks);
trace_view_save_filters(handle, trace_tree);
tracecmd_xml_close(handle);
diff --git a/trace-xml.c b/trace-xml.c
index 62473fb..bef1f9f 100644
--- a/trace-xml.c
+++ b/trace-xml.c
@@ -230,3 +230,19 @@ void tracecmd_xml_free_system(struct tracecmd_xml_system *system)
xmlXPathFreeObject(system->result);
free(system);
}
+
+int tracecmd_xml_system_exists(struct tracecmd_xml_handle *handle,
+ const char *system)
+{
+ struct tracecmd_xml_system *sys;
+ int exists = 0;
+
+ sys = tracecmd_xml_find_system(handle, system);
+ if (sys) {
+ exists = 1;
+ tracecmd_xml_free_system(sys);
+ }
+
+ return exists;
+}
+
diff --git a/trace-xml.h b/trace-xml.h
index f84907d..d1f62b0 100644
--- a/trace-xml.h
+++ b/trace-xml.h
@@ -56,5 +56,7 @@ struct tracecmd_xml_system_node *
tracecmd_xml_node_next(struct tracecmd_xml_system_node *tnode);
const char *tracecmd_xml_node_value(struct tracecmd_xml_handle *handle,
struct tracecmd_xml_system_node *tnode);
+int tracecmd_xml_system_exists(struct tracecmd_xml_handle *handle,
+ const char *system);
#endif /* __TRACE_XML_H */
--
cgit v1.2.2
From f501cf496f91df0a71a41aee74d1b213799d85e4 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Thu, 10 Jun 2010 16:33:59 -0400
Subject: kernelshark: Add tests if task filters are same
On load of task filters, if they are the same, then make them synced.
On syncing of task filters, if they are already the same, do not ask
which way to sync, just sync them and keep them synced.
Signed-off-by: Steven Rostedt
---
kernel-shark.c | 79 +++++++++++++++++++++++++++++++++++++++-------------------
trace-hash.c | 36 ++++++++++++++++++++++++++
trace-hash.h | 1 +
3 files changed, 91 insertions(+), 25 deletions(-)
diff --git a/kernel-shark.c b/kernel-shark.c
index 91ecf82..3a0d0fb 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -241,6 +241,19 @@ static void unsync_task_filters(struct shark_info *info)
info->list_hide_tasks = filter_task_hash_copy(info->ginfo->hide_tasks);
}
+static void sync_task_filters(struct shark_info *info)
+{
+ info->sync_task_filters = 1;
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->task_sync_menu),
+ "Unsync Graph and List Task Filters");
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_task_menu),
+ "tasks");
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_hide_task_menu),
+ "hide tasks");
+ gtk_widget_hide(info->list_task_menu);
+ gtk_widget_hide(info->list_hide_task_menu);
+}
+
static void unsync_event_filters(struct shark_info *info)
{
info->sync_event_filters = 0;
@@ -255,6 +268,19 @@ static void unsync_event_filters(struct shark_info *info)
gtk_widget_show(info->list_adv_events_menu);
}
+static void sync_event_filters(struct shark_info *info)
+{
+ info->sync_event_filters = 1;
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->events_sync_menu),
+ "Unsync Graph and List Event Filters");
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_events_menu),
+ "events");
+ gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_adv_events_menu),
+ "advanced events");
+ gtk_widget_hide(info->list_events_menu);
+ gtk_widget_hide(info->list_adv_events_menu);
+}
+
static void
/* Callback for the clicked signal of the Load button */
load_clicked (gpointer data)
@@ -341,6 +367,16 @@ load_filters_clicked (gpointer data)
tracecmd_xml_close(handle);
+ /*
+ * If the events or tasks filters are the same for both
+ * the list and graph, then sync them back.
+ */
+ if (filter_task_compare(ginfo->task_filter,
+ info->list_task_filter) &&
+ filter_task_compare(ginfo->hide_tasks,
+ info->list_hide_tasks))
+ sync_task_filters(info);
+
out:
g_free(filename);
@@ -442,9 +478,17 @@ sync_task_filter_clicked (GtkWidget *subitem, gpointer data)
store = TRACE_VIEW_STORE(model);
- /* Ask user which way to sync */
- result = trace_sync_select_menu("Sync Task Filters",
- selections, &keep);
+ /* If they are already equal, then just perminently sync them */
+ if (filter_task_compare(info->ginfo->task_filter,
+ info->list_task_filter) &&
+ filter_task_compare(info->ginfo->hide_tasks,
+ info->list_hide_tasks))
+ result = 2;
+
+ else
+ /* Ask user which way to sync */
+ result = trace_sync_select_menu("Sync Task Filters",
+ selections, &keep);
switch (result) {
case 0:
@@ -480,21 +524,15 @@ sync_task_filter_clicked (GtkWidget *subitem, gpointer data)
info->list_hide_tasks = NULL;
}
break;
+ case 2:
+ keep = 1;
+ break;
default:
keep = 0;
}
- if (keep) {
- info->sync_task_filters = 1;
- gtk_menu_item_set_label(GTK_MENU_ITEM(info->task_sync_menu),
- "Unsync Graph and List Task Filters");
- gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_task_menu),
- "tasks");
- gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_hide_task_menu),
- "hide tasks");
- gtk_widget_hide(info->list_task_menu);
- gtk_widget_hide(info->list_hide_task_menu);
- }
+ if (keep)
+ sync_task_filters(info);
}
/* Callback for the clicked signal of the events sync filter button */
@@ -550,17 +588,8 @@ sync_events_filter_clicked (GtkWidget *subitem, gpointer data)
keep = 0;
}
- if (keep) {
- info->sync_event_filters = 1;
- gtk_menu_item_set_label(GTK_MENU_ITEM(info->events_sync_menu),
- "Unsync Graph and List Event Filters");
- gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_events_menu),
- "events");
- gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_adv_events_menu),
- "advanced events");
- gtk_widget_hide(info->list_events_menu);
- gtk_widget_hide(info->list_adv_events_menu);
- }
+ if (keep)
+ sync_event_filters(info);
}
static void filter_list_enable_clicked (gpointer data);
diff --git a/trace-hash.c b/trace-hash.c
index 3349715..ed53ee1 100644
--- a/trace-hash.c
+++ b/trace-hash.c
@@ -182,3 +182,39 @@ int *filter_task_pids(struct filter_task *hash)
return pids;
}
+
+/**
+ * filter_task_compare - compare two task hashs to see if they are equal
+ * @hash1: one hash to compare
+ * @hash2: another hash to compare to @hash1
+ *
+ * Returns 1 if the two hashes are the same, 0 otherwise.
+ */
+int filter_task_compare(struct filter_task *hash1, struct filter_task *hash2)
+{
+ int *pids;
+ int ret = 0;
+ int i;
+
+ /* If counts don't match, then they obviously are not the same */
+ if (hash1->count != hash2->count)
+ return 0;
+
+ /* If both hashes are empty, they are the same */
+ if (!hash1->count && !hash2->count)
+ return 1;
+
+ /* Now compare the pids of one hash with the other */
+ pids = filter_task_pids(hash1);
+ for (i = 0; pids[i] >= 0; i++) {
+ if (!filter_task_find_pid(hash2, pids[i]))
+ break;
+ }
+
+ if (pids[i] == -1)
+ ret = 1;
+
+ free(pids);
+
+ return ret;
+}
diff --git a/trace-hash.h b/trace-hash.h
index 29088e7..b5296eb 100644
--- a/trace-hash.h
+++ b/trace-hash.h
@@ -43,6 +43,7 @@ struct filter_task *filter_task_hash_alloc(void);
void filter_task_hash_free(struct filter_task *hash);
struct filter_task *filter_task_hash_copy(struct filter_task *hash);
int *filter_task_pids(struct filter_task *hash);
+int filter_task_compare(struct filter_task *hash1, struct filter_task *hash2);
static inline gint filter_task_count(struct filter_task *hash)
{
--
cgit v1.2.2
From b09e5f4f3fc5c8fc2c51376050af19660c8053f4 Mon Sep 17 00:00:00 2001
From: Steven Rostedt
Date: Thu, 10 Jun 2010 17:01:42 -0400
Subject: kernelshark/parse-events: Add tests if event filters are same
On load of event filters, if the list and graph filters are the same,
then make them synced.
On syncing of event filters, if they are already the same, do not ask
which way to sync, just sync them and keep them synced.
Signed-off-by: Steven Rostedt
---
kernel-shark.c | 29 ++++++++++++++++++++++++-----
parse-events.h | 2 ++
parse-filter.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 83 insertions(+), 5 deletions(-)
diff --git a/kernel-shark.c b/kernel-shark.c
index 3a0d0fb..9ca3942 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -311,9 +311,12 @@ load_filters_clicked (gpointer data)
struct shark_info *info = data;
struct graph_info *ginfo = info->ginfo;
GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview);
+ GtkTreeModel *model;
+ TraceViewStore *store;
struct tracecmd_xml_handle *handle;
struct filter_task *task_filter;
struct filter_task *hide_tasks;
+ struct event_filter *event_filter;
gchar *filename;
int ret;
@@ -349,7 +352,6 @@ load_filters_clicked (gpointer data)
ret = tracecmd_xml_system_exists(handle,
"ListTaskFilter");
if (ret) {
-
task_filter = info->list_task_filter;
hide_tasks = info->list_hide_tasks;
filter_task_clear(task_filter);
@@ -377,6 +379,16 @@ load_filters_clicked (gpointer data)
info->list_hide_tasks))
sync_task_filters(info);
+ model = gtk_tree_view_get_model(trace_tree);
+ if (!model)
+ goto out;
+
+ store = TRACE_VIEW_STORE(model);
+ event_filter = trace_view_store_get_event_filter(store);
+
+ if (pevent_filter_compare(event_filter, ginfo->event_filter))
+ sync_event_filters(info);
+
out:
g_free(filename);
@@ -563,10 +575,15 @@ sync_events_filter_clicked (GtkWidget *subitem, gpointer data)
return;
store = TRACE_VIEW_STORE(model);
+ event_filter = trace_view_store_get_event_filter(store);
- /* Ask user which way to sync */
- result = trace_sync_select_menu("Sync Event Filters",
- selections, &keep);
+ /* If they are already equal, then just perminently sync them */
+ if (pevent_filter_compare(event_filter, ginfo->event_filter))
+ result = 2;
+ else
+ /* Ask user which way to sync */
+ result = trace_sync_select_menu("Sync Event Filters",
+ selections, &keep);
switch (result) {
case 0:
@@ -579,11 +596,13 @@ sync_events_filter_clicked (GtkWidget *subitem, gpointer data)
case 1:
/* Sync Graph Filter with List Filter */
all_events = trace_view_store_get_all_events_enabled(store);
- event_filter = trace_view_store_get_event_filter(store);
trace_graph_copy_filter(info->ginfo, all_events,
event_filter);
break;
+ case 2:
+ keep = 1;
+ break;
default:
keep = 0;
}
diff --git a/parse-events.h b/parse-events.h
index 5afbd1a..9f56d69 100644
--- a/parse-events.h
+++ b/parse-events.h
@@ -701,4 +701,6 @@ int pevent_filter_copy(struct event_filter *dest, struct event_filter *source);
int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
enum filter_trivial_type type);
+int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2);
+
#endif /* _PARSE_EVENTS_H */
diff --git a/parse-filter.c b/parse-filter.c
index 4efce04..75512e3 100644
--- a/parse-filter.c
+++ b/parse-filter.c
@@ -2026,3 +2026,60 @@ pevent_filter_make_string(struct event_filter *filter, int event_id)
return arg_to_str(filter, filter_type->filter);
}
+/**
+ * pevent_filter_compare - compare two filters and return if they are the same
+ * @filter1: Filter to compare with @filter2
+ * @filter2: Filter to compare with @filter1
+ *
+ * Returns:
+ * 1 if the two filters hold the same content.
+ * 0 if they do not.
+ */
+int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2)
+{
+ struct filter_type *filter_type1;
+ struct filter_type *filter_type2;
+ char *str1, *str2;
+ int result;
+ int i;
+
+ /* Do the easy checks first */
+ if (filter1->filters != filter2->filters)
+ return 0;
+ if (!filter1->filters && !filter2->filters)
+ return 1;
+
+ /*
+ * Now take a look at each of the events to see if they have the same
+ * filters to them.
+ */
+ for (i = 0; i < filter1->filters; i++) {
+ filter_type1 = &filter1->event_filters[i];
+ filter_type2 = find_filter_type(filter2, filter_type1->event_id);
+ if (!filter_type2)
+ break;
+ if (filter_type1->filter->type != filter_type2->filter->type)
+ break;
+ switch (filter_type1->filter->type) {
+ case FILTER_TRIVIAL_FALSE:
+ case FILTER_TRIVIAL_TRUE:
+ /* trivial types just need the type compared */
+ continue;
+ default:
+ break;
+ }
+ /* The best way to compare complex filters is with strings */
+ str1 = arg_to_str(filter1, filter_type1->filter);
+ str2 = arg_to_str(filter2, filter_type2->filter);
+ result = strcmp(str1, str2) != 0;
+ free(str1);
+ free(str2);
+ if (result)
+ break;
+ }
+
+ if (i < filter1->filters)
+ return 0;
+ return 1;
+}
+
--
cgit v1.2.2