aboutsummaryrefslogtreecommitdiffstats
path: root/kernel-shark.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel-shark.c')
-rw-r--r--kernel-shark.c309
1 files changed, 279 insertions, 30 deletions
diff --git a/kernel-shark.c b/kernel-shark.c
index 87e4c40..5823934 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -23,6 +23,7 @@
23#include <string.h> 23#include <string.h>
24#include <stdarg.h> 24#include <stdarg.h>
25#include <fcntl.h> 25#include <fcntl.h>
26#include <dirent.h>
26#include <sys/types.h> 27#include <sys/types.h>
27#include <sys/stat.h> 28#include <sys/stat.h>
28#include <unistd.h> 29#include <unistd.h>
@@ -35,6 +36,7 @@
35#include "trace-cmd.h" 36#include "trace-cmd.h"
36#include "trace-gui.h" 37#include "trace-gui.h"
37#include "kernel-shark.h" 38#include "kernel-shark.h"
39#include "util.h"
38#include "version.h" 40#include "version.h"
39 41
40#define ___stringify(X) #X 42#define ___stringify(X) #X
@@ -211,6 +213,7 @@ static void free_info(struct shark_info *info)
211 213
212 kernel_shark_clear_capture(info); 214 kernel_shark_clear_capture(info);
213 215
216 free(info->current_filter);
214 free(info->ginfo); 217 free(info->ginfo);
215 free(info); 218 free(info);
216} 219}
@@ -335,7 +338,8 @@ load_clicked (gpointer data)
335 struct shark_info *info = data; 338 struct shark_info *info = data;
336 gchar *filename; 339 gchar *filename;
337 340
338 filename = trace_get_file_dialog("Load File", NULL, FALSE); 341 filename = trace_get_file_dialog_filter("Load File", NULL,
342 TRACE_DIALOG_FILTER_DATA, FALSE);
339 if (!filename) 343 if (!filename)
340 return; 344 return;
341 345
@@ -344,11 +348,52 @@ load_clicked (gpointer data)
344 g_free(filename); 348 g_free(filename);
345} 349}
346 350
347/* Callback for the clicked signal of the Load Filters button */ 351static GString *get_home_filters_new(void)
348static void 352{
349load_filters_clicked (gpointer data) 353 char *path = getenv("HOME");
354 GString *str;
355
356 str = g_string_new(path);
357 g_string_append(str, "/.trace-cmd/filters/");
358 return str;
359}
360
361static int create_home_filters(void)
362{
363 char *path = getenv("HOME");
364 GString *str;
365 struct stat st;
366 int ret;
367
368 str = g_string_new(path);
369 g_string_append(str, "/.trace-cmd");
370 ret = stat(str->str, &st);
371 if (ret < 0) {
372 ret = mkdir(str->str, 0755);
373 if (ret < 0) {
374 warning("Can not create %s", str->str);
375 goto out;
376 }
377 }
378
379 g_string_append(str, "/filters");
380 ret = stat(str->str, &st);
381 if (ret < 0) {
382 ret = mkdir(str->str, 0755);
383 if (ret < 0) {
384 warning("Can not create %s", str->str);
385 goto out;
386 }
387 }
388
389 ret = 0;
390 out:
391 g_string_free(str, TRUE);
392 return ret;
393}
394
395static void load_filter(struct shark_info *info, const char *filename)
350{ 396{
351 struct shark_info *info = data;
352 struct graph_info *ginfo = info->ginfo; 397 struct graph_info *ginfo = info->ginfo;
353 GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview); 398 GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview);
354 GtkTreeModel *model; 399 GtkTreeModel *model;
@@ -357,17 +402,12 @@ load_filters_clicked (gpointer data)
357 struct filter_task *task_filter; 402 struct filter_task *task_filter;
358 struct filter_task *hide_tasks; 403 struct filter_task *hide_tasks;
359 struct event_filter *event_filter; 404 struct event_filter *event_filter;
360 gchar *filename;
361 int ret; 405 int ret;
362 406
363 filename = trace_get_file_dialog("Load Filters", NULL, FALSE);
364 if (!filename)
365 return;
366
367 handle = tracecmd_xml_open(filename); 407 handle = tracecmd_xml_open(filename);
368 if (!handle) { 408 if (!handle) {
369 warning("Could not open %s", filename); 409 warning("Could not open %s", filename);
370 goto out; 410 return;
371 } 411 }
372 412
373 /* Unsync the list and graph filters */ 413 /* Unsync the list and graph filters */
@@ -421,39 +461,61 @@ load_filters_clicked (gpointer data)
421 461
422 model = gtk_tree_view_get_model(trace_tree); 462 model = gtk_tree_view_get_model(trace_tree);
423 if (!model) 463 if (!model)
424 goto out; 464 return;
425 465
426 store = TRACE_VIEW_STORE(model); 466 store = TRACE_VIEW_STORE(model);
427 event_filter = trace_view_store_get_event_filter(store); 467 event_filter = trace_view_store_get_event_filter(store);
428 468
429 if (pevent_filter_compare(event_filter, ginfo->event_filter)) 469 if (pevent_filter_compare(event_filter, ginfo->event_filter))
430 sync_event_filters(info); 470 sync_event_filters(info);
471}
431 472
432 out: 473static void load_filter_clicked(GtkMenuItem *item, gpointer data)
433 g_free(filename); 474{
475 struct shark_info *info = data;
476 const char *name;
477 GString *path;
478
479 name = gtk_menu_item_get_label(item);
480
481 path = get_home_filters_new();
482 g_string_append_printf(path, "/%s.ksf", name);
434 483
484 load_filter(info, path->str);
485 g_string_free(path, TRUE);
486
487 free(info->current_filter);
488 info->current_filter = strdup(name);
435} 489}
436 490
437/* Callback for the clicked signal of the Save Filters button */ 491/* Callback for the clicked signal of the Load Filters button */
438static void 492static void
439save_filters_clicked (gpointer data) 493import_filters_clicked (gpointer data)
440{ 494{
441 struct shark_info *info = data; 495 struct shark_info *info = data;
496 gchar *filename;
497
498 filename = trace_get_file_dialog_filter("Load Filters", NULL,
499 TRACE_DIALOG_FILTER_FILTER, FALSE);
500 if (!filename)
501 return;
502
503 load_filter(info, filename);
504}
505
506static void save_filters(struct shark_info *info, const char *filename)
507{
442 struct graph_info *ginfo = info->ginfo; 508 struct graph_info *ginfo = info->ginfo;
443 struct tracecmd_xml_handle *handle; 509 struct tracecmd_xml_handle *handle;
444 GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview); 510 GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview);
445 struct filter_task *task_filter; 511 struct filter_task *task_filter;
446 struct filter_task *hide_tasks; 512 struct filter_task *hide_tasks;
447 gchar *filename;
448
449 filename = trace_get_file_dialog("Save Filters", "Save", TRUE);
450 if (!filename)
451 return;
452 513
453 handle = tracecmd_xml_create(filename, VERSION_STRING); 514 handle = tracecmd_xml_create(filename, VERSION_STRING);
454 if (!handle) 515 if (!handle) {
455 warning("Could not create %s", filename); 516 warning("Could not create %s", filename);
456 g_free(filename); 517 return;
518 }
457 519
458 trace_view_save_filters(handle, trace_tree); 520 trace_view_save_filters(handle, trace_tree);
459 trace_graph_save_filters(ginfo, handle); 521 trace_graph_save_filters(ginfo, handle);
@@ -478,6 +540,178 @@ save_filters_clicked (gpointer data)
478 tracecmd_xml_close(handle); 540 tracecmd_xml_close(handle);
479} 541}
480 542
543/* Callback for the clicked signal of the Save Filters button */
544static void
545export_filters_clicked (gpointer data)
546{
547 struct shark_info *info = data;
548 gchar *filename;
549
550 filename = trace_get_file_dialog_filter("Save Filters", "Save",
551 TRACE_DIALOG_FILTER_FILTER, TRUE);
552 if (!filename)
553 return;
554
555 save_filters(info, filename);
556 g_free(filename);
557}
558
559static void update_load_filter(struct shark_info *info)
560{
561 struct dirent *dent;
562 struct stat st;
563 DIR *dir;
564 GtkWidget *menu;
565 GtkWidget *sub_item;
566 GString *path;
567 int ret;
568
569 path = get_home_filters_new();
570
571 menu = gtk_menu_new();
572
573 ret = stat(path->str, &st);
574 if (ret < 0 || !S_ISDIR(st.st_mode))
575 goto update_rest;
576
577 dir = opendir(path->str);
578 if (!dir)
579 goto update_rest;
580
581 while ((dent = readdir(dir))) {
582 const char *name = dent->d_name;
583 GString *file;
584 gchar *item;
585
586 if (strcmp(name, ".") == 0 ||
587 strcmp(name, "..") == 0)
588 continue;
589
590 if (strcmp(name + strlen(name) - 4, ".ksf") != 0)
591 continue;
592
593 file = g_string_new(path->str);
594 g_string_append_printf(file, "/%s", name);
595
596 /* Save the file name but remove the .kss extention */
597 item = g_strdup(name);
598 item[strlen(name) - 4] = 0;
599
600 sub_item = gtk_menu_item_new_with_label(item);
601 gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
602 gtk_widget_show(sub_item);
603
604 g_signal_connect(G_OBJECT (sub_item), "activate",
605 G_CALLBACK (load_filter_clicked),
606 (gpointer) info);
607
608 g_free(item);
609 g_string_free(file, TRUE);
610 }
611
612 update_rest:
613 g_string_free(path, TRUE);
614
615 /* --- File - Load Filter - Filters --- */
616
617 sub_item = gtk_menu_item_new_with_label("Import Filter");
618
619 g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
620 G_CALLBACK (import_filters_clicked),
621 (gpointer) info);
622
623 /* Add them to the menu */
624 gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
625
626 /* We do need to show menu items */
627 gtk_widget_show(sub_item);
628
629 gtk_menu_item_set_submenu(GTK_MENU_ITEM (info->load_filter_menu), menu);
630
631}
632
633/* Callback for the clicked signal of the Save Filters button */
634static void
635save_filter_clicked (gpointer data)
636{
637 struct shark_info *info = data;
638 struct stat st;
639 GtkWidget *dialog;
640 GtkWidget *hbox;
641 GtkWidget *label;
642 GtkWidget *entry;
643 GString *file;
644 const char *name;
645 gint result;
646 int ret;
647
648 dialog = gtk_dialog_new_with_buttons("Save Filter",
649 NULL,
650 GTK_DIALOG_MODAL,
651 GTK_STOCK_OK,
652 GTK_RESPONSE_ACCEPT,
653 GTK_STOCK_CANCEL,
654 GTK_RESPONSE_REJECT,
655 NULL);
656
657 hbox = gtk_hbox_new(FALSE, 0);
658 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, FALSE, 0);
659 gtk_widget_show(hbox);
660
661 label = gtk_label_new("Filter Name: ");
662 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
663 gtk_widget_show(label);
664
665 entry = gtk_entry_new();
666 gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 0);
667 gtk_widget_show(entry);
668
669 if (info->current_filter)
670 gtk_entry_set_text(GTK_ENTRY(entry), info->current_filter);
671
672 again:
673 result = gtk_dialog_run(GTK_DIALOG(dialog));
674 switch (result) {
675 case GTK_RESPONSE_ACCEPT:
676 name = gtk_entry_get_text(GTK_ENTRY(entry));
677 if (!name || !has_text(name)) {
678 warning("Must enter a name");
679 goto again;
680 }
681 /* Make sure home settings exists */
682 if (create_home_filters() < 0)
683 break;
684 file = get_home_filters_new();
685 g_string_append_printf(file, "/%s.ksf", name);
686 ret = stat(file->str, &st);
687 if (ret >= 0) {
688 ret = trace_dialog(GTK_WINDOW(dialog), TRACE_GUI_ASK,
689 "The Filter '%s' already exists.\n"
690 "Are you sure you want to replace it",
691 name);
692 if (ret == GTK_RESPONSE_NO) {
693 g_string_free(file, TRUE);
694 goto again;
695 }
696 }
697 save_filters(info, file->str);
698
699 free(info->current_filter);
700 info->current_filter = strdup(name);
701
702 update_load_filter(info);
703 g_string_free(file, TRUE);
704 break;
705
706 case GTK_RESPONSE_REJECT:
707 break;
708 default:
709 break;
710 };
711
712 gtk_widget_destroy(dialog);
713}
714
481/* Callback for the clicked signal of the Exit button */ 715/* Callback for the clicked signal of the Exit button */
482static void 716static void
483exit_clicked (gpointer data) 717exit_clicked (gpointer data)
@@ -1630,30 +1864,45 @@ void kernel_shark(int argc, char **argv)
1630 gtk_widget_show(sub_item); 1864 gtk_widget_show(sub_item);
1631 1865
1632 1866
1633 /* --- File - Load Filter Option --- */ 1867 /* --- File - Load Filter --- */
1634 1868
1635 sub_item = gtk_menu_item_new_with_label("Load filters"); 1869 sub_item = gtk_menu_item_new_with_label("Load filter");
1636 1870
1637 /* Add them to the menu */ 1871 /* Add them to the menu */
1638 gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); 1872 gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
1639 1873
1640 g_signal_connect_swapped (G_OBJECT (sub_item), "activate", 1874 info->load_filter_menu = sub_item;
1641 G_CALLBACK (load_filters_clicked),
1642 (gpointer) info);
1643 1875
1644 /* We do need to show menu items */ 1876 /* We do need to show menu items */
1645 gtk_widget_show(sub_item); 1877 gtk_widget_show(sub_item);
1646 1878
1879 update_load_filter(info);
1880
1647 1881
1648 /* --- File - Save Filter Option --- */ 1882 /* --- File - Save Filter Option --- */
1649 1883
1650 sub_item = gtk_menu_item_new_with_label("Save filters"); 1884 sub_item = gtk_menu_item_new_with_label("Save filter");
1885
1886 /* Add them to the menu */
1887 gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
1888
1889 /* We do need to show menu items */
1890 gtk_widget_show(sub_item);
1891
1892 g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
1893 G_CALLBACK (save_filter_clicked),
1894 (gpointer) info);
1895
1896
1897 /* --- File - Export Filter Option --- */
1898
1899 sub_item = gtk_menu_item_new_with_label("Export filters");
1651 1900
1652 /* Add them to the menu */ 1901 /* Add them to the menu */
1653 gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); 1902 gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
1654 1903
1655 g_signal_connect_swapped (G_OBJECT (sub_item), "activate", 1904 g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
1656 G_CALLBACK (save_filters_clicked), 1905 G_CALLBACK (export_filters_clicked),
1657 (gpointer) info); 1906 (gpointer) info);
1658 1907
1659 /* We do need to show menu items */ 1908 /* We do need to show menu items */