aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--kernel-shark.c37
-rw-r--r--trace-capture.c748
-rw-r--r--trace-capture.h28
4 files changed, 815 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index a278510..1eebd1c 100644
--- a/Makefile
+++ b/Makefile
@@ -128,7 +128,7 @@ python_dir_SQ = $(subst ','\'',$(python_dir))
128LIBS = -L. -ltracecmd -ldl 128LIBS = -L. -ltracecmd -ldl
129LIB_FILE = libtracecmd.a 129LIB_FILE = libtracecmd.a
130 130
131PACKAGES= gtk+-2.0 libxml-2.0 131PACKAGES= gtk+-2.0 libxml-2.0 gthread-2.0
132 132
133ifndef BUILDGUI 133ifndef BUILDGUI
134 BUILDGUI = 0 134 BUILDGUI = 0
@@ -254,7 +254,7 @@ TRACE_GRAPH_OBJS = trace-graph.o trace-plot.o trace-plot-cpu.o trace-plot-task.o
254TRACE_VIEW_MAIN_OBJS = trace-view-main.o $(TRACE_VIEW_OBJS) $(TRACE_GUI_OBJS) 254TRACE_VIEW_MAIN_OBJS = trace-view-main.o $(TRACE_VIEW_OBJS) $(TRACE_GUI_OBJS)
255TRACE_GRAPH_MAIN_OBJS = trace-graph-main.o $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS) 255TRACE_GRAPH_MAIN_OBJS = trace-graph-main.o $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS)
256KERNEL_SHARK_OBJS = $(TRACE_VIEW_OBJS) $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS) \ 256KERNEL_SHARK_OBJS = $(TRACE_VIEW_OBJS) $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS) \
257 kernel-shark.o 257 trace-capture.o kernel-shark.o
258 258
259PEVENT_LIB_OBJS = parse-events.o trace-seq.o parse-filter.o parse-utils.o 259PEVENT_LIB_OBJS = parse-events.o trace-seq.o parse-filter.o parse-utils.o
260TCMD_LIB_OBJS = $(PEVENT_LIB_OBJS) trace-util.o trace-input.o trace-ftrace.o \ 260TCMD_LIB_OBJS = $(PEVENT_LIB_OBJS) trace-util.o trace-input.o trace-ftrace.o \
diff --git a/kernel-shark.c b/kernel-shark.c
index 2f2d968..7c0f816 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -31,6 +31,7 @@
31#include <getopt.h> 31#include <getopt.h>
32 32
33#include "trace-compat.h" 33#include "trace-compat.h"
34#include "trace-capture.h"
34#include "trace-cmd.h" 35#include "trace-cmd.h"
35#include "trace-gui.h" 36#include "trace-gui.h"
36#include "kernel-shark.h" 37#include "kernel-shark.h"
@@ -1494,6 +1495,9 @@ void kernel_shark(int argc, char **argv)
1494 int ret; 1495 int ret;
1495 int c; 1496 int c;
1496 1497
1498 g_thread_init(NULL);
1499 gdk_threads_init();
1500
1497 gtk_init(&argc, &argv); 1501 gtk_init(&argc, &argv);
1498 1502
1499 while ((c = getopt(argc, argv, "hvi:")) != -1) { 1503 while ((c = getopt(argc, argv, "hvi:")) != -1) {
@@ -1889,6 +1893,36 @@ void kernel_shark(int argc, char **argv)
1889 1893
1890 1894
1891 1895
1896 /* --- Capture Option --- */
1897
1898 menu_item = gtk_menu_item_new_with_label("Capture");
1899 gtk_widget_show(menu_item);
1900
1901 gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), menu_item);
1902
1903 menu = gtk_menu_new(); /* Don't need to show menus */
1904
1905
1906
1907 /* --- Capture - Record Option --- */
1908
1909 sub_item = gtk_menu_item_new_with_label("Record");
1910
1911 /* Add them to the menu */
1912 gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
1913
1914 /* We can attach the Quit menu item to our exit function */
1915 g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
1916 G_CALLBACK (tracecmd_capture_clicked),
1917 (gpointer) info);
1918
1919 /* We do need to show menu items */
1920 gtk_widget_show(sub_item);
1921
1922 /* --- End Capture Options --- */
1923 gtk_menu_item_set_submenu(GTK_MENU_ITEM (menu_item), menu);
1924
1925
1892 /* --- Help Option --- */ 1926 /* --- Help Option --- */
1893 1927
1894 menu_item = gtk_menu_item_new_with_label("Help"); 1928 menu_item = gtk_menu_item_new_with_label("Help");
@@ -2049,7 +2083,10 @@ void kernel_shark(int argc, char **argv)
2049 gtk_widget_set_size_request(window, TRACE_WIDTH, TRACE_HEIGHT); 2083 gtk_widget_set_size_request(window, TRACE_WIDTH, TRACE_HEIGHT);
2050 2084
2051 gtk_widget_show (window); 2085 gtk_widget_show (window);
2086
2087 gdk_threads_enter();
2052 gtk_main (); 2088 gtk_main ();
2089 gdk_threads_leave();
2053} 2090}
2054 2091
2055int main(int argc, char **argv) 2092int main(int argc, char **argv)
diff --git a/trace-capture.c b/trace-capture.c
new file mode 100644
index 0000000..fda61fc
--- /dev/null
+++ b/trace-capture.c
@@ -0,0 +1,748 @@
1/*
2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */
21#define _GNU_SOURCE
22
23#include <stdio.h>
24#include <string.h>
25#include <stdarg.h>
26#include <fcntl.h>
27#include <ctype.h>
28#include <sys/time.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <sys/select.h>
32#include <unistd.h>
33#include <pthread.h>
34#include <gtk/gtk.h>
35#include <errno.h>
36#include <getopt.h>
37
38#include "trace-cmd.h"
39#include "trace-gui.h"
40#include "kernel-shark.h"
41
42#define default_output_file "trace.dat"
43
44struct trace_capture {
45 struct pevent *pevent;
46 GtkWidget *command_entry;
47 GtkWidget *file_entry;
48 GtkWidget *output_text;
49 GtkTextBuffer *output_buffer;
50 GtkWidget *output_dialog;
51 GtkWidget *plugin_combo;
52 pthread_t thread;
53 gboolean all_events;
54 gboolean kill_thread;
55 gboolean capture_done;
56 gchar **systems;
57 int *events;
58 gchar *plugin;
59 int command_input_fd;
60 int command_output_fd;
61};
62
63static int is_just_ws(const char *str)
64{
65 int i;
66
67 for (i = 0; str[i]; i++)
68 if (!isspace(str[i]))
69 break;
70 return !str[i];
71}
72
73static void clear_capture_events(struct trace_capture *cap)
74{
75 int i;
76
77 cap->all_events = FALSE;
78
79 if (cap->systems) {
80 for (i = 0; cap->systems[i]; i++)
81 free(cap->systems[i]);
82
83 free(cap->systems);
84 cap->systems = NULL;
85 }
86
87 free(cap->events);
88 cap->events = NULL;
89}
90
91void end_capture(struct trace_capture *cap)
92{
93 cap->capture_done = TRUE;
94
95 if (cap->kill_thread)
96 pthread_join(cap->thread, NULL);
97
98 if (cap->command_input_fd)
99 close(cap->command_input_fd);
100
101 if (cap->command_output_fd)
102 close(cap->command_output_fd);
103}
104
105static char *get_tracing_dir(void)
106{
107 static char *tracing_dir;
108
109 if (tracing_dir)
110 return tracing_dir;
111
112 tracing_dir = tracecmd_find_tracing_dir();
113 return tracing_dir;
114}
115
116static void free_list(char **list)
117{
118 int i;
119
120 for (i = 0; list[i]; i++)
121 free(list[i]);
122
123 free(list);
124}
125
126static int is_latency(char *plugin)
127{
128 return strcmp(plugin, "wakeup") == 0 ||
129 strcmp(plugin, "wakeup_rt") == 0 ||
130 strcmp(plugin, "irqsoff") == 0 ||
131 strcmp(plugin, "preemptoff") == 0 ||
132 strcmp(plugin, "preemptirqsoff") == 0;
133}
134
135static void close_command_display(struct trace_capture *cap)
136{
137 gtk_widget_destroy(cap->output_dialog);
138 cap->output_dialog = NULL;
139}
140
141static void display_command_close(GtkWidget *widget, gint id, gpointer data)
142{
143 struct trace_capture *cap = data;
144
145 close_command_display(cap);
146}
147
148static void display_command_destroy(GtkWidget *widget, gpointer data)
149{
150 struct trace_capture *cap = data;
151
152 close_command_display(cap);
153}
154
155static void display_command(struct trace_capture *cap)
156{
157 GtkWidget *dialog;
158 GtkWidget *scrollwin;
159 GtkWidget *viewport;
160 GtkWidget *textview;
161 GtkTextBuffer *buffer;
162 const gchar *command;
163 GString *str;
164
165 command = gtk_entry_get_text(GTK_ENTRY(cap->command_entry));
166
167 if (!command || !strlen(command) || is_just_ws(command))
168 command = "trace-cmd";
169
170 str = g_string_new("");
171
172 g_string_printf(str, "(%s)", command);
173
174 dialog = gtk_dialog_new_with_buttons(str->str,
175 NULL,
176 GTK_DIALOG_MODAL,
177 "Close",
178 GTK_RESPONSE_ACCEPT,
179 NULL);
180
181 g_string_free(str, TRUE);
182
183 g_signal_connect(dialog, "response",
184 G_CALLBACK(display_command_close),
185 (gpointer)cap);
186
187 gtk_signal_connect (GTK_OBJECT(dialog), "delete_event",
188 (GtkSignalFunc) display_command_destroy,
189 (gpointer)cap);
190
191 scrollwin = gtk_scrolled_window_new(NULL, NULL);
192 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
193 GTK_POLICY_AUTOMATIC,
194 GTK_POLICY_AUTOMATIC);
195 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrollwin, TRUE, TRUE, 0);
196 gtk_widget_show(scrollwin);
197
198 viewport = gtk_viewport_new(NULL, NULL);
199 gtk_widget_show(viewport);
200
201 gtk_container_add(GTK_CONTAINER(scrollwin), viewport);
202
203 textview = gtk_text_view_new();
204 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
205
206 gtk_container_add(GTK_CONTAINER(viewport), textview);
207 gtk_widget_show(textview);
208
209 cap->output_text = textview;
210 cap->output_buffer = buffer;
211
212 gtk_widget_set_size_request(GTK_WIDGET(dialog),
213 500, 600);
214
215 gtk_widget_show(dialog);
216
217 cap->output_dialog = dialog;
218
219}
220
221static int calculate_trace_cmd_words(struct trace_capture *cap)
222{
223 int words = 4; /* trace-cmd record -o file */
224 int i;
225
226 if (cap->all_events)
227 words += 2;
228 else {
229 if (cap->systems) {
230 for (i = 0; cap->systems[i]; i++)
231 words += 2;
232 }
233
234 if (cap->events)
235 for (i = 0; cap->events[i] >= 0; i++)
236 words += 2;
237 }
238
239 if (cap->plugin)
240 words += 2;
241
242 return words;
243}
244
245static int add_trace_cmd_words(struct trace_capture *cap, char **args)
246{
247 struct event_format *event;
248 char **systems = cap->systems;
249 const gchar *output;
250 int *events = cap->events;
251 int words = 0;
252 int len;
253 int i;
254
255 output = gtk_entry_get_text(GTK_ENTRY(cap->file_entry));
256
257 args[words++] = strdup("trace-cmd");
258 args[words++] = strdup("record");
259 args[words++] = strdup("-o");
260 args[words++] = strdup(output);
261
262 if (cap->plugin) {
263 args[words++] = strdup("-p");
264 args[words++] = strdup(cap->plugin);
265 }
266
267 if (cap->all_events) {
268 args[words++] = strdup("-e");
269 args[words++] = strdup("all");
270 } else {
271 if (systems) {
272 for (i = 0; systems[i]; i++) {
273 args[words++] = strdup("-e");
274 args[words++] = strdup(systems[i]);
275 }
276 }
277
278 if (events) {
279 for (i = 0; events[i] >= 0; i++) {
280 event = pevent_find_event(cap->pevent, events[i]);
281 if (!event)
282 continue;
283 args[words++] = strdup("-e");
284 len = strlen(event->name) + strlen(event->system) + 2;
285 args[words] = malloc_or_die(len);
286 snprintf(args[words++], len, "%s:%s",
287 event->system, event->name);
288 }
289 }
290 }
291
292 return words;
293}
294
295static gchar *get_combo_text(GtkComboBox *combo)
296{
297 GtkTreeModel *model;
298 GtkTreeIter iter;
299 gchar *text;
300
301 model = gtk_combo_box_get_model(combo);
302 if (!model)
303 return NULL;
304
305 if (!gtk_combo_box_get_active_iter(combo, &iter))
306 return NULL;
307
308 gtk_tree_model_get(model, &iter,
309 0, &text,
310 -1);
311
312 return text;
313}
314
315static void execute_command(struct trace_capture *cap)
316{
317 const gchar *ccommand;
318 gchar *command;
319 gchar **args;
320 gboolean space;
321 int words;
322 int tc_words;
323 int i;
324
325 cap->plugin = get_combo_text(GTK_COMBO_BOX(cap->plugin_combo));
326 if (strcmp(cap->plugin, "NONE") == 0) {
327 g_free(cap->plugin);
328 cap->plugin = NULL;
329 }
330
331 ccommand = gtk_entry_get_text(GTK_ENTRY(cap->command_entry));
332 if (!ccommand || !strlen(ccommand) || is_just_ws(ccommand)) {
333 write(1, "hello cruel world!!!", 21);
334 return;
335 }
336
337 command = strdup(ccommand);
338
339 space = TRUE;
340 words = 0;
341 for (i = 0; command[i]; i++) {
342 if (isspace(command[i]))
343 space = TRUE;
344 else {
345 if (space)
346 words++;
347 space = FALSE;
348 }
349 }
350
351 tc_words = calculate_trace_cmd_words(cap);
352
353 args = malloc_or_die(sizeof(*args) * (tc_words + words + 1));
354
355 add_trace_cmd_words(cap, args);
356
357 words = tc_words;
358 space = TRUE;
359 for (i = 0; command[i]; i++) {
360 if (isspace(command[i])) {
361 space = TRUE;
362 command[i] = 0;
363 } else {
364 if (space) {
365 args[words] = &command[i];
366 words++;
367 }
368 space = FALSE;
369 }
370 }
371 args[words] = NULL;
372
373 write(1, "# ", 2);
374 for (i = 0; args[i]; i++) {
375 write(1, args[i], strlen(args[i]));
376 write(1, " ", 1);
377 }
378 write(1, "\n", 1);
379
380 execvp(args[0], args);
381 perror("execvp");
382
383 for (i = 0; args[i]; i++)
384 free(args[i]);
385 free(args);
386 g_free(cap->plugin);
387}
388
389static void *monitor_pipes(void *data)
390{
391 struct trace_capture *cap = data;
392 GtkTextIter iter;
393 gchar buf[BUFSIZ+1];
394 struct timeval tv;
395 fd_set fds;
396 gboolean eof;
397 int ret;
398 int r;
399
400 do {
401 FD_ZERO(&fds);
402 FD_SET(cap->command_input_fd, &fds);
403 tv.tv_sec = 6;
404 tv.tv_usec = 0;
405 ret = select(cap->command_input_fd+1, &fds, NULL, NULL, &tv);
406 if (ret < 0)
407 break;
408
409 eof = TRUE;
410 while ((r = read(cap->command_input_fd, buf, BUFSIZ)) > 0) {
411 eof = FALSE;
412 buf[r] = 0;
413 gtk_text_buffer_get_end_iter(cap->output_buffer,
414 &iter);
415 gtk_text_buffer_insert(cap->output_buffer, &iter, buf, -1);
416 }
417 } while (!cap->capture_done && !eof);
418
419 pthread_exit(NULL);
420}
421
422static void run_command(struct trace_capture *cap)
423{
424 int brass[2];
425 int copper[2];
426 int pid;
427
428 if (pipe(brass) < 0) {
429 warning("Could not create pipe");
430 return;
431 }
432
433 if (pipe(copper) < 0) {
434 warning("Could not create pipe");
435 goto fail_pipe;
436 }
437
438 if ((pid = fork()) < 0) {
439 warning("Could not fork process");
440 goto fail_fork;
441 }
442
443 if (!pid) {
444 close(brass[0]);
445 close(copper[1]);
446 close(0);
447 close(1);
448 close(2);
449
450 dup(copper[0]);
451 dup(brass[1]);
452 dup(brass[1]);
453
454 execute_command(cap);
455
456 close(1);
457 exit(0);
458 }
459 close(brass[1]);
460 close(copper[0]);
461
462 /* these should never be 0 */
463 if (!brass[1] || !copper[0])
464 warning("Pipes have zero as file descriptor");
465
466 cap->command_input_fd = brass[0];
467 cap->command_output_fd = copper[1];
468
469 if (pthread_create(&cap->thread, NULL, monitor_pipes, cap) < 0)
470 warning("Failed to create thread");
471 else
472 cap->kill_thread = 1;
473
474 return;
475
476 fail_fork:
477 close(copper[0]);
478 close(copper[1]);
479 fail_pipe:
480 close(brass[0]);
481 close(brass[1]);
482}
483
484static int trim_plugins(char **plugins)
485{
486 int len = 0;
487 int i;
488
489 if (!plugins)
490 return 0;
491
492 for (i = 0; plugins[i]; i++) {
493 if (is_latency(plugins[i]))
494 continue;
495 plugins[len++] = plugins[i];
496 }
497 plugins[len] = NULL;
498
499 return len;
500}
501
502static void event_filter_callback(gboolean accept,
503 gboolean all_events,
504 gchar **systems,
505 gint *events,
506 gpointer data)
507{
508 struct trace_capture *cap = data;
509 int nr_sys, nr_events;
510 int i;
511
512 if (!accept)
513 return;
514
515 clear_capture_events(cap);
516
517 if (all_events) {
518 cap->all_events = TRUE;
519 return;
520 }
521
522 if (systems) {
523 for (nr_sys = 0; systems[nr_sys]; nr_sys++)
524 ;
525 cap->systems = malloc_or_die(sizeof(*cap->systems) * (nr_sys + 1));
526 for (i = 0; i < nr_sys; i++)
527 cap->systems[i] = strdup(systems[i]);
528 cap->systems[i] = NULL;
529 }
530
531 if (events) {
532 for (nr_events = 0; events[nr_events] >= 0; nr_events++)
533 ;
534 cap->events = malloc_or_die(sizeof(*cap->events) * (nr_events + 1));
535 for (i = 0; i < nr_events; i++)
536 cap->events[i] = events[i];
537 cap->events[i] = -1;
538 }
539}
540
541static void event_button_clicked(GtkWidget *widget, gpointer data)
542{
543 struct trace_capture *cap = data;
544 struct pevent *pevent = cap->pevent;
545
546 trace_filter_pevent_dialog(pevent, cap->all_events,
547 cap->systems, cap->events,
548 event_filter_callback, cap);
549}
550
551static void
552file_clicked (GtkWidget *widget, gpointer data)
553{
554 struct trace_capture *cap = data;
555 gchar *filename;
556
557 filename = trace_get_file_dialog("Trace File");
558 if (!filename)
559 return;
560
561 gtk_entry_set_text(GTK_ENTRY(cap->file_entry), filename);
562}
563
564static void execute_button_clicked(GtkWidget *widget, gpointer data)
565{
566 struct trace_capture *cap = data;
567 GtkWidget *dialog;
568 GtkWidget *label;
569
570 display_command(cap);
571
572 run_command(cap);
573
574 dialog = gtk_dialog_new_with_buttons("Stop Execution",
575 NULL,
576 GTK_DIALOG_MODAL,
577 "Stop",
578 GTK_RESPONSE_ACCEPT,
579 NULL);
580 label = gtk_label_new("Hit Stop to end execution");
581 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
582 gtk_widget_show(label);
583
584 gtk_dialog_run(GTK_DIALOG(dialog));
585
586 end_capture(cap);
587
588 gtk_widget_destroy(dialog);
589}
590
591static GtkTreeModel *create_plugin_combo_model(gpointer data)
592{
593 char **plugins = data;
594 GtkListStore *list;
595 GtkTreeIter iter;
596 int i;
597
598 list = gtk_list_store_new(1, G_TYPE_STRING);
599
600 gtk_list_store_append(list, &iter);
601 gtk_list_store_set(list, &iter,
602 0, "NONE",
603 -1);
604
605 for (i = 0; plugins && plugins[i]; i++) {
606 gtk_list_store_append(list, &iter);
607 gtk_list_store_set(list, &iter,
608 0, plugins[i],
609 -1);
610 }
611
612 return GTK_TREE_MODEL(list);
613}
614
615static void tracing_dialog(struct shark_info *info, const char *tracing)
616{
617 struct pevent *pevent;
618 GtkWidget *dialog;
619 GtkWidget *button;
620 GtkWidget *hbox;
621 GtkWidget *combo;
622 GtkWidget *label;
623 GtkWidget *entry;
624 char **plugins;
625 int nr_plugins;
626 struct trace_capture cap;
627
628 memset(&cap, 0, sizeof(cap));
629
630 plugins = tracecmd_local_plugins(tracing);
631
632 /* Skip latency plugins */
633 nr_plugins = trim_plugins(plugins);
634 if (!nr_plugins && plugins) {
635 free_list(plugins);
636 plugins = NULL;
637 }
638
639 /* Send parse warnings to status display */
640 trace_dialog_register_alt_warning(vpr_stat);
641
642 pevent = tracecmd_local_events(tracing);
643 trace_dialog_register_alt_warning(NULL);
644
645 cap.pevent = pevent;
646
647 if (!pevent && !nr_plugins) {
648 warning("No events or plugins found");
649 return;
650 }
651
652 dialog = gtk_dialog_new_with_buttons("Capture",
653 NULL,
654 GTK_DIALOG_MODAL,
655 "Done",
656 GTK_RESPONSE_ACCEPT,
657 NULL);
658
659 if (pevent) {
660 button = gtk_button_new_with_label("Select Events");
661 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
662 button, TRUE, TRUE, 0);
663 gtk_widget_show(button);
664
665 g_signal_connect (button, "clicked",
666 G_CALLBACK (event_button_clicked),
667 (gpointer)&cap);
668 }
669
670 hbox = gtk_hbox_new(FALSE, 0);
671 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 0);
672 gtk_widget_show(hbox);
673
674 combo = trace_create_combo_box(hbox, "Plugin: ", create_plugin_combo_model, plugins);
675 cap.plugin_combo = combo;
676
677 label = gtk_label_new("Command:");
678 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
679 gtk_widget_show(label);
680
681 entry = gtk_entry_new();
682 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), entry, TRUE, TRUE, 0);
683 gtk_widget_show(entry);
684
685 cap.command_entry = entry;
686
687 hbox = gtk_hbox_new(FALSE, 0);
688 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 0);
689 gtk_widget_show(hbox);
690
691 button = gtk_button_new_with_label("Save file: ");
692 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
693 gtk_widget_show(button);
694
695 g_signal_connect (button, "clicked",
696 G_CALLBACK (file_clicked),
697 (gpointer)&cap);
698
699 entry = gtk_entry_new();
700 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
701 gtk_widget_show(entry);
702
703 gtk_entry_set_text(GTK_ENTRY(entry), default_output_file);
704 cap.file_entry = entry;
705
706 button = gtk_button_new_with_label("Execute");
707 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), button, TRUE, TRUE, 0);
708 gtk_widget_show(button);
709
710 g_signal_connect (button, "clicked",
711 G_CALLBACK (execute_button_clicked),
712 (gpointer)&cap);
713
714 gtk_widget_show(dialog);
715 gtk_dialog_run(GTK_DIALOG(dialog));
716
717 gtk_widget_destroy(dialog);
718
719 end_capture(&cap);
720
721 if (cap.output_dialog)
722 gtk_widget_destroy(cap.output_dialog);
723
724 if (pevent)
725 pevent_free(pevent);
726
727 if (plugins)
728 free_list(plugins);
729
730 clear_capture_events(&cap);
731}
732
733void tracecmd_capture_clicked(gpointer data)
734{
735 struct shark_info *info = data;
736 char *tracing;
737
738 tracing = get_tracing_dir();
739
740 if (!tracing) {
741 warning("Can not find or mount tracing directory!\n"
742 "Either tracing is not configured for this kernel\n"
743 "or you do not have the proper permissions to mount the directory");
744 return;
745 }
746
747 tracing_dialog(info, tracing);
748}
diff --git a/trace-capture.h b/trace-capture.h
new file mode 100644
index 0000000..6466cc6
--- /dev/null
+++ b/trace-capture.h
@@ -0,0 +1,28 @@
1/*
2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */
21#ifndef _TRACE_CAPTURE_H
22#define _TRACE_CAPTURE_H
23
24#include "kernel-shark.h"
25
26void tracecmd_capture_clicked(gpointer data);
27
28#endif /* _TRACE_CAPTURE_H */