kernelshark: Start of making kernelshark utility

Add a utility that makes both trace-graph and trace-view interact.
It may also in the future do recording as well.

Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
diff --git a/Makefile b/Makefile
index 0d81f17..9975f2f 100644
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,7 @@
 	$(CC) -c $(CFLAGS) $(EXT) $(INCLUDES) $< -o $@
 
 TARGETS = libparsevent.a libtracecmd.a trace-cmd plugin_hrtimer.so plugin_mac80211.so \
-	plugin_sched_switch.so trace-graph trace-view
+	plugin_sched_switch.so trace-graph trace-view kernelshark
 
 all: $(TARGETS)
 
@@ -38,16 +38,22 @@
 trace-filter.o::	$(HEADERS)
 trace-graph.o::		$(HEADERS) trace-graph.h
 trace-graph-main.o::	$(HEADERS) trace-graph.h
+kernel-shark.o::	$(HEADERS)
+
+TRACE_VIEW_OBJS = trace-view.o trace-view-store.o trace-filter.o
 
 trace-cmd:: trace-cmd.o trace-read.o
 	$(CC) $^ -rdynamic -o $@ $(LIBS)
 
-trace-view:: trace-view-main.o trace-view.o trace-view-store.o trace-filter.o
+trace-view:: trace-view-main.o $(TRACE_VIEW_OBJS)
 	$(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS)
 
 trace-graph:: trace-graph-main.o trace-graph.o trace-compat.o
 	$(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS)
 
+kernelshark:: kernel-shark.o trace-compat.o $(TRACE_VIEW_OBJS) trace-graph.o
+	$(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS)
+
 .PHONY: gtk_depends
 view_depends:
 	@pkg-config --cflags $(PACKAGES)
diff --git a/kernel-shark.c b/kernel-shark.c
new file mode 100644
index 0000000..8fd16c9
--- /dev/null
+++ b/kernel-shark.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2009, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <gtk/gtk.h>
+
+#include "trace-compat.h"
+#include "trace-cmd.h"
+#include "kernel-shark.h"
+
+#define version "0.1.1"
+
+#define TRACE_WIDTH	800
+#define TRACE_HEIGHT	600
+
+#define input_file "trace.dat"
+
+
+/* Callback for the clicked signal of the Exit button */
+static void
+exit_clicked (GtkWidget *widget, gpointer data)
+{
+	gtk_widget_destroy (GTK_WIDGET (data)); /* the user data points to the main window */
+	gtk_main_quit ();
+}
+
+/* Callback for the delete_event signal of the main application window */
+static gint
+delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+	gtk_widget_destroy (widget); /* destroy the main window */
+	gtk_main_quit ();
+	return TRUE;
+}
+
+/* Callback for the clicked signal of the Events filter button */
+static void
+events_clicked (gpointer data)
+{
+	struct shark_info *info = data;
+
+	trace_filter_event_dialog(info->treeview);
+}
+
+/* Callback for the clicked signal of the CPUs filter button */
+static void
+cpus_clicked (gpointer data)
+{
+	struct shark_info *info = data;
+
+	trace_filter_cpu_dialog(info->treeview);
+}
+
+void kernel_shark(int argc, char **argv)
+{
+	struct tracecmd_input *handle;
+	struct shark_info *info;
+	GtkWidget *window;
+	GtkWidget *vbox;
+	GtkWidget *hbox;
+	GtkWidget *menu_bar;
+	GtkWidget *menu;
+	GtkWidget *menu_item;
+	GtkWidget *sub_item;
+	GtkWidget *scrollwin;
+	GtkWidget *draw;
+	GtkWidget *label;
+	GtkWidget *spin;
+
+	info = g_new0(typeof(*info), 1);
+	if (!info)
+		die("Unable to allocate info");
+
+	handle = tracecmd_open(input_file);
+
+	if (!handle)
+		die("error reading header");
+
+	if (tracecmd_read_headers(handle) < 0)
+		return;
+
+	if (tracecmd_init_data(handle) < 0)
+		die("failed to init data");
+
+	gtk_init(&argc, &argv);
+
+	/* --- Main window --- */
+
+	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+	/* --- Top Level Vbox --- */
+
+	vbox = gtk_vbox_new(FALSE, 0);
+	gtk_container_add(GTK_CONTAINER (window), vbox);
+	gtk_widget_show(vbox);
+
+	/* --- Menu Bar --- */
+
+	menu_bar = gtk_menu_bar_new();
+	gtk_box_pack_start(GTK_BOX (vbox), menu_bar, FALSE, FALSE, 0);
+	gtk_widget_show(menu_bar);
+
+	/* --- File Option --- */
+
+	menu_item = gtk_menu_item_new_with_label("File");
+	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 */
+
+
+	/* --- File - Quit Option --- */
+
+	sub_item = gtk_menu_item_new_with_label("Quit");
+
+	/* 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 (exit_clicked),
+				  (gpointer) window);
+
+	/* We do need to show menu items */
+	gtk_widget_show(sub_item);
+
+	gtk_menu_item_set_submenu(GTK_MENU_ITEM (menu_item), menu);
+
+	/* --- end File options --- */
+
+	/* --- Filter Option --- */
+
+	menu_item = gtk_menu_item_new_with_label("Filter");
+	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 */
+
+
+	/* --- Filter - Events Option --- */
+
+	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 (events_clicked),
+				  (gpointer) info);
+
+	/* We do need to show menu items */
+	gtk_widget_show(sub_item);
+
+
+	/* --- Filter - CPUs Option --- */
+
+	sub_item = gtk_menu_item_new_with_label("CPUs");
+
+	/* 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 (cpus_clicked),
+				  (gpointer) info);
+
+	/* We do need to show menu items */
+	gtk_widget_show(sub_item);
+
+
+	/* --- End Filter Options --- */
+	gtk_menu_item_set_submenu(GTK_MENU_ITEM (menu_item), menu);
+
+	/* --- Top Level Hbox --- */
+
+	hbox = gtk_hbox_new(FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
+	gtk_widget_show(hbox);
+
+	/* --- Scroll Window --- */
+	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 (hbox), scrollwin, TRUE, TRUE, 0);
+	gtk_widget_show(scrollwin);
+
+	/* --- Set up Drawing --- */
+
+	info->ginfo = trace_graph_create(handle, GTK_SCROLLED_WINDOW(scrollwin));
+	draw = trace_graph_get_draw(info->ginfo);
+
+	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollwin),
+					      draw);
+	gtk_widget_show(draw);
+
+
+
+	/* --- Paging Hbox --- */
+
+	hbox = gtk_hbox_new(FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+	gtk_widget_show(hbox);
+
+	/* --- Page Spin Button --- */
+
+	label = gtk_label_new("Page");
+	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+	gtk_widget_show(label);
+
+	spin = gtk_spin_button_new(NULL, 1.0, 0);
+	gtk_spin_button_set_range(GTK_SPIN_BUTTON(spin), 1, 1);
+	gtk_box_pack_start(GTK_BOX(hbox), spin, FALSE, FALSE, 0);
+	gtk_widget_show(spin);
+
+	/* --- Top Level Trace View Paging Hbox --- */
+
+	hbox = gtk_hbox_new(FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
+	gtk_widget_show(hbox);
+
+	/* --- Scroll Window --- */
+	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 (hbox), scrollwin, TRUE, TRUE, 0);
+	gtk_widget_show(scrollwin);
+
+	/* --- Set up Trace Tree --- */
+
+	info->treeview = gtk_tree_view_new();
+
+	trace_view_load(info->treeview, handle, spin);
+
+	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollwin),
+					      info->treeview);
+	gtk_widget_show(info->treeview);
+
+
+	/**********************************************
+	 *   Main Window
+	 **********************************************/
+
+	/* Connect to the delete_event signal and Run the application */
+
+	gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+			    (GtkSignalFunc) delete_event,
+			    NULL);
+
+	gtk_widget_set_size_request(window, TRACE_WIDTH, TRACE_HEIGHT);
+
+	gtk_widget_show (window);
+	gtk_main ();
+}
+
+int main(int argc, char **argv)
+{
+	kernel_shark(argc, argv);
+	return 0;
+}
diff --git a/kernel-shark.h b/kernel-shark.h
new file mode 100644
index 0000000..58761b0
--- /dev/null
+++ b/kernel-shark.h
@@ -0,0 +1,12 @@
+#ifndef _KERNEL_SHARK_H
+#define _KERNEL_SHARK_H
+
+#include "trace-graph.h"
+#include "trace-view.h"
+
+struct shark_info {
+	struct graph_info	*ginfo;
+	GtkWidget		*treeview;
+};
+
+#endif /* _KERNEL_SHARK_H */
diff --git a/trace-view-store.c b/trace-view-store.c
index f26351a..4c96336 100644
--- a/trace-view-store.c
+++ b/trace-view-store.c
@@ -854,11 +854,8 @@
 		list = NULL;
 		next = &list;
 
-		for (;;) {
-			data = tracecmd_read_data(handle, cpu);
-			if (!data)
-				break;
-
+		data = tracecmd_read_cpu_first(handle, cpu);
+		while (data) {
 			*next = rec = g_malloc(sizeof(*rec));
 			g_assert(rec != NULL);
 			rec->offset = data->offset;
@@ -867,6 +864,7 @@
 			next = &rec->next;
 			free(data);
 			count++;
+			data = tracecmd_read_data(handle, cpu);
 		}
 
 		if (count) {